1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.hadoop.hbase;
21
22 import java.io.ByteArrayInputStream;
23 import java.io.DataInputStream;
24 import java.io.IOException;
25 import java.util.Set;
26 import java.util.TreeSet;
27
28 import junit.framework.TestCase;
29
30 import org.apache.commons.logging.Log;
31 import org.apache.commons.logging.LogFactory;
32 import org.apache.hadoop.hbase.KeyValue.KVComparator;
33 import org.apache.hadoop.hbase.KeyValue.MetaComparator;
34 import org.apache.hadoop.hbase.KeyValue.Type;
35 import org.apache.hadoop.hbase.util.Bytes;
36 import org.apache.hadoop.io.WritableUtils;
37 import org.junit.experimental.categories.Category;
38
39 @Category(SmallTests.class)
40 public class TestKeyValue extends TestCase {
41 private final Log LOG = LogFactory.getLog(this.getClass().getName());
42
43 public void testColumnCompare() throws Exception {
44 final byte [] a = Bytes.toBytes("aaa");
45 byte [] family1 = Bytes.toBytes("abc");
46 byte [] qualifier1 = Bytes.toBytes("def");
47 byte [] family2 = Bytes.toBytes("abcd");
48 byte [] qualifier2 = Bytes.toBytes("ef");
49
50 KeyValue aaa = new KeyValue(a, family1, qualifier1, 0L, Type.Put, a);
51 assertFalse(aaa.matchingColumn(family2, qualifier2));
52 assertTrue(aaa.matchingColumn(family1, qualifier1));
53 aaa = new KeyValue(a, family2, qualifier2, 0L, Type.Put, a);
54 assertFalse(aaa.matchingColumn(family1, qualifier1));
55 assertTrue(aaa.matchingColumn(family2,qualifier2));
56 byte [] nullQualifier = new byte[0];
57 aaa = new KeyValue(a, family1, nullQualifier, 0L, Type.Put, a);
58 assertTrue(aaa.matchingColumn(family1,null));
59 assertFalse(aaa.matchingColumn(family2,qualifier2));
60 }
61
62
63
64
65
66 public void testColumnCompare_prefix() throws Exception {
67 final byte [] a = Bytes.toBytes("aaa");
68 byte [] family1 = Bytes.toBytes("abc");
69 byte [] qualifier1 = Bytes.toBytes("def");
70 byte [] family2 = Bytes.toBytes("ab");
71 byte [] qualifier2 = Bytes.toBytes("def");
72
73 KeyValue aaa = new KeyValue(a, family1, qualifier1, 0L, Type.Put, a);
74 assertFalse(aaa.matchingColumn(family2, qualifier2));
75 }
76
77 public void testBasics() throws Exception {
78 LOG.info("LOWKEY: " + KeyValue.LOWESTKEY.toString());
79 check(Bytes.toBytes(getName()),
80 Bytes.toBytes(getName()), Bytes.toBytes(getName()), 1,
81 Bytes.toBytes(getName()));
82
83 check(Bytes.toBytes(getName()), Bytes.toBytes(getName()), null, 1, null);
84 check(HConstants.EMPTY_BYTE_ARRAY, Bytes.toBytes(getName()), null, 1, null);
85 }
86
87 private void check(final byte [] row, final byte [] family, byte [] qualifier,
88 final long timestamp, final byte [] value) {
89 KeyValue kv = new KeyValue(row, family, qualifier, timestamp, value);
90 assertTrue(Bytes.compareTo(kv.getRow(), row) == 0);
91 assertTrue(kv.matchingColumn(family, qualifier));
92
93 LOG.info(kv.toString());
94 }
95
96 public void testPlainCompare() throws Exception {
97 final byte [] a = Bytes.toBytes("aaa");
98 final byte [] b = Bytes.toBytes("bbb");
99 final byte [] fam = Bytes.toBytes("col");
100 final byte [] qf = Bytes.toBytes("umn");
101
102 KeyValue aaa = new KeyValue(a, fam, qf, a);
103 KeyValue bbb = new KeyValue(b, fam, qf, b);
104 byte [] keyabb = aaa.getKey();
105 byte [] keybbb = bbb.getKey();
106 assertTrue(KeyValue.COMPARATOR.compare(aaa, bbb) < 0);
107 assertTrue(KeyValue.KEY_COMPARATOR.compare(keyabb, 0, keyabb.length, keybbb,
108 0, keybbb.length) < 0);
109 assertTrue(KeyValue.COMPARATOR.compare(bbb, aaa) > 0);
110 assertTrue(KeyValue.KEY_COMPARATOR.compare(keybbb, 0, keybbb.length, keyabb,
111 0, keyabb.length) > 0);
112
113 assertTrue(KeyValue.COMPARATOR.compare(bbb, bbb) == 0);
114 assertTrue(KeyValue.KEY_COMPARATOR.compare(keybbb, 0, keybbb.length, keybbb,
115 0, keybbb.length) == 0);
116 assertTrue(KeyValue.COMPARATOR.compare(aaa, aaa) == 0);
117 assertTrue(KeyValue.KEY_COMPARATOR.compare(keyabb, 0, keyabb.length, keyabb,
118 0, keyabb.length) == 0);
119
120 aaa = new KeyValue(a, fam, qf, 1, a);
121 bbb = new KeyValue(a, fam, qf, 2, a);
122 assertTrue(KeyValue.COMPARATOR.compare(aaa, bbb) > 0);
123 assertTrue(KeyValue.COMPARATOR.compare(bbb, aaa) < 0);
124 assertTrue(KeyValue.COMPARATOR.compare(aaa, aaa) == 0);
125
126
127 aaa = new KeyValue(a, fam, qf, 1, KeyValue.Type.Delete, a);
128 bbb = new KeyValue(a, fam, qf, 1, a);
129 assertTrue(KeyValue.COMPARATOR.compare(aaa, bbb) < 0);
130 assertTrue(KeyValue.COMPARATOR.compare(bbb, aaa) > 0);
131 assertTrue(KeyValue.COMPARATOR.compare(aaa, aaa) == 0);
132 }
133
134 public void testMoreComparisons() throws Exception {
135
136 long now = System.currentTimeMillis();
137 KeyValue a = new KeyValue(Bytes.toBytes(".META.,,99999999999999"), now);
138 KeyValue b = new KeyValue(Bytes.toBytes(".META.,,1"), now);
139 KVComparator c = new KeyValue.RootComparator();
140 assertTrue(c.compare(b, a) < 0);
141 KeyValue aa = new KeyValue(Bytes.toBytes(".META.,,1"), now);
142 KeyValue bb = new KeyValue(Bytes.toBytes(".META.,,1"),
143 Bytes.toBytes("info"), Bytes.toBytes("regioninfo"), 1235943454602L,
144 (byte[])null);
145 assertTrue(c.compare(aa, bb) < 0);
146
147
148 KeyValue aaa = new KeyValue(
149 Bytes.toBytes("TestScanMultipleVersions,row_0500,1236020145502"), now);
150 KeyValue bbb = new KeyValue(
151 Bytes.toBytes("TestScanMultipleVersions,,99999999999999"), now);
152 c = new KeyValue.MetaComparator();
153 assertTrue(c.compare(bbb, aaa) < 0);
154
155 KeyValue aaaa = new KeyValue(Bytes.toBytes("TestScanMultipleVersions,,1236023996656"),
156 Bytes.toBytes("info"), Bytes.toBytes("regioninfo"), 1236024396271L,
157 (byte[])null);
158 assertTrue(c.compare(aaaa, bbb) < 0);
159
160 KeyValue x = new KeyValue(Bytes.toBytes("TestScanMultipleVersions,row_0500,1236034574162"),
161 Bytes.toBytes("info"), Bytes.toBytes(""), 9223372036854775807L,
162 (byte[])null);
163 KeyValue y = new KeyValue(Bytes.toBytes("TestScanMultipleVersions,row_0500,1236034574162"),
164 Bytes.toBytes("info"), Bytes.toBytes("regioninfo"), 1236034574912L,
165 (byte[])null);
166 assertTrue(c.compare(x, y) < 0);
167 comparisons(new KeyValue.MetaComparator());
168 comparisons(new KeyValue.KVComparator());
169 metacomparisons(new KeyValue.RootComparator());
170 metacomparisons(new KeyValue.MetaComparator());
171 }
172
173 public void testBadMetaCompareSingleDelim() {
174 MetaComparator c = new KeyValue.MetaComparator();
175 long now = System.currentTimeMillis();
176
177
178 KeyValue a = new KeyValue(Bytes.toBytes("table,a1"), now);
179 KeyValue b = new KeyValue(Bytes.toBytes("table,a2"), now);
180 try {
181 c.compare(a, b);
182 } catch (IllegalArgumentException iae) {
183 assertEquals(".META. key must have two ',' delimiters and have the following" +
184 " format: '<table>,<key>,<etc>'", iae.getMessage());
185 return;
186 }
187 fail("Expected IllegalArgumentException");
188 }
189
190 public void testMetaComparatorTableKeysWithCommaOk() {
191 MetaComparator c = new KeyValue.MetaComparator();
192 long now = System.currentTimeMillis();
193
194
195 KeyValue a = new KeyValue(Bytes.toBytes("table,key,with,commas1,1234"), now);
196 KeyValue b = new KeyValue(Bytes.toBytes("table,key,with,commas2,0123"), now);
197 assertTrue(c.compare(a, b) < 0);
198 }
199
200
201
202
203
204
205 public void testKeyValueBorderCases() throws IOException {
206
207
208 KeyValue rowA = new KeyValue(Bytes.toBytes("testtable,www.hbase.org/,1234"),
209 Bytes.toBytes("fam"), Bytes.toBytes(""), Long.MAX_VALUE, (byte[])null);
210 KeyValue rowB = new KeyValue(Bytes.toBytes("testtable,www.hbase.org/%20,99999"),
211 Bytes.toBytes("fam"), Bytes.toBytes(""), Long.MAX_VALUE, (byte[])null);
212 assertTrue(KeyValue.META_COMPARATOR.compare(rowA, rowB) < 0);
213
214 rowA = new KeyValue(Bytes.toBytes("testtable,,1234"), Bytes.toBytes("fam"),
215 Bytes.toBytes(""), Long.MAX_VALUE, (byte[])null);
216 rowB = new KeyValue(Bytes.toBytes("testtable,$www.hbase.org/,99999"),
217 Bytes.toBytes("fam"), Bytes.toBytes(""), Long.MAX_VALUE, (byte[])null);
218 assertTrue(KeyValue.META_COMPARATOR.compare(rowA, rowB) < 0);
219
220 rowA = new KeyValue(Bytes.toBytes(".META.,testtable,www.hbase.org/,1234,4321"),
221 Bytes.toBytes("fam"), Bytes.toBytes(""), Long.MAX_VALUE, (byte[])null);
222 rowB = new KeyValue(Bytes.toBytes(".META.,testtable,www.hbase.org/%20,99999,99999"),
223 Bytes.toBytes("fam"), Bytes.toBytes(""), Long.MAX_VALUE, (byte[])null);
224 assertTrue(KeyValue.ROOT_COMPARATOR.compare(rowA, rowB) < 0);
225 }
226
227 private void metacomparisons(final KeyValue.MetaComparator c) {
228 long now = System.currentTimeMillis();
229 assertTrue(c.compare(new KeyValue(Bytes.toBytes(".META.,a,,0,1"), now),
230 new KeyValue(Bytes.toBytes(".META.,a,,0,1"), now)) == 0);
231 KeyValue a = new KeyValue(Bytes.toBytes(".META.,a,,0,1"), now);
232 KeyValue b = new KeyValue(Bytes.toBytes(".META.,a,,0,2"), now);
233 assertTrue(c.compare(a, b) < 0);
234 assertTrue(c.compare(new KeyValue(Bytes.toBytes(".META.,a,,0,2"), now),
235 new KeyValue(Bytes.toBytes(".META.,a,,0,1"), now)) > 0);
236 }
237
238 private void comparisons(final KeyValue.KVComparator c) {
239 long now = System.currentTimeMillis();
240 assertTrue(c.compare(new KeyValue(Bytes.toBytes(".META.,,1"), now),
241 new KeyValue(Bytes.toBytes(".META.,,1"), now)) == 0);
242 assertTrue(c.compare(new KeyValue(Bytes.toBytes(".META.,,1"), now),
243 new KeyValue(Bytes.toBytes(".META.,,2"), now)) < 0);
244 assertTrue(c.compare(new KeyValue(Bytes.toBytes(".META.,,2"), now),
245 new KeyValue(Bytes.toBytes(".META.,,1"), now)) > 0);
246 }
247
248 public void testBinaryKeys() throws Exception {
249 Set<KeyValue> set = new TreeSet<KeyValue>(KeyValue.COMPARATOR);
250 final byte [] fam = Bytes.toBytes("col");
251 final byte [] qf = Bytes.toBytes("umn");
252 final byte [] nb = new byte[0];
253 KeyValue [] keys = {new KeyValue(Bytes.toBytes("aaaaa,\u0000\u0000,2"), fam, qf, 2, nb),
254 new KeyValue(Bytes.toBytes("aaaaa,\u0001,3"), fam, qf, 3, nb),
255 new KeyValue(Bytes.toBytes("aaaaa,,1"), fam, qf, 1, nb),
256 new KeyValue(Bytes.toBytes("aaaaa,\u1000,5"), fam, qf, 5, nb),
257 new KeyValue(Bytes.toBytes("aaaaa,a,4"), fam, qf, 4, nb),
258 new KeyValue(Bytes.toBytes("a,a,0"), fam, qf, 0, nb),
259 };
260
261 for (int i = 0; i < keys.length; i++) {
262 set.add(keys[i]);
263 }
264
265 boolean assertion = false;
266 int count = 0;
267 try {
268 for (KeyValue k: set) {
269 assertTrue(count++ == k.getTimestamp());
270 }
271 } catch (junit.framework.AssertionFailedError e) {
272
273 assertion = true;
274 }
275 assertTrue(assertion);
276
277 set = new TreeSet<KeyValue>(new KeyValue.MetaComparator());
278 for (int i = 0; i < keys.length; i++) {
279 set.add(keys[i]);
280 }
281 count = 0;
282 for (KeyValue k: set) {
283 assertTrue(count++ == k.getTimestamp());
284 }
285
286 KeyValue [] rootKeys = {
287 new KeyValue(Bytes.toBytes(".META.,aaaaa,\u0000\u0000,0,2"), fam, qf, 2, nb),
288 new KeyValue(Bytes.toBytes(".META.,aaaaa,\u0001,0,3"), fam, qf, 3, nb),
289 new KeyValue(Bytes.toBytes(".META.,aaaaa,,0,1"), fam, qf, 1, nb),
290 new KeyValue(Bytes.toBytes(".META.,aaaaa,\u1000,0,5"), fam, qf, 5, nb),
291 new KeyValue(Bytes.toBytes(".META.,aaaaa,a,0,4"), fam, qf, 4, nb),
292 new KeyValue(Bytes.toBytes(".META.,,0"), fam, qf, 0, nb),
293 };
294
295 set = new TreeSet<KeyValue>(new KeyValue.MetaComparator());
296
297 for (int i = 0; i < keys.length; i++) {
298 set.add(rootKeys[i]);
299 }
300 assertion = false;
301 count = 0;
302 try {
303 for (KeyValue k: set) {
304 assertTrue(count++ == k.getTimestamp());
305 }
306 } catch (junit.framework.AssertionFailedError e) {
307
308 assertion = true;
309 }
310
311 set = new TreeSet<KeyValue>(new KeyValue.RootComparator());
312
313 for (int i = 0; i < keys.length; i++) {
314 set.add(rootKeys[i]);
315 }
316 count = 0;
317 for (KeyValue k: set) {
318 assertTrue(count++ == k.getTimestamp());
319 }
320 }
321
322 public void testStackedUpKeyValue() {
323
324
325
326
327 }
328
329 private final byte[] rowA = Bytes.toBytes("rowA");
330 private final byte[] rowB = Bytes.toBytes("rowB");
331
332 private final byte[] family = Bytes.toBytes("family");
333 private final byte[] qualA = Bytes.toBytes("qfA");
334
335 private void assertKVLess(KeyValue.KVComparator c,
336 KeyValue less,
337 KeyValue greater) {
338 int cmp = c.compare(less,greater);
339 assertTrue(cmp < 0);
340 cmp = c.compare(greater,less);
341 assertTrue(cmp > 0);
342 }
343
344 private void assertKVLessWithoutRow(KeyValue.KeyComparator c, int common, KeyValue less,
345 KeyValue greater) {
346 int cmp = c.compareIgnoringPrefix(common, less.getBuffer(), less.getOffset()
347 + KeyValue.ROW_OFFSET, less.getKeyLength(), greater.getBuffer(),
348 greater.getOffset() + KeyValue.ROW_OFFSET, greater.getKeyLength());
349 assertTrue(cmp < 0);
350 cmp = c.compareIgnoringPrefix(common, greater.getBuffer(), greater.getOffset()
351 + KeyValue.ROW_OFFSET, greater.getKeyLength(), less.getBuffer(),
352 less.getOffset() + KeyValue.ROW_OFFSET, less.getKeyLength());
353 assertTrue(cmp > 0);
354 }
355
356 public void testCompareWithoutRow() {
357 final KeyValue.KeyComparator c = KeyValue.KEY_COMPARATOR;
358 byte[] row = Bytes.toBytes("row");
359
360 byte[] fa = Bytes.toBytes("fa");
361 byte[] fami = Bytes.toBytes("fami");
362 byte[] fami1 = Bytes.toBytes("fami1");
363
364 byte[] qual0 = Bytes.toBytes("");
365 byte[] qual1 = Bytes.toBytes("qf1");
366 byte[] qual2 = Bytes.toBytes("qf2");
367 long ts = 1;
368
369
370 KeyValue kv_0 = new KeyValue(row, fa, qual0, ts, Type.Put);
371
372 KeyValue kv0_0 = new KeyValue(row, fami, qual0, ts, Type.Put);
373
374 KeyValue kv0_1 = new KeyValue(row, fami, qual1, ts, Type.Put);
375
376 KeyValue kv0_2 = new KeyValue(row, fami, qual2, ts, Type.Put);
377
378 KeyValue kv1_0 = new KeyValue(row, fami1, qual0, ts, Type.Put);
379
380
381 assertKVLessWithoutRow(c, 0, kv0_1, kv0_2);
382
383 assertKVLessWithoutRow(c, 0, kv0_1, kv1_0);
384
385
386
387
388
389
390
391 int commonLength = KeyValue.ROW_LENGTH_SIZE + KeyValue.FAMILY_LENGTH_SIZE
392 + row.length;
393
394 assertKVLessWithoutRow(c, commonLength + 2, kv_0, kv0_0);
395
396 assertKVLessWithoutRow(c, commonLength + 4, kv0_0, kv0_1);
397
398 assertKVLessWithoutRow(c, commonLength + 4, kv0_1, kv1_0);
399
400 assertKVLessWithoutRow(c, commonLength + 6, kv0_1, kv0_2);
401 }
402
403 public void testFirstLastOnRow() {
404 final KVComparator c = KeyValue.COMPARATOR;
405 long ts = 1;
406
407
408
409 final KeyValue firstOnRowA = KeyValue.createFirstOnRow(rowA);
410 final KeyValue kvA_1 = new KeyValue(rowA, null, null, ts, Type.Put);
411 final KeyValue kvA_2 = new KeyValue(rowA, family, qualA, ts, Type.Put);
412
413 final KeyValue lastOnRowA = KeyValue.createLastOnRow(rowA);
414 final KeyValue firstOnRowB = KeyValue.createFirstOnRow(rowB);
415 final KeyValue kvB = new KeyValue(rowB, family, qualA, ts, Type.Put);
416
417 assertKVLess(c, firstOnRowA, firstOnRowB);
418 assertKVLess(c, firstOnRowA, kvA_1);
419 assertKVLess(c, firstOnRowA, kvA_2);
420 assertKVLess(c, kvA_1, kvA_2);
421 assertKVLess(c, kvA_2, firstOnRowB);
422 assertKVLess(c, kvA_1, firstOnRowB);
423
424 assertKVLess(c, lastOnRowA, firstOnRowB);
425 assertKVLess(c, firstOnRowB, kvB);
426 assertKVLess(c, lastOnRowA, kvB);
427
428 assertKVLess(c, kvA_2, lastOnRowA);
429 assertKVLess(c, kvA_1, lastOnRowA);
430 assertKVLess(c, firstOnRowA, lastOnRowA);
431 }
432
433 public void testCreateKeyOnly() throws Exception {
434 long ts = 1;
435 byte [] value = Bytes.toBytes("a real value");
436 byte [] evalue = new byte[0];
437
438 for (byte[] val : new byte[][]{value, evalue}) {
439 for (boolean useLen : new boolean[]{false,true}) {
440 KeyValue kv1 = new KeyValue(rowA, family, qualA, ts, val);
441 KeyValue kv1ko = kv1.createKeyOnly(useLen);
442
443 assertTrue(kv1.equals(kv1ko));
444
445 assertTrue(kv1ko.getValue().length == (useLen?Bytes.SIZEOF_INT:0));
446 if (useLen) {
447 assertEquals(kv1.getValueLength(), Bytes.toInt(kv1ko.getValue()));
448 }
449 }
450 }
451 }
452
453 public void testCreateKeyValueFromKey() {
454 KeyValue kv = new KeyValue(Bytes.toBytes("myRow"), Bytes.toBytes("myCF"),
455 Bytes.toBytes("myQualifier"), 12345L, Bytes.toBytes("myValue"));
456 int initialPadding = 10;
457 int endingPadding = 20;
458 int keyLen = kv.getKeyLength();
459 byte[] tmpArr = new byte[initialPadding + endingPadding + keyLen];
460 System.arraycopy(kv.getBuffer(), kv.getKeyOffset(), tmpArr,
461 initialPadding, keyLen);
462 KeyValue kvFromKey = KeyValue.createKeyValueFromKey(tmpArr, initialPadding,
463 keyLen);
464 assertEquals(keyLen, kvFromKey.getKeyLength());
465 assertEquals(KeyValue.ROW_OFFSET + keyLen, kvFromKey.getBuffer().length);
466 System.err.println("kv=" + kv);
467 System.err.println("kvFromKey=" + kvFromKey);
468 assertEquals(kvFromKey.toString(),
469 kv.toString().replaceAll("=[0-9]+", "=0"));
470 }
471
472
473
474
475
476
477 public void testReadFields() throws IOException {
478 KeyValue kv1 = new KeyValue(Bytes.toBytes("row1"), Bytes.toBytes("cf1"),
479 Bytes.toBytes("qualifier1"), 12345L, Bytes.toBytes("value1"));
480 kv1.getRow();
481 KeyValue kv2 = new KeyValue(Bytes.toBytes("row2"), Bytes.toBytes("cf2"),
482 Bytes.toBytes("qualifier2"), 12345L, Bytes.toBytes("value2"));
483 kv1.readFields(new DataInputStream(new ByteArrayInputStream(WritableUtils
484 .toByteArray(kv2))));
485
486 assertEquals(kv1, kv2);
487
488 assertTrue(Bytes.equals(kv1.getRow(), kv2.getRow()));
489 }
490
491
492
493
494
495 public void testGetTimestamp() {
496 KeyValue kv = new KeyValue(Bytes.toBytes("myRow"), Bytes.toBytes("myCF"),
497 Bytes.toBytes("myQualifier"), HConstants.LATEST_TIMESTAMP,
498 Bytes.toBytes("myValue"));
499 long time1 = kv.getTimestamp();
500 kv.updateLatestStamp(Bytes.toBytes(12345L));
501 long time2 = kv.getTimestamp();
502 assertEquals(HConstants.LATEST_TIMESTAMP, time1);
503 assertEquals(12345L, time2);
504 }
505
506 @org.junit.Rule
507 public org.apache.hadoop.hbase.ResourceCheckerJUnitRule cu =
508 new org.apache.hadoop.hbase.ResourceCheckerJUnitRule();
509 }
510