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.client;
019
020import static org.junit.jupiter.api.Assertions.assertTrue;
021
022import java.io.IOException;
023import java.util.Arrays;
024import java.util.Optional;
025import org.apache.hadoop.hbase.Cell;
026import org.apache.hadoop.hbase.CellBuilderType;
027import org.apache.hadoop.hbase.CellUtil;
028import org.apache.hadoop.hbase.CoprocessorEnvironment;
029import org.apache.hadoop.hbase.ExtendedCellBuilderFactory;
030import org.apache.hadoop.hbase.HBaseTestingUtil;
031import org.apache.hadoop.hbase.KeyValue;
032import org.apache.hadoop.hbase.TableName;
033import org.apache.hadoop.hbase.coprocessor.ObserverContext;
034import org.apache.hadoop.hbase.coprocessor.RegionCoprocessor;
035import org.apache.hadoop.hbase.coprocessor.RegionCoprocessorEnvironment;
036import org.apache.hadoop.hbase.coprocessor.RegionObserver;
037import org.apache.hadoop.hbase.testclassification.ClientTests;
038import org.apache.hadoop.hbase.testclassification.MediumTests;
039import org.apache.hadoop.hbase.util.Bytes;
040import org.junit.jupiter.api.AfterAll;
041import org.junit.jupiter.api.BeforeAll;
042import org.junit.jupiter.api.Tag;
043import org.junit.jupiter.api.Test;
044
045@Tag(MediumTests.TAG)
046@Tag(ClientTests.TAG)
047public class TestResultFromCoprocessor {
048
049  private static final HBaseTestingUtil TEST_UTIL = new HBaseTestingUtil();
050  private static final byte[] ROW = Bytes.toBytes("normal_row");
051  private static final byte[] FAMILY = Bytes.toBytes("fm");
052  private static final byte[] QUAL = Bytes.toBytes("qual");
053  private static final byte[] VALUE = Bytes.toBytes(100L);
054  private static final byte[] FIXED_VALUE = Bytes.toBytes("fixed_value");
055  private static final Cell FIXED_CELL = ExtendedCellBuilderFactory
056    .create(CellBuilderType.DEEP_COPY).setRow(ROW).setFamily(FAMILY).setQualifier(QUAL)
057    .setTimestamp(0).setType(KeyValue.Type.Put.getCode()).setValue(FIXED_VALUE).build();
058  private static final Result FIXED_RESULT = Result.create(Arrays.asList(FIXED_CELL));
059  private static final TableName TABLE_NAME = TableName.valueOf("TestResultFromCoprocessor");
060
061  @BeforeAll
062  public static void setUpBeforeClass() throws Exception {
063    TEST_UTIL.startMiniCluster(3);
064    TableDescriptor desc =
065      TableDescriptorBuilder.newBuilder(TABLE_NAME).setCoprocessor(MyObserver.class.getName())
066        .setColumnFamily(ColumnFamilyDescriptorBuilder.of(FAMILY)).build();
067    TEST_UTIL.getAdmin().createTable(desc);
068  }
069
070  @AfterAll
071  public static void tearDownAfterClass() throws Exception {
072    TEST_UTIL.shutdownMiniCluster();
073  }
074
075  @Test
076  public void testAppend() throws IOException {
077    try (Table t = TEST_UTIL.getConnection().getTable(TABLE_NAME)) {
078      Put put = new Put(ROW);
079      put.addColumn(FAMILY, QUAL, VALUE);
080      t.put(put);
081      assertRowAndValue(t.get(new Get(ROW)), ROW, VALUE);
082      Append append = new Append(ROW);
083      append.addColumn(FAMILY, QUAL, FIXED_VALUE);
084      assertRowAndValue(t.append(append), ROW, FIXED_VALUE);
085      assertRowAndValue(t.get(new Get(ROW)), ROW, Bytes.add(VALUE, FIXED_VALUE));
086    }
087  }
088
089  @Test
090  public void testIncrement() throws IOException {
091    try (Table t = TEST_UTIL.getConnection().getTable(TABLE_NAME)) {
092      Put put = new Put(ROW);
093      put.addColumn(FAMILY, QUAL, VALUE);
094      t.put(put);
095      assertRowAndValue(t.get(new Get(ROW)), ROW, VALUE);
096      Increment inc = new Increment(ROW);
097      inc.addColumn(FAMILY, QUAL, 99);
098      assertRowAndValue(t.increment(inc), ROW, FIXED_VALUE);
099      assertRowAndValue(t.get(new Get(ROW)), ROW, Bytes.toBytes(199L));
100    }
101  }
102
103  private static void assertRowAndValue(Result r, byte[] row, byte[] value) {
104    for (Cell c : r.rawCells()) {
105      assertTrue(Bytes.equals(CellUtil.cloneRow(c), row));
106      assertTrue(Bytes.equals(CellUtil.cloneValue(c), value));
107    }
108  }
109
110  public static class MyObserver implements RegionCoprocessor, RegionObserver {
111    @Override
112    public Optional<RegionObserver> getRegionObserver() {
113      return Optional.of(this);
114    }
115
116    @Override
117    public Result postAppend(final ObserverContext<? extends RegionCoprocessorEnvironment> c,
118      final Append append, final Result result) {
119      return FIXED_RESULT;
120    }
121
122    @Override
123    public Result postIncrement(final ObserverContext<? extends RegionCoprocessorEnvironment> c,
124      final Increment increment, final Result result) {
125      return FIXED_RESULT;
126    }
127
128    @Override
129    public void start(CoprocessorEnvironment env) throws IOException {
130    }
131
132    @Override
133    public void stop(CoprocessorEnvironment env) throws IOException {
134    }
135  }
136
137}