HBASE-26481 Consider rolling upgrading from old region replication framework (#3880)
[hbase.git] / hbase-server / src / test / java / org / apache / hadoop / hbase / client / TestResult.java
blob35783e2ff965e999f1d8750b7716fb5a4bd8b09b
1 /**
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
18 package org.apache.hadoop.hbase.client;
20 import static org.hamcrest.MatcherAssert.assertThat;
21 import static org.hamcrest.Matchers.greaterThan;
22 import static org.hamcrest.Matchers.is;
23 import static org.hamcrest.Matchers.lessThan;
24 import static org.junit.Assert.assertArrayEquals;
25 import java.io.IOException;
26 import java.nio.ByteBuffer;
27 import java.util.ArrayList;
28 import java.util.Arrays;
29 import java.util.List;
30 import java.util.NoSuchElementException;
31 import junit.framework.TestCase;
32 import org.apache.hadoop.hbase.ArrayBackedTag;
33 import org.apache.hadoop.hbase.ByteBufferKeyValue;
34 import org.apache.hadoop.hbase.Cell;
35 import org.apache.hadoop.hbase.CellComparator;
36 import org.apache.hadoop.hbase.CellScanner;
37 import org.apache.hadoop.hbase.CellUtil;
38 import org.apache.hadoop.hbase.HBaseClassTestRule;
39 import org.apache.hadoop.hbase.KeyValue;
40 import org.apache.hadoop.hbase.Tag;
41 import org.apache.hadoop.hbase.testclassification.ClientTests;
42 import org.apache.hadoop.hbase.testclassification.SmallTests;
43 import org.apache.hadoop.hbase.util.ByteBufferUtils;
44 import org.apache.hadoop.hbase.util.Bytes;
45 import org.hamcrest.MatcherAssert;
46 import org.junit.ClassRule;
47 import org.junit.experimental.categories.Category;
48 import org.slf4j.Logger;
49 import org.slf4j.LoggerFactory;
51 @Category({SmallTests.class, ClientTests.class})
52 public class TestResult extends TestCase {
54 @ClassRule
55 public static final HBaseClassTestRule CLASS_RULE =
56 HBaseClassTestRule.forClass(TestResult.class);
58 private static final Logger LOG = LoggerFactory.getLogger(TestResult.class.getName());
60 static KeyValue[] genKVs(final byte[] row, final byte[] family,
61 final byte[] value,
62 final long timestamp,
63 final int cols) {
64 KeyValue [] kvs = new KeyValue[cols];
66 for (int i = 0; i < cols ; i++) {
67 kvs[i] = new KeyValue(
68 row, family, Bytes.toBytes(i),
69 timestamp,
70 Bytes.add(value, Bytes.toBytes(i)));
72 return kvs;
75 static final byte [] row = Bytes.toBytes("row");
76 static final byte [] family = Bytes.toBytes("family");
77 static final byte [] value = Bytes.toBytes("value");
78 static final byte [] qual = Bytes.toBytes("qual");
80 /**
81 * Run some tests to ensure Result acts like a proper CellScanner.
82 * @throws IOException
84 public void testResultAsCellScanner() throws IOException {
85 Cell [] cells = genKVs(row, family, value, 1, 10);
86 Arrays.sort(cells, CellComparator.getInstance());
87 Result r = Result.create(cells);
88 assertSame(r, cells);
89 // Assert I run over same result multiple times.
90 assertSame(r.cellScanner(), cells);
91 assertSame(r.cellScanner(), cells);
92 // Assert we are not creating new object when doing cellscanner
93 assertTrue(r == r.cellScanner());
96 private void assertSame(final CellScanner cellScanner, final Cell [] cells) throws IOException {
97 int count = 0;
98 while (cellScanner.advance()) {
99 assertTrue(cells[count].equals(cellScanner.current()));
100 count++;
102 assertEquals(cells.length, count);
105 public void testBasicGetColumn() throws Exception {
106 KeyValue [] kvs = genKVs(row, family, value, 1, 100);
108 Arrays.sort(kvs, CellComparator.getInstance());
110 Result r = Result.create(kvs);
112 for (int i = 0; i < 100; ++i) {
113 final byte[] qf = Bytes.toBytes(i);
115 List<Cell> ks = r.getColumnCells(family, qf);
116 assertEquals(1, ks.size());
117 assertTrue(CellUtil.matchingQualifier(ks.get(0), qf));
118 assertEquals(ks.get(0), r.getColumnLatestCell(family, qf));
122 public void testCurrentOnEmptyCell() throws IOException {
123 Result r = Result.create(new Cell[0]);
124 assertFalse(r.advance());
125 assertNull(r.current());
128 public void testAdvanceTwiceOnEmptyCell() throws IOException {
129 Result r = Result.create(new Cell[0]);
130 assertFalse(r.advance());
131 try {
132 r.advance();
133 fail("NoSuchElementException should have been thrown!");
134 } catch (NoSuchElementException ex) {
135 LOG.debug("As expected: " + ex.getMessage());
139 public void testMultiVersionGetColumn() throws Exception {
140 KeyValue [] kvs1 = genKVs(row, family, value, 1, 100);
141 KeyValue [] kvs2 = genKVs(row, family, value, 200, 100);
143 KeyValue [] kvs = new KeyValue[kvs1.length+kvs2.length];
144 System.arraycopy(kvs1, 0, kvs, 0, kvs1.length);
145 System.arraycopy(kvs2, 0, kvs, kvs1.length, kvs2.length);
147 Arrays.sort(kvs, CellComparator.getInstance());
149 Result r = Result.create(kvs);
150 for (int i = 0; i < 100; ++i) {
151 final byte[] qf = Bytes.toBytes(i);
153 List<Cell> ks = r.getColumnCells(family, qf);
154 assertEquals(2, ks.size());
155 assertTrue(CellUtil.matchingQualifier(ks.get(0), qf));
156 assertEquals(200, ks.get(0).getTimestamp());
157 assertEquals(ks.get(0), r.getColumnLatestCell(family, qf));
161 public void testBasicGetValue() throws Exception {
162 KeyValue [] kvs = genKVs(row, family, value, 1, 100);
164 Arrays.sort(kvs, CellComparator.getInstance());
166 Result r = Result.create(kvs);
168 for (int i = 0; i < 100; ++i) {
169 final byte[] qf = Bytes.toBytes(i);
171 assertArrayEquals(Bytes.add(value, Bytes.toBytes(i)), r.getValue(family, qf));
172 assertTrue(r.containsColumn(family, qf));
176 public void testMultiVersionGetValue() throws Exception {
177 KeyValue [] kvs1 = genKVs(row, family, value, 1, 100);
178 KeyValue [] kvs2 = genKVs(row, family, value, 200, 100);
180 KeyValue [] kvs = new KeyValue[kvs1.length+kvs2.length];
181 System.arraycopy(kvs1, 0, kvs, 0, kvs1.length);
182 System.arraycopy(kvs2, 0, kvs, kvs1.length, kvs2.length);
184 Arrays.sort(kvs, CellComparator.getInstance());
186 Result r = Result.create(kvs);
187 for (int i = 0; i < 100; ++i) {
188 final byte[] qf = Bytes.toBytes(i);
190 assertArrayEquals(Bytes.add(value, Bytes.toBytes(i)), r.getValue(family, qf));
191 assertTrue(r.containsColumn(family, qf));
195 public void testBasicLoadValue() throws Exception {
196 KeyValue [] kvs = genKVs(row, family, value, 1, 100);
198 Arrays.sort(kvs, CellComparator.getInstance());
200 Result r = Result.create(kvs);
201 ByteBuffer loadValueBuffer = ByteBuffer.allocate(1024);
203 for (int i = 0; i < 100; ++i) {
204 final byte[] qf = Bytes.toBytes(i);
206 loadValueBuffer.clear();
207 r.loadValue(family, qf, loadValueBuffer);
208 loadValueBuffer.flip();
209 assertEquals(loadValueBuffer, ByteBuffer.wrap(Bytes.add(value, Bytes.toBytes(i))));
210 assertEquals(ByteBuffer.wrap(Bytes.add(value, Bytes.toBytes(i))),
211 r.getValueAsByteBuffer(family, qf));
215 public void testMultiVersionLoadValue() throws Exception {
216 KeyValue [] kvs1 = genKVs(row, family, value, 1, 100);
217 KeyValue [] kvs2 = genKVs(row, family, value, 200, 100);
219 KeyValue [] kvs = new KeyValue[kvs1.length+kvs2.length];
220 System.arraycopy(kvs1, 0, kvs, 0, kvs1.length);
221 System.arraycopy(kvs2, 0, kvs, kvs1.length, kvs2.length);
223 Arrays.sort(kvs, CellComparator.getInstance());
225 ByteBuffer loadValueBuffer = ByteBuffer.allocate(1024);
227 Result r = Result.create(kvs);
228 for (int i = 0; i < 100; ++i) {
229 final byte[] qf = Bytes.toBytes(i);
231 loadValueBuffer.clear();
232 r.loadValue(family, qf, loadValueBuffer);
233 loadValueBuffer.flip();
234 assertEquals(loadValueBuffer, ByteBuffer.wrap(Bytes.add(value, Bytes.toBytes(i))));
235 assertEquals(ByteBuffer.wrap(Bytes.add(value, Bytes.toBytes(i))),
236 r.getValueAsByteBuffer(family, qf));
241 * Verify that Result.compareResults(...) behaves correctly.
243 public void testCompareResults() throws Exception {
244 byte [] value1 = Bytes.toBytes("value1");
245 byte [] qual = Bytes.toBytes("qual");
247 KeyValue kv1 = new KeyValue(row, family, qual, value);
248 KeyValue kv2 = new KeyValue(row, family, qual, value1);
250 Result r1 = Result.create(new KeyValue[] {kv1});
251 Result r2 = Result.create(new KeyValue[] {kv2});
252 // no exception thrown
253 Result.compareResults(r1, r1);
254 try {
255 // these are different (HBASE-4800)
256 Result.compareResults(r1, r2);
257 fail();
258 } catch (Exception x) {
259 assertTrue(x.getMessage().startsWith("This result was different:"));
263 public void testCompareResultsWithTags() throws Exception {
264 Tag t1 = new ArrayBackedTag((byte) 1, Bytes.toBytes("TAG1"));
265 Tag t2 = new ArrayBackedTag((byte) 2, Bytes.toBytes("TAG2"));
266 // Both BB backed tags KV are null
267 Result result1 = getByteBufferBackedTagResult(null);
268 Result result2 = getByteBufferBackedTagResult(null);
269 Result.compareResults(result1, result2);
271 // Test both byte buffer backed tags KeyValue
272 result1 = getByteBufferBackedTagResult(t1);
273 result2 = getByteBufferBackedTagResult(t1);
274 Result.compareResults(result1, result2);
276 // Both array backed tags KV are null
277 result1 = getArrayBackedTagResult(null);
278 result2 = getArrayBackedTagResult(null);
279 Result.compareResults(result1, result2);
281 // Test both array backed tags KeyValue
282 result1 = getArrayBackedTagResult(t1);
283 result2 = getArrayBackedTagResult(t1);
284 Result.compareResults(result1, result2);
286 // left instance of byte buffer and right instance of array backed
287 result1 = getByteBufferBackedTagResult(t1);
288 result2 = getArrayBackedTagResult(t1);
289 Result.compareResults(result1, result2);
291 // left instance of array backed and right instance of byte buffer backed.
292 result1 = getArrayBackedTagResult(t1);
293 result2 = getByteBufferBackedTagResult(t1);
294 Result.compareResults(result1, result2);
296 // Left BB backed null tag and right BB backed non null tag
297 result1 = getByteBufferBackedTagResult(null);
298 result2 = getByteBufferBackedTagResult(t2);
299 try {
300 Result.compareResults(result1, result2);
301 fail();
302 } catch (Exception e) {
303 // Expected
306 // Left BB backed non null tag and right BB backed null tag
307 result1 = getByteBufferBackedTagResult(t1);
308 result2 = getByteBufferBackedTagResult(null);
309 try {
310 Result.compareResults(result1, result2);
311 fail();
312 } catch (Exception e) {
313 // Expected
316 // Both byte buffer backed tags KV are different
317 result1 = getByteBufferBackedTagResult(t1);
318 result2 = getByteBufferBackedTagResult(t2);
319 try {
320 Result.compareResults(result1, result2);
321 fail();
322 } catch (Exception e) {
323 // Expected
326 // Left array backed non null tag and right array backed null tag
327 result1 = getArrayBackedTagResult(t1);
328 result2 = getArrayBackedTagResult(null);
329 try {
330 Result.compareResults(result1, result2);
331 fail();
332 } catch (Exception e) {
333 // Expected
336 // Left array backed null tag and right array backed non null tag
337 result1 = getByteBufferBackedTagResult(null);
338 result2 = getByteBufferBackedTagResult(t2);
339 try {
340 Result.compareResults(result1, result2);
341 fail();
342 } catch (Exception e) {
343 // Expected
346 // Both array backed tags KV are different
347 result1 = getArrayBackedTagResult(t1);
348 result2 = getArrayBackedTagResult(t2);
349 try {
350 Result.compareResults(result1, result2);
351 fail();
352 } catch (Exception e) {
353 // Expected
356 // left instance of byte buffer and right instance of array backed are different
357 result1 = getByteBufferBackedTagResult(t1);
358 result2 = getArrayBackedTagResult(t2);
359 try {
360 Result.compareResults(result1, result2);
361 fail();
362 } catch (Exception e) {
363 // Expected
366 // left instance of array backed and right instance of byte buffer backed are different
367 result1 = getArrayBackedTagResult(t1);
368 result2 = getByteBufferBackedTagResult(t2);
369 try {
370 Result.compareResults(result1, result2);
371 fail();
372 } catch (Exception e) {
373 // Expected
377 public void testCompareResultMemoryUsage() {
378 List<Cell> cells1 = new ArrayList<>();
379 for (long i = 0; i < 100; i++) {
380 cells1.add(new KeyValue(row, family, Bytes.toBytes(i), value));
383 List<Cell> cells2 = new ArrayList<>();
384 for (long i = 0; i < 100; i++) {
385 cells2.add(new KeyValue(row, family, Bytes.toBytes(i), Bytes.toBytes(i)));
388 Result r1 = Result.create(cells1);
389 Result r2 = Result.create(cells2);
390 try {
391 Result.compareResults(r1, r2);
392 fail();
393 } catch (Exception x) {
394 assertTrue(x.getMessage().startsWith("This result was different:"));
395 assertThat(x.getMessage().length(), is(greaterThan(100)));
398 try {
399 Result.compareResults(r1, r2, false);
400 fail();
401 } catch (Exception x) {
402 assertEquals("This result was different: row=row", x.getMessage());
403 assertThat(x.getMessage().length(), is(lessThan(100)));
407 private Result getArrayBackedTagResult(Tag tag) {
408 List<Tag> tags = null;
409 if (tag != null) {
410 tags = Arrays.asList(tag);
412 KeyValue kvCell = new KeyValue(row, family, qual, 0L, KeyValue.Type.Put,
413 value, tags);
414 return Result.create(new Cell[] {kvCell});
417 private Result getByteBufferBackedTagResult(Tag tag) {
418 List<Tag> tags = null;
419 if (tag != null) {
420 tags = Arrays.asList(tag);
422 KeyValue kvCell = new KeyValue(row, family, qual, 0L, KeyValue.Type.Put,
423 value, tags);
424 ByteBuffer buf = ByteBuffer.allocateDirect(kvCell.getBuffer().length);
425 ByteBufferUtils.copyFromArrayToBuffer(buf, kvCell.getBuffer(), 0, kvCell.getBuffer().length);
426 ByteBufferKeyValue bbKV = new ByteBufferKeyValue(buf, 0, buf.capacity(), 0L);
427 return Result.create(new Cell[] {bbKV});
430 * Verifies that one can't modify instance of EMPTY_RESULT.
432 public void testEmptyResultIsReadonly() {
433 Result emptyResult = Result.EMPTY_RESULT;
434 Result otherResult = new Result();
436 try {
437 emptyResult.copyFrom(otherResult);
438 fail("UnsupportedOperationException should have been thrown!");
439 } catch (UnsupportedOperationException ex) {
440 LOG.debug("As expected: " + ex.getMessage());
442 try {
443 emptyResult.setExists(true);
444 fail("UnsupportedOperationException should have been thrown!");
445 } catch (UnsupportedOperationException ex) {
446 LOG.debug("As expected: " + ex.getMessage());
451 * Microbenchmark that compares {@link Result#getValue} and {@link Result#loadValue} performance.
453 * @throws Exception
455 public void doReadBenchmark() throws Exception {
457 final int n = 5;
458 final int m = 100000000;
460 StringBuilder valueSB = new StringBuilder();
461 for (int i = 0; i < 100; i++) {
462 valueSB.append((byte)(Math.random() * 10));
465 StringBuilder rowSB = new StringBuilder();
466 for (int i = 0; i < 50; i++) {
467 rowSB.append((byte)(Math.random() * 10));
470 KeyValue [] kvs = genKVs(Bytes.toBytes(rowSB.toString()), family,
471 Bytes.toBytes(valueSB.toString()), 1, n);
472 Arrays.sort(kvs, CellComparator.getInstance());
473 ByteBuffer loadValueBuffer = ByteBuffer.allocate(1024);
474 Result r = Result.create(kvs);
476 byte[][] qfs = new byte[n][Bytes.SIZEOF_INT];
477 for (int i = 0; i < n; ++i) {
478 System.arraycopy(qfs[i], 0, Bytes.toBytes(i), 0, Bytes.SIZEOF_INT);
481 // warm up
482 for (int k = 0; k < 100000; k++) {
483 for (int i = 0; i < n; ++i) {
484 r.getValue(family, qfs[i]);
485 loadValueBuffer.clear();
486 r.loadValue(family, qfs[i], loadValueBuffer);
487 loadValueBuffer.flip();
491 System.gc();
492 long start = System.nanoTime();
493 for (int k = 0; k < m; k++) {
494 for (int i = 0; i < n; ++i) {
495 loadValueBuffer.clear();
496 r.loadValue(family, qfs[i], loadValueBuffer);
497 loadValueBuffer.flip();
500 long stop = System.nanoTime();
501 System.out.println("loadValue(): " + (stop - start));
503 System.gc();
504 start = System.nanoTime();
505 for (int k = 0; k < m; k++) {
506 for (int i = 0; i < n; i++) {
507 r.getValue(family, qfs[i]);
510 stop = System.nanoTime();
511 System.out.println("getValue(): " + (stop - start));
515 * Calls non-functional test methods.
517 * @param args
519 public static void main(String[] args) {
520 TestResult testResult = new TestResult();
521 try {
522 testResult.doReadBenchmark();
523 } catch (Exception e) {
524 LOG.error("Unexpected exception", e);