View Javadoc

1   /**
2    *
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *     http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   */
19  package org.apache.hadoop.hbase;
20  
21  import java.io.IOException;
22  import java.util.Arrays;
23  import java.util.Set;
24  import java.util.TreeSet;
25  
26  import junit.framework.TestCase;
27  
28  import org.apache.commons.logging.Log;
29  import org.apache.commons.logging.LogFactory;
30  import org.apache.hadoop.hbase.KeyValue.KVComparator;
31  import org.apache.hadoop.hbase.KeyValue.KeyComparator;
32  import org.apache.hadoop.hbase.KeyValue.MetaComparator;
33  import org.apache.hadoop.hbase.KeyValue.Type;
34  import org.apache.hadoop.hbase.util.Bytes;
35  
36  public class TestKeyValue extends TestCase {
37    private final Log LOG = LogFactory.getLog(this.getClass().getName());
38  
39    public void testColumnCompare() throws Exception {
40      final byte [] a = Bytes.toBytes("aaa");
41      byte [] family1 = Bytes.toBytes("abc");
42      byte [] qualifier1 = Bytes.toBytes("def");
43      byte [] family2 = Bytes.toBytes("abcd");
44      byte [] qualifier2 = Bytes.toBytes("ef");
45  
46      KeyValue aaa = new KeyValue(a, family1, qualifier1, 0L, Type.Put, a);
47      assertFalse(aaa.matchingColumn(family2, qualifier2));
48      assertTrue(aaa.matchingColumn(family1, qualifier1));
49      aaa = new KeyValue(a, family2, qualifier2, 0L, Type.Put, a);
50      assertFalse(aaa.matchingColumn(family1, qualifier1));
51      assertTrue(aaa.matchingColumn(family2,qualifier2));
52      byte [] nullQualifier = new byte[0];
53      aaa = new KeyValue(a, family1, nullQualifier, 0L, Type.Put, a);
54      assertTrue(aaa.matchingColumn(family1,null));
55      assertFalse(aaa.matchingColumn(family2,qualifier2));
56    }
57  
58    /**
59     * Test a corner case when the family qualifier is a prefix of the
60     *  column qualifier.
61     */
62    public void testColumnCompare_prefix() throws Exception {
63      final byte [] a = Bytes.toBytes("aaa");
64      byte [] family1 = Bytes.toBytes("abc");
65      byte [] qualifier1 = Bytes.toBytes("def");
66      byte [] family2 = Bytes.toBytes("ab");
67      byte [] qualifier2 = Bytes.toBytes("def");
68  
69      KeyValue aaa = new KeyValue(a, family1, qualifier1, 0L, Type.Put, a);
70      assertFalse(aaa.matchingColumn(family2, qualifier2));
71    }
72  
73    public void testBasics() throws Exception {
74      LOG.info("LOWKEY: " + KeyValue.LOWESTKEY.toString());
75      check(Bytes.toBytes(getName()),
76        Bytes.toBytes(getName()), Bytes.toBytes(getName()), 1,
77        Bytes.toBytes(getName()));
78      // Test empty value and empty column -- both should work. (not empty fam)
79      check(Bytes.toBytes(getName()), Bytes.toBytes(getName()), null, 1, null);
80      check(HConstants.EMPTY_BYTE_ARRAY, Bytes.toBytes(getName()), null, 1, null);
81    }
82  
83    private void check(final byte [] row, final byte [] family, byte [] qualifier,
84      final long timestamp, final byte [] value) {
85      KeyValue kv = new KeyValue(row, family, qualifier, timestamp, value);
86      assertTrue(Bytes.compareTo(kv.getRow(), row) == 0);
87      assertTrue(kv.matchingColumn(family, qualifier));
88      // Call toString to make sure it works.
89      LOG.info(kv.toString());
90    }
91  
92    public void testPlainCompare() throws Exception {
93      final byte [] a = Bytes.toBytes("aaa");
94      final byte [] b = Bytes.toBytes("bbb");
95      final byte [] fam = Bytes.toBytes("col");
96      final byte [] qf = Bytes.toBytes("umn");
97  //    final byte [] column = Bytes.toBytes("col:umn");
98      KeyValue aaa = new KeyValue(a, fam, qf, a);
99      KeyValue bbb = new KeyValue(b, fam, qf, b);
100     byte [] keyabb = aaa.getKey();
101     byte [] keybbb = bbb.getKey();
102     assertTrue(KeyValue.COMPARATOR.compare(aaa, bbb) < 0);
103     assertTrue(KeyValue.KEY_COMPARATOR.compare(keyabb, 0, keyabb.length, keybbb,
104       0, keybbb.length) < 0);
105     assertTrue(KeyValue.COMPARATOR.compare(bbb, aaa) > 0);
106     assertTrue(KeyValue.KEY_COMPARATOR.compare(keybbb, 0, keybbb.length, keyabb,
107       0, keyabb.length) > 0);
108     // Compare breaks if passed same ByteBuffer as both left and right arguments.
109     assertTrue(KeyValue.COMPARATOR.compare(bbb, bbb) == 0);
110     assertTrue(KeyValue.KEY_COMPARATOR.compare(keybbb, 0, keybbb.length, keybbb,
111       0, keybbb.length) == 0);
112     assertTrue(KeyValue.COMPARATOR.compare(aaa, aaa) == 0);
113     assertTrue(KeyValue.KEY_COMPARATOR.compare(keyabb, 0, keyabb.length, keyabb,
114       0, keyabb.length) == 0);
115     // Do compare with different timestamps.
116     aaa = new KeyValue(a, fam, qf, 1, a);
117     bbb = new KeyValue(a, fam, qf, 2, a);
118     assertTrue(KeyValue.COMPARATOR.compare(aaa, bbb) > 0);
119     assertTrue(KeyValue.COMPARATOR.compare(bbb, aaa) < 0);
120     assertTrue(KeyValue.COMPARATOR.compare(aaa, aaa) == 0);
121     // Do compare with different types.  Higher numbered types -- Delete
122     // should sort ahead of lower numbers; i.e. Put
123     aaa = new KeyValue(a, fam, qf, 1, KeyValue.Type.Delete, a);
124     bbb = new KeyValue(a, fam, qf, 1, a);
125     assertTrue(KeyValue.COMPARATOR.compare(aaa, bbb) < 0);
126     assertTrue(KeyValue.COMPARATOR.compare(bbb, aaa) > 0);
127     assertTrue(KeyValue.COMPARATOR.compare(aaa, aaa) == 0);
128   }
129 
130   public void testMoreComparisons() throws Exception {
131     long now = System.currentTimeMillis();
132 
133     // Meta compares
134     KeyValue aaa = new KeyValue(
135         Bytes.toBytes("TestScanMultipleVersions,row_0500,1236020145502"), now);
136     KeyValue bbb = new KeyValue(
137         Bytes.toBytes("TestScanMultipleVersions,,99999999999999"), now);
138     KVComparator c = new KeyValue.MetaComparator();
139     assertTrue(c.compare(bbb, aaa) < 0);
140 
141     KeyValue aaaa = new KeyValue(Bytes.toBytes("TestScanMultipleVersions,,1236023996656"),
142         Bytes.toBytes("info"), Bytes.toBytes("regioninfo"), 1236024396271L,
143         (byte[])null);
144     assertTrue(c.compare(aaaa, bbb) < 0);
145 
146     KeyValue x = new KeyValue(Bytes.toBytes("TestScanMultipleVersions,row_0500,1236034574162"),
147         Bytes.toBytes("info"), Bytes.toBytes(""), 9223372036854775807L,
148         (byte[])null);
149     KeyValue y = new KeyValue(Bytes.toBytes("TestScanMultipleVersions,row_0500,1236034574162"),
150         Bytes.toBytes("info"), Bytes.toBytes("regioninfo"), 1236034574912L,
151         (byte[])null);
152     assertTrue(c.compare(x, y) < 0);
153     comparisons(new KeyValue.MetaComparator());
154     comparisons(new KeyValue.KVComparator());
155     metacomparisons(new KeyValue.MetaComparator());
156   }
157 
158   public void testBadMetaCompareSingleDelim() {
159     MetaComparator c = new KeyValue.MetaComparator();
160     long now = System.currentTimeMillis();
161     // meta keys values are not quite right.  A users can enter illegal values
162     // from shell when scanning meta.
163     KeyValue a = new KeyValue(Bytes.toBytes("table,a1"), now);
164     KeyValue b = new KeyValue(Bytes.toBytes("table,a2"), now);
165     try {
166       c.compare(a, b);
167     } catch (IllegalArgumentException iae) {
168       assertEquals(".META. key must have two ',' delimiters and have the following" +
169       		" format: '<table>,<key>,<etc>'", iae.getMessage());
170       return;
171     }
172     fail("Expected IllegalArgumentException");
173   }
174 
175   public void testMetaComparatorTableKeysWithCommaOk() {
176     MetaComparator c = new KeyValue.MetaComparator();
177     long now = System.currentTimeMillis();
178     // meta keys values are not quite right.  A users can enter illegal values
179     // from shell when scanning meta.
180     KeyValue a = new KeyValue(Bytes.toBytes("table,key,with,commas1,1234"), now);
181     KeyValue b = new KeyValue(Bytes.toBytes("table,key,with,commas2,0123"), now);
182     assertTrue(c.compare(a, b) < 0);
183   }
184 
185   /**
186    * Tests cases where rows keys have characters below the ','.
187    * See HBASE-832
188    * @throws IOException
189    */
190   public void testKeyValueBorderCases() throws IOException {
191     // % sorts before , so if we don't do special comparator, rowB would
192     // come before rowA.
193     KeyValue rowA = new KeyValue(Bytes.toBytes("testtable,www.hbase.org/,1234"),
194       Bytes.toBytes("fam"), Bytes.toBytes(""), Long.MAX_VALUE, (byte[])null);
195     KeyValue rowB = new KeyValue(Bytes.toBytes("testtable,www.hbase.org/%20,99999"),
196         Bytes.toBytes("fam"), Bytes.toBytes(""), Long.MAX_VALUE, (byte[])null);
197     assertTrue(KeyValue.META_COMPARATOR.compare(rowA, rowB) < 0);
198 
199     rowA = new KeyValue(Bytes.toBytes("testtable,,1234"), Bytes.toBytes("fam"),
200         Bytes.toBytes(""), Long.MAX_VALUE, (byte[])null);
201     rowB = new KeyValue(Bytes.toBytes("testtable,$www.hbase.org/,99999"),
202         Bytes.toBytes("fam"), Bytes.toBytes(""), Long.MAX_VALUE, (byte[])null);
203     assertTrue(KeyValue.META_COMPARATOR.compare(rowA, rowB) < 0);
204 
205   }
206 
207   private void metacomparisons(final KeyValue.MetaComparator c) {
208     long now = System.currentTimeMillis();
209     assertTrue(c.compare(new KeyValue(
210         Bytes.toBytes(TableName.META_TABLE_NAME.getNameAsString()+",a,,0,1"), now),
211       new KeyValue(
212           Bytes.toBytes(TableName.META_TABLE_NAME.getNameAsString()+",a,,0,1"), now)) == 0);
213     KeyValue a = new KeyValue(
214         Bytes.toBytes(TableName.META_TABLE_NAME.getNameAsString()+",a,,0,1"), now);
215     KeyValue b = new KeyValue(
216         Bytes.toBytes(TableName.META_TABLE_NAME.getNameAsString()+",a,,0,2"), now);
217     assertTrue(c.compare(a, b) < 0);
218     assertTrue(c.compare(new KeyValue(
219         Bytes.toBytes(TableName.META_TABLE_NAME.getNameAsString()+",a,,0,2"), now),
220       new KeyValue(
221           Bytes.toBytes(TableName.META_TABLE_NAME.getNameAsString()+",a,,0,1"), now)) > 0);
222   }
223 
224   private void comparisons(final KeyValue.KVComparator c) {
225     long now = System.currentTimeMillis();
226     assertTrue(c.compare(new KeyValue(
227         Bytes.toBytes(TableName.META_TABLE_NAME.getNameAsString()+",,1"), now),
228       new KeyValue(
229           Bytes.toBytes(TableName.META_TABLE_NAME.getNameAsString()+",,1"), now)) == 0);
230     assertTrue(c.compare(new KeyValue(
231         Bytes.toBytes(TableName.META_TABLE_NAME.getNameAsString()+",,1"), now),
232       new KeyValue(
233           Bytes.toBytes(TableName.META_TABLE_NAME.getNameAsString()+",,2"), now)) < 0);
234     assertTrue(c.compare(new KeyValue(
235         Bytes.toBytes(TableName.META_TABLE_NAME.getNameAsString()+",,2"), now),
236       new KeyValue(
237           Bytes.toBytes(TableName.META_TABLE_NAME.getNameAsString()+",,1"), now)) > 0);
238   }
239 
240   public void testBinaryKeys() throws Exception {
241     Set<KeyValue> set = new TreeSet<KeyValue>(KeyValue.COMPARATOR);
242     final byte [] fam = Bytes.toBytes("col");
243     final byte [] qf = Bytes.toBytes("umn");
244     final byte [] nb = new byte[0];
245     KeyValue [] keys = {new KeyValue(Bytes.toBytes("aaaaa,\u0000\u0000,2"), fam, qf, 2, nb),
246       new KeyValue(Bytes.toBytes("aaaaa,\u0001,3"), fam, qf, 3, nb),
247       new KeyValue(Bytes.toBytes("aaaaa,,1"), fam, qf, 1, nb),
248       new KeyValue(Bytes.toBytes("aaaaa,\u1000,5"), fam, qf, 5, nb),
249       new KeyValue(Bytes.toBytes("aaaaa,a,4"), fam, qf, 4, nb),
250       new KeyValue(Bytes.toBytes("a,a,0"), fam, qf, 0, nb),
251     };
252     // Add to set with bad comparator
253     for (int i = 0; i < keys.length; i++) {
254       set.add(keys[i]);
255     }
256     // This will output the keys incorrectly.
257     boolean assertion = false;
258     int count = 0;
259     try {
260       for (KeyValue k: set) {
261         assertTrue(count++ == k.getTimestamp());
262       }
263     } catch (junit.framework.AssertionFailedError e) {
264       // Expected
265       assertion = true;
266     }
267     assertTrue(assertion);
268     // Make set with good comparator
269     set = new TreeSet<KeyValue>(new KeyValue.MetaComparator());
270     for (int i = 0; i < keys.length; i++) {
271       set.add(keys[i]);
272     }
273     count = 0;
274     for (KeyValue k: set) {
275       assertTrue(count++ == k.getTimestamp());
276     }
277   }
278 
279   public void testStackedUpKeyValue() {
280     // Test multiple KeyValues in a single blob.
281 
282     // TODO actually write this test!
283 
284   }
285 
286   private final byte[] rowA = Bytes.toBytes("rowA");
287   private final byte[] rowB = Bytes.toBytes("rowB");
288 
289   private final byte[] family = Bytes.toBytes("family");
290   private final byte[] qualA = Bytes.toBytes("qfA");
291   private final byte[] qualB = Bytes.toBytes("qfB");
292 
293   private void assertKVLess(KeyValue.KVComparator c,
294                             KeyValue less,
295                             KeyValue greater) {
296     int cmp = c.compare(less,greater);
297     assertTrue(cmp < 0);
298     cmp = c.compare(greater,less);
299     assertTrue(cmp > 0);
300   }
301 
302   private void assertKVLessWithoutRow(KeyValue.KeyComparator c, int common, KeyValue less,
303       KeyValue greater) {
304     int cmp = c.compareIgnoringPrefix(common, less.getBuffer(), less.getOffset()
305         + KeyValue.ROW_OFFSET, less.getKeyLength(), greater.getBuffer(),
306         greater.getOffset() + KeyValue.ROW_OFFSET, greater.getKeyLength());
307     assertTrue(cmp < 0);
308     cmp = c.compareIgnoringPrefix(common, greater.getBuffer(), greater.getOffset()
309         + KeyValue.ROW_OFFSET, greater.getKeyLength(), less.getBuffer(),
310         less.getOffset() + KeyValue.ROW_OFFSET, less.getKeyLength());
311     assertTrue(cmp > 0);
312   }
313 
314   public void testCompareWithoutRow() {
315     final KeyValue.KeyComparator c = KeyValue.KEY_COMPARATOR;
316     byte[] row = Bytes.toBytes("row");
317 
318     byte[] fa = Bytes.toBytes("fa");
319     byte[] fami = Bytes.toBytes("fami");
320     byte[] fami1 = Bytes.toBytes("fami1");
321 
322     byte[] qual0 = Bytes.toBytes("");
323     byte[] qual1 = Bytes.toBytes("qf1");
324     byte[] qual2 = Bytes.toBytes("qf2");
325     long ts = 1;
326 
327     // 'fa:'
328     KeyValue kv_0 = new KeyValue(row, fa, qual0, ts, Type.Put);
329     // 'fami:'
330     KeyValue kv0_0 = new KeyValue(row, fami, qual0, ts, Type.Put);
331     // 'fami:qf1'
332     KeyValue kv0_1 = new KeyValue(row, fami, qual1, ts, Type.Put);
333     // 'fami:qf2'
334     KeyValue kv0_2 = new KeyValue(row, fami, qual2, ts, Type.Put);
335     // 'fami1:'
336     KeyValue kv1_0 = new KeyValue(row, fami1, qual0, ts, Type.Put);
337 
338     // 'fami:qf1' < 'fami:qf2'
339     assertKVLessWithoutRow(c, 0, kv0_1, kv0_2);
340     // 'fami:qf1' < 'fami1:'
341     assertKVLessWithoutRow(c, 0, kv0_1, kv1_0);
342 
343     // Test comparison by skipping the same prefix bytes.
344     /***
345      * KeyValue Format and commonLength:
346      * |_keyLen_|_valLen_|_rowLen_|_rowKey_|_famiLen_|_fami_|_Quali_|....
347      * ------------------|-------commonLength--------|--------------
348      */
349     int commonLength = KeyValue.ROW_LENGTH_SIZE + KeyValue.FAMILY_LENGTH_SIZE
350         + row.length;
351     // 'fa:' < 'fami:'. They have commonPrefix + 2 same prefix bytes.
352     assertKVLessWithoutRow(c, commonLength + 2, kv_0, kv0_0);
353     // 'fami:' < 'fami:qf1'. They have commonPrefix + 4 same prefix bytes.
354     assertKVLessWithoutRow(c, commonLength + 4, kv0_0, kv0_1);
355     // 'fami:qf1' < 'fami1:'. They have commonPrefix + 4 same prefix bytes.
356     assertKVLessWithoutRow(c, commonLength + 4, kv0_1, kv1_0);
357     // 'fami:qf1' < 'fami:qf2'. They have commonPrefix + 6 same prefix bytes.
358     assertKVLessWithoutRow(c, commonLength + 6, kv0_1, kv0_2);
359   }
360 
361   public void testFirstLastOnRow() {
362     final KVComparator c = KeyValue.COMPARATOR;
363     long ts = 1;
364     byte[] bufferA = new byte[128];
365     int offsetA = 0;
366     byte[] bufferB = new byte[128];
367     int offsetB = 7;
368 
369     // These are listed in sort order (ie: every one should be less
370     // than the one on the next line).
371     final KeyValue firstOnRowA = KeyValue.createFirstOnRow(rowA);
372     final KeyValue firstOnRowABufferFamQual = KeyValue.createFirstOnRow(bufferA, offsetA,
373         rowA, 0, rowA.length, family, 0, family.length, qualA, 0, qualA.length);
374     final KeyValue kvA_1 = new KeyValue(rowA, null, null, ts, Type.Put);
375     final KeyValue kvA_2 = new KeyValue(rowA, family, qualA, ts, Type.Put);
376 
377     final KeyValue lastOnRowA = KeyValue.createLastOnRow(rowA);
378     final KeyValue firstOnRowB = KeyValue.createFirstOnRow(rowB);
379     final KeyValue firstOnRowBBufferFam = KeyValue.createFirstOnRow(bufferB, offsetB,
380         rowB, 0, rowB.length, family, 0, family.length, null, 0, 0);
381     final KeyValue kvB = new KeyValue(rowB, family, qualA, ts, Type.Put);
382 
383     assertKVLess(c, firstOnRowA, firstOnRowB);
384     assertKVLess(c, firstOnRowA, firstOnRowBBufferFam);
385     assertKVLess(c, firstOnRowABufferFamQual, firstOnRowB);
386     assertKVLess(c, firstOnRowA, kvA_1);
387     assertKVLess(c, firstOnRowA, kvA_2);
388     assertKVLess(c, firstOnRowABufferFamQual, kvA_2);
389     assertKVLess(c, kvA_1, kvA_2);
390     assertKVLess(c, kvA_2, firstOnRowB);
391     assertKVLess(c, kvA_1, firstOnRowB);
392     assertKVLess(c, kvA_2, firstOnRowBBufferFam);
393     assertKVLess(c, kvA_1, firstOnRowBBufferFam);
394 
395     assertKVLess(c, lastOnRowA, firstOnRowB);
396     assertKVLess(c, lastOnRowA, firstOnRowBBufferFam);
397     assertKVLess(c, firstOnRowB, kvB);
398     assertKVLess(c, firstOnRowBBufferFam, kvB);
399     assertKVLess(c, lastOnRowA, kvB);
400 
401     assertKVLess(c, kvA_2, lastOnRowA);
402     assertKVLess(c, kvA_1, lastOnRowA);
403     assertKVLess(c, firstOnRowA, lastOnRowA);
404     assertKVLess(c, firstOnRowABufferFamQual, lastOnRowA);
405   }
406 
407   public void testCreateKeyOnly() throws Exception {
408     long ts = 1;
409     byte [] value = Bytes.toBytes("a real value");
410     byte [] evalue = new byte[0]; // empty value
411 
412     for (byte[] val : new byte[][]{value, evalue}) {
413       for (boolean useLen : new boolean[]{false,true}) {
414         KeyValue kv1 = new KeyValue(rowA, family, qualA, ts, val);
415         KeyValue kv1ko = kv1.createKeyOnly(useLen);
416         // keys are still the same
417         assertTrue(kv1.equals(kv1ko));
418         // but values are not
419         assertTrue(kv1ko.getValue().length == (useLen?Bytes.SIZEOF_INT:0));
420         if (useLen) {
421           assertEquals(kv1.getValueLength(), Bytes.toInt(kv1ko.getValue()));
422         }
423       }
424     }
425   }
426 
427   public void testCreateKeyValueFromKey() {
428     KeyValue kv = new KeyValue(Bytes.toBytes("myRow"), Bytes.toBytes("myCF"),
429         Bytes.toBytes("myQualifier"), 12345L, Bytes.toBytes("myValue"));
430     int initialPadding = 10;
431     int endingPadding = 20;
432     int keyLen = kv.getKeyLength();
433     byte[] tmpArr = new byte[initialPadding + endingPadding + keyLen];
434     System.arraycopy(kv.getBuffer(), kv.getKeyOffset(), tmpArr,
435         initialPadding, keyLen);
436     KeyValue kvFromKey = KeyValue.createKeyValueFromKey(tmpArr, initialPadding,
437         keyLen);
438     assertEquals(keyLen, kvFromKey.getKeyLength());
439     assertEquals(KeyValue.ROW_OFFSET + keyLen, kvFromKey.getBuffer().length);
440     System.err.println("kv=" + kv);
441     System.err.println("kvFromKey=" + kvFromKey);
442     assertEquals(kvFromKey.toString(),
443         kv.toString().replaceAll("=[0-9]+", "=0"));
444   }
445 
446   /**
447    * Tests that getTimestamp() does always return the proper timestamp, even after updating it.
448    * See HBASE-6265.
449    */
450   public void testGetTimestamp() {
451     KeyValue kv = new KeyValue(Bytes.toBytes("myRow"), Bytes.toBytes("myCF"),
452       Bytes.toBytes("myQualifier"), HConstants.LATEST_TIMESTAMP,
453       Bytes.toBytes("myValue"));
454     long time1 = kv.getTimestamp();
455     kv.updateLatestStamp(Bytes.toBytes(12345L));
456     long time2 = kv.getTimestamp();
457     assertEquals(HConstants.LATEST_TIMESTAMP, time1);
458     assertEquals(12345L, time2);
459   }
460 
461   /**
462    * See HBASE-7845
463    */
464   public void testGetShortMidpointKey() {
465     final KeyComparator keyComparator = new KeyValue.KeyComparator();
466     //verify that faked shorter rowkey could be generated
467     long ts = 5;
468     KeyValue kv1 = new KeyValue(Bytes.toBytes("the quick brown fox"), family, qualA, ts, Type.Put);
469     KeyValue kv2 = new KeyValue(Bytes.toBytes("the who test text"), family, qualA, ts, Type.Put);
470     byte[] newKey = keyComparator.getShortMidpointKey(kv1.getKey(), kv2.getKey());
471     assertTrue(keyComparator.compare(kv1.getKey(), newKey) < 0);
472     assertTrue(keyComparator.compare(newKey, kv2.getKey()) < 0);
473     short newRowLength = Bytes.toShort(newKey, 0);
474     byte[] expectedArray = Bytes.toBytes("the r");
475     Bytes.equals(newKey, KeyValue.ROW_LENGTH_SIZE, newRowLength, expectedArray, 0,
476       expectedArray.length);
477 
478     //verify: same with "row + family + qualifier", return rightKey directly
479     kv1 = new KeyValue(Bytes.toBytes("ilovehbase"), family, qualA, 5, Type.Put);
480     kv2 = new KeyValue(Bytes.toBytes("ilovehbase"), family, qualA, 0, Type.Put);
481     assertTrue(keyComparator.compare(kv1.getKey(), kv2.getKey()) < 0);
482     newKey = keyComparator.getShortMidpointKey(kv1.getKey(), kv2.getKey());
483     assertTrue(keyComparator.compare(kv1.getKey(), newKey) < 0);
484     assertTrue(keyComparator.compare(newKey, kv2.getKey()) == 0);
485     kv1 = new KeyValue(Bytes.toBytes("ilovehbase"), family, qualA, -5, Type.Put);
486     kv2 = new KeyValue(Bytes.toBytes("ilovehbase"), family, qualA, -10, Type.Put);
487     assertTrue(keyComparator.compare(kv1.getKey(), kv2.getKey()) < 0);
488     newKey = keyComparator.getShortMidpointKey(kv1.getKey(), kv2.getKey());
489     assertTrue(keyComparator.compare(kv1.getKey(), newKey) < 0);
490     assertTrue(keyComparator.compare(newKey, kv2.getKey()) == 0);
491 
492     // verify: same with row, different with qualifier
493     kv1 = new KeyValue(Bytes.toBytes("ilovehbase"), family, qualA, 5, Type.Put);
494     kv2 = new KeyValue(Bytes.toBytes("ilovehbase"), family, qualB, 5, Type.Put);
495     assertTrue(keyComparator.compare(kv1.getKey(), kv2.getKey()) < 0);
496     newKey = keyComparator.getShortMidpointKey(kv1.getKey(), kv2.getKey());
497     assertTrue(keyComparator.compare(kv1.getKey(), newKey) < 0);
498     assertTrue(keyComparator.compare(newKey, kv2.getKey()) < 0);
499     KeyValue newKeyValue = KeyValue.createKeyValueFromKey(newKey);
500     assertTrue(Arrays.equals(newKeyValue.getFamily(),family));
501     assertTrue(Arrays.equals(newKeyValue.getQualifier(),qualB));
502     assertTrue(newKeyValue.getTimestamp() == HConstants.LATEST_TIMESTAMP);
503     assertTrue(newKeyValue.getType() == Type.Maximum.getCode());
504 
505     //verify metaKeyComparator's getShortMidpointKey output
506     final KeyComparator metaKeyComparator = new KeyValue.MetaKeyComparator();
507     kv1 = new KeyValue(Bytes.toBytes("ilovehbase123"), family, qualA, 5, Type.Put);
508     kv2 = new KeyValue(Bytes.toBytes("ilovehbase234"), family, qualA, 0, Type.Put);
509     newKey = metaKeyComparator.getShortMidpointKey(kv1.getKey(), kv2.getKey());
510     assertTrue(metaKeyComparator.compare(kv1.getKey(), newKey) < 0);
511     assertTrue(metaKeyComparator.compare(newKey, kv2.getKey()) == 0);
512 
513     //verify common fix scenario
514     kv1 = new KeyValue(Bytes.toBytes("ilovehbase"), family, qualA, ts, Type.Put);
515     kv2 = new KeyValue(Bytes.toBytes("ilovehbaseandhdfs"), family, qualA, ts, Type.Put);
516     assertTrue(keyComparator.compare(kv1.getKey(), kv2.getKey()) < 0);
517     newKey = keyComparator.getShortMidpointKey(kv1.getKey(), kv2.getKey());
518     assertTrue(keyComparator.compare(kv1.getKey(), newKey) < 0);
519     assertTrue(keyComparator.compare(newKey, kv2.getKey()) == 0);
520   }
521 }