This is an automated email from the ASF dual-hosted git repository.

junegunn 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 4be0c5ecd49 HBASE-29721 Add validation for Mutations without column 
families (#7469)
4be0c5ecd49 is described below

commit 4be0c5ecd496176e856cc5742461eaad372e71d3
Author: Jaehui Lee <[email protected]>
AuthorDate: Fri Feb 20 14:17:34 2026 +0900

    HBASE-29721 Add validation for Mutations without column families (#7469)
    
    Signed-off-by: Junegunn Choi <[email protected]>
---
 .../hbase/client/AsyncBufferedMutatorImpl.java     |   6 +-
 .../hadoop/hbase/client/ConnectionUtils.java       |  24 ++--
 .../hadoop/hbase/client/RawAsyncTableImpl.java     |  40 +++---
 .../apache/hadoop/hbase/client/TestAsyncTable.java | 135 ++++++++++++++-------
 .../hadoop/hbase/client/TestAsyncTableBatch.java   | 132 +++++++++++++-------
 5 files changed, 215 insertions(+), 122 deletions(-)

diff --git 
a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncBufferedMutatorImpl.java
 
b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncBufferedMutatorImpl.java
index 452318c1ef5..6d41d28c852 100644
--- 
a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncBufferedMutatorImpl.java
+++ 
b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncBufferedMutatorImpl.java
@@ -17,7 +17,7 @@
  */
 package org.apache.hadoop.hbase.client;
 
-import static org.apache.hadoop.hbase.client.ConnectionUtils.validatePut;
+import static org.apache.hadoop.hbase.client.ConnectionUtils.validateMutation;
 import static org.apache.hadoop.hbase.util.FutureUtils.addListener;
 
 import java.io.IOException;
@@ -175,9 +175,7 @@ class AsyncBufferedMutatorImpl implements 
AsyncBufferedMutator {
     long heapSize = 0;
     for (Mutation mutation : mutations) {
       heapSize += mutation.heapSize();
-      if (mutation instanceof Put) {
-        validatePut((Put) mutation, maxKeyValueSize);
-      }
+      validateMutation(mutation, maxKeyValueSize);
     }
     Batch batch = null;
     lock.lock();
diff --git 
a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ConnectionUtils.java
 
b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ConnectionUtils.java
index 40e205ddca8..a9e83ff8eae 100644
--- 
a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ConnectionUtils.java
+++ 
b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ConnectionUtils.java
@@ -480,13 +480,20 @@ public final class ConnectionUtils {
     return future;
   }
 
-  // validate for well-formedness
-  static void validatePut(Put put, int maxKeyValueSize) {
-    if (put.isEmpty()) {
-      throw new IllegalArgumentException("No columns to insert");
+  // Validate individual Mutation
+  static void validateMutation(Mutation mutation, int maxKeyValueSize) {
+    // Skip Delete
+    if (mutation instanceof Delete) return;
+
+    // 1. Check if empty
+    if (mutation.isEmpty()) {
+      throw new IllegalArgumentException(
+        "No columns to " + mutation.getClass().getSimpleName().toLowerCase());
     }
+
+    // 2. Check if size exceeds maxKeyValueSize
     if (maxKeyValueSize > 0) {
-      for (List<Cell> list : put.getFamilyCellMap().values()) {
+      for (List<Cell> list : mutation.getFamilyCellMap().values()) {
         for (Cell cell : list) {
           if (cell.getSerializedSize() > maxKeyValueSize) {
             throw new IllegalArgumentException("KeyValue size too large");
@@ -496,11 +503,10 @@ public final class ConnectionUtils {
     }
   }
 
-  static void validatePutsInRowMutations(RowMutations rowMutations, int 
maxKeyValueSize) {
+  // Validate RowMutations
+  static void validateRowMutations(RowMutations rowMutations, int 
maxKeyValueSize) {
     for (Mutation mutation : rowMutations.getMutations()) {
-      if (mutation instanceof Put) {
-        validatePut((Put) mutation, maxKeyValueSize);
-      }
+      validateMutation(mutation, maxKeyValueSize);
     }
   }
 
diff --git 
a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/RawAsyncTableImpl.java
 
b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/RawAsyncTableImpl.java
index 553b4afa55e..d24f9853825 100644
--- 
a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/RawAsyncTableImpl.java
+++ 
b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/RawAsyncTableImpl.java
@@ -18,11 +18,10 @@
 package org.apache.hadoop.hbase.client;
 
 import static java.util.stream.Collectors.toList;
-import static org.apache.hadoop.hbase.client.ConnectionUtils.checkHasFamilies;
 import static org.apache.hadoop.hbase.client.ConnectionUtils.isEmptyStopRow;
 import static 
org.apache.hadoop.hbase.client.ConnectionUtils.timelineConsistentRead;
-import static org.apache.hadoop.hbase.client.ConnectionUtils.validatePut;
-import static 
org.apache.hadoop.hbase.client.ConnectionUtils.validatePutsInRowMutations;
+import static org.apache.hadoop.hbase.client.ConnectionUtils.validateMutation;
+import static 
org.apache.hadoop.hbase.client.ConnectionUtils.validateRowMutations;
 import static org.apache.hadoop.hbase.trace.TraceUtil.tracedFuture;
 import static org.apache.hadoop.hbase.trace.TraceUtil.tracedFutures;
 import static org.apache.hadoop.hbase.util.FutureUtils.addListener;
@@ -249,7 +248,7 @@ class RawAsyncTableImpl implements 
AsyncTable<AdvancedScanResultConsumer> {
 
   @Override
   public CompletableFuture<Void> put(Put put) {
-    validatePut(put, conn.connConf.getMaxKeyValueSize());
+    validateMutation(put, conn.connConf.getMaxKeyValueSize());
     final Supplier<Span> supplier = 
newTableOperationSpanBuilder().setOperation(put);
     return tracedFuture(() -> this.<Void, Put> newCaller(put, 
writeRpcTimeoutNs)
       .action((controller, loc, stub) -> RawAsyncTableImpl.<Put> 
voidMutate(controller, loc, stub,
@@ -268,7 +267,7 @@ class RawAsyncTableImpl implements 
AsyncTable<AdvancedScanResultConsumer> {
 
   @Override
   public CompletableFuture<Result> append(Append append) {
-    checkHasFamilies(append);
+    validateMutation(append, conn.connConf.getMaxKeyValueSize());
     final Supplier<Span> supplier = 
newTableOperationSpanBuilder().setOperation(append);
     return tracedFuture(() -> {
       long nonceGroup = conn.getNonceGenerator().getNonceGroup();
@@ -283,7 +282,7 @@ class RawAsyncTableImpl implements 
AsyncTable<AdvancedScanResultConsumer> {
 
   @Override
   public CompletableFuture<Result> increment(Increment increment) {
-    checkHasFamilies(increment);
+    validateMutation(increment, conn.connConf.getMaxKeyValueSize());
     final Supplier<Span> supplier = 
newTableOperationSpanBuilder().setOperation(increment);
     return tracedFuture(() -> {
       long nonceGroup = conn.getNonceGenerator().getNonceGroup();
@@ -349,7 +348,7 @@ class RawAsyncTableImpl implements 
AsyncTable<AdvancedScanResultConsumer> {
 
     @Override
     public CompletableFuture<Boolean> thenPut(Put put) {
-      validatePut(put, conn.connConf.getMaxKeyValueSize());
+      validateMutation(put, conn.connConf.getMaxKeyValueSize());
       preCheck();
       final Supplier<Span> supplier = newTableOperationSpanBuilder()
         .setOperation(HBaseSemanticAttributes.Operation.CHECK_AND_MUTATE)
@@ -383,7 +382,7 @@ class RawAsyncTableImpl implements 
AsyncTable<AdvancedScanResultConsumer> {
     @Override
     public CompletableFuture<Boolean> thenMutate(RowMutations mutations) {
       preCheck();
-      validatePutsInRowMutations(mutations, 
conn.connConf.getMaxKeyValueSize());
+      validateRowMutations(mutations, conn.connConf.getMaxKeyValueSize());
       final Supplier<Span> supplier = newTableOperationSpanBuilder()
         .setOperation(HBaseSemanticAttributes.Operation.CHECK_AND_MUTATE)
         .setContainerOperations(mutations);
@@ -425,7 +424,7 @@ class RawAsyncTableImpl implements 
AsyncTable<AdvancedScanResultConsumer> {
 
     @Override
     public CompletableFuture<Boolean> thenPut(Put put) {
-      validatePut(put, conn.connConf.getMaxKeyValueSize());
+      validateMutation(put, conn.connConf.getMaxKeyValueSize());
       final Supplier<Span> supplier = newTableOperationSpanBuilder()
         .setOperation(HBaseSemanticAttributes.Operation.CHECK_AND_MUTATE)
         .setContainerOperations(put);
@@ -456,7 +455,7 @@ class RawAsyncTableImpl implements 
AsyncTable<AdvancedScanResultConsumer> {
 
     @Override
     public CompletableFuture<Boolean> thenMutate(RowMutations mutations) {
-      validatePutsInRowMutations(mutations, 
conn.connConf.getMaxKeyValueSize());
+      validateRowMutations(mutations, conn.connConf.getMaxKeyValueSize());
       final Supplier<Span> supplier = newTableOperationSpanBuilder()
         .setOperation(HBaseSemanticAttributes.Operation.CHECK_AND_MUTATE)
         .setContainerOperations(mutations);
@@ -487,9 +486,7 @@ class RawAsyncTableImpl implements 
AsyncTable<AdvancedScanResultConsumer> {
           || checkAndMutate.getAction() instanceof Append
       ) {
         Mutation mutation = (Mutation) checkAndMutate.getAction();
-        if (mutation instanceof Put) {
-          validatePut((Put) mutation, conn.connConf.getMaxKeyValueSize());
-        }
+        validateMutation(mutation, conn.connConf.getMaxKeyValueSize());
         long nonceGroup = conn.getNonceGenerator().getNonceGroup();
         long nonce = conn.getNonceGenerator().newNonce();
         return RawAsyncTableImpl.this
@@ -506,7 +503,7 @@ class RawAsyncTableImpl implements 
AsyncTable<AdvancedScanResultConsumer> {
           .call();
       } else if (checkAndMutate.getAction() instanceof RowMutations) {
         RowMutations rowMutations = (RowMutations) checkAndMutate.getAction();
-        validatePutsInRowMutations(rowMutations, 
conn.connConf.getMaxKeyValueSize());
+        validateRowMutations(rowMutations, conn.connConf.getMaxKeyValueSize());
         long nonceGroup = conn.getNonceGenerator().getNonceGroup();
         long nonce = conn.getNonceGenerator().newNonce();
         return RawAsyncTableImpl.this
@@ -585,7 +582,7 @@ class RawAsyncTableImpl implements 
AsyncTable<AdvancedScanResultConsumer> {
 
   @Override
   public CompletableFuture<Result> mutateRow(RowMutations mutations) {
-    validatePutsInRowMutations(mutations, conn.connConf.getMaxKeyValueSize());
+    validateRowMutations(mutations, conn.connConf.getMaxKeyValueSize());
     long nonceGroup = conn.getNonceGenerator().getNonceGroup();
     long nonce = conn.getNonceGenerator().newNonce();
     final Supplier<Span> supplier =
@@ -694,18 +691,19 @@ class RawAsyncTableImpl implements 
AsyncTable<AdvancedScanResultConsumer> {
 
   private <T> List<CompletableFuture<T>> batch(List<? extends Row> actions, 
long rpcTimeoutNs) {
     for (Row action : actions) {
-      if (action instanceof Put) {
-        validatePut((Put) action, conn.connConf.getMaxKeyValueSize());
+      if (action instanceof Mutation) {
+        validateMutation((Mutation) action, 
conn.connConf.getMaxKeyValueSize());
       } else if (action instanceof CheckAndMutate) {
         CheckAndMutate checkAndMutate = (CheckAndMutate) action;
-        if (checkAndMutate.getAction() instanceof Put) {
-          validatePut((Put) checkAndMutate.getAction(), 
conn.connConf.getMaxKeyValueSize());
+        if (checkAndMutate.getAction() instanceof Mutation) {
+          validateMutation((Mutation) checkAndMutate.getAction(),
+            conn.connConf.getMaxKeyValueSize());
         } else if (checkAndMutate.getAction() instanceof RowMutations) {
-          validatePutsInRowMutations((RowMutations) checkAndMutate.getAction(),
+          validateRowMutations((RowMutations) checkAndMutate.getAction(),
             conn.connConf.getMaxKeyValueSize());
         }
       } else if (action instanceof RowMutations) {
-        validatePutsInRowMutations((RowMutations) action, 
conn.connConf.getMaxKeyValueSize());
+        validateRowMutations((RowMutations) action, 
conn.connConf.getMaxKeyValueSize());
       }
     }
     return conn.callerFactory.batch().table(tableName).actions(actions)
diff --git 
a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAsyncTable.java 
b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAsyncTable.java
index f5631fd5b0d..3966da78b82 100644
--- 
a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAsyncTable.java
+++ 
b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAsyncTable.java
@@ -39,6 +39,7 @@ import java.util.concurrent.ExecutionException;
 import java.util.concurrent.ForkJoinPool;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicLong;
+import java.util.function.Consumer;
 import java.util.function.Supplier;
 import java.util.stream.IntStream;
 import org.apache.hadoop.hbase.CompareOperator;
@@ -1641,60 +1642,112 @@ public class TestAsyncTable {
   }
 
   @Test
-  public void testInvalidPut() {
-    try {
-      getTable.get().put(new Put(Bytes.toBytes(0)));
-      fail("Should fail since the put does not contain any cells");
-    } catch (IllegalArgumentException e) {
-      assertThat(e.getMessage(), containsString("No columns to insert"));
-    }
+  public void testInvalidMutation() throws Exception {
+    Consumer<Mutation> executeMutation = mutation -> {
+      if (mutation instanceof Put) {
+        getTable.get().put((Put) mutation);
+      } else if (mutation instanceof Increment) {
+        getTable.get().increment((Increment) mutation);
+      } else if (mutation instanceof Append) {
+        getTable.get().append((Append) mutation);
+      }
+    };
 
-    try {
-      getTable.get()
-        .put(new Put(Bytes.toBytes(0)).addColumn(FAMILY, QUALIFIER, new 
byte[MAX_KEY_VALUE_SIZE]));
-      fail("Should fail since the put exceeds the max key value size");
-    } catch (IllegalArgumentException e) {
-      assertThat(e.getMessage(), containsString("KeyValue size too large"));
+    Mutation[] emptyMutations =
+      { new Put(Bytes.toBytes(0)), new Increment(Bytes.toBytes(0)), new 
Append(Bytes.toBytes(0)) };
+
+    String[] emptyMessages =
+      { "No columns to put", "No columns to increment", "No columns to append" 
};
+
+    Mutation[] oversizedMutations =
+      { new Put(Bytes.toBytes(0)).addColumn(FAMILY, QUALIFIER, new 
byte[MAX_KEY_VALUE_SIZE]),
+        new Increment(Bytes.toBytes(0)).addColumn(FAMILY, new 
byte[MAX_KEY_VALUE_SIZE], 1),
+        new Append(Bytes.toBytes(0)).addColumn(FAMILY, QUALIFIER, new 
byte[MAX_KEY_VALUE_SIZE]) };
+
+    for (int i = 0; i < emptyMutations.length; i++) {
+      // Test empty mutation
+      try {
+        executeMutation.accept(emptyMutations[i]);
+        fail("Should fail since the mutation does not contain any cells");
+      } catch (IllegalArgumentException e) {
+        assertThat(e.getMessage(), containsString(emptyMessages[i]));
+      }
+
+      // Test oversized mutation
+      try {
+        executeMutation.accept(oversizedMutations[i]);
+        fail("Should fail since the mutation exceeds the max key value size");
+      } catch (IllegalArgumentException e) {
+        assertThat(e.getMessage(), containsString("KeyValue size too large"));
+      }
     }
   }
 
   @Test
-  public void testInvalidPutInRowMutations() throws IOException {
+  public void testInvalidMutationInRowMutations() throws IOException {
     final byte[] row = Bytes.toBytes(0);
-    try {
-      getTable.get().mutateRow(new RowMutations(row).add(new Put(row)));
-      fail("Should fail since the put does not contain any cells");
-    } catch (IllegalArgumentException e) {
-      assertThat(e.getMessage(), containsString("No columns to insert"));
-    }
 
-    try {
-      getTable.get().mutateRow(new RowMutations(row)
-        .add(new Put(row).addColumn(FAMILY, QUALIFIER, new 
byte[MAX_KEY_VALUE_SIZE])));
-      fail("Should fail since the put exceeds the max key value size");
-    } catch (IllegalArgumentException e) {
-      assertThat(e.getMessage(), containsString("KeyValue size too large"));
+    Mutation[] emptyMutations = { new Put(row), new Increment(row), new 
Append(row) };
+
+    String[] emptyMessages =
+      { "No columns to put", "No columns to increment", "No columns to append" 
};
+
+    Mutation[] oversizedMutations =
+      { new Put(row).addColumn(FAMILY, QUALIFIER, new 
byte[MAX_KEY_VALUE_SIZE]),
+        new Increment(row).addColumn(FAMILY, new byte[MAX_KEY_VALUE_SIZE], 1),
+        new Append(row).addColumn(FAMILY, QUALIFIER, new 
byte[MAX_KEY_VALUE_SIZE]) };
+
+    for (int i = 0; i < emptyMutations.length; i++) {
+      // Test empty mutation
+      try {
+        getTable.get().mutateRow(new RowMutations(row).add(emptyMutations[i]));
+        fail("Should fail since the mutation does not contain any cells");
+      } catch (IllegalArgumentException e) {
+        assertThat(e.getMessage(), containsString(emptyMessages[i]));
+      }
+
+      // Test oversized mutation
+      try {
+        getTable.get().mutateRow(new 
RowMutations(row).add(oversizedMutations[i]));
+        fail("Should fail since the mutation exceeds the max key value size");
+      } catch (IllegalArgumentException e) {
+        assertThat(e.getMessage(), containsString("KeyValue size too large"));
+      }
     }
   }
 
   @Test
-  public void testInvalidPutInRowMutationsInCheckAndMutate() throws 
IOException {
+  public void testInvalidMutationInRowMutationsInCheckAndMutate() throws 
IOException {
     final byte[] row = Bytes.toBytes(0);
-    try {
-      
getTable.get().checkAndMutate(CheckAndMutate.newBuilder(row).ifNotExists(FAMILY,
 QUALIFIER)
-        .build(new RowMutations(row).add(new Put(row))));
-      fail("Should fail since the put does not contain any cells");
-    } catch (IllegalArgumentException e) {
-      assertThat(e.getMessage(), containsString("No columns to insert"));
-    }
 
-    try {
-      getTable.get().checkAndMutate(
-        CheckAndMutate.newBuilder(row).ifNotExists(FAMILY, 
QUALIFIER).build(new RowMutations(row)
-          .add(new Put(row).addColumn(FAMILY, QUALIFIER, new 
byte[MAX_KEY_VALUE_SIZE]))));
-      fail("Should fail since the put exceeds the max key value size");
-    } catch (IllegalArgumentException e) {
-      assertThat(e.getMessage(), containsString("KeyValue size too large"));
+    Mutation[] emptyMutations = { new Put(row), new Increment(row), new 
Append(row) };
+
+    String[] emptyMessages =
+      { "No columns to put", "No columns to increment", "No columns to append" 
};
+
+    Mutation[] oversizedMutations =
+      { new Put(row).addColumn(FAMILY, QUALIFIER, new 
byte[MAX_KEY_VALUE_SIZE]),
+        new Increment(row).addColumn(FAMILY, new byte[MAX_KEY_VALUE_SIZE], 1),
+        new Append(row).addColumn(FAMILY, QUALIFIER, new 
byte[MAX_KEY_VALUE_SIZE]) };
+
+    for (int i = 0; i < emptyMutations.length; i++) {
+      // Test empty mutation
+      try {
+        
getTable.get().checkAndMutate(CheckAndMutate.newBuilder(row).ifNotExists(FAMILY,
 QUALIFIER)
+          .build(new RowMutations(row).add(emptyMutations[i])));
+        fail("Should fail since the mutation does not contain any cells");
+      } catch (IllegalArgumentException e) {
+        assertThat(e.getMessage(), containsString(emptyMessages[i]));
+      }
+
+      // Test oversized mutation
+      try {
+        
getTable.get().checkAndMutate(CheckAndMutate.newBuilder(row).ifNotExists(FAMILY,
 QUALIFIER)
+          .build(new RowMutations(row).add(oversizedMutations[i])));
+        fail("Should fail since the mutation exceeds the max key value size");
+      } catch (IllegalArgumentException e) {
+        assertThat(e.getMessage(), containsString("KeyValue size too large"));
+      }
     }
   }
 }
diff --git 
a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAsyncTableBatch.java
 
b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAsyncTableBatch.java
index e7ce9fa3405..86c39153f60 100644
--- 
a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAsyncTableBatch.java
+++ 
b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAsyncTableBatch.java
@@ -317,69 +317,107 @@ public class TestAsyncTableBatch {
   }
 
   @Test
-  public void testInvalidPut() {
+  public void testInvalidMutation() {
     AsyncTable<?> table = tableGetter.apply(TABLE_NAME);
-    try {
-      table.batch(Arrays.asList(new Delete(Bytes.toBytes(0)), new 
Put(Bytes.toBytes(0))));
-      fail("Should fail since the put does not contain any cells");
-    } catch (IllegalArgumentException e) {
-      assertThat(e.getMessage(), containsString("No columns to insert"));
-    }
 
-    try {
-      table.batch(
-        Arrays.asList(new Put(Bytes.toBytes(0)).addColumn(FAMILY, CQ, new 
byte[MAX_KEY_VALUE_SIZE]),
-          new Delete(Bytes.toBytes(0))));
-      fail("Should fail since the put exceeds the max key value size");
-    } catch (IllegalArgumentException e) {
-      assertThat(e.getMessage(), containsString("KeyValue size too large"));
+    Mutation[] emptyMutations =
+      { new Put(Bytes.toBytes(0)), new Increment(Bytes.toBytes(0)), new 
Append(Bytes.toBytes(0)) };
+
+    String[] emptyMessages =
+      { "No columns to put", "No columns to increment", "No columns to append" 
};
+
+    Mutation[] oversizedMutations =
+      { new Put(Bytes.toBytes(0)).addColumn(FAMILY, CQ, new 
byte[MAX_KEY_VALUE_SIZE]),
+        new Increment(Bytes.toBytes(0)).addColumn(FAMILY, new 
byte[MAX_KEY_VALUE_SIZE], 1),
+        new Append(Bytes.toBytes(0)).addColumn(FAMILY, CQ, new 
byte[MAX_KEY_VALUE_SIZE]) };
+
+    for (int i = 0; i < emptyMutations.length; i++) {
+      // Test empty mutation
+      try {
+        table.batch(Arrays.asList(new Delete(Bytes.toBytes(0)), 
emptyMutations[i]));
+        fail("Should fail since the mutation does not contain any cells");
+      } catch (IllegalArgumentException e) {
+        assertThat(e.getMessage(), containsString(emptyMessages[i]));
+      }
+
+      // Test oversized mutation
+      try {
+        table.batch(Arrays.asList(oversizedMutations[i], new 
Delete(Bytes.toBytes(0))));
+        fail("Should fail since the mutation exceeds the max key value size");
+      } catch (IllegalArgumentException e) {
+        assertThat(e.getMessage(), containsString("KeyValue size too large"));
+      }
     }
   }
 
   @Test
-  public void testInvalidPutInRowMutations() throws IOException {
+  public void testInvalidMutationInRowMutations() throws IOException {
     final byte[] row = Bytes.toBytes(0);
-
     AsyncTable<?> table = tableGetter.apply(TABLE_NAME);
-    try {
-      table.batch(Arrays.asList(new Delete(row), new RowMutations(row).add(new 
Put(row))));
-      fail("Should fail since the put does not contain any cells");
-    } catch (IllegalArgumentException e) {
-      assertThat(e.getMessage(), containsString("No columns to insert"));
-    }
 
-    try {
-      table.batch(Arrays.asList(
-        new RowMutations(row).add(new Put(row).addColumn(FAMILY, CQ, new 
byte[MAX_KEY_VALUE_SIZE])),
-        new Delete(row)));
-      fail("Should fail since the put exceeds the max key value size");
-    } catch (IllegalArgumentException e) {
-      assertThat(e.getMessage(), containsString("KeyValue size too large"));
+    Mutation[] emptyMutations = { new Put(row), new Increment(row), new 
Append(row) };
+
+    String[] emptyMessages =
+      { "No columns to put", "No columns to increment", "No columns to append" 
};
+
+    Mutation[] oversizedMutations =
+      { new Put(row).addColumn(FAMILY, CQ, new byte[MAX_KEY_VALUE_SIZE]),
+        new Increment(row).addColumn(FAMILY, new byte[MAX_KEY_VALUE_SIZE], 1),
+        new Append(row).addColumn(FAMILY, CQ, new byte[MAX_KEY_VALUE_SIZE]) };
+
+    for (int i = 0; i < emptyMutations.length; i++) {
+      // Test empty mutation
+      try {
+        table.batch(Arrays.asList(new Delete(row), new 
RowMutations(row).add(emptyMutations[i])));
+        fail("Should fail since the mutation does not contain any cells");
+      } catch (IllegalArgumentException e) {
+        assertThat(e.getMessage(), containsString(emptyMessages[i]));
+      }
+
+      // Test oversized mutation
+      try {
+        table
+          .batch(Arrays.asList(new 
RowMutations(row).add(oversizedMutations[i]), new Delete(row)));
+        fail("Should fail since the mutation exceeds the max key value size");
+      } catch (IllegalArgumentException e) {
+        assertThat(e.getMessage(), containsString("KeyValue size too large"));
+      }
     }
   }
 
   @Test
-  public void testInvalidPutInRowMutationsInCheckAndMutate() throws 
IOException {
+  public void testInvalidMutationInRowMutationsInCheckAndMutate() throws 
IOException {
     final byte[] row = Bytes.toBytes(0);
-
     AsyncTable<?> table = tableGetter.apply(TABLE_NAME);
-    try {
-      table.batch(Arrays.asList(new Delete(row), CheckAndMutate.newBuilder(row)
-        .ifNotExists(FAMILY, CQ).build(new RowMutations(row).add(new 
Put(row)))));
-      fail("Should fail since the put does not contain any cells");
-    } catch (IllegalArgumentException e) {
-      assertThat(e.getMessage(), containsString("No columns to insert"));
-    }
 
-    try {
-      table.batch(Arrays.asList(
-        CheckAndMutate.newBuilder(row).ifNotExists(FAMILY, CQ)
-          .build(new RowMutations(row)
-            .add(new Put(row).addColumn(FAMILY, CQ, new 
byte[MAX_KEY_VALUE_SIZE]))),
-        new Delete(row)));
-      fail("Should fail since the put exceeds the max key value size");
-    } catch (IllegalArgumentException e) {
-      assertThat(e.getMessage(), containsString("KeyValue size too large"));
+    Mutation[] emptyMutations = { new Put(row), new Increment(row), new 
Append(row) };
+
+    String[] emptyMessages =
+      { "No columns to put", "No columns to increment", "No columns to append" 
};
+
+    Mutation[] oversizedMutations =
+      { new Put(row).addColumn(FAMILY, CQ, new byte[MAX_KEY_VALUE_SIZE]),
+        new Increment(row).addColumn(FAMILY, new byte[MAX_KEY_VALUE_SIZE], 1),
+        new Append(row).addColumn(FAMILY, CQ, new byte[MAX_KEY_VALUE_SIZE]) };
+
+    for (int i = 0; i < emptyMutations.length; i++) {
+      // Test empty mutation
+      try {
+        table.batch(Arrays.asList(new Delete(row), 
CheckAndMutate.newBuilder(row)
+          .ifNotExists(FAMILY, CQ).build(new 
RowMutations(row).add(emptyMutations[i]))));
+        fail("Should fail since the mutation does not contain any cells");
+      } catch (IllegalArgumentException e) {
+        assertThat(e.getMessage(), containsString(emptyMessages[i]));
+      }
+
+      // Test oversized mutation
+      try {
+        
table.batch(Arrays.asList(CheckAndMutate.newBuilder(row).ifNotExists(FAMILY, CQ)
+          .build(new RowMutations(row).add(oversizedMutations[i])), new 
Delete(row)));
+        fail("Should fail since the mutation exceeds the max key value size");
+      } catch (IllegalArgumentException e) {
+        assertThat(e.getMessage(), containsString("KeyValue size too large"));
+      }
     }
   }
 

Reply via email to