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}