diff options
author | Jon Bratseth <bratseth@yahoo-inc.com> | 2016-06-15 23:09:44 +0200 |
---|---|---|
committer | Jon Bratseth <bratseth@yahoo-inc.com> | 2016-06-15 23:09:44 +0200 |
commit | 72231250ed81e10d66bfe70701e64fa5fe50f712 (patch) | |
tree | 2728bba1131a6f6e5bdf95afec7d7ff9358dac50 /predicate-search/src/test/java/com/yahoo/search/predicate/annotator/PredicateTreeAnnotatorTest.java |
Publish
Diffstat (limited to 'predicate-search/src/test/java/com/yahoo/search/predicate/annotator/PredicateTreeAnnotatorTest.java')
-rw-r--r-- | predicate-search/src/test/java/com/yahoo/search/predicate/annotator/PredicateTreeAnnotatorTest.java | 271 |
1 files changed, 271 insertions, 0 deletions
diff --git a/predicate-search/src/test/java/com/yahoo/search/predicate/annotator/PredicateTreeAnnotatorTest.java b/predicate-search/src/test/java/com/yahoo/search/predicate/annotator/PredicateTreeAnnotatorTest.java new file mode 100644 index 00000000000..7ccc910a4bf --- /dev/null +++ b/predicate-search/src/test/java/com/yahoo/search/predicate/annotator/PredicateTreeAnnotatorTest.java @@ -0,0 +1,271 @@ +// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.search.predicate.annotator; + +import com.google.common.primitives.Ints; +import com.yahoo.document.predicate.FeatureConjunction; +import com.yahoo.document.predicate.FeatureRange; +import com.yahoo.document.predicate.Predicate; +import com.yahoo.document.predicate.PredicateHash; +import com.yahoo.document.predicate.RangeEdgePartition; +import com.yahoo.document.predicate.RangePartition; +import com.yahoo.search.predicate.index.Feature; +import com.yahoo.search.predicate.index.conjunction.IndexableFeatureConjunction; +import com.yahoo.search.predicate.index.IntervalWithBounds; +import org.apache.commons.lang.ArrayUtils; +import org.junit.Test; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import static com.yahoo.document.predicate.Predicates.and; +import static com.yahoo.document.predicate.Predicates.feature; +import static com.yahoo.document.predicate.Predicates.not; +import static com.yahoo.document.predicate.Predicates.or; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +public class PredicateTreeAnnotatorTest { + + @Test + public void require_that_or_intervals_are_the_same() { + Predicate p = + or( + feature("key1").inSet("value1"), + feature("key2").inSet("value2")); + PredicateTreeAnnotations r = PredicateTreeAnnotator.createPredicateTreeAnnotations(p); + assertEquals(1, r.minFeature); + assertEquals(2, r.intervalEnd); + assertEquals(2, r.intervalMap.size()); + assertIntervalContains(r, "key1=value1", 0x00010002); + assertIntervalContains(r, "key2=value2", 0x00010002); + } + + @Test + public void require_that_ands_below_ors_get_different_intervals() { + Predicate p = + or( + and( + feature("key1").inSet("value1"), + feature("key1").inSet("value1"), + feature("key1").inSet("value1")), + and( + feature("key2").inSet("value2"), + feature("key2").inSet("value2"), + feature("key2").inSet("value2"))); + PredicateTreeAnnotations r = PredicateTreeAnnotator.createPredicateTreeAnnotations(p); + assertEquals(1, r.minFeature); + assertEquals(6, r.intervalEnd); + assertEquals(2, r.intervalMap.size()); + assertIntervalContains(r, "key1=value1", 0x00010001, 0x00020002, 0x00030006); + assertIntervalContains(r, "key2=value2", 0x00010004, 0x00050005, 0x00060006); + } + + @Test + public void require_that_nots_get_correct_intervals() { + Predicate p = + and( + feature("key").inSet("value"), + not(feature("key").inSet("value")), + feature("key").inSet("value"), + not(feature("key").inSet("value"))); + PredicateTreeAnnotations r = PredicateTreeAnnotator.createPredicateTreeAnnotations(p); + assertEquals(2, r.minFeature); + assertEquals(6, r.intervalEnd); + assertEquals(2, r.intervalMap.size()); + assertIntervalContains(r, "key=value", 0x00010001, 0x00020002, 0x00040004, 0x00050005); + assertIntervalContains(r, Feature.Z_STAR_COMPRESSED_ATTRIBUTE_NAME, 0x00020001, 0x00050004); + } + + @Test + public void require_that_final_first_not_interval_is_extended() { + Predicate p = not(feature("key").inSet("A")); + PredicateTreeAnnotations r = PredicateTreeAnnotator.createPredicateTreeAnnotations(p); + assertEquals(1, r.minFeature); + assertEquals(2, r.intervalEnd); + assertEquals(2, r.intervalMap.size()); + assertIntervalContains(r, "key=A", 0x00010001); + assertIntervalContains(r, Feature.Z_STAR_COMPRESSED_ATTRIBUTE_NAME, 0x00010000); + } + + @Test + public void show_different_types_of_not_intervals() { + { + Predicate p = + and( + or( + and( + feature("key").inSet("A"), + not(feature("key").inSet("B"))), + and( + not(feature("key").inSet("C")), + feature("key").inSet("D"))), + feature("foo").inSet("bar")); + PredicateTreeAnnotations r = PredicateTreeAnnotator.createPredicateTreeAnnotations(p); + assertEquals(3, r.minFeature); + assertEquals(7, r.intervalEnd); + assertEquals(6, r.intervalMap.size()); + + assertIntervalContains(r, "foo=bar", 0x00070007); + assertIntervalContains(r, "key=A", 0x00010001); + assertIntervalContains(r, "key=B", 0x00020002); + assertIntervalContains(r, "key=C", 0x00010004); + assertIntervalContains(r, "key=D", 0x00060006); + assertIntervalContains(r, Feature.Z_STAR_COMPRESSED_ATTRIBUTE_NAME, 0x00020001, 0x00000006, 0x00040000); + } + { + Predicate p = + or( + not(feature("key").inSet("A")), + not(feature("key").inSet("B"))); + + PredicateTreeAnnotations r = PredicateTreeAnnotator.createPredicateTreeAnnotations(p); + assertEquals(1, r.minFeature); + assertEquals(4, r.intervalEnd); + assertEquals(3, r.intervalMap.size()); + assertIntervalContains(r, "key=A", 0x00010003); + assertIntervalContains(r, "key=B", 0x00010003); + assertIntervalContains(r, Feature.Z_STAR_COMPRESSED_ATTRIBUTE_NAME, 0x00030000, 0x00030000); + } + { + Predicate p = + or( + and( + not(feature("key").inSet("A")), + not(feature("key").inSet("B"))), + and( + not(feature("key").inSet("C")), + not(feature("key").inSet("D")))); + + PredicateTreeAnnotations r = PredicateTreeAnnotator.createPredicateTreeAnnotations(p); + assertEquals(1, r.minFeature); + assertEquals(8, r.intervalEnd); + assertEquals(5, r.intervalMap.size()); + assertIntervalContains(r, "key=A", 0x00010001); + assertIntervalContains(r, "key=B", 0x00030007); + assertIntervalContains(r, "key=C", 0x00010005); + assertIntervalContains(r, "key=D", 0x00070007); + assertIntervalContains(r, Feature.Z_STAR_COMPRESSED_ATTRIBUTE_NAME, + 0x00010000, 0x00070002, 0x00050000, 0x00070006); + } + } + + @Test + public void require_that_hashed_ranges_get_correct_intervals() { + Predicate p = + and( + range("key", + partition("key=10-19"), + partition("key=20-29"), + edgePartition("key=0", 5, 10, 20), + edgePartition("key=30", 0, 0, 3)), + range("foo", + partition("foo=10-19"), + partition("foo=20-29"), + edgePartition("foo=0", 5, 40, 60), + edgePartition("foo=30", 0, 0, 3))); + + + PredicateTreeAnnotations r = PredicateTreeAnnotator.createPredicateTreeAnnotations(p); + assertEquals(2, r.minFeature); + assertEquals(2, r.intervalEnd); + assertEquals(4, r.intervalMap.size()); + assertEquals(4, r.boundsMap.size()); + assertIntervalContains(r, "key=10-19", 0x00010001); + assertIntervalContains(r, "key=20-29", 0x00010001); + assertBoundsContains(r, "key=0", bound(0x00010001, 0x000a0015)); // [10..20] + assertBoundsContains(r, "key=30", bound(0x00010001, 0x40000004)); // [..3] + + assertIntervalContains(r, "foo=10-19", 0x00020002); + assertIntervalContains(r, "foo=20-29", 0x00020002); + assertBoundsContains(r, "foo=0", bound(0x00020002, 0x0028003d)); // [40..60] + assertBoundsContains(r, "foo=30", bound(0x00020002, 0x40000004)); // [..3] + } + + @Test + public void require_that_extreme_ranges_works() { + Predicate p = + and( + range("max range", partition("max range=9223372036854775806-9223372036854775807")), + range("max edge", edgePartition("max edge=9223372036854775807", 0, 0, 1)), + range("min range", partition("min range=-9223372036854775807-9223372036854775806")), + range("min edge", edgePartition("min edge=-9223372036854775808", 0, 0, 1))); + PredicateTreeAnnotations r = PredicateTreeAnnotator.createPredicateTreeAnnotations(p); + assertEquals(4, r.minFeature); + assertEquals(4, r.intervalEnd); + assertEquals(2, r.intervalMap.size()); + assertEquals(2, r.boundsMap.size()); + assertIntervalContains(r, "max range=9223372036854775806-9223372036854775807", 0x00010001); + assertBoundsContains(r, "max edge=9223372036854775807", bound(0x00020002, 0x40000002)); + assertIntervalContains(r, "min range=-9223372036854775807-9223372036854775806", 0x00030003); + assertBoundsContains(r, "min edge=-9223372036854775808", bound(0x00040004, 0x40000002)); + } + + @Test + public void require_that_featureconjunctions_are_registered_and_given_an_interval() { + Predicate p = + and( + or( + range("key", + partition("key=10-19"), + partition("key=20-29"), + edgePartition("key=0", 5, 10, 20), + edgePartition("key=30", 0, 0, 3)), + conj( + not(feature("keyA").inSet("C")), + feature("keyB").inSet("D"))), + feature("foo").inSet("bar")); + PredicateTreeAnnotations r = PredicateTreeAnnotator.createPredicateTreeAnnotations(p); + assertEquals(2, r.minFeature); + assertEquals(3, r.intervalEnd); + assertEquals(3, r.intervalMap.size()); + assertEquals(2, r.boundsMap.size()); + assertEquals(1, r.featureConjunctions.size()); + + Map.Entry<IndexableFeatureConjunction, List<Integer>> entry = r.featureConjunctions.entrySet().iterator().next(); + assertEquals(1, entry.getValue().size()); + assertEquals(0b1_0000000000000010, entry.getValue().get(0).longValue()); + } + + private static void assertIntervalContains(PredicateTreeAnnotations r, String feature, Integer... expectedIntervals) { + long hash = PredicateHash.hash64(feature); + List<Integer> actualIntervals = r.intervalMap.get(hash); + assertNotNull(actualIntervals); + assertArrayEquals(ArrayUtils.toPrimitive(expectedIntervals), Ints.toArray(actualIntervals)); + } + + private static void assertBoundsContains(PredicateTreeAnnotations r, String feature, IntervalWithBounds expectedBounds) { + long hash = PredicateHash.hash64(feature); + List<IntervalWithBounds> actualBounds = r.boundsMap.get(hash); + assertNotNull(actualBounds); + assertEquals(1, actualBounds.size()); + assertEquals(expectedBounds, actualBounds.get(0)); + } + + private static IntervalWithBounds bound(int interval, int bounds) { + return new IntervalWithBounds(interval, bounds); + } + + private static RangePartition partition(String label) { + return new RangePartition(label); + } + + private static RangePartition edgePartition(String label, long value, int lower, int upper) { + return new RangeEdgePartition(label, value, lower, upper); + } + + private static FeatureRange range(String key, RangePartition... partitions) { + return range(key, null, null, partitions); + } + + private static FeatureRange range(String key, Long lower, Long upper, RangePartition... partitions) { + FeatureRange range = new FeatureRange(key, lower, upper); + Arrays.asList(partitions).forEach(range::addPartition); + return range; + } + + private static FeatureConjunction conj(Predicate... operands) { + return new FeatureConjunction(Arrays.asList(operands)); + } +} |