001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.client; 019 020import static org.hamcrest.CoreMatchers.containsString; 021import static org.hamcrest.CoreMatchers.instanceOf; 022import static org.hamcrest.MatcherAssert.assertThat; 023import static org.junit.Assert.assertArrayEquals; 024import static org.junit.Assert.assertEquals; 025import static org.junit.Assert.assertFalse; 026import static org.junit.Assert.assertNull; 027import static org.junit.Assert.assertTrue; 028import static org.junit.Assert.fail; 029 030import java.io.IOException; 031import java.io.UncheckedIOException; 032import java.util.ArrayList; 033import java.util.Arrays; 034import java.util.List; 035import java.util.Optional; 036import java.util.concurrent.CompletableFuture; 037import java.util.concurrent.ExecutionException; 038import java.util.concurrent.ForkJoinPool; 039import java.util.concurrent.Future; 040import java.util.concurrent.TimeUnit; 041import java.util.concurrent.TimeoutException; 042import java.util.function.Function; 043import java.util.stream.Collectors; 044import java.util.stream.IntStream; 045import org.apache.hadoop.hbase.Cell; 046import org.apache.hadoop.hbase.HBaseClassTestRule; 047import org.apache.hadoop.hbase.HBaseTestingUtil; 048import org.apache.hadoop.hbase.TableName; 049import org.apache.hadoop.hbase.coprocessor.ObserverContext; 050import org.apache.hadoop.hbase.coprocessor.RegionCoprocessor; 051import org.apache.hadoop.hbase.coprocessor.RegionCoprocessorEnvironment; 052import org.apache.hadoop.hbase.coprocessor.RegionObserver; 053import org.apache.hadoop.hbase.regionserver.NoSuchColumnFamilyException; 054import org.apache.hadoop.hbase.testclassification.ClientTests; 055import org.apache.hadoop.hbase.testclassification.LargeTests; 056import org.apache.hadoop.hbase.util.Bytes; 057import org.junit.After; 058import org.junit.AfterClass; 059import org.junit.Before; 060import org.junit.BeforeClass; 061import org.junit.ClassRule; 062import org.junit.Test; 063import org.junit.experimental.categories.Category; 064import org.junit.runner.RunWith; 065import org.junit.runners.Parameterized; 066import org.junit.runners.Parameterized.Parameter; 067import org.junit.runners.Parameterized.Parameters; 068 069@RunWith(Parameterized.class) 070@Category({ LargeTests.class, ClientTests.class }) 071public class TestAsyncTableBatch { 072 073 @ClassRule 074 public static final HBaseClassTestRule CLASS_RULE = 075 HBaseClassTestRule.forClass(TestAsyncTableBatch.class); 076 077 private static final HBaseTestingUtil TEST_UTIL = new HBaseTestingUtil(); 078 079 private static TableName TABLE_NAME = TableName.valueOf("async"); 080 081 private static byte[] FAMILY = Bytes.toBytes("cf"); 082 083 private static byte[] CQ = Bytes.toBytes("cq"); 084 private static byte[] CQ1 = Bytes.toBytes("cq1"); 085 086 private static int COUNT = 1000; 087 088 private static AsyncConnection CONN; 089 090 private static byte[][] SPLIT_KEYS; 091 092 private static int MAX_KEY_VALUE_SIZE = 64 * 1024; 093 094 @Parameter(0) 095 public String tableType; 096 097 @Parameter(1) 098 public Function<TableName, AsyncTable<?>> tableGetter; 099 100 private static AsyncTable<?> getRawTable(TableName tableName) { 101 return CONN.getTable(tableName); 102 } 103 104 private static AsyncTable<?> getTable(TableName tableName) { 105 return CONN.getTable(tableName, ForkJoinPool.commonPool()); 106 } 107 108 @Parameters(name = "{index}: type={0}") 109 public static List<Object[]> params() { 110 Function<TableName, AsyncTable<?>> rawTableGetter = TestAsyncTableBatch::getRawTable; 111 Function<TableName, AsyncTable<?>> tableGetter = TestAsyncTableBatch::getTable; 112 return Arrays.asList(new Object[] { "raw", rawTableGetter }, 113 new Object[] { "normal", tableGetter }); 114 } 115 116 @BeforeClass 117 public static void setUp() throws Exception { 118 TEST_UTIL.getConfiguration().setInt(ConnectionConfiguration.MAX_KEYVALUE_SIZE_KEY, 119 MAX_KEY_VALUE_SIZE); 120 TEST_UTIL.startMiniCluster(3); 121 SPLIT_KEYS = new byte[8][]; 122 for (int i = 111; i < 999; i += 111) { 123 SPLIT_KEYS[i / 111 - 1] = Bytes.toBytes(String.format("%03d", i)); 124 } 125 CONN = ConnectionFactory.createAsyncConnection(TEST_UTIL.getConfiguration()).get(); 126 } 127 128 @AfterClass 129 public static void tearDown() throws Exception { 130 CONN.close(); 131 TEST_UTIL.shutdownMiniCluster(); 132 } 133 134 @Before 135 public void setUpBeforeTest() throws IOException, InterruptedException { 136 TEST_UTIL.createTable(TABLE_NAME, FAMILY, SPLIT_KEYS); 137 TEST_UTIL.waitTableAvailable(TABLE_NAME); 138 } 139 140 @After 141 public void tearDownAfterTest() throws IOException { 142 Admin admin = TEST_UTIL.getAdmin(); 143 if (admin.isTableEnabled(TABLE_NAME)) { 144 admin.disableTable(TABLE_NAME); 145 } 146 admin.deleteTable(TABLE_NAME); 147 } 148 149 private byte[] getRow(int i) { 150 return Bytes.toBytes(String.format("%03d", i)); 151 } 152 153 @Test 154 public void test() 155 throws InterruptedException, ExecutionException, IOException, TimeoutException { 156 AsyncTable<?> table = tableGetter.apply(TABLE_NAME); 157 table.putAll(IntStream.range(0, COUNT) 158 .mapToObj(i -> new Put(getRow(i)).addColumn(FAMILY, CQ, Bytes.toBytes(i))) 159 .collect(Collectors.toList())).get(); 160 List<Result> results = table.getAll(IntStream.range(0, COUNT) 161 .mapToObj(i -> Arrays.asList(new Get(getRow(i)), new Get(Arrays.copyOf(getRow(i), 4)))) 162 .flatMap(l -> l.stream()).collect(Collectors.toList())).get(); 163 assertEquals(2 * COUNT, results.size()); 164 for (int i = 0; i < COUNT; i++) { 165 assertEquals(i, Bytes.toInt(results.get(2 * i).getValue(FAMILY, CQ))); 166 assertTrue(results.get(2 * i + 1).isEmpty()); 167 } 168 Admin admin = TEST_UTIL.getAdmin(); 169 admin.flush(TABLE_NAME); 170 List<Future<?>> splitFutures = 171 TEST_UTIL.getHBaseCluster().getRegions(TABLE_NAME).stream().map(r -> { 172 byte[] startKey = r.getRegionInfo().getStartKey(); 173 int number = startKey.length == 0 ? 55 : Integer.parseInt(Bytes.toString(startKey)); 174 byte[] splitPoint = Bytes.toBytes(String.format("%03d", number + 55)); 175 try { 176 return admin.splitRegionAsync(r.getRegionInfo().getRegionName(), splitPoint); 177 } catch (IOException e) { 178 throw new UncheckedIOException(e); 179 } 180 }).collect(Collectors.toList()); 181 for (Future<?> future : splitFutures) { 182 future.get(30, TimeUnit.SECONDS); 183 } 184 table 185 .deleteAll( 186 IntStream.range(0, COUNT).mapToObj(i -> new Delete(getRow(i))).collect(Collectors.toList())) 187 .get(); 188 results = table 189 .getAll( 190 IntStream.range(0, COUNT).mapToObj(i -> new Get(getRow(i))).collect(Collectors.toList())) 191 .get(); 192 assertEquals(COUNT, results.size()); 193 results.forEach(r -> assertTrue(r.isEmpty())); 194 } 195 196 @Test 197 public void testWithRegionServerFailover() throws Exception { 198 AsyncTable<?> table = tableGetter.apply(TABLE_NAME); 199 table.putAll(IntStream.range(0, COUNT) 200 .mapToObj(i -> new Put(getRow(i)).addColumn(FAMILY, CQ, Bytes.toBytes(i))) 201 .collect(Collectors.toList())).get(); 202 TEST_UTIL.getMiniHBaseCluster().getRegionServer(0).abort("Aborting for tests"); 203 Thread.sleep(100); 204 table.putAll(IntStream.range(COUNT, 2 * COUNT) 205 .mapToObj(i -> new Put(getRow(i)).addColumn(FAMILY, CQ, Bytes.toBytes(i))) 206 .collect(Collectors.toList())).get(); 207 List<Result> results = table.getAll( 208 IntStream.range(0, 2 * COUNT).mapToObj(i -> new Get(getRow(i))).collect(Collectors.toList())) 209 .get(); 210 assertEquals(2 * COUNT, results.size()); 211 results.forEach(r -> assertFalse(r.isEmpty())); 212 table.deleteAll(IntStream.range(0, 2 * COUNT).mapToObj(i -> new Delete(getRow(i))) 213 .collect(Collectors.toList())).get(); 214 results = table.getAll( 215 IntStream.range(0, 2 * COUNT).mapToObj(i -> new Get(getRow(i))).collect(Collectors.toList())) 216 .get(); 217 assertEquals(2 * COUNT, results.size()); 218 results.forEach(r -> assertTrue(r.isEmpty())); 219 } 220 221 @Test 222 public void testMixed() throws InterruptedException, ExecutionException, IOException { 223 AsyncTable<?> table = tableGetter.apply(TABLE_NAME); 224 table.putAll(IntStream.range(0, 7) 225 .mapToObj(i -> new Put(Bytes.toBytes(i)).addColumn(FAMILY, CQ, Bytes.toBytes((long) i))) 226 .collect(Collectors.toList())).get(); 227 List<Row> actions = new ArrayList<>(); 228 actions.add(new Get(Bytes.toBytes(0))); 229 actions.add(new Put(Bytes.toBytes(1)).addColumn(FAMILY, CQ, Bytes.toBytes(2L))); 230 actions.add(new Delete(Bytes.toBytes(2))); 231 actions.add(new Increment(Bytes.toBytes(3)).addColumn(FAMILY, CQ, 1)); 232 actions.add(new Append(Bytes.toBytes(4)).addColumn(FAMILY, CQ, Bytes.toBytes(4))); 233 RowMutations rm = new RowMutations(Bytes.toBytes(5)); 234 rm.add((Mutation) new Put(Bytes.toBytes(5)).addColumn(FAMILY, CQ, Bytes.toBytes(100L))); 235 rm.add((Mutation) new Put(Bytes.toBytes(5)).addColumn(FAMILY, CQ1, Bytes.toBytes(200L))); 236 actions.add(rm); 237 actions.add(new Get(Bytes.toBytes(6))); 238 239 List<Object> results = table.batchAll(actions).get(); 240 assertEquals(7, results.size()); 241 Result getResult = (Result) results.get(0); 242 assertEquals(0, Bytes.toLong(getResult.getValue(FAMILY, CQ))); 243 assertEquals(2, Bytes.toLong(table.get(new Get(Bytes.toBytes(1))).get().getValue(FAMILY, CQ))); 244 assertTrue(table.get(new Get(Bytes.toBytes(2))).get().isEmpty()); 245 Result incrementResult = (Result) results.get(3); 246 assertEquals(4, Bytes.toLong(incrementResult.getValue(FAMILY, CQ))); 247 Result appendResult = (Result) results.get(4); 248 byte[] appendValue = appendResult.getValue(FAMILY, CQ); 249 assertEquals(12, appendValue.length); 250 assertEquals(4, Bytes.toLong(appendValue)); 251 assertEquals(4, Bytes.toInt(appendValue, 8)); 252 assertEquals(100, 253 Bytes.toLong(table.get(new Get(Bytes.toBytes(5))).get().getValue(FAMILY, CQ))); 254 assertEquals(200, 255 Bytes.toLong(table.get(new Get(Bytes.toBytes(5))).get().getValue(FAMILY, CQ1))); 256 getResult = (Result) results.get(6); 257 assertEquals(6, Bytes.toLong(getResult.getValue(FAMILY, CQ))); 258 } 259 260 public static final class ErrorInjectObserver implements RegionCoprocessor, RegionObserver { 261 262 @Override 263 public Optional<RegionObserver> getRegionObserver() { 264 return Optional.of(this); 265 } 266 267 @Override 268 public void preGetOp(ObserverContext<? extends RegionCoprocessorEnvironment> e, Get get, 269 List<Cell> results) throws IOException { 270 if (e.getEnvironment().getRegionInfo().getEndKey().length == 0) { 271 throw new DoNotRetryRegionException("Inject Error"); 272 } 273 } 274 } 275 276 @Test 277 public void testPartialSuccess() throws IOException, InterruptedException, ExecutionException { 278 Admin admin = TEST_UTIL.getAdmin(); 279 TableDescriptor htd = TableDescriptorBuilder.newBuilder(admin.getDescriptor(TABLE_NAME)) 280 .setCoprocessor(ErrorInjectObserver.class.getName()).build(); 281 admin.modifyTable(htd); 282 AsyncTable<?> table = tableGetter.apply(TABLE_NAME); 283 table.putAll(Arrays.asList(SPLIT_KEYS).stream().map(k -> new Put(k).addColumn(FAMILY, CQ, k)) 284 .collect(Collectors.toList())).get(); 285 List<CompletableFuture<Result>> futures = table 286 .get(Arrays.asList(SPLIT_KEYS).stream().map(k -> new Get(k)).collect(Collectors.toList())); 287 for (int i = 0; i < SPLIT_KEYS.length - 1; i++) { 288 assertArrayEquals(SPLIT_KEYS[i], futures.get(i).get().getValue(FAMILY, CQ)); 289 } 290 try { 291 futures.get(SPLIT_KEYS.length - 1).get(); 292 fail(); 293 } catch (ExecutionException e) { 294 assertThat(e.getCause(), instanceOf(RetriesExhaustedException.class)); 295 } 296 } 297 298 @Test 299 public void testPartialSuccessOnSameRegion() throws InterruptedException, ExecutionException { 300 AsyncTable<?> table = tableGetter.apply(TABLE_NAME); 301 List<CompletableFuture<Object>> futures = table.batch(Arrays.asList( 302 new Put(Bytes.toBytes("put")).addColumn(Bytes.toBytes("not-exists"), CQ, 303 Bytes.toBytes("bad")), 304 new Increment(Bytes.toBytes("inc")).addColumn(FAMILY, CQ, 1), 305 new Put(Bytes.toBytes("put")).addColumn(FAMILY, CQ, Bytes.toBytes("good")))); 306 try { 307 futures.get(0).get(); 308 fail(); 309 } catch (ExecutionException e) { 310 assertThat(e.getCause(), instanceOf(RetriesExhaustedException.class)); 311 assertThat(e.getCause().getCause(), instanceOf(NoSuchColumnFamilyException.class)); 312 } 313 assertEquals(1, Bytes.toLong(((Result) futures.get(1).get()).getValue(FAMILY, CQ))); 314 assertTrue(((Result) futures.get(2).get()).isEmpty()); 315 assertEquals("good", 316 Bytes.toString(table.get(new Get(Bytes.toBytes("put"))).get().getValue(FAMILY, CQ))); 317 } 318 319 @Test 320 public void testInvalidPut() { 321 AsyncTable<?> table = tableGetter.apply(TABLE_NAME); 322 try { 323 table.batch(Arrays.asList(new Delete(Bytes.toBytes(0)), new Put(Bytes.toBytes(0)))); 324 fail("Should fail since the put does not contain any cells"); 325 } catch (IllegalArgumentException e) { 326 assertThat(e.getMessage(), containsString("No columns to insert")); 327 } 328 329 try { 330 table.batch( 331 Arrays.asList(new Put(Bytes.toBytes(0)).addColumn(FAMILY, CQ, new byte[MAX_KEY_VALUE_SIZE]), 332 new Delete(Bytes.toBytes(0)))); 333 fail("Should fail since the put exceeds the max key value size"); 334 } catch (IllegalArgumentException e) { 335 assertThat(e.getMessage(), containsString("KeyValue size too large")); 336 } 337 } 338 339 @Test 340 public void testInvalidPutInRowMutations() throws IOException { 341 final byte[] row = Bytes.toBytes(0); 342 343 AsyncTable<?> table = tableGetter.apply(TABLE_NAME); 344 try { 345 table.batch(Arrays.asList(new Delete(row), new RowMutations(row).add(new Put(row)))); 346 fail("Should fail since the put does not contain any cells"); 347 } catch (IllegalArgumentException e) { 348 assertThat(e.getMessage(), containsString("No columns to insert")); 349 } 350 351 try { 352 table.batch(Arrays.asList( 353 new RowMutations(row).add(new Put(row).addColumn(FAMILY, CQ, new byte[MAX_KEY_VALUE_SIZE])), 354 new Delete(row))); 355 fail("Should fail since the put exceeds the max key value size"); 356 } catch (IllegalArgumentException e) { 357 assertThat(e.getMessage(), containsString("KeyValue size too large")); 358 } 359 } 360 361 @Test 362 public void testInvalidPutInRowMutationsInCheckAndMutate() throws IOException { 363 final byte[] row = Bytes.toBytes(0); 364 365 AsyncTable<?> table = tableGetter.apply(TABLE_NAME); 366 try { 367 table.batch(Arrays.asList(new Delete(row), CheckAndMutate.newBuilder(row) 368 .ifNotExists(FAMILY, CQ).build(new RowMutations(row).add(new Put(row))))); 369 fail("Should fail since the put does not contain any cells"); 370 } catch (IllegalArgumentException e) { 371 assertThat(e.getMessage(), containsString("No columns to insert")); 372 } 373 374 try { 375 table.batch(Arrays.asList( 376 CheckAndMutate.newBuilder(row).ifNotExists(FAMILY, CQ) 377 .build(new RowMutations(row) 378 .add(new Put(row).addColumn(FAMILY, CQ, new byte[MAX_KEY_VALUE_SIZE]))), 379 new Delete(row))); 380 fail("Should fail since the put exceeds the max key value size"); 381 } catch (IllegalArgumentException e) { 382 assertThat(e.getMessage(), containsString("KeyValue size too large")); 383 } 384 } 385 386 @Test 387 public void testWithCheckAndMutate() throws Exception { 388 AsyncTable<?> table = tableGetter.apply(TABLE_NAME); 389 390 byte[] row1 = Bytes.toBytes("row1"); 391 byte[] row2 = Bytes.toBytes("row2"); 392 byte[] row3 = Bytes.toBytes("row3"); 393 byte[] row4 = Bytes.toBytes("row4"); 394 byte[] row5 = Bytes.toBytes("row5"); 395 byte[] row6 = Bytes.toBytes("row6"); 396 byte[] row7 = Bytes.toBytes("row7"); 397 398 table 399 .putAll(Arrays.asList(new Put(row1).addColumn(FAMILY, Bytes.toBytes("A"), Bytes.toBytes("a")), 400 new Put(row2).addColumn(FAMILY, Bytes.toBytes("B"), Bytes.toBytes("b")), 401 new Put(row3).addColumn(FAMILY, Bytes.toBytes("C"), Bytes.toBytes("c")), 402 new Put(row4).addColumn(FAMILY, Bytes.toBytes("D"), Bytes.toBytes("d")), 403 new Put(row5).addColumn(FAMILY, Bytes.toBytes("E"), Bytes.toBytes("e")), 404 new Put(row6).addColumn(FAMILY, Bytes.toBytes("F"), Bytes.toBytes(10L)), 405 new Put(row7).addColumn(FAMILY, Bytes.toBytes("G"), Bytes.toBytes("g")))) 406 .get(); 407 408 CheckAndMutate checkAndMutate1 = 409 CheckAndMutate.newBuilder(row1).ifEquals(FAMILY, Bytes.toBytes("A"), Bytes.toBytes("a")) 410 .build(new RowMutations(row1) 411 .add(new Put(row1).addColumn(FAMILY, Bytes.toBytes("B"), Bytes.toBytes("g"))) 412 .add(new Delete(row1).addColumns(FAMILY, Bytes.toBytes("A"))) 413 .add(new Increment(row1).addColumn(FAMILY, Bytes.toBytes("C"), 3L)) 414 .add(new Append(row1).addColumn(FAMILY, Bytes.toBytes("D"), Bytes.toBytes("d")))); 415 Get get = new Get(row2).addColumn(FAMILY, Bytes.toBytes("B")); 416 RowMutations mutations = 417 new RowMutations(row3).add(new Delete(row3).addColumns(FAMILY, Bytes.toBytes("C"))) 418 .add(new Put(row3).addColumn(FAMILY, Bytes.toBytes("F"), Bytes.toBytes("f"))) 419 .add(new Increment(row3).addColumn(FAMILY, Bytes.toBytes("A"), 5L)) 420 .add(new Append(row3).addColumn(FAMILY, Bytes.toBytes("B"), Bytes.toBytes("b"))); 421 CheckAndMutate checkAndMutate2 = 422 CheckAndMutate.newBuilder(row4).ifEquals(FAMILY, Bytes.toBytes("D"), Bytes.toBytes("a")) 423 .build(new Put(row4).addColumn(FAMILY, Bytes.toBytes("E"), Bytes.toBytes("h"))); 424 Put put = new Put(row5).addColumn(FAMILY, Bytes.toBytes("E"), Bytes.toBytes("f")); 425 CheckAndMutate checkAndMutate3 = 426 CheckAndMutate.newBuilder(row6).ifEquals(FAMILY, Bytes.toBytes("F"), Bytes.toBytes(10L)) 427 .build(new Increment(row6).addColumn(FAMILY, Bytes.toBytes("F"), 1)); 428 CheckAndMutate checkAndMutate4 = 429 CheckAndMutate.newBuilder(row7).ifEquals(FAMILY, Bytes.toBytes("G"), Bytes.toBytes("g")) 430 .build(new Append(row7).addColumn(FAMILY, Bytes.toBytes("G"), Bytes.toBytes("g"))); 431 432 List<Row> actions = Arrays.asList(checkAndMutate1, get, mutations, checkAndMutate2, put, 433 checkAndMutate3, checkAndMutate4); 434 List<Object> results = table.batchAll(actions).get(); 435 436 CheckAndMutateResult checkAndMutateResult = (CheckAndMutateResult) results.get(0); 437 assertTrue(checkAndMutateResult.isSuccess()); 438 assertEquals(3L, 439 Bytes.toLong(checkAndMutateResult.getResult().getValue(FAMILY, Bytes.toBytes("C")))); 440 assertEquals("d", 441 Bytes.toString(checkAndMutateResult.getResult().getValue(FAMILY, Bytes.toBytes("D")))); 442 443 assertEquals("b", 444 Bytes.toString(((Result) results.get(1)).getValue(FAMILY, Bytes.toBytes("B")))); 445 446 Result result = (Result) results.get(2); 447 assertTrue(result.getExists()); 448 assertEquals(5L, Bytes.toLong(result.getValue(FAMILY, Bytes.toBytes("A")))); 449 assertEquals("b", Bytes.toString(result.getValue(FAMILY, Bytes.toBytes("B")))); 450 451 checkAndMutateResult = (CheckAndMutateResult) results.get(3); 452 assertFalse(checkAndMutateResult.isSuccess()); 453 assertNull(checkAndMutateResult.getResult()); 454 455 assertTrue(((Result) results.get(4)).isEmpty()); 456 457 checkAndMutateResult = (CheckAndMutateResult) results.get(5); 458 assertTrue(checkAndMutateResult.isSuccess()); 459 assertEquals(11, 460 Bytes.toLong(checkAndMutateResult.getResult().getValue(FAMILY, Bytes.toBytes("F")))); 461 462 checkAndMutateResult = (CheckAndMutateResult) results.get(6); 463 assertTrue(checkAndMutateResult.isSuccess()); 464 assertEquals("gg", 465 Bytes.toString(checkAndMutateResult.getResult().getValue(FAMILY, Bytes.toBytes("G")))); 466 467 result = table.get(new Get(row1)).get(); 468 assertEquals("g", Bytes.toString(result.getValue(FAMILY, Bytes.toBytes("B")))); 469 assertNull(result.getValue(FAMILY, Bytes.toBytes("A"))); 470 assertEquals(3L, Bytes.toLong(result.getValue(FAMILY, Bytes.toBytes("C")))); 471 assertEquals("d", Bytes.toString(result.getValue(FAMILY, Bytes.toBytes("D")))); 472 473 result = table.get(new Get(row3)).get(); 474 assertNull(result.getValue(FAMILY, Bytes.toBytes("C"))); 475 assertEquals("f", Bytes.toString(result.getValue(FAMILY, Bytes.toBytes("F")))); 476 assertNull(Bytes.toString(result.getValue(FAMILY, Bytes.toBytes("C")))); 477 assertEquals(5L, Bytes.toLong(result.getValue(FAMILY, Bytes.toBytes("A")))); 478 assertEquals("b", Bytes.toString(result.getValue(FAMILY, Bytes.toBytes("B")))); 479 480 result = table.get(new Get(row4)).get(); 481 assertEquals("d", Bytes.toString(result.getValue(FAMILY, Bytes.toBytes("D")))); 482 483 result = table.get(new Get(row5)).get(); 484 assertEquals("f", Bytes.toString(result.getValue(FAMILY, Bytes.toBytes("E")))); 485 486 result = table.get(new Get(row6)).get(); 487 assertEquals(11, Bytes.toLong(result.getValue(FAMILY, Bytes.toBytes("F")))); 488 489 result = table.get(new Get(row7)).get(); 490 assertEquals("gg", Bytes.toString(result.getValue(FAMILY, Bytes.toBytes("G")))); 491 } 492}