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