001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.hadoop.hbase.coprocessor;
019
020import static org.junit.Assert.assertNotNull;
021import static org.junit.Assert.assertTrue;
022
023import java.io.IOException;
024import java.util.Arrays;
025import java.util.List;
026import java.util.Optional;
027import org.apache.hadoop.hbase.Cell;
028import org.apache.hadoop.hbase.CellBuilderFactory;
029import org.apache.hadoop.hbase.CellBuilderType;
030import org.apache.hadoop.hbase.HBaseClassTestRule;
031import org.apache.hadoop.hbase.HBaseTestingUtil;
032import org.apache.hadoop.hbase.HConstants;
033import org.apache.hadoop.hbase.TableName;
034import org.apache.hadoop.hbase.client.Append;
035import org.apache.hadoop.hbase.client.Increment;
036import org.apache.hadoop.hbase.client.Result;
037import org.apache.hadoop.hbase.client.Row;
038import org.apache.hadoop.hbase.client.Table;
039import org.apache.hadoop.hbase.testclassification.CoprocessorTests;
040import org.apache.hadoop.hbase.testclassification.MediumTests;
041import org.apache.hadoop.hbase.util.Bytes;
042import org.junit.AfterClass;
043import org.junit.BeforeClass;
044import org.junit.ClassRule;
045import org.junit.Test;
046import org.junit.experimental.categories.Category;
047
048@Category({ CoprocessorTests.class, MediumTests.class })
049public class TestIncrementAndAppendWithNullResult {
050
051  @ClassRule
052  public static final HBaseClassTestRule CLASS_RULE =
053    HBaseClassTestRule.forClass(TestIncrementAndAppendWithNullResult.class);
054
055  private static final HBaseTestingUtil util = new HBaseTestingUtil();
056  private static final TableName TEST_TABLE = TableName.valueOf("test");
057  private static final byte[] TEST_FAMILY = Bytes.toBytes("f1");
058  private static final byte[] ROW_A = Bytes.toBytes("aaa");
059  private static final byte[] qualifierCol1 = Bytes.toBytes("col1");
060  private static Table table;
061
062  @BeforeClass
063  public static void setupBeforeClass() throws Exception {
064    util.getConfiguration().set(CoprocessorHost.REGION_COPROCESSOR_CONF_KEY,
065      MyObserver.class.getName());
066    // reduce the retry count so as to speed up the test
067    util.getConfiguration().setInt(HConstants.HBASE_CLIENT_RETRIES_NUMBER, 2);
068    util.startMiniCluster();
069    table = util.createTable(TEST_TABLE, TEST_FAMILY);
070  }
071
072  @AfterClass
073  public static void tearDownAfterClass() throws Exception {
074    util.shutdownMiniCluster();
075  }
076
077  public static class MyObserver implements RegionCoprocessor, RegionObserver {
078    private static final Result TMP_RESULT = Result.create(Arrays
079      .asList(CellBuilderFactory.create(CellBuilderType.SHALLOW_COPY).setRow(Bytes.toBytes("row"))
080        .setFamily(Bytes.toBytes("family")).setQualifier(Bytes.toBytes("qualifier"))
081        .setType(Cell.Type.Put).setValue(Bytes.toBytes("value")).build()));
082
083    @Override
084    public Optional<RegionObserver> getRegionObserver() {
085      return Optional.of(this);
086    }
087
088    @Override
089    public Result preIncrementAfterRowLock(
090      ObserverContext<? extends RegionCoprocessorEnvironment> c, Increment increment)
091      throws IOException {
092      return TMP_RESULT;
093    }
094
095    @Override
096    public Result postIncrement(ObserverContext<? extends RegionCoprocessorEnvironment> c,
097      Increment increment, Result result) throws IOException {
098      return null;
099    }
100
101    @Override
102    public Result postAppend(ObserverContext<? extends RegionCoprocessorEnvironment> c,
103      Append append, Result result) {
104      return null;
105    }
106
107    @Override
108    public Result preAppendAfterRowLock(ObserverContext<? extends RegionCoprocessorEnvironment> c,
109      Append append) {
110      return TMP_RESULT;
111    }
112  }
113
114  @Test
115  public void testIncrement() throws Exception {
116    testAppend(new Increment(ROW_A).addColumn(TEST_FAMILY, qualifierCol1, 10L));
117    testAppend(
118      new Increment(ROW_A).addColumn(TEST_FAMILY, qualifierCol1, 10L).setReturnResults(false));
119  }
120
121  private void testAppend(Increment inc) throws Exception {
122    checkResult(table.increment(inc));
123    List<Row> actions = Arrays.asList(inc, inc);
124    Object[] results = new Object[actions.size()];
125    table.batch(actions, results);
126    checkResult(results);
127  }
128
129  @Test
130  public void testAppend() throws Exception {
131    testAppend(new Append(ROW_A).addColumn(TEST_FAMILY, qualifierCol1, Bytes.toBytes("value")));
132    testAppend(new Append(ROW_A).addColumn(TEST_FAMILY, qualifierCol1, Bytes.toBytes("value"))
133      .setReturnResults(false));
134
135  }
136
137  private void testAppend(Append append) throws Exception {
138    checkResult(table.append(append));
139    List<Row> actions = Arrays.asList(append, append);
140    Object[] results = new Object[actions.size()];
141    table.batch(actions, results);
142    checkResult(results);
143  }
144
145  private static void checkResult(Result r) {
146    checkResult(new Object[] { r });
147  }
148
149  private static void checkResult(Object[] results) {
150    for (int i = 0; i != results.length; ++i) {
151      assertNotNull("The result[" + i + "] should not be null", results[i]);
152      assertTrue("The result[" + i + "] should be Result type", results[i] instanceof Result);
153      assertTrue("The result[" + i + "] shuold be empty", ((Result) results[i]).isEmpty());
154    }
155  }
156}