You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by zh...@apache.org on 2026/05/07 13:48:43 UTC
(hbase) branch master updated: HBASE-30141 Split TestFromClientSide5 (#8193)
This is an automated email from the ASF dual-hosted git repository.
Apache9 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hbase.git
The following commit(s) were added to refs/heads/master by this push:
new f5575e333e0 HBASE-30141 Split TestFromClientSide5 (#8193)
f5575e333e0 is described below
commit f5575e333e03354c6a480797e344226a890c188a
Author: Duo Zhang <zh...@apache.org>
AuthorDate: Thu May 7 21:48:37 2026 +0800
HBASE-30141 Split TestFromClientSide5 (#8193)
Signed-off-by: Xiao Liu <li...@apache.org>
---
.../hadoop/hbase/client/FromClientSideTest5.java | 1280 --------------------
.../hbase/client/FromClientSideTestBase.java | 196 ++-
.../client/FromClientSideTestCheckAndMutate.java | 337 ++++++
.../client/FromClientSideTestMultiRowMutation.java | 385 ++++++
.../client/FromClientSideTestReverseScan.java | 669 ++++++++++
.../hadoop/hbase/client/TestFromClientSide5.java | 3 +-
.../client/TestFromClientSide5WithCoprocessor.java | 3 +-
....java => TestFromClientSideCheckAndMutate.java} | 9 +-
...omClientSideCheckAndMutateWithCoprocessor.java} | 11 +-
...ava => TestFromClientSideMultiRowMutation.java} | 9 +-
...ClientSideMultiRowMutationWithCoprocessor.java} | 11 +-
...sor.java => TestFromClientSideReverseScan.java} | 9 +-
...tFromClientSideReverseScanWithCoprocessor.java} | 10 +-
13 files changed, 1506 insertions(+), 1426 deletions(-)
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/FromClientSideTest5.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/FromClientSideTest5.java
index 1fff2b6910b..2bd8bce55ca 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/FromClientSideTest5.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/FromClientSideTest5.java
@@ -28,7 +28,6 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.junit.jupiter.api.Assertions.fail;
import java.io.IOException;
import java.time.Duration;
@@ -59,21 +58,14 @@ import org.apache.hadoop.hbase.Waiter;
import org.apache.hadoop.hbase.client.Scan.ReadType;
import org.apache.hadoop.hbase.client.metrics.ScanMetrics;
import org.apache.hadoop.hbase.filter.BinaryComparator;
-import org.apache.hadoop.hbase.filter.Filter;
import org.apache.hadoop.hbase.filter.FilterList;
import org.apache.hadoop.hbase.filter.FirstKeyOnlyFilter;
import org.apache.hadoop.hbase.filter.InclusiveStopFilter;
-import org.apache.hadoop.hbase.filter.KeyOnlyFilter;
-import org.apache.hadoop.hbase.filter.QualifierFilter;
-import org.apache.hadoop.hbase.filter.RegexStringComparator;
import org.apache.hadoop.hbase.filter.RowFilter;
-import org.apache.hadoop.hbase.filter.SingleColumnValueFilter;
import org.apache.hadoop.hbase.filter.SubstringComparator;
import org.apache.hadoop.hbase.filter.ValueFilter;
-import org.apache.hadoop.hbase.io.TimeRange;
import org.apache.hadoop.hbase.io.hfile.BlockCache;
import org.apache.hadoop.hbase.io.hfile.CacheConfig;
-import org.apache.hadoop.hbase.ipc.CoprocessorRpcChannel;
import org.apache.hadoop.hbase.regionserver.HRegion;
import org.apache.hadoop.hbase.regionserver.HRegionServer;
import org.apache.hadoop.hbase.regionserver.HStore;
@@ -87,13 +79,6 @@ import org.junit.jupiter.api.TestTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;
-import org.apache.hadoop.hbase.shaded.protobuf.generated.ClientProtos.MutationProto;
-import org.apache.hadoop.hbase.shaded.protobuf.generated.ClientProtos.MutationProto.MutationType;
-import org.apache.hadoop.hbase.shaded.protobuf.generated.MultiRowMutationProtos.MultiRowMutationService;
-import org.apache.hadoop.hbase.shaded.protobuf.generated.MultiRowMutationProtos.MutateRowsRequest;
-import org.apache.hadoop.hbase.shaded.protobuf.generated.MultiRowMutationProtos.MutateRowsResponse;
-
/**
* Run tests that use the HBase clients; {@link Table}. Sets up the HBase mini cluster once at start
* and runs through all client tests. Each creates a table named for the method and does its stuff
@@ -215,347 +200,6 @@ public class FromClientSideTest5 extends FromClientSideTestBase {
}
}
- @TestTemplate
- public void testMultiRowMutation() throws Exception {
- LOG.info("Starting testMultiRowMutation");
- final byte[] ROW1 = Bytes.toBytes("testRow1");
- final byte[] ROW2 = Bytes.toBytes("testRow2");
- final byte[] ROW3 = Bytes.toBytes("testRow3");
- TEST_UTIL.createTable(tableName, FAMILY);
- try (Connection conn = getConnection(); Table t = conn.getTable(tableName)) {
- // Add initial data
- t.batch(Arrays.asList(new Put(ROW1).addColumn(FAMILY, QUALIFIER, VALUE),
- new Put(ROW2).addColumn(FAMILY, QUALIFIER, Bytes.toBytes(1L)),
- new Put(ROW3).addColumn(FAMILY, QUALIFIER, VALUE)), new Object[3]);
-
- // Execute MultiRowMutation
- Put put = new Put(ROW).addColumn(FAMILY, QUALIFIER, VALUE);
- MutationProto m1 = ProtobufUtil.toMutation(MutationType.PUT, put);
-
- Delete delete = new Delete(ROW1);
- MutationProto m2 = ProtobufUtil.toMutation(MutationType.DELETE, delete);
-
- Increment increment = new Increment(ROW2).addColumn(FAMILY, QUALIFIER, 1L);
- MutationProto m3 = ProtobufUtil.toMutation(MutationType.INCREMENT, increment);
-
- Append append = new Append(ROW3).addColumn(FAMILY, QUALIFIER, VALUE);
- MutationProto m4 = ProtobufUtil.toMutation(MutationType.APPEND, append);
-
- MutateRowsRequest.Builder mrmBuilder = MutateRowsRequest.newBuilder();
- mrmBuilder.addMutationRequest(m1);
- mrmBuilder.addMutationRequest(m2);
- mrmBuilder.addMutationRequest(m3);
- mrmBuilder.addMutationRequest(m4);
-
- CoprocessorRpcChannel channel = t.coprocessorService(ROW);
- MultiRowMutationService.BlockingInterface service =
- MultiRowMutationService.newBlockingStub(channel);
- MutateRowsResponse response = service.mutateRows(null, mrmBuilder.build());
-
- // Assert
- assertTrue(response.getProcessed());
-
- Result r = t.get(new Get(ROW));
- assertEquals(Bytes.toString(VALUE), Bytes.toString(r.getValue(FAMILY, QUALIFIER)));
-
- r = t.get(new Get(ROW1));
- assertTrue(r.isEmpty());
-
- r = t.get(new Get(ROW2));
- assertEquals(2L, Bytes.toLong(r.getValue(FAMILY, QUALIFIER)));
-
- r = t.get(new Get(ROW3));
- assertEquals(Bytes.toString(VALUE) + Bytes.toString(VALUE),
- Bytes.toString(r.getValue(FAMILY, QUALIFIER)));
- }
- }
-
- @TestTemplate
- public void testMultiRowMutationWithSingleConditionWhenConditionMatches() throws Exception {
- final byte[] ROW1 = Bytes.toBytes("testRow1");
- final byte[] ROW2 = Bytes.toBytes("testRow2");
- final byte[] VALUE1 = Bytes.toBytes("testValue1");
- final byte[] VALUE2 = Bytes.toBytes("testValue2");
- TEST_UTIL.createTable(tableName, FAMILY);
- try (Connection conn = getConnection(); Table t = conn.getTable(tableName)) {
- // Add initial data
- t.put(new Put(ROW2).addColumn(FAMILY, QUALIFIER, VALUE2));
-
- // Execute MultiRowMutation with conditions
- Put put1 = new Put(ROW).addColumn(FAMILY, QUALIFIER, VALUE);
- MutationProto m1 = ProtobufUtil.toMutation(MutationType.PUT, put1);
- Put put2 = new Put(ROW1).addColumn(FAMILY, QUALIFIER, VALUE1);
- MutationProto m2 = ProtobufUtil.toMutation(MutationType.PUT, put2);
- Delete delete = new Delete(ROW2);
- MutationProto m3 = ProtobufUtil.toMutation(MutationType.DELETE, delete);
-
- MutateRowsRequest.Builder mrmBuilder = MutateRowsRequest.newBuilder();
- mrmBuilder.addMutationRequest(m1);
- mrmBuilder.addMutationRequest(m2);
- mrmBuilder.addMutationRequest(m3);
- mrmBuilder.addCondition(
- ProtobufUtil.toCondition(ROW2, FAMILY, QUALIFIER, CompareOperator.EQUAL, VALUE2, null));
-
- CoprocessorRpcChannel channel = t.coprocessorService(ROW);
- MultiRowMutationService.BlockingInterface service =
- MultiRowMutationService.newBlockingStub(channel);
- MutateRowsResponse response = service.mutateRows(null, mrmBuilder.build());
-
- // Assert
- assertTrue(response.getProcessed());
-
- Result r = t.get(new Get(ROW));
- assertEquals(Bytes.toString(VALUE), Bytes.toString(r.getValue(FAMILY, QUALIFIER)));
-
- r = t.get(new Get(ROW1));
- assertEquals(Bytes.toString(VALUE1), Bytes.toString(r.getValue(FAMILY, QUALIFIER)));
-
- r = t.get(new Get(ROW2));
- assertTrue(r.isEmpty());
- }
- }
-
- @TestTemplate
- public void testMultiRowMutationWithSingleConditionWhenConditionNotMatch() throws Exception {
- final byte[] ROW1 = Bytes.toBytes("testRow1");
- final byte[] ROW2 = Bytes.toBytes("testRow2");
- final byte[] VALUE1 = Bytes.toBytes("testValue1");
- final byte[] VALUE2 = Bytes.toBytes("testValue2");
- TEST_UTIL.createTable(tableName, FAMILY);
- try (Connection conn = getConnection(); Table t = conn.getTable(tableName)) {
- // Add initial data
- t.put(new Put(ROW2).addColumn(FAMILY, QUALIFIER, VALUE2));
-
- // Execute MultiRowMutation with conditions
- Put put1 = new Put(ROW).addColumn(FAMILY, QUALIFIER, VALUE);
- MutationProto m1 = ProtobufUtil.toMutation(MutationType.PUT, put1);
- Put put2 = new Put(ROW1).addColumn(FAMILY, QUALIFIER, VALUE1);
- MutationProto m2 = ProtobufUtil.toMutation(MutationType.PUT, put2);
- Delete delete = new Delete(ROW2);
- MutationProto m3 = ProtobufUtil.toMutation(MutationType.DELETE, delete);
-
- MutateRowsRequest.Builder mrmBuilder = MutateRowsRequest.newBuilder();
- mrmBuilder.addMutationRequest(m1);
- mrmBuilder.addMutationRequest(m2);
- mrmBuilder.addMutationRequest(m3);
- mrmBuilder.addCondition(
- ProtobufUtil.toCondition(ROW2, FAMILY, QUALIFIER, CompareOperator.EQUAL, VALUE1, null));
-
- CoprocessorRpcChannel channel = t.coprocessorService(ROW);
- MultiRowMutationService.BlockingInterface service =
- MultiRowMutationService.newBlockingStub(channel);
- MutateRowsResponse response = service.mutateRows(null, mrmBuilder.build());
-
- // Assert
- assertFalse(response.getProcessed());
-
- Result r = t.get(new Get(ROW));
- assertTrue(r.isEmpty());
-
- r = t.get(new Get(ROW1));
- assertTrue(r.isEmpty());
-
- r = t.get(new Get(ROW2));
- assertEquals(Bytes.toString(VALUE2), Bytes.toString(r.getValue(FAMILY, QUALIFIER)));
- }
- }
-
- @TestTemplate
- public void testMultiRowMutationWithMultipleConditionsWhenConditionsMatch() throws Exception {
- final byte[] ROW1 = Bytes.toBytes("testRow1");
- final byte[] ROW2 = Bytes.toBytes("testRow2");
- final byte[] VALUE1 = Bytes.toBytes("testValue1");
- final byte[] VALUE2 = Bytes.toBytes("testValue2");
- TEST_UTIL.createTable(tableName, FAMILY);
- try (Connection conn = getConnection(); Table t = conn.getTable(tableName)) {
- // Add initial data
- t.put(new Put(ROW2).addColumn(FAMILY, QUALIFIER, VALUE2));
-
- // Execute MultiRowMutation with conditions
- Put put1 = new Put(ROW).addColumn(FAMILY, QUALIFIER, VALUE);
- MutationProto m1 = ProtobufUtil.toMutation(MutationType.PUT, put1);
- Put put2 = new Put(ROW1).addColumn(FAMILY, QUALIFIER, VALUE1);
- MutationProto m2 = ProtobufUtil.toMutation(MutationType.PUT, put2);
- Delete delete = new Delete(ROW2);
- MutationProto m3 = ProtobufUtil.toMutation(MutationType.DELETE, delete);
-
- MutateRowsRequest.Builder mrmBuilder = MutateRowsRequest.newBuilder();
- mrmBuilder.addMutationRequest(m1);
- mrmBuilder.addMutationRequest(m2);
- mrmBuilder.addMutationRequest(m3);
- mrmBuilder.addCondition(
- ProtobufUtil.toCondition(ROW, FAMILY, QUALIFIER, CompareOperator.EQUAL, null, null));
- mrmBuilder.addCondition(
- ProtobufUtil.toCondition(ROW2, FAMILY, QUALIFIER, CompareOperator.EQUAL, VALUE2, null));
-
- CoprocessorRpcChannel channel = t.coprocessorService(ROW);
- MultiRowMutationService.BlockingInterface service =
- MultiRowMutationService.newBlockingStub(channel);
- MutateRowsResponse response = service.mutateRows(null, mrmBuilder.build());
-
- // Assert
- assertTrue(response.getProcessed());
-
- Result r = t.get(new Get(ROW));
- assertEquals(Bytes.toString(VALUE), Bytes.toString(r.getValue(FAMILY, QUALIFIER)));
-
- r = t.get(new Get(ROW1));
- assertEquals(Bytes.toString(VALUE1), Bytes.toString(r.getValue(FAMILY, QUALIFIER)));
-
- r = t.get(new Get(ROW2));
- assertTrue(r.isEmpty());
- }
- }
-
- @TestTemplate
- public void testMultiRowMutationWithMultipleConditionsWhenConditionsNotMatch() throws Exception {
- final byte[] ROW1 = Bytes.toBytes("testRow1");
- final byte[] ROW2 = Bytes.toBytes("testRow2");
- final byte[] VALUE1 = Bytes.toBytes("testValue1");
- final byte[] VALUE2 = Bytes.toBytes("testValue2");
- TEST_UTIL.createTable(tableName, FAMILY);
- try (Connection conn = getConnection(); Table t = conn.getTable(tableName)) {
- // Add initial data
- t.put(new Put(ROW2).addColumn(FAMILY, QUALIFIER, VALUE2));
-
- // Execute MultiRowMutation with conditions
- Put put1 = new Put(ROW).addColumn(FAMILY, QUALIFIER, VALUE);
- MutationProto m1 = ProtobufUtil.toMutation(MutationType.PUT, put1);
- Put put2 = new Put(ROW1).addColumn(FAMILY, QUALIFIER, VALUE1);
- MutationProto m2 = ProtobufUtil.toMutation(MutationType.PUT, put2);
- Delete delete = new Delete(ROW2);
- MutationProto m3 = ProtobufUtil.toMutation(MutationType.DELETE, delete);
-
- MutateRowsRequest.Builder mrmBuilder = MutateRowsRequest.newBuilder();
- mrmBuilder.addMutationRequest(m1);
- mrmBuilder.addMutationRequest(m2);
- mrmBuilder.addMutationRequest(m3);
- mrmBuilder.addCondition(
- ProtobufUtil.toCondition(ROW1, FAMILY, QUALIFIER, CompareOperator.EQUAL, null, null));
- mrmBuilder.addCondition(
- ProtobufUtil.toCondition(ROW2, FAMILY, QUALIFIER, CompareOperator.EQUAL, VALUE1, null));
-
- CoprocessorRpcChannel channel = t.coprocessorService(ROW);
- MultiRowMutationService.BlockingInterface service =
- MultiRowMutationService.newBlockingStub(channel);
- MutateRowsResponse response = service.mutateRows(null, mrmBuilder.build());
-
- // Assert
- assertFalse(response.getProcessed());
-
- Result r = t.get(new Get(ROW));
- assertTrue(r.isEmpty());
-
- r = t.get(new Get(ROW1));
- assertTrue(r.isEmpty());
-
- r = t.get(new Get(ROW2));
- assertEquals(Bytes.toString(VALUE2), Bytes.toString(r.getValue(FAMILY, QUALIFIER)));
- }
- }
-
- @TestTemplate
- public void testMultiRowMutationWithFilterConditionWhenConditionMatches() throws Exception {
- final byte[] ROW1 = Bytes.toBytes("testRow1");
- final byte[] ROW2 = Bytes.toBytes("testRow2");
- final byte[] QUALIFIER2 = Bytes.toBytes("testQualifier2");
- final byte[] VALUE1 = Bytes.toBytes("testValue1");
- final byte[] VALUE2 = Bytes.toBytes("testValue2");
- final byte[] VALUE3 = Bytes.toBytes("testValue3");
- TEST_UTIL.createTable(tableName, FAMILY);
- try (Connection conn = getConnection(); Table t = conn.getTable(tableName)) {
- // Add initial data
- t.put(
- new Put(ROW2).addColumn(FAMILY, QUALIFIER, VALUE2).addColumn(FAMILY, QUALIFIER2, VALUE3));
-
- // Execute MultiRowMutation with conditions
- Put put1 = new Put(ROW).addColumn(FAMILY, QUALIFIER, VALUE);
- MutationProto m1 = ProtobufUtil.toMutation(MutationType.PUT, put1);
- Put put2 = new Put(ROW1).addColumn(FAMILY, QUALIFIER, VALUE1);
- MutationProto m2 = ProtobufUtil.toMutation(MutationType.PUT, put2);
- Delete delete = new Delete(ROW2);
- MutationProto m3 = ProtobufUtil.toMutation(MutationType.DELETE, delete);
-
- MutateRowsRequest.Builder mrmBuilder = MutateRowsRequest.newBuilder();
- mrmBuilder.addMutationRequest(m1);
- mrmBuilder.addMutationRequest(m2);
- mrmBuilder.addMutationRequest(m3);
- mrmBuilder.addCondition(ProtobufUtil.toCondition(ROW2,
- new FilterList(
- new SingleColumnValueFilter(FAMILY, QUALIFIER, CompareOperator.EQUAL, VALUE2),
- new SingleColumnValueFilter(FAMILY, QUALIFIER2, CompareOperator.EQUAL, VALUE3)),
- null));
-
- CoprocessorRpcChannel channel = t.coprocessorService(ROW);
- MultiRowMutationService.BlockingInterface service =
- MultiRowMutationService.newBlockingStub(channel);
- MutateRowsResponse response = service.mutateRows(null, mrmBuilder.build());
-
- // Assert
- assertTrue(response.getProcessed());
-
- Result r = t.get(new Get(ROW));
- assertEquals(Bytes.toString(VALUE), Bytes.toString(r.getValue(FAMILY, QUALIFIER)));
-
- r = t.get(new Get(ROW1));
- assertEquals(Bytes.toString(VALUE1), Bytes.toString(r.getValue(FAMILY, QUALIFIER)));
-
- r = t.get(new Get(ROW2));
- assertTrue(r.isEmpty());
- }
- }
-
- @TestTemplate
- public void testMultiRowMutationWithFilterConditionWhenConditionNotMatch() throws Exception {
- final byte[] ROW1 = Bytes.toBytes("testRow1");
- final byte[] ROW2 = Bytes.toBytes("testRow2");
- final byte[] QUALIFIER2 = Bytes.toBytes("testQualifier2");
- final byte[] VALUE1 = Bytes.toBytes("testValue1");
- final byte[] VALUE2 = Bytes.toBytes("testValue2");
- final byte[] VALUE3 = Bytes.toBytes("testValue3");
- TEST_UTIL.createTable(tableName, FAMILY);
- try (Connection conn = getConnection(); Table t = conn.getTable(tableName)) {
- // Add initial data
- t.put(
- new Put(ROW2).addColumn(FAMILY, QUALIFIER, VALUE2).addColumn(FAMILY, QUALIFIER2, VALUE3));
-
- // Execute MultiRowMutation with conditions
- Put put1 = new Put(ROW).addColumn(FAMILY, QUALIFIER, VALUE);
- MutationProto m1 = ProtobufUtil.toMutation(MutationType.PUT, put1);
- Put put2 = new Put(ROW1).addColumn(FAMILY, QUALIFIER, VALUE1);
- MutationProto m2 = ProtobufUtil.toMutation(MutationType.PUT, put2);
- Delete delete = new Delete(ROW2);
- MutationProto m3 = ProtobufUtil.toMutation(MutationType.DELETE, delete);
-
- MutateRowsRequest.Builder mrmBuilder = MutateRowsRequest.newBuilder();
- mrmBuilder.addMutationRequest(m1);
- mrmBuilder.addMutationRequest(m2);
- mrmBuilder.addMutationRequest(m3);
- mrmBuilder.addCondition(ProtobufUtil.toCondition(ROW2,
- new FilterList(
- new SingleColumnValueFilter(FAMILY, QUALIFIER, CompareOperator.EQUAL, VALUE2),
- new SingleColumnValueFilter(FAMILY, QUALIFIER2, CompareOperator.EQUAL, VALUE2)),
- null));
-
- CoprocessorRpcChannel channel = t.coprocessorService(ROW);
- MultiRowMutationService.BlockingInterface service =
- MultiRowMutationService.newBlockingStub(channel);
- MutateRowsResponse response = service.mutateRows(null, mrmBuilder.build());
-
- // Assert
- assertFalse(response.getProcessed());
-
- Result r = t.get(new Get(ROW));
- assertTrue(r.isEmpty());
-
- r = t.get(new Get(ROW1));
- assertTrue(r.isEmpty());
-
- r = t.get(new Get(ROW2));
- assertEquals(Bytes.toString(VALUE2), Bytes.toString(r.getValue(FAMILY, QUALIFIER)));
- }
- }
-
@TestTemplate
public void testRowMutations() throws Exception {
LOG.info("Starting testRowMutations");
@@ -862,305 +506,6 @@ public class FromClientSideTest5 extends FromClientSideTestBase {
}
}
- @TestTemplate
- public void testCheckAndPut() throws IOException {
- final byte[] anotherrow = Bytes.toBytes("anotherrow");
- final byte[] value2 = Bytes.toBytes("abcd");
- TEST_UTIL.createTable(tableName, FAMILY);
- try (Connection conn = getConnection(); Table table = conn.getTable(tableName)) {
- Put put1 = new Put(ROW);
- put1.addColumn(FAMILY, QUALIFIER, VALUE);
-
- // row doesn't exist, so using non-null value should be considered "not match".
- boolean ok =
- table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER).ifEquals(VALUE).thenPut(put1);
- assertFalse(ok);
-
- // row doesn't exist, so using "ifNotExists" should be considered "match".
- ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER).ifNotExists().thenPut(put1);
- assertTrue(ok);
-
- // row now exists, so using "ifNotExists" should be considered "not match".
- ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER).ifNotExists().thenPut(put1);
- assertFalse(ok);
-
- Put put2 = new Put(ROW);
- put2.addColumn(FAMILY, QUALIFIER, value2);
-
- // row now exists, use the matching value to check
- ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER).ifEquals(VALUE).thenPut(put2);
- assertTrue(ok);
-
- Put put3 = new Put(anotherrow);
- put3.addColumn(FAMILY, QUALIFIER, VALUE);
-
- // try to do CheckAndPut on different rows
- try {
- table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER).ifEquals(value2).thenPut(put3);
- fail("trying to check and modify different rows should have failed.");
- } catch (Exception ignored) {
- }
- }
- }
-
- @TestTemplate
- public void testCheckAndMutateWithTimeRange() throws IOException {
- TEST_UTIL.createTable(tableName, FAMILY);
- try (Connection conn = getConnection(); Table table = conn.getTable(tableName)) {
- final long ts = EnvironmentEdgeManager.currentTime() / 2;
- Put put = new Put(ROW);
- put.addColumn(FAMILY, QUALIFIER, ts, VALUE);
-
- boolean ok =
- table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER).ifNotExists().thenPut(put);
- assertTrue(ok);
-
- ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
- .timeRange(TimeRange.at(ts + 10000)).ifEquals(VALUE).thenPut(put);
- assertFalse(ok);
-
- ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
- .timeRange(TimeRange.from(ts + 10000)).ifEquals(VALUE).thenPut(put);
- assertFalse(ok);
-
- ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
- .timeRange(TimeRange.between(ts + 10000, ts + 20000)).ifEquals(VALUE).thenPut(put);
- assertFalse(ok);
-
- ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER).timeRange(TimeRange.until(ts))
- .ifEquals(VALUE).thenPut(put);
- assertFalse(ok);
-
- ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER).timeRange(TimeRange.at(ts))
- .ifEquals(VALUE).thenPut(put);
- assertTrue(ok);
-
- ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER).timeRange(TimeRange.from(ts))
- .ifEquals(VALUE).thenPut(put);
- assertTrue(ok);
-
- ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
- .timeRange(TimeRange.between(ts, ts + 20000)).ifEquals(VALUE).thenPut(put);
- assertTrue(ok);
-
- ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
- .timeRange(TimeRange.until(ts + 10000)).ifEquals(VALUE).thenPut(put);
- assertTrue(ok);
-
- RowMutations rm = new RowMutations(ROW).add((Mutation) put);
- ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
- .timeRange(TimeRange.at(ts + 10000)).ifEquals(VALUE).thenMutate(rm);
- assertFalse(ok);
-
- ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER).timeRange(TimeRange.at(ts))
- .ifEquals(VALUE).thenMutate(rm);
- assertTrue(ok);
-
- Delete delete = new Delete(ROW).addColumn(FAMILY, QUALIFIER);
-
- ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
- .timeRange(TimeRange.at(ts + 10000)).ifEquals(VALUE).thenDelete(delete);
- assertFalse(ok);
-
- ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER).timeRange(TimeRange.at(ts))
- .ifEquals(VALUE).thenDelete(delete);
- assertTrue(ok);
- }
- }
-
- @TestTemplate
- public void testCheckAndPutWithCompareOp() throws IOException {
- final byte[] value1 = Bytes.toBytes("aaaa");
- final byte[] value2 = Bytes.toBytes("bbbb");
- final byte[] value3 = Bytes.toBytes("cccc");
- final byte[] value4 = Bytes.toBytes("dddd");
- TEST_UTIL.createTable(tableName, FAMILY);
- try (Connection conn = getConnection(); Table table = conn.getTable(tableName)) {
- Put put2 = new Put(ROW);
- put2.addColumn(FAMILY, QUALIFIER, value2);
-
- Put put3 = new Put(ROW);
- put3.addColumn(FAMILY, QUALIFIER, value3);
-
- // row doesn't exist, so using "ifNotExists" should be considered "match".
- boolean ok =
- table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER).ifNotExists().thenPut(put2);
- assertTrue(ok);
-
- // cell = "bbbb", using "aaaa" to compare only LESS/LESS_OR_EQUAL/NOT_EQUAL
- // turns out "match"
- ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
- .ifMatches(CompareOperator.GREATER, value1).thenPut(put2);
- assertFalse(ok);
- ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
- .ifMatches(CompareOperator.EQUAL, value1).thenPut(put2);
- assertFalse(ok);
- ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
- .ifMatches(CompareOperator.GREATER_OR_EQUAL, value1).thenPut(put2);
- assertFalse(ok);
- ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
- .ifMatches(CompareOperator.LESS, value1).thenPut(put2);
- assertTrue(ok);
- ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
- .ifMatches(CompareOperator.LESS_OR_EQUAL, value1).thenPut(put2);
- assertTrue(ok);
- ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
- .ifMatches(CompareOperator.NOT_EQUAL, value1).thenPut(put3);
- assertTrue(ok);
-
- // cell = "cccc", using "dddd" to compare only LARGER/LARGER_OR_EQUAL/NOT_EQUAL
- // turns out "match"
- ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
- .ifMatches(CompareOperator.LESS, value4).thenPut(put3);
- assertFalse(ok);
- ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
- .ifMatches(CompareOperator.LESS_OR_EQUAL, value4).thenPut(put3);
- assertFalse(ok);
- ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
- .ifMatches(CompareOperator.EQUAL, value4).thenPut(put3);
- assertFalse(ok);
- ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
- .ifMatches(CompareOperator.GREATER, value4).thenPut(put3);
- assertTrue(ok);
- ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
- .ifMatches(CompareOperator.GREATER_OR_EQUAL, value4).thenPut(put3);
- assertTrue(ok);
- ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
- .ifMatches(CompareOperator.NOT_EQUAL, value4).thenPut(put2);
- assertTrue(ok);
-
- // cell = "bbbb", using "bbbb" to compare only GREATER_OR_EQUAL/LESS_OR_EQUAL/EQUAL
- // turns out "match"
- ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
- .ifMatches(CompareOperator.GREATER, value2).thenPut(put2);
- assertFalse(ok);
- ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
- .ifMatches(CompareOperator.NOT_EQUAL, value2).thenPut(put2);
- assertFalse(ok);
- ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
- .ifMatches(CompareOperator.LESS, value2).thenPut(put2);
- assertFalse(ok);
- ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
- .ifMatches(CompareOperator.GREATER_OR_EQUAL, value2).thenPut(put2);
- assertTrue(ok);
- ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
- .ifMatches(CompareOperator.LESS_OR_EQUAL, value2).thenPut(put2);
- assertTrue(ok);
- ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
- .ifMatches(CompareOperator.EQUAL, value2).thenPut(put3);
- assertTrue(ok);
- }
- }
-
- @TestTemplate
- public void testCheckAndDelete() throws IOException {
- final byte[] value1 = Bytes.toBytes("aaaa");
- TEST_UTIL.createTable(tableName, FAMILY);
- try (Connection conn = getConnection(); Table table = conn.getTable(tableName)) {
- Put put = new Put(ROW);
- put.addColumn(FAMILY, QUALIFIER, value1);
- table.put(put);
-
- Delete delete = new Delete(ROW);
- delete.addColumns(FAMILY, QUALIFIER);
-
- boolean ok =
- table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER).ifEquals(value1).thenDelete(delete);
- assertTrue(ok);
- }
- }
-
- @TestTemplate
- public void testCheckAndDeleteWithCompareOp() throws IOException {
- final byte[] value1 = Bytes.toBytes("aaaa");
- final byte[] value2 = Bytes.toBytes("bbbb");
- final byte[] value3 = Bytes.toBytes("cccc");
- final byte[] value4 = Bytes.toBytes("dddd");
- TEST_UTIL.createTable(tableName, FAMILY);
- try (Connection conn = getConnection(); Table table = conn.getTable(tableName)) {
- Put put2 = new Put(ROW);
- put2.addColumn(FAMILY, QUALIFIER, value2);
- table.put(put2);
-
- Put put3 = new Put(ROW);
- put3.addColumn(FAMILY, QUALIFIER, value3);
-
- Delete delete = new Delete(ROW);
- delete.addColumns(FAMILY, QUALIFIER);
-
- // cell = "bbbb", using "aaaa" to compare only LESS/LESS_OR_EQUAL/NOT_EQUAL
- // turns out "match"
- boolean ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
- .ifMatches(CompareOperator.GREATER, value1).thenDelete(delete);
- assertFalse(ok);
- ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
- .ifMatches(CompareOperator.EQUAL, value1).thenDelete(delete);
- assertFalse(ok);
- ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
- .ifMatches(CompareOperator.GREATER_OR_EQUAL, value1).thenDelete(delete);
- assertFalse(ok);
- ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
- .ifMatches(CompareOperator.LESS, value1).thenDelete(delete);
- assertTrue(ok);
- table.put(put2);
- ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
- .ifMatches(CompareOperator.LESS_OR_EQUAL, value1).thenDelete(delete);
- assertTrue(ok);
- table.put(put2);
- ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
- .ifMatches(CompareOperator.NOT_EQUAL, value1).thenDelete(delete);
- assertTrue(ok);
-
- // cell = "cccc", using "dddd" to compare only LARGER/LARGER_OR_EQUAL/NOT_EQUAL
- // turns out "match"
- table.put(put3);
- ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
- .ifMatches(CompareOperator.LESS, value4).thenDelete(delete);
- assertFalse(ok);
- ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
- .ifMatches(CompareOperator.LESS_OR_EQUAL, value4).thenDelete(delete);
- assertFalse(ok);
- ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
- .ifMatches(CompareOperator.EQUAL, value4).thenDelete(delete);
- assertFalse(ok);
- ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
- .ifMatches(CompareOperator.GREATER, value4).thenDelete(delete);
- assertTrue(ok);
- table.put(put3);
- ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
- .ifMatches(CompareOperator.GREATER_OR_EQUAL, value4).thenDelete(delete);
- assertTrue(ok);
- table.put(put3);
- ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
- .ifMatches(CompareOperator.NOT_EQUAL, value4).thenDelete(delete);
- assertTrue(ok);
-
- // cell = "bbbb", using "bbbb" to compare only GREATER_OR_EQUAL/LESS_OR_EQUAL/EQUAL
- // turns out "match"
- table.put(put2);
- ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
- .ifMatches(CompareOperator.GREATER, value2).thenDelete(delete);
- assertFalse(ok);
- ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
- .ifMatches(CompareOperator.NOT_EQUAL, value2).thenDelete(delete);
- assertFalse(ok);
- ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
- .ifMatches(CompareOperator.LESS, value2).thenDelete(delete);
- assertFalse(ok);
- ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
- .ifMatches(CompareOperator.GREATER_OR_EQUAL, value2).thenDelete(delete);
- assertTrue(ok);
- table.put(put2);
- ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
- .ifMatches(CompareOperator.LESS_OR_EQUAL, value2).thenDelete(delete);
- assertTrue(ok);
- table.put(put2);
- ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
- .ifMatches(CompareOperator.EQUAL, value2).thenDelete(delete);
- assertTrue(ok);
- }
- }
-
/**
* Test ScanMetrics
*/
@@ -1753,631 +1098,6 @@ public class FromClientSideTest5 extends FromClientSideTestBase {
}
}
- @TestTemplate
- public void testSuperSimpleWithReverseScan() throws Exception {
- TEST_UTIL.createTable(tableName, FAMILY);
- try (Connection conn = getConnection(); Table ht = conn.getTable(tableName)) {
- Put put = new Put(Bytes.toBytes("0-b11111-0000000000000000000"));
- put.addColumn(FAMILY, QUALIFIER, VALUE);
- ht.put(put);
- put = new Put(Bytes.toBytes("0-b11111-0000000000000000002"));
- put.addColumn(FAMILY, QUALIFIER, VALUE);
- ht.put(put);
- put = new Put(Bytes.toBytes("0-b11111-0000000000000000004"));
- put.addColumn(FAMILY, QUALIFIER, VALUE);
- ht.put(put);
- put = new Put(Bytes.toBytes("0-b11111-0000000000000000006"));
- put.addColumn(FAMILY, QUALIFIER, VALUE);
- ht.put(put);
- put = new Put(Bytes.toBytes("0-b11111-0000000000000000008"));
- put.addColumn(FAMILY, QUALIFIER, VALUE);
- ht.put(put);
- put = new Put(Bytes.toBytes("0-b22222-0000000000000000001"));
- put.addColumn(FAMILY, QUALIFIER, VALUE);
- ht.put(put);
- put = new Put(Bytes.toBytes("0-b22222-0000000000000000003"));
- put.addColumn(FAMILY, QUALIFIER, VALUE);
- ht.put(put);
- put = new Put(Bytes.toBytes("0-b22222-0000000000000000005"));
- put.addColumn(FAMILY, QUALIFIER, VALUE);
- ht.put(put);
- put = new Put(Bytes.toBytes("0-b22222-0000000000000000007"));
- put.addColumn(FAMILY, QUALIFIER, VALUE);
- ht.put(put);
- put = new Put(Bytes.toBytes("0-b22222-0000000000000000009"));
- put.addColumn(FAMILY, QUALIFIER, VALUE);
- ht.put(put);
- Scan scan = new Scan().withStartRow(Bytes.toBytes("0-b11111-9223372036854775807"))
- .withStopRow(Bytes.toBytes("0-b11111-0000000000000000000"), true);
- scan.setReversed(true);
- try (ResultScanner scanner = ht.getScanner(scan)) {
- Result result = scanner.next();
- assertTrue(Bytes.equals(result.getRow(), Bytes.toBytes("0-b11111-0000000000000000008")));
- }
- }
- }
-
- @TestTemplate
- public void testFiltersWithReverseScan() throws Exception {
- TEST_UTIL.createTable(tableName, FAMILY);
- try (Connection conn = getConnection(); Table ht = conn.getTable(tableName)) {
- byte[][] ROWS = makeN(ROW, 10);
- byte[][] QUALIFIERS =
- { Bytes.toBytes("col0-<d2v1>-<d3v2>"), Bytes.toBytes("col1-<d2v1>-<d3v2>"),
- Bytes.toBytes("col2-<d2v1>-<d3v2>"), Bytes.toBytes("col3-<d2v1>-<d3v2>"),
- Bytes.toBytes("col4-<d2v1>-<d3v2>"), Bytes.toBytes("col5-<d2v1>-<d3v2>"),
- Bytes.toBytes("col6-<d2v1>-<d3v2>"), Bytes.toBytes("col7-<d2v1>-<d3v2>"),
- Bytes.toBytes("col8-<d2v1>-<d3v2>"), Bytes.toBytes("col9-<d2v1>-<d3v2>") };
- for (int i = 0; i < 10; i++) {
- Put put = new Put(ROWS[i]);
- put.addColumn(FAMILY, QUALIFIERS[i], VALUE);
- ht.put(put);
- }
- Scan scan = new Scan();
- scan.setReversed(true);
- scan.addFamily(FAMILY);
- Filter filter =
- new QualifierFilter(CompareOperator.EQUAL, new RegexStringComparator("col[1-5]"));
- scan.setFilter(filter);
- try (ResultScanner scanner = ht.getScanner(scan)) {
- int expectedIndex = 5;
- for (Result result : scanner) {
- assertEquals(1, result.size());
- Cell c = result.rawCells()[0];
- assertTrue(Bytes.equals(c.getRowArray(), c.getRowOffset(), c.getRowLength(),
- ROWS[expectedIndex], 0, ROWS[expectedIndex].length));
- assertTrue(
- Bytes.equals(c.getQualifierArray(), c.getQualifierOffset(), c.getQualifierLength(),
- QUALIFIERS[expectedIndex], 0, QUALIFIERS[expectedIndex].length));
- expectedIndex--;
- }
- assertEquals(0, expectedIndex);
- }
- }
- }
-
- @TestTemplate
- public void testKeyOnlyFilterWithReverseScan() throws Exception {
- TEST_UTIL.createTable(tableName, FAMILY);
- try (Connection conn = getConnection(); Table ht = conn.getTable(tableName)) {
- byte[][] ROWS = makeN(ROW, 10);
- byte[][] QUALIFIERS =
- { Bytes.toBytes("col0-<d2v1>-<d3v2>"), Bytes.toBytes("col1-<d2v1>-<d3v2>"),
- Bytes.toBytes("col2-<d2v1>-<d3v2>"), Bytes.toBytes("col3-<d2v1>-<d3v2>"),
- Bytes.toBytes("col4-<d2v1>-<d3v2>"), Bytes.toBytes("col5-<d2v1>-<d3v2>"),
- Bytes.toBytes("col6-<d2v1>-<d3v2>"), Bytes.toBytes("col7-<d2v1>-<d3v2>"),
- Bytes.toBytes("col8-<d2v1>-<d3v2>"), Bytes.toBytes("col9-<d2v1>-<d3v2>") };
- for (int i = 0; i < 10; i++) {
- Put put = new Put(ROWS[i]);
- put.addColumn(FAMILY, QUALIFIERS[i], VALUE);
- ht.put(put);
- }
- Scan scan = new Scan();
- scan.setReversed(true);
- scan.addFamily(FAMILY);
- Filter filter = new KeyOnlyFilter(true);
- scan.setFilter(filter);
- try (ResultScanner ignored = ht.getScanner(scan)) {
- int count = 0;
- for (Result result : ht.getScanner(scan)) {
- assertEquals(1, result.size());
- assertEquals(Bytes.SIZEOF_INT, result.rawCells()[0].getValueLength());
- assertEquals(VALUE.length, Bytes.toInt(CellUtil.cloneValue(result.rawCells()[0])));
- count++;
- }
- assertEquals(10, count);
- }
- }
- }
-
- /**
- * Test simple table and non-existent row cases.
- */
- @TestTemplate
- public void testSimpleMissingWithReverseScan() throws Exception {
- TEST_UTIL.createTable(tableName, FAMILY);
- try (Connection conn = getConnection(); Table ht = conn.getTable(tableName)) {
- byte[][] ROWS = makeN(ROW, 4);
-
- // Try to get a row on an empty table
- Scan scan = new Scan();
- scan.setReversed(true);
- Result result = getSingleScanResult(ht, scan);
- assertNullResult(result);
-
- scan = new Scan().withStartRow(ROWS[0]);
- scan.setReversed(true);
- result = getSingleScanResult(ht, scan);
- assertNullResult(result);
-
- scan = new Scan().withStartRow(ROWS[0]).withStopRow(ROWS[1], true);
- scan.setReversed(true);
- result = getSingleScanResult(ht, scan);
- assertNullResult(result);
-
- scan = new Scan();
- scan.setReversed(true);
- scan.addFamily(FAMILY);
- result = getSingleScanResult(ht, scan);
- assertNullResult(result);
-
- scan = new Scan();
- scan.setReversed(true);
- scan.addColumn(FAMILY, QUALIFIER);
- result = getSingleScanResult(ht, scan);
- assertNullResult(result);
-
- // Insert a row
- Put put = new Put(ROWS[2]);
- put.addColumn(FAMILY, QUALIFIER, VALUE);
- ht.put(put);
-
- // Make sure we can scan the row
- scan = new Scan();
- scan.setReversed(true);
- result = getSingleScanResult(ht, scan);
- assertSingleResult(result, ROWS[2], FAMILY, QUALIFIER, VALUE);
-
- scan = new Scan().withStartRow(ROWS[3]).withStopRow(ROWS[0], true);
- scan.setReversed(true);
- result = getSingleScanResult(ht, scan);
- assertSingleResult(result, ROWS[2], FAMILY, QUALIFIER, VALUE);
-
- scan = new Scan().withStartRow(ROWS[2]).withStopRow(ROWS[1], true);
- scan.setReversed(true);
- result = getSingleScanResult(ht, scan);
- assertSingleResult(result, ROWS[2], FAMILY, QUALIFIER, VALUE);
-
- // Try to scan empty rows around it
- // Introduced MemStore#shouldSeekForReverseScan to fix the following
- scan = new Scan().withStartRow(ROWS[1]);
- scan.setReversed(true);
- result = getSingleScanResult(ht, scan);
- assertNullResult(result);
- }
- }
-
- @TestTemplate
- public void testNullWithReverseScan() throws Exception {
- TEST_UTIL.createTable(tableName, FAMILY);
- try (Connection conn = getConnection(); Table ht = conn.getTable(tableName)) {
- // Null qualifier (should work)
- Put put = new Put(ROW);
- put.addColumn(FAMILY, null, VALUE);
- ht.put(put);
- scanTestNull(ht, ROW, FAMILY, VALUE, true);
- Delete delete = new Delete(ROW);
- delete.addColumns(FAMILY, null);
- ht.delete(delete);
- }
-
- // Use a new table
- TableName newTableName = TableName.valueOf(tableName.toString() + "2");
- TEST_UTIL.createTable(newTableName, FAMILY);
- try (Connection conn = getConnection(); Table ht = conn.getTable(newTableName)) {
- // Empty qualifier, byte[0] instead of null (should work)
- Put put = new Put(ROW);
- put.addColumn(FAMILY, HConstants.EMPTY_BYTE_ARRAY, VALUE);
- ht.put(put);
- scanTestNull(ht, ROW, FAMILY, VALUE, true);
- TEST_UTIL.flush();
- scanTestNull(ht, ROW, FAMILY, VALUE, true);
- Delete delete = new Delete(ROW);
- delete.addColumns(FAMILY, HConstants.EMPTY_BYTE_ARRAY);
- ht.delete(delete);
- // Null value
- put = new Put(ROW);
- put.addColumn(FAMILY, QUALIFIER, null);
- ht.put(put);
- Scan scan = new Scan();
- scan.setReversed(true);
- scan.addColumn(FAMILY, QUALIFIER);
- Result result = getSingleScanResult(ht, scan);
- assertSingleResult(result, ROW, FAMILY, QUALIFIER, null);
- }
- }
-
- @TestTemplate
- @SuppressWarnings("checkstyle:MethodLength")
- public void testDeletesWithReverseScan() throws Exception {
- byte[][] ROWS = makeNAscii(ROW, 6);
- byte[][] FAMILIES = makeNAscii(FAMILY, 3);
- byte[][] VALUES = makeN(VALUE, 5);
- long[] ts = { 1000, 2000, 3000, 4000, 5000 };
- TEST_UTIL.createTable(tableName, FAMILIES, 3);
- try (Connection conn = getConnection(); Table ht = conn.getTable(tableName)) {
- Put put = new Put(ROW);
- put.addColumn(FAMILIES[0], QUALIFIER, ts[0], VALUES[0]);
- put.addColumn(FAMILIES[0], QUALIFIER, ts[1], VALUES[1]);
- ht.put(put);
-
- Delete delete = new Delete(ROW);
- delete.addFamily(FAMILIES[0], ts[0]);
- ht.delete(delete);
-
- Scan scan = new Scan().withStartRow(ROW);
- scan.setReversed(true);
- scan.addFamily(FAMILIES[0]);
- scan.readVersions(Integer.MAX_VALUE);
- Result result = getSingleScanResult(ht, scan);
- assertNResult(result, ROW, FAMILIES[0], QUALIFIER, new long[] { ts[1] },
- new byte[][] { VALUES[1] }, 0, 0);
-
- // Test delete latest version
- put = new Put(ROW);
- put.addColumn(FAMILIES[0], QUALIFIER, ts[4], VALUES[4]);
- put.addColumn(FAMILIES[0], QUALIFIER, ts[2], VALUES[2]);
- put.addColumn(FAMILIES[0], QUALIFIER, ts[3], VALUES[3]);
- put.addColumn(FAMILIES[0], null, ts[4], VALUES[4]);
- put.addColumn(FAMILIES[0], null, ts[2], VALUES[2]);
- put.addColumn(FAMILIES[0], null, ts[3], VALUES[3]);
- ht.put(put);
-
- delete = new Delete(ROW);
- delete.addColumn(FAMILIES[0], QUALIFIER); // ts[4]
- ht.delete(delete);
-
- scan = new Scan().withStartRow(ROW);
- scan.setReversed(true);
- scan.addColumn(FAMILIES[0], QUALIFIER);
- scan.readVersions(Integer.MAX_VALUE);
- result = getSingleScanResult(ht, scan);
- assertNResult(result, ROW, FAMILIES[0], QUALIFIER, new long[] { ts[1], ts[2], ts[3] },
- new byte[][] { VALUES[1], VALUES[2], VALUES[3] }, 0, 2);
-
- // Test for HBASE-1847
- delete = new Delete(ROW);
- delete.addColumn(FAMILIES[0], null);
- ht.delete(delete);
-
- // Cleanup null qualifier
- delete = new Delete(ROW);
- delete.addColumns(FAMILIES[0], null);
- ht.delete(delete);
-
- // Expected client behavior might be that you can re-put deleted values
- // But alas, this is not to be. We can't put them back in either case.
-
- put = new Put(ROW);
- put.addColumn(FAMILIES[0], QUALIFIER, ts[0], VALUES[0]);
- put.addColumn(FAMILIES[0], QUALIFIER, ts[4], VALUES[4]);
- ht.put(put);
-
- // The Scanner returns the previous values, the expected-naive-unexpected
- // behavior
-
- scan = new Scan().withStartRow(ROW);
- scan.setReversed(true);
- scan.addFamily(FAMILIES[0]);
- scan.readVersions(Integer.MAX_VALUE);
- result = getSingleScanResult(ht, scan);
- assertNResult(result, ROW, FAMILIES[0], QUALIFIER, new long[] { ts[1], ts[2], ts[3] },
- new byte[][] { VALUES[1], VALUES[2], VALUES[3] }, 0, 2);
-
- // Test deleting an entire family from one row but not the other various
- // ways
-
- put = new Put(ROWS[0]);
- put.addColumn(FAMILIES[1], QUALIFIER, ts[0], VALUES[0]);
- put.addColumn(FAMILIES[1], QUALIFIER, ts[1], VALUES[1]);
- put.addColumn(FAMILIES[2], QUALIFIER, ts[2], VALUES[2]);
- put.addColumn(FAMILIES[2], QUALIFIER, ts[3], VALUES[3]);
- ht.put(put);
-
- put = new Put(ROWS[1]);
- put.addColumn(FAMILIES[1], QUALIFIER, ts[0], VALUES[0]);
- put.addColumn(FAMILIES[1], QUALIFIER, ts[1], VALUES[1]);
- put.addColumn(FAMILIES[2], QUALIFIER, ts[2], VALUES[2]);
- put.addColumn(FAMILIES[2], QUALIFIER, ts[3], VALUES[3]);
- ht.put(put);
-
- put = new Put(ROWS[2]);
- put.addColumn(FAMILIES[1], QUALIFIER, ts[0], VALUES[0]);
- put.addColumn(FAMILIES[1], QUALIFIER, ts[1], VALUES[1]);
- put.addColumn(FAMILIES[2], QUALIFIER, ts[2], VALUES[2]);
- put.addColumn(FAMILIES[2], QUALIFIER, ts[3], VALUES[3]);
- ht.put(put);
-
- delete = new Delete(ROWS[0]);
- delete.addFamily(FAMILIES[2]);
- ht.delete(delete);
-
- delete = new Delete(ROWS[1]);
- delete.addColumns(FAMILIES[1], QUALIFIER);
- ht.delete(delete);
-
- delete = new Delete(ROWS[2]);
- delete.addColumn(FAMILIES[1], QUALIFIER);
- delete.addColumn(FAMILIES[1], QUALIFIER);
- delete.addColumn(FAMILIES[2], QUALIFIER);
- ht.delete(delete);
-
- scan = new Scan().withStartRow(ROWS[0]);
- scan.setReversed(true);
- scan.addFamily(FAMILIES[1]);
- scan.addFamily(FAMILIES[2]);
- scan.readVersions(Integer.MAX_VALUE);
- result = getSingleScanResult(ht, scan);
- assertEquals(2, result.size(), "Expected 2 keys but received " + result.size());
- assertNResult(result, ROWS[0], FAMILIES[1], QUALIFIER, new long[] { ts[0], ts[1] },
- new byte[][] { VALUES[0], VALUES[1] }, 0, 1);
-
- scan = new Scan().withStartRow(ROWS[1]);
- scan.setReversed(true);
- scan.addFamily(FAMILIES[1]);
- scan.addFamily(FAMILIES[2]);
- scan.readVersions(Integer.MAX_VALUE);
- result = getSingleScanResult(ht, scan);
- assertEquals(2, result.size(), "Expected 2 keys but received " + result.size());
-
- scan = new Scan().withStartRow(ROWS[2]);
- scan.setReversed(true);
- scan.addFamily(FAMILIES[1]);
- scan.addFamily(FAMILIES[2]);
- scan.readVersions(Integer.MAX_VALUE);
- result = getSingleScanResult(ht, scan);
- assertEquals(1, result.size());
- assertNResult(result, ROWS[2], FAMILIES[2], QUALIFIER, new long[] { ts[2] },
- new byte[][] { VALUES[2] }, 0, 0);
-
- // Test if we delete the family first in one row (HBASE-1541)
-
- delete = new Delete(ROWS[3]);
- delete.addFamily(FAMILIES[1]);
- ht.delete(delete);
-
- put = new Put(ROWS[3]);
- put.addColumn(FAMILIES[2], QUALIFIER, VALUES[0]);
- ht.put(put);
-
- put = new Put(ROWS[4]);
- put.addColumn(FAMILIES[1], QUALIFIER, VALUES[1]);
- put.addColumn(FAMILIES[2], QUALIFIER, VALUES[2]);
- ht.put(put);
-
- scan = new Scan().withStartRow(ROWS[4]);
- scan.setReversed(true);
- scan.addFamily(FAMILIES[1]);
- scan.addFamily(FAMILIES[2]);
- scan.readVersions(Integer.MAX_VALUE);
- try (ResultScanner scanner = ht.getScanner(scan)) {
- result = scanner.next();
- assertEquals(2, result.size(), "Expected 2 keys but received " + result.size());
- assertTrue(Bytes.equals(CellUtil.cloneRow(result.rawCells()[0]), ROWS[4]));
- assertTrue(Bytes.equals(CellUtil.cloneRow(result.rawCells()[1]), ROWS[4]));
- assertTrue(Bytes.equals(CellUtil.cloneValue(result.rawCells()[0]), VALUES[1]));
- assertTrue(Bytes.equals(CellUtil.cloneValue(result.rawCells()[1]), VALUES[2]));
- result = scanner.next();
- assertEquals(1, result.size(), "Expected 1 key but received " + result.size());
- assertTrue(Bytes.equals(CellUtil.cloneRow(result.rawCells()[0]), ROWS[3]));
- assertTrue(Bytes.equals(CellUtil.cloneValue(result.rawCells()[0]), VALUES[0]));
- }
- }
- }
-
- /**
- * Tests reversed scan under multi regions
- */
- @TestTemplate
- public void testReversedScanUnderMultiRegions() throws Exception {
- // Test Initialization.
- byte[] maxByteArray = ConnectionUtils.MAX_BYTE_ARRAY;
- byte[][] splitRows = new byte[][] { Bytes.toBytes("005"),
- Bytes.add(Bytes.toBytes("005"), Bytes.multiple(maxByteArray, 16)), Bytes.toBytes("006"),
- Bytes.add(Bytes.toBytes("006"), Bytes.multiple(maxByteArray, 8)), Bytes.toBytes("007"),
- Bytes.add(Bytes.toBytes("007"), Bytes.multiple(maxByteArray, 4)), Bytes.toBytes("008"),
- Bytes.multiple(maxByteArray, 2) };
- TEST_UTIL.createTable(tableName, FAMILY, splitRows);
- TEST_UTIL.waitUntilAllRegionsAssigned(tableName);
- try (Connection conn = getConnection(); Table table = conn.getTable(tableName)) {
- try (RegionLocator l = conn.getRegionLocator(tableName)) {
- assertEquals(splitRows.length + 1, l.getAllRegionLocations().size());
- }
- // Insert one row each region
- int insertNum = splitRows.length;
- for (byte[] splitRow : splitRows) {
- Put put = new Put(splitRow);
- put.addColumn(FAMILY, QUALIFIER, VALUE);
- table.put(put);
- }
-
- // scan forward
- try (ResultScanner scanner = table.getScanner(new Scan())) {
- int count = 0;
- for (Result r : scanner) {
- assertFalse(r.isEmpty());
- count++;
- }
- assertEquals(insertNum, count);
- }
-
- // scan backward
- Scan scan = new Scan();
- scan.setReversed(true);
- try (ResultScanner scanner = table.getScanner(scan)) {
- int count = 0;
- byte[] lastRow = null;
- for (Result r : scanner) {
- assertFalse(r.isEmpty());
- count++;
- byte[] thisRow = r.getRow();
- if (lastRow != null) {
- assertTrue(Bytes.compareTo(thisRow, lastRow) < 0, "Error scan order, last row= "
- + Bytes.toString(lastRow) + ",this row=" + Bytes.toString(thisRow));
- }
- lastRow = thisRow;
- }
- assertEquals(insertNum, count);
- }
- }
- }
-
- /**
- * Tests reversed scan under multi regions
- */
- @TestTemplate
- public void testSmallReversedScanUnderMultiRegions() throws Exception {
- // Test Initialization.
- byte[][] splitRows = new byte[][] { Bytes.toBytes("000"), Bytes.toBytes("002"),
- Bytes.toBytes("004"), Bytes.toBytes("006"), Bytes.toBytes("008"), Bytes.toBytes("010") };
- TEST_UTIL.createTable(tableName, FAMILY, splitRows);
- TEST_UTIL.waitUntilAllRegionsAssigned(tableName);
- try (Connection conn = getConnection(); Table table = conn.getTable(tableName)) {
- try (RegionLocator l = conn.getRegionLocator(tableName)) {
- assertEquals(splitRows.length + 1, l.getAllRegionLocations().size());
- }
- for (byte[] splitRow : splitRows) {
- Put put = new Put(splitRow);
- put.addColumn(FAMILY, QUALIFIER, VALUE);
- table.put(put);
-
- byte[] nextRow = Bytes.copy(splitRow);
- nextRow[nextRow.length - 1]++;
-
- put = new Put(nextRow);
- put.addColumn(FAMILY, QUALIFIER, VALUE);
- table.put(put);
- }
-
- // scan forward
- try (ResultScanner scanner = table.getScanner(new Scan())) {
- int count = 0;
- for (Result r : scanner) {
- assertTrue(!r.isEmpty());
- count++;
- }
- assertEquals(12, count);
- }
-
- reverseScanTest(table, ReadType.STREAM);
- reverseScanTest(table, ReadType.PREAD);
- reverseScanTest(table, ReadType.DEFAULT);
- }
- }
-
- private void reverseScanTest(Table table, ReadType readType) throws IOException {
- // scan backward
- Scan scan = new Scan();
- scan.setReversed(true);
- try (ResultScanner scanner = table.getScanner(scan)) {
- int count = 0;
- byte[] lastRow = null;
- for (Result r : scanner) {
- assertTrue(!r.isEmpty());
- count++;
- byte[] thisRow = r.getRow();
- if (lastRow != null) {
- assertTrue(Bytes.compareTo(thisRow, lastRow) < 0, "Error scan order, last row= "
- + Bytes.toString(lastRow) + ",this row=" + Bytes.toString(thisRow));
- }
- lastRow = thisRow;
- }
- assertEquals(12, count);
- }
-
- scan = new Scan();
- scan.setReadType(readType);
- scan.setReversed(true);
- scan.withStartRow(Bytes.toBytes("002"));
- try (ResultScanner scanner = table.getScanner(scan)) {
- int count = 0;
- byte[] lastRow = null;
- for (Result r : scanner) {
- assertTrue(!r.isEmpty());
- count++;
- byte[] thisRow = r.getRow();
- if (lastRow != null) {
- assertTrue(Bytes.compareTo(thisRow, lastRow) < 0, "Error scan order, last row= "
- + Bytes.toString(lastRow) + ",this row=" + Bytes.toString(thisRow));
- }
- lastRow = thisRow;
- }
- assertEquals(3, count); // 000 001 002
- }
-
- scan = new Scan();
- scan.setReadType(readType);
- scan.setReversed(true);
- scan.withStartRow(Bytes.toBytes("002"));
- scan.withStopRow(Bytes.toBytes("000"));
- try (ResultScanner scanner = table.getScanner(scan)) {
- int count = 0;
- byte[] lastRow = null;
- for (Result r : scanner) {
- assertFalse(r.isEmpty());
- count++;
- byte[] thisRow = r.getRow();
- if (lastRow != null) {
- assertTrue(Bytes.compareTo(thisRow, lastRow) < 0, "Error scan order, last row= "
- + Bytes.toString(lastRow) + ",this row=" + Bytes.toString(thisRow));
- }
- lastRow = thisRow;
- }
- assertEquals(2, count); // 001 002
- }
-
- scan = new Scan();
- scan.setReadType(readType);
- scan.setReversed(true);
- scan.withStartRow(Bytes.toBytes("001"));
- try (ResultScanner scanner = table.getScanner(scan)) {
- int count = 0;
- byte[] lastRow = null;
- for (Result r : scanner) {
- assertFalse(r.isEmpty());
- count++;
- byte[] thisRow = r.getRow();
- if (lastRow != null) {
- assertTrue(Bytes.compareTo(thisRow, lastRow) < 0, "Error scan order, last row= "
- + Bytes.toString(lastRow) + ",this row=" + Bytes.toString(thisRow));
- }
- lastRow = thisRow;
- }
- assertEquals(2, count); // 000 001
- }
-
- scan = new Scan();
- scan.setReadType(readType);
- scan.setReversed(true);
- scan.withStartRow(Bytes.toBytes("000"));
- try (ResultScanner scanner = table.getScanner(scan)) {
- int count = 0;
- byte[] lastRow = null;
- for (Result r : scanner) {
- assertFalse(r.isEmpty());
- count++;
- byte[] thisRow = r.getRow();
- if (lastRow != null) {
- assertTrue(Bytes.compareTo(thisRow, lastRow) < 0, "Error scan order, last row= "
- + Bytes.toString(lastRow) + ",this row=" + Bytes.toString(thisRow));
- }
- lastRow = thisRow;
- }
- assertEquals(1, count); // 000
- }
-
- scan = new Scan();
- scan.setReadType(readType);
- scan.setReversed(true);
- scan.withStartRow(Bytes.toBytes("006"));
- scan.withStopRow(Bytes.toBytes("002"));
- try (ResultScanner scanner = table.getScanner(scan)) {
- int count = 0;
- byte[] lastRow = null;
- for (Result r : scanner) {
- assertFalse(r.isEmpty());
- count++;
- byte[] thisRow = r.getRow();
- if (lastRow != null) {
- assertTrue(Bytes.compareTo(thisRow, lastRow) < 0, "Error scan order, last row= "
- + Bytes.toString(lastRow) + ",this row=" + Bytes.toString(thisRow));
- }
- lastRow = thisRow;
- }
- assertEquals(4, count); // 003 004 005 006
- }
- }
-
@TestTemplate
public void testFilterAllRecords() throws IOException {
Scan scan = new Scan();
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/FromClientSideTestBase.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/FromClientSideTestBase.java
index a7f9ce7e665..a347a045e0f 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/FromClientSideTestBase.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/FromClientSideTestBase.java
@@ -18,9 +18,9 @@
package org.apache.hadoop.hbase.client;
import static org.apache.hadoop.hbase.HBaseTestingUtil.countRows;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.IOException;
import java.util.Arrays;
@@ -146,7 +146,7 @@ public class FromClientSideTestBase {
ht.delete(delete);
count++;
}
- assertEquals("Did not perform correct number of deletes", 3, count);
+ assertEquals(3, count, "Did not perform correct number of deletes");
}
protected int getNumberOfRows(String keyPrefix, String value, Table ht) throws Exception {
@@ -332,47 +332,42 @@ public class FromClientSideTestBase {
}
protected void assertKey(Cell key, byte[] row, byte[] family, byte[] qualifier, byte[] value) {
- assertTrue("Expected row [" + Bytes.toString(row) + "] " + "Got row ["
- + Bytes.toString(CellUtil.cloneRow(key)) + "]", equals(row, CellUtil.cloneRow(key)));
- assertTrue(
+ assertTrue(equals(row, CellUtil.cloneRow(key)), "Expected row [" + Bytes.toString(row) + "] "
+ + "Got row [" + Bytes.toString(CellUtil.cloneRow(key)) + "]");
+ assertTrue(equals(family, CellUtil.cloneFamily(key)),
"Expected family [" + Bytes.toString(family) + "] " + "Got family ["
- + Bytes.toString(CellUtil.cloneFamily(key)) + "]",
- equals(family, CellUtil.cloneFamily(key)));
- assertTrue(
+ + Bytes.toString(CellUtil.cloneFamily(key)) + "]");
+ assertTrue(equals(qualifier, CellUtil.cloneQualifier(key)),
"Expected qualifier [" + Bytes.toString(qualifier) + "] " + "Got qualifier ["
- + Bytes.toString(CellUtil.cloneQualifier(key)) + "]",
- equals(qualifier, CellUtil.cloneQualifier(key)));
- assertTrue("Expected value [" + Bytes.toString(value) + "] " + "Got value ["
- + Bytes.toString(CellUtil.cloneValue(key)) + "]", equals(value, CellUtil.cloneValue(key)));
+ + Bytes.toString(CellUtil.cloneQualifier(key)) + "]");
+ assertTrue(equals(value, CellUtil.cloneValue(key)), "Expected value [" + Bytes.toString(value)
+ + "] " + "Got value [" + Bytes.toString(CellUtil.cloneValue(key)) + "]");
}
static void assertIncrementKey(Cell key, byte[] row, byte[] family, byte[] qualifier,
long value) {
- assertTrue("Expected row [" + Bytes.toString(row) + "] " + "Got row ["
- + Bytes.toString(CellUtil.cloneRow(key)) + "]", equals(row, CellUtil.cloneRow(key)));
- assertTrue(
+ assertTrue(equals(row, CellUtil.cloneRow(key)), "Expected row [" + Bytes.toString(row) + "] "
+ + "Got row [" + Bytes.toString(CellUtil.cloneRow(key)) + "]");
+ assertTrue(equals(family, CellUtil.cloneFamily(key)),
"Expected family [" + Bytes.toString(family) + "] " + "Got family ["
- + Bytes.toString(CellUtil.cloneFamily(key)) + "]",
- equals(family, CellUtil.cloneFamily(key)));
- assertTrue(
+ + Bytes.toString(CellUtil.cloneFamily(key)) + "]");
+ assertTrue(equals(qualifier, CellUtil.cloneQualifier(key)),
"Expected qualifier [" + Bytes.toString(qualifier) + "] " + "Got qualifier ["
- + Bytes.toString(CellUtil.cloneQualifier(key)) + "]",
- equals(qualifier, CellUtil.cloneQualifier(key)));
- assertEquals("Expected value [" + value + "] " + "Got value ["
- + Bytes.toLong(CellUtil.cloneValue(key)) + "]", Bytes.toLong(CellUtil.cloneValue(key)),
- value);
+ + Bytes.toString(CellUtil.cloneQualifier(key)) + "]");
+ assertEquals(Bytes.toLong(CellUtil.cloneValue(key)), value, "Expected value [" + value + "] "
+ + "Got value [" + Bytes.toLong(CellUtil.cloneValue(key)) + "]");
}
protected void assertNumKeys(Result result, int n) throws Exception {
- assertEquals("Expected " + n + " keys but got " + result.size(), result.size(), n);
+ assertEquals(result.size(), n, "Expected " + n + " keys but got " + result.size());
}
protected void assertNResult(Result result, byte[] row, byte[][] families, byte[][] qualifiers,
byte[][] values, int[][] idxs) {
- assertTrue("Expected row [" + Bytes.toString(row) + "] " + "Got row ["
- + Bytes.toString(result.getRow()) + "]", equals(row, result.getRow()));
- assertEquals("Expected " + idxs.length + " keys but result contains " + result.size(),
- result.size(), idxs.length);
+ assertTrue(equals(row, result.getRow()), "Expected row [" + Bytes.toString(row) + "] "
+ + "Got row [" + Bytes.toString(result.getRow()) + "]");
+ assertEquals(result.size(), idxs.length,
+ "Expected " + idxs.length + " keys but result contains " + result.size());
Cell[] keys = result.rawCells();
@@ -385,19 +380,19 @@ public class FromClientSideTestBase {
byte[] famb = CellUtil.cloneFamily(key);
byte[] qualb = CellUtil.cloneQualifier(key);
byte[] valb = CellUtil.cloneValue(key);
- assertTrue("(" + i + ") Expected family [" + Bytes.toString(family) + "] " + "Got family ["
- + Bytes.toString(famb) + "]", equals(family, famb));
- assertTrue("(" + i + ") Expected qualifier [" + Bytes.toString(qualifier) + "] "
- + "Got qualifier [" + Bytes.toString(qualb) + "]", equals(qualifier, qualb));
- assertTrue("(" + i + ") Expected value [" + Bytes.toString(value) + "] " + "Got value ["
- + Bytes.toString(valb) + "]", equals(value, valb));
+ assertTrue(equals(family, famb), "(" + i + ") Expected family [" + Bytes.toString(family)
+ + "] " + "Got family [" + Bytes.toString(famb) + "]");
+ assertTrue(equals(qualifier, qualb), "(" + i + ") Expected qualifier ["
+ + Bytes.toString(qualifier) + "] " + "Got qualifier [" + Bytes.toString(qualb) + "]");
+ assertTrue(equals(value, valb), "(" + i + ") Expected value [" + Bytes.toString(value) + "] "
+ + "Got value [" + Bytes.toString(valb) + "]");
}
}
protected void assertNResult(Result result, byte[] row, byte[] family, byte[] qualifier,
long[] stamps, byte[][] values, int start, int end) {
- assertTrue("Expected row [" + Bytes.toString(row) + "] " + "Got row ["
- + Bytes.toString(result.getRow()) + "]", equals(row, result.getRow()));
+ assertTrue(equals(row, result.getRow()), "Expected row [" + Bytes.toString(row) + "] "
+ + "Got row [" + Bytes.toString(result.getRow()) + "]");
int expectedResults = end - start + 1;
assertEquals(expectedResults, result.size());
@@ -408,16 +403,17 @@ public class FromClientSideTestBase {
long ts = stamps[end - i];
Cell key = keys[i];
- assertTrue("(" + i + ") Expected family [" + Bytes.toString(family) + "] " + "Got family ["
- + Bytes.toString(CellUtil.cloneFamily(key)) + "]", CellUtil.matchingFamily(key, family));
- assertTrue(
+ assertTrue(CellUtil.matchingFamily(key, family),
+ "(" + i + ") Expected family [" + Bytes.toString(family) + "] " + "Got family ["
+ + Bytes.toString(CellUtil.cloneFamily(key)) + "]");
+ assertTrue(CellUtil.matchingQualifier(key, qualifier),
"(" + i + ") Expected qualifier [" + Bytes.toString(qualifier) + "] " + "Got qualifier ["
- + Bytes.toString(CellUtil.cloneQualifier(key)) + "]",
- CellUtil.matchingQualifier(key, qualifier));
- assertEquals("Expected ts [" + ts + "] " + "Got ts [" + key.getTimestamp() + "]", ts,
- key.getTimestamp());
- assertTrue("(" + i + ") Expected value [" + Bytes.toString(value) + "] " + "Got value ["
- + Bytes.toString(CellUtil.cloneValue(key)) + "]", CellUtil.matchingValue(key, value));
+ + Bytes.toString(CellUtil.cloneQualifier(key)) + "]");
+ assertEquals(ts, key.getTimestamp(),
+ "Expected ts [" + ts + "] " + "Got ts [" + key.getTimestamp() + "]");
+ assertTrue(CellUtil.matchingValue(key, value),
+ "(" + i + ") Expected value [" + Bytes.toString(value) + "] " + "Got value ["
+ + Bytes.toString(CellUtil.cloneValue(key)) + "]");
}
}
@@ -427,91 +423,89 @@ public class FromClientSideTestBase {
*/
protected void assertDoubleResult(Result result, byte[] row, byte[] familyA, byte[] qualifierA,
byte[] valueA, byte[] familyB, byte[] qualifierB, byte[] valueB) {
- assertTrue("Expected row [" + Bytes.toString(row) + "] " + "Got row ["
- + Bytes.toString(result.getRow()) + "]", equals(row, result.getRow()));
- assertEquals("Expected two keys but result contains " + result.size(), 2, result.size());
+ assertTrue(equals(row, result.getRow()), "Expected row [" + Bytes.toString(row) + "] "
+ + "Got row [" + Bytes.toString(result.getRow()) + "]");
+ assertEquals(2, result.size(), "Expected two keys but result contains " + result.size());
Cell[] kv = result.rawCells();
Cell kvA = kv[0];
- assertTrue(
+ assertTrue(equals(familyA, CellUtil.cloneFamily(kvA)),
"(A) Expected family [" + Bytes.toString(familyA) + "] " + "Got family ["
- + Bytes.toString(CellUtil.cloneFamily(kvA)) + "]",
- equals(familyA, CellUtil.cloneFamily(kvA)));
- assertTrue(
+ + Bytes.toString(CellUtil.cloneFamily(kvA)) + "]");
+ assertTrue(equals(qualifierA, CellUtil.cloneQualifier(kvA)),
"(A) Expected qualifier [" + Bytes.toString(qualifierA) + "] " + "Got qualifier ["
- + Bytes.toString(CellUtil.cloneQualifier(kvA)) + "]",
- equals(qualifierA, CellUtil.cloneQualifier(kvA)));
- assertTrue("(A) Expected value [" + Bytes.toString(valueA) + "] " + "Got value ["
- + Bytes.toString(CellUtil.cloneValue(kvA)) + "]", equals(valueA, CellUtil.cloneValue(kvA)));
+ + Bytes.toString(CellUtil.cloneQualifier(kvA)) + "]");
+ assertTrue(equals(valueA, CellUtil.cloneValue(kvA)),
+ "(A) Expected value [" + Bytes.toString(valueA) + "] " + "Got value ["
+ + Bytes.toString(CellUtil.cloneValue(kvA)) + "]");
Cell kvB = kv[1];
- assertTrue(
+ assertTrue(equals(familyB, CellUtil.cloneFamily(kvB)),
"(B) Expected family [" + Bytes.toString(familyB) + "] " + "Got family ["
- + Bytes.toString(CellUtil.cloneFamily(kvB)) + "]",
- equals(familyB, CellUtil.cloneFamily(kvB)));
- assertTrue(
+ + Bytes.toString(CellUtil.cloneFamily(kvB)) + "]");
+ assertTrue(equals(qualifierB, CellUtil.cloneQualifier(kvB)),
"(B) Expected qualifier [" + Bytes.toString(qualifierB) + "] " + "Got qualifier ["
- + Bytes.toString(CellUtil.cloneQualifier(kvB)) + "]",
- equals(qualifierB, CellUtil.cloneQualifier(kvB)));
- assertTrue("(B) Expected value [" + Bytes.toString(valueB) + "] " + "Got value ["
- + Bytes.toString(CellUtil.cloneValue(kvB)) + "]", equals(valueB, CellUtil.cloneValue(kvB)));
+ + Bytes.toString(CellUtil.cloneQualifier(kvB)) + "]");
+ assertTrue(equals(valueB, CellUtil.cloneValue(kvB)),
+ "(B) Expected value [" + Bytes.toString(valueB) + "] " + "Got value ["
+ + Bytes.toString(CellUtil.cloneValue(kvB)) + "]");
}
protected void assertSingleResult(Result result, byte[] row, byte[] family, byte[] qualifier,
byte[] value) {
- assertTrue("Expected row [" + Bytes.toString(row) + "] " + "Got row ["
- + Bytes.toString(result.getRow()) + "]", equals(row, result.getRow()));
- assertEquals("Expected a single key but result contains " + result.size(), 1, result.size());
+ assertTrue(equals(row, result.getRow()), "Expected row [" + Bytes.toString(row) + "] "
+ + "Got row [" + Bytes.toString(result.getRow()) + "]");
+ assertEquals(1, result.size(), "Expected a single key but result contains " + result.size());
Cell kv = result.rawCells()[0];
- assertTrue("Expected family [" + Bytes.toString(family) + "] " + "Got family ["
- + Bytes.toString(CellUtil.cloneFamily(kv)) + "]", equals(family, CellUtil.cloneFamily(kv)));
- assertTrue(
+ assertTrue(equals(family, CellUtil.cloneFamily(kv)),
+ "Expected family [" + Bytes.toString(family) + "] " + "Got family ["
+ + Bytes.toString(CellUtil.cloneFamily(kv)) + "]");
+ assertTrue(equals(qualifier, CellUtil.cloneQualifier(kv)),
"Expected qualifier [" + Bytes.toString(qualifier) + "] " + "Got qualifier ["
- + Bytes.toString(CellUtil.cloneQualifier(kv)) + "]",
- equals(qualifier, CellUtil.cloneQualifier(kv)));
- assertTrue("Expected value [" + Bytes.toString(value) + "] " + "Got value ["
- + Bytes.toString(CellUtil.cloneValue(kv)) + "]", equals(value, CellUtil.cloneValue(kv)));
+ + Bytes.toString(CellUtil.cloneQualifier(kv)) + "]");
+ assertTrue(equals(value, CellUtil.cloneValue(kv)), "Expected value [" + Bytes.toString(value)
+ + "] " + "Got value [" + Bytes.toString(CellUtil.cloneValue(kv)) + "]");
}
protected void assertSingleResult(Result result, byte[] row, byte[] family, byte[] qualifier,
long value) {
- assertTrue("Expected row [" + Bytes.toString(row) + "] " + "Got row ["
- + Bytes.toString(result.getRow()) + "]", equals(row, result.getRow()));
- assertEquals("Expected a single key but result contains " + result.size(), 1, result.size());
+ assertTrue(equals(row, result.getRow()), "Expected row [" + Bytes.toString(row) + "] "
+ + "Got row [" + Bytes.toString(result.getRow()) + "]");
+ assertEquals(1, result.size(), "Expected a single key but result contains " + result.size());
Cell kv = result.rawCells()[0];
- assertTrue("Expected family [" + Bytes.toString(family) + "] " + "Got family ["
- + Bytes.toString(CellUtil.cloneFamily(kv)) + "]", equals(family, CellUtil.cloneFamily(kv)));
- assertTrue(
+ assertTrue(equals(family, CellUtil.cloneFamily(kv)),
+ "Expected family [" + Bytes.toString(family) + "] " + "Got family ["
+ + Bytes.toString(CellUtil.cloneFamily(kv)) + "]");
+ assertTrue(equals(qualifier, CellUtil.cloneQualifier(kv)),
"Expected qualifier [" + Bytes.toString(qualifier) + "] " + "Got qualifier ["
- + Bytes.toString(CellUtil.cloneQualifier(kv)) + "]",
- equals(qualifier, CellUtil.cloneQualifier(kv)));
- assertEquals("Expected value [" + value + "] " + "Got value ["
- + Bytes.toLong(CellUtil.cloneValue(kv)) + "]", value, Bytes.toLong(CellUtil.cloneValue(kv)));
+ + Bytes.toString(CellUtil.cloneQualifier(kv)) + "]");
+ assertEquals(value, Bytes.toLong(CellUtil.cloneValue(kv)), "Expected value [" + value + "] "
+ + "Got value [" + Bytes.toLong(CellUtil.cloneValue(kv)) + "]");
}
protected void assertSingleResult(Result result, byte[] row, byte[] family, byte[] qualifier,
long ts, byte[] value) {
- assertTrue("Expected row [" + Bytes.toString(row) + "] " + "Got row ["
- + Bytes.toString(result.getRow()) + "]", equals(row, result.getRow()));
- assertEquals("Expected a single key but result contains " + result.size(), 1, result.size());
+ assertTrue(equals(row, result.getRow()), "Expected row [" + Bytes.toString(row) + "] "
+ + "Got row [" + Bytes.toString(result.getRow()) + "]");
+ assertEquals(1, result.size(), "Expected a single key but result contains " + result.size());
Cell kv = result.rawCells()[0];
- assertTrue("Expected family [" + Bytes.toString(family) + "] " + "Got family ["
- + Bytes.toString(CellUtil.cloneFamily(kv)) + "]", equals(family, CellUtil.cloneFamily(kv)));
- assertTrue(
+ assertTrue(equals(family, CellUtil.cloneFamily(kv)),
+ "Expected family [" + Bytes.toString(family) + "] " + "Got family ["
+ + Bytes.toString(CellUtil.cloneFamily(kv)) + "]");
+ assertTrue(equals(qualifier, CellUtil.cloneQualifier(kv)),
"Expected qualifier [" + Bytes.toString(qualifier) + "] " + "Got qualifier ["
- + Bytes.toString(CellUtil.cloneQualifier(kv)) + "]",
- equals(qualifier, CellUtil.cloneQualifier(kv)));
- assertEquals("Expected ts [" + ts + "] " + "Got ts [" + kv.getTimestamp() + "]", ts,
- kv.getTimestamp());
- assertTrue("Expected value [" + Bytes.toString(value) + "] " + "Got value ["
- + Bytes.toString(CellUtil.cloneValue(kv)) + "]", equals(value, CellUtil.cloneValue(kv)));
+ + Bytes.toString(CellUtil.cloneQualifier(kv)) + "]");
+ assertEquals(ts, kv.getTimestamp(),
+ "Expected ts [" + ts + "] " + "Got ts [" + kv.getTimestamp() + "]");
+ assertTrue(equals(value, CellUtil.cloneValue(kv)), "Expected value [" + Bytes.toString(value)
+ + "] " + "Got value [" + Bytes.toString(CellUtil.cloneValue(kv)) + "]");
}
protected void assertEmptyResult(Result result) throws Exception {
- assertTrue("expected an empty result but result contains " + result.size() + " keys",
- result.isEmpty());
+ assertTrue(result.isEmpty(),
+ "expected an empty result but result contains " + result.size() + " keys");
}
protected void assertNullResult(Result result) throws Exception {
- assertNull("expected null result but received a non-null result", result);
+ assertNull(result, "expected null result but received a non-null result");
}
protected void getVersionRangeAndVerifyGreaterThan(Table ht, byte[] row, byte[] family,
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/FromClientSideTestCheckAndMutate.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/FromClientSideTestCheckAndMutate.java
new file mode 100644
index 00000000000..8e0e0e3df30
--- /dev/null
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/FromClientSideTestCheckAndMutate.java
@@ -0,0 +1,337 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hbase.client;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+
+import java.io.IOException;
+import org.apache.hadoop.hbase.CompareOperator;
+import org.apache.hadoop.hbase.io.TimeRange;
+import org.apache.hadoop.hbase.util.Bytes;
+import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
+import org.junit.jupiter.api.TestTemplate;
+
+@SuppressWarnings("deprecation")
+public class FromClientSideTestCheckAndMutate extends FromClientSideTestBase {
+
+ protected FromClientSideTestCheckAndMutate(Class<? extends ConnectionRegistry> registryImpl,
+ int numHedgedReqs) {
+ super(registryImpl, numHedgedReqs);
+ }
+
+ @TestTemplate
+ public void testCheckAndPut() throws IOException {
+ final byte[] anotherrow = Bytes.toBytes("anotherrow");
+ final byte[] value2 = Bytes.toBytes("abcd");
+ TEST_UTIL.createTable(tableName, FAMILY);
+ try (Connection conn = getConnection(); Table table = conn.getTable(tableName)) {
+ Put put1 = new Put(ROW);
+ put1.addColumn(FAMILY, QUALIFIER, VALUE);
+
+ // row doesn't exist, so using non-null value should be considered "not match".
+ boolean ok =
+ table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER).ifEquals(VALUE).thenPut(put1);
+ assertFalse(ok);
+
+ // row doesn't exist, so using "ifNotExists" should be considered "match".
+ ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER).ifNotExists().thenPut(put1);
+ assertTrue(ok);
+
+ // row now exists, so using "ifNotExists" should be considered "not match".
+ ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER).ifNotExists().thenPut(put1);
+ assertFalse(ok);
+
+ Put put2 = new Put(ROW);
+ put2.addColumn(FAMILY, QUALIFIER, value2);
+
+ // row now exists, use the matching value to check
+ ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER).ifEquals(VALUE).thenPut(put2);
+ assertTrue(ok);
+
+ Put put3 = new Put(anotherrow);
+ put3.addColumn(FAMILY, QUALIFIER, VALUE);
+
+ // try to do CheckAndPut on different rows
+ try {
+ table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER).ifEquals(value2).thenPut(put3);
+ fail("trying to check and modify different rows should have failed.");
+ } catch (Exception ignored) {
+ }
+ }
+ }
+
+ @TestTemplate
+ public void testCheckAndMutateWithTimeRange() throws IOException {
+ TEST_UTIL.createTable(tableName, FAMILY);
+ try (Connection conn = getConnection(); Table table = conn.getTable(tableName)) {
+ final long ts = EnvironmentEdgeManager.currentTime() / 2;
+ Put put = new Put(ROW);
+ put.addColumn(FAMILY, QUALIFIER, ts, VALUE);
+
+ boolean ok =
+ table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER).ifNotExists().thenPut(put);
+ assertTrue(ok);
+
+ ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
+ .timeRange(TimeRange.at(ts + 10000)).ifEquals(VALUE).thenPut(put);
+ assertFalse(ok);
+
+ ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
+ .timeRange(TimeRange.from(ts + 10000)).ifEquals(VALUE).thenPut(put);
+ assertFalse(ok);
+
+ ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
+ .timeRange(TimeRange.between(ts + 10000, ts + 20000)).ifEquals(VALUE).thenPut(put);
+ assertFalse(ok);
+
+ ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER).timeRange(TimeRange.until(ts))
+ .ifEquals(VALUE).thenPut(put);
+ assertFalse(ok);
+
+ ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER).timeRange(TimeRange.at(ts))
+ .ifEquals(VALUE).thenPut(put);
+ assertTrue(ok);
+
+ ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER).timeRange(TimeRange.from(ts))
+ .ifEquals(VALUE).thenPut(put);
+ assertTrue(ok);
+
+ ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
+ .timeRange(TimeRange.between(ts, ts + 20000)).ifEquals(VALUE).thenPut(put);
+ assertTrue(ok);
+
+ ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
+ .timeRange(TimeRange.until(ts + 10000)).ifEquals(VALUE).thenPut(put);
+ assertTrue(ok);
+
+ RowMutations rm = new RowMutations(ROW).add((Mutation) put);
+ ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
+ .timeRange(TimeRange.at(ts + 10000)).ifEquals(VALUE).thenMutate(rm);
+ assertFalse(ok);
+
+ ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER).timeRange(TimeRange.at(ts))
+ .ifEquals(VALUE).thenMutate(rm);
+ assertTrue(ok);
+
+ Delete delete = new Delete(ROW).addColumn(FAMILY, QUALIFIER);
+
+ ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
+ .timeRange(TimeRange.at(ts + 10000)).ifEquals(VALUE).thenDelete(delete);
+ assertFalse(ok);
+
+ ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER).timeRange(TimeRange.at(ts))
+ .ifEquals(VALUE).thenDelete(delete);
+ assertTrue(ok);
+ }
+ }
+
+ @TestTemplate
+ public void testCheckAndPutWithCompareOp() throws IOException {
+ final byte[] value1 = Bytes.toBytes("aaaa");
+ final byte[] value2 = Bytes.toBytes("bbbb");
+ final byte[] value3 = Bytes.toBytes("cccc");
+ final byte[] value4 = Bytes.toBytes("dddd");
+ TEST_UTIL.createTable(tableName, FAMILY);
+ try (Connection conn = getConnection(); Table table = conn.getTable(tableName)) {
+ Put put2 = new Put(ROW);
+ put2.addColumn(FAMILY, QUALIFIER, value2);
+
+ Put put3 = new Put(ROW);
+ put3.addColumn(FAMILY, QUALIFIER, value3);
+
+ // row doesn't exist, so using "ifNotExists" should be considered "match".
+ boolean ok =
+ table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER).ifNotExists().thenPut(put2);
+ assertTrue(ok);
+
+ // cell = "bbbb", using "aaaa" to compare only LESS/LESS_OR_EQUAL/NOT_EQUAL
+ // turns out "match"
+ ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
+ .ifMatches(CompareOperator.GREATER, value1).thenPut(put2);
+ assertFalse(ok);
+ ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
+ .ifMatches(CompareOperator.EQUAL, value1).thenPut(put2);
+ assertFalse(ok);
+ ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
+ .ifMatches(CompareOperator.GREATER_OR_EQUAL, value1).thenPut(put2);
+ assertFalse(ok);
+ ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
+ .ifMatches(CompareOperator.LESS, value1).thenPut(put2);
+ assertTrue(ok);
+ ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
+ .ifMatches(CompareOperator.LESS_OR_EQUAL, value1).thenPut(put2);
+ assertTrue(ok);
+ ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
+ .ifMatches(CompareOperator.NOT_EQUAL, value1).thenPut(put3);
+ assertTrue(ok);
+
+ // cell = "cccc", using "dddd" to compare only LARGER/LARGER_OR_EQUAL/NOT_EQUAL
+ // turns out "match"
+ ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
+ .ifMatches(CompareOperator.LESS, value4).thenPut(put3);
+ assertFalse(ok);
+ ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
+ .ifMatches(CompareOperator.LESS_OR_EQUAL, value4).thenPut(put3);
+ assertFalse(ok);
+ ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
+ .ifMatches(CompareOperator.EQUAL, value4).thenPut(put3);
+ assertFalse(ok);
+ ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
+ .ifMatches(CompareOperator.GREATER, value4).thenPut(put3);
+ assertTrue(ok);
+ ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
+ .ifMatches(CompareOperator.GREATER_OR_EQUAL, value4).thenPut(put3);
+ assertTrue(ok);
+ ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
+ .ifMatches(CompareOperator.NOT_EQUAL, value4).thenPut(put2);
+ assertTrue(ok);
+
+ // cell = "bbbb", using "bbbb" to compare only GREATER_OR_EQUAL/LESS_OR_EQUAL/EQUAL
+ // turns out "match"
+ ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
+ .ifMatches(CompareOperator.GREATER, value2).thenPut(put2);
+ assertFalse(ok);
+ ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
+ .ifMatches(CompareOperator.NOT_EQUAL, value2).thenPut(put2);
+ assertFalse(ok);
+ ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
+ .ifMatches(CompareOperator.LESS, value2).thenPut(put2);
+ assertFalse(ok);
+ ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
+ .ifMatches(CompareOperator.GREATER_OR_EQUAL, value2).thenPut(put2);
+ assertTrue(ok);
+ ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
+ .ifMatches(CompareOperator.LESS_OR_EQUAL, value2).thenPut(put2);
+ assertTrue(ok);
+ ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
+ .ifMatches(CompareOperator.EQUAL, value2).thenPut(put3);
+ assertTrue(ok);
+ }
+ }
+
+ @TestTemplate
+ public void testCheckAndDelete() throws IOException {
+ final byte[] value1 = Bytes.toBytes("aaaa");
+ TEST_UTIL.createTable(tableName, FAMILY);
+ try (Connection conn = getConnection(); Table table = conn.getTable(tableName)) {
+ Put put = new Put(ROW);
+ put.addColumn(FAMILY, QUALIFIER, value1);
+ table.put(put);
+
+ Delete delete = new Delete(ROW);
+ delete.addColumns(FAMILY, QUALIFIER);
+
+ boolean ok =
+ table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER).ifEquals(value1).thenDelete(delete);
+ assertTrue(ok);
+ }
+ }
+
+ @TestTemplate
+ public void testCheckAndDeleteWithCompareOp() throws IOException {
+ final byte[] value1 = Bytes.toBytes("aaaa");
+ final byte[] value2 = Bytes.toBytes("bbbb");
+ final byte[] value3 = Bytes.toBytes("cccc");
+ final byte[] value4 = Bytes.toBytes("dddd");
+ TEST_UTIL.createTable(tableName, FAMILY);
+ try (Connection conn = getConnection(); Table table = conn.getTable(tableName)) {
+ Put put2 = new Put(ROW);
+ put2.addColumn(FAMILY, QUALIFIER, value2);
+ table.put(put2);
+
+ Put put3 = new Put(ROW);
+ put3.addColumn(FAMILY, QUALIFIER, value3);
+
+ Delete delete = new Delete(ROW);
+ delete.addColumns(FAMILY, QUALIFIER);
+
+ // cell = "bbbb", using "aaaa" to compare only LESS/LESS_OR_EQUAL/NOT_EQUAL
+ // turns out "match"
+ boolean ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
+ .ifMatches(CompareOperator.GREATER, value1).thenDelete(delete);
+ assertFalse(ok);
+ ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
+ .ifMatches(CompareOperator.EQUAL, value1).thenDelete(delete);
+ assertFalse(ok);
+ ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
+ .ifMatches(CompareOperator.GREATER_OR_EQUAL, value1).thenDelete(delete);
+ assertFalse(ok);
+ ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
+ .ifMatches(CompareOperator.LESS, value1).thenDelete(delete);
+ assertTrue(ok);
+ table.put(put2);
+ ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
+ .ifMatches(CompareOperator.LESS_OR_EQUAL, value1).thenDelete(delete);
+ assertTrue(ok);
+ table.put(put2);
+ ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
+ .ifMatches(CompareOperator.NOT_EQUAL, value1).thenDelete(delete);
+ assertTrue(ok);
+
+ // cell = "cccc", using "dddd" to compare only LARGER/LARGER_OR_EQUAL/NOT_EQUAL
+ // turns out "match"
+ table.put(put3);
+ ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
+ .ifMatches(CompareOperator.LESS, value4).thenDelete(delete);
+ assertFalse(ok);
+ ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
+ .ifMatches(CompareOperator.LESS_OR_EQUAL, value4).thenDelete(delete);
+ assertFalse(ok);
+ ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
+ .ifMatches(CompareOperator.EQUAL, value4).thenDelete(delete);
+ assertFalse(ok);
+ ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
+ .ifMatches(CompareOperator.GREATER, value4).thenDelete(delete);
+ assertTrue(ok);
+ table.put(put3);
+ ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
+ .ifMatches(CompareOperator.GREATER_OR_EQUAL, value4).thenDelete(delete);
+ assertTrue(ok);
+ table.put(put3);
+ ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
+ .ifMatches(CompareOperator.NOT_EQUAL, value4).thenDelete(delete);
+ assertTrue(ok);
+
+ // cell = "bbbb", using "bbbb" to compare only GREATER_OR_EQUAL/LESS_OR_EQUAL/EQUAL
+ // turns out "match"
+ table.put(put2);
+ ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
+ .ifMatches(CompareOperator.GREATER, value2).thenDelete(delete);
+ assertFalse(ok);
+ ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
+ .ifMatches(CompareOperator.NOT_EQUAL, value2).thenDelete(delete);
+ assertFalse(ok);
+ ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
+ .ifMatches(CompareOperator.LESS, value2).thenDelete(delete);
+ assertFalse(ok);
+ ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
+ .ifMatches(CompareOperator.GREATER_OR_EQUAL, value2).thenDelete(delete);
+ assertTrue(ok);
+ table.put(put2);
+ ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
+ .ifMatches(CompareOperator.LESS_OR_EQUAL, value2).thenDelete(delete);
+ assertTrue(ok);
+ table.put(put2);
+ ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER)
+ .ifMatches(CompareOperator.EQUAL, value2).thenDelete(delete);
+ assertTrue(ok);
+ }
+ }
+}
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/FromClientSideTestMultiRowMutation.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/FromClientSideTestMultiRowMutation.java
new file mode 100644
index 00000000000..e05e7e40bfb
--- /dev/null
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/FromClientSideTestMultiRowMutation.java
@@ -0,0 +1,385 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hbase.client;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.util.Arrays;
+import org.apache.hadoop.hbase.CompareOperator;
+import org.apache.hadoop.hbase.filter.FilterList;
+import org.apache.hadoop.hbase.filter.SingleColumnValueFilter;
+import org.apache.hadoop.hbase.ipc.CoprocessorRpcChannel;
+import org.apache.hadoop.hbase.util.Bytes;
+import org.junit.jupiter.api.TestTemplate;
+
+import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;
+import org.apache.hadoop.hbase.shaded.protobuf.generated.ClientProtos.MutationProto;
+import org.apache.hadoop.hbase.shaded.protobuf.generated.ClientProtos.MutationProto.MutationType;
+import org.apache.hadoop.hbase.shaded.protobuf.generated.MultiRowMutationProtos.MultiRowMutationService;
+import org.apache.hadoop.hbase.shaded.protobuf.generated.MultiRowMutationProtos.MutateRowsRequest;
+import org.apache.hadoop.hbase.shaded.protobuf.generated.MultiRowMutationProtos.MutateRowsResponse;
+
+public class FromClientSideTestMultiRowMutation extends FromClientSideTestBase {
+
+ protected FromClientSideTestMultiRowMutation(Class<? extends ConnectionRegistry> registryImpl,
+ int numHedgedReqs) {
+ super(registryImpl, numHedgedReqs);
+ }
+
+ @TestTemplate
+ public void testMultiRowMutation() throws Exception {
+ final byte[] ROW1 = Bytes.toBytes("testRow1");
+ final byte[] ROW2 = Bytes.toBytes("testRow2");
+ final byte[] ROW3 = Bytes.toBytes("testRow3");
+ TEST_UTIL.createTable(tableName, FAMILY);
+ try (Connection conn = getConnection(); Table t = conn.getTable(tableName)) {
+ // Add initial data
+ t.batch(Arrays.asList(new Put(ROW1).addColumn(FAMILY, QUALIFIER, VALUE),
+ new Put(ROW2).addColumn(FAMILY, QUALIFIER, Bytes.toBytes(1L)),
+ new Put(ROW3).addColumn(FAMILY, QUALIFIER, VALUE)), new Object[3]);
+
+ // Execute MultiRowMutation
+ Put put = new Put(ROW).addColumn(FAMILY, QUALIFIER, VALUE);
+ MutationProto m1 = ProtobufUtil.toMutation(MutationType.PUT, put);
+
+ Delete delete = new Delete(ROW1);
+ MutationProto m2 = ProtobufUtil.toMutation(MutationType.DELETE, delete);
+
+ Increment increment = new Increment(ROW2).addColumn(FAMILY, QUALIFIER, 1L);
+ MutationProto m3 = ProtobufUtil.toMutation(MutationType.INCREMENT, increment);
+
+ Append append = new Append(ROW3).addColumn(FAMILY, QUALIFIER, VALUE);
+ MutationProto m4 = ProtobufUtil.toMutation(MutationType.APPEND, append);
+
+ MutateRowsRequest.Builder mrmBuilder = MutateRowsRequest.newBuilder();
+ mrmBuilder.addMutationRequest(m1);
+ mrmBuilder.addMutationRequest(m2);
+ mrmBuilder.addMutationRequest(m3);
+ mrmBuilder.addMutationRequest(m4);
+
+ CoprocessorRpcChannel channel = t.coprocessorService(ROW);
+ MultiRowMutationService.BlockingInterface service =
+ MultiRowMutationService.newBlockingStub(channel);
+ MutateRowsResponse response = service.mutateRows(null, mrmBuilder.build());
+
+ // Assert
+ assertTrue(response.getProcessed());
+
+ Result r = t.get(new Get(ROW));
+ assertEquals(Bytes.toString(VALUE), Bytes.toString(r.getValue(FAMILY, QUALIFIER)));
+
+ r = t.get(new Get(ROW1));
+ assertTrue(r.isEmpty());
+
+ r = t.get(new Get(ROW2));
+ assertEquals(2L, Bytes.toLong(r.getValue(FAMILY, QUALIFIER)));
+
+ r = t.get(new Get(ROW3));
+ assertEquals(Bytes.toString(VALUE) + Bytes.toString(VALUE),
+ Bytes.toString(r.getValue(FAMILY, QUALIFIER)));
+ }
+ }
+
+ @TestTemplate
+ public void testMultiRowMutationWithSingleConditionWhenConditionMatches() throws Exception {
+ final byte[] ROW1 = Bytes.toBytes("testRow1");
+ final byte[] ROW2 = Bytes.toBytes("testRow2");
+ final byte[] VALUE1 = Bytes.toBytes("testValue1");
+ final byte[] VALUE2 = Bytes.toBytes("testValue2");
+ TEST_UTIL.createTable(tableName, FAMILY);
+ try (Connection conn = getConnection(); Table t = conn.getTable(tableName)) {
+ // Add initial data
+ t.put(new Put(ROW2).addColumn(FAMILY, QUALIFIER, VALUE2));
+
+ // Execute MultiRowMutation with conditions
+ Put put1 = new Put(ROW).addColumn(FAMILY, QUALIFIER, VALUE);
+ MutationProto m1 = ProtobufUtil.toMutation(MutationType.PUT, put1);
+ Put put2 = new Put(ROW1).addColumn(FAMILY, QUALIFIER, VALUE1);
+ MutationProto m2 = ProtobufUtil.toMutation(MutationType.PUT, put2);
+ Delete delete = new Delete(ROW2);
+ MutationProto m3 = ProtobufUtil.toMutation(MutationType.DELETE, delete);
+
+ MutateRowsRequest.Builder mrmBuilder = MutateRowsRequest.newBuilder();
+ mrmBuilder.addMutationRequest(m1);
+ mrmBuilder.addMutationRequest(m2);
+ mrmBuilder.addMutationRequest(m3);
+ mrmBuilder.addCondition(
+ ProtobufUtil.toCondition(ROW2, FAMILY, QUALIFIER, CompareOperator.EQUAL, VALUE2, null));
+
+ CoprocessorRpcChannel channel = t.coprocessorService(ROW);
+ MultiRowMutationService.BlockingInterface service =
+ MultiRowMutationService.newBlockingStub(channel);
+ MutateRowsResponse response = service.mutateRows(null, mrmBuilder.build());
+
+ // Assert
+ assertTrue(response.getProcessed());
+
+ Result r = t.get(new Get(ROW));
+ assertEquals(Bytes.toString(VALUE), Bytes.toString(r.getValue(FAMILY, QUALIFIER)));
+
+ r = t.get(new Get(ROW1));
+ assertEquals(Bytes.toString(VALUE1), Bytes.toString(r.getValue(FAMILY, QUALIFIER)));
+
+ r = t.get(new Get(ROW2));
+ assertTrue(r.isEmpty());
+ }
+ }
+
+ @TestTemplate
+ public void testMultiRowMutationWithSingleConditionWhenConditionNotMatch() throws Exception {
+ final byte[] ROW1 = Bytes.toBytes("testRow1");
+ final byte[] ROW2 = Bytes.toBytes("testRow2");
+ final byte[] VALUE1 = Bytes.toBytes("testValue1");
+ final byte[] VALUE2 = Bytes.toBytes("testValue2");
+ TEST_UTIL.createTable(tableName, FAMILY);
+ try (Connection conn = getConnection(); Table t = conn.getTable(tableName)) {
+ // Add initial data
+ t.put(new Put(ROW2).addColumn(FAMILY, QUALIFIER, VALUE2));
+
+ // Execute MultiRowMutation with conditions
+ Put put1 = new Put(ROW).addColumn(FAMILY, QUALIFIER, VALUE);
+ MutationProto m1 = ProtobufUtil.toMutation(MutationType.PUT, put1);
+ Put put2 = new Put(ROW1).addColumn(FAMILY, QUALIFIER, VALUE1);
+ MutationProto m2 = ProtobufUtil.toMutation(MutationType.PUT, put2);
+ Delete delete = new Delete(ROW2);
+ MutationProto m3 = ProtobufUtil.toMutation(MutationType.DELETE, delete);
+
+ MutateRowsRequest.Builder mrmBuilder = MutateRowsRequest.newBuilder();
+ mrmBuilder.addMutationRequest(m1);
+ mrmBuilder.addMutationRequest(m2);
+ mrmBuilder.addMutationRequest(m3);
+ mrmBuilder.addCondition(
+ ProtobufUtil.toCondition(ROW2, FAMILY, QUALIFIER, CompareOperator.EQUAL, VALUE1, null));
+
+ CoprocessorRpcChannel channel = t.coprocessorService(ROW);
+ MultiRowMutationService.BlockingInterface service =
+ MultiRowMutationService.newBlockingStub(channel);
+ MutateRowsResponse response = service.mutateRows(null, mrmBuilder.build());
+
+ // Assert
+ assertFalse(response.getProcessed());
+
+ Result r = t.get(new Get(ROW));
+ assertTrue(r.isEmpty());
+
+ r = t.get(new Get(ROW1));
+ assertTrue(r.isEmpty());
+
+ r = t.get(new Get(ROW2));
+ assertEquals(Bytes.toString(VALUE2), Bytes.toString(r.getValue(FAMILY, QUALIFIER)));
+ }
+ }
+
+ @TestTemplate
+ public void testMultiRowMutationWithMultipleConditionsWhenConditionsMatch() throws Exception {
+ final byte[] ROW1 = Bytes.toBytes("testRow1");
+ final byte[] ROW2 = Bytes.toBytes("testRow2");
+ final byte[] VALUE1 = Bytes.toBytes("testValue1");
+ final byte[] VALUE2 = Bytes.toBytes("testValue2");
+ TEST_UTIL.createTable(tableName, FAMILY);
+ try (Connection conn = getConnection(); Table t = conn.getTable(tableName)) {
+ // Add initial data
+ t.put(new Put(ROW2).addColumn(FAMILY, QUALIFIER, VALUE2));
+
+ // Execute MultiRowMutation with conditions
+ Put put1 = new Put(ROW).addColumn(FAMILY, QUALIFIER, VALUE);
+ MutationProto m1 = ProtobufUtil.toMutation(MutationType.PUT, put1);
+ Put put2 = new Put(ROW1).addColumn(FAMILY, QUALIFIER, VALUE1);
+ MutationProto m2 = ProtobufUtil.toMutation(MutationType.PUT, put2);
+ Delete delete = new Delete(ROW2);
+ MutationProto m3 = ProtobufUtil.toMutation(MutationType.DELETE, delete);
+
+ MutateRowsRequest.Builder mrmBuilder = MutateRowsRequest.newBuilder();
+ mrmBuilder.addMutationRequest(m1);
+ mrmBuilder.addMutationRequest(m2);
+ mrmBuilder.addMutationRequest(m3);
+ mrmBuilder.addCondition(
+ ProtobufUtil.toCondition(ROW, FAMILY, QUALIFIER, CompareOperator.EQUAL, null, null));
+ mrmBuilder.addCondition(
+ ProtobufUtil.toCondition(ROW2, FAMILY, QUALIFIER, CompareOperator.EQUAL, VALUE2, null));
+
+ CoprocessorRpcChannel channel = t.coprocessorService(ROW);
+ MultiRowMutationService.BlockingInterface service =
+ MultiRowMutationService.newBlockingStub(channel);
+ MutateRowsResponse response = service.mutateRows(null, mrmBuilder.build());
+
+ // Assert
+ assertTrue(response.getProcessed());
+
+ Result r = t.get(new Get(ROW));
+ assertEquals(Bytes.toString(VALUE), Bytes.toString(r.getValue(FAMILY, QUALIFIER)));
+
+ r = t.get(new Get(ROW1));
+ assertEquals(Bytes.toString(VALUE1), Bytes.toString(r.getValue(FAMILY, QUALIFIER)));
+
+ r = t.get(new Get(ROW2));
+ assertTrue(r.isEmpty());
+ }
+ }
+
+ @TestTemplate
+ public void testMultiRowMutationWithMultipleConditionsWhenConditionsNotMatch() throws Exception {
+ final byte[] ROW1 = Bytes.toBytes("testRow1");
+ final byte[] ROW2 = Bytes.toBytes("testRow2");
+ final byte[] VALUE1 = Bytes.toBytes("testValue1");
+ final byte[] VALUE2 = Bytes.toBytes("testValue2");
+ TEST_UTIL.createTable(tableName, FAMILY);
+ try (Connection conn = getConnection(); Table t = conn.getTable(tableName)) {
+ // Add initial data
+ t.put(new Put(ROW2).addColumn(FAMILY, QUALIFIER, VALUE2));
+
+ // Execute MultiRowMutation with conditions
+ Put put1 = new Put(ROW).addColumn(FAMILY, QUALIFIER, VALUE);
+ MutationProto m1 = ProtobufUtil.toMutation(MutationType.PUT, put1);
+ Put put2 = new Put(ROW1).addColumn(FAMILY, QUALIFIER, VALUE1);
+ MutationProto m2 = ProtobufUtil.toMutation(MutationType.PUT, put2);
+ Delete delete = new Delete(ROW2);
+ MutationProto m3 = ProtobufUtil.toMutation(MutationType.DELETE, delete);
+
+ MutateRowsRequest.Builder mrmBuilder = MutateRowsRequest.newBuilder();
+ mrmBuilder.addMutationRequest(m1);
+ mrmBuilder.addMutationRequest(m2);
+ mrmBuilder.addMutationRequest(m3);
+ mrmBuilder.addCondition(
+ ProtobufUtil.toCondition(ROW1, FAMILY, QUALIFIER, CompareOperator.EQUAL, null, null));
+ mrmBuilder.addCondition(
+ ProtobufUtil.toCondition(ROW2, FAMILY, QUALIFIER, CompareOperator.EQUAL, VALUE1, null));
+
+ CoprocessorRpcChannel channel = t.coprocessorService(ROW);
+ MultiRowMutationService.BlockingInterface service =
+ MultiRowMutationService.newBlockingStub(channel);
+ MutateRowsResponse response = service.mutateRows(null, mrmBuilder.build());
+
+ // Assert
+ assertFalse(response.getProcessed());
+
+ Result r = t.get(new Get(ROW));
+ assertTrue(r.isEmpty());
+
+ r = t.get(new Get(ROW1));
+ assertTrue(r.isEmpty());
+
+ r = t.get(new Get(ROW2));
+ assertEquals(Bytes.toString(VALUE2), Bytes.toString(r.getValue(FAMILY, QUALIFIER)));
+ }
+ }
+
+ @TestTemplate
+ public void testMultiRowMutationWithFilterConditionWhenConditionMatches() throws Exception {
+ final byte[] ROW1 = Bytes.toBytes("testRow1");
+ final byte[] ROW2 = Bytes.toBytes("testRow2");
+ final byte[] QUALIFIER2 = Bytes.toBytes("testQualifier2");
+ final byte[] VALUE1 = Bytes.toBytes("testValue1");
+ final byte[] VALUE2 = Bytes.toBytes("testValue2");
+ final byte[] VALUE3 = Bytes.toBytes("testValue3");
+ TEST_UTIL.createTable(tableName, FAMILY);
+ try (Connection conn = getConnection(); Table t = conn.getTable(tableName)) {
+ // Add initial data
+ t.put(
+ new Put(ROW2).addColumn(FAMILY, QUALIFIER, VALUE2).addColumn(FAMILY, QUALIFIER2, VALUE3));
+
+ // Execute MultiRowMutation with conditions
+ Put put1 = new Put(ROW).addColumn(FAMILY, QUALIFIER, VALUE);
+ MutationProto m1 = ProtobufUtil.toMutation(MutationType.PUT, put1);
+ Put put2 = new Put(ROW1).addColumn(FAMILY, QUALIFIER, VALUE1);
+ MutationProto m2 = ProtobufUtil.toMutation(MutationType.PUT, put2);
+ Delete delete = new Delete(ROW2);
+ MutationProto m3 = ProtobufUtil.toMutation(MutationType.DELETE, delete);
+
+ MutateRowsRequest.Builder mrmBuilder = MutateRowsRequest.newBuilder();
+ mrmBuilder.addMutationRequest(m1);
+ mrmBuilder.addMutationRequest(m2);
+ mrmBuilder.addMutationRequest(m3);
+ mrmBuilder.addCondition(ProtobufUtil.toCondition(ROW2,
+ new FilterList(
+ new SingleColumnValueFilter(FAMILY, QUALIFIER, CompareOperator.EQUAL, VALUE2),
+ new SingleColumnValueFilter(FAMILY, QUALIFIER2, CompareOperator.EQUAL, VALUE3)),
+ null));
+
+ CoprocessorRpcChannel channel = t.coprocessorService(ROW);
+ MultiRowMutationService.BlockingInterface service =
+ MultiRowMutationService.newBlockingStub(channel);
+ MutateRowsResponse response = service.mutateRows(null, mrmBuilder.build());
+
+ // Assert
+ assertTrue(response.getProcessed());
+
+ Result r = t.get(new Get(ROW));
+ assertEquals(Bytes.toString(VALUE), Bytes.toString(r.getValue(FAMILY, QUALIFIER)));
+
+ r = t.get(new Get(ROW1));
+ assertEquals(Bytes.toString(VALUE1), Bytes.toString(r.getValue(FAMILY, QUALIFIER)));
+
+ r = t.get(new Get(ROW2));
+ assertTrue(r.isEmpty());
+ }
+ }
+
+ @TestTemplate
+ public void testMultiRowMutationWithFilterConditionWhenConditionNotMatch() throws Exception {
+ final byte[] ROW1 = Bytes.toBytes("testRow1");
+ final byte[] ROW2 = Bytes.toBytes("testRow2");
+ final byte[] QUALIFIER2 = Bytes.toBytes("testQualifier2");
+ final byte[] VALUE1 = Bytes.toBytes("testValue1");
+ final byte[] VALUE2 = Bytes.toBytes("testValue2");
+ final byte[] VALUE3 = Bytes.toBytes("testValue3");
+ TEST_UTIL.createTable(tableName, FAMILY);
+ try (Connection conn = getConnection(); Table t = conn.getTable(tableName)) {
+ // Add initial data
+ t.put(
+ new Put(ROW2).addColumn(FAMILY, QUALIFIER, VALUE2).addColumn(FAMILY, QUALIFIER2, VALUE3));
+
+ // Execute MultiRowMutation with conditions
+ Put put1 = new Put(ROW).addColumn(FAMILY, QUALIFIER, VALUE);
+ MutationProto m1 = ProtobufUtil.toMutation(MutationType.PUT, put1);
+ Put put2 = new Put(ROW1).addColumn(FAMILY, QUALIFIER, VALUE1);
+ MutationProto m2 = ProtobufUtil.toMutation(MutationType.PUT, put2);
+ Delete delete = new Delete(ROW2);
+ MutationProto m3 = ProtobufUtil.toMutation(MutationType.DELETE, delete);
+
+ MutateRowsRequest.Builder mrmBuilder = MutateRowsRequest.newBuilder();
+ mrmBuilder.addMutationRequest(m1);
+ mrmBuilder.addMutationRequest(m2);
+ mrmBuilder.addMutationRequest(m3);
+ mrmBuilder.addCondition(ProtobufUtil.toCondition(ROW2,
+ new FilterList(
+ new SingleColumnValueFilter(FAMILY, QUALIFIER, CompareOperator.EQUAL, VALUE2),
+ new SingleColumnValueFilter(FAMILY, QUALIFIER2, CompareOperator.EQUAL, VALUE2)),
+ null));
+
+ CoprocessorRpcChannel channel = t.coprocessorService(ROW);
+ MultiRowMutationService.BlockingInterface service =
+ MultiRowMutationService.newBlockingStub(channel);
+ MutateRowsResponse response = service.mutateRows(null, mrmBuilder.build());
+
+ // Assert
+ assertFalse(response.getProcessed());
+
+ Result r = t.get(new Get(ROW));
+ assertTrue(r.isEmpty());
+
+ r = t.get(new Get(ROW1));
+ assertTrue(r.isEmpty());
+
+ r = t.get(new Get(ROW2));
+ assertEquals(Bytes.toString(VALUE2), Bytes.toString(r.getValue(FAMILY, QUALIFIER)));
+ }
+ }
+}
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/FromClientSideTestReverseScan.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/FromClientSideTestReverseScan.java
new file mode 100644
index 00000000000..f0f479bc273
--- /dev/null
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/FromClientSideTestReverseScan.java
@@ -0,0 +1,669 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hbase.client;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.io.IOException;
+import org.apache.hadoop.hbase.Cell;
+import org.apache.hadoop.hbase.CellUtil;
+import org.apache.hadoop.hbase.CompareOperator;
+import org.apache.hadoop.hbase.HConstants;
+import org.apache.hadoop.hbase.TableName;
+import org.apache.hadoop.hbase.client.Scan.ReadType;
+import org.apache.hadoop.hbase.filter.Filter;
+import org.apache.hadoop.hbase.filter.KeyOnlyFilter;
+import org.apache.hadoop.hbase.filter.QualifierFilter;
+import org.apache.hadoop.hbase.filter.RegexStringComparator;
+import org.apache.hadoop.hbase.util.Bytes;
+import org.junit.jupiter.api.TestTemplate;
+
+public class FromClientSideTestReverseScan extends FromClientSideTestBase {
+
+ protected FromClientSideTestReverseScan(Class<? extends ConnectionRegistry> registryImpl,
+ int numHedgedReqs) {
+ super(registryImpl, numHedgedReqs);
+ }
+
+ @TestTemplate
+ public void testSuperSimpleWithReverseScan() throws Exception {
+ TEST_UTIL.createTable(tableName, FAMILY);
+ try (Connection conn = getConnection(); Table ht = conn.getTable(tableName)) {
+ Put put = new Put(Bytes.toBytes("0-b11111-0000000000000000000"));
+ put.addColumn(FAMILY, QUALIFIER, VALUE);
+ ht.put(put);
+ put = new Put(Bytes.toBytes("0-b11111-0000000000000000002"));
+ put.addColumn(FAMILY, QUALIFIER, VALUE);
+ ht.put(put);
+ put = new Put(Bytes.toBytes("0-b11111-0000000000000000004"));
+ put.addColumn(FAMILY, QUALIFIER, VALUE);
+ ht.put(put);
+ put = new Put(Bytes.toBytes("0-b11111-0000000000000000006"));
+ put.addColumn(FAMILY, QUALIFIER, VALUE);
+ ht.put(put);
+ put = new Put(Bytes.toBytes("0-b11111-0000000000000000008"));
+ put.addColumn(FAMILY, QUALIFIER, VALUE);
+ ht.put(put);
+ put = new Put(Bytes.toBytes("0-b22222-0000000000000000001"));
+ put.addColumn(FAMILY, QUALIFIER, VALUE);
+ ht.put(put);
+ put = new Put(Bytes.toBytes("0-b22222-0000000000000000003"));
+ put.addColumn(FAMILY, QUALIFIER, VALUE);
+ ht.put(put);
+ put = new Put(Bytes.toBytes("0-b22222-0000000000000000005"));
+ put.addColumn(FAMILY, QUALIFIER, VALUE);
+ ht.put(put);
+ put = new Put(Bytes.toBytes("0-b22222-0000000000000000007"));
+ put.addColumn(FAMILY, QUALIFIER, VALUE);
+ ht.put(put);
+ put = new Put(Bytes.toBytes("0-b22222-0000000000000000009"));
+ put.addColumn(FAMILY, QUALIFIER, VALUE);
+ ht.put(put);
+ Scan scan = new Scan().withStartRow(Bytes.toBytes("0-b11111-9223372036854775807"))
+ .withStopRow(Bytes.toBytes("0-b11111-0000000000000000000"), true);
+ scan.setReversed(true);
+ try (ResultScanner scanner = ht.getScanner(scan)) {
+ Result result = scanner.next();
+ assertTrue(Bytes.equals(result.getRow(), Bytes.toBytes("0-b11111-0000000000000000008")));
+ }
+ }
+ }
+
+ @TestTemplate
+ public void testFiltersWithReverseScan() throws Exception {
+ TEST_UTIL.createTable(tableName, FAMILY);
+ try (Connection conn = getConnection(); Table ht = conn.getTable(tableName)) {
+ byte[][] ROWS = makeN(ROW, 10);
+ byte[][] QUALIFIERS =
+ { Bytes.toBytes("col0-<d2v1>-<d3v2>"), Bytes.toBytes("col1-<d2v1>-<d3v2>"),
+ Bytes.toBytes("col2-<d2v1>-<d3v2>"), Bytes.toBytes("col3-<d2v1>-<d3v2>"),
+ Bytes.toBytes("col4-<d2v1>-<d3v2>"), Bytes.toBytes("col5-<d2v1>-<d3v2>"),
+ Bytes.toBytes("col6-<d2v1>-<d3v2>"), Bytes.toBytes("col7-<d2v1>-<d3v2>"),
+ Bytes.toBytes("col8-<d2v1>-<d3v2>"), Bytes.toBytes("col9-<d2v1>-<d3v2>") };
+ for (int i = 0; i < 10; i++) {
+ Put put = new Put(ROWS[i]);
+ put.addColumn(FAMILY, QUALIFIERS[i], VALUE);
+ ht.put(put);
+ }
+ Scan scan = new Scan();
+ scan.setReversed(true);
+ scan.addFamily(FAMILY);
+ Filter filter =
+ new QualifierFilter(CompareOperator.EQUAL, new RegexStringComparator("col[1-5]"));
+ scan.setFilter(filter);
+ try (ResultScanner scanner = ht.getScanner(scan)) {
+ int expectedIndex = 5;
+ for (Result result : scanner) {
+ assertEquals(1, result.size());
+ Cell c = result.rawCells()[0];
+ assertTrue(Bytes.equals(c.getRowArray(), c.getRowOffset(), c.getRowLength(),
+ ROWS[expectedIndex], 0, ROWS[expectedIndex].length));
+ assertTrue(
+ Bytes.equals(c.getQualifierArray(), c.getQualifierOffset(), c.getQualifierLength(),
+ QUALIFIERS[expectedIndex], 0, QUALIFIERS[expectedIndex].length));
+ expectedIndex--;
+ }
+ assertEquals(0, expectedIndex);
+ }
+ }
+ }
+
+ @TestTemplate
+ public void testKeyOnlyFilterWithReverseScan() throws Exception {
+ TEST_UTIL.createTable(tableName, FAMILY);
+ try (Connection conn = getConnection(); Table ht = conn.getTable(tableName)) {
+ byte[][] ROWS = makeN(ROW, 10);
+ byte[][] QUALIFIERS =
+ { Bytes.toBytes("col0-<d2v1>-<d3v2>"), Bytes.toBytes("col1-<d2v1>-<d3v2>"),
+ Bytes.toBytes("col2-<d2v1>-<d3v2>"), Bytes.toBytes("col3-<d2v1>-<d3v2>"),
+ Bytes.toBytes("col4-<d2v1>-<d3v2>"), Bytes.toBytes("col5-<d2v1>-<d3v2>"),
+ Bytes.toBytes("col6-<d2v1>-<d3v2>"), Bytes.toBytes("col7-<d2v1>-<d3v2>"),
+ Bytes.toBytes("col8-<d2v1>-<d3v2>"), Bytes.toBytes("col9-<d2v1>-<d3v2>") };
+ for (int i = 0; i < 10; i++) {
+ Put put = new Put(ROWS[i]);
+ put.addColumn(FAMILY, QUALIFIERS[i], VALUE);
+ ht.put(put);
+ }
+ Scan scan = new Scan();
+ scan.setReversed(true);
+ scan.addFamily(FAMILY);
+ Filter filter = new KeyOnlyFilter(true);
+ scan.setFilter(filter);
+ try (ResultScanner ignored = ht.getScanner(scan)) {
+ int count = 0;
+ for (Result result : ht.getScanner(scan)) {
+ assertEquals(1, result.size());
+ assertEquals(Bytes.SIZEOF_INT, result.rawCells()[0].getValueLength());
+ assertEquals(VALUE.length, Bytes.toInt(CellUtil.cloneValue(result.rawCells()[0])));
+ count++;
+ }
+ assertEquals(10, count);
+ }
+ }
+ }
+
+ /**
+ * Test simple table and non-existent row cases.
+ */
+ @TestTemplate
+ public void testSimpleMissingWithReverseScan() throws Exception {
+ TEST_UTIL.createTable(tableName, FAMILY);
+ try (Connection conn = getConnection(); Table ht = conn.getTable(tableName)) {
+ byte[][] ROWS = makeN(ROW, 4);
+
+ // Try to get a row on an empty table
+ Scan scan = new Scan();
+ scan.setReversed(true);
+ Result result = getSingleScanResult(ht, scan);
+ assertNullResult(result);
+
+ scan = new Scan().withStartRow(ROWS[0]);
+ scan.setReversed(true);
+ result = getSingleScanResult(ht, scan);
+ assertNullResult(result);
+
+ scan = new Scan().withStartRow(ROWS[0]).withStopRow(ROWS[1], true);
+ scan.setReversed(true);
+ result = getSingleScanResult(ht, scan);
+ assertNullResult(result);
+
+ scan = new Scan();
+ scan.setReversed(true);
+ scan.addFamily(FAMILY);
+ result = getSingleScanResult(ht, scan);
+ assertNullResult(result);
+
+ scan = new Scan();
+ scan.setReversed(true);
+ scan.addColumn(FAMILY, QUALIFIER);
+ result = getSingleScanResult(ht, scan);
+ assertNullResult(result);
+
+ // Insert a row
+ Put put = new Put(ROWS[2]);
+ put.addColumn(FAMILY, QUALIFIER, VALUE);
+ ht.put(put);
+
+ // Make sure we can scan the row
+ scan = new Scan();
+ scan.setReversed(true);
+ result = getSingleScanResult(ht, scan);
+ assertSingleResult(result, ROWS[2], FAMILY, QUALIFIER, VALUE);
+
+ scan = new Scan().withStartRow(ROWS[3]).withStopRow(ROWS[0], true);
+ scan.setReversed(true);
+ result = getSingleScanResult(ht, scan);
+ assertSingleResult(result, ROWS[2], FAMILY, QUALIFIER, VALUE);
+
+ scan = new Scan().withStartRow(ROWS[2]).withStopRow(ROWS[1], true);
+ scan.setReversed(true);
+ result = getSingleScanResult(ht, scan);
+ assertSingleResult(result, ROWS[2], FAMILY, QUALIFIER, VALUE);
+
+ // Try to scan empty rows around it
+ // Introduced MemStore#shouldSeekForReverseScan to fix the following
+ scan = new Scan().withStartRow(ROWS[1]);
+ scan.setReversed(true);
+ result = getSingleScanResult(ht, scan);
+ assertNullResult(result);
+ }
+ }
+
+ @TestTemplate
+ public void testNullWithReverseScan() throws Exception {
+ TEST_UTIL.createTable(tableName, FAMILY);
+ try (Connection conn = getConnection(); Table ht = conn.getTable(tableName)) {
+ // Null qualifier (should work)
+ Put put = new Put(ROW);
+ put.addColumn(FAMILY, null, VALUE);
+ ht.put(put);
+ scanTestNull(ht, ROW, FAMILY, VALUE, true);
+ Delete delete = new Delete(ROW);
+ delete.addColumns(FAMILY, null);
+ ht.delete(delete);
+ }
+
+ // Use a new table
+ TableName newTableName = TableName.valueOf(tableName.toString() + "2");
+ TEST_UTIL.createTable(newTableName, FAMILY);
+ try (Connection conn = getConnection(); Table ht = conn.getTable(newTableName)) {
+ // Empty qualifier, byte[0] instead of null (should work)
+ Put put = new Put(ROW);
+ put.addColumn(FAMILY, HConstants.EMPTY_BYTE_ARRAY, VALUE);
+ ht.put(put);
+ scanTestNull(ht, ROW, FAMILY, VALUE, true);
+ TEST_UTIL.flush();
+ scanTestNull(ht, ROW, FAMILY, VALUE, true);
+ Delete delete = new Delete(ROW);
+ delete.addColumns(FAMILY, HConstants.EMPTY_BYTE_ARRAY);
+ ht.delete(delete);
+ // Null value
+ put = new Put(ROW);
+ put.addColumn(FAMILY, QUALIFIER, null);
+ ht.put(put);
+ Scan scan = new Scan();
+ scan.setReversed(true);
+ scan.addColumn(FAMILY, QUALIFIER);
+ Result result = getSingleScanResult(ht, scan);
+ assertSingleResult(result, ROW, FAMILY, QUALIFIER, null);
+ }
+ }
+
+ @TestTemplate
+ @SuppressWarnings("checkstyle:MethodLength")
+ public void testDeletesWithReverseScan() throws Exception {
+ byte[][] ROWS = makeNAscii(ROW, 6);
+ byte[][] FAMILIES = makeNAscii(FAMILY, 3);
+ byte[][] VALUES = makeN(VALUE, 5);
+ long[] ts = { 1000, 2000, 3000, 4000, 5000 };
+ TEST_UTIL.createTable(tableName, FAMILIES, 3);
+ try (Connection conn = getConnection(); Table ht = conn.getTable(tableName)) {
+ Put put = new Put(ROW);
+ put.addColumn(FAMILIES[0], QUALIFIER, ts[0], VALUES[0]);
+ put.addColumn(FAMILIES[0], QUALIFIER, ts[1], VALUES[1]);
+ ht.put(put);
+
+ Delete delete = new Delete(ROW);
+ delete.addFamily(FAMILIES[0], ts[0]);
+ ht.delete(delete);
+
+ Scan scan = new Scan().withStartRow(ROW);
+ scan.setReversed(true);
+ scan.addFamily(FAMILIES[0]);
+ scan.readVersions(Integer.MAX_VALUE);
+ Result result = getSingleScanResult(ht, scan);
+ assertNResult(result, ROW, FAMILIES[0], QUALIFIER, new long[] { ts[1] },
+ new byte[][] { VALUES[1] }, 0, 0);
+
+ // Test delete latest version
+ put = new Put(ROW);
+ put.addColumn(FAMILIES[0], QUALIFIER, ts[4], VALUES[4]);
+ put.addColumn(FAMILIES[0], QUALIFIER, ts[2], VALUES[2]);
+ put.addColumn(FAMILIES[0], QUALIFIER, ts[3], VALUES[3]);
+ put.addColumn(FAMILIES[0], null, ts[4], VALUES[4]);
+ put.addColumn(FAMILIES[0], null, ts[2], VALUES[2]);
+ put.addColumn(FAMILIES[0], null, ts[3], VALUES[3]);
+ ht.put(put);
+
+ delete = new Delete(ROW);
+ delete.addColumn(FAMILIES[0], QUALIFIER); // ts[4]
+ ht.delete(delete);
+
+ scan = new Scan().withStartRow(ROW);
+ scan.setReversed(true);
+ scan.addColumn(FAMILIES[0], QUALIFIER);
+ scan.readVersions(Integer.MAX_VALUE);
+ result = getSingleScanResult(ht, scan);
+ assertNResult(result, ROW, FAMILIES[0], QUALIFIER, new long[] { ts[1], ts[2], ts[3] },
+ new byte[][] { VALUES[1], VALUES[2], VALUES[3] }, 0, 2);
+
+ // Test for HBASE-1847
+ delete = new Delete(ROW);
+ delete.addColumn(FAMILIES[0], null);
+ ht.delete(delete);
+
+ // Cleanup null qualifier
+ delete = new Delete(ROW);
+ delete.addColumns(FAMILIES[0], null);
+ ht.delete(delete);
+
+ // Expected client behavior might be that you can re-put deleted values
+ // But alas, this is not to be. We can't put them back in either case.
+
+ put = new Put(ROW);
+ put.addColumn(FAMILIES[0], QUALIFIER, ts[0], VALUES[0]);
+ put.addColumn(FAMILIES[0], QUALIFIER, ts[4], VALUES[4]);
+ ht.put(put);
+
+ // The Scanner returns the previous values, the expected-naive-unexpected
+ // behavior
+
+ scan = new Scan().withStartRow(ROW);
+ scan.setReversed(true);
+ scan.addFamily(FAMILIES[0]);
+ scan.readVersions(Integer.MAX_VALUE);
+ result = getSingleScanResult(ht, scan);
+ assertNResult(result, ROW, FAMILIES[0], QUALIFIER, new long[] { ts[1], ts[2], ts[3] },
+ new byte[][] { VALUES[1], VALUES[2], VALUES[3] }, 0, 2);
+
+ // Test deleting an entire family from one row but not the other various
+ // ways
+
+ put = new Put(ROWS[0]);
+ put.addColumn(FAMILIES[1], QUALIFIER, ts[0], VALUES[0]);
+ put.addColumn(FAMILIES[1], QUALIFIER, ts[1], VALUES[1]);
+ put.addColumn(FAMILIES[2], QUALIFIER, ts[2], VALUES[2]);
+ put.addColumn(FAMILIES[2], QUALIFIER, ts[3], VALUES[3]);
+ ht.put(put);
+
+ put = new Put(ROWS[1]);
+ put.addColumn(FAMILIES[1], QUALIFIER, ts[0], VALUES[0]);
+ put.addColumn(FAMILIES[1], QUALIFIER, ts[1], VALUES[1]);
+ put.addColumn(FAMILIES[2], QUALIFIER, ts[2], VALUES[2]);
+ put.addColumn(FAMILIES[2], QUALIFIER, ts[3], VALUES[3]);
+ ht.put(put);
+
+ put = new Put(ROWS[2]);
+ put.addColumn(FAMILIES[1], QUALIFIER, ts[0], VALUES[0]);
+ put.addColumn(FAMILIES[1], QUALIFIER, ts[1], VALUES[1]);
+ put.addColumn(FAMILIES[2], QUALIFIER, ts[2], VALUES[2]);
+ put.addColumn(FAMILIES[2], QUALIFIER, ts[3], VALUES[3]);
+ ht.put(put);
+
+ delete = new Delete(ROWS[0]);
+ delete.addFamily(FAMILIES[2]);
+ ht.delete(delete);
+
+ delete = new Delete(ROWS[1]);
+ delete.addColumns(FAMILIES[1], QUALIFIER);
+ ht.delete(delete);
+
+ delete = new Delete(ROWS[2]);
+ delete.addColumn(FAMILIES[1], QUALIFIER);
+ delete.addColumn(FAMILIES[1], QUALIFIER);
+ delete.addColumn(FAMILIES[2], QUALIFIER);
+ ht.delete(delete);
+
+ scan = new Scan().withStartRow(ROWS[0]);
+ scan.setReversed(true);
+ scan.addFamily(FAMILIES[1]);
+ scan.addFamily(FAMILIES[2]);
+ scan.readVersions(Integer.MAX_VALUE);
+ result = getSingleScanResult(ht, scan);
+ assertEquals(2, result.size(), "Expected 2 keys but received " + result.size());
+ assertNResult(result, ROWS[0], FAMILIES[1], QUALIFIER, new long[] { ts[0], ts[1] },
+ new byte[][] { VALUES[0], VALUES[1] }, 0, 1);
+
+ scan = new Scan().withStartRow(ROWS[1]);
+ scan.setReversed(true);
+ scan.addFamily(FAMILIES[1]);
+ scan.addFamily(FAMILIES[2]);
+ scan.readVersions(Integer.MAX_VALUE);
+ result = getSingleScanResult(ht, scan);
+ assertEquals(2, result.size(), "Expected 2 keys but received " + result.size());
+
+ scan = new Scan().withStartRow(ROWS[2]);
+ scan.setReversed(true);
+ scan.addFamily(FAMILIES[1]);
+ scan.addFamily(FAMILIES[2]);
+ scan.readVersions(Integer.MAX_VALUE);
+ result = getSingleScanResult(ht, scan);
+ assertEquals(1, result.size());
+ assertNResult(result, ROWS[2], FAMILIES[2], QUALIFIER, new long[] { ts[2] },
+ new byte[][] { VALUES[2] }, 0, 0);
+
+ // Test if we delete the family first in one row (HBASE-1541)
+
+ delete = new Delete(ROWS[3]);
+ delete.addFamily(FAMILIES[1]);
+ ht.delete(delete);
+
+ put = new Put(ROWS[3]);
+ put.addColumn(FAMILIES[2], QUALIFIER, VALUES[0]);
+ ht.put(put);
+
+ put = new Put(ROWS[4]);
+ put.addColumn(FAMILIES[1], QUALIFIER, VALUES[1]);
+ put.addColumn(FAMILIES[2], QUALIFIER, VALUES[2]);
+ ht.put(put);
+
+ scan = new Scan().withStartRow(ROWS[4]);
+ scan.setReversed(true);
+ scan.addFamily(FAMILIES[1]);
+ scan.addFamily(FAMILIES[2]);
+ scan.readVersions(Integer.MAX_VALUE);
+ try (ResultScanner scanner = ht.getScanner(scan)) {
+ result = scanner.next();
+ assertEquals(2, result.size(), "Expected 2 keys but received " + result.size());
+ assertTrue(Bytes.equals(CellUtil.cloneRow(result.rawCells()[0]), ROWS[4]));
+ assertTrue(Bytes.equals(CellUtil.cloneRow(result.rawCells()[1]), ROWS[4]));
+ assertTrue(Bytes.equals(CellUtil.cloneValue(result.rawCells()[0]), VALUES[1]));
+ assertTrue(Bytes.equals(CellUtil.cloneValue(result.rawCells()[1]), VALUES[2]));
+ result = scanner.next();
+ assertEquals(1, result.size(), "Expected 1 key but received " + result.size());
+ assertTrue(Bytes.equals(CellUtil.cloneRow(result.rawCells()[0]), ROWS[3]));
+ assertTrue(Bytes.equals(CellUtil.cloneValue(result.rawCells()[0]), VALUES[0]));
+ }
+ }
+ }
+
+ /**
+ * Tests reversed scan under multi regions
+ */
+ @TestTemplate
+ public void testReversedScanUnderMultiRegions() throws Exception {
+ // Test Initialization.
+ byte[] maxByteArray = ConnectionUtils.MAX_BYTE_ARRAY;
+ byte[][] splitRows = new byte[][] { Bytes.toBytes("005"),
+ Bytes.add(Bytes.toBytes("005"), Bytes.multiple(maxByteArray, 16)), Bytes.toBytes("006"),
+ Bytes.add(Bytes.toBytes("006"), Bytes.multiple(maxByteArray, 8)), Bytes.toBytes("007"),
+ Bytes.add(Bytes.toBytes("007"), Bytes.multiple(maxByteArray, 4)), Bytes.toBytes("008"),
+ Bytes.multiple(maxByteArray, 2) };
+ TEST_UTIL.createTable(tableName, FAMILY, splitRows);
+ TEST_UTIL.waitUntilAllRegionsAssigned(tableName);
+ try (Connection conn = getConnection(); Table table = conn.getTable(tableName)) {
+ try (RegionLocator l = conn.getRegionLocator(tableName)) {
+ assertEquals(splitRows.length + 1, l.getAllRegionLocations().size());
+ }
+ // Insert one row each region
+ int insertNum = splitRows.length;
+ for (byte[] splitRow : splitRows) {
+ Put put = new Put(splitRow);
+ put.addColumn(FAMILY, QUALIFIER, VALUE);
+ table.put(put);
+ }
+
+ // scan forward
+ try (ResultScanner scanner = table.getScanner(new Scan())) {
+ int count = 0;
+ for (Result r : scanner) {
+ assertFalse(r.isEmpty());
+ count++;
+ }
+ assertEquals(insertNum, count);
+ }
+
+ // scan backward
+ Scan scan = new Scan();
+ scan.setReversed(true);
+ try (ResultScanner scanner = table.getScanner(scan)) {
+ int count = 0;
+ byte[] lastRow = null;
+ for (Result r : scanner) {
+ assertFalse(r.isEmpty());
+ count++;
+ byte[] thisRow = r.getRow();
+ if (lastRow != null) {
+ assertTrue(Bytes.compareTo(thisRow, lastRow) < 0, "Error scan order, last row= "
+ + Bytes.toString(lastRow) + ",this row=" + Bytes.toString(thisRow));
+ }
+ lastRow = thisRow;
+ }
+ assertEquals(insertNum, count);
+ }
+ }
+ }
+
+ /**
+ * Tests reversed scan under multi regions
+ */
+ @TestTemplate
+ public void testSmallReversedScanUnderMultiRegions() throws Exception {
+ // Test Initialization.
+ byte[][] splitRows = new byte[][] { Bytes.toBytes("000"), Bytes.toBytes("002"),
+ Bytes.toBytes("004"), Bytes.toBytes("006"), Bytes.toBytes("008"), Bytes.toBytes("010") };
+ TEST_UTIL.createTable(tableName, FAMILY, splitRows);
+ TEST_UTIL.waitUntilAllRegionsAssigned(tableName);
+ try (Connection conn = getConnection(); Table table = conn.getTable(tableName)) {
+ try (RegionLocator l = conn.getRegionLocator(tableName)) {
+ assertEquals(splitRows.length + 1, l.getAllRegionLocations().size());
+ }
+ for (byte[] splitRow : splitRows) {
+ Put put = new Put(splitRow);
+ put.addColumn(FAMILY, QUALIFIER, VALUE);
+ table.put(put);
+
+ byte[] nextRow = Bytes.copy(splitRow);
+ nextRow[nextRow.length - 1]++;
+
+ put = new Put(nextRow);
+ put.addColumn(FAMILY, QUALIFIER, VALUE);
+ table.put(put);
+ }
+
+ // scan forward
+ try (ResultScanner scanner = table.getScanner(new Scan())) {
+ int count = 0;
+ for (Result r : scanner) {
+ assertTrue(!r.isEmpty());
+ count++;
+ }
+ assertEquals(12, count);
+ }
+
+ reverseScanTest(table, ReadType.STREAM);
+ reverseScanTest(table, ReadType.PREAD);
+ reverseScanTest(table, ReadType.DEFAULT);
+ }
+ }
+
+ private void reverseScanTest(Table table, ReadType readType) throws IOException {
+ // scan backward
+ Scan scan = new Scan();
+ scan.setReversed(true);
+ try (ResultScanner scanner = table.getScanner(scan)) {
+ int count = 0;
+ byte[] lastRow = null;
+ for (Result r : scanner) {
+ assertTrue(!r.isEmpty());
+ count++;
+ byte[] thisRow = r.getRow();
+ if (lastRow != null) {
+ assertTrue(Bytes.compareTo(thisRow, lastRow) < 0, "Error scan order, last row= "
+ + Bytes.toString(lastRow) + ",this row=" + Bytes.toString(thisRow));
+ }
+ lastRow = thisRow;
+ }
+ assertEquals(12, count);
+ }
+
+ scan = new Scan();
+ scan.setReadType(readType);
+ scan.setReversed(true);
+ scan.withStartRow(Bytes.toBytes("002"));
+ try (ResultScanner scanner = table.getScanner(scan)) {
+ int count = 0;
+ byte[] lastRow = null;
+ for (Result r : scanner) {
+ assertTrue(!r.isEmpty());
+ count++;
+ byte[] thisRow = r.getRow();
+ if (lastRow != null) {
+ assertTrue(Bytes.compareTo(thisRow, lastRow) < 0, "Error scan order, last row= "
+ + Bytes.toString(lastRow) + ",this row=" + Bytes.toString(thisRow));
+ }
+ lastRow = thisRow;
+ }
+ assertEquals(3, count); // 000 001 002
+ }
+
+ scan = new Scan();
+ scan.setReadType(readType);
+ scan.setReversed(true);
+ scan.withStartRow(Bytes.toBytes("002"));
+ scan.withStopRow(Bytes.toBytes("000"));
+ try (ResultScanner scanner = table.getScanner(scan)) {
+ int count = 0;
+ byte[] lastRow = null;
+ for (Result r : scanner) {
+ assertFalse(r.isEmpty());
+ count++;
+ byte[] thisRow = r.getRow();
+ if (lastRow != null) {
+ assertTrue(Bytes.compareTo(thisRow, lastRow) < 0, "Error scan order, last row= "
+ + Bytes.toString(lastRow) + ",this row=" + Bytes.toString(thisRow));
+ }
+ lastRow = thisRow;
+ }
+ assertEquals(2, count); // 001 002
+ }
+
+ scan = new Scan();
+ scan.setReadType(readType);
+ scan.setReversed(true);
+ scan.withStartRow(Bytes.toBytes("001"));
+ try (ResultScanner scanner = table.getScanner(scan)) {
+ int count = 0;
+ byte[] lastRow = null;
+ for (Result r : scanner) {
+ assertFalse(r.isEmpty());
+ count++;
+ byte[] thisRow = r.getRow();
+ if (lastRow != null) {
+ assertTrue(Bytes.compareTo(thisRow, lastRow) < 0, "Error scan order, last row= "
+ + Bytes.toString(lastRow) + ",this row=" + Bytes.toString(thisRow));
+ }
+ lastRow = thisRow;
+ }
+ assertEquals(2, count); // 000 001
+ }
+
+ scan = new Scan();
+ scan.setReadType(readType);
+ scan.setReversed(true);
+ scan.withStartRow(Bytes.toBytes("000"));
+ try (ResultScanner scanner = table.getScanner(scan)) {
+ int count = 0;
+ byte[] lastRow = null;
+ for (Result r : scanner) {
+ assertFalse(r.isEmpty());
+ count++;
+ byte[] thisRow = r.getRow();
+ if (lastRow != null) {
+ assertTrue(Bytes.compareTo(thisRow, lastRow) < 0, "Error scan order, last row= "
+ + Bytes.toString(lastRow) + ",this row=" + Bytes.toString(thisRow));
+ }
+ lastRow = thisRow;
+ }
+ assertEquals(1, count); // 000
+ }
+
+ scan = new Scan();
+ scan.setReadType(readType);
+ scan.setReversed(true);
+ scan.withStartRow(Bytes.toBytes("006"));
+ scan.withStopRow(Bytes.toBytes("002"));
+ try (ResultScanner scanner = table.getScanner(scan)) {
+ int count = 0;
+ byte[] lastRow = null;
+ for (Result r : scanner) {
+ assertFalse(r.isEmpty());
+ count++;
+ byte[] thisRow = r.getRow();
+ if (lastRow != null) {
+ assertTrue(Bytes.compareTo(thisRow, lastRow) < 0, "Error scan order, last row= "
+ + Bytes.toString(lastRow) + ",this row=" + Bytes.toString(thisRow));
+ }
+ lastRow = thisRow;
+ }
+ assertEquals(4, count); // 003 004 005 006
+ }
+ }
+}
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientSide5.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientSide5.java
index 4efedafbf2a..b4017a23803 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientSide5.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientSide5.java
@@ -19,7 +19,6 @@ package org.apache.hadoop.hbase.client;
import org.apache.hadoop.hbase.HBaseParameterizedTestTemplate;
import org.apache.hadoop.hbase.coprocessor.MultiRowMutationEndpoint;
-import org.apache.hadoop.hbase.regionserver.NoOpScanPolicyObserver;
import org.apache.hadoop.hbase.testclassification.ClientTests;
import org.apache.hadoop.hbase.testclassification.LargeTests;
import org.junit.jupiter.api.BeforeAll;
@@ -41,6 +40,6 @@ public class TestFromClientSide5 extends FromClientSideTest5 {
@BeforeAll
public static void setUpBeforeClass() throws Exception {
- initialize(NoOpScanPolicyObserver.class, MultiRowMutationEndpoint.class);
+ initialize(MultiRowMutationEndpoint.class);
}
}
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientSide5WithCoprocessor.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientSide5WithCoprocessor.java
index b7203a0b585..c1785665d89 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientSide5WithCoprocessor.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientSide5WithCoprocessor.java
@@ -19,6 +19,7 @@ package org.apache.hadoop.hbase.client;
import org.apache.hadoop.hbase.HBaseParameterizedTestTemplate;
import org.apache.hadoop.hbase.coprocessor.MultiRowMutationEndpoint;
+import org.apache.hadoop.hbase.regionserver.NoOpScanPolicyObserver;
import org.apache.hadoop.hbase.testclassification.ClientTests;
import org.apache.hadoop.hbase.testclassification.LargeTests;
import org.junit.jupiter.api.BeforeAll;
@@ -41,6 +42,6 @@ public class TestFromClientSide5WithCoprocessor extends FromClientSideTest5 {
@BeforeAll
public static void setUpBeforeClass() throws Exception {
- initialize(MultiRowMutationEndpoint.class);
+ initialize(NoOpScanPolicyObserver.class, MultiRowMutationEndpoint.class);
}
}
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientSide5WithCoprocessor.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientSideCheckAndMutate.java
similarity index 76%
copy from hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientSide5WithCoprocessor.java
copy to hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientSideCheckAndMutate.java
index b7203a0b585..be10e310ddb 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientSide5WithCoprocessor.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientSideCheckAndMutate.java
@@ -24,17 +24,12 @@ import org.apache.hadoop.hbase.testclassification.LargeTests;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Tag;
-/**
- * Run tests that use the HBase clients; {@link Table}. Sets up the HBase mini cluster once at start
- * and runs through all client tests. Each creates a table named for the method and does its stuff
- * against that. Parameterized to run with different registry implementations.
- */
@Tag(LargeTests.TAG)
@Tag(ClientTests.TAG)
@HBaseParameterizedTestTemplate(name = "{index}: registryImpl={0}, numHedgedReqs={1}")
-public class TestFromClientSide5WithCoprocessor extends FromClientSideTest5 {
+public class TestFromClientSideCheckAndMutate extends FromClientSideTestCheckAndMutate {
- public TestFromClientSide5WithCoprocessor(Class<? extends ConnectionRegistry> registryImpl,
+ public TestFromClientSideCheckAndMutate(Class<? extends ConnectionRegistry> registryImpl,
int numHedgedReqs) {
super(registryImpl, numHedgedReqs);
}
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientSide5.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientSideCheckAndMutateWithCoprocessor.java
similarity index 77%
copy from hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientSide5.java
copy to hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientSideCheckAndMutateWithCoprocessor.java
index 4efedafbf2a..965f84b4a66 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientSide5.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientSideCheckAndMutateWithCoprocessor.java
@@ -25,17 +25,14 @@ import org.apache.hadoop.hbase.testclassification.LargeTests;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Tag;
-/**
- * Run tests that use the HBase clients; {@link Table}. Sets up the HBase mini cluster once at start
- * and runs through all client tests. Each creates a table named for the method and does its stuff
- * against that. Parameterized to run with different registry implementations.
- */
@Tag(LargeTests.TAG)
@Tag(ClientTests.TAG)
@HBaseParameterizedTestTemplate(name = "{index}: registryImpl={0}, numHedgedReqs={1}")
-public class TestFromClientSide5 extends FromClientSideTest5 {
+public class TestFromClientSideCheckAndMutateWithCoprocessor
+ extends FromClientSideTestCheckAndMutate {
- public TestFromClientSide5(Class<? extends ConnectionRegistry> registryImpl, int numHedgedReqs) {
+ public TestFromClientSideCheckAndMutateWithCoprocessor(
+ Class<? extends ConnectionRegistry> registryImpl, int numHedgedReqs) {
super(registryImpl, numHedgedReqs);
}
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientSide5WithCoprocessor.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientSideMultiRowMutation.java
similarity index 78%
copy from hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientSide5WithCoprocessor.java
copy to hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientSideMultiRowMutation.java
index b7203a0b585..b94d225ccfa 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientSide5WithCoprocessor.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientSideMultiRowMutation.java
@@ -24,17 +24,12 @@ import org.apache.hadoop.hbase.testclassification.LargeTests;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Tag;
-/**
- * Run tests that use the HBase clients; {@link Table}. Sets up the HBase mini cluster once at start
- * and runs through all client tests. Each creates a table named for the method and does its stuff
- * against that. Parameterized to run with different registry implementations.
- */
@Tag(LargeTests.TAG)
@Tag(ClientTests.TAG)
@HBaseParameterizedTestTemplate(name = "{index}: registryImpl={0}, numHedgedReqs={1}")
-public class TestFromClientSide5WithCoprocessor extends FromClientSideTest5 {
+public class TestFromClientSideMultiRowMutation extends FromClientSideTestMultiRowMutation {
- public TestFromClientSide5WithCoprocessor(Class<? extends ConnectionRegistry> registryImpl,
+ public TestFromClientSideMultiRowMutation(Class<? extends ConnectionRegistry> registryImpl,
int numHedgedReqs) {
super(registryImpl, numHedgedReqs);
}
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientSide5.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientSideMultiRowMutationWithCoprocessor.java
similarity index 77%
copy from hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientSide5.java
copy to hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientSideMultiRowMutationWithCoprocessor.java
index 4efedafbf2a..8a7685e05e3 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientSide5.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientSideMultiRowMutationWithCoprocessor.java
@@ -25,17 +25,14 @@ import org.apache.hadoop.hbase.testclassification.LargeTests;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Tag;
-/**
- * Run tests that use the HBase clients; {@link Table}. Sets up the HBase mini cluster once at start
- * and runs through all client tests. Each creates a table named for the method and does its stuff
- * against that. Parameterized to run with different registry implementations.
- */
@Tag(LargeTests.TAG)
@Tag(ClientTests.TAG)
@HBaseParameterizedTestTemplate(name = "{index}: registryImpl={0}, numHedgedReqs={1}")
-public class TestFromClientSide5 extends FromClientSideTest5 {
+public class TestFromClientSideMultiRowMutationWithCoprocessor
+ extends FromClientSideTestMultiRowMutation {
- public TestFromClientSide5(Class<? extends ConnectionRegistry> registryImpl, int numHedgedReqs) {
+ public TestFromClientSideMultiRowMutationWithCoprocessor(
+ Class<? extends ConnectionRegistry> registryImpl, int numHedgedReqs) {
super(registryImpl, numHedgedReqs);
}
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientSide5WithCoprocessor.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientSideReverseScan.java
similarity index 76%
copy from hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientSide5WithCoprocessor.java
copy to hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientSideReverseScan.java
index b7203a0b585..e4d3c27a178 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientSide5WithCoprocessor.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientSideReverseScan.java
@@ -24,17 +24,12 @@ import org.apache.hadoop.hbase.testclassification.LargeTests;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Tag;
-/**
- * Run tests that use the HBase clients; {@link Table}. Sets up the HBase mini cluster once at start
- * and runs through all client tests. Each creates a table named for the method and does its stuff
- * against that. Parameterized to run with different registry implementations.
- */
@Tag(LargeTests.TAG)
@Tag(ClientTests.TAG)
@HBaseParameterizedTestTemplate(name = "{index}: registryImpl={0}, numHedgedReqs={1}")
-public class TestFromClientSide5WithCoprocessor extends FromClientSideTest5 {
+public class TestFromClientSideReverseScan extends FromClientSideTestReverseScan {
- public TestFromClientSide5WithCoprocessor(Class<? extends ConnectionRegistry> registryImpl,
+ public TestFromClientSideReverseScan(Class<? extends ConnectionRegistry> registryImpl,
int numHedgedReqs) {
super(registryImpl, numHedgedReqs);
}
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientSide5.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientSideReverseScanWithCoprocessor.java
similarity index 77%
copy from hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientSide5.java
copy to hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientSideReverseScanWithCoprocessor.java
index 4efedafbf2a..03c6693f133 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientSide5.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientSideReverseScanWithCoprocessor.java
@@ -25,17 +25,13 @@ import org.apache.hadoop.hbase.testclassification.LargeTests;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Tag;
-/**
- * Run tests that use the HBase clients; {@link Table}. Sets up the HBase mini cluster once at start
- * and runs through all client tests. Each creates a table named for the method and does its stuff
- * against that. Parameterized to run with different registry implementations.
- */
@Tag(LargeTests.TAG)
@Tag(ClientTests.TAG)
@HBaseParameterizedTestTemplate(name = "{index}: registryImpl={0}, numHedgedReqs={1}")
-public class TestFromClientSide5 extends FromClientSideTest5 {
+public class TestFromClientSideReverseScanWithCoprocessor extends FromClientSideTestReverseScan {
- public TestFromClientSide5(Class<? extends ConnectionRegistry> registryImpl, int numHedgedReqs) {
+ public TestFromClientSideReverseScanWithCoprocessor(
+ Class<? extends ConnectionRegistry> registryImpl, int numHedgedReqs) {
super(registryImpl, numHedgedReqs);
}