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;
019
020import static org.junit.Assert.assertEquals;
021import static org.junit.Assert.assertTrue;
022
023import java.nio.ByteBuffer;
024import java.util.Collections;
025import java.util.Set;
026import java.util.TreeSet;
027
028import org.apache.hadoop.hbase.KeyValue.Type;
029import org.apache.hadoop.hbase.testclassification.MiscTests;
030import org.apache.hadoop.hbase.testclassification.SmallTests;
031import org.apache.hadoop.hbase.util.Bytes;
032import org.junit.ClassRule;
033import org.junit.Test;
034import org.junit.experimental.categories.Category;
035
036@Category({MiscTests.class, SmallTests.class})
037public class TestCellComparator {
038
039  @ClassRule
040  public static final HBaseClassTestRule CLASS_RULE =
041      HBaseClassTestRule.forClass(TestCellComparator.class);
042
043  private CellComparator comparator = CellComparator.getInstance();
044  byte[] row1 = Bytes.toBytes("row1");
045  byte[] row2 = Bytes.toBytes("row2");
046  byte[] row_1_0 = Bytes.toBytes("row10");
047
048  byte[] fam1 = Bytes.toBytes("fam1");
049  byte[] fam2 = Bytes.toBytes("fam2");
050  byte[] fam_1_2 = Bytes.toBytes("fam12");
051
052  byte[] qual1 = Bytes.toBytes("qual1");
053  byte[] qual2 = Bytes.toBytes("qual2");
054
055  byte[] val = Bytes.toBytes("val");
056
057  @Test
058  public void testCompareCells() {
059    KeyValue kv1 = new KeyValue(row1, fam1, qual1, val);
060    KeyValue kv2 = new KeyValue(row2, fam1, qual1, val);
061    assertTrue((comparator.compare(kv1, kv2)) < 0);
062
063    kv1 = new KeyValue(row1, fam2, qual1, val);
064    kv2 = new KeyValue(row1, fam1, qual1, val);
065    assertTrue((comparator.compareFamilies(kv1, kv2) > 0));
066
067    kv1 = new KeyValue(row1, fam1, qual1, 1L, val);
068    kv2 = new KeyValue(row1, fam1, qual1, 2L, val);
069    assertTrue((comparator.compare(kv1, kv2) > 0));
070
071    kv1 = new KeyValue(row1, fam1, qual1, 1L, Type.Put);
072    kv2 = new KeyValue(row1, fam1, qual1, 1L, Type.Maximum);
073    assertTrue((comparator.compare(kv1, kv2) > 0));
074
075    kv1 = new KeyValue(row1, fam1, qual1, 1L, Type.Put);
076    kv2 = new KeyValue(row1, fam1, qual1, 1L, Type.Put);
077    assertTrue((CellUtil.equals(kv1, kv2)));
078  }
079
080  @Test
081  public void testCompareCellWithKey() throws Exception {
082    KeyValue kv1 = new KeyValue(row1, fam1, qual1, val);
083    KeyValue kv2 = new KeyValue(row2, fam1, qual1, val);
084    assertTrue(
085      (PrivateCellUtil.compare(comparator, kv1, kv2.getKey(), 0, kv2.getKey().length)) < 0);
086
087    kv1 = new KeyValue(row1, fam2, qual1, val);
088    kv2 = new KeyValue(row1, fam1, qual1, val);
089    assertTrue(
090      (PrivateCellUtil.compare(comparator, kv1, kv2.getKey(), 0, kv2.getKey().length)) > 0);
091
092    kv1 = new KeyValue(row1, fam1, qual1, 1L, val);
093    kv2 = new KeyValue(row1, fam1, qual1, 2L, val);
094    assertTrue(
095      (PrivateCellUtil.compare(comparator, kv1, kv2.getKey(), 0, kv2.getKey().length)) > 0);
096
097    kv1 = new KeyValue(row1, fam1, qual1, 1L, Type.Put);
098    kv2 = new KeyValue(row1, fam1, qual1, 1L, Type.Maximum);
099    assertTrue(
100      (PrivateCellUtil.compare(comparator, kv1, kv2.getKey(), 0, kv2.getKey().length)) > 0);
101
102    kv1 = new KeyValue(row1, fam1, qual1, 1L, Type.Put);
103    kv2 = new KeyValue(row1, fam1, qual1, 1L, Type.Put);
104    assertTrue(
105      (PrivateCellUtil.compare(comparator, kv1, kv2.getKey(), 0, kv2.getKey().length)) == 0);
106  }
107
108  @Test
109  public void testCompareByteBufferedCell() {
110    byte[] r1 = Bytes.toBytes("row1");
111    byte[] r2 = Bytes.toBytes("row2");
112    byte[] f1 = Bytes.toBytes("cf1");
113    byte[] q1 = Bytes.toBytes("qual1");
114    byte[] q2 = Bytes.toBytes("qual2");
115    byte[] v = Bytes.toBytes("val1");
116    KeyValue kv = new KeyValue(r1, f1, q1, v);
117    ByteBuffer buffer = ByteBuffer.wrap(kv.getBuffer());
118    Cell bbCell1 = new ByteBufferKeyValue(buffer, 0, buffer.remaining());
119    kv = new KeyValue(r2, f1, q1, v);
120    buffer = ByteBuffer.wrap(kv.getBuffer());
121    Cell bbCell2 = new ByteBufferKeyValue(buffer, 0, buffer.remaining());
122    // compareColumns not on CellComparator so use Impl directly
123    assertEquals(0, CellComparatorImpl.COMPARATOR.compareColumns(bbCell1, bbCell2));
124    assertEquals(0, CellComparatorImpl.COMPARATOR.compareColumns(bbCell1, kv));
125    kv = new KeyValue(r2, f1, q2, v);
126    buffer = ByteBuffer.wrap(kv.getBuffer());
127    Cell bbCell3 = new ByteBufferKeyValue(buffer, 0, buffer.remaining());
128    assertEquals(0, comparator.compareFamilies(bbCell2, bbCell3));
129    assertTrue(comparator.compareQualifiers(bbCell2, bbCell3) < 0);
130    assertTrue(CellComparatorImpl.COMPARATOR.compareColumns(bbCell2, bbCell3) < 0);
131
132    assertEquals(0, comparator.compareRows(bbCell2, bbCell3));
133    assertTrue(comparator.compareRows(bbCell1, bbCell2) < 0);
134  }
135
136  /**
137   * Test meta comparisons using our new ByteBufferKeyValue Cell type, the type we use everywhere
138   * in 2.0.
139   */
140  @Test
141  public void testMetaComparisons() throws Exception {
142    long now = System.currentTimeMillis();
143
144    // Meta compares
145    Cell aaa = createByteBufferKeyValueFromKeyValue(new KeyValue(
146        Bytes.toBytes("TestScanMultipleVersions,row_0500,1236020145502"), now));
147    Cell bbb = createByteBufferKeyValueFromKeyValue(new KeyValue(
148        Bytes.toBytes("TestScanMultipleVersions,,99999999999999"), now));
149    CellComparator c = CellComparatorImpl.META_COMPARATOR;
150    assertTrue(c.compare(bbb, aaa) < 0);
151
152    Cell ccc = createByteBufferKeyValueFromKeyValue(
153        new KeyValue(Bytes.toBytes("TestScanMultipleVersions,,1236023996656"),
154        Bytes.toBytes("info"), Bytes.toBytes("regioninfo"), 1236024396271L,
155        (byte[])null));
156    assertTrue(c.compare(ccc, bbb) < 0);
157
158    Cell x = createByteBufferKeyValueFromKeyValue(
159        new KeyValue(Bytes.toBytes("TestScanMultipleVersions,row_0500,1236034574162"),
160        Bytes.toBytes("info"), Bytes.toBytes(""), 9223372036854775807L,
161        (byte[])null));
162    Cell y = createByteBufferKeyValueFromKeyValue(
163        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  }
168
169  private static Cell createByteBufferKeyValueFromKeyValue(KeyValue kv) {
170    ByteBuffer bb = ByteBuffer.wrap(kv.getBuffer());
171    return new ByteBufferKeyValue(bb, 0, bb.remaining());
172  }
173
174  /**
175   * More tests using ByteBufferKeyValue copied over from TestKeyValue which uses old KVs only.
176   */
177  @Test
178  public void testMetaComparisons2() {
179    long now = System.currentTimeMillis();
180    CellComparator c = CellComparatorImpl.META_COMPARATOR;
181    assertTrue(c.compare(createByteBufferKeyValueFromKeyValue(new KeyValue(
182            Bytes.toBytes(TableName.META_TABLE_NAME.getNameAsString()+",a,,0,1"), now)),
183        createByteBufferKeyValueFromKeyValue(new KeyValue(
184            Bytes.toBytes(TableName.META_TABLE_NAME.getNameAsString()+",a,,0,1"), now))) == 0);
185    Cell a = createByteBufferKeyValueFromKeyValue(new KeyValue(
186        Bytes.toBytes(TableName.META_TABLE_NAME.getNameAsString()+",a,,0,1"), now));
187    Cell b = createByteBufferKeyValueFromKeyValue(new KeyValue(
188        Bytes.toBytes(TableName.META_TABLE_NAME.getNameAsString()+",a,,0,2"), now));
189    assertTrue(c.compare(a, b) < 0);
190    assertTrue(c.compare(createByteBufferKeyValueFromKeyValue(new KeyValue(
191            Bytes.toBytes(TableName.META_TABLE_NAME.getNameAsString()+",a,,0,2"), now)),
192        createByteBufferKeyValueFromKeyValue(new KeyValue(
193            Bytes.toBytes(TableName.META_TABLE_NAME.getNameAsString()+",a,,0,1"), now))) > 0);
194    assertTrue(c.compare(createByteBufferKeyValueFromKeyValue(new KeyValue(
195            Bytes.toBytes(TableName.META_TABLE_NAME.getNameAsString()+",,1"), now)),
196        createByteBufferKeyValueFromKeyValue(new KeyValue(
197            Bytes.toBytes(TableName.META_TABLE_NAME.getNameAsString()+",,1"), now))) == 0);
198    assertTrue(c.compare(createByteBufferKeyValueFromKeyValue(new KeyValue(
199            Bytes.toBytes(TableName.META_TABLE_NAME.getNameAsString()+",,1"), now)),
200        createByteBufferKeyValueFromKeyValue(new KeyValue(
201            Bytes.toBytes(TableName.META_TABLE_NAME.getNameAsString()+",,2"), now))) < 0);
202    assertTrue(c.compare(createByteBufferKeyValueFromKeyValue(new KeyValue(
203            Bytes.toBytes(TableName.META_TABLE_NAME.getNameAsString()+",,2"), now)),
204        createByteBufferKeyValueFromKeyValue(new KeyValue(
205            Bytes.toBytes(TableName.META_TABLE_NAME.getNameAsString()+",,1"), now))) > 0);
206  }
207
208  @Test
209  public void testBinaryKeys() throws Exception {
210    Set<Cell> set = new TreeSet<>(CellComparatorImpl.COMPARATOR);
211    final byte [] fam = Bytes.toBytes("col");
212    final byte [] qf = Bytes.toBytes("umn");
213    final byte [] nb = new byte[0];
214    Cell [] keys = {
215        createByteBufferKeyValueFromKeyValue(
216            new KeyValue(Bytes.toBytes("aaaaa,\u0000\u0000,2"), fam, qf, 2, nb)),
217        createByteBufferKeyValueFromKeyValue(
218            new KeyValue(Bytes.toBytes("aaaaa,\u0001,3"), fam, qf, 3, nb)),
219        createByteBufferKeyValueFromKeyValue(
220            new KeyValue(Bytes.toBytes("aaaaa,,1"), fam, qf, 1, nb)),
221        createByteBufferKeyValueFromKeyValue(
222            new KeyValue(Bytes.toBytes("aaaaa,\u1000,5"), fam, qf, 5, nb)),
223        createByteBufferKeyValueFromKeyValue(
224            new KeyValue(Bytes.toBytes("aaaaa,a,4"), fam, qf, 4, nb)),
225        createByteBufferKeyValueFromKeyValue(
226            new KeyValue(Bytes.toBytes("a,a,0"), fam, qf, 0, nb)),
227    };
228    // Add to set with bad comparator
229    Collections.addAll(set, keys);
230    // This will output the keys incorrectly.
231    boolean assertion = false;
232    int count = 0;
233    try {
234      for (Cell k: set) {
235        assertTrue("count=" + count + ", " + k.toString(), count++ == k.getTimestamp());
236      }
237    } catch (AssertionError e) {
238      // Expected
239      assertion = true;
240    }
241    assertTrue(assertion);
242    // Make set with good comparator
243    set = new TreeSet<>(CellComparatorImpl.META_COMPARATOR);
244    Collections.addAll(set, keys);
245    count = 0;
246    for (Cell k: set) {
247      assertTrue("count=" + count + ", " + k.toString(), count++ == k.getTimestamp());
248    }
249  }
250}