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
.apache
.hadoop
.hbase
.HBaseTestCase
.assertByteEquals
;
22 import java
.io
.IOException
;
23 import java
.nio
.ByteBuffer
;
24 import java
.util
.Arrays
;
25 import java
.util
.List
;
26 import java
.util
.NoSuchElementException
;
27 import junit
.framework
.TestCase
;
28 import org
.apache
.hadoop
.hbase
.Cell
;
29 import org
.apache
.hadoop
.hbase
.CellComparator
;
30 import org
.apache
.hadoop
.hbase
.CellScanner
;
31 import org
.apache
.hadoop
.hbase
.CellUtil
;
32 import org
.apache
.hadoop
.hbase
.HBaseClassTestRule
;
33 import org
.apache
.hadoop
.hbase
.KeyValue
;
34 import org
.apache
.hadoop
.hbase
.testclassification
.ClientTests
;
35 import org
.apache
.hadoop
.hbase
.testclassification
.SmallTests
;
36 import org
.apache
.hadoop
.hbase
.util
.Bytes
;
37 import org
.junit
.ClassRule
;
38 import org
.junit
.experimental
.categories
.Category
;
39 import org
.slf4j
.Logger
;
40 import org
.slf4j
.LoggerFactory
;
42 @Category({SmallTests
.class, ClientTests
.class})
43 public class TestResult
extends TestCase
{
46 public static final HBaseClassTestRule CLASS_RULE
=
47 HBaseClassTestRule
.forClass(TestResult
.class);
49 private static final Logger LOG
= LoggerFactory
.getLogger(TestResult
.class.getName());
51 static KeyValue
[] genKVs(final byte[] row
, final byte[] family
,
55 KeyValue
[] kvs
= new KeyValue
[cols
];
57 for (int i
= 0; i
< cols
; i
++) {
58 kvs
[i
] = new KeyValue(
59 row
, family
, Bytes
.toBytes(i
),
61 Bytes
.add(value
, Bytes
.toBytes(i
)));
66 static final byte [] row
= Bytes
.toBytes("row");
67 static final byte [] family
= Bytes
.toBytes("family");
68 static final byte [] value
= Bytes
.toBytes("value");
71 * Run some tests to ensure Result acts like a proper CellScanner.
74 public void testResultAsCellScanner() throws IOException
{
75 Cell
[] cells
= genKVs(row
, family
, value
, 1, 10);
76 Arrays
.sort(cells
, CellComparator
.getInstance());
77 Result r
= Result
.create(cells
);
79 // Assert I run over same result multiple times.
80 assertSame(r
.cellScanner(), cells
);
81 assertSame(r
.cellScanner(), cells
);
82 // Assert we are not creating new object when doing cellscanner
83 assertTrue(r
== r
.cellScanner());
86 private void assertSame(final CellScanner cellScanner
, final Cell
[] cells
) throws IOException
{
88 while (cellScanner
.advance()) {
89 assertTrue(cells
[count
].equals(cellScanner
.current()));
92 assertEquals(cells
.length
, count
);
95 public void testBasicGetColumn() throws Exception
{
96 KeyValue
[] kvs
= genKVs(row
, family
, value
, 1, 100);
98 Arrays
.sort(kvs
, CellComparator
.getInstance());
100 Result r
= Result
.create(kvs
);
102 for (int i
= 0; i
< 100; ++i
) {
103 final byte[] qf
= Bytes
.toBytes(i
);
105 List
<Cell
> ks
= r
.getColumnCells(family
, qf
);
106 assertEquals(1, ks
.size());
107 assertTrue(CellUtil
.matchingQualifier(ks
.get(0), qf
));
108 assertEquals(ks
.get(0), r
.getColumnLatestCell(family
, qf
));
112 public void testCurrentOnEmptyCell() throws IOException
{
113 Result r
= Result
.create(new Cell
[0]);
114 assertFalse(r
.advance());
115 assertNull(r
.current());
118 public void testAdvanceTwiceOnEmptyCell() throws IOException
{
119 Result r
= Result
.create(new Cell
[0]);
120 assertFalse(r
.advance());
123 fail("NoSuchElementException should have been thrown!");
124 } catch (NoSuchElementException ex
) {
125 LOG
.debug("As expected: " + ex
.getMessage());
129 public void testMultiVersionGetColumn() throws Exception
{
130 KeyValue
[] kvs1
= genKVs(row
, family
, value
, 1, 100);
131 KeyValue
[] kvs2
= genKVs(row
, family
, value
, 200, 100);
133 KeyValue
[] kvs
= new KeyValue
[kvs1
.length
+kvs2
.length
];
134 System
.arraycopy(kvs1
, 0, kvs
, 0, kvs1
.length
);
135 System
.arraycopy(kvs2
, 0, kvs
, kvs1
.length
, kvs2
.length
);
137 Arrays
.sort(kvs
, CellComparator
.getInstance());
139 Result r
= Result
.create(kvs
);
140 for (int i
= 0; i
< 100; ++i
) {
141 final byte[] qf
= Bytes
.toBytes(i
);
143 List
<Cell
> ks
= r
.getColumnCells(family
, qf
);
144 assertEquals(2, ks
.size());
145 assertTrue(CellUtil
.matchingQualifier(ks
.get(0), qf
));
146 assertEquals(200, ks
.get(0).getTimestamp());
147 assertEquals(ks
.get(0), r
.getColumnLatestCell(family
, qf
));
151 public void testBasicGetValue() throws Exception
{
152 KeyValue
[] kvs
= genKVs(row
, family
, value
, 1, 100);
154 Arrays
.sort(kvs
, CellComparator
.getInstance());
156 Result r
= Result
.create(kvs
);
158 for (int i
= 0; i
< 100; ++i
) {
159 final byte[] qf
= Bytes
.toBytes(i
);
161 assertByteEquals(Bytes
.add(value
, Bytes
.toBytes(i
)), r
.getValue(family
, qf
));
162 assertTrue(r
.containsColumn(family
, qf
));
166 public void testMultiVersionGetValue() throws Exception
{
167 KeyValue
[] kvs1
= genKVs(row
, family
, value
, 1, 100);
168 KeyValue
[] kvs2
= genKVs(row
, family
, value
, 200, 100);
170 KeyValue
[] kvs
= new KeyValue
[kvs1
.length
+kvs2
.length
];
171 System
.arraycopy(kvs1
, 0, kvs
, 0, kvs1
.length
);
172 System
.arraycopy(kvs2
, 0, kvs
, kvs1
.length
, kvs2
.length
);
174 Arrays
.sort(kvs
, CellComparator
.getInstance());
176 Result r
= Result
.create(kvs
);
177 for (int i
= 0; i
< 100; ++i
) {
178 final byte[] qf
= Bytes
.toBytes(i
);
180 assertByteEquals(Bytes
.add(value
, Bytes
.toBytes(i
)), r
.getValue(family
, qf
));
181 assertTrue(r
.containsColumn(family
, qf
));
185 public void testBasicLoadValue() throws Exception
{
186 KeyValue
[] kvs
= genKVs(row
, family
, value
, 1, 100);
188 Arrays
.sort(kvs
, CellComparator
.getInstance());
190 Result r
= Result
.create(kvs
);
191 ByteBuffer loadValueBuffer
= ByteBuffer
.allocate(1024);
193 for (int i
= 0; i
< 100; ++i
) {
194 final byte[] qf
= Bytes
.toBytes(i
);
196 loadValueBuffer
.clear();
197 r
.loadValue(family
, qf
, loadValueBuffer
);
198 loadValueBuffer
.flip();
199 assertEquals(loadValueBuffer
, ByteBuffer
.wrap(Bytes
.add(value
, Bytes
.toBytes(i
))));
200 assertEquals(ByteBuffer
.wrap(Bytes
.add(value
, Bytes
.toBytes(i
))),
201 r
.getValueAsByteBuffer(family
, qf
));
205 public void testMultiVersionLoadValue() throws Exception
{
206 KeyValue
[] kvs1
= genKVs(row
, family
, value
, 1, 100);
207 KeyValue
[] kvs2
= genKVs(row
, family
, value
, 200, 100);
209 KeyValue
[] kvs
= new KeyValue
[kvs1
.length
+kvs2
.length
];
210 System
.arraycopy(kvs1
, 0, kvs
, 0, kvs1
.length
);
211 System
.arraycopy(kvs2
, 0, kvs
, kvs1
.length
, kvs2
.length
);
213 Arrays
.sort(kvs
, CellComparator
.getInstance());
215 ByteBuffer loadValueBuffer
= ByteBuffer
.allocate(1024);
217 Result r
= Result
.create(kvs
);
218 for (int i
= 0; i
< 100; ++i
) {
219 final byte[] qf
= Bytes
.toBytes(i
);
221 loadValueBuffer
.clear();
222 r
.loadValue(family
, qf
, loadValueBuffer
);
223 loadValueBuffer
.flip();
224 assertEquals(loadValueBuffer
, ByteBuffer
.wrap(Bytes
.add(value
, Bytes
.toBytes(i
))));
225 assertEquals(ByteBuffer
.wrap(Bytes
.add(value
, Bytes
.toBytes(i
))),
226 r
.getValueAsByteBuffer(family
, qf
));
231 * Verify that Result.compareResults(...) behaves correctly.
233 public void testCompareResults() throws Exception
{
234 byte [] value1
= Bytes
.toBytes("value1");
235 byte [] qual
= Bytes
.toBytes("qual");
237 KeyValue kv1
= new KeyValue(row
, family
, qual
, value
);
238 KeyValue kv2
= new KeyValue(row
, family
, qual
, value1
);
240 Result r1
= Result
.create(new KeyValue
[] {kv1
});
241 Result r2
= Result
.create(new KeyValue
[] {kv2
});
242 // no exception thrown
243 Result
.compareResults(r1
, r1
);
245 // these are different (HBASE-4800)
246 Result
.compareResults(r1
, r2
);
248 } catch (Exception x
) {
249 assertTrue(x
.getMessage().startsWith("This result was different:"));
254 * Verifies that one can't modify instance of EMPTY_RESULT.
256 public void testEmptyResultIsReadonly() {
257 Result emptyResult
= Result
.EMPTY_RESULT
;
258 Result otherResult
= new Result();
261 emptyResult
.copyFrom(otherResult
);
262 fail("UnsupportedOperationException should have been thrown!");
263 } catch (UnsupportedOperationException ex
) {
264 LOG
.debug("As expected: " + ex
.getMessage());
267 emptyResult
.setExists(true);
268 fail("UnsupportedOperationException should have been thrown!");
269 } catch (UnsupportedOperationException ex
) {
270 LOG
.debug("As expected: " + ex
.getMessage());
275 * Microbenchmark that compares {@link Result#getValue} and {@link Result#loadValue} performance.
279 public void doReadBenchmark() throws Exception
{
282 final int m
= 100000000;
284 StringBuilder valueSB
= new StringBuilder();
285 for (int i
= 0; i
< 100; i
++) {
286 valueSB
.append((byte)(Math
.random() * 10));
289 StringBuilder rowSB
= new StringBuilder();
290 for (int i
= 0; i
< 50; i
++) {
291 rowSB
.append((byte)(Math
.random() * 10));
294 KeyValue
[] kvs
= genKVs(Bytes
.toBytes(rowSB
.toString()), family
,
295 Bytes
.toBytes(valueSB
.toString()), 1, n
);
296 Arrays
.sort(kvs
, CellComparator
.getInstance());
297 ByteBuffer loadValueBuffer
= ByteBuffer
.allocate(1024);
298 Result r
= Result
.create(kvs
);
300 byte[][] qfs
= new byte[n
][Bytes
.SIZEOF_INT
];
301 for (int i
= 0; i
< n
; ++i
) {
302 System
.arraycopy(qfs
[i
], 0, Bytes
.toBytes(i
), 0, Bytes
.SIZEOF_INT
);
306 for (int k
= 0; k
< 100000; k
++) {
307 for (int i
= 0; i
< n
; ++i
) {
308 r
.getValue(family
, qfs
[i
]);
309 loadValueBuffer
.clear();
310 r
.loadValue(family
, qfs
[i
], loadValueBuffer
);
311 loadValueBuffer
.flip();
316 long start
= System
.nanoTime();
317 for (int k
= 0; k
< m
; k
++) {
318 for (int i
= 0; i
< n
; ++i
) {
319 loadValueBuffer
.clear();
320 r
.loadValue(family
, qfs
[i
], loadValueBuffer
);
321 loadValueBuffer
.flip();
324 long stop
= System
.nanoTime();
325 System
.out
.println("loadValue(): " + (stop
- start
));
328 start
= System
.nanoTime();
329 for (int k
= 0; k
< m
; k
++) {
330 for (int i
= 0; i
< n
; i
++) {
331 r
.getValue(family
, qfs
[i
]);
334 stop
= System
.nanoTime();
335 System
.out
.println("getValue(): " + (stop
- start
));
339 * Calls non-functional test methods.
343 public static void main(String
[] args
) {
344 TestResult testResult
= new TestResult();
346 testResult
.doReadBenchmark();
347 } catch (Exception e
) {
348 LOG
.error("Unexpected exception", e
);