/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.hadoop.hbase.filter; import org.apache.hadoop.hbase.KeyValue; import org.apache.hadoop.hbase.KeyValueUtil; import org.apache.hadoop.hbase.testclassification.FilterTests; import org.apache.hadoop.hbase.testclassification.SmallTests; import org.apache.hadoop.hbase.util.Bytes; import org.junit.Assert; import org.junit.Test; import org.junit.experimental.categories.Category; @Category({FilterTests.class, SmallTests.class}) public class TestFuzzyRowFilter { @Test public void testSatisfiesNoUnsafeForward() { Assert.assertEquals(FuzzyRowFilter.SatisfiesCode.YES, FuzzyRowFilter.satisfiesNoUnsafe(false, new byte[]{1, (byte) -128, 1, 0, 1}, 0, 5, new byte[]{1, 0, 1}, new byte[]{0, 1, 0})); Assert.assertEquals(FuzzyRowFilter.SatisfiesCode.NEXT_EXISTS, FuzzyRowFilter.satisfiesNoUnsafe(false, new byte[]{1, (byte) -128, 2, 0, 1}, 0, 5, new byte[]{1, 0, 1}, new byte[]{0, 1, 0})); Assert.assertEquals(FuzzyRowFilter.SatisfiesCode.YES, FuzzyRowFilter.satisfiesNoUnsafe(false, new byte[]{1, 2, 1, 3, 3}, 0, 5, new byte[]{1, 2, 0, 3}, new byte[]{0, 0, 1, 0})); Assert.assertEquals(FuzzyRowFilter.SatisfiesCode.NEXT_EXISTS, FuzzyRowFilter.satisfiesNoUnsafe(false, new byte[]{1, 1, 1, 3, 0}, // row to check 0, 5, new byte[]{1, 2, 0, 3}, // fuzzy row new byte[]{0, 0, 1, 0})); // mask Assert.assertEquals(FuzzyRowFilter.SatisfiesCode.NEXT_EXISTS, FuzzyRowFilter.satisfiesNoUnsafe(false, new byte[]{1, 1, 1, 3, 0}, 0, 5, new byte[]{1, (byte) 245, 0, 3}, new byte[]{0, 0, 1, 0})); Assert.assertEquals(FuzzyRowFilter.SatisfiesCode.NEXT_EXISTS, FuzzyRowFilter.satisfiesNoUnsafe(false, new byte[]{1, 2, 1, 0, 1}, 0, 5, new byte[]{0, 1, 2}, new byte[]{1, 0, 0})); } @Test public void testSatisfiesForward() { Assert.assertEquals(FuzzyRowFilter.SatisfiesCode.YES, FuzzyRowFilter.satisfies(false, new byte[]{1, (byte) -128, 1, 0, 1}, new byte[]{1, 0, 1}, new byte[]{-1, 0, -1})); Assert.assertEquals(FuzzyRowFilter.SatisfiesCode.NEXT_EXISTS, FuzzyRowFilter.satisfies(false, new byte[]{1, (byte) -128, 2, 0, 1}, new byte[]{1, 0, 1}, new byte[]{-1, 0, -1})); Assert.assertEquals(FuzzyRowFilter.SatisfiesCode.YES, FuzzyRowFilter.satisfies(false, new byte[]{1, 2, 1, 3, 3}, new byte[]{1, 2, 0, 3}, new byte[]{-1, -1, 0, -1})); Assert.assertEquals(FuzzyRowFilter.SatisfiesCode.NEXT_EXISTS, FuzzyRowFilter.satisfies(false, new byte[]{1, 1, 1, 3, 0}, // row to check new byte[]{1, 2, 0, 3}, // fuzzy row new byte[]{-1, -1, 0, -1})); // mask Assert.assertEquals(FuzzyRowFilter.SatisfiesCode.NEXT_EXISTS, FuzzyRowFilter.satisfies(false, new byte[]{1, 1, 1, 3, 0}, new byte[]{1, (byte) 245, 0, 3}, new byte[]{-1, -1, 0, -1})); Assert.assertEquals(FuzzyRowFilter.SatisfiesCode.NEXT_EXISTS, FuzzyRowFilter.satisfies(false, new byte[]{1, 2, 1, 0, 1}, new byte[]{0, 1, 2}, new byte[]{0, -1, -1})); } @Test public void testSatisfiesReverse() { Assert.assertEquals(FuzzyRowFilter.SatisfiesCode.YES, FuzzyRowFilter.satisfies(true, new byte[]{1, (byte) -128, 1, 0, 1}, new byte[]{1, 0, 1}, new byte[]{-1, 0, -1})); Assert.assertEquals(FuzzyRowFilter.SatisfiesCode.NEXT_EXISTS, FuzzyRowFilter.satisfies(true, new byte[]{1, (byte) -128, 2, 0, 1}, new byte[]{1, 0, 1}, new byte[]{-1, 0, -1})); Assert.assertEquals(FuzzyRowFilter.SatisfiesCode.NEXT_EXISTS, FuzzyRowFilter.satisfies(true, new byte[]{2, 3, 1, 1, 1}, new byte[]{1, 0, 1}, new byte[]{-1, 0, -1})); Assert.assertEquals(FuzzyRowFilter.SatisfiesCode.YES, FuzzyRowFilter.satisfies(true, new byte[]{1, 2, 1, 3, 3}, new byte[]{1, 2, 0, 3}, new byte[]{-1, -1, 0, -1})); Assert.assertEquals(FuzzyRowFilter.SatisfiesCode.NEXT_EXISTS, FuzzyRowFilter.satisfies(true, new byte[]{1, (byte) 245, 1, 3, 0}, new byte[]{1, 1, 0, 3}, new byte[]{-1, -1, 0, -1})); Assert.assertEquals(FuzzyRowFilter.SatisfiesCode.NEXT_EXISTS, FuzzyRowFilter.satisfies(true, new byte[]{1, 3, 1, 3, 0}, new byte[]{1, 2, 0, 3}, new byte[]{-1, -1, 0, -1})); Assert.assertEquals(FuzzyRowFilter.SatisfiesCode.NEXT_EXISTS, FuzzyRowFilter.satisfies(true, new byte[]{2, 1, 1, 1, 0}, new byte[]{1, 2, 0, 3}, new byte[]{-1, -1, 0, -1})); Assert.assertEquals(FuzzyRowFilter.SatisfiesCode.NEXT_EXISTS, FuzzyRowFilter.satisfies(true, new byte[]{1, 2, 1, 0, 1}, new byte[]{0, 1, 2}, new byte[]{0, -1, -1})); } @Test public void testSatisfiesNoUnsafeReverse() { Assert.assertEquals(FuzzyRowFilter.SatisfiesCode.YES, FuzzyRowFilter.satisfiesNoUnsafe(true, new byte[]{1, (byte) -128, 1, 0, 1}, 0, 5, new byte[]{1, 0, 1}, new byte[]{0, 1, 0})); Assert.assertEquals(FuzzyRowFilter.SatisfiesCode.NEXT_EXISTS, FuzzyRowFilter.satisfiesNoUnsafe(true, new byte[]{1, (byte) -128, 2, 0, 1}, 0, 5, new byte[]{1, 0, 1}, new byte[]{0, 1, 0})); Assert.assertEquals(FuzzyRowFilter.SatisfiesCode.NEXT_EXISTS, FuzzyRowFilter.satisfiesNoUnsafe(true, new byte[]{2, 3, 1, 1, 1}, 0, 5, new byte[]{1, 0, 1}, new byte[]{0, 1, 0})); Assert.assertEquals(FuzzyRowFilter.SatisfiesCode.YES, FuzzyRowFilter.satisfiesNoUnsafe(true, new byte[]{1, 2, 1, 3, 3}, 0, 5, new byte[]{1, 2, 0, 3}, new byte[]{0, 0, 1, 0})); Assert.assertEquals(FuzzyRowFilter.SatisfiesCode.NEXT_EXISTS, FuzzyRowFilter.satisfiesNoUnsafe(true, new byte[]{1, (byte) 245, 1, 3, 0}, 0, 5, new byte[]{1, 1, 0, 3}, new byte[]{0, 0, 1, 0})); Assert.assertEquals(FuzzyRowFilter.SatisfiesCode.NEXT_EXISTS, FuzzyRowFilter.satisfiesNoUnsafe(true, new byte[]{1, 3, 1, 3, 0}, 0, 5, new byte[]{1, 2, 0, 3}, new byte[]{0, 0, 1, 0})); Assert.assertEquals(FuzzyRowFilter.SatisfiesCode.NEXT_EXISTS, FuzzyRowFilter.satisfiesNoUnsafe(true, new byte[]{2, 1, 1, 1, 0}, 0, 5, new byte[]{1, 2, 0, 3}, new byte[]{0, 0, 1, 0})); Assert.assertEquals(FuzzyRowFilter.SatisfiesCode.NEXT_EXISTS, FuzzyRowFilter.satisfiesNoUnsafe(true, new byte[]{1, 2, 1, 0, 1}, 0, 5, new byte[]{0, 1, 2}, new byte[]{1, 0, 0})); } @Test public void testGetNextForFuzzyRuleForward() { assertNext(false, new byte[]{0, 1, 2}, // fuzzy row new byte[]{0, -1, -1}, // mask new byte[]{1, 2, 1, 0, 1}, // current new byte[]{2, 1, 2}); // expected next assertNext(false, new byte[]{0, 1, 2}, // fuzzy row new byte[]{0, -1, -1}, // mask new byte[]{1, 1, 2, 0, 1}, // current new byte[]{1, 1, 2, 0, 2}); // expected next assertNext(false, new byte[]{0, 1, 0, 2, 0}, // fuzzy row new byte[]{0, -1, 0, -1, 0}, // mask new byte[]{1, 0, 2, 0, 1}, // current new byte[]{1, 1, 0, 2}); // expected next assertNext(false, new byte[]{1, 0, 1}, new byte[]{-1, 0, -1}, new byte[]{1, (byte) 128, 2, 0, 1}, new byte[]{1, (byte) 129, 1}); assertNext(false, new byte[]{0, 1, 0, 1}, new byte[]{0, -1, 0, -1}, new byte[]{5, 1, 0, 1}, new byte[]{5, 1, 1, 1}); assertNext(false, new byte[]{0, 1, 0, 1}, new byte[]{0, -1, 0, -1}, new byte[]{5, 1, 0, 1, 1}, new byte[]{5, 1, 0, 1, 2}); assertNext(false, new byte[]{0, 1, 0, 0}, // fuzzy row new byte[]{0, -1, 0, 0}, // mask new byte[]{5, 1, (byte) 255, 1}, // current new byte[]{5, 1, (byte) 255, 2}); // expected next assertNext(false, new byte[]{0, 1, 0, 1}, // fuzzy row new byte[]{0, -1, 0, -1}, // mask new byte[]{5, 1, (byte) 255, 1}, // current new byte[]{6, 1, 0, 1}); // expected next assertNext(false, new byte[]{0, 1, 0, 1}, // fuzzy row new byte[]{0, -1, 0, -1}, // mask new byte[]{5, 1, (byte) 255, 0}, // current new byte[]{5, 1, (byte) 255, 1}); // expected next assertNext(false, new byte[]{5, 1, 1, 0}, new byte[]{-1, -1, 0, 0}, new byte[]{5, 1, (byte) 255, 1}, new byte[]{5, 1, (byte) 255, 2}); assertNext(false, new byte[]{1, 1, 1, 1}, new byte[]{-1, -1, 0, 0}, new byte[]{1, 1, 2, 2}, new byte[]{1, 1, 2, 3}); assertNext(false, new byte[]{1, 1, 1, 1}, new byte[]{-1, -1, 0, 0}, new byte[]{1, 1, 3, 2}, new byte[]{1, 1, 3, 3}); assertNext(false, new byte[]{1, 1, 1, 1}, new byte[]{0, 0, 0, 0}, new byte[]{1, 1, 2, 3}, new byte[]{1, 1, 2, 4}); assertNext(false, new byte[]{1, 1, 1, 1}, new byte[]{0, 0, 0, 0}, new byte[]{1, 1, 3, 2}, new byte[]{1, 1, 3, 3}); assertNext(false, new byte[]{1, 1, 0, 0}, new byte[]{-1, -1, 0, 0}, new byte[]{0, 1, 3, 2}, new byte[]{1, 1}); // No next for this one Assert.assertNull(FuzzyRowFilter.getNextForFuzzyRule( new byte[]{2, 3, 1, 1, 1}, // row to check new byte[]{1, 0, 1}, // fuzzy row new byte[]{-1, 0, -1})); // mask Assert.assertNull(FuzzyRowFilter.getNextForFuzzyRule( new byte[]{1, (byte) 245, 1, 3, 0}, new byte[]{1, 1, 0, 3}, new byte[]{-1, -1, 0, -1})); Assert.assertNull(FuzzyRowFilter.getNextForFuzzyRule( new byte[]{1, 3, 1, 3, 0}, new byte[]{1, 2, 0, 3}, new byte[]{-1, -1, 0, -1})); Assert.assertNull(FuzzyRowFilter.getNextForFuzzyRule( new byte[]{2, 1, 1, 1, 0}, new byte[]{1, 2, 0, 3}, new byte[]{-1, -1, 0, -1})); } @Test public void testGetNextForFuzzyRuleReverse() { assertNext(true, new byte[]{0, 1, 2}, // fuzzy row new byte[]{0, -1, -1}, // mask new byte[]{1, 2, 1, 0, 1}, // current // TODO: should be {1, 1, 3} ? new byte[]{1, 1, 2, (byte) 0xFF, (byte) 0xFF}); // expected next assertNext(true, new byte[]{0, 1, 0, 2, 0}, // fuzzy row new byte[]{0, -1, 0, -1, 0}, // mask new byte[]{1, 2, 1, 3, 1}, // current // TODO: should be {1, 1, 1, 3} ? new byte[]{1, 1, 0, 2, 0}); // expected next assertNext(true, new byte[]{1, 0, 1}, new byte[]{-1, 0, -1}, new byte[]{1, (byte) 128, 2, 0, 1}, // TODO: should be {1, (byte) 128, 2} ? new byte[]{1, (byte) 128, 1, (byte) 0xFF, (byte) 0xFF}); assertNext(true, new byte[]{0, 1, 0, 1}, new byte[]{0, -1, 0, -1}, new byte[]{5, 1, 0, 2, 1}, // TODO: should be {5, 1, 0, 2} ? new byte[]{5, 1, 0, 1, (byte) 0xFF}); assertNext(true, new byte[]{0, 1, 0, 0}, // fuzzy row new byte[]{0, -1, 0, 0}, // mask new byte[]{5, 1, (byte) 255, 1}, // current new byte[]{5, 1, (byte) 255, 0}); // expected next assertNext(true, new byte[]{0, 1, 0, 1}, // fuzzy row new byte[]{0, -1, 0, -1}, // mask new byte[]{5, 1, 0, 1}, // current new byte[]{4, 1, (byte) 255, 1}); // expected next assertNext(true, new byte[]{0, 1, 0, 1}, // fuzzy row new byte[]{0, -1, 0, -1}, // mask new byte[]{5, 1, (byte) 255, 0}, // current new byte[]{5, 1, (byte) 254, 1}); // expected next assertNext(true, new byte[]{1, 1, 0, 0}, new byte[]{-1, -1, 0, 0}, new byte[]{2, 1, 3, 2}, // TODO: should be {1, 0} ? new byte[]{1, 1, 0, 0}); assertNext(true, new byte[]{1, 0, 1}, // fuzzy row new byte[]{-1, 0, -1}, // mask new byte[]{2, 3, 1, 1, 1}, // row to check // TODO: should be {1, (byte) 0xFF, 2} ? new byte[]{1, 0, 1, (byte) 0xFF, (byte) 0xFF}); assertNext(true, new byte[]{1, 1, 0, 3}, new byte[]{-1, -1, 0, -1}, new byte[]{1, (byte) 245, 1, 3, 0}, // TODO: should be {1, 1, (byte) 255, 4} ? new byte[]{1, 1, 0, 3, (byte) 0xFF}); assertNext(true, new byte[]{1, 2, 0, 3}, new byte[]{-1, -1, 0, -1}, new byte[]{1, 3, 1, 3, 0}, // TODO: should be 1, 2, (byte) 255, 4 ? new byte[]{1, 2, 0, 3, (byte) 0xFF}); assertNext(true, new byte[]{1, 2, 0, 3}, new byte[]{-1, -1, 0, -1}, new byte[]{2, 1, 1, 1, 0}, // TODO: should be {1, 2, (byte) 255, 4} ? new byte[]{1, 2, 0, 3, (byte) 0xFF}); assertNext(true, // TODO: should be null? new byte[]{1, 0, 1}, new byte[]{-1, 0, -1}, new byte[]{1, (byte) 128, 2}, new byte[]{1, (byte) 128, 1}); assertNext(true, // TODO: should be null? new byte[]{0, 1, 0, 1}, new byte[]{0, -1, 0, -1}, new byte[]{5, 1, 0, 2}, new byte[]{5, 1, 0, 1}); assertNext(true, // TODO: should be null? new byte[]{5, 1, 1, 0}, new byte[]{-1, -1, 0, 0}, new byte[]{5, 1, (byte) 0xFF, 1}, new byte[]{5, 1, (byte) 0xFF, 0}); assertNext(true, // TODO: should be null? new byte[]{1, 1, 1, 1}, new byte[]{-1, -1, 0, 0}, new byte[]{1, 1, 2, 2}, new byte[]{1, 1, 2, 1}); assertNext(true, // TODO: should be null? new byte[]{1, 1, 1, 1}, new byte[]{0, 0, 0, 0}, new byte[]{1, 1, 2, 3}, new byte[]{1, 1, 2, 2}); Assert.assertNull(FuzzyRowFilter.getNextForFuzzyRule(true, new byte[]{1, 1, 1, 3, 0}, new byte[]{1, 2, 0, 3}, new byte[]{-1, -1, 0, -1})); } private static void assertNext(boolean reverse, byte[] fuzzyRow, byte[] mask, byte[] current, byte[] expected) { KeyValue kv = KeyValueUtil.createFirstOnRow(current); byte[] nextForFuzzyRule = FuzzyRowFilter.getNextForFuzzyRule(reverse, kv.getRowArray(), kv.getRowOffset(), kv.getRowLength(), fuzzyRow, mask); Assert.assertEquals(Bytes.toStringBinary(expected), Bytes.toStringBinary(nextForFuzzyRule)); } }