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