summaryrefslogtreecommitdiffstats
path: root/container-search/src/test/java
diff options
context:
space:
mode:
authorHenning Baldersheim <balder@yahoo-inc.com>2021-09-30 17:09:59 +0200
committerGitHub <noreply@github.com>2021-09-30 17:09:59 +0200
commitc75ff9433d7d8e7d1a0186592b57597ae632581c (patch)
tree9bed7a0bcca7752796a6c0bf2ead31694fcb4037 /container-search/src/test/java
parent041de033862d7e9ee8ff16770cd5cc63a11b5d16 (diff)
parent253fe67dfae65ab11ed008590403ffbe10fab02e (diff)
Merge branch 'master' into balder/do-not-depend-on-clusterinfo
Diffstat (limited to 'container-search/src/test/java')
-rw-r--r--container-search/src/test/java/com/yahoo/prelude/cluster/ClusterSearcherTestCase.java6
-rw-r--r--container-search/src/test/java/com/yahoo/prelude/fastsearch/SlimeSummaryTestCase.java23
-rw-r--r--container-search/src/test/java/com/yahoo/prelude/fastsearch/test/FastSearcherTestCase.java22
-rw-r--r--container-search/src/test/java/com/yahoo/prelude/fastsearch/test/documentdb-info.cfg4
-rw-r--r--container-search/src/test/java/com/yahoo/prelude/query/ItemsCommonStuffTestCase.java79
-rw-r--r--container-search/src/test/java/com/yahoo/prelude/query/parser/TestLinguistics.java4
-rw-r--r--container-search/src/test/java/com/yahoo/prelude/query/parser/test/ExactMatchAndDefaultIndexTestCase.java9
-rw-r--r--container-search/src/test/java/com/yahoo/prelude/query/parser/test/ParseTestCase.java396
-rw-r--r--container-search/src/test/java/com/yahoo/prelude/query/parser/test/ParsingTester.java30
-rw-r--r--container-search/src/test/java/com/yahoo/prelude/query/parser/test/TokenizerTestCase.java115
-rw-r--r--container-search/src/test/java/com/yahoo/prelude/query/parser/test/replacingtokens.cfg12
-rw-r--r--container-search/src/test/java/com/yahoo/prelude/query/test/QueryCanonicalizerTestCase.java43
-rw-r--r--container-search/src/test/java/com/yahoo/prelude/query/test/SameElementItemTestCase.java19
-rw-r--r--container-search/src/test/java/com/yahoo/prelude/querytransform/test/CJKSearcherTestCase.java2
-rw-r--r--container-search/src/test/java/com/yahoo/prelude/querytransform/test/LiteralBoostSearcherTestCase.java2
-rw-r--r--container-search/src/test/java/com/yahoo/prelude/querytransform/test/QueryRewriteTestCase.java4
-rw-r--r--container-search/src/test/java/com/yahoo/prelude/searcher/test/FieldCollapsingSearcherTestCase.java264
-rw-r--r--container-search/src/test/java/com/yahoo/prelude/searcher/test/PosSearcherTestCase.java11
-rw-r--r--container-search/src/test/java/com/yahoo/prelude/searcher/test/ValidatePredicateSearcherTestCase.java14
-rw-r--r--container-search/src/test/java/com/yahoo/prelude/semantics/test/ExpansionTestCase.java33
-rw-r--r--container-search/src/test/java/com/yahoo/prelude/semantics/test/ProductionRuleTestCase.java2
-rw-r--r--container-search/src/test/java/com/yahoo/prelude/semantics/test/RuleBaseAbstractTestCase.java4
-rw-r--r--container-search/src/test/java/com/yahoo/prelude/semantics/test/SegmentSubstitutionTestCase.java8
-rw-r--r--container-search/src/test/java/com/yahoo/prelude/semantics/test/SemanticSearcherTestCase.java15
-rw-r--r--container-search/src/test/java/com/yahoo/prelude/semantics/test/WeightingTestCase.java12
-rw-r--r--container-search/src/test/java/com/yahoo/prelude/semantics/test/rulebases/expansion.sr8
-rw-r--r--container-search/src/test/java/com/yahoo/prelude/test/IndexFactsTestCase.java6
-rw-r--r--container-search/src/test/java/com/yahoo/prelude/test/QueryTestCase.java6
-rw-r--r--container-search/src/test/java/com/yahoo/search/StupidSingleThreadedHttpServer.java166
-rw-r--r--container-search/src/test/java/com/yahoo/search/dispatch/DispatcherTest.java54
-rw-r--r--container-search/src/test/java/com/yahoo/search/dispatch/InterleavedSearchInvokerTest.java99
-rw-r--r--container-search/src/test/java/com/yahoo/search/dispatch/LeanHitTest.java12
-rw-r--r--container-search/src/test/java/com/yahoo/search/dispatch/LoadBalancerTest.java1
-rw-r--r--container-search/src/test/java/com/yahoo/search/dispatch/MockInvoker.java16
-rw-r--r--container-search/src/test/java/com/yahoo/search/dispatch/MockSearchCluster.java12
-rw-r--r--container-search/src/test/java/com/yahoo/search/dispatch/SearchPathTest.java56
-rw-r--r--container-search/src/test/java/com/yahoo/search/dispatch/TopKEstimatorTest.java168
-rw-r--r--container-search/src/test/java/com/yahoo/search/dispatch/rpc/MockClient.java2
-rw-r--r--container-search/src/test/java/com/yahoo/search/dispatch/rpc/RpcSearchInvokerTest.java18
-rw-r--r--container-search/src/test/java/com/yahoo/search/dispatch/searchcluster/SearchClusterCoverageTest.java141
-rw-r--r--container-search/src/test/java/com/yahoo/search/dispatch/searchcluster/SearchClusterTest.java62
-rw-r--r--container-search/src/test/java/com/yahoo/search/dispatch/searchcluster/SearchClusterTester.java33
-rw-r--r--container-search/src/test/java/com/yahoo/search/grouping/GroupingRequestTestCase.java4
-rw-r--r--container-search/src/test/java/com/yahoo/search/grouping/UniqueGroupingSearcherTestCase.java6
-rw-r--r--container-search/src/test/java/com/yahoo/search/grouping/vespa/IntegerEmbedderTestCase.java (renamed from container-search/src/test/java/com/yahoo/search/grouping/vespa/IntegerEncoderTestCase.java)2
-rw-r--r--container-search/src/test/java/com/yahoo/search/handler/SearchHandlerTest.java (renamed from container-search/src/test/java/com/yahoo/search/handler/test/SearchHandlerTestCase.java)29
-rw-r--r--container-search/src/test/java/com/yahoo/search/handler/test/JSONSearchHandlerTestCase.java191
-rw-r--r--container-search/src/test/java/com/yahoo/search/handler/test/config/chains.cfg16
-rw-r--r--container-search/src/test/java/com/yahoo/search/handler/test/config/handlers.cfg15
-rw-r--r--container-search/src/test/java/com/yahoo/search/handler/test/config/handlers2/chains.cfg8
-rw-r--r--container-search/src/test/java/com/yahoo/search/handler/test/config/handlersInvalid/handlers.cfg2
-rw-r--r--container-search/src/test/java/com/yahoo/search/query/MatchingTestCase.java17
-rw-r--r--container-search/src/test/java/com/yahoo/search/query/SoftTimeoutTestCase.java17
-rw-r--r--container-search/src/test/java/com/yahoo/search/query/profile/compiled/BindingTestCase.java56
-rw-r--r--container-search/src/test/java/com/yahoo/search/query/profile/compiled/CompiledQueryProfileRegistryTest.java29
-rw-r--r--container-search/src/test/java/com/yahoo/search/query/profile/config/test/QueryProfileConfigurationTestCase.java14
-rw-r--r--container-search/src/test/java/com/yahoo/search/query/profile/config/test/XmlReadingTestCase.java100
-rw-r--r--container-search/src/test/java/com/yahoo/search/query/profile/config/test/inheritance/child.xml6
-rw-r--r--container-search/src/test/java/com/yahoo/search/query/profile/config/test/inheritance/parent.xml7
-rw-r--r--container-search/src/test/java/com/yahoo/search/query/profile/config/test/newscase4/default.xml2
-rw-r--r--container-search/src/test/java/com/yahoo/search/query/profile/config/test/newscase4/parent.xml2
-rw-r--r--container-search/src/test/java/com/yahoo/search/query/profile/config/test/tensortypes/profile1.xml1
-rw-r--r--container-search/src/test/java/com/yahoo/search/query/profile/config/test/tensortypes/profile2.xml1
-rw-r--r--container-search/src/test/java/com/yahoo/search/query/profile/config/test/tensortypes/types/type1.xml1
-rw-r--r--container-search/src/test/java/com/yahoo/search/query/profile/config/test/tensortypes/types/type2.xml1
-rw-r--r--container-search/src/test/java/com/yahoo/search/query/profile/config/test/typed/components.cfg1
-rw-r--r--container-search/src/test/java/com/yahoo/search/query/profile/config/test/untyped/components.cfg1
-rw-r--r--container-search/src/test/java/com/yahoo/search/query/profile/config/test/variants/default.xml5
-rw-r--r--container-search/src/test/java/com/yahoo/search/query/profile/config/test/variants/inherited.xml11
-rw-r--r--container-search/src/test/java/com/yahoo/search/query/profile/config/test/variants/main.xml5
-rw-r--r--container-search/src/test/java/com/yahoo/search/query/profile/test/QueryProfileSubstitutionTestCase.java2
-rw-r--r--container-search/src/test/java/com/yahoo/search/query/profile/test/QueryProfileTestCase.java18
-rw-r--r--container-search/src/test/java/com/yahoo/search/query/profile/test/QueryProfileVariantsTestCase.java84
-rw-r--r--container-search/src/test/java/com/yahoo/search/query/profile/types/test/MandatoryTestCase.java2
-rw-r--r--container-search/src/test/java/com/yahoo/search/query/profile/types/test/NativePropertiesTestCase.java9
-rw-r--r--container-search/src/test/java/com/yahoo/search/query/profile/types/test/OverrideTestCase.java3
-rw-r--r--container-search/src/test/java/com/yahoo/search/query/profile/types/test/QueryProfileTypeTestCase.java319
-rw-r--r--container-search/src/test/java/com/yahoo/search/query/rewrite/RewriterFeaturesTestCase.java2
-rw-r--r--container-search/src/test/java/com/yahoo/search/querytransform/WeakAndReplacementSearcherTestCase.java120
-rw-r--r--container-search/src/test/java/com/yahoo/search/querytransform/test/SortingDegraderTestCase.java13
-rw-r--r--container-search/src/test/java/com/yahoo/search/rendering/JsonRendererTestCase.java93
-rw-r--r--container-search/src/test/java/com/yahoo/search/result/FeatureDataTestCase.java10
-rw-r--r--container-search/src/test/java/com/yahoo/search/searchchain/config/test/SearchChainConfigurerTestCase.java40
-rw-r--r--container-search/src/test/java/com/yahoo/search/searchchain/config/test/dependencyConfig/handlers.cfg3
-rw-r--r--container-search/src/test/java/com/yahoo/search/searchchain/config/test/handlers.cfg3
-rw-r--r--container-search/src/test/java/com/yahoo/search/searchchain/config/test/testInstances/components.cfg1
-rw-r--r--container-search/src/test/java/com/yahoo/search/searchchain/test/AsyncExecutionOfOneChainTestCase.java12
-rw-r--r--container-search/src/test/java/com/yahoo/search/searchers/ValidateNearestNeighborTestCase.java77
-rw-r--r--container-search/src/test/java/com/yahoo/search/searchers/test/InputCheckingSearcherTestCase.java50
-rw-r--r--container-search/src/test/java/com/yahoo/search/searchers/test/QueryValidatorTestCase.java51
-rw-r--r--container-search/src/test/java/com/yahoo/search/test/QueryTestCase.java153
-rw-r--r--container-search/src/test/java/com/yahoo/search/yql/MinimalQueryInserterTestCase.java9
-rw-r--r--container-search/src/test/java/com/yahoo/search/yql/UserInputTestCase.java46
-rw-r--r--container-search/src/test/java/com/yahoo/search/yql/VespaSerializerTestCase.java18
-rw-r--r--container-search/src/test/java/com/yahoo/search/yql/YqlParserTestCase.java92
-rw-r--r--container-search/src/test/java/com/yahoo/select/SelectTestCase.java283
-rw-r--r--container-search/src/test/java/com/yahoo/vespa/streamingvisitors/VdsVisitorTestCase.java4
97 files changed, 2766 insertions, 1294 deletions
diff --git a/container-search/src/test/java/com/yahoo/prelude/cluster/ClusterSearcherTestCase.java b/container-search/src/test/java/com/yahoo/prelude/cluster/ClusterSearcherTestCase.java
index 5382999f96a..38c231cb1bb 100644
--- a/container-search/src/test/java/com/yahoo/prelude/cluster/ClusterSearcherTestCase.java
+++ b/container-search/src/test/java/com/yahoo/prelude/cluster/ClusterSearcherTestCase.java
@@ -13,7 +13,6 @@ import com.yahoo.prelude.IndexFacts;
import com.yahoo.prelude.IndexModel;
import com.yahoo.prelude.SearchDefinition;
import com.yahoo.prelude.fastsearch.DocumentdbInfoConfig;
-import com.yahoo.prelude.fastsearch.FS4ResourcePool;
import com.yahoo.prelude.fastsearch.FastHit;
import com.yahoo.prelude.fastsearch.VespaBackEndSearcher;
import com.yahoo.prelude.fastsearch.test.MockMetric;
@@ -528,8 +527,9 @@ public class ClusterSearcherTestCase {
clusterConfig.build(),
documentDbConfig.build(),
dispatchers,
- new FS4ResourcePool(new QrConfig.Builder().build()),
- vipStatus);
+ new QrConfig.Builder().build(),
+ vipStatus,
+ null);
}
private static class QueryTimeoutFixture {
diff --git a/container-search/src/test/java/com/yahoo/prelude/fastsearch/SlimeSummaryTestCase.java b/container-search/src/test/java/com/yahoo/prelude/fastsearch/SlimeSummaryTestCase.java
index d1399cabc75..49df321e581 100644
--- a/container-search/src/test/java/com/yahoo/prelude/fastsearch/SlimeSummaryTestCase.java
+++ b/container-search/src/test/java/com/yahoo/prelude/fastsearch/SlimeSummaryTestCase.java
@@ -4,16 +4,21 @@ package com.yahoo.prelude.fastsearch;
import com.google.common.collect.ImmutableSet;
import com.yahoo.config.subscription.ConfigGetter;
import com.yahoo.data.access.slime.SlimeAdapter;
+import com.yahoo.prelude.hitfield.JSONString;
import com.yahoo.prelude.hitfield.RawData;
import com.yahoo.prelude.hitfield.XMLString;
-import com.yahoo.prelude.hitfield.JSONString;
import com.yahoo.search.result.FeatureData;
import com.yahoo.search.result.Hit;
-import com.yahoo.search.result.NanNumber;
import com.yahoo.search.result.StructuredData;
+import com.yahoo.slime.BinaryFormat;
+import com.yahoo.slime.Cursor;
+import com.yahoo.slime.Slime;
+import com.yahoo.tensor.Tensor;
+import com.yahoo.tensor.serialization.TypedBinaryFormat;
+import org.junit.Test;
+
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
-
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Iterator;
@@ -21,14 +26,6 @@ import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
-import com.yahoo.slime.BinaryFormat;
-import com.yahoo.slime.Cursor;
-import com.yahoo.slime.Inspector;
-import com.yahoo.slime.Slime;
-import com.yahoo.tensor.Tensor;
-import com.yahoo.tensor.serialization.TypedBinaryFormat;
-import org.junit.Test;
-
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
@@ -102,7 +99,7 @@ public class SlimeSummaryTestCase {
if (hit.getField("jsonstring_field") instanceof JSONString) {
JSONString jstr = (JSONString) hit.getField("jsonstring_field");
assertEquals("{\"foo\":1,\"bar\":2}", jstr.getContent());
- assertNotNull(jstr.getParsedJSON());
+ assertNotNull(getParsedJSON(jstr));
com.yahoo.data.access.Inspector value = jstr.inspect();
assertEquals(1L, value.field("foo").asLong());
@@ -126,6 +123,8 @@ public class SlimeSummaryTestCase {
assertEquals(tensor2, featureData.getTensor("tensor2_feature"));
}
+ @SuppressWarnings("removal") private static Object getParsedJSON(JSONString jstr) { return jstr.getParsedJSON(); }
+
@Test
public void testFieldAccessAPI() {
DocsumDefinitionSet partialDocsum1 = createDocsumDefinitionSet(partial_summary1_cf);
diff --git a/container-search/src/test/java/com/yahoo/prelude/fastsearch/test/FastSearcherTestCase.java b/container-search/src/test/java/com/yahoo/prelude/fastsearch/test/FastSearcherTestCase.java
index 63475c9c189..9e45c7ef245 100644
--- a/container-search/src/test/java/com/yahoo/prelude/fastsearch/test/FastSearcherTestCase.java
+++ b/container-search/src/test/java/com/yahoo/prelude/fastsearch/test/FastSearcherTestCase.java
@@ -3,6 +3,7 @@ package com.yahoo.prelude.fastsearch.test;
import com.google.common.collect.ImmutableList;
import com.yahoo.component.chain.Chain;
+import com.yahoo.config.subscription.ConfigGetter;
import com.yahoo.container.QrSearchersConfig;
import com.yahoo.container.handler.VipStatus;
import com.yahoo.container.protect.Error;
@@ -11,6 +12,7 @@ import com.yahoo.prelude.fastsearch.ClusterParams;
import com.yahoo.prelude.fastsearch.DocumentdbInfoConfig;
import com.yahoo.prelude.fastsearch.FastSearcher;
import com.yahoo.prelude.fastsearch.SummaryParameters;
+import com.yahoo.prelude.fastsearch.VespaBackEndSearcher;
import com.yahoo.search.Query;
import com.yahoo.search.Result;
import com.yahoo.search.Searcher;
@@ -32,6 +34,7 @@ import java.util.logging.Level;
import java.util.logging.Logger;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
@@ -105,6 +108,25 @@ public class FastSearcherTestCase {
}
@Test
+ public void testSummaryNeedsQuery() {
+ ConfigGetter<DocumentdbInfoConfig> getter = new ConfigGetter<>(DocumentdbInfoConfig.class);
+ DocumentdbInfoConfig config = getter.getConfig("file:src/test/java/com/yahoo/prelude/fastsearch/test/documentdb-info.cfg");
+ FastSearcher backend = new FastSearcher("container.0",
+ MockDispatcher.create(Collections.singletonList(new Node(0, "host0", 0))),
+ new SummaryParameters(null),
+ new ClusterParams("testhittype"),
+ config);
+ Query q = new Query("?query=foo");
+ Result result = doSearch(backend, q, 0, 10);
+ assertFalse(backend.summaryNeedsQuery(q));
+
+ q = new Query("?query=select+*+from+source+where+title+contains+%22foobar%22+and++geoLocation%28myfieldname%2C+63.5%2C+10.5%2C+%22999+km%22%29%3B");
+ q.getModel().setType(Query.Type.YQL);
+ result = doSearch(backend, q, 0, 10);
+ assertTrue(backend.summaryNeedsQuery(q));
+ }
+
+ @Test
public void testSinglePassGroupingIsNotForcedWithSingleNodeGroups() {
MockDispatcher dispatcher = MockDispatcher.create(ImmutableList.of(new Node(0, "host0", 0), new Node(2, "host1", 0)));
diff --git a/container-search/src/test/java/com/yahoo/prelude/fastsearch/test/documentdb-info.cfg b/container-search/src/test/java/com/yahoo/prelude/fastsearch/test/documentdb-info.cfg
index f69e0ed7a54..cc65ab2565e 100644
--- a/container-search/src/test/java/com/yahoo/prelude/fastsearch/test/documentdb-info.cfg
+++ b/container-search/src/test/java/com/yahoo/prelude/fastsearch/test/documentdb-info.cfg
@@ -348,4 +348,6 @@ documentdb[0].summaryclass[6].fields[29].name URLLIST
documentdb[0].summaryclass[6].fields[29].type string
documentdb[0].summaryclass[6].fields[30].name WORDS
documentdb[0].summaryclass[6].fields[30].type integer
-documentdb[0].rankprofile[0]
+documentdb[0].rankprofile[0].name "default"
+documentdb[0].rankprofile[0].hasSummaryFeatures false
+documentdb[0].rankprofile[0].hasRankFeatures false
diff --git a/container-search/src/test/java/com/yahoo/prelude/query/ItemsCommonStuffTestCase.java b/container-search/src/test/java/com/yahoo/prelude/query/ItemsCommonStuffTestCase.java
index 38911ef83c5..02175425808 100644
--- a/container-search/src/test/java/com/yahoo/prelude/query/ItemsCommonStuffTestCase.java
+++ b/container-search/src/test/java/com/yahoo/prelude/query/ItemsCommonStuffTestCase.java
@@ -9,8 +9,6 @@ import java.util.ListIterator;
import java.util.NoSuchElementException;
import java.util.regex.PatternSyntaxException;
-import org.junit.After;
-import org.junit.Before;
import org.junit.Test;
import com.yahoo.prelude.query.Item.ItemType;
@@ -18,20 +16,12 @@ import com.yahoo.prelude.query.Item.ItemType;
/**
* Check basic contracts common to "many" item implementations.
*
- * @author <a href="mailto:steinar@yahoo-inc.com">Steinar Knutsen</a>
+ * @author Steinar Knutsen
*/
public class ItemsCommonStuffTestCase {
- @Before
- public void setUp() throws Exception {
- }
-
- @After
- public void tearDown() throws Exception {
- }
-
@Test
- public final void testLoops() {
+ public void testLoops() {
AndSegmentItem as = new AndSegmentItem("farmyards", false, false);
boolean caught = false;
try {
@@ -52,7 +42,7 @@ public class ItemsCommonStuffTestCase {
a.addItem(as);
try {
as.addItem(a);
- } catch (QueryException e) {
+ } catch (IllegalArgumentException e) {
caught = true;
}
assertTrue(caught);
@@ -61,24 +51,24 @@ public class ItemsCommonStuffTestCase {
as.addItem(a);
try {
a.addItem(as);
- } catch (QueryException e) {
+ } catch (IllegalArgumentException e) {
caught = true;
}
assertTrue(caught);
}
@Test
- public final void testIndexName() {
+ public void testIndexName() {
WordItem w = new WordItem("nalle");
AndItem a = new AndItem();
a.addItem(w);
- final String expected = "mobil";
+ String expected = "mobil";
a.setIndexName(expected);
assertEquals(expected, w.getIndexName());
}
@Test
- public final void testBoundaries() {
+ public void testBoundaries() {
WordItem w = new WordItem("nalle");
AndItem a = new AndItem();
boolean caught = false;
@@ -112,7 +102,7 @@ public class ItemsCommonStuffTestCase {
}
@Test
- public final void testRemoving() {
+ public void testRemoving() {
AndItem other = new AndItem();
WordItem w = new WordItem("nalle");
AndItem a = new AndItem();
@@ -127,7 +117,7 @@ public class ItemsCommonStuffTestCase {
}
@Test
- public final void testGeneralMutability() {
+ public void testGeneralMutability() {
AndItem a = new AndItem();
assertFalse(a.isLocked());
a.lock();
@@ -135,7 +125,7 @@ public class ItemsCommonStuffTestCase {
}
@Test
- public final void testCounting() {
+ public void testCounting() {
WordItem w = new WordItem("nalle");
AndItem a = new AndItem();
WordItem v = new WordItem("bamse");
@@ -149,7 +139,7 @@ public class ItemsCommonStuffTestCase {
}
@Test
- public final void testIteratorJuggling() {
+ public void testIteratorJuggling() {
AndItem a = new AndItem();
WordItem w0 = new WordItem("nalle");
WordItem w1 = new WordItem("bamse");
@@ -178,9 +168,9 @@ public class ItemsCommonStuffTestCase {
}
@Test
- public final void testIdStuff() {
+ public void testIdStuff() {
Item i;
- final String expected = "i";
+ String expected = "i";
i = new ExactStringItem(expected);
assertEquals(ItemType.EXACT, i.getItemType());
assertEquals("EXACTSTRING", i.getName());
@@ -202,11 +192,11 @@ public class ItemsCommonStuffTestCase {
assertEquals("SAND", i.getName());
i = new WeakAndItem();
assertEquals(ItemType.WEAK_AND, i.getItemType());
- assertEquals("WAND", i.getName());
+ assertEquals("WEAKAND", i.getName());
}
@Test
- public final void testEquivBuilding() {
+ public void testEquivBuilding() {
WordItem w = new WordItem("nalle");
WordItem v = new WordItem("bamse");
w.setConnectivity(v, 1.0);
@@ -220,8 +210,8 @@ public class ItemsCommonStuffTestCase {
WordItem w = new WordItem("nalle");
WordItem v = new WordItem("bamse");
w.setConnectivity(v, 1.0);
- final String expected = "puppy";
- final String expected2 = "kvalp";
+ String expected = "puppy";
+ String expected2 = "kvalp";
EquivItem e = new EquivItem(w, Arrays.asList(new String[] { expected, expected2 }));
assertEquals(1.0, e.getConnectivity(), 1e-9);
assertSame(v, e.getConnectedItem());
@@ -230,12 +220,12 @@ public class ItemsCommonStuffTestCase {
}
@Test
- public final void testSegment() {
+ public void testSegment() {
AndSegmentItem as = new AndSegmentItem("farmyards", false, false);
assertFalse(as.isLocked());
- final WordItem firstItem = new WordItem("nalle");
+ WordItem firstItem = new WordItem("nalle");
as.addItem(firstItem);
- final WordItem item = new WordItem("bamse");
+ WordItem item = new WordItem("bamse");
as.addItem(1, item);
assertTrue(as.removeItem(item));
assertFalse(as.isFromUser());
@@ -245,28 +235,28 @@ public class ItemsCommonStuffTestCase {
boolean caught = false;
try {
as.removeItem(firstItem);
- } catch (QueryException e) {
+ } catch (IllegalArgumentException e) {
caught = true;
}
assertTrue(caught);
caught = false;
try {
as.addItem(new WordItem("puppy"));
- } catch (QueryException e) {
+ } catch (IllegalArgumentException e) {
caught= true;
}
assertTrue(caught);
caught = false;
try {
as.addItem(1, new WordItem("kvalp"));
- } catch (QueryException e) {
+ } catch (IllegalArgumentException e) {
caught = true;
}
assertTrue(caught);
}
@Test
- public final void testMarkersVsWords() {
+ public void testMarkersVsWords() {
WordItem mw0 = MarkerWordItem.createEndOfHost();
WordItem mw1 = MarkerWordItem.createStartOfHost();
WordItem w0 = new WordItem("$");
@@ -279,11 +269,11 @@ public class ItemsCommonStuffTestCase {
}
@Test
- public final void testNumberBasics() {
- final String expected = "12";
+ public void testNumberBasics() {
+ String expected = "12";
IntItem i = new IntItem(expected, "num");
assertEquals(expected, i.stringValue());
- final String expected2 = "34";
+ String expected2 = "34";
i.setNumber(expected2);
assertEquals(expected2, i.stringValue());
String expected3 = "56";
@@ -297,7 +287,7 @@ public class ItemsCommonStuffTestCase {
}
@Test
- public final void testNullItemFailsProperly() {
+ public void testNullItemFailsProperly() {
NullItem n = new NullItem();
n.setIndexName("nalle");
boolean caught = false;
@@ -324,7 +314,7 @@ public class ItemsCommonStuffTestCase {
}
@Test
- public final void testNearisNotAnd() {
+ public void testNearisNotAnd() {
AndItem a = new AndItem();
NearItem n = new NearItem();
n.setDistance(2);
@@ -343,7 +333,7 @@ public class ItemsCommonStuffTestCase {
}
@Test
- public final void testPhraseSegmentBasics() {
+ public void testPhraseSegmentBasics() {
AndSegmentItem a = new AndSegmentItem("gnurk", "gurk", false, false);
fill(a);
a.lock();
@@ -365,7 +355,7 @@ public class ItemsCommonStuffTestCase {
}
@Test
- public final void testPhraseConnectivity() {
+ public void testPhraseConnectivity() {
WordItem w = new WordItem("a");
PhraseItem p = new PhraseItem();
fill(p);
@@ -375,7 +365,7 @@ public class ItemsCommonStuffTestCase {
}
@Test
- public final void testBaseClassPhraseSegments() {
+ public void testBaseClassPhraseSegments() {
PhraseSegmentItem p = new PhraseSegmentItem("g", false, true);
fill(p);
assertEquals(4, p.encode(ByteBuffer.allocate(5000)));
@@ -386,7 +376,7 @@ public class ItemsCommonStuffTestCase {
}
@Test
- public final void testTermTypeBasic() {
+ public void testTermTypeBasic() {
assertFalse(TermType.AND.equals(TermType.DEFAULT));
assertFalse(TermType.AND.equals(Integer.valueOf(10)));
assertTrue(TermType.AND.equals(TermType.AND));
@@ -397,7 +387,7 @@ public class ItemsCommonStuffTestCase {
}
@Test
- public final void testRegexp() {
+ public void testRegexp() {
RegExpItem empty = new RegExpItem("a", true, "");
assertTrue(empty.isFromQuery());
assertTrue(empty.isStemmed());
@@ -416,5 +406,6 @@ public class ItemsCommonStuffTestCase {
}
assertEquals("Dangling meta character '*' near index 0\n" + "*\n" + "^", last.getMessage());
}
+
}
diff --git a/container-search/src/test/java/com/yahoo/prelude/query/parser/TestLinguistics.java b/container-search/src/test/java/com/yahoo/prelude/query/parser/TestLinguistics.java
index b697841a969..332d91dc125 100644
--- a/container-search/src/test/java/com/yahoo/prelude/query/parser/TestLinguistics.java
+++ b/container-search/src/test/java/com/yahoo/prelude/query/parser/TestLinguistics.java
@@ -60,6 +60,10 @@ public class TestLinguistics implements Linguistics {
return linguistics.getCharacterClasses();
}
+ public boolean equals(Linguistics other) {
+ return (other instanceof TestLinguistics);
+ }
+
}
diff --git a/container-search/src/test/java/com/yahoo/prelude/query/parser/test/ExactMatchAndDefaultIndexTestCase.java b/container-search/src/test/java/com/yahoo/prelude/query/parser/test/ExactMatchAndDefaultIndexTestCase.java
index 5cae40bd10d..df35d8dbdea 100644
--- a/container-search/src/test/java/com/yahoo/prelude/query/parser/test/ExactMatchAndDefaultIndexTestCase.java
+++ b/container-search/src/test/java/com/yahoo/prelude/query/parser/test/ExactMatchAndDefaultIndexTestCase.java
@@ -11,6 +11,7 @@ import org.junit.Test;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
import java.util.Collections;
import static org.junit.Assert.assertEquals;
@@ -34,7 +35,7 @@ public class ExactMatchAndDefaultIndexTestCase {
q.getModel().setExecution(new Execution(new Execution.Context(null, facts, null, null, null)));
assertEquals("AND testexact:a/b testexact:foo.com", q.getModel().getQueryTree().getRoot().toString());
q = new Query("?query=" + enc("a/b foo.com"));
- assertEquals("AND \"a b\" \"foo com\"", q.getModel().getQueryTree().getRoot().toString());
+ assertEquals("AND a b foo com", q.getModel().getQueryTree().getRoot().toString());
}
@Test
@@ -44,11 +45,7 @@ public class ExactMatchAndDefaultIndexTestCase {
}
private String enc(String s) {
- try {
- return URLEncoder.encode(s, "utf-8");
- } catch (UnsupportedEncodingException e) {
- throw new RuntimeException(e);
- }
+ return URLEncoder.encode(s, StandardCharsets.UTF_8);
}
}
diff --git a/container-search/src/test/java/com/yahoo/prelude/query/parser/test/ParseTestCase.java b/container-search/src/test/java/com/yahoo/prelude/query/parser/test/ParseTestCase.java
index 0fdad1a1f9c..8ca711297d3 100644
--- a/container-search/src/test/java/com/yahoo/prelude/query/parser/test/ParseTestCase.java
+++ b/container-search/src/test/java/com/yahoo/prelude/query/parser/test/ParseTestCase.java
@@ -7,6 +7,7 @@ import com.yahoo.prelude.IndexFacts;
import com.yahoo.prelude.IndexModel;
import com.yahoo.prelude.SearchDefinition;
import com.yahoo.prelude.query.AndItem;
+import com.yahoo.prelude.query.AndSegmentItem;
import com.yahoo.prelude.query.CompositeItem;
import com.yahoo.prelude.query.IntItem;
import com.yahoo.prelude.query.Item;
@@ -18,13 +19,13 @@ import com.yahoo.prelude.query.PrefixItem;
import com.yahoo.prelude.query.RankItem;
import com.yahoo.prelude.query.SubstringItem;
import com.yahoo.prelude.query.SuffixItem;
+import com.yahoo.prelude.query.TaggableItem;
import com.yahoo.prelude.query.WordItem;
-import com.yahoo.prelude.query.parser.SpecialTokens;
+import com.yahoo.language.process.SpecialTokens;
import com.yahoo.prelude.query.parser.TestLinguistics;
import com.yahoo.search.Query;
import org.junit.Test;
-import java.util.Collections;
import java.util.Iterator;
import static org.junit.Assert.assertEquals;
@@ -39,7 +40,7 @@ import static org.junit.Assert.assertTrue;
*/
public class ParseTestCase {
- private ParsingTester tester = new ParsingTester();
+ private final ParsingTester tester = new ParsingTester();
@Test
public void testSimpleTermQuery() {
@@ -48,7 +49,9 @@ public class ParseTestCase {
@Test
public void testTermWithIndexPrefix() {
- tester.assertParsed("url:foobar", "url:foobar", Query.Type.ANY);
+ tester.assertParsed("url:foobar",
+ "url:foobar",
+ Query.Type.ANY);
}
@Test
@@ -59,104 +62,98 @@ public class ParseTestCase {
@Test
public void testMultipleTermsWithUTF8EncodingOred() {
tester.assertParsed("OR l\u00e5gen delta M\u00dcNICH M\u00fcnchen",
- "l\u00e5gen delta M\u00dcNICH M\u00fcnchen", Query.Type.ANY);
+ "l\u00e5gen delta M\u00dcNICH M\u00fcnchen",
+ Query.Type.ANY);
}
@Test
public void testMultipleTermsWithMultiplePrefixes() {
tester.assertParsed("RANK (+bar -normal.title:foo -baz) url:foobar",
- "url:foobar +bar -normal.title:foo -baz", Query.Type.ANY);
+ "url:foobar +bar -normal.title:foo -baz", Query.Type.ANY);
}
@Test
public void testSimpleQueryDefaultOr() {
- tester.assertParsed("OR foobar foo bar baz", "foobar foo bar baz",
- Query.Type.ANY);
+ tester.assertParsed("OR foobar foo bar baz", "foobar foo bar baz", Query.Type.ANY);
}
@Test
public void testOrAndNot() {
tester.assertParsed("RANK (+(AND baz bar) -xyzzy -foobaz) foobar foo",
- "foobar +baz foo -xyzzy -foobaz +bar", Query.Type.ANY);
+ "foobar +baz foo -xyzzy -foobaz +bar", Query.Type.ANY);
}
@Test
public void testSimpleOrNestedAnd() {
tester.assertParsed("RANK (OR foo bar baz) foobar xyzzy",
- "foobar +(foo bar baz) xyzzy", Query.Type.ANY);
+ "foobar +(foo bar baz) xyzzy", Query.Type.ANY);
}
@Test
public void testSimpleOrNestedNot() {
tester.assertParsed("+(OR foobar xyzzy) -(AND foo bar baz)",
- "foobar -(foo bar baz) xyzzy", Query.Type.ANY);
+ "foobar -(foo bar baz) xyzzy", Query.Type.ANY);
}
@Test
public void testOrNotNestedAnd() {
- tester.assertParsed(
- "RANK (+(AND baz (OR foo bar baz) bar) -xyzzy -foobaz) foobar foo",
- "foobar +baz foo -xyzzy +(foo bar baz) -foobaz +bar",
- Query.Type.ANY);
+ tester.assertParsed("RANK (+(AND baz (OR foo bar baz) bar) -xyzzy -foobaz) foobar foo",
+ "foobar +baz foo -xyzzy +(foo bar baz) -foobaz +bar",
+ Query.Type.ANY);
}
@Test
public void testOrAndNotNestedNot() {
- tester.assertParsed(
- "RANK (+(AND baz bar) -xyzzy -(AND foo bar baz) -foobaz) foobar foo",
- "foobar +baz foo -xyzzy -(foo bar baz) -foobaz +bar",
- Query.Type.ANY);
+ tester.assertParsed("RANK (+(AND baz bar) -xyzzy -(AND foo bar baz) -foobaz) foobar foo",
+ "foobar +baz foo -xyzzy -(foo bar baz) -foobaz +bar",
+ Query.Type.ANY);
}
@Test
public void testOrMultipleNestedAnd() {
- tester.assertParsed(
- "RANK (AND (OR fo ba foba) (OR foz baraz)) foobar foo bar baz",
- "foobar +(fo ba foba) foo bar +(foz baraz) baz", Query.Type.ANY);
+ tester.assertParsed("RANK (AND (OR fo ba foba) (OR foz baraz)) foobar foo bar baz",
+ "foobar +(fo ba foba) foo bar +(foz baraz) baz",
+ Query.Type.ANY);
}
@Test
public void testOrMultipleNestedNot() {
- tester.assertParsed(
- "+(OR foobar foo bar baz) -(AND fo ba foba) -(AND foz baraz)",
- "foobar -(fo ba foba) foo bar -(foz baraz) baz", Query.Type.ANY);
+ tester.assertParsed("+(OR foobar foo bar baz) -(AND fo ba foba) -(AND foz baraz)",
+ "foobar -(fo ba foba) foo bar -(foz baraz) baz",
+ Query.Type.ANY);
}
@Test
public void testOrAndNotMultipleNestedAnd() {
- tester.assertParsed(
- "RANK (+(AND baz (OR foo bar baz) (OR foz bazaz) bar) -xyzzy -foobaz) foobar foo",
- "foobar +baz foo -xyzzy +(foo bar baz) -foobaz +(foz bazaz) +bar",
- Query.Type.ANY);
+ tester.assertParsed("RANK (+(AND baz (OR foo bar baz) (OR foz bazaz) bar) -xyzzy -foobaz) foobar foo",
+ "foobar +baz foo -xyzzy +(foo bar baz) -foobaz +(foz bazaz) +bar",
+ Query.Type.ANY);
}
@Test
public void testOrAndNotMultipleNestedNot() {
- tester.assertParsed(
- "RANK (+(AND baz bar) -xyzzy -(AND foo bar baz) -foobaz -(AND foz bazaz)) foobar foo",
- "foobar +baz foo -xyzzy -(foo bar baz) -foobaz -(foz bazaz) +bar",
- Query.Type.ANY);
+ tester.assertParsed("RANK (+(AND baz bar) -xyzzy -(AND foo bar baz) -foobaz -(AND foz bazaz)) foobar foo",
+ "foobar +baz foo -xyzzy -(foo bar baz) -foobaz -(foz bazaz) +bar",
+ Query.Type.ANY);
}
@Test
public void testOrMultipleNestedAndNot() {
- tester.assertParsed(
- "RANK (+(AND (OR ffoooo bbaarr) (OR oof rab raboof)) -(AND fo ba foba) -(AND foz baraz)) foobar foo bar baz",
- "foobar -(fo ba foba) foo +(ffoooo bbaarr) bar +(oof rab raboof) -(foz baraz) baz",
- Query.Type.ANY);
+ tester.assertParsed("RANK (+(AND (OR ffoooo bbaarr) (OR oof rab raboof)) -(AND fo ba foba) -(AND foz baraz)) foobar foo bar baz",
+ "foobar -(fo ba foba) foo +(ffoooo bbaarr) bar +(oof rab raboof) -(foz baraz) baz",
+ Query.Type.ANY);
}
@Test
public void testOrAndNotMultipleNestedAndNot() {
- tester.assertParsed(
- "RANK (+(AND (OR ffoooo bbaarr) (OR oof rab raboof) baz xyxyzzy) -(AND fo ba foba) -foo -bar -(AND foz baraz)) foobar",
- "foobar -(fo ba foba) -foo +(ffoooo bbaarr) -bar +(oof rab raboof) -(foz baraz) +baz +xyxyzzy",
- Query.Type.ANY);
+ tester.assertParsed("RANK (+(AND (OR ffoooo bbaarr) (OR oof rab raboof) baz xyxyzzy) -(AND fo ba foba) -foo -bar -(AND foz baraz)) foobar",
+ "foobar -(fo ba foba) -foo +(ffoooo bbaarr) -bar +(oof rab raboof) -(foz baraz) +baz +xyxyzzy",
+ Query.Type.ANY);
}
@Test
public void testExplicitPhrase() {
- Item root=tester.assertParsed("\"foo bar foobar\"", "\"foo bar foobar\"", Query.Type.ANY);
+ Item root = tester.assertParsed("\"foo bar foobar\"", "\"foo bar foobar\"", Query.Type.ANY);
assertTrue(root instanceof PhraseItem);
assertTrue(((PhraseItem)root).isExplicit());
}
@@ -164,21 +161,20 @@ public class ParseTestCase {
@Test
public void testPhraseWithIndex() {
tester.assertParsed("normal.title:\"foo bar foobar\"",
- "normal.title:\"foo bar foobar\"", Query.Type.ANY);
+ "normal.title:\"foo bar foobar\"", Query.Type.ANY);
}
@Test
public void testPhrasesAndTerms() {
tester.assertParsed("OR \"foo bar foobar\" xyzzy \"baz gaz faz\"",
- "\"foo bar foobar\" xyzzy \"baz gaz faz\"", Query.Type.ANY);
+ "\"foo bar foobar\" xyzzy \"baz gaz faz\"", Query.Type.ANY);
}
@Test
public void testPhrasesAndTermsWithOperators() {
- tester.assertParsed(
- "RANK (+(AND \"baz gaz faz\" bazar) -\"foo bar foobar\") foofoo xyzzy",
- "foofoo -\"foo bar foobar\" xyzzy +\"baz gaz faz\" +bazar",
- Query.Type.ANY);
+ tester.assertParsed("RANK (+(AND \"baz gaz faz\" bazar) -\"foo bar foobar\") foofoo xyzzy",
+ "foofoo -\"foo bar foobar\" xyzzy +\"baz gaz faz\" +bazar",
+ Query.Type.ANY);
}
@Test
@@ -188,38 +184,40 @@ public class ParseTestCase {
@Test
public void testTermWithCatalogAndIndexPrefixDefaultAnd() {
- tester.assertParsed("normal.title:foobar", "normal.title:foobar",
- Query.Type.ALL);
+ tester.assertParsed("normal.title:foobar", "normal.title:foobar", Query.Type.ALL);
}
@Test
public void testMultipleTermsWithMultiplePrefixesDefaultAnd() {
tester.assertParsed("+(AND url:foobar bar) -normal.title:foo -baz",
- "url:foobar +bar -normal.title:foo -baz", Query.Type.ALL);
+ "url:foobar +bar -normal.title:foo -baz",
+ Query.Type.ALL);
}
@Test
public void testSimpleQueryDefaultAnd() {
- tester.assertParsed("AND foobar foo bar baz", "foobar foo bar baz",
- Query.Type.ALL);
+ tester.assertParsed("AND foobar foo bar baz", "foobar foo bar baz", Query.Type.ALL);
}
@Test
public void testNotDefaultAnd() {
- tester.assertParsed(
- "+(AND foobar (OR foo bar baz) xyzzy) -(AND foz baraz bazar)",
- "foobar +(foo bar baz) xyzzy -(foz baraz bazar)", Query.Type.ALL);
+ tester.assertParsed("+(AND foobar (OR foo bar baz) xyzzy) -(AND foz baraz bazar)",
+ "foobar +(foo bar baz) xyzzy -(foz baraz bazar)",
+ Query.Type.ALL);
}
@Test
public void testSimpleTermQueryDefaultPhrase() {
- tester.assertParsed("foobar", "foobar", Query.Type.PHRASE);
+ tester.assertParsed("foobar",
+ "foobar",
+ Query.Type.PHRASE);
}
@Test
public void testSimpleQueryDefaultPhrase() {
- Item root=tester.assertParsed("\"foobar foo bar baz\"", "foobar foo bar baz",
- Query.Type.PHRASE);
+ Item root = tester.assertParsed("\"foobar foo bar baz\"",
+ "foobar foo bar baz",
+ Query.Type.PHRASE);
assertTrue(root instanceof PhraseItem);
assertFalse(((PhraseItem)root).isExplicit());
}
@@ -227,23 +225,25 @@ public class ParseTestCase {
@Test
public void testMultipleTermsWithMultiplePrefixesDefaultPhrase() {
tester.assertParsed("\"url foobar bar normal title foo baz\"",
- "url:foobar +bar -normal.title:foo -baz", Query.Type.PHRASE);
+ "url:foobar +bar -normal.title:foo -baz",
+ Query.Type.PHRASE);
}
@Test
public void testOdd1() {
- tester.assertParsed("AND \"window print\" error", "+window.print() +error",Query.Type.ALL);
+ tester.assertParsed("AND window print error", "+window.print() +error",
+ Query.Type.ALL);
}
@Test
public void testOdd2() {
- tester.assertParsed("normal.title:kaboom", "normal.title:\"kaboom\"",Query.Type.ALL);
+ tester.assertParsed("normal.title:kaboom", "normal.title:\"kaboom\"",
+ Query.Type.ALL);
}
@Test
public void testOdd2Uppercase() {
- tester.assertParsed("normal.title:KABOOM", "NORMAL.TITLE:\"KABOOM\"",
- Query.Type.ALL);
+ tester.assertParsed("normal.title:KABOOM", "NORMAL.TITLE:\"KABOOM\"", Query.Type.ALL);
}
@Test
@@ -280,19 +280,19 @@ public class ParseTestCase {
@Test
public void testNestedCompositesDefaultOr() {
tester.assertParsed("RANK (OR foobar bar baz) foo xyzzy",
- "foo +(foobar +(bar baz)) xyzzy", Query.Type.ANY);
+ "foo +(foobar +(bar baz)) xyzzy", Query.Type.ANY);
}
@Test
public void testNestedCompositesDefaultAnd() {
tester.assertParsed("AND foo (OR foobar bar baz) xyzzy",
- "foo +(foobar +(bar baz)) xyzzy", Query.Type.ALL);
+ "foo +(foobar +(bar baz)) xyzzy", Query.Type.ALL);
}
@Test
public void testNestedCompositesPhraseDefault() {
tester.assertParsed("\"foo foobar bar baz xyzzy\"",
- "foo +(foobar +(bar baz)) xyzzy", Query.Type.PHRASE);
+ "foo +(foobar +(bar baz)) xyzzy", Query.Type.PHRASE);
}
@Test
@@ -349,8 +349,7 @@ public class ParseTestCase {
@Test
public void testNumericWithIndex() {
- tester.assertParsed("document.size:[34;454]", "document.size:[34;454]",
- Query.Type.ANY);
+ tester.assertParsed("document.size:[34;454]", "document.size:[34;454]", Query.Type.ANY);
}
@Test
@@ -361,14 +360,14 @@ public class ParseTestCase {
@Test
public void testMultipleIntegerWithIndex() {
tester.assertParsed("OR document.size:[34;454] date:>1234567890",
- "document.size:[34;454] date:>1234567890", Query.Type.ANY);
+ "document.size:[34;454] date:>1234567890", Query.Type.ANY);
}
@Test
public void testMixedNumericAndOtherTerms() {
tester.assertParsed("RANK (AND document.size:<1024 xyzzy) foo date:>123456890",
- "foo +document.size:<1024 +xyzzy date:>123456890",
- Query.Type.ANY);
+ "foo +document.size:<1024 +xyzzy date:>123456890",
+ Query.Type.ANY);
}
@Test
@@ -378,20 +377,18 @@ public class ParseTestCase {
@Test
public void testItemPhraseEmptyPhrase() {
- tester.assertParsed("RANK to \"or not to be\"", "+to\"or not to be\"\"\"",
- Query.Type.ANY);
+ tester.assertParsed("RANK to \"or not to be\"", "+to\"or not to be\"\"\"", Query.Type.ANY);
}
@Test
public void testSimpleQuery() {
- tester.assertParsed("OR if am \"f g 4 2\" maybe", "if am \" f g 4 2\"\" maybe",
- Query.Type.ANY);
+ tester.assertParsed("OR if am \"f g 4 2\" maybe", "if am \" f g 4 2\"\" maybe", Query.Type.ANY);
}
@Test
public void testExcessivePluses() {
tester.assertParsed("+(AND other is nothing) -test",
- "++other +++++is ++++++nothing -test", Query.Type.ANY);
+ "++other +++++is ++++++nothing -test", Query.Type.ANY);
}
@Test
@@ -401,39 +398,38 @@ public class ParseTestCase {
@Test
public void testPlusesAndMinuses() {
- Item root=tester.assertParsed("\"a b c d d\"", "a+b+c+d--d", Query.Type.ANY);
- assertTrue(root instanceof PhraseItem);
- assertFalse(((PhraseItem)root).isExplicit());
+ tester.assertParsed("AND a b c d d", "a+b+c+d--d", Query.Type.ANY);
}
@Test
public void testNumbers() {
- tester.assertParsed("\"123 2132odfd 934032 32423\"",
- "123+2132odfd.934032,,32423", Query.Type.ANY);
+ tester.assertParsed("AND 123 2132odfd 934032 32423", "123+2132odfd.934032,,32423", Query.Type.ANY);
}
@Test
public void testOtherSignsInQuote() {
- tester.assertParsed("\"0032 4 320 24329043\"", "0032+4\\320.24329043",
- Query.Type.ANY);
+ tester.assertParsed("AND 0032 4 320 24329043", "0032+4\\320.24329043", Query.Type.ANY);
}
@Test
public void testGribberish() {
tester.assertParsed("1349832840234l3040roer\u00e6lf12",
- ",1349832840234l3040roer\u00e6lf12", Query.Type.ANY);
+ ",1349832840234l3040roer\u00e6lf12",
+ Query.Type.ANY);
}
@Test
public void testUrl() {
- tester.assertParsed("www:\"www hotelaiguablava com\"",
- "+www:www.hotelaiguablava:com", Query.Type.ANY);
+ tester.assertParsed("AND www:www www:hotelaiguablava www:com",
+ "+www:www.hotelaiguablava:com",
+ Query.Type.ANY);
}
@Test
public void testUrlGribberish() {
- tester.assertParsed("OR \"3 16\" fast.type:lycosoffensive",
- "[ 3:16 fast.type:lycosoffensive", Query.Type.ANY);
+ tester.assertParsed("OR (AND 3 16) fast.type:lycosoffensive",
+ "[ 3:16 fast.type:lycosoffensive",
+ Query.Type.ANY);
}
@Test
@@ -475,8 +471,7 @@ public class ParseTestCase {
@Test
public void testPrefixWithDotAdvanced() {
- tester.assertParsed("normal.title:foobar", "normal.title:foobar",
- Query.Type.ADVANCED);
+ tester.assertParsed("normal.title:foobar", "normal.title:foobar", Query.Type.ADVANCED);
}
@Test
@@ -486,20 +481,21 @@ public class ParseTestCase {
@Test
public void testSimplePhraseAdvanced() {
- tester.assertParsed("\"foo bar foobar\"", "\"foo bar foobar\"",
- Query.Type.ADVANCED);
+ tester.assertParsed("\"foo bar foobar\"", "\"foo bar foobar\"", Query.Type.ADVANCED);
}
@Test
public void testSimplePhraseWithIndexAdvanced() {
tester.assertParsed("normal.title:\"foo bar foobar\"",
- "normal.title:\"foo bar foobar\"", Query.Type.ADVANCED);
+ "normal.title:\"foo bar foobar\"",
+ Query.Type.ADVANCED);
}
@Test
public void testMultiplePhrasesAdvanced() {
tester.assertParsed("AND \"foo bar foobar\" \"baz gaz faz\"",
- "\"foo bar foobar\" and \"baz gaz faz\"", Query.Type.ADVANCED);
+ "\"foo bar foobar\" and \"baz gaz faz\"",
+ Query.Type.ADVANCED);
}
@Test
@@ -661,23 +657,23 @@ public class ParseTestCase {
@Test
public void testImplicitPhrase1Advanced() {
- tester.assertParsed("\"test if\"", "--test+-if", Query.Type.ADVANCED);
+ tester.assertParsed("AND test if", "--test+-if", Query.Type.ADVANCED);
}
@Test
public void testImplicitPhrase2Advanced() {
- tester.assertParsed("\"a b c d d\"", "a+b+c+d--d", Query.Type.ADVANCED);
+ tester.assertParsed("AND a b c d d", "a+b+c+d--d", Query.Type.ADVANCED);
}
@Test
public void testImplicitPhrase3Advanced() {
- tester.assertParsed("\"123 2132odfd 934032 32423\"",
+ tester.assertParsed("AND 123 2132odfd 934032 32423",
"123+2132odfd.934032,,32423", Query.Type.ADVANCED);
}
@Test
public void testImplicitPhrase4Advanced() {
- tester.assertParsed("\"0032 4 320 24329043\"", "0032+4\\320.24329043", Query.Type.ADVANCED);
+ tester.assertParsed("AND 0032 4 320 24329043", "0032+4\\320.24329043", Query.Type.ADVANCED);
}
@Test
@@ -730,7 +726,7 @@ public class ParseTestCase {
@Test
public void testSingleHyphen() {
- tester.assertParsed("\"a b\"", "a-b", Query.Type.ALL);
+ tester.assertParsed("AND a b", "a-b", Query.Type.ALL);
}
@Test
@@ -883,27 +879,27 @@ public class ParseTestCase {
@Test
public void testSimpleDotPhraseAny() {
- tester.assertParsed("OR a \"b c\" d", "a b.c d", Query.Type.ANY);
+ tester.assertParsed("OR a (AND b c) d", "a b.c d", Query.Type.ANY);
}
@Test
public void testSimpleHyphenPhraseAny() {
- tester.assertParsed("OR a \"b c\" d", "a b-c d", Query.Type.ANY);
+ tester.assertParsed("OR a (AND b c) d", "a b-c d", Query.Type.ANY);
}
@Test
public void testAnotherSimpleDotPhraseAny() {
- tester.assertParsed("OR \"a b\" c d", "a.b c d", Query.Type.ANY);
+ tester.assertParsed("OR (AND a b) c d", "a.b c d", Query.Type.ANY);
}
@Test
public void testYetAnotherSimpleDotPhraseAny() {
- tester.assertParsed("OR a b \"c d\"", "a b c.d", Query.Type.ANY);
+ tester.assertParsed("OR a b (AND c d)", "a b c.d", Query.Type.ANY);
}
@Test
public void testVariousSeparatorsPhraseAny() {
- tester.assertParsed("\"a b c d\"", "a-b.c%d", Query.Type.ANY);
+ tester.assertParsed("AND a b c d", "a-b.c%d", Query.Type.ANY);
}
@Test
@@ -918,45 +914,44 @@ public class ParseTestCase {
@Test
public void testIndexedDottedPhraseAny() {
- tester.assertParsed("OR a url:\"b c\" d", "a url:b.c d", Query.Type.ANY);
+ tester.assertParsed("OR a (AND url:b url:c) d", "a url:b.c d", Query.Type.ANY);
}
@Test
public void testIndexedPlusedPhraseAny() {
- tester.assertParsed("OR a normal.title:\"b c\" d", "a normal.title:b+c d",
- Query.Type.ANY);
+ tester.assertParsed("OR a (AND normal.title:b normal.title:c) d", "a normal.title:b+c d", Query.Type.ANY);
}
@Test
public void testNestedNotAny() {
tester.assertParsed(
- "RANK (+(OR normal.title:foobar url:\"www pvv org\") -foo) a",
+ "RANK (+(OR normal.title:foobar (AND url:www url:pvv url:org)) -foo) a",
"a +(normal.title:foobar url:www.pvv.org) -foo", Query.Type.ANY);
}
@Test
public void testDottedPhraseAdvanced() {
- tester.assertParsed("OR a \"b c\"", "a or b.c", Query.Type.ADVANCED);
+ tester.assertParsed("OR a (AND b c)", "a or b.c", Query.Type.ADVANCED);
}
@Test
public void testHyphenPhraseAdvanced() {
- tester.assertParsed("OR (AND a \"b c\") d", "a and b-c or d", Query.Type.ADVANCED);
+ tester.assertParsed("OR (AND a (AND b c)) d", "a and b-c or d", Query.Type.ADVANCED);
}
@Test
public void testAnotherDottedPhraseAdvanced() {
- tester.assertParsed("OR \"a b\" c", "a.b or c", Query.Type.ADVANCED);
+ tester.assertParsed("OR (AND a b) c", "a.b or c", Query.Type.ADVANCED);
}
@Test
public void testNottedDottedPhraseAdvanced() {
- tester.assertParsed("+a -\"c d\"", "a andnot c.d", Query.Type.ADVANCED);
+ tester.assertParsed("+a -(AND c d)", "a andnot c.d", Query.Type.ADVANCED);
}
@Test
public void testVariousSeparatorsPhraseAdvanced() {
- tester.assertParsed("\"a b c d\"", "a-b.c%d", Query.Type.ADVANCED);
+ tester.assertParsed("AND a b c d", "a-b.c%d", Query.Type.ADVANCED);
}
@Test
@@ -976,14 +971,14 @@ public class ParseTestCase {
@Test
public void testNestedPlussedPhraseAdvanced() {
- tester.assertParsed("AND (OR a normal.title:\"b c\") d",
+ tester.assertParsed("AND (OR a (AND normal.title:b normal.title:c)) d",
"a or normal.title:b+c and d", Query.Type.ADVANCED);
}
@Test
public void testNottedNestedDottedPhraseAdvanced() {
tester.assertParsed(
- "+(AND a (OR normal.title:foobar url:\"www pvv org\")) -foo",
+ "+(AND a (OR normal.title:foobar (AND url:www url:pvv url:org))) -foo",
"a and (normal.title:foobar or url:www.pvv.org) andnot foo",
Query.Type.ADVANCED);
}
@@ -995,7 +990,7 @@ public class ParseTestCase {
@Test
public void testPlusedTwiceThenQuotedPhraseAny() {
- tester.assertParsed("\"a b c d\"", "a+b+\"c d\"", Query.Type.ANY);
+ tester.assertParsed("AND a b c d", "a+b+\"c d\"", Query.Type.ANY);
}
@Test
@@ -1005,7 +1000,7 @@ public class ParseTestCase {
@Test
public void testPhrasesInBraces() {
- tester.assertParsed("url.domain:\"microsoft com\"",
+ tester.assertParsed("AND url.domain:microsoft url.domain:com",
"+(url.domain:microsoft.com)", Query.Type.ALL);
}
@@ -1053,17 +1048,17 @@ public class ParseTestCase {
@Test
public void testPhraseNotPrefix() {
- tester.assertParsed("OR foo \"prefix bar\"", "foo prefix*bar", Query.Type.ANY);
+ tester.assertParsed("OR foo (AND prefix bar)", "foo prefix*bar", Query.Type.ANY);
}
@Test
public void testPhraseNotSubstring() {
- tester.assertParsed("OR foo \"substring bar\"", "foo *substring*bar", Query.Type.ANY);
+ tester.assertParsed("OR foo (AND substring bar)", "foo *substring*bar", Query.Type.ANY);
}
@Test
public void testPhraseNotSuffix() {
- tester.assertParsed("OR \"foo suffix\" bar", "foo*suffix bar", Query.Type.ANY);
+ tester.assertParsed("OR (AND foo suffix) bar", "foo*suffix bar", Query.Type.ANY);
}
@Test
@@ -1086,20 +1081,17 @@ public class ParseTestCase {
@Test
public void testIndexedPhraseNotPrefix() {
- tester.assertParsed("foo.bar:\"prefix xyzzy\"", "foo.bar:prefix*xyzzy",
- Query.Type.ANY);
+ tester.assertParsed("AND foo.bar:prefix foo.bar:xyzzy", "foo.bar:prefix*xyzzy", Query.Type.ANY);
}
@Test
public void testIndexedPhraseNotSubstring() {
- tester.assertParsed("foo.bar:\"substring xyzzy\"", "foo.bar:*substring*xyzzy",
- Query.Type.ANY);
+ tester.assertParsed("AND foo.bar:substring foo.bar:xyzzy", "foo.bar:*substring*xyzzy", Query.Type.ANY);
}
@Test
public void testIndexedPhraseNotSuffix() {
- tester.assertParsed("foo.bar:\"xyzzy suffix\"", "foo.bar:xyzzy*suffix",
- Query.Type.ANY);
+ tester.assertParsed("AND foo.bar:xyzzy foo.bar:suffix", "foo.bar:xyzzy*suffix", Query.Type.ANY);
}
@Test
@@ -1120,20 +1112,20 @@ public class ParseTestCase {
assertTrue(root instanceof SuffixItem);
}
- /** Non existing index → phrase **/
+ /** Non existing index → and **/
@Test
public void testNonIndexPhraseNotPrefix() {
- tester.assertParsed("\"void prefix\"", "void:prefix*", Query.Type.ANY);
+ tester.assertParsed("AND void prefix", "void:prefix*", Query.Type.ANY);
}
@Test
public void testNonIndexPhraseNotSubstring() {
- tester.assertParsed("\"void substring\"", "void:*substring*", Query.Type.ANY);
+ tester.assertParsed("AND void substring", "void:*substring*", Query.Type.ANY);
}
@Test
public void testNonIndexPhraseNotSuffix() {
- tester.assertParsed("\"void suffix\"", "void:*suffix", Query.Type.ANY);
+ tester.assertParsed("AND void suffix", "void:*suffix", Query.Type.ANY);
}
/** Explicit phrase → remove '*' **/
@@ -1198,7 +1190,7 @@ public class ParseTestCase {
/** Extra spaces with index **/
@Test
public void testIndexPrefixExtraSpace() {
- tester.assertParsed("\"foo prefix\"", "foo:prefix *", Query.Type.ANY);
+ tester.assertParsed("AND foo prefix", "foo:prefix *", Query.Type.ANY);
}
@Test
@@ -1419,7 +1411,7 @@ public class ParseTestCase {
@Test
public void testMultipleDifferentPhraseSeparators() {
- tester.assertParsed("\"foo bar\"", "foo.-.bar", Query.Type.ANY);
+ tester.assertParsed("AND foo bar", "foo.-.bar", Query.Type.ANY);
}
@Test
@@ -1430,19 +1422,17 @@ public class ParseTestCase {
@Test
public void testReallyNoisyQuery1() {
- tester.assertParsed("AND word another", "&word\"()/&#)(/&another!\"",
- Query.Type.ALL);
+ tester.assertParsed("AND word another", "&word\"()/&#)(/&another!\"", Query.Type.ALL);
}
@Test
public void testReallyNoisyQuery2() {
- tester.assertParsed("\"\u03bc\u03bc hei\"", "&&&`\u00b5\u00b5=@hei", Query.Type.ALL);
+ tester.assertParsed("AND \u03bc\u03bc hei", "&&&`\u00b5\u00b5=@hei", Query.Type.ALL);
}
@Test
public void testReallyNoisyQuery3() {
- tester.assertParsed("AND \"hei hallo\" du der", "hei-hallo;du;der",
- Query.Type.ALL);
+ tester.assertParsed("AND hei hallo du der", "hei-hallo;du;der", Query.Type.ALL);
}
@Test
@@ -1478,7 +1468,7 @@ public class ParseTestCase {
@Test
public void testTheStupidSymbolsWhichAreNowWordCharactersInUnicode() {
- tester.assertParsed("\"yz a\"", "yz\u00A8\u00AA\u00AF", Query.Type.ANY);
+ tester.assertParsed("AND yz a", "yz\u00A8\u00AA\u00AF", Query.Type.ANY);
}
@Test
@@ -1498,7 +1488,7 @@ public class ParseTestCase {
@Test
public void testImplicitPhrasingWithIndex() {
- tester.assertParsed("a:\"b c\"", "a:/b/c", Query.Type.ANY);
+ tester.assertParsed("AND a:b a:c", "a:/b/c", Query.Type.ANY);
}
@Test
@@ -1508,7 +1498,7 @@ public class ParseTestCase {
@Test
public void testSingleNoisyPhraseWithIndex() {
- tester.assertParsed("mail:\"yahoo com\"", "mail:@yahoo.com", Query.Type.ANY);
+ tester.assertParsed("AND mail:yahoo mail:com", "mail:@yahoo.com", Query.Type.ANY);
}
@Test
@@ -1599,7 +1589,7 @@ public class ParseTestCase {
"url.all:http://www.newsadvance.com/servlet/Satellite?pagename=LNA/MGArticle/IMD_BasicArticle&c=MGArticle&cid=1031782787014&path=!mgnetwork!diversions",
Query.Type.ALL);
tester.assertParsed(
- "AND ull:\"http www neue oz de information pub Boulevard index html file a 3 s 4 file\" s:\"37 iptc bdt 20050607 294 dpa 9001170 txt\" s:\"3 dir\" s:\"26 opt DPA parsed boulevard\" s:\"7 bereich\" s:\"9 Boulevard\"",
+ "AND ull:http ull:www ull:neue ull:oz ull:de ull:information ull:pub ull:Boulevard ull:index ull:html ull:file ull:a ull:3 ull:s ull:4 ull:file s:\"37 iptc bdt 20050607 294 dpa 9001170 txt\" s:\"3 dir\" s:\"26 opt DPA parsed boulevard\" s:\"7 bereich\" s:\"9 Boulevard\"",
"ull:http://www.neue-oz.de/information/pub_Boulevard/index.html?file=a:3:{s:4:\"file\";s:37:\"iptc-bdt-20050607-294-dpa_9001170.txt\";s:3:\"dir\";s:26:\"/opt/DPA/parsed/boulevard/\";s:7:\"bereich\";s:9:\"Boulevard\";}",
Query.Type.ALL);
}
@@ -1640,30 +1630,30 @@ public class ParseTestCase {
@Test
public void testTooLongQueryTerms() {
- tester.assertParsed("AND \"545558598787gggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggcfffffffffffffffffffffffffffffffffffffffffffccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccclllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyytttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrreeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeewwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqlkjhcxxdfffxdzzaqwwsxedcrfvtgbyhnujmikkiloolpppof filter ew 545558598787gggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggcfffffffffffffffffffffffffffffffffffffffffffccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccclllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyytttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrreeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeewwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqlkjhcxxdfffxdzzaqwwsxedcrfvtgbyhnujmikkiloolpppof\"!1000 \"2b 2f 545558598787gggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggcfffffffffffffffffffffffffffffffffffffffffffccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccclllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyytttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrreeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeewwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqlkjhcxxdfffxdzzaqwwsxedcrfvtgbyhnujmikkiloolpppof\"",
+ tester.assertParsed("AND 545558598787gggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggcfffffffffffffffffffffffffffffffffffffffffffccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccclllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyytttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrreeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeewwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqlkjhcxxdfffxdzzaqwwsxedcrfvtgbyhnujmikkiloolpppof filter ew 545558598787gggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggcfffffffffffffffffffffffffffffffffffffffffffccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccclllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyytttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrreeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeewwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqlkjhcxxdfffxdzzaqwwsxedcrfvtgbyhnujmikkiloolpppof 2b 2f 545558598787gggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggcfffffffffffffffffffffffffffffffffffffffffffccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccclllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyytttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrreeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeewwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqlkjhcxxdfffxdzzaqwwsxedcrfvtgbyhnujmikkiloolpppof",
"+/545558598787gggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggcfffffffffffffffffffffffffffffffffffffffffffccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccclllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyytttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrreeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeewwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqlkjhcxxdfffxdzzaqwwsxedcrfvtgbyhnujmikkiloolpppof&filter=ew:545558598787gggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggcfffffffffffffffffffffffffffffffffffffffffffccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccclllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyytttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrreeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeewwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqlkjhcxxdfffxdzzaqwwsxedcrfvtgbyhnujmikkiloolpppof!1000 =.2b..2f.545558598787gggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggcfffffffffffffffffffffffffffffffffffffffffffccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccclllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyytttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrreeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeewwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqlkjhcxxdfffxdzzaqwwsxedcrfvtgbyhnujmikkiloolpppof",
Query.Type.ALL);
}
@Test
public void testNonSpecialTokenParsing() {
- ParsingTester customTester = new ParsingTester(new SpecialTokens("default"));
- customTester.assertParsed("OR c or c with \"tcp ip\"", "c# or c++ with tcp/ip", Query.Type.ANY);
+ ParsingTester customTester = new ParsingTester(SpecialTokens.empty());
+ customTester.assertParsed("OR c or c with (AND tcp ip)", "c# or c++ with tcp/ip", Query.Type.ANY);
}
@Test
public void testNonIndexWithColons1() {
- tester.assertParsed("OR this is \"notan iindex\"", "this is notan:iindex", Query.Type.ANY);
+ tester.assertParsed("OR this is (AND notan iindex)", "this is notan:iindex", Query.Type.ANY);
}
@Test
public void testNonIndexWithColons2() {
- tester.assertParsed("OR this is \"notan iindex either\"", "this is notan:iindex:either", Query.Type.ANY);
+ tester.assertParsed("OR this is (AND notan iindex either)", "this is notan:iindex:either", Query.Type.ANY);
}
@Test
public void testIndexThenUnderscoreTermBecomesIndex() {
- tester.assertParsed("name:\"batch article\"", "name:batch_article", Query.Type.ANY);
+ tester.assertParsed("AND name:batch name:article", "name:batch_article", Query.Type.ANY);
}
@Test
@@ -1671,17 +1661,17 @@ public class ParseTestCase {
// "first" "second" and "third" are segments in the test language
Item item = tester.parseQuery("name:firstsecondthird", null, Language.CHINESE_SIMPLIFIED, Query.Type.ANY, TestLinguistics.INSTANCE);
- assertTrue(item instanceof PhraseSegmentItem);
- PhraseSegmentItem phrase = (PhraseSegmentItem) item;
+ assertTrue(item instanceof AndSegmentItem);
+ AndSegmentItem segment = (AndSegmentItem) item;
- assertEquals(3, phrase.getItemCount());
- assertEquals("name:first", phrase.getItem(0).toString());
- assertEquals("name:second", phrase.getItem(1).toString());
- assertEquals("name:third", phrase.getItem(2).toString());
+ assertEquals(3, segment.getItemCount());
+ assertEquals("name:first", segment.getItem(0).toString());
+ assertEquals("name:second", segment.getItem(1).toString());
+ assertEquals("name:third", segment.getItem(2).toString());
- assertEquals("name", ((WordItem) phrase.getItem(0)).getIndexName());
- assertEquals("name", ((WordItem) phrase.getItem(1)).getIndexName());
- assertEquals("name", ((WordItem) phrase.getItem(2)).getIndexName());
+ assertEquals("name", ((WordItem) segment.getItem(0)).getIndexName());
+ assertEquals("name", ((WordItem) segment.getItem(1)).getIndexName());
+ assertEquals("name", ((WordItem) segment.getItem(2)).getIndexName());
}
@Test
@@ -1690,21 +1680,21 @@ public class ParseTestCase {
Item item = tester.parseQuery("name:\"firstsecondthird\"", null, Language.CHINESE_SIMPLIFIED, Query.Type.ANY, TestLinguistics.INSTANCE);
assertTrue(item instanceof PhraseSegmentItem);
- PhraseSegmentItem phrase = (PhraseSegmentItem) item;
+ PhraseSegmentItem segment = (PhraseSegmentItem) item;
- assertEquals(3, phrase.getItemCount());
- assertEquals("name:first", phrase.getItem(0).toString());
- assertEquals("name:second", phrase.getItem(1).toString());
- assertEquals("name:third", phrase.getItem(2).toString());
+ assertEquals(3, segment.getItemCount());
+ assertEquals("name:first", segment.getItem(0).toString());
+ assertEquals("name:second", segment.getItem(1).toString());
+ assertEquals("name:third", segment.getItem(2).toString());
- assertEquals("name", ((WordItem) phrase.getItem(0)).getIndexName());
- assertEquals("name", ((WordItem) phrase.getItem(1)).getIndexName());
- assertEquals("name", ((WordItem)phrase.getItem(2)).getIndexName());
+ assertEquals("name", ((WordItem) segment.getItem(0)).getIndexName());
+ assertEquals("name", ((WordItem) segment.getItem(1)).getIndexName());
+ assertEquals("name", ((WordItem)segment.getItem(2)).getIndexName());
}
@Test
public void testAndItemAndImplicitPhrase() {
- tester.assertParsed("\"\u00d8 \u00d8 \u00d8 \u00d9\"",
+ tester.assertParsed("AND \u00d8 \u00d8 \u00d8 \u00d9",
"\u00d8\u00b9\u00d8\u00b1\u00d8\u00a8\u00d9", "",
Query.Type.ALL, Language.CHINESE_SIMPLIFIED);
}
@@ -1736,7 +1726,7 @@ public class ParseTestCase {
@Test
public void testFakeCJKSegmentingOfMultiplePhrases() {
Item item = tester.parseQuery("name:firstsecond.s", null, Language.CHINESE_SIMPLIFIED, Query.Type.ANY, TestLinguistics.INSTANCE);
- assertEquals("name:\"'first second' s\"", item.toString());
+ assertEquals("AND (SAND name:first name:second) name:s", item.toString());
}
@Test
@@ -1801,7 +1791,7 @@ public class ParseTestCase {
@Test
public void testCommaOnlyLeadsToImplicitPhrasing() {
- tester.assertParsed("\"A B C\"", "A,B,C", Query.Type.ALL);
+ tester.assertParsed("AND A B C", "A,B,C", Query.Type.ALL);
}
@Test
@@ -1873,8 +1863,8 @@ public class ParseTestCase {
@Test
public void testJPMobileExceptionQuery() {
- tester.assertParsed("OR concat and \"make string\" 1 47 or",
- "(concat \"and\" (make-string 1 47) \"or\")", Query.Type.ALL);
+ tester.assertParsed("OR concat and (AND make string) 1 47 or",
+ "(concat \"and\" (make-string 1 47) \"or\")", Query.Type.ALL);
}
@Test
@@ -1882,7 +1872,7 @@ public class ParseTestCase {
tester.assertParsed("b", "a: b", Query.Type.ALL);
tester.assertParsed("AND a b", "a : b", Query.Type.ALL);
tester.assertParsed("AND a b", "a :b", Query.Type.ALL);
- tester.assertParsed("\"a b\"", "a.:b", Query.Type.ALL);
+ tester.assertParsed("AND a b", "a.:b", Query.Type.ALL);
tester.assertParsed("a:b", "a:b", Query.Type.ALL);
}
@@ -1917,8 +1907,7 @@ public class ParseTestCase {
tester.assertParsed("AND ringtone AND (OR a:\"Delivery SMAF large max 150kB 063\" OR a:\"RealMusic Delivery\")",
"ringtone AND (a:\"Delivery SMAF large max.150kB (063)\" OR a:\"RealMusic Delivery\" )",
Query.Type.ALL);
- // The last one here is a little weird, but it's not a problem,
- // so I let it pass for now...
+ // The last one here is a little weird, but it's not a problem, so let it pass for now...
tester.assertParsed("OR (OR ringtone AND) (OR a:\"Delivery SMAF large max 150kB 063\" OR a:\"RealMusic Delivery\")",
"ringtone AND (a:\"Delivery SMAF large max.150kB (063)\" OR a:\"RealMusic Delivery\" )",
Query.Type.ANY);
@@ -1926,7 +1915,7 @@ public class ParseTestCase {
@Test
public void testMixedCaseIndexNames() {
- tester.assertParsed("AND mixedCase:a mixedCase:b \"notAnIndex c\" mixedCase:d",
+ tester.assertParsed("AND mixedCase:a mixedCase:b notAnIndex c mixedCase:d",
"mixedcase:a MIXEDCASE:b notAnIndex:c mixedCase:d",
Query.Type.ALL);
}
@@ -1934,7 +1923,7 @@ public class ParseTestCase {
/** CJK special tokens should be recognized also on non-boundaries */
@Test
public void testChineseSpecialTokens() {
- tester.assertParsed("AND \"cat tcp/ip zu\" \"foo dotnet bar dotnet dotnet c# c++ bar dotnet dotnet wiz\"",
+ tester.assertParsed("AND cat tcp/ip zu foo dotnet bar dotnet dotnet c# c++ bar dotnet dotnet wiz",
"cattcp/ipzu foo.netbar.net.netC#c++bar.net.netwiz","", Query.Type.ALL, Language.CHINESE_SIMPLIFIED);
}
@@ -1945,7 +1934,7 @@ public class ParseTestCase {
@Test
public void testChineseSpecialTokensWithMultiSegmentReplace() {
// special-token-fs is a special token, to be replaced by firstsecond, first and second are segments in test
- tester.assertParsed("AND \"tcp/ip firstsecond dotnet\" firstsecond 'first second'","tcp/ipspecial-token-fs.net special-token-fs firstsecond",
+ tester.assertParsed("AND tcp/ip firstsecond dotnet firstsecond (SAND first second)","tcp/ipspecial-token-fs.net special-token-fs firstsecond",
"", Query.Type.ALL, Language.CHINESE_SIMPLIFIED, TestLinguistics.INSTANCE);
}
@@ -1981,6 +1970,13 @@ public class ParseTestCase {
}
@Test
+ public void testNegativeTermPositiveNumberInParentheses() {
+ tester.assertParsed("+a -12", "a -(12)", Query.Type.ALL);
+ tester.assertParsed("+a -(AND 12 15)", "a -(12 15)", Query.Type.ALL);
+ tester.assertParsed("+a -12 -15", "a -(12) -(15)", Query.Type.ALL);
+ }
+
+ @Test
public void testSingleNegativeNumberLikeTerm() {
tester.assertParsed("-12", "-12", Query.Type.ALL);
}
@@ -2014,7 +2010,7 @@ public class ParseTestCase {
@Test
public void testVersionNumbers() {
- tester.assertParsed("\"1 0 9\"", "1.0.9", Query.Type.ALL);
+ tester.assertParsed("AND 1 0 9", "1.0.9", Query.Type.ALL);
}
@Test
@@ -2321,7 +2317,7 @@ public class ParseTestCase {
@Test
public void testOdd1Web() {
- tester.assertParsed("AND \"window print\" error", "+window.print() +error",Query.Type.WEB);
+ tester.assertParsed("AND window print error", "+window.print() +error",Query.Type.WEB);
}
@Test
@@ -2351,13 +2347,13 @@ public class ParseTestCase {
@Test
public void testDefaultWebIndices() {
- tester.assertParsed("\"notanindex b\"","notanindex:b",Query.Type.WEB);
- tester.assertParsed("site:\"b $\"","site:b",Query.Type.WEB);
- tester.assertParsed("hostname:b","hostname:b",Query.Type.WEB);
- tester.assertParsed("link:b","link:b",Query.Type.WEB);
- tester.assertParsed("url:b","url:b",Query.Type.WEB);
- tester.assertParsed("inurl:b","inurl:b",Query.Type.WEB);
- tester.assertParsed("intitle:b","intitle:b",Query.Type.WEB);
+ tester.assertParsed("AND notanindex b","notanindex:b", Query.Type.WEB);
+ tester.assertParsed("site:\"b $\"","site:b", Query.Type.WEB);
+ tester.assertParsed("hostname:b","hostname:b", Query.Type.WEB);
+ tester.assertParsed("link:b","link:b", Query.Type.WEB);
+ tester.assertParsed("url:b","url:b", Query.Type.WEB);
+ tester.assertParsed("inurl:b","inurl:b", Query.Type.WEB);
+ tester.assertParsed("intitle:b","intitle:b", Query.Type.WEB);
}
@Test
@@ -2489,17 +2485,17 @@ public class ParseTestCase {
@Test
public void testSimpleWandAdvanced() {
- tester.assertParsed("WAND(100) foo bar baz", "foo wand bar wand baz", Query.Type.ADVANCED);
+ tester.assertParsed("WEAKAND(100) foo bar baz", "foo wand bar wand baz", Query.Type.ADVANCED);
}
@Test
public void testSimpleWandAdvancedWithNonDefaultN() {
- tester.assertParsed("WAND(32) foo bar baz", "foo wand(32) bar wand(32) baz", Query.Type.ADVANCED);
+ tester.assertParsed("WEAKAND(32) foo bar baz", "foo weakand(32) bar weakand(32) baz", Query.Type.ADVANCED);
}
@Test
public void testSimpleWandAdvancedWithNonDefaultNAndWeights() {
- tester.assertParsed("WAND(32) foo!32 bar!64 baz", "foo!32 wand(32) bar!64 wand(32) baz", Query.Type.ADVANCED);
+ tester.assertParsed("WEAKAND(32) foo!32 bar!64 baz", "foo!32 weakand(32) bar!64 weakand(32) baz", Query.Type.ADVANCED);
}
@Test
@@ -2519,6 +2515,26 @@ public class ParseTestCase {
}
@Test
+ public void testAndSegmenting() {
+ Item root = tester.parseQuery("a'b&c'd", Language.ENGLISH, Query.Type.ALL);
+ assertTrue(root instanceof AndItem);
+ AndItem top = (AndItem) root;
+ assertTrue(top.getItem(0) instanceof AndSegmentItem);
+ assertTrue(top.getItem(1) instanceof AndSegmentItem);
+ AndSegmentItem seg1 = (AndSegmentItem) top.getItem(0);
+ AndSegmentItem seg2 = (AndSegmentItem) top.getItem(1);
+ Item t1 = seg1.getItem(0);
+ Item t2 = seg1.getItem(1);
+ Item t3 = seg2.getItem(0);
+ Item t4 = seg2.getItem(1);
+ assertTrue(((TaggableItem)t2).hasUniqueID());
+ assertTrue(((TaggableItem)t3).hasUniqueID());
+ assertTrue(((TaggableItem)t1).getConnectedItem() == t2);
+ assertTrue(((TaggableItem)t2).getConnectedItem() == t3);
+ assertTrue(((TaggableItem)t3).getConnectedItem() == t4);
+ }
+
+ @Test
public void testSiteAndSegmentPhrases() {
tester.assertParsed("host.all:\"www abc com x y-z $\"",
"host.all:www.abc.com/x'y-z", "",
@@ -2527,7 +2543,7 @@ public class ParseTestCase {
@Test
public void testSiteAndSegmentPhrasesFollowedByText() {
- tester.assertParsed("AND host.all:\"www abc com x y-z $\" 'a b'",
+ tester.assertParsed("AND host.all:\"www abc com x y-z $\" (SAND a b)",
"host.all:www.abc.com/x'y-z a'b", "",
Query.Type.ALL, Language.ENGLISH);
}
@@ -2544,7 +2560,7 @@ public class ParseTestCase {
@Test
public void testNonAsciiNumber() {
- tester.assertParsed("title:\"199 119 201 149\"", "title:199.119.201.149", Query.Type.ALL);
+ tester.assertParsed("AND title:199 title:119 title:201 title:149", "title:199.119.201.149", Query.Type.ALL);
}
}
diff --git a/container-search/src/test/java/com/yahoo/prelude/query/parser/test/ParsingTester.java b/container-search/src/test/java/com/yahoo/prelude/query/parser/test/ParsingTester.java
index 9c61b10e15f..fd7e4cbe0e6 100644
--- a/container-search/src/test/java/com/yahoo/prelude/query/parser/test/ParsingTester.java
+++ b/container-search/src/test/java/com/yahoo/prelude/query/parser/test/ParsingTester.java
@@ -11,8 +11,8 @@ import com.yahoo.prelude.IndexFacts;
import com.yahoo.prelude.IndexModel;
import com.yahoo.prelude.query.Item;
import com.yahoo.prelude.query.NullItem;
-import com.yahoo.prelude.query.parser.SpecialTokenRegistry;
-import com.yahoo.prelude.query.parser.SpecialTokens;
+import com.yahoo.language.process.SpecialTokenRegistry;
+import com.yahoo.language.process.SpecialTokens;
import com.yahoo.search.Query;
import com.yahoo.search.config.IndexInfoConfig;
import com.yahoo.search.query.parser.Parsable;
@@ -20,6 +20,9 @@ import com.yahoo.search.query.parser.Parser;
import com.yahoo.search.query.parser.ParserEnvironment;
import com.yahoo.search.query.parser.ParserFactory;
+import java.util.ArrayList;
+import java.util.List;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
@@ -32,7 +35,7 @@ import static org.junit.Assert.assertTrue;
public class ParsingTester {
private static final Linguistics linguistics = new SimpleLinguistics();
- private IndexFacts indexFacts;
+ private final IndexFacts indexFacts;
private SpecialTokenRegistry tokenRegistry;
public ParsingTester() {
@@ -49,11 +52,10 @@ public class ParsingTester {
public ParsingTester(IndexFacts indexFacts, SpecialTokens specialTokens) {
indexFacts.freeze();
- specialTokens.freeze();
this.indexFacts = indexFacts;
tokenRegistry = new SpecialTokenRegistry();
- tokenRegistry.addSpecialTokens(specialTokens);
+ tokenRegistry = new SpecialTokenRegistry(List.of(specialTokens));
}
/**
@@ -72,13 +74,13 @@ public class ParsingTester {
* This can be used to add new tokens and passing the resulting special tokens to the constructor of this.
*/
public static SpecialTokens createSpecialTokens() {
- SpecialTokens tokens = new SpecialTokens("default");
- tokens.addSpecialToken("c++", null);
- tokens.addSpecialToken(".net", "dotnet");
- tokens.addSpecialToken("tcp/ip", null);
- tokens.addSpecialToken("c#", null);
- tokens.addSpecialToken("special-token-fs","firstsecond");
- return tokens;
+ List<SpecialTokens.Token> tokens = new ArrayList<>();
+ tokens.add(new SpecialTokens.Token("c++"));
+ tokens.add(new SpecialTokens.Token(".net", "dotnet"));
+ tokens.add(new SpecialTokens.Token("tcp/ip"));
+ tokens.add(new SpecialTokens.Token("c#"));
+ tokens.add(new SpecialTokens.Token("special-token-fs","firstsecond"));
+ return new SpecialTokens("default", tokens);
}
/**
@@ -124,6 +126,10 @@ public class ParsingTester {
return root;
}
+ public Item parseQuery(String query, Language language, Query.Type type) {
+ return parseQuery(query, null, language, type, new SimpleLinguistics());
+ }
+
public Item parseQuery(String query, String filter, Language language, Query.Type type, Linguistics linguistics) {
Parser parser = ParserFactory.newInstance(type, new ParserEnvironment()
.setIndexFacts(indexFacts)
diff --git a/container-search/src/test/java/com/yahoo/prelude/query/parser/test/TokenizerTestCase.java b/container-search/src/test/java/com/yahoo/prelude/query/parser/test/TokenizerTestCase.java
index 12d993e8d41..ab727a10cdd 100644
--- a/container-search/src/test/java/com/yahoo/prelude/query/parser/test/TokenizerTestCase.java
+++ b/container-search/src/test/java/com/yahoo/prelude/query/parser/test/TokenizerTestCase.java
@@ -6,12 +6,13 @@ import com.yahoo.prelude.Index;
import com.yahoo.prelude.IndexFacts;
import com.yahoo.prelude.IndexModel;
import com.yahoo.prelude.SearchDefinition;
-import com.yahoo.prelude.query.parser.SpecialTokenRegistry;
-import com.yahoo.prelude.query.parser.SpecialTokens;
+import com.yahoo.language.process.SpecialTokenRegistry;
+import com.yahoo.language.process.SpecialTokens;
import com.yahoo.prelude.query.parser.Token;
import com.yahoo.prelude.query.parser.Tokenizer;
import org.junit.Test;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -35,18 +36,16 @@ import static org.junit.Assert.assertTrue;
/**
* Tests the tokenizer
*
- * @author bratseth
+ * @author bratseth
*/
public class TokenizerTestCase {
- private SpecialTokenRegistry defaultRegistry = new SpecialTokenRegistry("file:src/test/java/com/yahoo/prelude/query/parser/test/replacingtokens.cfg");
-
@Test
public void testPlainTokenization() {
Tokenizer tokenizer = new Tokenizer(new SimpleLinguistics());
- tokenizer.setSpecialTokens(createSpecialTokens());
- List<?> tokens = tokenizer.tokenize("drive (to hwy88, 88) +or language:en ugcapi_1");
+ tokenizer.setSpecialTokens(createSpecialTokens().getSpecialTokens("default"));
+ List<?> tokens = tokenizer.tokenize("drive (to hwy88, 88) +or language:en ugcapi_1 & &a");
assertEquals(new Token(WORD, "drive"), tokens.get(0));
assertEquals(new Token(SPACE, " "), tokens.get(1));
@@ -69,6 +68,11 @@ public class TokenizerTestCase {
assertEquals(new Token(WORD, "ugcapi"), tokens.get(18));
assertEquals(new Token(UNDERSCORE, "_"), tokens.get(19));
assertEquals(new Token(NUMBER, "1"), tokens.get(20));
+ assertEquals(new Token(SPACE, " "), tokens.get(21));
+ assertEquals(new Token(NOISE, "<NOISE>"), tokens.get(22));
+ assertEquals(new Token(SPACE, " "), tokens.get(23));
+ assertEquals(new Token(NOISE, "<NOISE>"), tokens.get(24));
+ assertEquals(new Token(WORD, "a"), tokens.get(25));
}
@Test
@@ -82,7 +86,7 @@ public class TokenizerTestCase {
public void testOneSpecialToken() {
Tokenizer tokenizer = new Tokenizer(new SimpleLinguistics());
- tokenizer.setSpecialTokens(createSpecialTokens());
+ tokenizer.setSpecialTokens(createSpecialTokens().getSpecialTokens("default"));
List<?> tokens = tokenizer.tokenize("c++ lovers, please apply");
assertEquals(new Token(WORD, "c++"), tokens.get(0));
@@ -92,7 +96,7 @@ public class TokenizerTestCase {
public void testSpecialTokenCombination() {
Tokenizer tokenizer = new Tokenizer(new SimpleLinguistics());
- tokenizer.setSpecialTokens(createSpecialTokens());
+ tokenizer.setSpecialTokens(createSpecialTokens().getSpecialTokens("default"));
List<?> tokens = tokenizer.tokenize("c#, c++ or .net know, not tcp/ip");
assertEquals(new Token(WORD, "c#"), tokens.get(0));
@@ -118,10 +122,9 @@ public class TokenizerTestCase {
*/
@Test
public void testSpecialTokenCJK() {
- assertEquals("Special tokens configured", 6, defaultRegistry.getSpecialTokens("default").size());
Tokenizer tokenizer = new Tokenizer(new SimpleLinguistics());
tokenizer.setSubstringSpecialTokens(true);
- tokenizer.setSpecialTokens(defaultRegistry.getSpecialTokens("default"));
+ tokenizer.setSpecialTokens(createSpecialTokens().getSpecialTokens("replacing"));
List<?> tokens = tokenizer.tokenize("fooc#bar,c++with spacebarknowknowknow,knowknownot know");
assertEquals(new Token(WORD, "foo"), tokens.get(0));
@@ -146,7 +149,7 @@ public class TokenizerTestCase {
public void testSpecialTokenCaseInsensitive() {
Tokenizer tokenizer = new Tokenizer(new SimpleLinguistics());
- tokenizer.setSpecialTokens(createSpecialTokens());
+ tokenizer.setSpecialTokens(createSpecialTokens().getSpecialTokens("default"));
List<?> tokens = tokenizer.tokenize("The AS/400 is great");
assertEquals(new Token(WORD, "The"), tokens.get(0));
@@ -162,7 +165,7 @@ public class TokenizerTestCase {
public void testSpecialTokenNonMatch() {
Tokenizer tokenizer = new Tokenizer(new SimpleLinguistics());
- tokenizer.setSpecialTokens(createSpecialTokens());
+ tokenizer.setSpecialTokens(createSpecialTokens().getSpecialTokens("default"));
List<?> tokens = tokenizer.tokenize("c++ c+ aS/400 i/o .net i/ooo ap.net");
assertEquals(new Token(WORD, "c++"), tokens.get(0));
@@ -185,18 +188,9 @@ public class TokenizerTestCase {
@Test
public void testSpecialTokenConfigurationDefault() {
- String tokenFile = "file:src/test/java/com/yahoo/prelude/query/parser/test/specialtokens.cfg";
-
- SpecialTokenRegistry r = new SpecialTokenRegistry(tokenFile);
- assertEquals("Special tokens configured", 6,
- r.getSpecialTokens("default").size());
- assertEquals("Special tokens configured", 4,
- r.getSpecialTokens("other").size());
-
Tokenizer tokenizer = new Tokenizer(new SimpleLinguistics());
- tokenizer.setSpecialTokens(
- r.getSpecialTokens("default"));
+ tokenizer.setSpecialTokens(createSpecialTokens().getSpecialTokens("default"));
List<?> tokens = tokenizer.tokenize(
"with space, c++ or .... know, not b.s.d.");
@@ -219,18 +213,9 @@ public class TokenizerTestCase {
@Test
public void testSpecialTokenConfigurationOther() {
- String tokenFile = "file:src/test/java/com/yahoo/prelude/query/parser/test/specialtokens.cfg";
-
- SpecialTokenRegistry r = new SpecialTokenRegistry(tokenFile);
- assertEquals("Special tokens configured", 6,
- r.getSpecialTokens("default").size());
- assertEquals("Special tokens configured", 4,
- r.getSpecialTokens("other").size());
-
Tokenizer tokenizer = new Tokenizer(new SimpleLinguistics());
- tokenizer.setSpecialTokens(
- r.getSpecialTokens("other"));
+ tokenizer.setSpecialTokens(createSpecialTokens().getSpecialTokens("other"));
List<?> tokens = tokenizer.tokenize(
"with space,!!!*** [huh] or ------ " + "know, &&&%%% b.s.d.");
@@ -262,26 +247,9 @@ public class TokenizerTestCase {
}
@Test
- public void testSpecialTokenConfigurationMissing() {
- String tokenFile = "file:source/bogus/specialtokens.cfg";
-
- SpecialTokenRegistry r = new SpecialTokenRegistry(tokenFile);
-
- Tokenizer tokenizer = new Tokenizer(new SimpleLinguistics());
-
- tokenizer.setSpecialTokens(r.getSpecialTokens("other"));
- List<?> tokens = tokenizer.tokenize("c++");
-
- assertEquals(new Token(WORD, "c"), tokens.get(0));
- assertEquals(new Token(PLUS, "+"), tokens.get(1));
- assertEquals(new Token(PLUS, "+"), tokens.get(2));
- }
-
- @Test
public void testTokenReplacing() {
- assertEquals("Special tokens configured", 6, defaultRegistry.getSpecialTokens("default").size());
Tokenizer tokenizer = new Tokenizer(new SimpleLinguistics());
- tokenizer.setSpecialTokens(defaultRegistry.getSpecialTokens("default"));
+ tokenizer.setSpecialTokens(createSpecialTokens().getSpecialTokens("replacing"));
List<?> tokens = tokenizer.tokenize("with space, c++ or .... know, not b.s.d.");
assertEquals(new Token(WORD, "with-space"), tokens.get(0));
@@ -740,7 +708,7 @@ public class TokenizerTestCase {
public void testSingleQuoteAsWordCharacter() {
Tokenizer tokenizer = new Tokenizer(new SimpleLinguistics());
- tokenizer.setSpecialTokens(createSpecialTokens());
+ tokenizer.setSpecialTokens(createSpecialTokens().getSpecialTokens("default"));
List<?> tokens = tokenizer.tokenize("drive (to hwy88, 88) +or language:en nalle:a'a ugcapi_1 'a' 'a a'");
assertEquals(new Token(WORD, "drive"), tokens.get(0));
@@ -776,17 +744,38 @@ public class TokenizerTestCase {
assertEquals(new Token(WORD, "a'"), tokens.get(30));
}
- private SpecialTokens createSpecialTokens() {
- SpecialTokens tokens = new SpecialTokens("default");
-
- tokens.addSpecialToken("c+", null);
- tokens.addSpecialToken("c++", null);
- tokens.addSpecialToken(".net", null);
- tokens.addSpecialToken("tcp/ip", null);
- tokens.addSpecialToken("i/o", null);
- tokens.addSpecialToken("c#", null);
- tokens.addSpecialToken("AS/400", null);
- return tokens;
+ private SpecialTokenRegistry createSpecialTokens() {
+ List<SpecialTokens.Token> tokens = new ArrayList<>();
+ tokens.add(new SpecialTokens.Token("c+"));
+ tokens.add(new SpecialTokens.Token("c++"));
+ tokens.add(new SpecialTokens.Token(".net"));
+ tokens.add(new SpecialTokens.Token("tcp/ip"));
+ tokens.add(new SpecialTokens.Token("i/o"));
+ tokens.add(new SpecialTokens.Token("c#"));
+ tokens.add(new SpecialTokens.Token("AS/400"));
+ tokens.add(new SpecialTokens.Token("...."));
+ tokens.add(new SpecialTokens.Token("b.s.d."));
+ tokens.add(new SpecialTokens.Token("with space"));
+ tokens.add(new SpecialTokens.Token("dvd\\xB1r"));
+ SpecialTokens defaultTokens = new SpecialTokens("default", tokens);
+
+ tokens = new ArrayList<>();
+ tokens.add(new SpecialTokens.Token("[huh]"));
+ tokens.add(new SpecialTokens.Token("&&&%%%"));
+ tokens.add(new SpecialTokens.Token("------"));
+ tokens.add(new SpecialTokens.Token("!!!***"));
+ SpecialTokens otherTokens = new SpecialTokens("other", tokens);
+
+ tokens = new ArrayList<>();
+ tokens.add(new SpecialTokens.Token("...."));
+ tokens.add(new SpecialTokens.Token("c++", "cpp"));
+ tokens.add(new SpecialTokens.Token("b.s.d."));
+ tokens.add(new SpecialTokens.Token("with space", "with-space"));
+ tokens.add(new SpecialTokens.Token("c#"));
+ tokens.add(new SpecialTokens.Token("know", "knuwww"));
+ SpecialTokens replacingTokens = new SpecialTokens("replacing", tokens);
+
+ return new SpecialTokenRegistry(List.of(defaultTokens, otherTokens, replacingTokens));
}
}
diff --git a/container-search/src/test/java/com/yahoo/prelude/query/parser/test/replacingtokens.cfg b/container-search/src/test/java/com/yahoo/prelude/query/parser/test/replacingtokens.cfg
deleted file mode 100644
index 6a189de0164..00000000000
--- a/container-search/src/test/java/com/yahoo/prelude/query/parser/test/replacingtokens.cfg
+++ /dev/null
@@ -1,12 +0,0 @@
-tokenlist[1]
-tokenlist[0].name default
-tokenlist[0].tokens[6]
-tokenlist[0].tokens[0].token ....
-tokenlist[0].tokens[1].token c++
-tokenlist[0].tokens[1].replace cpp
-tokenlist[0].tokens[2].token b.s.d.
-tokenlist[0].tokens[3].token with space
-tokenlist[0].tokens[3].replace with-space
-tokenlist[0].tokens[4].token c#
-tokenlist[0].tokens[5].token know
-tokenlist[0].tokens[5].replace knuwww
diff --git a/container-search/src/test/java/com/yahoo/prelude/query/test/QueryCanonicalizerTestCase.java b/container-search/src/test/java/com/yahoo/prelude/query/test/QueryCanonicalizerTestCase.java
index d3b64100c1e..e7a2a4f3ef8 100644
--- a/container-search/src/test/java/com/yahoo/prelude/query/test/QueryCanonicalizerTestCase.java
+++ b/container-search/src/test/java/com/yahoo/prelude/query/test/QueryCanonicalizerTestCase.java
@@ -29,7 +29,7 @@ public class QueryCanonicalizerTestCase {
CompositeItem root = new WeakAndItem();
root.addItem(new WordItem("word"));
- assertCanonicalized("WAND(100) word", null, root);
+ assertCanonicalized("WEAKAND(100) word", null, root);
}
@Test
@@ -108,6 +108,47 @@ public class QueryCanonicalizerTestCase {
}
@Test
+ public void testMultilevelWeakAndCollapsing() {
+ CompositeItem root = new WeakAndItem();
+ CompositeItem l1 = new WeakAndItem();
+ CompositeItem l2 = new WeakAndItem();
+ CompositeItem l3 = new WeakAndItem();
+ CompositeItem l4 = new WeakAndItem();
+
+ root.addItem(l1);
+
+ l1.addItem(l2);
+ l1.addItem(new WordItem("l1"));
+
+ l2.addItem(l3);
+ l2.addItem(new WordItem("l2"));
+
+ l3.addItem(l4);
+ l3.addItem(new WordItem("l3"));
+
+ l4.addItem(new WordItem("l4"));
+
+ assertCanonicalized("WEAKAND(100) l4 l3 l2 l1", null, root);
+ }
+
+ @Test
+ public void testWeakAndCollapsingRequireSameNAndIndex() {
+ CompositeItem root = new WeakAndItem(10);
+ CompositeItem l1 = new WeakAndItem(100);
+ CompositeItem l2 = new WeakAndItem(100);
+ l2.setIndexName("other");
+
+ root.addItem(l1);
+
+ l1.addItem(l2);
+ l1.addItem(new WordItem("l1"));
+
+ l2.addItem(new WordItem("l2"));
+
+ assertCanonicalized("WEAKAND(10) (WEAKAND(100) (WEAKAND(100) l2) l1)", null, root);
+ }
+
+ @Test
public void testNullRoot() {
assertCanonicalized(null, "No query", new Query());
}
diff --git a/container-search/src/test/java/com/yahoo/prelude/query/test/SameElementItemTestCase.java b/container-search/src/test/java/com/yahoo/prelude/query/test/SameElementItemTestCase.java
index 1382c106ae3..bb3a775ccf2 100644
--- a/container-search/src/test/java/com/yahoo/prelude/query/test/SameElementItemTestCase.java
+++ b/container-search/src/test/java/com/yahoo/prelude/query/test/SameElementItemTestCase.java
@@ -5,10 +5,14 @@ import com.yahoo.prelude.query.AndItem;
import com.yahoo.prelude.query.IntItem;
import com.yahoo.prelude.query.Item;
import com.yahoo.prelude.query.SameElementItem;
+import com.yahoo.prelude.query.Substring;
import com.yahoo.prelude.query.TermItem;
+import com.yahoo.prelude.query.WordAlternativesItem;
import com.yahoo.prelude.query.WordItem;
import org.junit.Test;
+import java.util.Collections;
+import java.util.List;
import java.util.Optional;
import static org.junit.Assert.assertEquals;
@@ -79,7 +83,7 @@ public class SameElementItemTestCase {
}
@Test
- public void requireAllChildrenAreTermItems() {
+ public void requireNoChildrenAreWordAlternatives() {
try {
SameElementItem s = new SameElementItem("structa");
s.addItem(new AndItem());
@@ -91,6 +95,19 @@ public class SameElementItemTestCase {
}
}
+ @Test
+ public void requireAllChildrenAreTermItems() {
+ try {
+ SameElementItem s = new SameElementItem("structa");
+ s.addItem(new WordAlternativesItem("test", true, new Substring("origin"), List.of(new WordAlternativesItem.Alternative("a", 0.3))));
+ fail("Expected exception");
+ }
+ catch (IllegalArgumentException e) { // Success
+ assertEquals("Child item WORD_ALTERNATIVES test:[ a(0.3) ] should NOT be an instance of class com.yahoo.prelude.query.WordAlternativesItem but is class com.yahoo.prelude.query.WordAlternativesItem",
+ e.getMessage());
+ }
+ }
+
private void verifyExtractSingle(TermItem term) {
String subFieldName = term.getIndexName();
SameElementItem s = new SameElementItem("structa");
diff --git a/container-search/src/test/java/com/yahoo/prelude/querytransform/test/CJKSearcherTestCase.java b/container-search/src/test/java/com/yahoo/prelude/querytransform/test/CJKSearcherTestCase.java
index 91cf5015cba..0ca4b8aa615 100644
--- a/container-search/src/test/java/com/yahoo/prelude/querytransform/test/CJKSearcherTestCase.java
+++ b/container-search/src/test/java/com/yahoo/prelude/querytransform/test/CJKSearcherTestCase.java
@@ -45,7 +45,7 @@ public class CJKSearcherTestCase {
@Test
public void testCjkQueryWithOverlappingTokens() {
// The test language segmenter will segment "bcd" into the overlapping tokens "bc" "cd"
- assertTransformed("bcd", "'bc cd'", Query.Type.ALL, Language.CHINESE_SIMPLIFIED, Language.CHINESE_TRADITIONAL,
+ assertTransformed("bcd", "SAND bc cd", Query.Type.ALL, Language.CHINESE_SIMPLIFIED, Language.CHINESE_TRADITIONAL,
TestLinguistics.INSTANCE);
// While "efg" will be segmented into one of the standard options, "e" "fg"
diff --git a/container-search/src/test/java/com/yahoo/prelude/querytransform/test/LiteralBoostSearcherTestCase.java b/container-search/src/test/java/com/yahoo/prelude/querytransform/test/LiteralBoostSearcherTestCase.java
index 12e756a07ee..023cd3c2849 100644
--- a/container-search/src/test/java/com/yahoo/prelude/querytransform/test/LiteralBoostSearcherTestCase.java
+++ b/container-search/src/test/java/com/yahoo/prelude/querytransform/test/LiteralBoostSearcherTestCase.java
@@ -71,7 +71,7 @@ public class LiteralBoostSearcherTestCase {
@Test
public void testQueryWithoutBoost() {
- assertEquals("RANK (AND \"nonexistant a\" \"nonexistant b\") default_literal:nonexistant default_literal:a default_literal:nonexistant default_literal:b",
+ assertEquals("RANK (AND nonexistant a nonexistant b) default_literal:nonexistant default_literal:a default_literal:nonexistant default_literal:b",
transformQuery("?query=nonexistant:a nonexistant:b&source=cluster1&restrict=type1"));
}
diff --git a/container-search/src/test/java/com/yahoo/prelude/querytransform/test/QueryRewriteTestCase.java b/container-search/src/test/java/com/yahoo/prelude/querytransform/test/QueryRewriteTestCase.java
index 36137abd9b8..6143682c028 100644
--- a/container-search/src/test/java/com/yahoo/prelude/querytransform/test/QueryRewriteTestCase.java
+++ b/container-search/src/test/java/com/yahoo/prelude/querytransform/test/QueryRewriteTestCase.java
@@ -89,8 +89,10 @@ public class QueryRewriteTestCase {
@Test
public void testRestrictRank() {
- assertRewritten("sddocname:per&filter=abc", "espen", "|abc");
+ assertRewritten("sddocname:per&filter=abc", "espen", "NULL");
assertRewritten("sddocname:per&filter=abc", "per", "RANK sddocname:per |abc");
+ assertRewritten("sddocname:per RANK bar", "per", "RANK sddocname:per bar");
+ assertRewritten("sddocname:per RANK bar", "espen", "NULL");
}
private static Query query(String queryString, String restrict) {
diff --git a/container-search/src/test/java/com/yahoo/prelude/searcher/test/FieldCollapsingSearcherTestCase.java b/container-search/src/test/java/com/yahoo/prelude/searcher/test/FieldCollapsingSearcherTestCase.java
index 4875121a501..12619bf0a5e 100644
--- a/container-search/src/test/java/com/yahoo/prelude/searcher/test/FieldCollapsingSearcherTestCase.java
+++ b/container-search/src/test/java/com/yahoo/prelude/searcher/test/FieldCollapsingSearcherTestCase.java
@@ -40,34 +40,8 @@ import static org.junit.Assert.assertTrue;
*
* @author Steinar Knutsen
*/
-@SuppressWarnings("deprecation")
public class FieldCollapsingSearcherTestCase {
- private FastHit createHit(String uri,int relevancy,int mid) {
- FastHit hit = new FastHit(uri,relevancy);
- hit.setField("amid", String.valueOf(mid));
- return hit;
- }
-
- private void assertHit(String uri,int relevancy,int mid,Hit hit) {
- assertEquals(uri,hit.getId().toString());
- assertEquals(relevancy, ((int) hit.getRelevance().getScore()));
- assertEquals(mid,Integer.parseInt((String) hit.getField("amid")));
- }
-
- private static class ZeroHitsControl extends com.yahoo.search.Searcher {
- public int queryCount = 0;
- public com.yahoo.search.Result search(com.yahoo.search.Query query,
- com.yahoo.search.searchchain.Execution execution) {
- ++queryCount;
- if (query.getHits() == 0) {
- return new Result(query);
- } else {
- return new Result(query, ErrorMessage.createIllegalQuery("Did not request zero hits."));
- }
- }
- }
-
@Test
public void testFieldCollapsingWithoutHits() {
// Set up
@@ -116,14 +90,14 @@ public class FieldCollapsingSearcherTestCase {
// The searcher turns off collapsing further on in the chain
q.properties().set("collapse", "0");
Result r = new Result(q);
- r.hits().add(createHit("http://acme.org/a.html",10,0));
- r.hits().add(createHit("http://acme.org/b.html", 9,0));
- r.hits().add(createHit("http://acme.org/c.html", 9,1));
- r.hits().add(createHit("http://acme.org/d.html", 8,1));
- r.hits().add(createHit("http://acme.org/e.html", 8,2));
- r.hits().add(createHit("http://acme.org/f.html", 7,2));
- r.hits().add(createHit("http://acme.org/g.html", 7,3));
- r.hits().add(createHit("http://acme.org/h.html", 6,3));
+ r.hits().add(createHit("http://acme.org/a.html",10, 0));
+ r.hits().add(createHit("http://acme.org/b.html", 9, 0));
+ r.hits().add(createHit("http://acme.org/c.html", 9, 1));
+ r.hits().add(createHit("http://acme.org/d.html", 8, 1));
+ r.hits().add(createHit("http://acme.org/e.html", 8, 2));
+ r.hits().add(createHit("http://acme.org/f.html", 7, 2));
+ r.hits().add(createHit("http://acme.org/g.html", 7, 3));
+ r.hits().add(createHit("http://acme.org/h.html", 6, 3));
r.setTotalHitCount(8);
docsource.addResult(q, r);
@@ -133,10 +107,10 @@ public class FieldCollapsingSearcherTestCase {
assertEquals(4, r.getHitCount());
assertEquals(1, docsource.getQueryCount());
- assertHit("http://acme.org/a.html",10,0,r.hits().get(0));
- assertHit("http://acme.org/c.html", 9,1,r.hits().get(1));
- assertHit("http://acme.org/e.html", 8,2,r.hits().get(2));
- assertHit("http://acme.org/g.html", 7,3,r.hits().get(3));
+ assertHit("http://acme.org/a.html",10, 0, r.hits().get(0));
+ assertHit("http://acme.org/c.html", 9, 1, r.hits().get(1));
+ assertHit("http://acme.org/e.html", 8, 2, r.hits().get(2));
+ assertHit("http://acme.org/g.html", 7, 3, r.hits().get(3));
}
@Test
@@ -152,14 +126,14 @@ public class FieldCollapsingSearcherTestCase {
// The searcher turns off collapsing further on in the chain
q.properties().set("collapse", "0");
Result r = new Result(q);
- r.hits().add(createHit("http://acme.org/a.html",10,0));
- r.hits().add(createHit("http://acme.org/b.html", 9,0));
- r.hits().add(createHit("http://acme.org/c.html", 9,1));
- r.hits().add(createHit("http://acme.org/d.html", 8,1));
- r.hits().add(createHit("http://acme.org/e.html", 8,2));
- r.hits().add(createHit("http://acme.org/f.html", 7,2));
- r.hits().add(createHit("http://acme.org/g.html", 7,3));
- r.hits().add(createHit("http://acme.org/h.html", 6,3));
+ r.hits().add(createHit("http://acme.org/a.html",10, 0));
+ r.hits().add(createHit("http://acme.org/b.html", 9, 0));
+ r.hits().add(createHit("http://acme.org/c.html", 9, 1));
+ r.hits().add(createHit("http://acme.org/d.html", 8, 1));
+ r.hits().add(createHit("http://acme.org/e.html", 8, 2));
+ r.hits().add(createHit("http://acme.org/f.html", 7, 2));
+ r.hits().add(createHit("http://acme.org/g.html", 7, 3));
+ r.hits().add(createHit("http://acme.org/h.html", 6, 3));
r.setTotalHitCount(8);
docsource.addResult(q, r);
@@ -169,10 +143,10 @@ public class FieldCollapsingSearcherTestCase {
assertEquals(4, r.getHitCount());
assertEquals(1, docsource.getQueryCount());
- assertHit("http://acme.org/a.html",10,0,r.hits().get(0));
- assertHit("http://acme.org/c.html", 9,1,r.hits().get(1));
- assertHit("http://acme.org/e.html", 8,2,r.hits().get(2));
- assertHit("http://acme.org/g.html", 7,3,r.hits().get(3));
+ assertHit("http://acme.org/a.html",10,0, r.hits().get(0));
+ assertHit("http://acme.org/c.html", 9,1, r.hits().get(1));
+ assertHit("http://acme.org/e.html", 8,2, r.hits().get(2));
+ assertHit("http://acme.org/g.html", 7,3, r.hits().get(3));
}
@Test
@@ -185,14 +159,14 @@ public class FieldCollapsingSearcherTestCase {
Query q = new Query("?query=test_collapse");
Result r = new Result(q);
- r.hits().add(createHit("http://acme.org/a.html",10,0));
- r.hits().add(createHit("http://acme.org/b.html", 9,0));
- r.hits().add(createHit("http://acme.org/c.html", 9,1));
- r.hits().add(createHit("http://acme.org/d.html", 8,1));
- r.hits().add(createHit("http://acme.org/e.html", 8,2));
- r.hits().add(createHit("http://acme.org/f.html", 7,2));
- r.hits().add(createHit("http://acme.org/g.html", 7,3));
- r.hits().add(createHit("http://acme.org/h.html", 6,3));
+ r.hits().add(createHit("http://acme.org/a.html",10, 0));
+ r.hits().add(createHit("http://acme.org/b.html", 9, 0));
+ r.hits().add(createHit("http://acme.org/c.html", 9, 1));
+ r.hits().add(createHit("http://acme.org/d.html", 8, 1));
+ r.hits().add(createHit("http://acme.org/e.html", 8, 2));
+ r.hits().add(createHit("http://acme.org/f.html", 7, 2));
+ r.hits().add(createHit("http://acme.org/g.html", 7, 3));
+ r.hits().add(createHit("http://acme.org/h.html", 6, 3));
r.setTotalHitCount(8);
docsource.addResult(q, r);
@@ -220,16 +194,16 @@ public class FieldCollapsingSearcherTestCase {
// The searcher turns off collapsing further on in the chain
q.properties().set("collapse", "0");
Result r = new Result(q);
- r.hits().add(createHit("http://acme.org/a.html",10,0));
- r.hits().add(createHit("http://acme.org/b.html", 9,0));
- r.hits().add(createHit("http://acme.org/c.html", 9,0));
- r.hits().add(createHit("http://acme.org/d.html", 8,0));
- r.hits().add(createHit("http://acme.org/e.html", 8,0));
- r.hits().add(createHit("http://acme.org/f.html", 7,0));
- r.hits().add(createHit("http://acme.org/g.html", 7,0));
- r.hits().add(createHit("http://acme.org/h.html", 6,0));
- r.hits().add(createHit("http://acme.org/i.html", 5,1));
- r.hits().add(createHit("http://acme.org/j.html", 4,2));
+ r.hits().add(createHit("http://acme.org/a.html",10, 0));
+ r.hits().add(createHit("http://acme.org/b.html", 9, 0));
+ r.hits().add(createHit("http://acme.org/c.html", 9, 0));
+ r.hits().add(createHit("http://acme.org/d.html", 8, 0));
+ r.hits().add(createHit("http://acme.org/e.html", 8, 0));
+ r.hits().add(createHit("http://acme.org/f.html", 7, 0));
+ r.hits().add(createHit("http://acme.org/g.html", 7, 0));
+ r.hits().add(createHit("http://acme.org/h.html", 6, 0));
+ r.hits().add(createHit("http://acme.org/i.html", 5, 1));
+ r.hits().add(createHit("http://acme.org/j.html", 4, 2));
r.setTotalHitCount(10);
docsource.addResult(q, r);
@@ -239,15 +213,15 @@ public class FieldCollapsingSearcherTestCase {
assertEquals(2, r.getHitCount());
assertEquals(2, docsource.getQueryCount());
- assertHit("http://acme.org/a.html",10,0,r.hits().get(0));
- assertHit("http://acme.org/i.html", 5,1,r.hits().get(1));
+ assertHit("http://acme.org/a.html",10, 0, r.hits().get(0));
+ assertHit("http://acme.org/i.html", 5, 1, r.hits().get(1));
// Next results
docsource.resetQueryCount();
r = doSearch(collapse, q, 2, 2, chained);
assertEquals(1, r.getHitCount());
assertEquals(2, docsource.getQueryCount());
- assertHit("http://acme.org/j.html",4,2,r.hits().get(0));
+ assertHit("http://acme.org/j.html",4, 2, r.hits().get(0));
}
/**
@@ -265,16 +239,16 @@ public class FieldCollapsingSearcherTestCase {
// The searcher turns off collapsing further on in the chain
q.properties().set("collapse", "0");
Result r = new Result(q);
- r.hits().add(createHit("http://acme.org/a.html",10,1));
- r.hits().add(createHit("http://acme.org/b.html",10,1));
- r.hits().add(createHit("http://acme.org/c.html",10,0));
- r.hits().add(createHit("http://acme.org/d.html",10,0));
- r.hits().add(createHit("http://acme.org/e.html",10,0));
- r.hits().add(createHit("http://acme.org/f.html",10,0));
- r.hits().add(createHit("http://acme.org/g.html",10,0));
- r.hits().add(createHit("http://acme.org/h.html",10,0));
- r.hits().add(createHit("http://acme.org/i.html",10,0));
- r.hits().add(createHit("http://acme.org/j.html",10,1));
+ r.hits().add(createHit("http://acme.org/a.html", 10, 1));
+ r.hits().add(createHit("http://acme.org/b.html", 10, 1));
+ r.hits().add(createHit("http://acme.org/c.html", 10, 0));
+ r.hits().add(createHit("http://acme.org/d.html", 10, 0));
+ r.hits().add(createHit("http://acme.org/e.html", 10, 0));
+ r.hits().add(createHit("http://acme.org/f.html", 10, 0));
+ r.hits().add(createHit("http://acme.org/g.html", 10, 0));
+ r.hits().add(createHit("http://acme.org/h.html", 10, 0));
+ r.hits().add(createHit("http://acme.org/i.html", 10, 0));
+ r.hits().add(createHit("http://acme.org/j.html", 10, 1));
r.setTotalHitCount(10);
docsource.addResult(q, r);
@@ -287,17 +261,6 @@ public class FieldCollapsingSearcherTestCase {
assertHit("http://acme.org/c.html",10,0,r.hits().get(1));
}
- public static class QueryMessupSearcher extends Searcher {
- public Result search(com.yahoo.search.Query query, Execution execution) {
- AndItem a = new AndItem();
- a.addItem(query.getModel().getQueryTree().getRoot());
- a.addItem(new WordItem("b"));
- query.getModel().getQueryTree().setRoot(a);
-
- return execution.search(query);
- }
- }
-
@Test
public void testQueryTransformAndCollapsing() {
// Set up
@@ -309,9 +272,9 @@ public class FieldCollapsingSearcherTestCase {
chained.put(collapse, messUp);
chained.put(messUp, docsource);
- // Caveat: Collapse is set to false, because that's what the
- // collapser asks for
- Query q = new Query("?query=test_collapse+b&collapsefield=amid");
+ // Caveat: Collapse is set to false, because that's what the collapser asks for
+ Query q = new Query("?query=%22test%20collapse%22+b&collapsefield=amid");
+ System.out.println(q);
// The searcher turns off collapsing further on in the chain
q.properties().set("collapse", "0");
Result r = new Result(q);
@@ -327,13 +290,13 @@ public class FieldCollapsingSearcherTestCase {
docsource.addResult(q, r);
// Test basic collapsing on mid
- q = new Query("?query=test_collapse&collapsefield=amid");
+ q = new Query("?query=%22test%20collapse%22&collapsefield=amid");
r = doSearch(collapse, q, 0, 2, chained);
assertEquals(2, docsource.getQueryCount());
assertEquals(2, r.getHitCount());
- assertHit("http://acme.org/a.html",10,0,r.hits().get(0));
- assertHit("http://acme.org/h.html", 6,1,r.hits().get(1));
+ assertHit("http://acme.org/a.html",10, 0, r.hits().get(0));
+ assertHit("http://acme.org/h.html", 6, 1, r.hits().get(1));
}
@Test
@@ -367,10 +330,10 @@ public class FieldCollapsingSearcherTestCase {
assertEquals(4, r.getHitCount());
assertEquals(1, docsource.getQueryCount());
assertTrue(r.isFilled("placeholder"));
- assertHit("http://acme.org/a.html",10,0,r.hits().get(0));
- assertHit("http://acme.org/c.html", 9,1,r.hits().get(1));
- assertHit("http://acme.org/e.html", 8,2,r.hits().get(2));
- assertHit("http://acme.org/g.html", 7,3,r.hits().get(3));
+ assertHit("http://acme.org/a.html",10, 0, r.hits().get(0));
+ assertHit("http://acme.org/c.html", 9, 1, r.hits().get(1));
+ assertHit("http://acme.org/e.html", 8, 2, r.hits().get(2));
+ assertHit("http://acme.org/g.html", 7, 3, r.hits().get(3));
docsource.resetQueryCount();
// Test basic collapsing on mid
@@ -381,10 +344,10 @@ public class FieldCollapsingSearcherTestCase {
assertEquals(1, docsource.getQueryCount());
assertFalse(r.isFilled("placeholder"));
assertTrue(r.isFilled("short"));
- assertHit("http://acme.org/a.html",10,0,r.hits().get(0));
- assertHit("http://acme.org/c.html", 9,1,r.hits().get(1));
- assertHit("http://acme.org/e.html", 8,2,r.hits().get(2));
- assertHit("http://acme.org/g.html", 7,3,r.hits().get(3));
+ assertHit("http://acme.org/a.html",10, 0, r.hits().get(0));
+ assertHit("http://acme.org/c.html", 9, 1, r.hits().get(1));
+ assertHit("http://acme.org/e.html", 8, 2, r.hits().get(2));
+ assertHit("http://acme.org/g.html", 7, 3, r.hits().get(3));
}
@Test
@@ -400,14 +363,14 @@ public class FieldCollapsingSearcherTestCase {
// The searcher turns off collapsing further on in the chain
q.properties().set("collapse", "0");
Result r = new Result(q);
- r.hits().add(createHit("http://acme.org/a.html",10,0));
- r.hits().add(createHit("http://acme.org/b.html", 9,0));
- r.hits().add(createHit("http://acme.org/c.html", 9,1));
- r.hits().add(createHit("http://acme.org/d.html", 8,1));
- r.hits().add(createHit("http://acme.org/e.html", 8,2));
- r.hits().add(createHit("http://acme.org/f.html", 7,2));
- r.hits().add(createHit("http://acme.org/g.html", 7,3));
- r.hits().add(createHit("http://acme.org/h.html", 6,3));
+ r.hits().add(createHit("http://acme.org/a.html",10, 0));
+ r.hits().add(createHit("http://acme.org/b.html", 9, 0));
+ r.hits().add(createHit("http://acme.org/c.html", 9, 1));
+ r.hits().add(createHit("http://acme.org/d.html", 8, 1));
+ r.hits().add(createHit("http://acme.org/e.html", 8, 2));
+ r.hits().add(createHit("http://acme.org/f.html", 7, 2));
+ r.hits().add(createHit("http://acme.org/g.html", 7, 3));
+ r.hits().add(createHit("http://acme.org/h.html", 6, 3));
r.setTotalHitCount(8);
docsource.addResult(q, r);
@@ -416,29 +379,28 @@ public class FieldCollapsingSearcherTestCase {
Result result = new Execution(chain, Execution.Context.createContextStub()).search(query);
// Assert that the regular hits are collapsed
- assertEquals(4+1, result.getHitCount());
+ assertEquals(4 + 1, result.getHitCount());
assertEquals(1, docsource.getQueryCount());
- assertHit("http://acme.org/a.html",10,0,result.hits().get(0));
- assertHit("http://acme.org/c.html", 9,1,result.hits().get(1));
- assertHit("http://acme.org/e.html", 8,2,result.hits().get(2));
- assertHit("http://acme.org/g.html", 7,3,result.hits().get(3));
+ assertHit("http://acme.org/a.html",10, 0, result.hits().get(0));
+ assertHit("http://acme.org/c.html", 9, 1, result.hits().get(1));
+ assertHit("http://acme.org/e.html", 8, 2, result.hits().get(2));
+ assertHit("http://acme.org/g.html", 7, 3, result.hits().get(3));
// Assert that the aggregation group hierarchy is left intact
- HitGroup root= getFirstGroupIn(result.hits());
+ HitGroup root = getFirstGroupIn(result.hits());
assertNotNull(root);
- assertEquals("group:root:",root.getId().stringValue().substring(0,11)); // The id ends by a global counter currently
- assertEquals(1,root.size());
- HitGroup groupList= (GroupList)root.get("grouplist:g1");
+ assertEquals("group:root:",root.getId().stringValue().substring(0, 11)); // The id ends by a global counter currently
+ assertEquals(1, root.size());
+ HitGroup groupList = (GroupList)root.get("grouplist:g1");
assertNotNull(groupList);
- assertEquals(1,groupList.size());
- HitGroup group= (HitGroup)groupList.get("group:long:37");
+ assertEquals(1, groupList.size());
+ HitGroup group = (HitGroup)groupList.get("group:long:37");
assertNotNull(group);
}
private Group getFirstGroupIn(HitGroup hits) {
- for (Hit h : hits) {
+ for (Hit h : hits)
if (h instanceof Group) return (Group)h;
- }
return null;
}
@@ -450,9 +412,8 @@ public class FieldCollapsingSearcherTestCase {
private Chain<Searcher> chainedAsSearchChain(Searcher topOfChain, Map<Searcher, Searcher> chained) {
List<Searcher> searchers = new ArrayList<>();
- for (Searcher current = topOfChain; current != null; current = chained.get(current)) {
+ for (Searcher current = topOfChain; current != null; current = chained.get(current))
searchers.add(current);
- }
return new Chain<>(searchers);
}
@@ -470,7 +431,7 @@ public class FieldCollapsingSearcherTestCase {
@Override
public Result search(Query query, Execution execution) {
- Result r=execution.search(query);
+ Result r = execution.search(query);
r.hits().add(createAggregationGroup("g1"));
return r;
}
@@ -479,10 +440,51 @@ public class FieldCollapsingSearcherTestCase {
Group root = new Group(new RootId(0), new Relevance(1));
GroupList groupList = new GroupList(label);
root.add(groupList);
- Group value=new Group(new LongId(37l),new Relevance(2.11));
+ Group value = new Group(new LongId(37l), new Relevance(2.11));
groupList.add(value);
return root;
}
}
+ private FastHit createHit(String uri,int relevancy,int mid) {
+ FastHit hit = new FastHit(uri,relevancy);
+ hit.setField("amid", String.valueOf(mid));
+ return hit;
+ }
+
+ private void assertHit(String uri,int relevancy,int mid,Hit hit) {
+ assertEquals(uri,hit.getId().toString());
+ assertEquals(relevancy, ((int) hit.getRelevance().getScore()));
+ assertEquals(mid,Integer.parseInt((String) hit.getField("amid")));
+ }
+
+ private static class ZeroHitsControl extends com.yahoo.search.Searcher {
+
+ public int queryCount = 0;
+
+ @Override
+ public Result search(Query query, Execution execution) {
+ ++queryCount;
+ if (query.getHits() == 0) {
+ return new Result(query);
+ } else {
+ return new Result(query, ErrorMessage.createIllegalQuery("Did not request zero hits."));
+ }
+ }
+ }
+
+ public static class QueryMessupSearcher extends Searcher {
+
+ @Override
+ public Result search(com.yahoo.search.Query query, Execution execution) {
+ AndItem a = new AndItem();
+ a.addItem(query.getModel().getQueryTree().getRoot());
+ a.addItem(new WordItem("b"));
+ query.getModel().getQueryTree().setRoot(a);
+
+ return execution.search(query);
+ }
+
+ }
+
}
diff --git a/container-search/src/test/java/com/yahoo/prelude/searcher/test/PosSearcherTestCase.java b/container-search/src/test/java/com/yahoo/prelude/searcher/test/PosSearcherTestCase.java
index e2973f8ed65..b0c593ea405 100644
--- a/container-search/src/test/java/com/yahoo/prelude/searcher/test/PosSearcherTestCase.java
+++ b/container-search/src/test/java/com/yahoo/prelude/searcher/test/PosSearcherTestCase.java
@@ -118,6 +118,13 @@ public class PosSearcherTestCase {
q.properties().set("pos.units", "udeg");
doSearch(searcher, q, 0, 10);
assertEquals("(2,0,0,18026,0,1,0,4294967295)", q.getRanking().getLocation().toString());
+
+ q = new Query();
+ q.properties().set("pos.ll", "N0;E0");
+ q.properties().set("pos.radius", "-42");
+ doSearch(searcher, q, 0, 10);
+ assertEquals("(2,0,0,-1,0,1,0,4294967295)", q.getRanking().getLocation().toString());
+ assertEquals("(2,0,0,-1,0,1,0,4294967295)", q.getRanking().getLocation().backendString());
}
/**
@@ -128,13 +135,13 @@ public class PosSearcherTestCase {
Query q = new Query();
q.properties().set("pos.xy", "22500;22500");
doSearch(searcher, q, 0, 10);
- assertEquals("(2,22500,22500,5000,0,1,0)", q.getRanking().getLocation().toString());
+ assertEquals("(2,22500,22500,450668,0,1,0)", q.getRanking().getLocation().toString());
q = new Query();
q.properties().set("pos.xy", "22500;22500");
q.properties().set("pos.units", "unknown");
doSearch(searcher, q, 0, 10);
- assertEquals("(2,22500,22500,5000,0,1,0)", q.getRanking().getLocation().toString());
+ assertEquals("(2,22500,22500,450668,0,1,0)", q.getRanking().getLocation().toString());
}
@Test
diff --git a/container-search/src/test/java/com/yahoo/prelude/searcher/test/ValidatePredicateSearcherTestCase.java b/container-search/src/test/java/com/yahoo/prelude/searcher/test/ValidatePredicateSearcherTestCase.java
index 1b9ca1cd29b..850586ba8c5 100644
--- a/container-search/src/test/java/com/yahoo/prelude/searcher/test/ValidatePredicateSearcherTestCase.java
+++ b/container-search/src/test/java/com/yahoo/prelude/searcher/test/ValidatePredicateSearcherTestCase.java
@@ -2,7 +2,6 @@
package com.yahoo.prelude.searcher.test;
import com.google.common.util.concurrent.MoreExecutors;
-import com.yahoo.language.Linguistics;
import com.yahoo.language.simple.SimpleLinguistics;
import com.yahoo.prelude.Index;
import com.yahoo.prelude.IndexFacts;
@@ -20,13 +19,11 @@ import com.yahoo.search.searchchain.Execution;
import com.yahoo.search.yql.YqlParser;
import org.junit.Test;
-import java.util.*;
-
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
/**
- * @author <a href="mailto:magnarn@yahoo-inc.com">Magnar Nedland</a>
+ * @author Magnar Nedland
*/
public class ValidatePredicateSearcherTestCase {
@@ -46,6 +43,14 @@ public class ValidatePredicateSearcherTestCase {
assertEquals(ErrorMessage.createIllegalQuery("age=200 outside configured predicate bounds."), r.hits().getError());
}
+ @Test
+ public void queryFailsWhenPredicateFieldIsUsedInTermSearch() {
+ ValidatePredicateSearcher searcher = new ValidatePredicateSearcher();
+ String q = "select * from sources * where predicate_field CONTAINS \"true\";";
+ Result r = doSearch(searcher, q, "predicate-bounds [0..99]");
+ assertEquals(ErrorMessage.createIllegalQuery("Index 'predicate_field' is predicate attribute and can only be used in conjunction with a predicate query operator."), r.hits().getError());
+ }
+
private static Result doSearch(ValidatePredicateSearcher searcher, String yqlQuery, String command) {
QueryTree queryTree = new YqlParser(new ParserEnvironment()).parse(new Parsable().setQuery(yqlQuery));
Query query = new Query();
@@ -53,6 +58,7 @@ public class ValidatePredicateSearcherTestCase {
SearchDefinition searchDefinition = new SearchDefinition("document");
Index index = new Index("predicate_field");
+ index.setPredicate(true);
index.addCommand(command);
searchDefinition.addIndex(index);
IndexFacts indexFacts = new IndexFacts(new IndexModel(searchDefinition));
diff --git a/container-search/src/test/java/com/yahoo/prelude/semantics/test/ExpansionTestCase.java b/container-search/src/test/java/com/yahoo/prelude/semantics/test/ExpansionTestCase.java
new file mode 100644
index 00000000000..fa6b4eefdd5
--- /dev/null
+++ b/container-search/src/test/java/com/yahoo/prelude/semantics/test/ExpansionTestCase.java
@@ -0,0 +1,33 @@
+// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.prelude.semantics.test;
+
+import org.junit.Test;
+
+public class ExpansionTestCase extends RuleBaseAbstractTestCase {
+
+ public ExpansionTestCase() {
+ super("expansion.sr");
+ }
+
+ @Test
+ public void testOrExpansion() {
+ assertSemantics("OR or1 or2 or3", "or1");
+ }
+
+ @Test
+ public void testEquivExpansion1() {
+ assertSemantics("EQUIV equiv1 equiv2 equiv3", "equiv1");
+ }
+
+ @Test
+ public void testEquivExpansion2() {
+ assertSemantics("EQUIV testfield:e1 testfield:e2 testfield:e3", "testfield:foo");
+ }
+
+ @Test
+ public void testEquivExpansion3() {
+ assertSemantics("AND testfield:e1 testfield:e2 testfield:e3 testfield:e1 testfield:e2 testfield:e3",
+ "testfield:foo testfield:bar");
+ }
+
+}
diff --git a/container-search/src/test/java/com/yahoo/prelude/semantics/test/ProductionRuleTestCase.java b/container-search/src/test/java/com/yahoo/prelude/semantics/test/ProductionRuleTestCase.java
index 3513904af02..6c0084d1bdc 100644
--- a/container-search/src/test/java/com/yahoo/prelude/semantics/test/ProductionRuleTestCase.java
+++ b/container-search/src/test/java/com/yahoo/prelude/semantics/test/ProductionRuleTestCase.java
@@ -50,7 +50,7 @@ public class ProductionRuleTestCase {
RuleEvaluation e = new Evaluation(query).freshRuleEvaluation();
assertTrue(rule.matches(e));
rule.produce(e);
- assertEquals("brand:sony", query.getModel().getQueryTree().getRoot().toString());
+ assertEquals("AND brand:sony", query.getModel().getQueryTree().getRoot().toString());
}
}
diff --git a/container-search/src/test/java/com/yahoo/prelude/semantics/test/RuleBaseAbstractTestCase.java b/container-search/src/test/java/com/yahoo/prelude/semantics/test/RuleBaseAbstractTestCase.java
index 41597a22832..81d359a804d 100644
--- a/container-search/src/test/java/com/yahoo/prelude/semantics/test/RuleBaseAbstractTestCase.java
+++ b/container-search/src/test/java/com/yahoo/prelude/semantics/test/RuleBaseAbstractTestCase.java
@@ -57,8 +57,8 @@ public abstract class RuleBaseAbstractTestCase {
}
protected Query assertSemantics(String result, String input, int tracelevel, Query.Type queryType) {
- Query query=new Query("?query=" + QueryTestCase.httpEncode(input) + "&tracelevel=0&tracelevel.rules=" + tracelevel +
- "&language=und&type=" + queryType.toString());
+ Query query = new Query("?query=" + QueryTestCase.httpEncode(input) + "&tracelevel=0&tracelevel.rules=" + tracelevel +
+ "&language=und&type=" + queryType);
return assertSemantics(result, query);
}
diff --git a/container-search/src/test/java/com/yahoo/prelude/semantics/test/SegmentSubstitutionTestCase.java b/container-search/src/test/java/com/yahoo/prelude/semantics/test/SegmentSubstitutionTestCase.java
index b8db5e4d90f..a4cf7d8c380 100644
--- a/container-search/src/test/java/com/yahoo/prelude/semantics/test/SegmentSubstitutionTestCase.java
+++ b/container-search/src/test/java/com/yahoo/prelude/semantics/test/SegmentSubstitutionTestCase.java
@@ -23,7 +23,7 @@ public class SegmentSubstitutionTestCase extends RuleBaseAbstractTestCase {
Query q = new Query("?query=ignored&tracelevel=0&tracelevel.rules=0");
q.getModel().getQueryTree().setRoot(a);
- assertSemantics("\"first third\"", q);
+ assertSemantics("AND first third", q);
}
@Test
@@ -32,7 +32,7 @@ public class SegmentSubstitutionTestCase extends RuleBaseAbstractTestCase {
Query q = new Query("?query=ignored&tracelevel=0&tracelevel.rules=0");
q.getModel().getQueryTree().setRoot(a);
- assertSemantics("\"bc first third fg\"", q);
+ assertSemantics("AND bc first third fg", q);
}
@Test
@@ -41,7 +41,7 @@ public class SegmentSubstitutionTestCase extends RuleBaseAbstractTestCase {
Query q = new Query("?query=ignored&tracelevel=0&tracelevel.rules=0");
q.getModel().getQueryTree().setRoot(a);
- assertSemantics("+bc -\"first third\"", q);
+ assertSemantics("+bc -(AND first third)", q);
}
@Test
@@ -50,7 +50,7 @@ public class SegmentSubstitutionTestCase extends RuleBaseAbstractTestCase {
Query q = new Query("?query=ignored&tracelevel=0&tracelevel.rules=0");
q.getModel().getQueryTree().setRoot(a);
- assertSemantics("\"9 2 7 0 bc third 2 3 8 9\"", q);
+ assertSemantics("AND 9 2 7 0 bc third 2 3 8 9", q);
}
private static Item parseQuery(String query) {
diff --git a/container-search/src/test/java/com/yahoo/prelude/semantics/test/SemanticSearcherTestCase.java b/container-search/src/test/java/com/yahoo/prelude/semantics/test/SemanticSearcherTestCase.java
index b7754075724..2e43eae3775 100644
--- a/container-search/src/test/java/com/yahoo/prelude/semantics/test/SemanticSearcherTestCase.java
+++ b/container-search/src/test/java/com/yahoo/prelude/semantics/test/SemanticSearcherTestCase.java
@@ -24,7 +24,6 @@ import static org.junit.Assert.assertEquals;
*
* @author bratseth
*/
-@SuppressWarnings("deprecation")
public class SemanticSearcherTestCase extends RuleBaseAbstractTestCase {
public SemanticSearcherTestCase() {
@@ -35,6 +34,8 @@ public class SemanticSearcherTestCase extends RuleBaseAbstractTestCase {
public void testSingleShopping() {
assertSemantics("brand:sony",
"sony");
+ assertSemantics("brand:sony!150",
+ "sony!150");
}
@Test
@@ -63,7 +64,7 @@ public class SemanticSearcherTestCase extends RuleBaseAbstractTestCase {
@Test
public void testLiteralReplacing() {
- assertSemantics("AND lord of rings","lotr");
+ assertSemantics("AND lord of rings", "lotr");
}
@Test
@@ -151,7 +152,7 @@ public class SemanticSearcherTestCase extends RuleBaseAbstractTestCase {
@Test
public void testOrProduction() {
- assertSemantics("OR something somethingelse","something");
+ assertSemantics("OR something somethingelse", "something");
}
// This test is order dependent. Fix it!!
@@ -159,15 +160,15 @@ public class SemanticSearcherTestCase extends RuleBaseAbstractTestCase {
public void testWeightedSetItem() {
Query q = new Query();
WeightedSetItem weightedSet=new WeightedSetItem("fieldName");
- weightedSet.addToken("a",1);
- weightedSet.addToken("b",2);
+ weightedSet.addToken("a", 1);
+ weightedSet.addToken("b", 2);
q.getModel().getQueryTree().setRoot(weightedSet);
- assertSemantics("WEIGHTEDSET fieldName{[1]:\"a\",[2]:\"b\"}",q);
+ assertSemantics("WEIGHTEDSET fieldName{[1]:\"a\",[2]:\"b\"}", q);
}
@Test
public void testNullQuery() {
- Query query=new Query(""); // Causes a query containing a NullItem
+ Query query = new Query(""); // Causes a query containing a NullItem
doSearch(searcher, query, 0, 10);
assertEquals(NullItem.class, query.getModel().getQueryTree().getRoot().getClass()); // Still a NullItem
}
diff --git a/container-search/src/test/java/com/yahoo/prelude/semantics/test/WeightingTestCase.java b/container-search/src/test/java/com/yahoo/prelude/semantics/test/WeightingTestCase.java
index 349a3502c0f..3e684ca6c04 100644
--- a/container-search/src/test/java/com/yahoo/prelude/semantics/test/WeightingTestCase.java
+++ b/container-search/src/test/java/com/yahoo/prelude/semantics/test/WeightingTestCase.java
@@ -14,12 +14,12 @@ public class WeightingTestCase extends RuleBaseAbstractTestCase {
@Test
public void testWeighting() {
- assertSemantics("foo!150","foo");
- assertSemantics("AND foo!150 snip","foo snip");
- assertSemantics("AND foo!150 bar","foo bar");
- assertSemantics("AND bar!57 foo","bar foo");
- assertSemantics("AND foo!150 fu","foo fu");
- assertSemantics("AND foo!150 bar kanoo boat!237","foo bar kanoo");
+ assertSemantics("foo!150", "foo");
+ assertSemantics("AND foo!150 snip", "foo snip");
+ assertSemantics("AND foo!150 bar", "foo bar");
+ assertSemantics("AND bar!57 foo!150", "bar foo");
+ assertSemantics("AND foo!150 fu", "foo fu");
+ assertSemantics("AND foo!150 bar kanoo boat!237", "foo bar kanoo");
}
}
diff --git a/container-search/src/test/java/com/yahoo/prelude/semantics/test/rulebases/expansion.sr b/container-search/src/test/java/com/yahoo/prelude/semantics/test/rulebases/expansion.sr
new file mode 100644
index 00000000000..d03f060cbde
--- /dev/null
+++ b/container-search/src/test/java/com/yahoo/prelude/semantics/test/rulebases/expansion.sr
@@ -0,0 +1,8 @@
+# Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+or1 +> ?or2 ?or3;
+
+equiv1 +> =equiv2 =equiv3;
+
+testfield:[test] -> =testfield:e1 =testfield:e2 =testfield:e3;
+
+[test] :- foo, bar, baz;
diff --git a/container-search/src/test/java/com/yahoo/prelude/test/IndexFactsTestCase.java b/container-search/src/test/java/com/yahoo/prelude/test/IndexFactsTestCase.java
index 82a5a0c7a24..e2ac44316e7 100644
--- a/container-search/src/test/java/com/yahoo/prelude/test/IndexFactsTestCase.java
+++ b/container-search/src/test/java/com/yahoo/prelude/test/IndexFactsTestCase.java
@@ -73,7 +73,7 @@ public class IndexFactsTestCase {
Query q = newQuery("?query=a:b", indexFacts);
assertEquals("a:b", q.getModel().getQueryTree().getRoot().toString());
q = newQuery("?query=notarealindex:b", indexFacts);
- assertEquals("\"notarealindex b\"", q.getModel().getQueryTree().getRoot().toString());
+ assertEquals("AND notarealindex b", q.getModel().getQueryTree().getRoot().toString());
}
@Test
@@ -302,8 +302,8 @@ public class IndexFactsTestCase {
IndexFacts.Session session2 = indexFacts.newSession(query2.getModel().getSources(), query2.getModel().getRestrict());
assertTrue(session1.getIndex("url").isUriIndex());
assertTrue(session2.getIndex("url").isUriIndex());
- assertEquals("url:\"https foo bar\"", query1.getModel().getQueryTree().toString());
- assertEquals("url:\"https foo bar\"", query2.getModel().getQueryTree().toString());
+ assertEquals("AND url:https url:foo url:bar", query1.getModel().getQueryTree().toString());
+ assertEquals("AND url:https url:foo url:bar", query2.getModel().getQueryTree().toString());
}
@Test
diff --git a/container-search/src/test/java/com/yahoo/prelude/test/QueryTestCase.java b/container-search/src/test/java/com/yahoo/prelude/test/QueryTestCase.java
index 4b2ced1b771..a04834b261c 100644
--- a/container-search/src/test/java/com/yahoo/prelude/test/QueryTestCase.java
+++ b/container-search/src/test/java/com/yahoo/prelude/test/QueryTestCase.java
@@ -8,25 +8,21 @@ import com.yahoo.prelude.Index;
import com.yahoo.prelude.IndexFacts;
import com.yahoo.prelude.IndexModel;
import com.yahoo.prelude.SearchDefinition;
-import com.yahoo.prelude.query.QueryException;
import com.yahoo.prelude.query.WordItem;
import com.yahoo.search.Query;
import com.yahoo.search.query.Sorting;
import com.yahoo.search.searchchain.Execution;
import com.yahoo.yolean.Exceptions;
import org.hamcrest.Matcher;
-import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
-import java.util.Collections;
import java.util.List;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.anyOf;
import static org.junit.Assert.*;
-import static org.junit.Assume.assumeTrue;
/**
* Tests for query class
@@ -376,7 +372,7 @@ public class QueryTestCase {
try {
newQuery(queryString);
fail("Above statement should throw");
- } catch (QueryException e) {
+ } catch (IllegalArgumentException e) {
// As expected.
assertThat(Exceptions.toMessageString(e), expectedErrorMessage);
}
diff --git a/container-search/src/test/java/com/yahoo/search/StupidSingleThreadedHttpServer.java b/container-search/src/test/java/com/yahoo/search/StupidSingleThreadedHttpServer.java
deleted file mode 100644
index 6e67386bfde..00000000000
--- a/container-search/src/test/java/com/yahoo/search/StupidSingleThreadedHttpServer.java
+++ /dev/null
@@ -1,166 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.search;
-
-import com.yahoo.text.Utf8;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.net.ServerSocket;
-import java.net.Socket;
-import java.net.SocketException;
-import java.util.Locale;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * As the name implies, a stupid, single-threaded bad-excuse-for-HTTP server.
- *
- * @author <a href="mailto:einarmr@yahoo-inc.com">Einar M R Rosenvinge</a>
- */
-public class StupidSingleThreadedHttpServer implements Runnable {
-
- private static final Logger log = Logger.getLogger(StupidSingleThreadedHttpServer.class.getName());
-
- private final ServerSocket serverSocket;
- private final int delaySeconds;
- private Thread serverThread = null;
- private CompletableFuture<String> requestFuture = new CompletableFuture<>();
- private final Pattern contentLengthPattern = Pattern.compile("content-length: (\\d+)",
- Pattern.CASE_INSENSITIVE | Pattern.DOTALL | Pattern.MULTILINE);
-
- public StupidSingleThreadedHttpServer() throws IOException {
- this(0, 0);
- }
-
- public StupidSingleThreadedHttpServer(int port, int delaySeconds) throws IOException {
- this.delaySeconds = delaySeconds;
- this.serverSocket = new ServerSocket(port);
- }
-
- public void start() {
- serverThread = new Thread(this);
- serverThread.setDaemon(true);
- serverThread.start();
- }
-
- public void run() {
- try {
- while(true) {
- Socket socket = serverSocket.accept();
- StringBuilder request = new StringBuilder();
- socket.setSoLinger(true, 60);
- BufferedReader in = new BufferedReader(
- new InputStreamReader(
- socket.getInputStream()));
-
- int contentLength = -1;
- String inputLine;
- while (!"".equals(inputLine = in.readLine())) { //read header:
- request.append(inputLine).append("\r\n");
- if (inputLine.toLowerCase(Locale.US).contains("content-length")) {
- Matcher contentLengthMatcher = contentLengthPattern.matcher(inputLine);
- if (contentLengthMatcher.matches()) {
- contentLength = Integer.parseInt(contentLengthMatcher.group(1));
- }
- }
- }
- request.append("\r\n");
-
- if (contentLength < 0) {
- System.err.println("WARNING! Got no Content-Length header!!");
- } else {
- char[] requestBody = new char[contentLength];
- int readRemaining = contentLength;
-
- do {
- int read = in.read(requestBody, (contentLength - readRemaining), readRemaining);
- if (read < 0) {
- throw new IllegalStateException("Should not get EOF here!!");
- }
- readRemaining -= read;
- } while (readRemaining > 0);
-
- request.append(new String(requestBody));
- }
-
- // Simulate service slowness
- if (delaySeconds > 0) {
- try {
- System.out.println(this.getClass().getCanonicalName() + " sleeping in " + delaySeconds + " s before responding...");
- Thread.sleep((long) (delaySeconds * 1000));
- System.out.println("done sleeping, responding");
- } catch (InterruptedException e) {
- //ignore
- }
- }
-
- socket.getOutputStream().write(getResponse(request.toString()));
- socket.getOutputStream().flush();
- in.close();
- socket.close();
-
- boolean wasCompleted = requestFuture.complete(request.toString());
- if (!wasCompleted) {
- log.log(Level.INFO, "Only the first request will be stored, ignoring. "
- + "Old value: " + requestFuture.get()
- + ", New value: " + request.toString());
- }
- }
- } catch (SocketException se) {
- if ("Socket closed".equals(se.getMessage())) {
- //ignore
- } else {
- throw new RuntimeException(se);
- }
- } catch (IOException|InterruptedException|ExecutionException e) {
- throw new RuntimeException(e);
- }
- }
-
- protected byte[] getResponse(String request) {
- return Utf8.toBytes("HTTP/1.1 200 OK\r\n" +
- "Content-Type: text/xml; charset=UTF-8\r\n" +
- "Connection: close\r\n" +
- "Content-Length: 0\r\n" +
- "\r\n");
- }
-
- protected byte[] getResponseBody() {
- return new byte[0];
- }
-
- public void stop() {
- if (!serverSocket.isClosed()) {
- try {
- serverSocket.close();
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
- try {
- serverThread.interrupt();
- } catch (Exception e) {
- //ignore
- }
- }
-
- public int getServerPort() {
- return serverSocket.getLocalPort();
- }
-
- public String getRequest() {
- try {
- return requestFuture.get(1, TimeUnit.MINUTES);
- } catch (InterruptedException | ExecutionException | TimeoutException e) {
- throw new AssertionError("Failed waiting for request. ", e);
- }
- }
-
-}
diff --git a/container-search/src/test/java/com/yahoo/search/dispatch/DispatcherTest.java b/container-search/src/test/java/com/yahoo/search/dispatch/DispatcherTest.java
index 5433a28dd6e..be761acf2c2 100644
--- a/container-search/src/test/java/com/yahoo/search/dispatch/DispatcherTest.java
+++ b/container-search/src/test/java/com/yahoo/search/dispatch/DispatcherTest.java
@@ -6,6 +6,7 @@ import com.yahoo.prelude.fastsearch.test.MockMetric;
import com.yahoo.search.Query;
import com.yahoo.search.Result;
import com.yahoo.search.cluster.ClusterMonitor;
+import com.yahoo.search.dispatch.searchcluster.Group;
import com.yahoo.search.dispatch.searchcluster.Node;
import com.yahoo.search.dispatch.searchcluster.PingFactory;
import com.yahoo.search.dispatch.searchcluster.Pinger;
@@ -35,7 +36,7 @@ public class DispatcherTest {
q.getModel().setSearchPath("1/0"); // second node in first group
MockInvokerFactory invokerFactory = new MockInvokerFactory(cl, (nodes, a) -> {
assertEquals(1, nodes.size());
- assertEquals(2, nodes.get(0).key());
+ assertEquals(1, nodes.get(0).key());
return true;
});
Dispatcher disp = new Dispatcher(new ClusterMonitor(cl, false), cl, createDispatchConfig(), invokerFactory, new MockMetric());
@@ -92,6 +93,53 @@ public class DispatcherTest {
}
}
+ @Test
+ public void testGroup0IsSelected() {
+ SearchCluster cluster = new MockSearchCluster("1", 3, 1);
+ Dispatcher dispatcher = new Dispatcher(new ClusterMonitor(cluster, false), cluster, createDispatchConfig(), new MockInvokerFactory(cluster, (n, a) -> true), new MockMetric());
+ cluster.pingIterationCompleted();
+ assertEquals(0,
+ dispatcher.getSearchInvoker(new Query(), null).distributionKey().get().longValue());
+ dispatcher.deconstruct();
+ }
+
+ @Test
+ public void testGroup0IsSkippedWhenItIsBlockingFeed() {
+ SearchCluster cluster = new MockSearchCluster("1", 3, 1);
+ Dispatcher dispatcher = new Dispatcher(new ClusterMonitor(cluster, false), cluster, createDispatchConfig(), new MockInvokerFactory(cluster, (n, a) -> true), new MockMetric());
+ cluster.group(0).get().nodes().get(0).setBlockingWrites(true);
+ cluster.pingIterationCompleted();
+ assertEquals("Blocking group is avoided",
+ 1,
+ (dispatcher.getSearchInvoker(new Query(), null).distributionKey().get()).longValue());
+ dispatcher.deconstruct();
+ }
+
+ @Test
+ public void testGroup0IsSelectedWhenMoreAreBlockingFeed() {
+ SearchCluster cluster = new MockSearchCluster("1", 3, 1);
+ Dispatcher dispatcher = new Dispatcher(new ClusterMonitor(cluster, false), cluster, createDispatchConfig(), new MockInvokerFactory(cluster, (n, a) -> true), new MockMetric());
+ cluster.group(0).get().nodes().get(0).setBlockingWrites(true);
+ cluster.group(1).get().nodes().get(0).setBlockingWrites(true);
+ cluster.pingIterationCompleted();
+ assertEquals("Blocking group is used when multiple groups are blocking",
+ 0,
+ dispatcher.getSearchInvoker(new Query(), null).distributionKey().get().longValue());
+ dispatcher.deconstruct();
+ }
+
+ @Test
+ public void testGroup0IsSelectedWhenItIsBlockingFeedWhenNoOthers() {
+ SearchCluster cluster = new MockSearchCluster("1", 1, 1);
+ Dispatcher dispatcher = new Dispatcher(new ClusterMonitor(cluster, false), cluster, createDispatchConfig(), new MockInvokerFactory(cluster, (n, a) -> true), new MockMetric());
+ cluster.group(0).get().nodes().get(0).setBlockingWrites(true);
+ cluster.pingIterationCompleted();
+ assertEquals("Blocking group is used when there is no alternative",
+ 0,
+ (dispatcher.getSearchInvoker(new Query(), null).distributionKey().get()).longValue());
+ dispatcher.deconstruct();
+ }
+
interface FactoryStep {
boolean returnInvoker(List<Node> nodes, boolean acceptIncompleteCoverage);
}
@@ -109,7 +157,6 @@ public class DispatcherTest {
@Override
public Optional<SearchInvoker> createSearchInvoker(VespaBackEndSearcher searcher,
Query query,
- OptionalInt groupId,
List<Node> nodes,
boolean acceptIncompleteCoverage,
int maxHitsPerNode) {
@@ -119,7 +166,7 @@ public class DispatcherTest {
boolean nonEmpty = events[step].returnInvoker(nodes, acceptIncompleteCoverage);
step++;
if (nonEmpty) {
- return Optional.of(new MockInvoker(1));
+ return Optional.of(new MockInvoker(nodes.get(0).key()));
} else {
return Optional.empty();
}
@@ -150,4 +197,5 @@ public class DispatcherTest {
return null;
}
}
+
}
diff --git a/container-search/src/test/java/com/yahoo/search/dispatch/InterleavedSearchInvokerTest.java b/container-search/src/test/java/com/yahoo/search/dispatch/InterleavedSearchInvokerTest.java
index 27685426cf8..21a15165ab3 100644
--- a/container-search/src/test/java/com/yahoo/search/dispatch/InterleavedSearchInvokerTest.java
+++ b/container-search/src/test/java/com/yahoo/search/dispatch/InterleavedSearchInvokerTest.java
@@ -7,6 +7,8 @@ import com.yahoo.prelude.fastsearch.FastHit;
import com.yahoo.prelude.fastsearch.GroupingListHit;
import com.yahoo.search.Query;
import com.yahoo.search.Result;
+import com.yahoo.search.dispatch.searchcluster.Group;
+import com.yahoo.search.dispatch.searchcluster.Node;
import com.yahoo.search.dispatch.searchcluster.SearchCluster;
import com.yahoo.search.result.Coverage;
import com.yahoo.search.result.DefaultErrorHit;
@@ -44,15 +46,16 @@ import static org.junit.Assert.fail;
* @author ollivir
*/
public class InterleavedSearchInvokerTest {
- private ManualClock clock = new ManualClock(Instant.now());
- private Query query = new TestQuery();
- private LinkedList<Event> expectedEvents = new LinkedList<>();
- private List<SearchInvoker> invokers = new ArrayList<>();
+
+ private final ManualClock clock = new ManualClock(Instant.now());
+ private final Query query = new TestQuery();
+ private final LinkedList<Event> expectedEvents = new LinkedList<>();
+ private final List<SearchInvoker> invokers = new ArrayList<>();
@Test
public void requireThatAdaptiveTimeoutsAreNotUsedWithFullCoverageRequirement() throws IOException {
SearchCluster cluster = new MockSearchCluster("!", createDispatchConfig(100.0), 1, 3);
- SearchInvoker invoker = createInterleavedInvoker(cluster, 3);
+ SearchInvoker invoker = createInterleavedInvoker(cluster, new Group(0, List.of()), 3);
expectedEvents.add(new Event(5000, 100, 0));
expectedEvents.add(new Event(4900, 100, 1));
@@ -66,7 +69,7 @@ public class InterleavedSearchInvokerTest {
@Test
public void requireThatTimeoutsAreNotMarkedAsAdaptive() throws IOException {
SearchCluster cluster = new MockSearchCluster("!", createDispatchConfig(100.0), 1, 3);
- SearchInvoker invoker = createInterleavedInvoker(cluster, 3);
+ SearchInvoker invoker = createInterleavedInvoker(cluster, new Group(0, List.of()), 3);
expectedEvents.add(new Event(5000, 300, 0));
expectedEvents.add(new Event(4700, 300, 1));
@@ -84,7 +87,7 @@ public class InterleavedSearchInvokerTest {
@Test
public void requireThatAdaptiveTimeoutDecreasesTimeoutWhenCoverageIsReached() throws IOException {
SearchCluster cluster = new MockSearchCluster("!", createDispatchConfig(50.0), 1, 4);
- SearchInvoker invoker = createInterleavedInvoker(cluster, 4);
+ SearchInvoker invoker = createInterleavedInvoker(cluster, new Group(0, List.of()), 4);
expectedEvents.add(new Event(5000, 100, 0));
expectedEvents.add(new Event(4900, 100, 1));
@@ -105,7 +108,7 @@ public class InterleavedSearchInvokerTest {
SearchCluster cluster = new MockSearchCluster("!", 1, 2);
invokers.add(new MockInvoker(0, createCoverage(50155, 50155, 50155, 1, 1, 0)));
invokers.add(new MockInvoker(1, createCoverage(49845, 49845, 49845, 1, 1, 0)));
- SearchInvoker invoker = createInterleavedInvoker(cluster, 0);
+ SearchInvoker invoker = createInterleavedInvoker(cluster, new Group(0, List.of()), 0);
expectedEvents.add(new Event(null, 100, 0));
expectedEvents.add(new Event(null, 200, 1));
@@ -126,7 +129,7 @@ public class InterleavedSearchInvokerTest {
SearchCluster cluster = new MockSearchCluster("!", 1, 2);
invokers.add(new MockInvoker(0, createCoverage(10101, 50155, 50155, 1, 1, DEGRADED_BY_MATCH_PHASE)));
invokers.add(new MockInvoker(1, createCoverage(13319, 49845, 49845, 1, 1, DEGRADED_BY_MATCH_PHASE)));
- SearchInvoker invoker = createInterleavedInvoker(cluster, 0);
+ SearchInvoker invoker = createInterleavedInvoker(cluster, new Group(0, List.of()), 0);
expectedEvents.add(new Event(null, 100, 0));
expectedEvents.add(new Event(null, 200, 1));
@@ -148,7 +151,7 @@ public class InterleavedSearchInvokerTest {
SearchCluster cluster = new MockSearchCluster("!", 1, 2);
invokers.add(new MockInvoker(0, createCoverage(5000, 50155, 50155, 1, 1, DEGRADED_BY_TIMEOUT)));
invokers.add(new MockInvoker(1, createCoverage(4900, 49845, 49845, 1, 1, DEGRADED_BY_TIMEOUT)));
- SearchInvoker invoker = createInterleavedInvoker(cluster, 0);
+ SearchInvoker invoker = createInterleavedInvoker(cluster, new Group(0, List.of()),0);
expectedEvents.add(new Event(null, 100, 0));
expectedEvents.add(new Event(null, 200, 1));
@@ -170,7 +173,7 @@ public class InterleavedSearchInvokerTest {
SearchCluster cluster = new MockSearchCluster("!", 1, 2);
invokers.add(new MockInvoker(0, createCoverage(50155, 50155, 50155, 1, 1, 0)));
invokers.add(new MockInvoker(1, createCoverage(49845, 49845, 49845, 1, 1, 0)));
- SearchInvoker invoker = createInterleavedInvoker(cluster, 0);
+ SearchInvoker invoker = createInterleavedInvoker(cluster, new Group(0, List.of()), 0);
expectedEvents.add(new Event(null, 100, 0));
expectedEvents.add(null);
@@ -204,9 +207,60 @@ public class InterleavedSearchInvokerTest {
private static final List<Double> A5Aux = Arrays.asList(-1.0,11.0,8.5,7.5,-7.0,3.0,2.0);
private static final List<Double> B5Aux = Arrays.asList(9.0,8.0,-3.0,7.0,6.0,1.0, -1.0);
+ private void validateThatTopKProbabilityOverrideTakesEffect(Double topKProbability, int expectedK, Group group) throws IOException {
+ InterleavedSearchInvoker invoker = createInterLeavedTestInvoker(A5, B5, group);
+ query.setHits(8);
+ query.properties().set(Dispatcher.topKProbability, topKProbability);
+ SearchInvoker [] invokers = invoker.invokers().toArray(new SearchInvoker[0]);
+ Result result = invoker.search(query, null);
+ assertEquals(2, invokers.length);
+ assertEquals(expectedK, ((MockInvoker)invokers[0]).hitsRequested);
+ assertEquals(8, result.hits().size());
+ assertEquals(11.0, result.hits().get(0).getRelevance().getScore(), DELTA);
+ assertEquals(9.0, result.hits().get(1).getRelevance().getScore(), DELTA);
+ assertEquals(8.5, result.hits().get(2).getRelevance().getScore(), DELTA);
+ assertEquals(8.0, result.hits().get(3).getRelevance().getScore(), DELTA);
+ assertEquals(7.5, result.hits().get(4).getRelevance().getScore(), DELTA);
+ assertEquals(7.0, result.hits().get(5).getRelevance().getScore(), DELTA);
+ assertEquals(6.0, result.hits().get(6).getRelevance().getScore(), DELTA);
+ assertEquals(3.0, result.hits().get(7).getRelevance().getScore(), DELTA);
+ assertEquals(0, result.getQuery().getOffset());
+ assertEquals(8, result.getQuery().getHits());
+ }
+
+ @Test
+ public void requireThatTopKProbabilityOverrideTakesEffect() throws IOException {
+ validateThatTopKProbabilityOverrideTakesEffect(null, 8, new Group(0, List.of()));
+ validateThatTopKProbabilityOverrideTakesEffect(0.8, 7, new Group(0, List.of()));
+ }
+
+ @Test
+ public void requireThatTopKProbabilityOverrideIsDisabledOnContentSkew() throws IOException {
+ Node node0 = new Node(0, "host0", 0);
+ Node node1 = new Node(1, "host1", 0);
+ Group group = new Group(0, List.of(node0, node1));
+
+ node0.setActiveDocuments(1000000);
+ node1.setActiveDocuments(1100000);
+ group.aggregateNodeValues();
+ validateThatTopKProbabilityOverrideTakesEffect(0.8, 8, group);
+ }
+
+ @Test
+ public void requireThatTopKProbabilityOverrideIsDisabledOnLittleContent() throws IOException {
+ Node node0 = new Node(0, "host0", 0);
+ Node node1 = new Node(1, "host1", 0);
+ Group group = new Group(0, List.of(node0, node1));
+
+ node0.setActiveDocuments(10);
+ node1.setActiveDocuments(10);
+ group.aggregateNodeValues();
+ validateThatTopKProbabilityOverrideTakesEffect(0.8, 8, group);
+ }
+
@Test
public void requireThatMergeOfConcreteHitsObeySorting() throws IOException {
- InterleavedSearchInvoker invoker = createInterLeavedTestInvoker(A5, B5);
+ InterleavedSearchInvoker invoker = createInterLeavedTestInvoker(A5, B5, new Group(0, List.of()));
query.setHits(12);
Result result = invoker.search(query, null);
assertEquals(10, result.hits().size());
@@ -215,7 +269,7 @@ public class InterleavedSearchInvokerTest {
assertEquals(0, result.getQuery().getOffset());
assertEquals(12, result.getQuery().getHits());
- invoker = createInterLeavedTestInvoker(B5, A5);
+ invoker = createInterLeavedTestInvoker(B5, A5, new Group(0, List.of()));
result = invoker.search(query, null);
assertEquals(10, result.hits().size());
assertEquals(11.0, result.hits().get(0).getRelevance().getScore(), DELTA);
@@ -226,7 +280,7 @@ public class InterleavedSearchInvokerTest {
@Test
public void requireThatMergeOfConcreteHitsObeyOffset() throws IOException {
- InterleavedSearchInvoker invoker = createInterLeavedTestInvoker(A5, B5);
+ InterleavedSearchInvoker invoker = createInterLeavedTestInvoker(A5, B5, new Group(0, List.of()));
query.setHits(3);
query.setOffset(5);
Result result = invoker.search(query, null);
@@ -236,7 +290,7 @@ public class InterleavedSearchInvokerTest {
assertEquals(0, result.getQuery().getOffset());
assertEquals(3, result.getQuery().getHits());
- invoker = createInterLeavedTestInvoker(B5, A5);
+ invoker = createInterLeavedTestInvoker(B5, A5, new Group(0, List.of()));
query.setOffset(5);
result = invoker.search(query, null);
assertEquals(3, result.hits().size());
@@ -248,7 +302,7 @@ public class InterleavedSearchInvokerTest {
@Test
public void requireThatMergeOfConcreteHitsObeyOffsetWithAuxilliaryStuff() throws IOException {
- InterleavedSearchInvoker invoker = createInterLeavedTestInvoker(A5Aux, B5Aux);
+ InterleavedSearchInvoker invoker = createInterLeavedTestInvoker(A5Aux, B5Aux, new Group(0, List.of()));
query.setHits(3);
query.setOffset(5);
Result result = invoker.search(query, null);
@@ -259,7 +313,7 @@ public class InterleavedSearchInvokerTest {
assertEquals(0, result.getQuery().getOffset());
assertEquals(3, result.getQuery().getHits());
- invoker = createInterLeavedTestInvoker(B5Aux, A5Aux);
+ invoker = createInterLeavedTestInvoker(B5Aux, A5Aux, new Group(0, List.of()));
query.setOffset(5);
result = invoker.search(query, null);
assertEquals(7, result.hits().size());
@@ -270,12 +324,12 @@ public class InterleavedSearchInvokerTest {
assertEquals(3, result.getQuery().getHits());
}
- private static InterleavedSearchInvoker createInterLeavedTestInvoker(List<Double> a, List<Double> b) {
+ private static InterleavedSearchInvoker createInterLeavedTestInvoker(List<Double> a, List<Double> b, Group group) {
SearchCluster cluster = new MockSearchCluster("!", 1, 2);
List<SearchInvoker> invokers = new ArrayList<>();
invokers.add(createInvoker(a, 0));
invokers.add(createInvoker(b, 1));
- InterleavedSearchInvoker invoker = new InterleavedSearchInvoker(invokers, cluster, Collections.emptySet());
+ InterleavedSearchInvoker invoker = new InterleavedSearchInvoker(invokers, cluster, group, Collections.emptySet());
invoker.responseAvailable(invokers.get(0));
invoker.responseAvailable(invokers.get(1));
return invoker;
@@ -303,7 +357,7 @@ public class InterleavedSearchInvokerTest {
Coverage errorCoverage = new Coverage(0, 0, 0);
errorCoverage.setNodesTried(1);
invokers.add(new SearchErrorInvoker(ErrorMessage.createBackendCommunicationError("node is down"), errorCoverage));
- SearchInvoker invoker = createInterleavedInvoker(cluster, 0);
+ SearchInvoker invoker = createInterleavedInvoker(cluster, new Group(0, List.of()), 0);
expectedEvents.add(new Event(null, 1, 1));
expectedEvents.add(new Event(null, 100, 0));
@@ -321,12 +375,13 @@ public class InterleavedSearchInvokerTest {
assertThat(cov.isDegradedByTimeout(), is(true));
}
- private InterleavedSearchInvoker createInterleavedInvoker(SearchCluster searchCluster, int numInvokers) {
+ private InterleavedSearchInvoker createInterleavedInvoker(SearchCluster searchCluster, Group group, int numInvokers) {
for (int i = 0; i < numInvokers; i++) {
invokers.add(new MockInvoker(i));
}
- return new InterleavedSearchInvoker(invokers, searchCluster, null) {
+ return new InterleavedSearchInvoker(invokers, searchCluster, group,null) {
+
@Override
protected long currentTime() {
return clock.millis();
diff --git a/container-search/src/test/java/com/yahoo/search/dispatch/LeanHitTest.java b/container-search/src/test/java/com/yahoo/search/dispatch/LeanHitTest.java
index 085a9b24993..8d81c5d8521 100644
--- a/container-search/src/test/java/com/yahoo/search/dispatch/LeanHitTest.java
+++ b/container-search/src/test/java/com/yahoo/search/dispatch/LeanHitTest.java
@@ -37,10 +37,14 @@ public class LeanHitTest {
}
@Test
public void testOrderingBySortData() {
- assertEquals(0, new LeanHit(gidA, 0, 0, gidA).compareTo(new LeanHit(gidA, 0, 0, gidA)));
- verifyTransitiveOrdering(new LeanHit(gidA, 0, 0, gidA),
- new LeanHit(gidA, 0, 0, gidB),
- new LeanHit(gidA, 0, 0, gidC));
+ assertEquals(0, new LeanHit(gidA, 0, 0, 0.0, gidA).compareTo(new LeanHit(gidA, 0, 0, 0.0, gidA)));
+ verifyTransitiveOrdering(new LeanHit(gidA, 0, 0, 0.0, gidA),
+ new LeanHit(gidA, 0, 0, 0.0, gidB),
+ new LeanHit(gidA, 0, 0, 0.0, gidC));
+ }
+ @Test
+ public void testRelevanceIsKeptEvenWithBySortData() {
+ assertEquals(1.3, new LeanHit(gidA, 0, 0, 1.3, gidA).getRelevance(), 0.0);
}
@Test
public void testNaN2negativeInfinity() {
diff --git a/container-search/src/test/java/com/yahoo/search/dispatch/LoadBalancerTest.java b/container-search/src/test/java/com/yahoo/search/dispatch/LoadBalancerTest.java
index 36b476e2936..d0ba396ef94 100644
--- a/container-search/src/test/java/com/yahoo/search/dispatch/LoadBalancerTest.java
+++ b/container-search/src/test/java/com/yahoo/search/dispatch/LoadBalancerTest.java
@@ -26,6 +26,7 @@ import static org.junit.Assert.assertThat;
* @author ollivir
*/
public class LoadBalancerTest {
+
@Test
public void requireThatLoadBalancerServesSingleNodeSetups() {
Node n1 = new Node(0, "test-node1", 0);
diff --git a/container-search/src/test/java/com/yahoo/search/dispatch/MockInvoker.java b/container-search/src/test/java/com/yahoo/search/dispatch/MockInvoker.java
index c5fbda7c2f5..d86fcdfc25d 100644
--- a/container-search/src/test/java/com/yahoo/search/dispatch/MockInvoker.java
+++ b/container-search/src/test/java/com/yahoo/search/dispatch/MockInvoker.java
@@ -4,6 +4,7 @@ package com.yahoo.search.dispatch;
import com.yahoo.prelude.fastsearch.FastHit;
import com.yahoo.search.Query;
import com.yahoo.search.Result;
+import com.yahoo.search.dispatch.searchcluster.Group;
import com.yahoo.search.dispatch.searchcluster.Node;
import com.yahoo.search.result.Coverage;
import com.yahoo.search.result.Hit;
@@ -12,11 +13,14 @@ import com.yahoo.search.searchchain.Execution;
import java.io.IOException;
import java.util.List;
import java.util.Optional;
+import java.util.OptionalInt;
class MockInvoker extends SearchInvoker {
+
private final Coverage coverage;
private Query query;
private List<Hit> hits;
+ int hitsRequested;
protected MockInvoker(int key, Coverage coverage) {
super(Optional.of(new Node(key, "?", 0)));
@@ -33,12 +37,14 @@ class MockInvoker extends SearchInvoker {
}
@Override
- protected void sendSearchRequest(Query query) throws IOException {
+ protected Object sendSearchRequest(Query query, Object context) {
this.query = query;
+ hitsRequested = query.getHits();
+ return context;
}
@Override
- protected InvokerResult getSearchResult(Execution execution) throws IOException {
+ protected InvokerResult getSearchResult(Execution execution) {
InvokerResult ret = new InvokerResult(query, 10);
if (coverage != null) {
ret.getResult().setCoverage(coverage);
@@ -59,4 +65,10 @@ class MockInvoker extends SearchInvoker {
@Override
protected void release() {
}
+
+ @Override
+ public String toString() {
+ return "invoker with key " + distributionKey();
+ }
+
} \ No newline at end of file
diff --git a/container-search/src/test/java/com/yahoo/search/dispatch/MockSearchCluster.java b/container-search/src/test/java/com/yahoo/search/dispatch/MockSearchCluster.java
index 32c6738fc3b..8db54218e56 100644
--- a/container-search/src/test/java/com/yahoo/search/dispatch/MockSearchCluster.java
+++ b/container-search/src/test/java/com/yahoo/search/dispatch/MockSearchCluster.java
@@ -35,15 +35,14 @@ public class MockSearchCluster extends SearchCluster {
ImmutableList.Builder<Group> orderedGroupBuilder = ImmutableList.builder();
ImmutableMap.Builder<Integer, Group> groupBuilder = ImmutableMap.builder();
ImmutableMultimap.Builder<String, Node> hostBuilder = ImmutableMultimap.builder();
- int dk = 1;
+ int distributionKey = 0;
for (int group = 0; group < groups; group++) {
List<Node> nodes = new ArrayList<>();
for (int node = 0; node < nodesPerGroup; node++) {
- Node n = new Node(dk, "host" + dk, group);
- n.setWorking(true);
+ Node n = new Node(distributionKey, "host" + distributionKey, group);
nodes.add(n);
hostBuilder.put(n.hostname(), n);
- dk++;
+ distributionKey++;
}
Group g = new Group(group, nodes);
groupBuilder.put(group, g);
@@ -72,7 +71,7 @@ public class MockSearchCluster extends SearchCluster {
}
@Override
- public int groupSize() {
+ public int wantedGroupSize() {
return numNodesPerGroup;
}
@@ -115,12 +114,13 @@ public class MockSearchCluster extends SearchCluster {
public static DispatchConfig createDispatchConfig(double minSearchCoverage, Node... nodes) {
return createDispatchConfig(minSearchCoverage, Arrays.asList(nodes));
}
+
public static DispatchConfig createDispatchConfig(double minSearchCoverage, List<Node> nodes) {
DispatchConfig.Builder builder = new DispatchConfig.Builder();
builder.minActivedocsPercentage(88.0);
builder.minGroupCoverage(99.0);
- builder.maxNodesDownPerGroup(0);
builder.minSearchCoverage(minSearchCoverage);
+ builder.distributionPolicy(DispatchConfig.DistributionPolicy.Enum.ROUNDROBIN);
if (minSearchCoverage < 100.0) {
builder.minWaitAfterCoverageFactor(0);
builder.maxWaitAfterCoverageFactor(0.5);
diff --git a/container-search/src/test/java/com/yahoo/search/dispatch/SearchPathTest.java b/container-search/src/test/java/com/yahoo/search/dispatch/SearchPathTest.java
index 5a4457780e2..7633bbda913 100644
--- a/container-search/src/test/java/com/yahoo/search/dispatch/SearchPathTest.java
+++ b/container-search/src/test/java/com/yahoo/search/dispatch/SearchPathTest.java
@@ -8,33 +8,39 @@ import org.junit.Test;
import org.junit.rules.ExpectedException;
import java.util.Collection;
+import java.util.Set;
import java.util.stream.Collectors;
-import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
/**
* @author ollivir
*/
public class SearchPathTest {
+
@Test
public void requreThatSearchPathsAreParsedCorrectly() {
- assertThat(SearchPath.fromString("0/0").get().toString(), equalTo("0/0"));
- assertThat(SearchPath.fromString("1/0").get().toString(), equalTo("1/0"));
- assertThat(SearchPath.fromString("0/1").get().toString(), equalTo("0/1"));
+ assertEquals(SearchPath.fromString("0/0").get().toString(), "0/0");
+ assertEquals(SearchPath.fromString("1/0").get().toString(), "1/0");
+ assertEquals(SearchPath.fromString("0/1").get().toString(), "0/1");
- assertThat(SearchPath.fromString("0,1/2").get().toString(), equalTo("0,1/2"));
- assertThat(SearchPath.fromString("[0,1>/2").get().toString(), equalTo("0/2"));
- assertThat(SearchPath.fromString("[0,2>/2").get().toString(), equalTo("[0,2>/2"));
- assertThat(SearchPath.fromString("[0,1>,1/2").get().toString(), equalTo("0,1/2"));
+ assertEquals(SearchPath.fromString("0,1/2").get().toString(), "0,1/2");
+ assertEquals(SearchPath.fromString("0,1/1,2").get().toString(), "0,1/1,2");
+ assertEquals(SearchPath.fromString("[0,1>/2").get().toString(), "0/2");
+ assertEquals(SearchPath.fromString("[0,1>/[2,3>").get().toString(), "0/2");
+ assertEquals(SearchPath.fromString("[0,2>/2").get().toString(), "[0,2>/2");
+ assertEquals(SearchPath.fromString("[0,2>/[0,2>").get().toString(), "[0,2>/[0,2>");
+ assertEquals(SearchPath.fromString("[0,1>,1/2").get().toString(), "0,1/2");
+ assertEquals(SearchPath.fromString("[0,1>,1/[0,1>,1").get().toString(), "0,1/0,1");
- assertThat(SearchPath.fromString("*/2").get().toString(), equalTo("/2"));
- assertThat(SearchPath.fromString("1,*/2").get().toString(), equalTo("/2"));
+ assertEquals(SearchPath.fromString("*/2").get().toString(), "/2");
+ assertEquals(SearchPath.fromString("1,*/2").get().toString(), "/2");
- assertThat(SearchPath.fromString("1").get().toString(), equalTo("1"));
- assertThat(SearchPath.fromString("1/").get().toString(), equalTo("1"));
- assertThat(SearchPath.fromString("1/*").get().toString(), equalTo("1"));
+ assertEquals(SearchPath.fromString("1").get().toString(), "1");
+ assertEquals(SearchPath.fromString("1/").get().toString(), "1");
+ assertEquals(SearchPath.fromString("1/*").get().toString(), "1");
}
@Test
@@ -67,15 +73,27 @@ public class SearchPathTest {
SearchPath.fromString("1,2,3/r");
}
+ private void verifyRandomGroup(MockSearchCluster cluster, String searchPath, Set possibleSolutions) {
+ for (int i=0; i < 100; i++) {
+ String nodes = distKeysAsString(SearchPath.selectNodes(searchPath, cluster));
+ assertTrue(possibleSolutions.contains(nodes));
+ }
+ }
+
@Test
public void searchPathMustFilterNodesBasedOnDefinition() {
MockSearchCluster cluster = new MockSearchCluster("a",3, 3);
- assertThat(distKeysAsString(SearchPath.selectNodes("1/1", cluster)), equalTo("5"));
- assertThat(distKeysAsString(SearchPath.selectNodes("/1", cluster)), equalTo("4,5,6"));
- assertThat(distKeysAsString(SearchPath.selectNodes("0,1/2", cluster)), equalTo("7,8"));
- assertThat(distKeysAsString(SearchPath.selectNodes("[1,3>/1", cluster)), equalTo("5,6"));
- assertThat(distKeysAsString(SearchPath.selectNodes("[1,88>/1", cluster)), equalTo("5,6"));
+ assertEquals(distKeysAsString(SearchPath.selectNodes("1/1", cluster)), "4");
+ assertEquals(distKeysAsString(SearchPath.selectNodes("/1", cluster)), "3,4,5");
+ assertEquals(distKeysAsString(SearchPath.selectNodes("0,1/2", cluster)), "6,7");
+ assertEquals(distKeysAsString(SearchPath.selectNodes("[1,3>/1", cluster)), "4,5");
+ assertEquals(distKeysAsString(SearchPath.selectNodes("[1,88>/1", cluster)), "4,5");
+
+ verifyRandomGroup(cluster, "[1,88>/", Set.of("1,2", "4,5", "7,8"));
+ verifyRandomGroup(cluster, "[1,88>/0", Set.of("1,2"));
+ verifyRandomGroup(cluster, "[1,88>/2", Set.of("7,8"));
+ verifyRandomGroup(cluster, "[1,88>/0,2", Set.of("1,2", "7,8"));
}
private static String distKeysAsString(Collection<Node> nodes) {
diff --git a/container-search/src/test/java/com/yahoo/search/dispatch/TopKEstimatorTest.java b/container-search/src/test/java/com/yahoo/search/dispatch/TopKEstimatorTest.java
new file mode 100644
index 00000000000..795c7cfef20
--- /dev/null
+++ b/container-search/src/test/java/com/yahoo/search/dispatch/TopKEstimatorTest.java
@@ -0,0 +1,168 @@
+// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.search.dispatch;
+
+import org.junit.Test;
+
+import java.util.Locale;
+
+import static org.junit.Assert.assertEquals;
+
+public class TopKEstimatorTest {
+ @Test
+ public void requireHitsAreEstimatedAccordingToPartitionsAndProbability() {
+ TopKEstimator estimator = new TopKEstimator(30, 0.999);
+ assertEquals(91.97368471911312, estimator.estimateExactK(200, 3), 0.0);
+ assertEquals(92, estimator.estimateK(200, 3));
+ assertEquals(37.96328109101396, estimator.estimateExactK(200, 10), 0.0);
+ assertEquals(38, estimator.estimateK(200, 10));
+ assertEquals(23.815737601023095, estimator.estimateExactK(200, 20), 0.0);
+ assertEquals(24, estimator.estimateK(200, 20));
+
+ assertEquals(37.96328109101396, estimator.estimateExactK(200, 10, 0.999), 0.0);
+ assertEquals(38, estimator.estimateK(200, 10, 0.999));
+ assertEquals(34.36212304875885, estimator.estimateExactK(200, 10, 0.99), 0.0);
+ assertEquals(35, estimator.estimateK(200, 10, 0.99));
+ assertEquals(41.44244358524574, estimator.estimateExactK(200, 10, 0.9999), 0.0);
+ assertEquals(42, estimator.estimateK(200, 10, 0.9999));
+ assertEquals(44.909040374464155, estimator.estimateExactK(200, 10, 0.99999), 0.0);
+ assertEquals(45, estimator.estimateK(200, 10, 0.99999));
+ }
+ @Test
+ public void requireHitsAreEstimatedAccordingToPartitionsAndProbabilityForVaryingN_K200() {
+ TopKEstimator estimator = new TopKEstimator(30, 0.99999);
+ assertEquals(200, estimator.estimateExactK(200, 1), 0.0);
+ assertEquals(200, estimator.estimateK(200, 1));
+ assertEquals(137.4727798056239, estimator.estimateExactK(200, 2), 0.0);
+ assertEquals(102.95409291533568, estimator.estimateExactK(200, 3), 0.0);
+ assertEquals(44.909040374464155, estimator.estimateExactK(200, 10), 0.0);
+ assertEquals(28.86025772029091, estimator.estimateExactK(200, 20), 0.0);
+ }
+
+ @Test
+ public void requireHitsAreEstimatedAccordingToPartitionsAndProbabilityForVaryingN_K20() {
+ TopKEstimator estimator = new TopKEstimator(30, 0.99999);
+ assertEquals(20, estimator.estimateExactK(20, 1), 0.0);
+ assertEquals(20, estimator.estimateK(20, 1));
+ assertEquals(21.849933444373328, estimator.estimateExactK(20, 2), 0.0);
+ assertEquals(18.14175840378403, estimator.estimateExactK(20, 3), 0.0);
+ assertEquals(9.87693019124002, estimator.estimateExactK(20, 10), 0.0);
+ assertEquals(6.964137165389415, estimator.estimateExactK(20, 20), 0.0);
+ }
+
+ @Test
+ public void requireHitsAreEstimatedAccordingToPartitionsAndProbabilityForVaryingN_K10_Five9() {
+ TopKEstimator estimator = new TopKEstimator(30, 0.99999);
+ assertEquals(10, estimator.estimateExactK(10, 1), 0.0);
+ assertEquals(10, estimator.estimateK(10, 1));
+ assertEquals(13.379168295125641, estimator.estimateExactK(10, 2), 0.0);
+ assertEquals(11.447448515386741, estimator.estimateExactK(10, 3), 0.0);
+ assertEquals(6.569830753158866, estimator.estimateExactK(10, 10), 0.0);
+ assertEquals(4.717281833573569, estimator.estimateExactK(10, 20), 0.0);
+ }
+
+ @Test
+ public void requireHitsAreEstimatedAccordingToPartitionsAndProbabilityForVaryingN_K10_Four9() {
+ TopKEstimator estimator = new TopKEstimator(30, 0.9999);
+ assertEquals(10, estimator.estimateExactK(10, 1), 0.0);
+ assertEquals(10, estimator.estimateK(10, 1));
+ assertEquals(12.087323848369289, estimator.estimateExactK(10, 2), 0.0);
+ assertEquals(10.230749855131009, estimator.estimateExactK(10, 3), 0.0);
+ assertEquals(5.794676146031378, estimator.estimateExactK(10, 10), 0.0);
+ assertEquals(4.152394782937266, estimator.estimateExactK(10, 20), 0.0);
+ }
+
+ @Test
+ public void requireEstimatesAreRoundeUp() {
+ TopKEstimator estimator = new TopKEstimator(30, 0.9999);
+ assertEquals(5.794676146031378, estimator.estimateExactK(10, 10), 0.0);
+ assertEquals(6, estimator.estimateK(10, 10));
+ }
+
+ @Test
+ public void requireEstimatesAreCappedAtInputK() {
+ TopKEstimator estimator = new TopKEstimator(30, 0.9999);
+ assertEquals(12.087323848369289, estimator.estimateExactK(10, 2), 0.0);
+ assertEquals(10, estimator.estimateK(10, 2));
+ }
+
+ @Test
+ public void requireThatLargeKAreSane() {
+ System.out.println(dumpProbability(10, 0.05));
+ TopKEstimator idealEstimator = new TopKEstimator(30, 0.9999);
+ TopKEstimator skewedEstimator = new TopKEstimator(30, 0.9999, 0.05);
+ int [] K = {10, 20, 40, 80, 100, 200, 400, 800, 1000, 2000, 4000, 8000, 10000, 20000, 40000, 80000, 100000};
+ int [] expecedWithZeroSkew = {6, 9, 14, 22, 26, 42, 71, 123, 148, 268, 496, 936, 1152, 2215, 4304, 8429, 10480};
+ int [] expecedWith5pSkew = {6, 10, 14, 23, 26, 43, 73, 128, 154, 280, 518, 979, 1205, 2319, 4509, 8837, 10989};
+ for (int i = 0; i < K.length; i++) {
+ assertEquals(expecedWithZeroSkew[i], idealEstimator.estimateK(K[i], 10));
+ assertEquals(expecedWith5pSkew[i], skewedEstimator.estimateK(K[i], 10));
+ }
+
+ String expected =
+ "Prob/Hits: 1.0000000000 0.9999000000 0.9999900000 0.9999990000 0.9999999000 0.9999999900 0.9999999990 0.9999999999\n" +
+ " 10: 10.000 6.000 7.000 8.000 9.000 10.000 10.000 10.000\n" +
+ " 20: 10.000 4.500 5.000 5.500 6.500 7.000 7.500 8.000\n" +
+ " 40: 10.000 3.500 4.000 4.250 4.750 5.250 5.500 6.000\n" +
+ " 80: 10.000 2.750 3.000 3.250 3.625 3.875 4.250 4.500\n" +
+ " 100: 10.000 2.600 2.800 3.100 3.300 3.600 3.900 4.200\n" +
+ " 200: 10.000 2.100 2.250 2.450 2.650 2.800 3.000 3.200\n" +
+ " 400: 10.000 1.775 1.900 2.025 2.150 2.275 2.425 2.575\n" +
+ " 800: 10.000 1.538 1.625 1.713 1.813 1.900 2.000 2.100\n" +
+ " 1000: 10.000 1.480 1.560 1.640 1.720 1.810 1.890 1.990\n" +
+ " 2000: 10.000 1.340 1.395 1.450 1.510 1.570 1.630 1.695\n" +
+ " 4000: 10.000 1.240 1.280 1.320 1.360 1.403 1.445 1.493\n" +
+ " 8000: 10.000 1.170 1.198 1.225 1.254 1.284 1.315 1.348\n" +
+ " 10000: 10.000 1.152 1.177 1.202 1.227 1.254 1.282 1.311\n" +
+ " 20000: 10.000 1.108 1.125 1.143 1.161 1.180 1.199 1.220\n" +
+ " 40000: 10.000 1.076 1.088 1.101 1.114 1.127 1.141 1.156\n" +
+ " 80000: 10.000 1.054 1.062 1.071 1.080 1.090 1.100 1.110\n" +
+ " 100000: 10.000 1.048 1.056 1.064 1.072 1.080 1.089 1.098\n";
+ assertEquals(expected, dumpProbability(10, 0.0));
+ String expectedSkew =
+ "Prob/Hits: 1.0000000000 0.9999000000 0.9999900000 0.9999990000 0.9999999000 0.9999999900 0.9999999990 0.9999999999\n" +
+ " 10: 10.000 6.000 7.000 8.000 9.000 10.000 10.000 10.000\n" +
+ " 20: 10.000 5.000 5.500 6.000 6.500 7.000 7.500 8.500\n" +
+ " 40: 10.000 3.500 4.000 4.500 4.750 5.250 5.750 6.250\n" +
+ " 80: 10.000 2.875 3.125 3.375 3.750 4.000 4.375 4.625\n" +
+ " 100: 10.000 2.600 2.900 3.100 3.400 3.700 4.000 4.300\n" +
+ " 200: 10.000 2.150 2.350 2.500 2.700 2.900 3.100 3.300\n" +
+ " 400: 10.000 1.825 1.950 2.075 2.225 2.350 2.500 2.650\n" +
+ " 800: 10.000 1.600 1.688 1.775 1.875 1.975 2.075 2.175\n" +
+ " 1000: 10.000 1.540 1.620 1.700 1.790 1.870 1.960 2.060\n" +
+ " 2000: 10.000 1.400 1.455 1.510 1.570 1.630 1.695 1.760\n" +
+ " 4000: 10.000 1.295 1.335 1.375 1.418 1.460 1.505 1.553\n" +
+ " 8000: 10.000 1.224 1.251 1.280 1.309 1.340 1.371 1.405\n" +
+ " 10000: 10.000 1.205 1.230 1.255 1.282 1.309 1.337 1.367\n" +
+ " 20000: 10.000 1.160 1.177 1.195 1.214 1.233 1.253 1.275\n" +
+ " 40000: 10.000 1.127 1.140 1.153 1.166 1.179 1.194 1.209\n" +
+ " 80000: 10.000 1.105 1.114 1.123 1.132 1.141 1.152 1.162\n" +
+ " 100000: 10.000 1.099 1.107 1.115 1.123 1.132 1.141 1.150\n";
+ assertEquals(expectedSkew, dumpProbability(10, 0.05));
+ }
+
+ /**
+ * This make a table showing how many more hits will be fetched as a factor of hits requested.
+ * It shows how it varies with probability and hits requested for a given number of partitions.
+ */
+ private String dumpProbability(int numPartitions, double skewFactor) {
+ TopKEstimator estimator = new TopKEstimator(30, 0.9999, skewFactor);
+ int [] K = {10, 20, 40, 80, 100, 200, 400, 800, 1000, 2000, 4000, 8000, 10000, 20000, 40000, 80000, 100000};
+ double [] P = {1.0, 0.9999, 0.99999, 0.999999, 0.9999999, 0.99999999, 0.999999999, 0.9999999999};
+ int n = numPartitions;
+ StringBuilder sb = new StringBuilder();
+ sb.append(String.format("Prob/Hits:"));
+ for (double p : P) {
+ sb.append(String.format(Locale.ENGLISH, " %1.10f", p));
+ }
+ sb.append("\n");
+ for (int k : K) {
+ sb.append(String.format(Locale.ENGLISH, "%9d:", k));
+ for (double p : P) {
+ sb.append(String.format(Locale.ENGLISH, "%13.3f", (double)(estimator.estimateK(k, n, p)*n) / k));
+ }
+ sb.append("\n");
+ }
+ return sb.toString();
+ }
+
+}
diff --git a/container-search/src/test/java/com/yahoo/search/dispatch/rpc/MockClient.java b/container-search/src/test/java/com/yahoo/search/dispatch/rpc/MockClient.java
index 2fc8c0fd620..1a0037e4b8a 100644
--- a/container-search/src/test/java/com/yahoo/search/dispatch/rpc/MockClient.java
+++ b/container-search/src/test/java/com/yahoo/search/dispatch/rpc/MockClient.java
@@ -32,6 +32,8 @@ public class MockClient implements Client {
public void setMalfunctioning(boolean malfunctioning) { this.malfunctioning = malfunctioning; }
@Override
+ public void close() { }
+ @Override
public NodeConnection createConnection(String hostname, int port) {
return new MockNodeConnection(hostname, port);
}
diff --git a/container-search/src/test/java/com/yahoo/search/dispatch/rpc/RpcSearchInvokerTest.java b/container-search/src/test/java/com/yahoo/search/dispatch/rpc/RpcSearchInvokerTest.java
index ce19224b35f..27fc3f85136 100644
--- a/container-search/src/test/java/com/yahoo/search/dispatch/rpc/RpcSearchInvokerTest.java
+++ b/container-search/src/test/java/com/yahoo/search/dispatch/rpc/RpcSearchInvokerTest.java
@@ -20,6 +20,7 @@ import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@@ -38,7 +39,9 @@ public class RpcSearchInvokerTest {
var invoker = new RpcSearchInvoker(mockSearcher(), new Node(7, "seven", 1), mockPool, 1000);
Query q = new Query("search/?query=test&hits=10&offset=3");
- invoker.sendSearchRequest(q);
+ RpcSearchInvoker.RpcContext context = (RpcSearchInvoker.RpcContext) invoker.sendSearchRequest(q, null);
+ assertEquals(lengthHolder.get(), context.compressedPayload.uncompressedSize());
+ assertSame(context.compressedPayload.data(), payloadHolder.get());
var bytes = mockPool.compressor().decompress(payloadHolder.get(), compressionTypeHolder.get(), lengthHolder.get());
var request = SearchProtocol.SearchRequest.newBuilder().mergeFrom(bytes).build();
@@ -46,6 +49,12 @@ public class RpcSearchInvokerTest {
assertEquals(10, request.getHits());
assertEquals(3, request.getOffset());
assertTrue(request.getQueryTreeBlob().size() > 0);
+
+ var invoker2 = new RpcSearchInvoker(mockSearcher(), new Node(8, "eight", 1), mockPool, 1000);
+ RpcSearchInvoker.RpcContext context2 = (RpcSearchInvoker.RpcContext)invoker2.sendSearchRequest(q, context);
+ assertSame(context, context2);
+ assertEquals(lengthHolder.get(), context.compressedPayload.uncompressedSize());
+ assertSame(context.compressedPayload.data(), payloadHolder.get());
}
@Test
@@ -59,7 +68,7 @@ public class RpcSearchInvokerTest {
var invoker = new RpcSearchInvoker(mockSearcher(), new Node(7, "seven", 1), mockPool, maxHits);
Query q = new Query("search/?query=test&hits=10&offset=3");
- invoker.sendSearchRequest(q);
+ invoker.sendSearchRequest(q, null);
var bytes = mockPool.compressor().decompress(payloadHolder.get(), compressionTypeHolder.get(), lengthHolder.get());
var request = SearchProtocol.SearchRequest.newBuilder().mergeFrom(bytes).build();
@@ -71,6 +80,8 @@ public class RpcSearchInvokerTest {
AtomicInteger lengthHolder) {
return new Client() {
@Override
+ public void close() { }
+ @Override
public NodeConnection createConnection(String hostname, int port) {
return new NodeConnection() {
@Override
@@ -88,8 +99,7 @@ public class RpcSearchInvokerTest {
}
@Override
- public void close() {
- }
+ public void close() { }
};
}
};
diff --git a/container-search/src/test/java/com/yahoo/search/dispatch/searchcluster/SearchClusterCoverageTest.java b/container-search/src/test/java/com/yahoo/search/dispatch/searchcluster/SearchClusterCoverageTest.java
new file mode 100644
index 00000000000..8101aee74fd
--- /dev/null
+++ b/container-search/src/test/java/com/yahoo/search/dispatch/searchcluster/SearchClusterCoverageTest.java
@@ -0,0 +1,141 @@
+// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.search.dispatch.searchcluster;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author bratseth
+ */
+public class SearchClusterCoverageTest {
+
+ @Test
+ public void two_groups_equal_docs() {
+ var tester = new SearchClusterTester(2, 3);
+
+ tester.setDocsPerNode(100, 0);
+ tester.setDocsPerNode(100, 1);
+ tester.pingIterationCompleted();
+ assertTrue(tester.group(0).hasSufficientCoverage());
+ assertTrue(tester.group(1).hasSufficientCoverage());
+ }
+
+ @Test
+ public void two_groups_one_missing_docs() {
+ var tester = new SearchClusterTester(2, 3);
+
+ tester.setDocsPerNode(100, 0);
+ tester.setDocsPerNode( 70, 1);
+ tester.pingIterationCompleted();
+ assertTrue(tester.group(0).hasSufficientCoverage());
+ assertFalse(tester.group(1).hasSufficientCoverage());
+ }
+
+ @Test
+ public void three_groups_one_missing_docs() {
+ var tester = new SearchClusterTester(3, 3);
+
+ tester.setDocsPerNode(100, 0);
+ tester.setDocsPerNode( 87, 1); // min is set to 88 in MockSearchCluster
+ tester.setDocsPerNode(100, 2);
+ tester.pingIterationCompleted();
+ assertTrue(tester.group(0).hasSufficientCoverage());
+ assertFalse(tester.group(1).hasSufficientCoverage());
+ assertTrue(tester.group(2).hasSufficientCoverage());
+ }
+
+ @Test
+ public void three_groups_one_missing_docs_but_too_few() {
+ var tester = new SearchClusterTester(3, 3);
+
+ tester.setDocsPerNode(100, 0);
+ tester.setDocsPerNode( 89, 1); // min is set to 88 in MockSearchCluster
+ tester.setDocsPerNode(100, 2);
+ tester.pingIterationCompleted();
+ assertTrue(tester.group(0).hasSufficientCoverage());
+ assertTrue(tester.group(1).hasSufficientCoverage());
+ assertTrue(tester.group(2).hasSufficientCoverage());
+ }
+
+ @Test
+ public void three_groups_one_has_too_many_docs() {
+ var tester = new SearchClusterTester(3, 3);
+
+ tester.setDocsPerNode(100, 0);
+ tester.setDocsPerNode(150, 1);
+ tester.setDocsPerNode(100, 2);
+ tester.pingIterationCompleted();
+ assertTrue(tester.group(0).hasSufficientCoverage());
+ assertTrue(tester.group(1).hasSufficientCoverage());
+ assertTrue(tester.group(2).hasSufficientCoverage());
+ }
+
+ @Test
+ public void three_groups_one_has_a_node_down() {
+ var tester = new SearchClusterTester(3, 3);
+
+ tester.setDocsPerNode(100, 0);
+ tester.setDocsPerNode(100, 1);
+ tester.setDocsPerNode(100, 2);
+ tester.setWorking(1, 1, false);
+ tester.pingIterationCompleted();
+ assertTrue(tester.group(0).hasSufficientCoverage());
+ assertFalse(tester.group(1).hasSufficientCoverage());
+ assertTrue(tester.group(2).hasSufficientCoverage());
+ }
+
+ @Test
+ public void three_groups_one_has_a_node_down_but_remaining_has_enough_docs() {
+ var tester = new SearchClusterTester(3, 3);
+
+ tester.setDocsPerNode(100, 0);
+ tester.setDocsPerNode(150, 1);
+ tester.setDocsPerNode(100, 2);
+ tester.setWorking(1, 1, false);
+ tester.pingIterationCompleted();
+ assertTrue(tester.group(0).hasSufficientCoverage());
+ assertTrue("Sufficient documents on remaining two nodes", tester.group(1).hasSufficientCoverage());
+ assertTrue(tester.group(2).hasSufficientCoverage());
+ }
+
+ @Test
+ public void one_group_few_docs_unbalanced() {
+ var tester = new SearchClusterTester(1, 2);
+
+ Node node0 = tester.group(0).nodes().get(0);
+ Node node1 = tester.group(0).nodes().get(1);
+
+ // 1 document
+ node0.setWorking(true);
+ node1.setWorking(true);
+
+ node0.setActiveDocuments(1);
+ node1.setActiveDocuments(0);
+
+ tester.pingIterationCompleted();
+ assertFalse(tester.group(0).isBalanced());
+ assertTrue(tester.group(0).isSparse());
+ }
+
+ @Test
+ public void one_group_many_docs_unbalanced() {
+ var tester = new SearchClusterTester(1, 2);
+
+ Node node0 = tester.group(0).nodes().get(0);
+ Node node1 = tester.group(0).nodes().get(1);
+
+ // 1 document
+ node0.setWorking(true);
+ node1.setWorking(true);
+
+ node0.setActiveDocuments(1000000);
+ node1.setActiveDocuments(100000);
+
+ tester.pingIterationCompleted();
+ assertFalse(tester.group(0).isBalanced());
+ assertFalse(tester.group(0).isSparse());
+ }
+
+}
diff --git a/container-search/src/test/java/com/yahoo/search/dispatch/searchcluster/SearchClusterTest.java b/container-search/src/test/java/com/yahoo/search/dispatch/searchcluster/SearchClusterTest.java
index bb7baeda8da..22cc783967d 100644
--- a/container-search/src/test/java/com/yahoo/search/dispatch/searchcluster/SearchClusterTest.java
+++ b/container-search/src/test/java/com/yahoo/search/dispatch/searchcluster/SearchClusterTest.java
@@ -28,7 +28,7 @@ import static org.junit.Assert.assertTrue;
*/
public class SearchClusterTest {
- static class State implements AutoCloseable{
+ static class State implements AutoCloseable {
final String clusterId;
final int nodesPerGroup;
@@ -191,7 +191,7 @@ public class SearchClusterTest {
}
@Test
- public void requireThatVipStatusIsDefaultDownWithOnlySingleLocalDispatch() {
+ public void requireThatVipStatusStaysUpWithLocalDispatchAndClusterSize1() {
try (State test = new State("cluster.1", 1, HostName.getLocalhost())) {
assertTrue(test.searchCluster.localCorpusDispatchTarget().isPresent());
@@ -200,6 +200,20 @@ public class SearchClusterTest {
assertTrue(test.vipStatus.isInRotation());
test.numDocsPerNode.get(0).set(-1);
test.waitOneFullPingRound();
+ assertTrue(test.vipStatus.isInRotation());
+ }
+ }
+
+ @Test
+ public void requireThatVipStatusIsDefaultDownWithLocalDispatchAndClusterSize2() {
+ try (State test = new State("cluster.1", 1, HostName.getLocalhost(), "otherhost")) {
+ assertTrue(test.searchCluster.localCorpusDispatchTarget().isPresent());
+
+ assertFalse(test.vipStatus.isInRotation());
+ test.waitOneFullPingRound();
+ assertTrue(test.vipStatus.isInRotation());
+ test.numDocsPerNode.get(0).set(-1);
+ test.waitOneFullPingRound();
assertFalse(test.vipStatus.isInRotation());
}
}
@@ -320,4 +334,48 @@ public class SearchClusterTest {
assertEquals(3, node.getLastReceivedPongId());
}
+ @Test
+ public void requireThatEmptyGroupIsInBalance() {
+ Group group = new Group(0, new ArrayList<>());
+ assertTrue(group.isBalanced());
+ group.aggregateNodeValues();
+ assertTrue(group.isBalanced());
+ }
+
+ @Test
+ public void requireThatSingleNodeGroupIsInBalance() {
+ Group group = new Group(0, Arrays.asList(new Node(1, "n", 1)));
+ group.nodes().forEach(node -> node.setWorking(true));
+ assertTrue(group.isBalanced());
+ group.aggregateNodeValues();
+ assertTrue(group.isBalanced());
+ group.nodes().get(0).setActiveDocuments(1000);
+ group.aggregateNodeValues();
+ assertTrue(group.isBalanced());
+ }
+
+ @Test
+ public void requireThatMultiNodeGroupDetectsBalance() {
+ Group group = new Group(0, Arrays.asList(new Node(1, "n1", 1), new Node(2, "n2", 1)));
+ assertTrue(group.isBalanced());
+ group.nodes().forEach(node -> node.setWorking(true));
+ assertTrue(group.isBalanced());
+ group.aggregateNodeValues();
+ assertTrue(group.isBalanced());
+ group.nodes().get(0).setActiveDocuments(1000);
+ group.aggregateNodeValues();
+ assertFalse(group.isBalanced());
+ group.nodes().get(1).setActiveDocuments(100);
+ group.aggregateNodeValues();
+ assertFalse(group.isBalanced());
+ group.nodes().get(1).setActiveDocuments(800);
+ group.aggregateNodeValues();
+ assertFalse(group.isBalanced());
+ group.nodes().get(1).setActiveDocuments(818);
+ group.aggregateNodeValues();
+ assertFalse(group.isBalanced());
+ group.nodes().get(1).setActiveDocuments(819);
+ group.aggregateNodeValues();
+ assertTrue(group.isBalanced());
+ }
}
diff --git a/container-search/src/test/java/com/yahoo/search/dispatch/searchcluster/SearchClusterTester.java b/container-search/src/test/java/com/yahoo/search/dispatch/searchcluster/SearchClusterTester.java
new file mode 100644
index 00000000000..5e7ecb854ff
--- /dev/null
+++ b/container-search/src/test/java/com/yahoo/search/dispatch/searchcluster/SearchClusterTester.java
@@ -0,0 +1,33 @@
+// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.search.dispatch.searchcluster;
+
+import com.yahoo.search.dispatch.MockSearchCluster;
+
+public class SearchClusterTester {
+
+ private final SearchCluster cluster;
+
+ public SearchClusterTester(int groups, int nodesPerGroup) {
+ cluster = new MockSearchCluster("1", groups, nodesPerGroup);
+ }
+
+ public void pingIterationCompleted() {
+ cluster.pingIterationCompleted();
+ }
+
+ public Group group(int id) {
+ return cluster.group(id).get();
+ }
+
+ public void setWorking(int group, int node, boolean working) {
+ cluster.group(group).get().nodes().get(node).setWorking(working);
+ }
+
+ public void setDocsPerNode(int docs, int groupId) {
+ for (Node node : cluster.groups().get(groupId).nodes()) {
+ node.setWorking(true);
+ node.setActiveDocuments(docs);
+ }
+ }
+
+}
diff --git a/container-search/src/test/java/com/yahoo/search/grouping/GroupingRequestTestCase.java b/container-search/src/test/java/com/yahoo/search/grouping/GroupingRequestTestCase.java
index 244d45f1b29..fb08b39de4d 100644
--- a/container-search/src/test/java/com/yahoo/search/grouping/GroupingRequestTestCase.java
+++ b/container-search/src/test/java/com/yahoo/search/grouping/GroupingRequestTestCase.java
@@ -124,10 +124,10 @@ public class GroupingRequestTestCase {
assertEquals(Collections.emptyList(), query.getSelect().getGrouping());
GroupingRequest foo = GroupingRequest.newInstance(query);
- assertEquals(Arrays.asList(foo), query.getSelect().getGrouping());
+ assertEquals(List.of(foo), query.getSelect().getGrouping());
GroupingRequest bar = GroupingRequest.newInstance(query);
- assertEquals(Arrays.asList(foo, bar), query.getSelect().getGrouping());
+ assertEquals(List.of(foo, bar), query.getSelect().getGrouping());
}
diff --git a/container-search/src/test/java/com/yahoo/search/grouping/UniqueGroupingSearcherTestCase.java b/container-search/src/test/java/com/yahoo/search/grouping/UniqueGroupingSearcherTestCase.java
index 8ff03b35b60..86ab96a2197 100644
--- a/container-search/src/test/java/com/yahoo/search/grouping/UniqueGroupingSearcherTestCase.java
+++ b/container-search/src/test/java/com/yahoo/search/grouping/UniqueGroupingSearcherTestCase.java
@@ -2,7 +2,6 @@
package com.yahoo.search.grouping;
import com.yahoo.component.chain.Chain;
-import com.yahoo.prelude.query.QueryException;
import com.yahoo.search.Query;
import com.yahoo.search.Result;
import com.yahoo.search.Searcher;
@@ -41,18 +40,19 @@ public class UniqueGroupingSearcherTestCase {
new MockResultProvider(0, false));
assertEquals(0, result.hits().size());
}
+
@Test
public void testIllegalSortingSpec() {
try {
search("?query=foo&unique=fingerprint&sorting=-1",
new MockResultProvider(0, true).addGroupList(new GroupList("fingerprint")));
fail("Above statement should throw");
- } catch (QueryException e) {
+ } catch (IllegalArgumentException e) {
// As expected.
assertThat(
Exceptions.toMessageString(e),
containsString(
- "Invalid request parameter: Could not set 'ranking.sorting' to '-1': " +
+ "Could not set 'ranking.sorting' to '-1': " +
"Illegal attribute name '1' for sorting. Requires '[\\[]*[a-zA-Z_][\\.a-zA-Z0-9_-]*[\\]]*'"));
}
}
diff --git a/container-search/src/test/java/com/yahoo/search/grouping/vespa/IntegerEncoderTestCase.java b/container-search/src/test/java/com/yahoo/search/grouping/vespa/IntegerEmbedderTestCase.java
index 3b48ae35fcf..18a9f11e15e 100644
--- a/container-search/src/test/java/com/yahoo/search/grouping/vespa/IntegerEncoderTestCase.java
+++ b/container-search/src/test/java/com/yahoo/search/grouping/vespa/IntegerEmbedderTestCase.java
@@ -8,7 +8,7 @@ import static org.junit.Assert.assertEquals;
/**
* @author Simon Thoresen Hult
*/
-public class IntegerEncoderTestCase {
+public class IntegerEmbedderTestCase {
@Test
public void requireThatIntEncoderWorksAsExpected() {
diff --git a/container-search/src/test/java/com/yahoo/search/handler/test/SearchHandlerTestCase.java b/container-search/src/test/java/com/yahoo/search/handler/SearchHandlerTest.java
index c96af2ed4d1..2b584c7b285 100644
--- a/container-search/src/test/java/com/yahoo/search/handler/test/SearchHandlerTestCase.java
+++ b/container-search/src/test/java/com/yahoo/search/handler/SearchHandlerTest.java
@@ -1,5 +1,5 @@
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.search.handler.test;
+package com.yahoo.search.handler;
import com.yahoo.container.Container;
import com.yahoo.container.core.config.testutil.HandlersConfigurerTestWrapper;
@@ -8,13 +8,13 @@ import com.yahoo.container.jdisc.HttpResponse;
import com.yahoo.container.jdisc.RequestHandlerTestDriver;
import com.yahoo.container.jdisc.ThreadedHttpRequestHandler;
import com.yahoo.io.IOUtils;
+import com.yahoo.jdisc.Request;
import com.yahoo.jdisc.handler.RequestHandler;
+import com.yahoo.jdisc.test.MockMetric;
import com.yahoo.net.HostName;
import com.yahoo.search.Query;
import com.yahoo.search.Result;
import com.yahoo.search.Searcher;
-import com.yahoo.search.handler.HttpSearchResponse;
-import com.yahoo.search.handler.SearchHandler;
import com.yahoo.search.rendering.XmlRenderer;
import com.yahoo.search.result.ErrorMessage;
import com.yahoo.search.result.Hit;
@@ -44,7 +44,7 @@ import static org.junit.Assert.assertTrue;
/**
* @author bratseth
*/
-public class SearchHandlerTestCase {
+public class SearchHandlerTest {
private static final String testDir = "src/test/java/com/yahoo/search/handler/test/config";
private static final String myHostnameHeader = "my-hostname-header";
@@ -58,6 +58,7 @@ public class SearchHandlerTestCase {
private RequestHandlerTestDriver driver = null;
private HandlersConfigurerTestWrapper configurer = null;
+ private MockMetric metric;
private SearchHandler searchHandler;
@Before
@@ -71,6 +72,7 @@ public class SearchHandlerTestCase {
configurer = new HandlersConfigurerTestWrapper(new Container(), configId);
searchHandler = (SearchHandler)configurer.getRequestHandlerRegistry().getComponent(SearchHandler.class.getName());
+ metric = (MockMetric) searchHandler.metric();
driver = new RequestHandlerTestDriver(searchHandler);
}
@@ -179,10 +181,24 @@ public class SearchHandlerTestCase {
"http://localhost/search/?yql=select%20*%20from%20foo%20where%20bar%20%3E%201453501295%27%3B");
responseHandler.readAll();
assertThat(responseHandler.getStatus(), is(400));
+ assertEquals(Request.RequestType.READ, responseHandler.getResponse().getRequestType());
}
}
+ @Test
+ public void testRequestType() throws Exception {
+ IOUtils.copyDirectory(new File(testDir, "config_yql"), new File(tempDir), 1);
+ generateComponentsConfigForActive();
+ configurer.reloadConfig();
+ SearchHandler newSearchHandler = fetchSearchHandler(configurer);
+ try (RequestHandlerTestDriver newDriver = new RequestHandlerTestDriver(newSearchHandler)) {
+ RequestHandlerTestDriver.MockResponseHandler responseHandler = newDriver.sendRequest(
+ "http://localhost/search/?query=foo");
+ responseHandler.readAll();
+ assertEquals(Request.RequestType.READ, responseHandler.getResponse().getRequestType());
+ }
+ }
// Query handling takes a different code path when a query profile is active, so we test both paths.
@Test
@@ -201,7 +217,7 @@ public class SearchHandlerTestCase {
String response = responseHandler.readAll();
assertThat(responseHandler.getStatus(), is(400));
assertThat(response, containsString("offset"));
- assertThat(response, containsString("\"code\":" + com.yahoo.container.protect.Error.INVALID_QUERY_PARAMETER.code));
+ assertThat(response, containsString("\"code\":" + com.yahoo.container.protect.Error.ILLEGAL_QUERY.code));
}
@Test
@@ -274,6 +290,7 @@ public class SearchHandlerTestCase {
assertEquals(expected, response.readAll());
assertEquals(200, response.getStatus());
assertEquals(selfHostname, response.getResponse().headers().get(myHostnameHeader).get(0));
+ assertTrue(metric.metrics().containsKey(SearchHandler.RENDER_LATENCY_METRIC));
}
@Test
@@ -295,7 +312,7 @@ public class SearchHandlerTestCase {
}
private void assertHandlerResponse(int status, String responseData, String handlerName) throws Exception {
- RequestHandler forwardingHandler = configurer.getRequestHandlerRegistry().getComponent("com.yahoo.search.handler.test.SearchHandlerTestCase$" + handlerName + "Handler");
+ RequestHandler forwardingHandler = configurer.getRequestHandlerRegistry().getComponent("com.yahoo.search.handler.SearchHandlerTest$" + handlerName + "Handler");
try (RequestHandlerTestDriver forwardingDriver = new RequestHandlerTestDriver(forwardingHandler)) {
RequestHandlerTestDriver.MockResponseHandler response = forwardingDriver.sendRequest("http://localhost/" + handlerName + "?query=test");
response.awaitResponse();
diff --git a/container-search/src/test/java/com/yahoo/search/handler/test/JSONSearchHandlerTestCase.java b/container-search/src/test/java/com/yahoo/search/handler/test/JSONSearchHandlerTestCase.java
index 272092b6fc0..80e629ca4cb 100644
--- a/container-search/src/test/java/com/yahoo/search/handler/test/JSONSearchHandlerTestCase.java
+++ b/container-search/src/test/java/com/yahoo/search/handler/test/JSONSearchHandlerTestCase.java
@@ -1,10 +1,13 @@
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.search.handler.test;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
import com.yahoo.container.Container;
import com.yahoo.container.core.config.testutil.HandlersConfigurerTestWrapper;
import com.yahoo.container.jdisc.HttpRequest;
-
import com.yahoo.container.jdisc.RequestHandlerTestDriver;
import com.yahoo.container.protect.Error;
import com.yahoo.io.IOUtils;
@@ -13,8 +16,8 @@ import com.yahoo.search.handler.SearchHandler;
import com.yahoo.search.searchchain.config.test.SearchChainConfigurerTestCase;
import com.yahoo.slime.Inspector;
import com.yahoo.slime.SlimeUtils;
-import org.json.JSONArray;
-import org.json.JSONObject;
+import com.yahoo.test.json.JsonTestHelper;
+import org.assertj.core.api.Assertions;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
@@ -23,13 +26,19 @@ import org.junit.rules.TemporaryFolder;
import java.io.File;
import java.io.IOException;
-import java.util.Map;
+import java.nio.charset.StandardCharsets;
import java.util.HashMap;
+import java.util.Map;
import static com.yahoo.jdisc.http.HttpRequest.Method.GET;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.is;
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
/**
* Tests submitting the query as JSON.
@@ -38,6 +47,8 @@ import static org.junit.Assert.*;
*/
public class JSONSearchHandlerTestCase {
+ private static final ObjectMapper jsonMapper = new ObjectMapper();
+
private static final String testDir = "src/test/java/com/yahoo/search/handler/test/config";
private static final String myHostnameHeader = "my-hostname-header";
private static final String selfHostname = HostName.getLocalhost();
@@ -97,8 +108,8 @@ public class JSONSearchHandlerTestCase {
}
@Test
- public void testFailing() throws Exception {
- JSONObject json = new JSONObject();
+ public void testFailing() {
+ ObjectNode json = jsonMapper.createObjectNode();
json.put("query", "test");
json.put("searchChain", "classLoadingError");
assertTrue(driver.sendRequest(uri, com.yahoo.jdisc.http.HttpRequest.Method.POST, json.toString(), JSON_CONTENT_TYPE).readAll().contains("NoClassDefFoundError"));
@@ -106,16 +117,16 @@ public class JSONSearchHandlerTestCase {
@Test
- public synchronized void testPluginError() throws Exception {
- JSONObject json = new JSONObject();
+ public synchronized void testPluginError() {
+ ObjectNode json = jsonMapper.createObjectNode();
json.put("query", "test");
json.put("searchChain", "exceptionInPlugin");
assertTrue(driver.sendRequest(uri, com.yahoo.jdisc.http.HttpRequest.Method.POST, json.toString(), JSON_CONTENT_TYPE).readAll().contains("NullPointerException"));
}
@Test
- public synchronized void testWorkingReconfiguration() throws Exception {
- JSONObject json = new JSONObject();
+ public synchronized void testWorkingReconfiguration() throws IOException {
+ ObjectNode json = jsonMapper.createObjectNode();
json.put("query", "abc");
assertJsonResult(json, driver);
@@ -135,7 +146,7 @@ public class JSONSearchHandlerTestCase {
}
@Test
- public void testInvalidYqlQuery() throws Exception {
+ public void testInvalidYqlQuery() throws IOException {
IOUtils.copyDirectory(new File(testDir, "config_yql"), new File(tempDir), 1);
generateComponentsConfigForActive();
configurer.reloadConfig();
@@ -143,7 +154,7 @@ public class JSONSearchHandlerTestCase {
SearchHandler newSearchHandler = fetchSearchHandler(configurer);
assertTrue("Do I have a new instance of the search handler?", searchHandler != newSearchHandler);
try (RequestHandlerTestDriver newDriver = new RequestHandlerTestDriver(newSearchHandler)) {
- JSONObject json = new JSONObject();
+ ObjectNode json = jsonMapper.createObjectNode();
json.put("yql", "select * from foo where bar > 1453501295");
RequestHandlerTestDriver.MockResponseHandler responseHandler = newDriver.sendRequest(uri, com.yahoo.jdisc.http.HttpRequest.Method.POST, json.toString(), JSON_CONTENT_TYPE);
responseHandler.readAll();
@@ -153,14 +164,14 @@ public class JSONSearchHandlerTestCase {
// Query handling takes a different code path when a query profile is active, so we test both paths.
@Test
- public void testInvalidQueryParamWithQueryProfile() throws Exception {
+ public void testInvalidQueryParamWithQueryProfile() throws IOException {
try (RequestHandlerTestDriver newDriver = driverWithConfig("config_invalid_param")) {
testInvalidQueryParam(newDriver);
}
}
- private void testInvalidQueryParam(final RequestHandlerTestDriver testDriver) throws Exception {
- JSONObject json = new JSONObject();
+ private void testInvalidQueryParam(final RequestHandlerTestDriver testDriver) {
+ ObjectNode json = jsonMapper.createObjectNode();
json.put("query", "status_code:0");
json.put("hits", 20);
json.put("offset", -20);
@@ -169,20 +180,20 @@ public class JSONSearchHandlerTestCase {
String response = responseHandler.readAll();
assertThat(responseHandler.getStatus(), is(400));
assertThat(response, containsString("offset"));
- assertThat(response, containsString("\"code\":" + com.yahoo.container.protect.Error.INVALID_QUERY_PARAMETER.code));
+ assertThat(response, containsString("\"code\":" + com.yahoo.container.protect.Error.ILLEGAL_QUERY.code));
}
@Test
- public void testNormalResultJsonAliasRendering() throws Exception {
- JSONObject json = new JSONObject();
+ public void testNormalResultJsonAliasRendering() {
+ ObjectNode json = jsonMapper.createObjectNode();
json.put("format", "json");
json.put("query", "abc");
assertJsonResult(json, driver);
}
@Test
- public void testNullQuery() throws Exception {
- JSONObject json = new JSONObject();
+ public void testNullQuery() {
+ ObjectNode json = jsonMapper.createObjectNode();
json.put("format", "xml");
assertEquals("<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n" +
@@ -195,8 +206,8 @@ public class JSONSearchHandlerTestCase {
}
@Test
- public void testWebServiceStatus() throws Exception {
- JSONObject json = new JSONObject();
+ public void testWebServiceStatus() {
+ ObjectNode json = jsonMapper.createObjectNode();
json.put("query", "web_service_status_code");
RequestHandlerTestDriver.MockResponseHandler responseHandler =
driver.sendRequest(uri, com.yahoo.jdisc.http.HttpRequest.Method.POST, json.toString(), JSON_CONTENT_TYPE);
@@ -206,39 +217,39 @@ public class JSONSearchHandlerTestCase {
}
@Test
- public void testNormalResultImplicitDefaultRendering() throws Exception {
- JSONObject json = new JSONObject();
+ public void testNormalResultImplicitDefaultRendering() {
+ ObjectNode json = jsonMapper.createObjectNode();
json.put("query", "abc");
assertJsonResult(json, driver);
}
@Test
- public void testNormalResultExplicitDefaultRendering() throws Exception {
- JSONObject json = new JSONObject();
+ public void testNormalResultExplicitDefaultRendering() {
+ ObjectNode json = jsonMapper.createObjectNode();
json.put("query", "abc");
json.put("format", "default");
assertJsonResult(json, driver);
}
@Test
- public void testNormalResultXmlAliasRendering() throws Exception {
- JSONObject json = new JSONObject();
+ public void testNormalResultXmlAliasRendering() {
+ ObjectNode json = jsonMapper.createObjectNode();
json.put("query", "abc");
json.put("format", "xml");
assertXmlResult(json, driver);
}
@Test
- public void testNormalResultExplicitDefaultRenderingFullRendererName1() throws Exception {
- JSONObject json = new JSONObject();
+ public void testNormalResultExplicitDefaultRenderingFullRendererName1() {
+ ObjectNode json = jsonMapper.createObjectNode();
json.put("query", "abc");
json.put("format", "XmlRenderer");
assertXmlResult(json, driver);
}
@Test
- public void testNormalResultExplicitDefaultRenderingFullRendererName2() throws Exception {
- JSONObject json = new JSONObject();
+ public void testNormalResultExplicitDefaultRenderingFullRendererName2() {
+ ObjectNode json = jsonMapper.createObjectNode();
json.put("query", "abc");
json.put("format", "JsonRenderer");
assertJsonResult(json, driver);
@@ -253,7 +264,7 @@ public class JSONSearchHandlerTestCase {
" </hit>\n" +
"</result>\n";
- private void assertXmlResult(JSONObject json, RequestHandlerTestDriver driver) {
+ private void assertXmlResult(JsonNode json, RequestHandlerTestDriver driver) {
assertOkResult(driver.sendRequest(uri, com.yahoo.jdisc.http.HttpRequest.Method.POST, json.toString(), JSON_CONTENT_TYPE), xmlResult);
}
@@ -263,7 +274,7 @@ public class JSONSearchHandlerTestCase {
+ "{\"id\":\"testHit\",\"relevance\":1.0,\"fields\":{\"uri\":\"testHit\"}}"
+ "]}}";
- private void assertJsonResult(JSONObject json, RequestHandlerTestDriver driver) {
+ private void assertJsonResult(JsonNode json, RequestHandlerTestDriver driver) {
assertOkResult(driver.sendRequest(uri, com.yahoo.jdisc.http.HttpRequest.Method.POST, json.toString(), JSON_CONTENT_TYPE), jsonResult);
}
@@ -288,7 +299,7 @@ public class JSONSearchHandlerTestCase {
}
- private RequestHandlerTestDriver driverWithConfig(String configDirectory) throws Exception {
+ private RequestHandlerTestDriver driverWithConfig(String configDirectory) throws IOException {
IOUtils.copyDirectory(new File(testDir, configDirectory), new File(tempDir), 1);
generateComponentsConfigForActive();
configurer.reloadConfig();
@@ -299,44 +310,44 @@ public class JSONSearchHandlerTestCase {
}
@Test
- public void testSelectParameters() throws Exception {
- JSONObject json = new JSONObject();
+ public void testSelectParameters() throws IOException {
+ ObjectNode json = jsonMapper.createObjectNode();
- JSONObject select = new JSONObject();
+ ObjectNode select = jsonMapper.createObjectNode();
- JSONObject where = new JSONObject();
+ ObjectNode where = jsonMapper.createObjectNode();
where.put("where", "where");
- JSONObject grouping = new JSONObject();
+ ObjectNode grouping = jsonMapper.createObjectNode();
grouping.put("grouping", "grouping");
- select.put("where", where);
- select.put("grouping", grouping);
+ select.set("where", where);
+ select.set("grouping", grouping);
- json.put("select", select);
+ json.set("select", select);
- Inspector inspector = SlimeUtils.jsonToSlime(json.toString().getBytes("utf-8")).get();
+ Inspector inspector = SlimeUtils.jsonToSlime(json.toString().getBytes(StandardCharsets.UTF_8)).get();
Map<String, String> map = new HashMap<>();
searchHandler.createRequestMapping(inspector, map, "");
- JSONObject processedWhere = new JSONObject(map.get("select.where"));
- assertEquals(where.toString(), processedWhere.toString());
+ JsonNode processedWhere = jsonMapper.readTree(map.get("select.where"));
+ JsonTestHelper.assertJsonEquals(where.toString(), processedWhere.toString());
- JSONObject processedGrouping = new JSONObject(map.get("select.grouping"));
- assertEquals(grouping.toString(), processedGrouping.toString());
+ JsonNode processedGrouping = jsonMapper.readTree(map.get("select.grouping"));
+ JsonTestHelper.assertJsonEquals(grouping.toString(), processedGrouping.toString());
}
@Test
- public void testJsonQueryWithSelectWhere() throws Exception {
- JSONObject root = new JSONObject();
- JSONObject select = new JSONObject();
- JSONObject where = new JSONObject();
- JSONArray term = new JSONArray();
- term.put("default");
- term.put("bad");
- where.put("contains", term);
- select.put("where", where);
- root.put("select", select);
+ public void testJsonQueryWithSelectWhere() {
+ ObjectNode root = jsonMapper.createObjectNode();
+ ObjectNode select = jsonMapper.createObjectNode();
+ ObjectNode where = jsonMapper.createObjectNode();
+ ArrayNode term = jsonMapper.createArrayNode();
+ term.add("default");
+ term.add("bad");
+ where.set("contains", term);
+ select.set("where", where);
+ root.set("select", select);
// Run query
String result = driver.sendRequest(uri + "searchChain=echoingQuery", com.yahoo.jdisc.http.HttpRequest.Method.POST, root.toString(), JSON_CONTENT_TYPE).readAll();
@@ -393,8 +404,8 @@ public class JSONSearchHandlerTestCase {
}
@Test
- public void testJsonQueryWithYQL() throws Exception {
- JSONObject root = new JSONObject();
+ public void testJsonQueryWithYQL() {
+ ObjectNode root = jsonMapper.createObjectNode();
root.put("yql", "select * from sources * where default contains 'bad';");
// Run query
@@ -404,10 +415,10 @@ public class JSONSearchHandlerTestCase {
}
@Test
- public void testRequestMapping() throws Exception {
- JSONObject json = new JSONObject();
+ public void testRequestMapping() {
+ ObjectNode json = jsonMapper.createObjectNode();
json.put("yql", "select * from sources * where sddocname contains \"blog_post\" limit 0 | all(group(date) max(3) order(-count())each(output(count())));");
- json.put("hits", 10.0);
+ json.put("hits", 10);
json.put("offset", 5);
json.put("queryProfile", "foo");
json.put("nocache", false);
@@ -417,7 +428,7 @@ public class JSONSearchHandlerTestCase {
json.put("select", "_all");
- JSONObject model = new JSONObject();
+ ObjectNode model = jsonMapper.createObjectNode();
model.put("defaultIndex", 1);
model.put("encoding", "json");
model.put("filter", "default");
@@ -427,9 +438,9 @@ public class JSONSearchHandlerTestCase {
model.put("searchPath", "node1");
model.put("sources", "source1,source2");
model.put("type", "yql");
- json.put("model", model);
+ json.set("model", model);
- JSONObject ranking = new JSONObject();
+ ObjectNode ranking = jsonMapper.createObjectNode();
ranking.put("location", "123789.89123N;128123W");
ranking.put("features", "none");
ranking.put("listFeatures", false);
@@ -439,61 +450,61 @@ public class JSONSearchHandlerTestCase {
ranking.put("freshness", "0.05");
ranking.put("queryCache", false);
- JSONObject matchPhase = new JSONObject();
+ ObjectNode matchPhase = jsonMapper.createObjectNode();
matchPhase.put("maxHits", "100");
matchPhase.put("attribute", "title");
matchPhase.put("ascending", true);
- JSONObject diversity = new JSONObject();
+ ObjectNode diversity = jsonMapper.createObjectNode();
diversity.put("attribute", "title");
diversity.put("minGroups", 1);
- matchPhase.put("diversity", diversity);
- ranking.put("matchPhase", matchPhase);
- json.put("ranking", ranking);
+ matchPhase.set("diversity", diversity);
+ ranking.set("matchPhase", matchPhase);
+ json.set("ranking", ranking);
- JSONObject presentation = new JSONObject();
+ ObjectNode presentation = jsonMapper.createObjectNode();
presentation.put("bolding", true);
presentation.put("format", "json");
presentation.put("summary", "none");
presentation.put("template", "json");
presentation.put("timing", false);
- json.put("presentation", presentation);
+ json.set("presentation", presentation);
- JSONObject collapse = new JSONObject();
+ ObjectNode collapse = jsonMapper.createObjectNode();
collapse.put("field", "none");
collapse.put("size", 2);
collapse.put("summary", "default");
- json.put("collapse", collapse);
+ json.set("collapse", collapse);
- JSONObject trace = new JSONObject();
+ ObjectNode trace = jsonMapper.createObjectNode();
trace.put("level", 1);
trace.put("timestamps", false);
trace.put("rules", "none");
- json.put("trace", trace);
+ json.set("trace", trace);
- JSONObject pos = new JSONObject();
+ ObjectNode pos = jsonMapper.createObjectNode();
pos.put("ll", "1263123N;1231.9W");
pos.put("radius", "71234m");
pos.put("bb", "1237123W;123218N");
pos.put("attribute", "default");
- json.put("pos", pos);
+ json.set("pos", pos);
- JSONObject streaming = new JSONObject();
+ ObjectNode streaming = jsonMapper.createObjectNode();
streaming.put("userid", 123);
streaming.put("groupname", "abc");
streaming.put("selection", "none");
streaming.put("priority", 10);
streaming.put("maxbucketspervisitor", 5);
- json.put("streaming", streaming);
+ json.set("streaming", streaming);
- JSONObject rules = new JSONObject();
+ ObjectNode rules = jsonMapper.createObjectNode();
rules.put("off", false);
rules.put("rulebase", "default");
- json.put("rules", rules);
+ json.set("rules", rules);
- JSONObject metrics = new JSONObject();
+ ObjectNode metrics = jsonMapper.createObjectNode();
metrics.put("ignore", "_all");
- json.put("metrics", metrics);
+ json.set("metrics", metrics);
json.put("recall", "none");
json.put("user", 123);
@@ -501,7 +512,7 @@ public class JSONSearchHandlerTestCase {
json.put("hitcountestimate", true);
// Create mapping
- Inspector inspector = SlimeUtils.jsonToSlime(json.toString().getBytes("utf-8")).get();
+ Inspector inspector = SlimeUtils.jsonToSlime(json.toString().getBytes(StandardCharsets.UTF_8)).get();
Map<String, String> map = new HashMap<>();
searchHandler.createRequestMapping(inspector, map, "");
@@ -518,12 +529,12 @@ public class JSONSearchHandlerTestCase {
// Get mapping
Map<String, String> propertyMap = request.propertyMap();
- assertEquals("Should have same mapping for properties", map, propertyMap);
+ Assertions.assertThat(propertyMap).isEqualTo(map);
}
@Test
- public void testContentTypeParsing() throws Exception {
- JSONObject json = new JSONObject();
+ public void testContentTypeParsing() {
+ ObjectNode json = jsonMapper.createObjectNode();
json.put("query", "abc");
assertOkResult(driver.sendRequest(uri, com.yahoo.jdisc.http.HttpRequest.Method.POST, json.toString(), "Application/JSON; charset=utf-8"), jsonResult);
}
diff --git a/container-search/src/test/java/com/yahoo/search/handler/test/config/chains.cfg b/container-search/src/test/java/com/yahoo/search/handler/test/config/chains.cfg
index 9a16c6ed1e7..f7eba221ef1 100644
--- a/container-search/src/test/java/com/yahoo/search/handler/test/config/chains.cfg
+++ b/container-search/src/test/java/com/yahoo/search/handler/test/config/chains.cfg
@@ -1,20 +1,20 @@
chains[4]
chains[0].id default
chains[0].components[1]
-chains[0].components[0] com.yahoo.search.handler.test.SearchHandlerTestCase$TestSearcher
+chains[0].components[0] com.yahoo.search.handler.SearchHandlerTest$TestSearcher
chains[1].id classLoadingError
chains[1].components[1]
-chains[1].components[0] com.yahoo.search.handler.test.SearchHandlerTestCase$ClassLoadingErrorSearcher
+chains[1].components[0] com.yahoo.search.handler.SearchHandlerTest$ClassLoadingErrorSearcher
chains[2].id exceptionInPlugin
chains[2].components[1]
-chains[2].components[0] com.yahoo.search.handler.test.SearchHandlerTestCase$ExceptionInPluginSearcher
+chains[2].components[0] com.yahoo.search.handler.SearchHandlerTest$ExceptionInPluginSearcher
chains[3].id echoingQuery
chains[3].components[2]
chains[3].components[0] com.yahoo.search.yql.MinimalQueryInserter
-chains[3].components[1] com.yahoo.search.handler.test.SearchHandlerTestCase$EchoingQuerySearcher
+chains[3].components[1] com.yahoo.search.handler.SearchHandlerTest$EchoingQuerySearcher
components[5]
-components[0].id com.yahoo.search.handler.test.SearchHandlerTestCase$TestSearcher
-components[1].id com.yahoo.search.handler.test.SearchHandlerTestCase$ClassLoadingErrorSearcher
-components[2].id com.yahoo.search.handler.test.SearchHandlerTestCase$ExceptionInPluginSearcher
-components[3].id com.yahoo.search.handler.test.SearchHandlerTestCase$EchoingQuerySearcher
+components[0].id com.yahoo.search.handler.SearchHandlerTest$TestSearcher
+components[1].id com.yahoo.search.handler.SearchHandlerTest$ClassLoadingErrorSearcher
+components[2].id com.yahoo.search.handler.SearchHandlerTest$ExceptionInPluginSearcher
+components[3].id com.yahoo.search.handler.SearchHandlerTest$EchoingQuerySearcher
components[4].id com.yahoo.search.yql.MinimalQueryInserter
diff --git a/container-search/src/test/java/com/yahoo/search/handler/test/config/handlers.cfg b/container-search/src/test/java/com/yahoo/search/handler/test/config/handlers.cfg
index 96843d78aae..12f218581d5 100644
--- a/container-search/src/test/java/com/yahoo/search/handler/test/config/handlers.cfg
+++ b/container-search/src/test/java/com/yahoo/search/handler/test/config/handlers.cfg
@@ -1,8 +1,9 @@
-handler[7]
+handler[8]
handler[0].id com.yahoo.search.handler.SearchHandler
-handler[1].id com.yahoo.search.handler.test.SearchHandlerTestCase$NullReturningHandler
-handler[2].id com.yahoo.search.handler.test.SearchHandlerTestCase$NullReturningAsyncHandler
-handler[3].id com.yahoo.search.handler.test.SearchHandlerTestCase$ThrowingHandler
-handler[4].id com.yahoo.search.handler.test.SearchHandlerTestCase$ThrowingAsyncHandler
-handler[5].id com.yahoo.search.handler.test.SearchHandlerTestCase$ForwardingHandler
-handler[6].id com.yahoo.search.handler.test.SearchHandlerTestCase$ForwardingAsyncHandler
+handler[1].id com.yahoo.search.handler.SearchHandlerTest$NullReturningHandler
+handler[2].id com.yahoo.search.handler.SearchHandlerTest$NullReturningAsyncHandler
+handler[3].id com.yahoo.search.handler.SearchHandlerTest$ThrowingHandler
+handler[4].id com.yahoo.search.handler.SearchHandlerTest$ThrowingAsyncHandler
+handler[5].id com.yahoo.search.handler.SearchHandlerTest$ForwardingHandler
+handler[6].id com.yahoo.search.handler.SearchHandlerTest$ForwardingAsyncHandler
+handler[7].id com.yahoo.search.query.profile.compiled.CompiledQueryProfileRegistry
diff --git a/container-search/src/test/java/com/yahoo/search/handler/test/config/handlers2/chains.cfg b/container-search/src/test/java/com/yahoo/search/handler/test/config/handlers2/chains.cfg
index 2437efdec4f..83db7ef1cc9 100644
--- a/container-search/src/test/java/com/yahoo/search/handler/test/config/handlers2/chains.cfg
+++ b/container-search/src/test/java/com/yahoo/search/handler/test/config/handlers2/chains.cfg
@@ -1,10 +1,10 @@
chains[2]
chains[0].id default
chains[0].components[1]
-chains[0].components[0] com.yahoo.search.handler.test.SearchHandlerTestCase$TestSearcher
+chains[0].components[0] com.yahoo.search.handler.SearchHandlerTest$TestSearcher
chains[1].id hello
chains[1].components[1]
-chains[1].components[0] com.yahoo.search.handler.test.SearchHandlerTestCase$HelloWorldSearcher
+chains[1].components[0] com.yahoo.search.handler.SearchHandlerTest$HelloWorldSearcher
components[2]
-components[0].id com.yahoo.search.handler.test.SearchHandlerTestCase$TestSearcher
-components[1].id com.yahoo.search.handler.test.SearchHandlerTestCase$HelloWorldSearcher
+components[0].id com.yahoo.search.handler.SearchHandlerTest$TestSearcher
+components[1].id com.yahoo.search.handler.SearchHandlerTest$HelloWorldSearcher
diff --git a/container-search/src/test/java/com/yahoo/search/handler/test/config/handlersInvalid/handlers.cfg b/container-search/src/test/java/com/yahoo/search/handler/test/config/handlersInvalid/handlers.cfg
index 691b37b4955..9dd1aff9d06 100644
--- a/container-search/src/test/java/com/yahoo/search/handler/test/config/handlersInvalid/handlers.cfg
+++ b/container-search/src/test/java/com/yahoo/search/handler/test/config/handlersInvalid/handlers.cfg
@@ -1,3 +1,3 @@
handler[2]
handler[0].id com.yahoo.search.handler.SearchHandler
-handler[1].id com.yahoo.search.handler.test.SearchHandlerTestCase$ErrorOnInitializationHandler
+handler[1].id com.yahoo.search.handler.SearchHandlerTest$ErrorOnInitializationHandler
diff --git a/container-search/src/test/java/com/yahoo/search/query/MatchingTestCase.java b/container-search/src/test/java/com/yahoo/search/query/MatchingTestCase.java
index 462e5284972..3b6b3c7d7c6 100644
--- a/container-search/src/test/java/com/yahoo/search/query/MatchingTestCase.java
+++ b/container-search/src/test/java/com/yahoo/search/query/MatchingTestCase.java
@@ -1,7 +1,6 @@
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.search.query;
-import com.yahoo.prelude.query.QueryException;
import com.yahoo.search.Query;
import org.junit.Test;
@@ -12,9 +11,10 @@ import static org.junit.Assert.assertEquals;
* @author baldersheim
*/
public class MatchingTestCase {
+
@Test
public void testDefaultsInQuery() {
- Query query=new Query("?query=test");
+ Query query = new Query("?query=test");
assertNull(query.getRanking().getMatching().getTermwiseLimit());
assertNull(query.getRanking().getMatching().getNumThreadsPerSearch());
assertNull(query.getRanking().getMatching().getNumSearchPartitions());
@@ -24,7 +24,7 @@ public class MatchingTestCase {
@Test
public void testQueryOverride() {
- Query query=new Query("?query=test&ranking.matching.termwiselimit=0.7&ranking.matching.numthreadspersearch=17&ranking.matching.numsearchpartitions=13&ranking.matching.minhitsperthread=3");
+ Query query = new Query("?query=test&ranking.matching.termwiselimit=0.7&ranking.matching.numthreadspersearch=17&ranking.matching.numsearchpartitions=13&ranking.matching.minhitsperthread=3");
assertEquals(Double.valueOf(0.7), query.getRanking().getMatching().getTermwiseLimit());
assertEquals(Integer.valueOf(17), query.getRanking().getMatching().getNumThreadsPerSearch());
assertEquals(Integer.valueOf(13), query.getRanking().getMatching().getNumSearchPartitions());
@@ -40,16 +40,17 @@ public class MatchingTestCase {
private void verifyException(String key, String value) {
try {
new Query("?query=test&ranking.matching."+key+"="+value);
- assertFalse(true);
- } catch (QueryException e) {
- assertEquals("Invalid request parameter", e.getMessage());
- assertEquals("Could not set 'ranking.matching." + key + "' to '" + value +"'", e.getCause().getMessage());
- assertEquals(key + " must be in the range [0.0, 1.0]. It is " + value, e.getCause().getCause().getMessage());
+ fail();
+ } catch (IllegalArgumentException e) {
+ assertEquals("Could not set 'ranking.matching." + key + "' to '" + value +"'", e.getMessage());
+ assertEquals(key + " must be in the range [0.0, 1.0]. It is " + value, e.getCause().getMessage());
}
}
+
@Test
public void testLimits() {
verifyException("termwiselimit", "-0.1");
verifyException("termwiselimit", "1.1");
}
+
}
diff --git a/container-search/src/test/java/com/yahoo/search/query/SoftTimeoutTestCase.java b/container-search/src/test/java/com/yahoo/search/query/SoftTimeoutTestCase.java
index dff6d4c26c3..a15038ff7e2 100644
--- a/container-search/src/test/java/com/yahoo/search/query/SoftTimeoutTestCase.java
+++ b/container-search/src/test/java/com/yahoo/search/query/SoftTimeoutTestCase.java
@@ -1,7 +1,6 @@
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.search.query;
-import com.yahoo.prelude.query.QueryException;
import com.yahoo.search.Query;
import org.junit.Test;
import static org.junit.Assert.*;
@@ -10,9 +9,10 @@ import static org.junit.Assert.*;
* @author baldersheim
*/
public class SoftTimeoutTestCase {
+
@Test
public void testDefaultsInQuery() {
- Query query=new Query("?query=test");
+ Query query = new Query("?query=test");
assertTrue(query.getRanking().getSoftTimeout().getEnable());
assertNull(query.getRanking().getSoftTimeout().getFactor());
assertNull(query.getRanking().getSoftTimeout().getTailcost());
@@ -20,7 +20,7 @@ public class SoftTimeoutTestCase {
@Test
public void testQueryOverride() {
- Query query=new Query("?query=test&ranking.softtimeout.factor=0.7&ranking.softtimeout.tailcost=0.3");
+ Query query = new Query("?query=test&ranking.softtimeout.factor=0.7&ranking.softtimeout.tailcost=0.3");
assertTrue(query.getRanking().getSoftTimeout().getEnable());
assertEquals(Double.valueOf(0.7), query.getRanking().getSoftTimeout().getFactor());
assertEquals(Double.valueOf(0.3), query.getRanking().getSoftTimeout().getTailcost());
@@ -49,13 +49,13 @@ public class SoftTimeoutTestCase {
private void verifyException(String key, String value) {
try {
new Query("?query=test&ranking.softtimeout."+key+"="+value);
- assertFalse(true);
- } catch (QueryException e) {
- assertEquals("Invalid request parameter", e.getMessage());
- assertEquals("Could not set 'ranking.softtimeout." + key + "' to '" + value +"'", e.getCause().getMessage());
- assertEquals(key + " must be in the range [0.0, 1.0], got " + value, e.getCause().getCause().getMessage());
+ fail();
+ } catch (IllegalArgumentException e) {
+ assertEquals("Could not set 'ranking.softtimeout." + key + "' to '" + value +"'", e.getMessage());
+ assertEquals(key + " must be in the range [0.0, 1.0], got " + value, e.getCause().getMessage());
}
}
+
@Test
public void testLimits() {
verifyException("factor", "-0.1");
@@ -63,4 +63,5 @@ public class SoftTimeoutTestCase {
verifyException("tailcost", "-0.1");
verifyException("tailcost", "1.1");
}
+
}
diff --git a/container-search/src/test/java/com/yahoo/search/query/profile/compiled/BindingTestCase.java b/container-search/src/test/java/com/yahoo/search/query/profile/compiled/BindingTestCase.java
new file mode 100644
index 00000000000..621950ebc65
--- /dev/null
+++ b/container-search/src/test/java/com/yahoo/search/query/profile/compiled/BindingTestCase.java
@@ -0,0 +1,56 @@
+// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.search.query.profile.compiled;
+
+import com.yahoo.search.query.profile.DimensionBinding;
+import org.junit.Test;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author bratseth
+ */
+public class BindingTestCase {
+
+ @Test
+ public void testGeneralizes() {
+ Map<String, String> m1 = new HashMap<>();
+ m1.put("a", "a1");
+ m1.put("b", "b1");
+ m1.put("c", "c1");
+ m1.put("e", "e1");
+
+ Map<String, String> m2 = new HashMap<>();
+ m2.put("a", "a2");
+ m2.put("b", "b2");
+ m2.put("c", "c2");
+ m2.put("d", "d2");
+ m2.put("e", "e2");
+
+ Map<String, String> m3 = new HashMap<>();
+ m3.put("a", "a1");
+ m3.put("b", "b1");
+ m3.put("c", "c1");
+ m3.put("d", "d1");
+ m3.put("e", "e1");
+
+ Map<String, String> m4 = new HashMap<>();
+ m4.put("a", "a1");
+ m4.put("b", "b1");
+ m4.put("c", "c1");
+ m4.put("d", "d2");
+ m4.put("e", "e1");
+
+ Binding b1 = Binding.createFrom(DimensionBinding.createFrom(m1));
+ Binding b2 = Binding.createFrom(DimensionBinding.createFrom(m2));
+ Binding b3 = Binding.createFrom(DimensionBinding.createFrom(m3));
+ Binding b4 = Binding.createFrom(DimensionBinding.createFrom(m4));
+ assertFalse(b1.generalizes(b2));
+ assertTrue(b1.generalizes(b3));
+ assertTrue(b1.generalizes(b4));
+ }
+
+}
diff --git a/container-search/src/test/java/com/yahoo/search/query/profile/compiled/CompiledQueryProfileRegistryTest.java b/container-search/src/test/java/com/yahoo/search/query/profile/compiled/CompiledQueryProfileRegistryTest.java
new file mode 100644
index 00000000000..636298e8669
--- /dev/null
+++ b/container-search/src/test/java/com/yahoo/search/query/profile/compiled/CompiledQueryProfileRegistryTest.java
@@ -0,0 +1,29 @@
+// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.search.query.profile.compiled;
+
+import com.yahoo.search.query.profile.config.QueryProfilesConfig;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author gjoranv
+ */
+public class CompiledQueryProfileRegistryTest {
+
+ @Test
+ public void registry_can_be_created_from_config() {
+ var config = new QueryProfilesConfig.Builder()
+ .queryprofile(new QueryProfilesConfig.Queryprofile.Builder()
+ .id("profile1")
+ .property(new QueryProfilesConfig.Queryprofile.Property.Builder()
+ .name("hits")
+ .value("5")))
+ .build();
+
+ var registry = new CompiledQueryProfileRegistry(config);
+ var profile1 = registry.findQueryProfile("profile1");
+ assertEquals("5", profile1.get("hits"));
+ }
+
+}
diff --git a/container-search/src/test/java/com/yahoo/search/query/profile/config/test/QueryProfileConfigurationTestCase.java b/container-search/src/test/java/com/yahoo/search/query/profile/config/test/QueryProfileConfigurationTestCase.java
index 819cd3cdfd4..a1fba8e07f1 100644
--- a/container-search/src/test/java/com/yahoo/search/query/profile/config/test/QueryProfileConfigurationTestCase.java
+++ b/container-search/src/test/java/com/yahoo/search/query/profile/config/test/QueryProfileConfigurationTestCase.java
@@ -1,27 +1,25 @@
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.search.query.profile.config.test;
-import com.yahoo.config.subscription.ConfigInstanceUtil;
-import com.yahoo.io.IOUtils;
import com.yahoo.search.Query;
import com.yahoo.search.query.profile.QueryProfile;
-import com.yahoo.search.query.profile.compiled.CompiledQueryProfile;
import com.yahoo.search.query.profile.QueryProfileProperties;
+import com.yahoo.search.query.profile.compiled.CompiledQueryProfile;
import com.yahoo.search.query.profile.compiled.CompiledQueryProfileRegistry;
import com.yahoo.search.query.profile.config.QueryProfileConfigurer;
import com.yahoo.search.query.profile.config.QueryProfilesConfig;
+import com.yahoo.search.query.profile.config.QueryProfilesConfig.Queryprofile;
import com.yahoo.search.test.QueryTestCase;
-import com.yahoo.vespa.config.ConfigPayload;
-import org.junit.Ignore;
import org.junit.Test;
-import static org.junit.Assert.*;
-import java.io.File;
-import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+
/**
* @author bratseth
*/
diff --git a/container-search/src/test/java/com/yahoo/search/query/profile/config/test/XmlReadingTestCase.java b/container-search/src/test/java/com/yahoo/search/query/profile/config/test/XmlReadingTestCase.java
index e9f7ff24d42..253c6bd8792 100644
--- a/container-search/src/test/java/com/yahoo/search/query/profile/config/test/XmlReadingTestCase.java
+++ b/container-search/src/test/java/com/yahoo/search/query/profile/config/test/XmlReadingTestCase.java
@@ -3,7 +3,6 @@ package com.yahoo.search.query.profile.config.test;
import com.yahoo.jdisc.http.HttpRequest.Method;
import com.yahoo.container.jdisc.HttpRequest;
-import com.yahoo.processing.execution.Execution;
import com.yahoo.processing.request.CompoundName;
import com.yahoo.yolean.Exceptions;
import com.yahoo.search.Query;
@@ -32,6 +31,17 @@ import static org.junit.Assert.fail;
public class XmlReadingTestCase {
@Test
+ public void testInheritance() {
+ QueryProfileRegistry registry =
+ new QueryProfileXMLReader().read("src/test/java/com/yahoo/search/query/profile/config/test/inheritance");
+
+ CompiledQueryProfile cProfile = registry.getComponent("child").compile(null);
+ Query q = new Query("?query=foo", cProfile);
+ assertEquals("a.b-parent", q.properties().getString("a.b"));
+ assertEquals("d-parent", q.properties().getString("d"));
+ }
+
+ @Test
public void testValid() {
QueryProfileRegistry registry=
new QueryProfileXMLReader().read("src/test/java/com/yahoo/search/query/profile/config/test/validxml");
@@ -209,6 +219,19 @@ public class XmlReadingTestCase {
}
@Test
+ public void testQueryProfileVariantsWithOverridableFalse() {
+ QueryProfileXMLReader reader = new QueryProfileXMLReader();
+ CompiledQueryProfileRegistry registry = reader.read("src/test/java/com/yahoo/search/query/profile/config/test/variants/").compile();
+ CompiledQueryProfile profile = registry.findQueryProfile("default");
+
+ assertEquals("a.b.c-value", new Query("?d1=d1v", profile).properties().get("a.b.c"));
+ assertEquals("a.b.c-variant-value", new Query("?d1=d1v&d2=d2v", profile).properties().get("a.b.c"));
+
+ assertTrue(profile.isOverridable(new CompoundName("a.b.c"), Map.of("d1", "d1v")));
+ assertFalse(profile.isOverridable(new CompoundName("a.b.c"), Map.of("d1", "d1v", "d2", "d2v")));
+ }
+
+ @Test
public void testNewsFE1() {
CompiledQueryProfileRegistry registry=new QueryProfileXMLReader().read("src/test/java/com/yahoo/search/query/profile/config/test/newsfe").compile();
@@ -299,67 +322,70 @@ public class XmlReadingTestCase {
String queryString="tiled?query=india&queryProfile=myprofile&source.common.intl=tw&source.common.mode=adv";
Query query=new Query(HttpRequest.createTestRequest(queryString, Method.GET), registry.getComponent("myprofile"));
- for (Map.Entry e : query.properties().listProperties().entrySet())
- System.out.println(e);
assertEquals("news",query.properties().listProperties().get("source.common.provider"));
assertEquals("news",query.properties().get("source.common.provider"));
}
@Test
public void testNewsCase1() {
- CompiledQueryProfileRegistry registry=new QueryProfileXMLReader().read("src/test/java/com/yahoo/search/query/profile/config/test/newscase1").compile();
+ CompiledQueryProfileRegistry registry = new QueryProfileXMLReader().read("src/test/java/com/yahoo/search/query/profile/config/test/newscase1").compile();
Query query;
- query = new Query(HttpRequest.createTestRequest("?query=test&custid_1=parent", Method.GET),registry.getComponent("default"));
+ query = new Query(HttpRequest.createTestRequest("?query=test&custid_1=parent", Method.GET),
+ registry.getComponent("default"));
assertEquals(0.0, query.properties().get("ranking.features.b"));
assertEquals("0.0", query.properties().listProperties().get("ranking.features.b"));
- query = new Query(HttpRequest.createTestRequest("?query=test&custid_1=parent&custid_2=child", Method.GET),registry.getComponent("default"));
+ query = new Query(HttpRequest.createTestRequest("?query=test&custid_1=parent&custid_2=child", Method.GET),
+ registry.getComponent("default"));
assertEquals(0.1, query.properties().get("ranking.features.b"));
assertEquals("0.1", query.properties().listProperties().get("ranking.features.b"));
}
@Test
public void testNewsCase2() {
- CompiledQueryProfileRegistry registry=new QueryProfileXMLReader().read("src/test/java/com/yahoo/search/query/profile/config/test/newscase2").compile();
+ CompiledQueryProfileRegistry registry = new QueryProfileXMLReader().read("src/test/java/com/yahoo/search/query/profile/config/test/newscase2").compile();
Query query;
- query=new Query(HttpRequest.createTestRequest("?query=test&custid_1=parent", Method.GET),registry.getComponent("default"));
- assertEquals("0.0",query.properties().get("a.features.b"));
- assertEquals("0.0",query.properties().listProperties().get("a.features.b"));
- query=new Query(HttpRequest.createTestRequest("?query=test&custid_1=parent&custid_2=child", Method.GET),registry.getComponent("default"));
- assertEquals("0.1",query.properties().get("a.features.b"));
- assertEquals("0.1",query.properties().listProperties().get("a.features.b"));
+ query = new Query(HttpRequest.createTestRequest("?query=test&custid_1=parent", Method.GET),
+ registry.getComponent("default"));
+ assertEquals("0.0", query.properties().get("a.features.b"));
+ assertEquals("0.0", query.properties().listProperties().get("a.features.b"));
+ query = new Query(HttpRequest.createTestRequest("?query=test&custid_1=parent&custid_2=child", Method.GET),
+ registry.getComponent("default"));
+ assertEquals("0.1", query.properties().get("a.features.b"));
+ assertEquals("0.1", query.properties().listProperties().get("a.features.b"));
}
@Test
public void testNewsCase3() {
- CompiledQueryProfileRegistry registry=new QueryProfileXMLReader().read("src/test/java/com/yahoo/search/query/profile/config/test/newscase3").compile();
+ CompiledQueryProfileRegistry registry = new QueryProfileXMLReader().read("src/test/java/com/yahoo/search/query/profile/config/test/newscase3").compile();
- Query query;
- query=new Query(HttpRequest.createTestRequest("?query=test&custid_1=parent", Method.GET),registry.getComponent("default"));
+ Query query = new Query(HttpRequest.createTestRequest("?query=test&custid_1=parent", Method.GET),
+ registry.getComponent("default"));
assertEquals("0.0",query.properties().get("a.features"));
- query=new Query(HttpRequest.createTestRequest("?query=test&custid_1=parent&custid_2=child", Method.GET),registry.getComponent("default"));
+ query = new Query(HttpRequest.createTestRequest("?query=test&custid_1=parent&custid_2=child", Method.GET),
+ registry.getComponent("default"));
assertEquals("0.1",query.properties().get("a.features"));
}
- // Should cause an exception on the first line as we are trying to create a profile setting an illegal value in "ranking"
@Test
public void testNewsCase4() {
- CompiledQueryProfileRegistry registry=new QueryProfileXMLReader().read("src/test/java/com/yahoo/search/query/profile/config/test/newscase4").compile();
-
- Query query;
- query=new Query(HttpRequest.createTestRequest("?query=test&custid_1=parent", Method.GET),registry.getComponent("default"));
- assertEquals("0.0",query.properties().get("ranking.features"));
- query=new Query(HttpRequest.createTestRequest("?query=test&custid_1=parent&custid_2=child", Method.GET),registry.getComponent("default"));
- assertEquals("0.1",query.properties().get("ranking.features"));
+ CompiledQueryProfileRegistry registry = new QueryProfileXMLReader().read("src/test/java/com/yahoo/search/query/profile/config/test/newscase4").compile();
+
+ Query query = new Query(HttpRequest.createTestRequest("?query=test&custid_1=parent", Method.GET),
+ registry.getComponent("default"));
+ assertEquals(0.0, query.properties().get("ranking.features.foo"));
+ query = new Query(HttpRequest.createTestRequest("?query=test&custid_1=parent&custid_2=child", Method.GET),
+ registry.getComponent("default"));
+ assertEquals(0.1, query.properties().get("ranking.features.foo"));
}
@Test
public void testVersionRefs() {
- CompiledQueryProfileRegistry registry=new QueryProfileXMLReader().read("src/test/java/com/yahoo/search/query/profile/config/test/versionrefs").compile();
+ CompiledQueryProfileRegistry registry = new QueryProfileXMLReader().read("src/test/java/com/yahoo/search/query/profile/config/test/versionrefs").compile();
- Query query=new Query(HttpRequest.createTestRequest("?query=test", Method.GET),registry.getComponent("default"));
- assertEquals("MyProfile:1.0.2",query.properties().get("profile1.name"));
+ Query query = new Query(HttpRequest.createTestRequest("?query=test", Method.GET), registry.getComponent("default"));
+ assertEquals("MyProfile:1.0.2", query.properties().get("profile1.name"));
}
@Test
@@ -368,26 +394,28 @@ public class XmlReadingTestCase {
{
// Original reference
- Query query=new Query(HttpRequest.createTestRequest("?query=test", Method.GET),registry.getComponent("default"));
- assertEquals(null,query.properties().get("profileRef"));
- assertEquals("MyProfile1",query.properties().get("profileRef.name"));
- assertEquals("myProfile1Only",query.properties().get("profileRef.myProfile1Only"));
+ Query query = new Query(HttpRequest.createTestRequest("?query=test", Method.GET),
+ registry.getComponent("default"));
+ assertEquals(null, query.properties().get("profileRef"));
+ assertEquals("MyProfile1", query.properties().get("profileRef.name"));
+ assertEquals("myProfile1Only", query.properties().get("profileRef.myProfile1Only"));
assertNull(query.properties().get("profileRef.myProfile2Only"));
}
{
// Overridden reference
- Query query=new Query(HttpRequest.createTestRequest("?query=test&profileRef=ref:MyProfile2", Method.GET),registry.getComponent("default"));
+ Query query = new Query(HttpRequest.createTestRequest("?query=test&profileRef=ref:MyProfile2", Method.GET),registry.getComponent("default"));
assertEquals(null,query.properties().get("profileRef"));
- assertEquals("MyProfile2",query.properties().get("profileRef.name"));
- assertEquals("myProfile2Only",query.properties().get("profileRef.myProfile2Only"));
+ assertEquals("MyProfile2", query.properties().get("profileRef.name"));
+ assertEquals("myProfile2Only", query.properties().get("profileRef.myProfile2Only"));
assertNull(query.properties().get("profileRef.myProfile1Only"));
// later assignment
query.properties().set("profileRef.name", "newName");
assertEquals("newName", query.properties().get("profileRef.name"));
// ...will not impact others
- query=new Query(HttpRequest.createTestRequest("?query=test&profileRef=ref:MyProfile2", Method.GET), registry.getComponent("default"));
+ query = new Query(HttpRequest.createTestRequest("?query=test&profileRef=ref:MyProfile2", Method.GET),
+ registry.getComponent("default"));
assertEquals("MyProfile2", query.properties().get("profileRef.name"));
}
diff --git a/container-search/src/test/java/com/yahoo/search/query/profile/config/test/inheritance/child.xml b/container-search/src/test/java/com/yahoo/search/query/profile/config/test/inheritance/child.xml
new file mode 100644
index 00000000000..64dd3b787ac
--- /dev/null
+++ b/container-search/src/test/java/com/yahoo/search/query/profile/config/test/inheritance/child.xml
@@ -0,0 +1,6 @@
+<!-- Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -->
+<query-profile id="child" inherits="parent">
+ <field name="a.b.c">a.b.c-child</field>
+ <field name="d.e.f">d.e.f-child</field>
+</query-profile>
+
diff --git a/container-search/src/test/java/com/yahoo/search/query/profile/config/test/inheritance/parent.xml b/container-search/src/test/java/com/yahoo/search/query/profile/config/test/inheritance/parent.xml
new file mode 100644
index 00000000000..47873fcce4f
--- /dev/null
+++ b/container-search/src/test/java/com/yahoo/search/query/profile/config/test/inheritance/parent.xml
@@ -0,0 +1,7 @@
+<!-- Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -->
+<query-profile id="parent">
+ <field name="a.b">a.b-parent</field>
+ <field name="a.b.c">a.b.c-parent</field>
+ <field name="d">d-parent</field>
+ <field name="d.e.f">d.e.f-parent</field>
+</query-profile>
diff --git a/container-search/src/test/java/com/yahoo/search/query/profile/config/test/newscase4/default.xml b/container-search/src/test/java/com/yahoo/search/query/profile/config/test/newscase4/default.xml
index 07e0f9dda31..1366de00813 100644
--- a/container-search/src/test/java/com/yahoo/search/query/profile/config/test/newscase4/default.xml
+++ b/container-search/src/test/java/com/yahoo/search/query/profile/config/test/newscase4/default.xml
@@ -9,7 +9,7 @@
<query-profile for="parent" inherits="parent" />
<query-profile for="parent,child" >
- <field name="ranking.features">0.1</field>
+ <field name="ranking.features.foo">0.1</field>
</query-profile>
</query-profile>
diff --git a/container-search/src/test/java/com/yahoo/search/query/profile/config/test/newscase4/parent.xml b/container-search/src/test/java/com/yahoo/search/query/profile/config/test/newscase4/parent.xml
index d35642b9ddd..9fe0ee85dae 100644
--- a/container-search/src/test/java/com/yahoo/search/query/profile/config/test/newscase4/parent.xml
+++ b/container-search/src/test/java/com/yahoo/search/query/profile/config/test/newscase4/parent.xml
@@ -1,5 +1,5 @@
<?xml version="1.0"?>
<!-- Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -->
<query-profile id="parent">
- <field name="ranking.features">0.0</field>
+ <field name="ranking.features.foo">0.0</field>
</query-profile>
diff --git a/container-search/src/test/java/com/yahoo/search/query/profile/config/test/tensortypes/profile1.xml b/container-search/src/test/java/com/yahoo/search/query/profile/config/test/tensortypes/profile1.xml
index 000fd3e1c5b..d75961fb584 100644
--- a/container-search/src/test/java/com/yahoo/search/query/profile/config/test/tensortypes/profile1.xml
+++ b/container-search/src/test/java/com/yahoo/search/query/profile/config/test/tensortypes/profile1.xml
@@ -1,2 +1,3 @@
+<!-- Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -->
<query-profile id="profile1" type="type1">
</query-profile>
diff --git a/container-search/src/test/java/com/yahoo/search/query/profile/config/test/tensortypes/profile2.xml b/container-search/src/test/java/com/yahoo/search/query/profile/config/test/tensortypes/profile2.xml
index f6539da23e8..e08362043d2 100644
--- a/container-search/src/test/java/com/yahoo/search/query/profile/config/test/tensortypes/profile2.xml
+++ b/container-search/src/test/java/com/yahoo/search/query/profile/config/test/tensortypes/profile2.xml
@@ -1,2 +1,3 @@
+<!-- Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -->
<query-profile id="profile2" type="type2">
</query-profile>
diff --git a/container-search/src/test/java/com/yahoo/search/query/profile/config/test/tensortypes/types/type1.xml b/container-search/src/test/java/com/yahoo/search/query/profile/config/test/tensortypes/types/type1.xml
index 3dfaab9c5f2..33a223d026b 100644
--- a/container-search/src/test/java/com/yahoo/search/query/profile/config/test/tensortypes/types/type1.xml
+++ b/container-search/src/test/java/com/yahoo/search/query/profile/config/test/tensortypes/types/type1.xml
@@ -1,3 +1,4 @@
+<!-- Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -->
<query-profile-type id="type1">
<field name="ranking.features.query(tensor_1)" type="tensor&lt;float&gt;(x[1])" />
</query-profile-type>
diff --git a/container-search/src/test/java/com/yahoo/search/query/profile/config/test/tensortypes/types/type2.xml b/container-search/src/test/java/com/yahoo/search/query/profile/config/test/tensortypes/types/type2.xml
index ed7cf23e464..a856ddddb91 100644
--- a/container-search/src/test/java/com/yahoo/search/query/profile/config/test/tensortypes/types/type2.xml
+++ b/container-search/src/test/java/com/yahoo/search/query/profile/config/test/tensortypes/types/type2.xml
@@ -1,3 +1,4 @@
+<!-- Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -->
<query-profile-type id="type2">
<field name="ranking.features.query(tensor_2)" type="tensor&lt;float&gt;(x[2])" />
<field name="ranking.features.query(tensor_3)" type="tensor&lt;float&gt;(x[3])" />
diff --git a/container-search/src/test/java/com/yahoo/search/query/profile/config/test/typed/components.cfg b/container-search/src/test/java/com/yahoo/search/query/profile/config/test/typed/components.cfg
index a047ae1cb73..04dcbb22d5d 100644
--- a/container-search/src/test/java/com/yahoo/search/query/profile/config/test/typed/components.cfg
+++ b/container-search/src/test/java/com/yahoo/search/query/profile/config/test/typed/components.cfg
@@ -10,3 +10,4 @@ components[3].classId com.yahoo.search.query.profile.config.test.QueryProfileInt
components[4].id com.yahoo.search.handler.SearchHandler
components[5].id com.yahoo.container.core.config.HandlersConfigurerDi$RegistriesHack
components[6].id com.yahoo.search.searchchain.ExecutionFactory
+components[7].id com.yahoo.search.query.profile.compiled.CompiledQueryProfileRegistry
diff --git a/container-search/src/test/java/com/yahoo/search/query/profile/config/test/untyped/components.cfg b/container-search/src/test/java/com/yahoo/search/query/profile/config/test/untyped/components.cfg
index ef9d4490a77..b5bc450ec17 100644
--- a/container-search/src/test/java/com/yahoo/search/query/profile/config/test/untyped/components.cfg
+++ b/container-search/src/test/java/com/yahoo/search/query/profile/config/test/untyped/components.cfg
@@ -10,3 +10,4 @@ components[3].classId com.yahoo.search.query.profile.config.test.QueryProfileInt
components[4].id com.yahoo.search.handler.SearchHandler
components[5].id com.yahoo.container.core.config.HandlersConfigurerDi$RegistriesHack
components[6].id com.yahoo.search.searchchain.ExecutionFactory
+components[7].id com.yahoo.search.query.profile.compiled.CompiledQueryProfileRegistry
diff --git a/container-search/src/test/java/com/yahoo/search/query/profile/config/test/variants/default.xml b/container-search/src/test/java/com/yahoo/search/query/profile/config/test/variants/default.xml
new file mode 100644
index 00000000000..3cebc84a042
--- /dev/null
+++ b/container-search/src/test/java/com/yahoo/search/query/profile/config/test/variants/default.xml
@@ -0,0 +1,5 @@
+<!-- Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -->
+<query-profile id="default">
+ <dimensions>d1</dimensions>
+ <field name="a.b"><ref>main</ref></field>
+</query-profile>
diff --git a/container-search/src/test/java/com/yahoo/search/query/profile/config/test/variants/inherited.xml b/container-search/src/test/java/com/yahoo/search/query/profile/config/test/variants/inherited.xml
new file mode 100644
index 00000000000..819c9774a02
--- /dev/null
+++ b/container-search/src/test/java/com/yahoo/search/query/profile/config/test/variants/inherited.xml
@@ -0,0 +1,11 @@
+<!-- Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -->
+<query-profile id="inherited">
+ <dimensions>d2</dimensions>
+
+ <field name="c">a.b.c-value</field>
+
+ <query-profile for="d2v">
+ <field name="c" overridable="false">a.b.c-variant-value</field>
+ </query-profile>
+
+</query-profile>
diff --git a/container-search/src/test/java/com/yahoo/search/query/profile/config/test/variants/main.xml b/container-search/src/test/java/com/yahoo/search/query/profile/config/test/variants/main.xml
new file mode 100644
index 00000000000..464d9261307
--- /dev/null
+++ b/container-search/src/test/java/com/yahoo/search/query/profile/config/test/variants/main.xml
@@ -0,0 +1,5 @@
+<!-- Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -->
+<query-profile id="main">
+ <dimensions>d1</dimensions>
+ <query-profile for="d1v" inherits="inherited" />
+</query-profile>
diff --git a/container-search/src/test/java/com/yahoo/search/query/profile/test/QueryProfileSubstitutionTestCase.java b/container-search/src/test/java/com/yahoo/search/query/profile/test/QueryProfileSubstitutionTestCase.java
index b3b83b9c07e..4720b92848a 100644
--- a/container-search/src/test/java/com/yahoo/search/query/profile/test/QueryProfileSubstitutionTestCase.java
+++ b/container-search/src/test/java/com/yahoo/search/query/profile/test/QueryProfileSubstitutionTestCase.java
@@ -54,7 +54,7 @@ public class QueryProfileSubstitutionTestCase {
fail("Expected exception");
}
catch (IllegalArgumentException e) {
- assertEquals("Invalid query profile 'test': Could not resolve local substitution 'world' in variant DimensionBinding []",
+ assertEquals("Invalid query profile 'test': Could not resolve local substitution 'world' in variant []",
Exceptions.toMessageString(e));
}
}
diff --git a/container-search/src/test/java/com/yahoo/search/query/profile/test/QueryProfileTestCase.java b/container-search/src/test/java/com/yahoo/search/query/profile/test/QueryProfileTestCase.java
index bda191ee910..5598ae65990 100644
--- a/container-search/src/test/java/com/yahoo/search/query/profile/test/QueryProfileTestCase.java
+++ b/container-search/src/test/java/com/yahoo/search/query/profile/test/QueryProfileTestCase.java
@@ -6,6 +6,7 @@ import com.yahoo.container.jdisc.HttpRequest;
import com.yahoo.processing.request.CompoundName;
import com.yahoo.processing.request.Properties;
import com.yahoo.search.Query;
+import com.yahoo.search.query.profile.DimensionValues;
import com.yahoo.search.query.profile.QueryProfile;
import com.yahoo.search.query.profile.QueryProfileProperties;
import com.yahoo.search.query.profile.QueryProfileRegistry;
@@ -331,7 +332,7 @@ public class QueryProfileTestCase {
public void testInstanceOverridable() {
QueryProfile profile = new QueryProfile("root/unoverridableIndex");
profile.set("model.defaultIndex","default", null);
- profile.setOverridable("model.defaultIndex", false,null);
+ profile.setOverridable("model.defaultIndex", false, DimensionValues.empty);
assertFalse(profile.isDeclaredOverridable("model.defaultIndex",null));
@@ -351,7 +352,7 @@ public class QueryProfileTestCase {
QueryProfile profile = new QueryProfile("root/unoverridableIndex");
profile.setDimensions(new String[] {"x"});
profile.set("model.defaultIndex","default", null);
- profile.setOverridable("model.defaultIndex",false,null);
+ profile.setOverridable("model.defaultIndex", false, DimensionValues.empty);
assertFalse(profile.isDeclaredOverridable("model.defaultIndex",null));
@@ -370,7 +371,7 @@ public class QueryProfileTestCase {
QueryProfile profile=new QueryProfile("test");
profile.setDimensions(new String[] {"x"});
profile.set("a","original", null);
- profile.setOverridable("a",false,null);
+ profile.setOverridable("a", false, DimensionValues.empty);
assertFalse(profile.isDeclaredOverridable("a",null));
@@ -380,12 +381,12 @@ public class QueryProfileTestCase {
@Test
public void testSimpleInstanceOverridableWithVariants2() {
- QueryProfile profile=new QueryProfile("test");
+ QueryProfile profile = new QueryProfile("test");
profile.setDimensions(new String[] {"x"});
- profile.set("a","original",new String[] {"x1"}, null);
- profile.setOverridable("a",false,null);
+ profile.set("a", "original", new String[] {"x1"}, null);
+ profile.setOverridable("a", false, DimensionValues.empty);
- assertFalse(profile.isDeclaredOverridable("a",null));
+ assertFalse(profile.isDeclaredOverridable("a", null));
Query query = new Query(HttpRequest.createTestRequest("?x=x1&a=overridden", Method.GET), profile.compile(null));
assertEquals("original",query.properties().get("a"));
@@ -504,7 +505,8 @@ public class QueryProfileTestCase {
p.set("a","a-value", null);
p.set("a.b","a.b-value", null);
Map<String, Object> values = p.compile(null).listValues("a");
- assertEquals(1, values.size());
+ assertEquals(2, values.size());
+ p.set("a","a-value", null);
assertEquals("a.b-value", values.get("b"));
}
diff --git a/container-search/src/test/java/com/yahoo/search/query/profile/test/QueryProfileVariantsTestCase.java b/container-search/src/test/java/com/yahoo/search/query/profile/test/QueryProfileVariantsTestCase.java
index 7d3bec7cc9e..a592d40d2e9 100644
--- a/container-search/src/test/java/com/yahoo/search/query/profile/test/QueryProfileVariantsTestCase.java
+++ b/container-search/src/test/java/com/yahoo/search/query/profile/test/QueryProfileVariantsTestCase.java
@@ -10,10 +10,10 @@ import com.yahoo.search.query.profile.BackedOverridableQueryProfile;
import com.yahoo.search.query.profile.QueryProfile;
import com.yahoo.search.query.profile.QueryProfileProperties;
import com.yahoo.search.query.profile.QueryProfileRegistry;
+import com.yahoo.search.query.profile.QueryProfileVariant;
import com.yahoo.search.query.profile.compiled.CompiledQueryProfile;
import com.yahoo.search.query.profile.compiled.CompiledQueryProfileRegistry;
import com.yahoo.search.query.profile.compiled.ValueWithSource;
-import com.yahoo.yolean.trace.TraceNode;
import org.junit.Ignore;
import org.junit.Test;
@@ -24,6 +24,7 @@ import java.util.Map;
import java.util.stream.Collectors;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
/**
@@ -75,6 +76,87 @@ public class QueryProfileVariantsTestCase {
}
@Test
+ public void testReferenceInVariant() {
+ QueryProfileRegistry registry = new QueryProfileRegistry();
+ QueryProfile test = new QueryProfile("test");
+ test.setDimensions(new String[] { "d1" });
+ registry.register(test);
+
+ QueryProfile references = new QueryProfile("referenced");
+ references.setDimensions(new String[] { "d1" });
+ registry.register(references);
+
+ QueryProfile other = new QueryProfile("other");
+ other.setDimensions(new String[] { "d1" });
+ registry.register(other);
+
+ test.set( "a", references, new String[] { "d1v"}, registry);
+ test.set( "a.b", "test-value", new String[] { "d1v"}, registry);
+ other.set( "a", references, new String[] { "d1v"}, registry);
+ other.set("a.b", "other-value", new String[] { "d1v"}, registry);
+
+ assertEquals("test-value", test.get("a.b", new String[] { "d1v"}));
+ assertEquals("other-value", other.get("a.b", new String[] { "d1v"}));
+ assertNull(references.get("b", new String[] { "d1v"}));
+
+ var cRegistry = registry.compile();
+ assertEquals("test-value",
+ cRegistry.getComponent("test").get("a.b", Map.of("d1", "d1v")));
+ }
+
+ /**
+ * Tests referencing a variant which modifies the dimension set,
+ * and also setting a value within that variants subspace.
+ */
+ @Test
+ public void testVariantReference() {
+ QueryProfileRegistry registry = new QueryProfileRegistry();
+
+ QueryProfile parent = new QueryProfile("parent");
+ parent.set("b", 48, registry);
+ registry.register(parent);
+
+ QueryProfile referenced = new QueryProfile("referenced");
+ referenced.addInherited(parent);
+ referenced.setDimensions(new String[] {"d2", "d3"});
+ registry.register(referenced);
+
+ QueryProfile base = new QueryProfile("base");
+ base.setDimensions(new String[]{"d1", "d2", "d3"});
+ base.set("a", referenced, new String[] {null, null, "d3-val"}, registry);
+ assertEquals("Variant dimensions are not overridden by the referenced dimensions",
+ "[d1, d2, d3]",
+ ((QueryProfile)base.getVariants().getVariants().get(0).values().get("a")).getDimensions().toString());
+ base.set("a.b", 1, new String[] {null, null, "d3-val"}, registry);
+ QueryProfileVariant aVariants = base.getVariants().getVariants().get(0);
+ assertEquals("Variant dimensions are not overridden by the referenced dimensions",
+ "[d1, d2, d3]",
+ ((QueryProfile)base.getVariants().getVariants().get(0).values().get("a")).getDimensions().toString());
+ }
+
+ @Test
+ public void testReference() {
+ QueryProfileRegistry registry = new QueryProfileRegistry();
+ QueryProfile test = new QueryProfile("test");
+ registry.register(test);
+
+ QueryProfile references = new QueryProfile("referenced");
+ registry.register(references);
+
+ QueryProfile other = new QueryProfile("other");
+ registry.register(other);
+
+ test.set( "a", references, registry);
+ test.set( "a.b", "test-value", registry);
+ other.set( "a", references, registry);
+ other.set("a.b", "other-value", registry);
+
+ assertEquals("test-value", test.get("a.b"));
+ assertEquals("other-value", other.get("a.b"));
+ assertNull(references.get("b"));
+ }
+
+ @Test
public void testVariantInReferencedAndParentWithOtherMatchingVariant() {
QueryProfileRegistry registry = new QueryProfileRegistry();
QueryProfile parent = new QueryProfile("parent");
diff --git a/container-search/src/test/java/com/yahoo/search/query/profile/types/test/MandatoryTestCase.java b/container-search/src/test/java/com/yahoo/search/query/profile/types/test/MandatoryTestCase.java
index 7dc6eb3d8aa..b875c66735b 100644
--- a/container-search/src/test/java/com/yahoo/search/query/profile/types/test/MandatoryTestCase.java
+++ b/container-search/src/test/java/com/yahoo/search/query/profile/types/test/MandatoryTestCase.java
@@ -230,7 +230,6 @@ public class MandatoryTestCase {
defaultProfile.setType(fixture.rootType);
QueryProfile mandatoryProfile = new QueryProfile("mandatory");
- mandatoryProfile.setType(fixture.rootType);
mandatoryProfile.setType(fixture.mandatoryType);
fixture.registry.register(defaultProfile);
@@ -249,7 +248,6 @@ public class MandatoryTestCase {
defaultProfile.setType(fixture.rootType);
QueryProfile mandatoryProfile = new QueryProfile("mandatory");
- mandatoryProfile.setType(fixture.rootType);
mandatoryProfile.addInherited(defaultProfile); // The single difference from the test above
mandatoryProfile.setType(fixture.mandatoryType);
diff --git a/container-search/src/test/java/com/yahoo/search/query/profile/types/test/NativePropertiesTestCase.java b/container-search/src/test/java/com/yahoo/search/query/profile/types/test/NativePropertiesTestCase.java
index 224b0c82339..2ced2ba9323 100644
--- a/container-search/src/test/java/com/yahoo/search/query/profile/types/test/NativePropertiesTestCase.java
+++ b/container-search/src/test/java/com/yahoo/search/query/profile/types/test/NativePropertiesTestCase.java
@@ -3,7 +3,6 @@ package com.yahoo.search.query.profile.types.test;
import com.yahoo.jdisc.http.HttpRequest.Method;
import com.yahoo.container.jdisc.HttpRequest;
-import com.yahoo.prelude.query.QueryException;
import com.yahoo.search.Query;
import com.yahoo.search.query.profile.QueryProfile;
import com.yahoo.search.query.profile.types.QueryProfileType;
@@ -23,22 +22,22 @@ public class NativePropertiesTestCase {
@Test
public void testNativeInStrict() {
- QueryProfileType strictType=new QueryProfileType("strict");
+ QueryProfileType strictType = new QueryProfileType("strict");
strictType.setStrict(true);
- QueryProfile strict=new QueryProfile("profile");
+ QueryProfile strict = new QueryProfile("profile");
strict.setType(strictType);
try {
new Query(HttpRequest.createTestRequest("?hits=10&tracelevel=5", Method.GET), strict.compile(null));
fail("Above statement should throw");
- } catch (QueryException e) {
+ } catch (IllegalArgumentException e) {
// As expected.
}
try {
new Query(HttpRequest.createTestRequest("?notnative=5", Method.GET), strict.compile(null));
fail("Above statement should throw");
- } catch (QueryException e) {
+ } catch (IllegalArgumentException e) {
// As expected.
assertThat(
Exceptions.toMessageString(e),
diff --git a/container-search/src/test/java/com/yahoo/search/query/profile/types/test/OverrideTestCase.java b/container-search/src/test/java/com/yahoo/search/query/profile/types/test/OverrideTestCase.java
index aa6049a45ec..c0f1dfeca0b 100644
--- a/container-search/src/test/java/com/yahoo/search/query/profile/types/test/OverrideTestCase.java
+++ b/container-search/src/test/java/com/yahoo/search/query/profile/types/test/OverrideTestCase.java
@@ -5,6 +5,7 @@ import com.yahoo.jdisc.http.HttpRequest.Method;
import com.yahoo.container.jdisc.HttpRequest;
import com.yahoo.component.ComponentId;
import com.yahoo.search.Query;
+import com.yahoo.search.query.profile.DimensionValues;
import com.yahoo.search.query.profile.QueryProfile;
import com.yahoo.search.query.profile.QueryProfileRegistry;
import com.yahoo.search.query.profile.compiled.CompiledQueryProfileRegistry;
@@ -168,7 +169,7 @@ public class OverrideTestCase {
QueryProfile test = new QueryProfile("test");
test.setType(type);
test.set("myInteger", 1, registry);
- test.setOverridable("myInteger", false, null);
+ test.setOverridable("myInteger", false, DimensionValues.empty);
registry.register(test);
QueryProfile profile=new QueryProfile("profile");
diff --git a/container-search/src/test/java/com/yahoo/search/query/profile/types/test/QueryProfileTypeTestCase.java b/container-search/src/test/java/com/yahoo/search/query/profile/types/test/QueryProfileTypeTestCase.java
index 3c200debcaf..e22263070e0 100644
--- a/container-search/src/test/java/com/yahoo/search/query/profile/types/test/QueryProfileTypeTestCase.java
+++ b/container-search/src/test/java/com/yahoo/search/query/profile/types/test/QueryProfileTypeTestCase.java
@@ -3,8 +3,10 @@ package com.yahoo.search.query.profile.types.test;
import com.yahoo.component.ComponentId;
import com.yahoo.container.jdisc.HttpRequest;
-import com.yahoo.prelude.query.QueryException;
+import com.yahoo.language.Language;
+import com.yahoo.language.process.Embedder;
import com.yahoo.tensor.Tensor;
+import com.yahoo.tensor.TensorType;
import com.yahoo.yolean.Exceptions;
import com.yahoo.search.Query;
import com.yahoo.processing.request.CompoundName;
@@ -20,8 +22,9 @@ import com.yahoo.search.query.profile.types.QueryProfileTypeRegistry;
import org.junit.Before;
import org.junit.Test;
-import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
import static org.hamcrest.CoreMatchers.containsString;
import static org.junit.Assert.assertEquals;
@@ -39,29 +42,32 @@ public class QueryProfileTypeTestCase {
private QueryProfileRegistry registry;
- private QueryProfileType type, typeStrict, user, userStrict;
+ private QueryProfileType testtype, emptyInheritingTesttype, testtypeStrict, user, userStrict;
@Before
public void setUp() {
registry = new QueryProfileRegistry();
- type = new QueryProfileType(new ComponentId("testtype"));
- type.inherited().add(registry.getTypeRegistry().getComponent(new ComponentId("native")));
- typeStrict = new QueryProfileType(new ComponentId("testtypeStrict"));
- typeStrict.setStrict(true);
+ testtype = new QueryProfileType(new ComponentId("testtype"));
+ testtype.inherited().add(registry.getTypeRegistry().getComponent(new ComponentId("native")));
+ emptyInheritingTesttype = new QueryProfileType(new ComponentId("emptyInheritingTesttype"));
+ emptyInheritingTesttype.inherited().add(testtype);
+ testtypeStrict = new QueryProfileType(new ComponentId("testtypeStrict"));
+ testtypeStrict.setStrict(true);
user = new QueryProfileType(new ComponentId("user"));
userStrict = new QueryProfileType(new ComponentId("userStrict"));
userStrict.setStrict(true);
- registry.getTypeRegistry().register(type);
- registry.getTypeRegistry().register(typeStrict);
+ registry.getTypeRegistry().register(testtype);
+ registry.getTypeRegistry().register(emptyInheritingTesttype);
+ registry.getTypeRegistry().register(testtypeStrict);
registry.getTypeRegistry().register(user);
registry.getTypeRegistry().register(userStrict);
- addTypeFields(type, registry.getTypeRegistry());
- type.addField(new FieldDescription("myUserQueryProfile", FieldType.fromString("query-profile:user", registry.getTypeRegistry())));
- addTypeFields(typeStrict, registry.getTypeRegistry());
- typeStrict.addField(new FieldDescription("myUserQueryProfile", FieldType.fromString("query-profile:userStrict", registry.getTypeRegistry())));
+ addTypeFields(testtype, registry.getTypeRegistry());
+ testtype.addField(new FieldDescription("myUserQueryProfile", FieldType.fromString("query-profile:user", registry.getTypeRegistry())));
+ addTypeFields(testtypeStrict, registry.getTypeRegistry());
+ testtypeStrict.addField(new FieldDescription("myUserQueryProfile", FieldType.fromString("query-profile:userStrict", registry.getTypeRegistry())));
addUserFields(user, registry.getTypeRegistry());
addUserFields(userStrict, registry.getTypeRegistry());
@@ -78,6 +84,7 @@ public class QueryProfileTypeTestCase {
type.addField(new FieldDescription("ranking.features.query(myTensor1)", FieldType.fromString("tensor(a{},b{})", registry)), registry);
type.addField(new FieldDescription("ranking.features.query(myTensor2)", FieldType.fromString("tensor(x[2],y[2])", registry)), registry);
type.addField(new FieldDescription("ranking.features.query(myTensor3)", FieldType.fromString("tensor<float>(x{})",registry)), registry);
+ type.addField(new FieldDescription("ranking.features.query(myTensor4)", FieldType.fromString("tensor<float>(x[5])",registry)), registry);
type.addField(new FieldDescription("myQuery", FieldType.fromString("query", registry)), registry);
type.addField(new FieldDescription("myQueryProfile", FieldType.fromString("query-profile", registry),"qp"), registry);
}
@@ -90,7 +97,7 @@ public class QueryProfileTypeTestCase {
@Test
public void testTypedOfPrimitivesAssignmentNonStrict() {
QueryProfile profile=new QueryProfile("test");
- profile.setType(type);
+ profile.setType(testtype);
registry.register(profile);
profile.set("myString","anyValue", registry);
@@ -100,7 +107,7 @@ public class QueryProfileTypeTestCase {
profile.set("myInteger", 3, registry);
assertWrongType(profile,"long","myLong","notLong");
assertWrongType(profile, "long", "myLong", "1.5");
- profile.set("myLong", 4000000000000l, registry);
+ profile.set("myLong", 4000000000000L, registry);
assertWrongType(profile, "float", "myFloat", "notFloat");
profile.set("myFloat", 3.14f, registry);
assertWrongType(profile, "double", "myDouble", "notDouble");
@@ -157,7 +164,7 @@ public class QueryProfileTypeTestCase {
@Test
public void testTypedOfPrimitivesAssignmentStrict() {
QueryProfile profile=new QueryProfile("test");
- profile.setType(typeStrict);
+ profile.setType(testtypeStrict);
profile.set("myString", "anyValue", registry);
assertNotPermitted(profile, "nontypedString", "anyValueToo"); // Illegal because this is strict
@@ -199,7 +206,7 @@ public class QueryProfileTypeTestCase {
@Test
public void testTypedAssignmentOfQueryProfilesNonStrict() {
QueryProfile profile=new QueryProfile("test");
- profile.setType(type);
+ profile.setType(testtype);
QueryProfile map1=new QueryProfile("myMap1");
map1.set("key1","value1", registry);
@@ -230,7 +237,7 @@ public class QueryProfileTypeTestCase {
@Test
public void testTypedAssignmentOfQueryProfilesStrict() {
QueryProfile profile=new QueryProfile("test");
- profile.setType(typeStrict);
+ profile.setType(testtypeStrict);
QueryProfile map1=new QueryProfile("myMap1");
map1.set("key1","value1", registry);
@@ -261,7 +268,7 @@ public class QueryProfileTypeTestCase {
@Test
public void testTypedAssignmentOfQueryProfileReferencesNonStrict() {
QueryProfile profile = new QueryProfile("test");
- profile.setType(type);
+ profile.setType(testtype);
QueryProfile map1 = new QueryProfile("myMap1");
map1.set("key1","value1", registry);
@@ -305,7 +312,7 @@ public class QueryProfileTypeTestCase {
@Test
public void testTypedOverridingOfQueryProfileReferencesNonStrictThroughQuery() {
QueryProfile profile=new QueryProfile("test");
- profile.setType(type);
+ profile.setType(testtype);
QueryProfile myUser=new QueryProfile("myUser");
myUser.setType(user);
@@ -338,20 +345,22 @@ public class QueryProfileTypeTestCase {
*/
@Test
public void testTypedAssignmentOfQueryProfileReferencesNonStrictThroughQuery() {
- QueryProfile profile=new QueryProfile("test");
- profile.setType(type);
+ QueryProfile profile = new QueryProfile("test");
+ profile.setType(testtype);
- QueryProfile newUser=new QueryProfile("newUser");
+ QueryProfile newUser = new QueryProfile("newUser");
newUser.setType(user);
- newUser.set("myUserString","newUserValue1", registry);
- newUser.set("myUserInteger",845, registry);
+ newUser.set("myUserString", "newUserValue1", registry);
+ newUser.set("myUserInteger", 845, registry);
registry.register(profile);
registry.register(newUser);
CompiledQueryProfileRegistry cRegistry = registry.compile();
CompiledQueryProfile cprofile = cRegistry.getComponent("test");
- Query query = new Query(HttpRequest.createTestRequest("?myUserQueryProfile=newUser", com.yahoo.jdisc.http.HttpRequest.Method.GET), cprofile);
+ Query query = new Query(HttpRequest.createTestRequest("?myUserQueryProfile=newUser",
+ com.yahoo.jdisc.http.HttpRequest.Method.GET),
+ cprofile);
assertEquals(0, query.errors().size());
@@ -365,13 +374,13 @@ public class QueryProfileTypeTestCase {
*/
@Test
public void testTypedAssignmentOfQueryProfileReferencesStrictThroughQuery() {
- QueryProfile profile=new QueryProfile("test");
- profile.setType(typeStrict);
+ QueryProfile profile = new QueryProfile("test");
+ profile.setType(testtypeStrict);
- QueryProfile newUser=new QueryProfile("newUser");
+ QueryProfile newUser = new QueryProfile("newUser");
newUser.setType(userStrict);
- newUser.set("myUserString","newUserValue1", registry);
- newUser.set("myUserInteger",845, registry);
+ newUser.set("myUserString", "newUserValue1", registry);
+ newUser.set("myUserInteger", 845, registry);
registry.register(profile);
registry.register(newUser);
@@ -381,11 +390,11 @@ public class QueryProfileTypeTestCase {
Query query = new Query(HttpRequest.createTestRequest("?myUserQueryProfile=newUser", com.yahoo.jdisc.http.HttpRequest.Method.GET), cRegistry.getComponent("test"));
assertEquals(0, query.errors().size());
- assertEquals("newUserValue1",query.properties().get("myUserQueryProfile.myUserString"));
- assertEquals(845,query.properties().get("myUserQueryProfile.myUserInteger"));
+ assertEquals("newUserValue1", query.properties().get("myUserQueryProfile.myUserString"));
+ assertEquals(845, query.properties().get("myUserQueryProfile.myUserInteger"));
try {
- query.properties().set("myUserQueryProfile.someKey","value");
+ query.properties().set("myUserQueryProfile.someKey", "value");
fail("Should not be allowed to set this");
}
catch (IllegalArgumentException e) {
@@ -396,47 +405,96 @@ public class QueryProfileTypeTestCase {
}
@Test
- public void testTensorRankFeatureInRequest() throws UnsupportedEncodingException {
+ public void testTensorRankFeatureInRequest() {
QueryProfile profile = new QueryProfile("test");
- profile.setType(type);
+ profile.setType(testtype);
registry.register(profile);
CompiledQueryProfileRegistry cRegistry = registry.compile();
String tensorString = "{{a:a1, b:b1}:1.0, {a:a2, b:b1}:2.0}}";
- Query query = new Query(HttpRequest.createTestRequest("?" + encode("ranking.features.query(myTensor1)") +
- "=" + encode(tensorString),
- com.yahoo.jdisc.http.HttpRequest.Method.GET), cRegistry.getComponent("test"));
+ Query query = new Query(HttpRequest.createTestRequest("?" + urlEncode("ranking.features.query(myTensor1)") +
+ "=" + urlEncode(tensorString),
+ com.yahoo.jdisc.http.HttpRequest.Method.GET),
+ cRegistry.getComponent("test"));
assertEquals(0, query.errors().size());
assertEquals(Tensor.from(tensorString), query.properties().get("ranking.features.query(myTensor1)"));
assertEquals(Tensor.from(tensorString), query.getRanking().getFeatures().getTensor("query(myTensor1)").get());
}
- private String encode(String s) throws UnsupportedEncodingException {
- return URLEncoder.encode(s, "utf8");
+ // Expected to work exactly as testTensorRankFeatureInRequest
+ @Test
+ public void testTensorRankFeatureInRequestWithInheritedQueryProfileType() {
+ QueryProfile profile = new QueryProfile("test");
+ profile.setType(emptyInheritingTesttype);
+ registry.register(profile);
+
+ CompiledQueryProfileRegistry cRegistry = registry.compile();
+ String tensorString = "{{a:a1, b:b1}:1.0, {a:a2, b:b1}:2.0}}";
+ Query query = new Query(HttpRequest.createTestRequest("?" + urlEncode("ranking.features.query(myTensor1)") +
+ "=" + urlEncode(tensorString),
+ com.yahoo.jdisc.http.HttpRequest.Method.GET),
+ cRegistry.getComponent("test"));
+ assertEquals(0, query.errors().size());
+ assertEquals(Tensor.from(tensorString), query.properties().get("ranking.features.query(myTensor1)"));
+ assertEquals(Tensor.from(tensorString), query.getRanking().getFeatures().getTensor("query(myTensor1)").get());
+ }
+
+ @Test
+ public void testUnembeddedTensorRankFeatureInRequest() {
+ QueryProfile profile = new QueryProfile("test");
+ profile.setType(testtype);
+ registry.register(profile);
+
+ CompiledQueryProfileRegistry cRegistry = registry.compile();
+ String textToEmbed = "text to embed into a tensor";
+ Tensor expectedTensor = Tensor.from("tensor<float>(x[5]):[3,7,4,0,0]]");
+ Query query1 = new Query.Builder().setRequest(HttpRequest.createTestRequest("?" + urlEncode("ranking.features.query(myTensor4)") +
+ "=" + urlEncode("embed(" + textToEmbed + ")"),
+ com.yahoo.jdisc.http.HttpRequest.Method.GET))
+ .setQueryProfile(cRegistry.getComponent("test"))
+ .setEmbedder(new MockEmbedder(textToEmbed, Language.UNKNOWN, expectedTensor))
+ .build();
+ assertEquals(0, query1.errors().size());
+ assertEquals(expectedTensor, query1.properties().get("ranking.features.query(myTensor4)"));
+ assertEquals(expectedTensor, query1.getRanking().getFeatures().getTensor("query(myTensor4)").get());
+
+ // Explicit language
+ Query query2 = new Query.Builder().setRequest(HttpRequest.createTestRequest("?" + urlEncode("ranking.features.query(myTensor4)") +
+ "=" + urlEncode("embed(" + textToEmbed + ")") +
+ "&language=en",
+ com.yahoo.jdisc.http.HttpRequest.Method.GET))
+ .setQueryProfile(cRegistry.getComponent("test"))
+ .setEmbedder(new MockEmbedder(textToEmbed, Language.ENGLISH, expectedTensor))
+ .build();
+ assertEquals(0, query2.errors().size());
+ assertEquals(expectedTensor, query2.properties().get("ranking.features.query(myTensor4)"));
+ assertEquals(expectedTensor, query2.getRanking().getFeatures().getTensor("query(myTensor4)").get());
+
+ }
+
+ private String urlEncode(String s) {
+ return URLEncoder.encode(s, StandardCharsets.UTF_8);
}
@Test
public void testIllegalStrictAssignmentFromRequest() {
- QueryProfile profile=new QueryProfile("test");
- profile.setType(typeStrict);
+ QueryProfile profile = new QueryProfile("test");
+ profile.setType(testtypeStrict);
- QueryProfile newUser=new QueryProfile("newUser");
+ QueryProfile newUser = new QueryProfile("newUser");
newUser.setType(userStrict);
profile.set("myUserQueryProfile", newUser, registry);
try {
- new Query(
- HttpRequest.createTestRequest(
- "?myUserQueryProfile.nondeclared=someValue",
- com.yahoo.jdisc.http.HttpRequest.Method.GET),
- profile.compile(null));
+ new Query(HttpRequest.createTestRequest("?myUserQueryProfile.nondeclared=someValue",
+ com.yahoo.jdisc.http.HttpRequest.Method.GET),
+ profile.compile(null));
fail("Above statement should throw");
- } catch (QueryException e) {
+ } catch (IllegalArgumentException e) {
// As expected.
- assertThat(
- Exceptions.toMessageString(e),
- containsString("Could not set 'myUserQueryProfile.nondeclared' to 'someValue': 'nondeclared' is not declared in query profile type 'userStrict', and the type is strict"));
+ assertThat(Exceptions.toMessageString(e),
+ containsString("Could not set 'myUserQueryProfile.nondeclared' to 'someValue': 'nondeclared' is not declared in query profile type 'userStrict', and the type is strict"));
}
}
@@ -453,7 +511,7 @@ public class QueryProfileTypeTestCase {
topMap.set("subMap", subMap, registry);
QueryProfile test = new QueryProfile("test");
- test.setType(type);
+ test.setType(testtype);
subMap.set("typeProfile", test, registry);
QueryProfile myUser = new QueryProfile("myUser");
@@ -474,7 +532,9 @@ public class QueryProfileTypeTestCase {
registry.register(newUser);
CompiledQueryProfileRegistry cRegistry = registry.compile();
- Query query = new Query(HttpRequest.createTestRequest("?subMap.typeProfile.myUserQueryProfile=newUser", com.yahoo.jdisc.http.HttpRequest.Method.GET), cRegistry.getComponent("topMap"));
+ Query query = new Query(HttpRequest.createTestRequest("?subMap.typeProfile.myUserQueryProfile=newUser",
+ com.yahoo.jdisc.http.HttpRequest.Method.GET),
+ cRegistry.getComponent("topMap"));
assertEquals(0, query.errors().size());
@@ -487,25 +547,25 @@ public class QueryProfileTypeTestCase {
*/
@Test
public void testAnonTypedOverridingOfQueryProfileReferencesNonStrictThroughQueryNestedInAnUntypedProfile() {
- QueryProfile topMap=new QueryProfile("topMap");
+ QueryProfile topMap = new QueryProfile("topMap");
- QueryProfile subMap=new QueryProfile("topSubMap");
- topMap.set("subMap",subMap, registry);
+ QueryProfile subMap = new QueryProfile("topSubMap");
+ topMap.set("subMap", subMap, registry);
- QueryProfile test=new QueryProfile("test");
- test.setType(type);
- subMap.set("typeProfile",test, registry);
+ QueryProfile test = new QueryProfile("test");
+ test.setType(testtype);
+ subMap.set("typeProfile", test, registry);
- QueryProfile myUser=new QueryProfile("myUser");
+ QueryProfile myUser = new QueryProfile("myUser");
myUser.setType(user);
- myUser.set("myUserString","userValue1", registry);
- myUser.set("myUserInteger",442, registry);
- test.set("myQueryProfile",myUser, registry);
+ myUser.set("myUserString", "userValue1", registry);
+ myUser.set("myUserInteger", 442, registry);
+ test.set("myQueryProfile", myUser, registry);
- QueryProfile newUser=new QueryProfile("newUser");
+ QueryProfile newUser = new QueryProfile("newUser");
newUser.setType(user);
- newUser.set("myUserString","newUserValue1", registry);
- newUser.set("myUserInteger",845, registry);
+ newUser.set("myUserString", "newUserValue1", registry);
+ newUser.set("myUserInteger", 845, registry);
registry.register(topMap);
registry.register(subMap);
@@ -526,14 +586,14 @@ public class QueryProfileTypeTestCase {
*/
@Test
public void testSettingValueInStrictTypeNestedUnderUntypedMaps() {
- QueryProfile topMap=new QueryProfile("topMap");
+ QueryProfile topMap = new QueryProfile("topMap");
- QueryProfile subMap=new QueryProfile("topSubMap");
- topMap.set("subMap",subMap, registry);
+ QueryProfile subMap = new QueryProfile("topSubMap");
+ topMap.set("subMap", subMap, registry);
- QueryProfile test=new QueryProfile("test");
- test.setType(typeStrict);
- subMap.set("typeProfile",test, registry);
+ QueryProfile test = new QueryProfile("test");
+ test.setType(testtypeStrict);
+ subMap.set("typeProfile", test, registry);
registry.register(topMap);
registry.register(subMap);
@@ -542,16 +602,14 @@ public class QueryProfileTypeTestCase {
try {
new Query(
- HttpRequest.createTestRequest(
- "?subMap.typeProfile.someValue=value",
- com.yahoo.jdisc.http.HttpRequest.Method.GET),
+ HttpRequest.createTestRequest("?subMap.typeProfile.someValue=value",
+ com.yahoo.jdisc.http.HttpRequest.Method.GET),
cRegistry.getComponent("topMap"));
fail("Above statement should throw");
- } catch (QueryException e) {
+ } catch (IllegalArgumentException e) {
// As expected.
- assertThat(
- Exceptions.toMessageString(e),
- containsString("Could not set 'subMap.typeProfile.someValue' to 'value': 'someValue' is not declared in query profile type 'testtypeStrict', and the type is strict"));
+ assertThat(Exceptions.toMessageString(e),
+ containsString("Could not set 'subMap.typeProfile.someValue' to 'value': 'someValue' is not declared in query profile type 'testtypeStrict', and the type is strict"));
}
}
@@ -562,19 +620,19 @@ public class QueryProfileTypeTestCase {
*/
@Test
public void testTypedSettingOfQueryProfileReferencesNonStrictThroughQueryNestedInAnUntypedProfile() {
- QueryProfile topMap=new QueryProfile("topMap");
+ QueryProfile topMap = new QueryProfile("topMap");
- QueryProfile subMap=new QueryProfile("topSubMap");
+ QueryProfile subMap = new QueryProfile("topSubMap");
topMap.set("subMap",subMap, registry);
- QueryProfile test=new QueryProfile("test");
- test.setType(type);
+ QueryProfile test = new QueryProfile("test");
+ test.setType(testtype);
subMap.set("typeProfile",test, registry);
- QueryProfile newUser=new QueryProfile("newUser");
+ QueryProfile newUser = new QueryProfile("newUser");
newUser.setType(user);
- newUser.set("myUserString","newUserValue1", registry);
- newUser.set("myUserInteger",845, registry);
+ newUser.set("myUserString", "newUserValue1", registry);
+ newUser.set("myUserInteger", 845, registry);
registry.register(topMap);
registry.register(subMap);
@@ -582,13 +640,66 @@ public class QueryProfileTypeTestCase {
registry.register(newUser);
CompiledQueryProfileRegistry cRegistry = registry.compile();
- Query query = new Query(HttpRequest.createTestRequest("?subMap.typeProfile.myUserQueryProfile=newUser", com.yahoo.jdisc.http.HttpRequest.Method.GET), cRegistry.getComponent("topMap"));
+ Query query = new Query(HttpRequest.createTestRequest("?subMap.typeProfile.myUserQueryProfile=newUser",
+ com.yahoo.jdisc.http.HttpRequest.Method.GET),
+ cRegistry.getComponent("topMap"));
assertEquals(0, query.errors().size());
assertEquals("newUserValue1", query.properties().get("subMap.typeProfile.myUserQueryProfile.myUserString"));
assertEquals(845, query.properties().get("subMap.typeProfile.myUserQueryProfile.myUserInteger"));
}
+ @Test
+ public void testNestedTypeName() {
+ ComponentId.resetGlobalCountersForTests();
+ QueryProfileRegistry registry = new QueryProfileRegistry();
+ QueryProfileType type = new QueryProfileType("testType");
+ registry.getTypeRegistry().register(type);
+ type.addField(new FieldDescription("ranking.features.query(embedding_profile)",
+ "tensor<float>(model{},x[128])"),
+ registry.getTypeRegistry());
+ QueryProfile test = new QueryProfile("test");
+ registry.register(test);
+ test.setType(type);
+ CompiledQueryProfileRegistry cRegistry = registry.compile();
+ Query query = new Query("?query=foo", cRegistry.getComponent("test"));
+
+ // With a prefix we're not in the built-in type space
+ query.properties().set("prefix.ranking.foo", 0.1);
+ assertEquals(0.1, query.properties().get("prefix.ranking.foo"));
+ }
+
+ @Test
+ public void testNestedTypeNameUsingBuiltInTypes() {
+ ComponentId.resetGlobalCountersForTests();
+ QueryProfileRegistry registry = new QueryProfileRegistry();
+ QueryProfileType type = new QueryProfileType("testType");
+ type.inherited().add(Query.getArgumentType()); // Include native type checking
+ registry.getTypeRegistry().register(type);
+ type.addField(new FieldDescription("ranking.features.query(embedding_profile)",
+ "tensor<float>(model{},x[128])"),
+ registry.getTypeRegistry());
+ QueryProfile test = new QueryProfile("test");
+ registry.register(test);
+ test.setType(type);
+ CompiledQueryProfileRegistry cRegistry = registry.compile();
+ Query query = new Query("?query=foo", cRegistry.getComponent("test"));
+
+ // Cannot set a property in a strict built-in type
+ try {
+ query.properties().set("ranking.foo", 0.1);
+ fail("Expected exception");
+ }
+ catch (IllegalArgumentException e) {
+ assertEquals("'foo' is not a valid property in 'ranking'. See the query api for valid keys starting by 'ranking'.",
+ e.getCause().getMessage());
+ }
+
+ // With a prefix we're not in the built-in type space
+ query.properties().set("prefix.ranking.foo", 0.1);
+ assertEquals(0.1, query.properties().get("prefix.ranking.foo"));
+ }
+
private void assertWrongType(QueryProfile profile,String typeName,String name,Object value) {
try {
profile.set(name,value, registry);
@@ -611,4 +722,34 @@ public class QueryProfileTypeTestCase {
}
}
+ private static final class MockEmbedder implements Embedder {
+
+ private final String expectedText;
+ private final Language expectedLanguage;
+ private final Tensor tensorToReturn;
+
+ public MockEmbedder(String expectedText,
+ Language expectedLanguage,
+ Tensor tensorToReturn) {
+ this.expectedText = expectedText;
+ this.expectedLanguage = expectedLanguage;
+ this.tensorToReturn = tensorToReturn;
+ }
+
+ @Override
+ public List<Integer> embed(String text, Language language) {
+ fail("Unexpected call");
+ return null;
+ }
+
+ @Override
+ public Tensor embed(String text, Language language, TensorType tensorType) {
+ assertEquals(expectedText, text);
+ assertEquals(expectedLanguage, language);
+ assertEquals(tensorToReturn.type(), tensorType);
+ return tensorToReturn;
+ }
+
+ }
+
}
diff --git a/container-search/src/test/java/com/yahoo/search/query/rewrite/RewriterFeaturesTestCase.java b/container-search/src/test/java/com/yahoo/search/query/rewrite/RewriterFeaturesTestCase.java
index 5508c2a73a7..08146bbe069 100644
--- a/container-search/src/test/java/com/yahoo/search/query/rewrite/RewriterFeaturesTestCase.java
+++ b/container-search/src/test/java/com/yahoo/search/query/rewrite/RewriterFeaturesTestCase.java
@@ -8,7 +8,7 @@ import org.junit.Test;
import com.yahoo.prelude.query.AndItem;
import com.yahoo.prelude.query.CompositeItem;
import com.yahoo.prelude.query.Item;
-import com.yahoo.prelude.query.parser.SpecialTokenRegistry;
+import com.yahoo.language.process.SpecialTokenRegistry;
import com.yahoo.search.Query;
import com.yahoo.search.searchchain.Execution;
import com.yahoo.search.searchchain.Execution.Context;
diff --git a/container-search/src/test/java/com/yahoo/search/querytransform/WeakAndReplacementSearcherTestCase.java b/container-search/src/test/java/com/yahoo/search/querytransform/WeakAndReplacementSearcherTestCase.java
new file mode 100644
index 00000000000..a72fbeeaac9
--- /dev/null
+++ b/container-search/src/test/java/com/yahoo/search/querytransform/WeakAndReplacementSearcherTestCase.java
@@ -0,0 +1,120 @@
+// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.search.querytransform;
+
+import com.yahoo.component.chain.Chain;
+import com.yahoo.prelude.query.*;
+import com.yahoo.processing.request.CompoundName;
+import com.yahoo.search.Query;
+import com.yahoo.search.Result;
+import com.yahoo.search.Searcher;
+import com.yahoo.search.searchchain.Execution;
+import org.junit.Test;
+
+import java.util.stream.IntStream;
+
+import static org.junit.Assert.*;
+
+public class WeakAndReplacementSearcherTestCase {
+
+ private static final CompoundName WEAKAND_REPLACE = new CompoundName("weakAnd.replace");
+ private static final int N = 99;
+
+
+ private Execution buildExec() {
+ return new Execution(new Chain<Searcher>(new WeakAndReplacementSearcher()),
+ Execution.Context.createContextStub());
+ }
+
+ private Query buildDefaultQuery(boolean searcherEnabled) {
+ Query query = new Query();
+ query.properties().set("wand.hits", N);
+ query.properties().set(WEAKAND_REPLACE, searcherEnabled);
+ OrItem root = new OrItem();
+ root.addItem(new WordItem("text"));
+ NotItem notItem = new NotItem();
+ OrItem notItemOr = new OrItem();
+ notItemOr.addItem(new IntItem(1, "index"));
+ notItemOr.addItem(new WordItem("positive"));
+ notItem.addPositiveItem(notItemOr);
+ notItem.addNegativeItem(new WordItem("negative"));
+ query.getModel().getQueryTree().setRoot(root);
+ return query;
+ }
+
+
+
+
+ @Test
+ public void requireOrItemsToBeReplaced() {
+ Query query = buildDefaultQuery(true);
+ Result result = buildExec().search(query);
+ Item root = TestUtils.getQueryTreeRoot(result);
+ assertFalse(orItemsExist(root));
+ assertTrue(root instanceof WeakAndItem);
+ assertEquals(N, ((WeakAndItem)root).getN());
+ }
+
+ @Test
+ public void requireQueryPropertyToWork() {
+ Query query = buildDefaultQuery(false);
+ Item preRoot = query.getModel().getQueryTree().getRoot();
+ Result result = buildExec().search(query);
+ Item root = TestUtils.getQueryTreeRoot(result);
+ assertTrue(orItemsExist(root));
+ assertTrue(deepEquals(root, preRoot));
+ }
+
+ @Test
+ public void requireDoNothingOnNoOrItems() {
+ Query query = new Query();
+ query.properties().set(WEAKAND_REPLACE, true);
+ AndItem andItem = new AndItem();
+ andItem.addItem(new WordItem("1"));
+ andItem.addItem(new WordItem("2"));
+ query.getModel().getQueryTree().setRoot(andItem);
+ Result result = buildExec().search(query);
+ Item root = TestUtils.getQueryTreeRoot(result);
+ assertTrue(deepEquals(root, andItem));
+ }
+
+ @Test
+ public void requireChildrenAreTheSame() {
+ Query query = new Query();
+ query.properties().set(WEAKAND_REPLACE, true);
+ OrItem preRoot = new OrItem();
+ preRoot.addItem(new WordItem("val1"));
+ preRoot.addItem(new WordItem("val2"));
+
+ query.getModel().getQueryTree().setRoot(preRoot);
+ Result result = buildExec().search(query);
+ WeakAndItem root = (WeakAndItem)TestUtils.getQueryTreeRoot(result);
+ assertEquals(preRoot.getItem(0), root.getItem(0));
+ assertEquals(preRoot.getItem(1), root.getItem(1));
+ }
+
+ private boolean deepEquals(Item item1, Item item2) {
+ if (item1 != item2) {
+ return false;
+ }
+ if (!(item1 instanceof CompositeItem)) {
+ return true;
+ }
+
+ CompositeItem compositeItem1 = (CompositeItem) item1;
+ CompositeItem compositeItem2 = (CompositeItem) item2;
+ return IntStream.range(0, compositeItem1.getItemCount())
+ .allMatch(i -> deepEquals(compositeItem1.getItem(i), compositeItem2.getItem(i)));
+ }
+
+ private boolean orItemsExist(Item item) {
+ if (!(item instanceof CompositeItem)) {
+ return false;
+ }
+ if (item instanceof OrItem) {
+ return true;
+ }
+ CompositeItem compositeItem = (CompositeItem) item;
+ return compositeItem.items().stream().anyMatch(this::orItemsExist);
+ }
+
+}
diff --git a/container-search/src/test/java/com/yahoo/search/querytransform/test/SortingDegraderTestCase.java b/container-search/src/test/java/com/yahoo/search/querytransform/test/SortingDegraderTestCase.java
index 5a14cff1818..ab65e258477 100644
--- a/container-search/src/test/java/com/yahoo/search/querytransform/test/SortingDegraderTestCase.java
+++ b/container-search/src/test/java/com/yahoo/search/querytransform/test/SortingDegraderTestCase.java
@@ -6,7 +6,6 @@ import com.yahoo.prelude.Index;
import com.yahoo.prelude.IndexFacts;
import com.yahoo.prelude.IndexModel;
import com.yahoo.prelude.SearchDefinition;
-import com.yahoo.prelude.query.QueryException;
import com.yahoo.search.Query;
import com.yahoo.search.Result;
import com.yahoo.search.Searcher;
@@ -16,8 +15,6 @@ import com.yahoo.search.querytransform.SortingDegrader;
import com.yahoo.search.searchchain.Execution;
import org.junit.Test;
-import java.util.Collections;
-
import static org.junit.Assert.*;
/**
@@ -67,12 +64,10 @@ public class SortingDegraderTestCase {
try {
Query query = new Query("?ranking.sorting=-a1%20-a2&ranking.matchPhase.maxFilterCoverage=37");
assertTrue(false);
- } catch (QueryException qe) {
- assertEquals("Invalid request parameter", qe.getMessage());
- Throwable setE = qe.getCause();
- assertTrue(setE instanceof IllegalArgumentException);
- assertEquals("Could not set 'ranking.matchPhase.maxFilterCoverage' to '37'", setE.getMessage());
- Throwable rootE = setE.getCause();
+ } catch (IllegalArgumentException qe) {
+ assertTrue(qe instanceof IllegalArgumentException);
+ assertEquals("Could not set 'ranking.matchPhase.maxFilterCoverage' to '37'", qe.getMessage());
+ Throwable rootE = qe.getCause();
assertTrue(rootE instanceof IllegalArgumentException);
assertEquals("maxFilterCoverage must be in the range [0.0, 1.0]. It is 37.0", rootE.getMessage());
}
diff --git a/container-search/src/test/java/com/yahoo/search/rendering/JsonRendererTestCase.java b/container-search/src/test/java/com/yahoo/search/rendering/JsonRendererTestCase.java
index c4d49c11f5e..290b7266a3a 100644
--- a/container-search/src/test/java/com/yahoo/search/rendering/JsonRendererTestCase.java
+++ b/container-search/src/test/java/com/yahoo/search/rendering/JsonRendererTestCase.java
@@ -1,7 +1,6 @@
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.search.rendering;
-import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.util.concurrent.ListenableFuture;
@@ -56,9 +55,6 @@ import com.yahoo.tensor.TensorType;
import com.yahoo.tensor.serialization.TypedBinaryFormat;
import com.yahoo.text.Utf8;
import com.yahoo.yolean.trace.TraceNode;
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
import org.junit.Before;
import org.junit.Test;
@@ -67,7 +63,6 @@ import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
-import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
@@ -83,6 +78,8 @@ import static org.junit.Assert.assertTrue;
*/
public class JsonRendererTestCase {
+ private static final ObjectMapper jsonMapper = new ObjectMapper();
+
private JsonRenderer originalRenderer;
private JsonRenderer renderer;
@@ -127,6 +124,55 @@ public class JsonRendererTestCase {
}
@Test
+ public void testTensorShortForm() throws ExecutionException, InterruptedException, IOException {
+ String expected = "{" +
+ "\"root\":{" +
+ "\"id\":\"toplevel\"," +
+ "\"relevance\":1.0," +
+ "\"fields\":{" +
+ "\"totalCount\":1" +
+ "}," +
+ "\"children\":[{" +
+ "\"id\":\"tensors\"," +
+ "\"relevance\":1.0," +
+ "\"fields\":{" +
+ "\"tensor_standard\":{\"type\":\"tensor(x{},y{})\",\"cells\":[{\"address\":{\"x\":\"a\",\"y\":\"0\"},\"value\":1.0},{\"address\":{\"x\":\"b\",\"y\":\"1\"},\"value\":2.0}]}," +
+ "\"tensor_indexed\":{\"type\":\"tensor(x[2],y[3])\",\"values\":[[1.0,2.0,3.0],[4.0,5.0,6.0]]}," +
+ "\"tensor_single_mapped\":{\"type\":\"tensor(x{})\",\"cells\":{\"a\":1.0,\"b\":2.0}}," +
+ "\"tensor_mixed\":{\"type\":\"tensor(x{},y[2])\",\"blocks\":{\"a\":[1.0,2.0],\"b\":[3.0,4.0]}}," +
+ "\"summaryfeatures\":{" +
+ "\"tensor_standard\":{\"type\":\"tensor(x{},y{})\",\"cells\":[{\"address\":{\"x\":\"a\",\"y\":\"0\"},\"value\":1.0},{\"address\":{\"x\":\"b\",\"y\":\"1\"},\"value\":2.0}]}," +
+ "\"tensor_indexed\":{\"type\":\"tensor(x[2],y[3])\",\"values\":[[1.0,2.0,3.0],[4.0,5.0,6.0]]}," +
+ "\"tensor_single_mapped\":{\"type\":\"tensor(x{})\",\"cells\":{\"a\":1.0,\"b\":2.0}}," +
+ "\"tensor_mixed\":{\"type\":\"tensor(x{},y[2])\",\"blocks\":{\"a\":[1.0,2.0],\"b\":[3.0,4.0]}}" +
+ "}" +
+ "}" +
+ "}]" +
+ "}}\n";
+
+ Slime slime = new Slime();
+ Cursor features = slime.setObject();
+ features.setData("tensor_standard", TypedBinaryFormat.encode(Tensor.from("tensor(x{},y{}):{ {x:a,y:0}:1.0, {x:b,y:1}:2.0 }")));
+ features.setData("tensor_indexed", TypedBinaryFormat.encode(Tensor.from("tensor(x[2],y[3]):[[1,2,3],[4,5,6]]")));
+ features.setData("tensor_single_mapped", TypedBinaryFormat.encode(Tensor.from("tensor(x{}):{ a:1, b:2 }")));
+ features.setData("tensor_mixed", TypedBinaryFormat.encode(Tensor.from("tensor(x{},y[2]):{a:[1,2], b:[3,4]}")));
+ FeatureData summaryFeatures = new FeatureData(new SlimeAdapter(slime.get()));
+
+ Hit h = new Hit("tensors");
+ h.setField("tensor_standard", new TensorFieldValue(Tensor.from("tensor(x{},y{}):{ {x:a,y:0}:1.0, {x:b,y:1}:2.0 }")));
+ h.setField("tensor_indexed", new TensorFieldValue(Tensor.from("tensor(x[2],y[3]):[[1,2,3],[4,5,6]]")));
+ h.setField("tensor_single_mapped", new TensorFieldValue(Tensor.from("tensor(x{}):{ a:1, b:2 }")));
+ h.setField("tensor_mixed", new TensorFieldValue(Tensor.from("tensor(x{},y[2]):{a:[1,2], b:[3,4]}")));
+ h.setField("summaryfeatures", summaryFeatures);
+
+ Result r = new Result(new Query("/?format.tensors=short"));
+ r.hits().add(h);
+ r.setTotalHitCount(1L);
+ String summary = render(r);
+ assertEqualJson(expected, summary);
+ }
+
+ @Test
public void testDataTypes() throws IOException, InterruptedException, ExecutionException {
String expected = "{"
+ " \"root\": {"
@@ -466,7 +512,6 @@ public class JsonRendererTestCase {
assertEqualJson(expected, summary);
}
-
@Test
public void testTracingOfNodesWithBothChildrenAndDataAndEmptySubnode() throws IOException, InterruptedException, ExecutionException {
String expected = "{"
@@ -556,7 +601,6 @@ public class JsonRendererTestCase {
assertEqualJson(expected, summary);
}
-
@Test
public void test() throws IOException, InterruptedException, ExecutionException {
String expected = "{"
@@ -959,7 +1003,7 @@ public class JsonRendererTestCase {
}
@Test
- public void testJsonObjects() throws InterruptedException, ExecutionException, IOException, JSONException {
+ public void testJsonObjects() throws InterruptedException, ExecutionException, IOException {
String expected = "{"
+ " \"root\": {"
+ " \"children\": ["
@@ -973,14 +1017,6 @@ public class JsonRendererTestCase {
+ " },"
+ " \"json producer\": {"
+ " \"long in structured\": 7809531904"
- + " },"
- + " \"org.json array\": ["
- + " true,"
- + " true,"
- + " false"
- + " ],"
- + " \"org.json object\": {"
- + " \"forty-two\": 42"
+ " }"
+ " },"
+ " \"id\": \"json objects\","
@@ -996,26 +1032,17 @@ public class JsonRendererTestCase {
+ "}";
Result r = newEmptyResult();
Hit h = new Hit("json objects");
- JSONObject o = new JSONObject();
- JSONArray a = new JSONArray();
- ObjectMapper mapper = new ObjectMapper();
- JsonNode j = mapper.createObjectNode();
+ ObjectNode j = jsonMapper.createObjectNode();
JSONString s = new JSONString("{\"a\": \"b\"}");
Slime slime = new Slime();
Cursor c = slime.setObject();
c.setLong("long in structured", 7809531904L);
SlimeAdapter slimeInit = new SlimeAdapter(slime.get());
StructuredData struct = new StructuredData(slimeInit);
- ((ObjectNode) j).put("Nineteen-eighty-four", 1984);
- o.put("forty-two", 42);
- a.put(true);
- a.put(true);
- a.put(false);
+ j.put("Nineteen-eighty-four", 1984);
h.setField("inspectable", s);
h.setField("jackson", j);
h.setField("json producer", struct);
- h.setField("org.json array", a);
- h.setField("org.json object", o);
r.hits().add(h);
String summary = render(r);
assertEqualJson(expected, summary);
@@ -1236,11 +1263,13 @@ public class JsonRendererTestCase {
public void testThatTheJsonValidatorCanCatchErrors() {
String json = "{"
+ " \"root\": {"
- + " \"duplicate\": 1,"
- + " \"duplicate\": 2"
+ + " \"invalidvalue\": 1adsf,"
+ " }"
+ "}";
- assertEquals("Duplicate key \"duplicate\"", validateJSON(json));
+ assertEquals(
+ "Unexpected character ('a' (code 97)): was expecting comma to separate Object entries\n" +
+ " at [Source: (String)\"{ \"root\": { \"invalidvalue\": 1adsf, }}\"; line: 1, column: 41]",
+ validateJSON(json));
}
@Test
@@ -1316,9 +1345,9 @@ public class JsonRendererTestCase {
private String validateJSON(String presumablyValidJson) {
try {
- new JSONObject(presumablyValidJson);
+ jsonMapper.readTree(presumablyValidJson);
return "";
- } catch (JSONException e) {
+ } catch (IOException e) {
return e.getMessage();
}
}
diff --git a/container-search/src/test/java/com/yahoo/search/result/FeatureDataTestCase.java b/container-search/src/test/java/com/yahoo/search/result/FeatureDataTestCase.java
index 9cc7cc743fc..3c8e147029c 100644
--- a/container-search/src/test/java/com/yahoo/search/result/FeatureDataTestCase.java
+++ b/container-search/src/test/java/com/yahoo/search/result/FeatureDataTestCase.java
@@ -11,6 +11,7 @@ import org.junit.Test;
import java.util.stream.Collectors;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
/**
* @author bratseth
@@ -32,12 +33,21 @@ public class FeatureDataTestCase {
FeatureData featureData = new FeatureData(new SlimeAdapter(features));
assertEquals("scalar1,scalar2,tensor1,tensor2",
featureData.featureNames().stream().sorted().collect(Collectors.joining(",")));
+ assertNull(featureData.getDouble("nosuch1"));
assertEquals(1.5, featureData.getDouble("scalar1"), delta);
assertEquals(2.5, featureData.getDouble("scalar2"), delta);
+ assertEquals("Cached lookup", 2.5, featureData.getDouble("scalar2"), delta);
+ assertNull(featureData.getDouble("nosuch2"));
+ assertNull(featureData.getDouble("nosuch2"));
+
+ assertNull(featureData.getTensor("nosuch1"));
assertEquals(Tensor.from(1.5), featureData.getTensor("scalar1"));
assertEquals(Tensor.from(2.5), featureData.getTensor("scalar2"));
assertEquals(tensor1, featureData.getTensor("tensor1"));
assertEquals(tensor2, featureData.getTensor("tensor2"));
+ assertEquals("Cached lookup", tensor2, featureData.getTensor("tensor2"));
+ assertNull(featureData.getTensor("nosuch2"));
+ assertNull(featureData.getTensor("nosuch2"));
String expectedJson =
"{" +
diff --git a/container-search/src/test/java/com/yahoo/search/searchchain/config/test/SearchChainConfigurerTestCase.java b/container-search/src/test/java/com/yahoo/search/searchchain/config/test/SearchChainConfigurerTestCase.java
index a57ed07017f..5b16802a65e 100644
--- a/container-search/src/test/java/com/yahoo/search/searchchain/config/test/SearchChainConfigurerTestCase.java
+++ b/container-search/src/test/java/com/yahoo/search/searchchain/config/test/SearchChainConfigurerTestCase.java
@@ -18,13 +18,29 @@ import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
-import java.io.*;
-import java.util.*;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static org.hamcrest.CoreMatchers.*;
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertThat;
/**
* @author bratseth
@@ -32,8 +48,8 @@ import static org.junit.Assert.*;
*/
public class SearchChainConfigurerTestCase {
- private static Random random = new Random(1);
- private static String topCfgDir = System.getProperty("java.io.tmpdir") + File.separator +
+ private static final Random random = new Random(1);
+ private static final String topCfgDir = System.getProperty("java.io.tmpdir") + File.separator +
"SearchChainConfigurerTestCase" + File.separator;
private static final String testDir = "src/test/java/com/yahoo/search/searchchain/config/test/";
@@ -132,7 +148,7 @@ public class SearchChainConfigurerTestCase {
* that does not contain any bootstrap configs.
*/
@Test
- public void testSearcherConfigUpdate() throws IOException, InterruptedException {
+ public void testSearcherConfigUpdate() throws IOException {
File cfgDir = getCfgDir();
copyFile(testDir + "handlers.cfg", cfgDir + "/handlers.cfg");
copyFile(testDir + "qr-search.cfg", cfgDir + "/qr-search.cfg");
@@ -171,9 +187,9 @@ public class SearchChainConfigurerTestCase {
// Searchers with unchanged config (or that takes no config) are the same as before.
Searcher s = searchers.getComponent(DeclaredTestSearcher.class.getName());
- assertThat((DeclaredTestSearcher)s, sameInstance(noConfigSearcher));
+ assertThat(s, sameInstance(noConfigSearcher));
s = searchers.getComponent(StringSearcher.class.getName());
- assertThat((StringSearcher)s, sameInstance(stringSearcher));
+ assertThat(s, sameInstance(stringSearcher));
configurer.shutdown();
cleanup(cfgDir);
@@ -219,7 +235,7 @@ public class SearchChainConfigurerTestCase {
assertThat(getSearchChainRegistryFrom(configurer).getSearcherRegistry(), not(searchers));
searchers = getSearchChainRegistryFrom(configurer).getSearcherRegistry();
assertThat(searchers.getComponentCount(), is(3));
- assertThat((IntSearcher)searchers.getComponent(IntSearcher.class.getName()), sameInstance(intSearcher));
+ assertThat(searchers.getComponent(IntSearcher.class.getName()), sameInstance(intSearcher));
assertThat(searchers.getComponent(ConfigurableSearcher.class.getName()), instanceOf(ConfigurableSearcher.class));
assertThat(searchers.getComponent(DeclaredTestSearcher.class.getName()), instanceOf(DeclaredTestSearcher.class));
assertThat(searchers.getComponent(StringSearcher.class.getName()), nullValue());
@@ -326,7 +342,7 @@ public class SearchChainConfigurerTestCase {
if (append) {
Pattern p = Pattern.compile("^[a-z]+" + "\\[\\d+\\]\\.id (.+)");
BufferedReader reader = new BufferedReader(new InputStreamReader(
- new FileInputStream(new File(componentsFile)), "UTF-8"));
+ new FileInputStream(new File(componentsFile)), StandardCharsets.UTF_8));
while ((line = reader.readLine()) != null) {
Matcher m = p.matcher(line);
if (m.matches() && !m.group(1).equals(HandlersConfigurerDi.RegistriesHack.class.getName())) {
@@ -337,7 +353,7 @@ public class SearchChainConfigurerTestCase {
reader.close();
}
BufferedReader reader = new BufferedReader(new InputStreamReader(
- new FileInputStream(new File(configFile)), "UTF-8"));
+ new FileInputStream(new File(configFile)), StandardCharsets.UTF_8));
Pattern component = Pattern.compile("^" + componentType + "\\[\\d+\\]\\.id (.+)");
while ((line = reader.readLine()) != null) {
Matcher m = component.matcher(line);
@@ -353,7 +369,7 @@ public class SearchChainConfigurerTestCase {
buf.append("components[").append(i++).append("].id ").append(ExecutionFactory.class.getName()).append("\n");
buf.insert(0, "components["+i+"]\n");
- Writer writer = new OutputStreamWriter(new FileOutputStream(new File(componentsFile)), "UTF-8");
+ Writer writer = new OutputStreamWriter(new FileOutputStream(new File(componentsFile)), StandardCharsets.UTF_8);
writer.write(buf.toString());
writer.flush();
writer.close();
diff --git a/container-search/src/test/java/com/yahoo/search/searchchain/config/test/dependencyConfig/handlers.cfg b/container-search/src/test/java/com/yahoo/search/searchchain/config/test/dependencyConfig/handlers.cfg
index ad20005e7ad..53811bdf536 100644
--- a/container-search/src/test/java/com/yahoo/search/searchchain/config/test/dependencyConfig/handlers.cfg
+++ b/container-search/src/test/java/com/yahoo/search/searchchain/config/test/dependencyConfig/handlers.cfg
@@ -1,2 +1,3 @@
-handler[1]
+handler[2]
handler[0].id com.yahoo.search.handler.SearchHandler
+handler[1].id com.yahoo.search.query.profile.compiled.CompiledQueryProfileRegistry
diff --git a/container-search/src/test/java/com/yahoo/search/searchchain/config/test/handlers.cfg b/container-search/src/test/java/com/yahoo/search/searchchain/config/test/handlers.cfg
index ad20005e7ad..53811bdf536 100644
--- a/container-search/src/test/java/com/yahoo/search/searchchain/config/test/handlers.cfg
+++ b/container-search/src/test/java/com/yahoo/search/searchchain/config/test/handlers.cfg
@@ -1,2 +1,3 @@
-handler[1]
+handler[2]
handler[0].id com.yahoo.search.handler.SearchHandler
+handler[1].id com.yahoo.search.query.profile.compiled.CompiledQueryProfileRegistry
diff --git a/container-search/src/test/java/com/yahoo/search/searchchain/config/test/testInstances/components.cfg b/container-search/src/test/java/com/yahoo/search/searchchain/config/test/testInstances/components.cfg
index 8a985f92d10..e1d5c418c6a 100644
--- a/container-search/src/test/java/com/yahoo/search/searchchain/config/test/testInstances/components.cfg
+++ b/container-search/src/test/java/com/yahoo/search/searchchain/config/test/testInstances/components.cfg
@@ -22,3 +22,4 @@ components[8].classId com.yahoo.search.searchchain.config.test.twosearchers.Mult
components[8].bundle twosearchers
components[9].id com.yahoo.search.handler.SearchHandler
components[10].id com.yahoo.container.handler.config.HandlersConfigurerDi$RegistriesHack
+components[11].id com.yahoo.search.query.profile.compiled.CompiledQueryProfileRegistry
diff --git a/container-search/src/test/java/com/yahoo/search/searchchain/test/AsyncExecutionOfOneChainTestCase.java b/container-search/src/test/java/com/yahoo/search/searchchain/test/AsyncExecutionOfOneChainTestCase.java
index 182ec7568f3..28ad202c4f5 100644
--- a/container-search/src/test/java/com/yahoo/search/searchchain/test/AsyncExecutionOfOneChainTestCase.java
+++ b/container-search/src/test/java/com/yahoo/search/searchchain/test/AsyncExecutionOfOneChainTestCase.java
@@ -48,20 +48,20 @@ public class AsyncExecutionOfOneChainTestCase {
private class ParallelExecutor extends Searcher {
/** The number of parallel executions */
- private static final int parallelism=2;
+ private static final int parallelism = 2;
@Override
public Result search(Query query, Execution execution) {
- List<FutureResult> futureResults=new ArrayList<>(parallelism);
- for (int i=0; i<parallelism; i++)
+ List<FutureResult> futureResults = new ArrayList<>(parallelism);
+ for (int i = 0; i < parallelism; i++)
futureResults.add(new AsyncExecution(execution).search(query.clone()));
- Result mainResult=execution.search(query);
+ Result mainResult = execution.search(query);
// Add hits from other threads
AsyncExecution.waitForAll(futureResults,query.getTimeLeft());
for (FutureResult futureResult : futureResults) {
- Result result=futureResult.get();
+ Result result = futureResult.get();
mainResult.mergeWith(result);
mainResult.hits().addAll(result.hits().asList());
}
@@ -72,7 +72,7 @@ public class AsyncExecutionOfOneChainTestCase {
private static class RegularProvider extends Searcher {
- private AtomicInteger counter=new AtomicInteger();
+ private final AtomicInteger counter = new AtomicInteger();
@Override
public Result search(Query query,Execution execution) {
diff --git a/container-search/src/test/java/com/yahoo/search/searchers/ValidateNearestNeighborTestCase.java b/container-search/src/test/java/com/yahoo/search/searchers/ValidateNearestNeighborTestCase.java
index 0cbf3a6f92c..e5ed6f89fd4 100644
--- a/container-search/src/test/java/com/yahoo/search/searchers/ValidateNearestNeighborTestCase.java
+++ b/container-search/src/test/java/com/yahoo/search/searchers/ValidateNearestNeighborTestCase.java
@@ -1,14 +1,11 @@
// Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-
-package com.yahoo.prelude.searcher;
+package com.yahoo.search.searchers;
import com.google.common.util.concurrent.MoreExecutors;
import com.yahoo.config.subscription.ConfigGetter;
import com.yahoo.config.subscription.RawSource;
-import com.yahoo.language.Linguistics;
import com.yahoo.language.simple.SimpleLinguistics;
-import com.yahoo.prelude.Index;
import com.yahoo.prelude.IndexFacts;
import com.yahoo.prelude.IndexModel;
import com.yahoo.prelude.SearchDefinition;
@@ -20,15 +17,11 @@ import com.yahoo.search.rendering.RendererRegistry;
import com.yahoo.search.Result;
import com.yahoo.search.result.ErrorMessage;
import com.yahoo.search.searchchain.Execution;
-import com.yahoo.search.Searcher;
-import com.yahoo.search.searchers.ValidateNearestNeighborSearcher;
import com.yahoo.search.yql.YqlParser;
import com.yahoo.tensor.Tensor;
import com.yahoo.tensor.TensorType;
import com.yahoo.vespa.config.search.AttributesConfig;
-import java.util.*;
-
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
@@ -58,10 +51,20 @@ public class ValidateNearestNeighborTestCase {
"attribute[3].tensortype tensor(x{})\n" +
"attribute[4].name matrix\n" +
"attribute[4].datatype TENSOR\n" +
- "attribute[4].tensortype tensor(x[3],y[1])\n"
+ "attribute[4].tensortype tensor(x[3],y[1])\n" +
+ "attribute[5].name threetypes\n" +
+ "attribute[5].datatype TENSOR\n" +
+ "attribute[5].tensortype tensor(x[42])\n" +
+ "attribute[6].name threetypes\n" +
+ "attribute[6].datatype TENSOR\n" +
+ "attribute[6].tensortype tensor(x[3])\n" +
+ "attribute[7].name threetypes\n" +
+ "attribute[7].datatype TENSOR\n" +
+ "attribute[7].tensortype tensor(x{})\n"
)));
}
+ private static TensorType tt_dense_dvector_42 = TensorType.fromSpec("tensor(x[42])");
private static TensorType tt_dense_dvector_3 = TensorType.fromSpec("tensor(x[3])");
private static TensorType tt_dense_dvector_2 = TensorType.fromSpec("tensor(x[2])");
private static TensorType tt_dense_fvector_3 = TensorType.fromSpec("tensor<float>(x[3])");
@@ -100,7 +103,7 @@ public class ValidateNearestNeighborTestCase {
}
private String makeQuery(String attributeTensor, String queryTensor) {
- return "select * from sources * where [{\"targetNumHits\":1}]nearestNeighbor(" + attributeTensor + ", " + queryTensor + ");";
+ return "select * from sources * where [{\"targetHits\":1}]nearestNeighbor(" + attributeTensor + ", " + queryTensor + ");";
}
@Test
@@ -139,12 +142,25 @@ public class ValidateNearestNeighborTestCase {
assertEquals(ErrorMessage.createIllegalQuery(message), r.hits().getError());
}
+ static String desc(String field, String qt, int th, String errmsg) {
+ StringBuilder r = new StringBuilder();
+ r.append("NEAREST_NEIGHBOR {");
+ r.append("field=").append(field);
+ r.append(",queryTensorName=").append(qt);
+ r.append(",hnsw.exploreAdditionalHits=0");
+ r.append(",distanceThreshold=Infinity");
+ r.append(",approximate=true");
+ r.append(",targetHits=").append(th);
+ r.append("} ").append(errmsg);
+ return r.toString();
+ }
+
@Test
public void testMissingTargetNumHits() {
String q = "select * from sources * where nearestNeighbor(dvector,qvector);";
Tensor t = makeTensor(tt_dense_dvector_3);
Result r = doSearch(searcher, q, t);
- assertErrMsg("NEAREST_NEIGHBOR {field=dvector,queryTensorName=qvector,targetNumHits=0} has invalid targetNumHits", r);
+ assertErrMsg(desc("dvector", "qvector", 0, "has invalid targetHits 0: Must be >= 1"), r);
}
@Test
@@ -152,16 +168,7 @@ public class ValidateNearestNeighborTestCase {
String q = makeQuery("dvector", "foo");
Tensor t = makeTensor(tt_dense_dvector_3);
Result r = doSearch(searcher, q, t);
- assertErrMsg("NEAREST_NEIGHBOR {field=dvector,queryTensorName=foo,targetNumHits=1} query tensor not found", r);
- }
-
- @Test
- public void testQueryTensorWrongType() {
- String q = makeQuery("dvector", "qvector");
- Result r = doSearch(searcher, q, "tensor string");
- assertErrMsg("NEAREST_NEIGHBOR {field=dvector,queryTensorName=qvector,targetNumHits=1} query tensor should be a tensor, was: class java.lang.String", r);
- r = doSearch(searcher, q, null);
- assertErrMsg("NEAREST_NEIGHBOR {field=dvector,queryTensorName=qvector,targetNumHits=1} query tensor should be a tensor, was: null", r);
+ assertErrMsg(desc("dvector", "foo", 1, "requires a tensor rank feature query(foo) but this is not present"), r);
}
@Test
@@ -169,7 +176,7 @@ public class ValidateNearestNeighborTestCase {
String q = makeQuery("dvector", "qvector");
Tensor t = makeTensor(tt_dense_dvector_2, 2);
Result r = doSearch(searcher, q, t);
- assertErrMsg("NEAREST_NEIGHBOR {field=dvector,queryTensorName=qvector,targetNumHits=1} field type tensor(x[3]) does not match query tensor type tensor(x[2])", r);
+ assertErrMsg(desc("dvector", "qvector", 1, "field type tensor(x[3]) does not match query type tensor(x[2])"), r);
}
@Test
@@ -177,7 +184,7 @@ public class ValidateNearestNeighborTestCase {
String q = makeQuery("foo", "qvector");
Tensor t = makeTensor(tt_dense_dvector_3);
Result r = doSearch(searcher, q, t);
- assertErrMsg("NEAREST_NEIGHBOR {field=foo,queryTensorName=qvector,targetNumHits=1} field is not an attribute", r);
+ assertErrMsg(desc("foo", "qvector", 1, "field is not an attribute"), r);
}
@Test
@@ -185,7 +192,21 @@ public class ValidateNearestNeighborTestCase {
String q = makeQuery("simple", "qvector");
Tensor t = makeTensor(tt_dense_dvector_3);
Result r = doSearch(searcher, q, t);
- assertErrMsg("NEAREST_NEIGHBOR {field=simple,queryTensorName=qvector,targetNumHits=1} field is not a tensor", r);
+ assertErrMsg(desc("simple", "qvector", 1, "field is not a tensor"), r);
+ }
+
+ @Test
+ public void testSeveralAttributesWithSameName() {
+ String q = makeQuery("threetypes", "qvector");
+ Tensor t1 = makeTensor(tt_dense_fvector_3);
+ Result r1 = doSearch(searcher, q, t1);
+ assertNull(r1.hits().getError());
+ Tensor t2 = makeTensor(tt_dense_dvector_42, 42);
+ Result r2 = doSearch(searcher, q, t2);
+ assertNull(r2.hits().getError());
+ Tensor t3 = makeTensor(tt_dense_dvector_2, 2);
+ Result r3 = doSearch(searcher, q, t3);
+ assertErrMsg(desc("threetypes", "qvector", 1, "field type tensor(x[42]) does not match query type tensor(x[2])"), r3);
}
@Test
@@ -193,7 +214,7 @@ public class ValidateNearestNeighborTestCase {
String q = makeQuery("sparse", "qvector");
Tensor t = makeTensor(tt_sparse_vector_x);
Result r = doSearch(searcher, q, t);
- assertErrMsg("NEAREST_NEIGHBOR {field=sparse,queryTensorName=qvector,targetNumHits=1} tensor type tensor(x{}) is not a dense vector", r);
+ assertErrMsg(desc("sparse", "qvector", 1, "tensor type tensor(x{}) is not a dense vector"), r);
}
@Test
@@ -201,14 +222,14 @@ public class ValidateNearestNeighborTestCase {
String q = makeQuery("matrix", "qvector");
Tensor t = makeMatrix(tt_dense_matrix_xy);
Result r = doSearch(searcher, q, t);
- assertErrMsg("NEAREST_NEIGHBOR {field=matrix,queryTensorName=qvector,targetNumHits=1} tensor type tensor(x[3],y[1]) is not a dense vector", r);
+ assertErrMsg(desc("matrix", "qvector", 1, "tensor type tensor(x[3],y[1]) is not a dense vector"), r);
}
- private static Result doSearch(ValidateNearestNeighborSearcher searcher, String yqlQuery, Object qTensor) {
+ private static Result doSearch(ValidateNearestNeighborSearcher searcher, String yqlQuery, Tensor qTensor) {
QueryTree queryTree = new YqlParser(new ParserEnvironment()).parse(new Parsable().setQuery(yqlQuery));
Query query = new Query();
query.getModel().getQueryTree().setRoot(queryTree.getRoot());
- query.getRanking().getProperties().put("qvector", qTensor);
+ query.getRanking().getFeatures().put("query(qvector)", qTensor);
SearchDefinition searchDefinition = new SearchDefinition("document");
IndexFacts indexFacts = new IndexFacts(new IndexModel(searchDefinition));
Execution.Context context = new Execution.Context(null, indexFacts, null, new RendererRegistry(MoreExecutors.directExecutor()), new SimpleLinguistics());
diff --git a/container-search/src/test/java/com/yahoo/search/searchers/test/InputCheckingSearcherTestCase.java b/container-search/src/test/java/com/yahoo/search/searchers/test/InputCheckingSearcherTestCase.java
index dbeced57c52..9bf5b654a6d 100644
--- a/container-search/src/test/java/com/yahoo/search/searchers/test/InputCheckingSearcherTestCase.java
+++ b/container-search/src/test/java/com/yahoo/search/searchers/test/InputCheckingSearcherTestCase.java
@@ -5,6 +5,7 @@ import static org.junit.Assert.*;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
import org.junit.After;
import org.junit.Before;
@@ -23,50 +24,50 @@ import com.yahoo.text.Utf8;
/**
* Functional test for InputCheckingSearcher.
*
- * @author <a href="mailto:steinar@yahoo-inc.com">Steinar Knutsen</a>
+ * @author Steinar Knutsen
*/
public class InputCheckingSearcherTestCase {
Execution execution;
@Before
- public void setUp() throws Exception {
+ public void setUp() {
execution = new Execution(new Chain<Searcher>(new InputCheckingSearcher(MetricReceiver.nullImplementation)),
- Execution.Context.createContextStub(new IndexFacts()));
+ Execution.Context.createContextStub(new IndexFacts()));
}
@After
- public void tearDown() throws Exception {
+ public void tearDown() {
execution = null;
}
@Test
- public final void testCommonCase() {
+ public void testCommonCase() {
Result r = execution.search(new Query("/search/?query=three+blind+mice"));
assertNull(r.hits().getErrorHit());
}
@Test
- public final void candidateButAsciiOnly() {
+ public void candidateButAsciiOnly() {
Result r = execution.search(new Query("/search/?query=a+a+a+a+a+a"));
assertNull(r.hits().getErrorHit());
}
@Test
- public final void candidateButValid() throws UnsupportedEncodingException {
+ public void candidateButValid() throws UnsupportedEncodingException {
Result r = execution.search(new Query("/search/?query=" + URLEncoder.encode("å å å å å å", "UTF-8")));
assertNull(r.hits().getErrorHit());
}
@Test
- public final void candidateButValidAndOutsideFirst256() throws UnsupportedEncodingException {
+ public void candidateButValidAndOutsideFirst256() throws UnsupportedEncodingException {
Result r = execution.search(new Query("/search/?query=" + URLEncoder.encode("œ œ œ œ œ œ", "UTF-8")));
assertNull(r.hits().getErrorHit());
}
@Test
- public final void testDoubleEncoded() throws UnsupportedEncodingException {
+ public void testDoubleEncoded() throws UnsupportedEncodingException {
String rawQuery = "å å å å å å";
byte[] encodedOnce = Utf8.toBytes(rawQuery);
char[] secondEncodingBuffer = new char[encodedOnce.length];
@@ -74,33 +75,42 @@ public class InputCheckingSearcherTestCase {
secondEncodingBuffer[i] = (char) (encodedOnce[i] & 0xFF);
}
String query = new String(secondEncodingBuffer);
- Result r = execution.search(new Query("/search/?query=" + URLEncoder.encode(query, "UTF-8")));
+ Result r = execution.search(new Query("/search/?query=" + URLEncoder.encode(query, StandardCharsets.UTF_8)));
assertEquals(1, r.hits().getErrorHit().errors().size());
}
@Test
- public final void testRepeatedConsecutiveTermsInPhrase() {
- Result r = execution.search(new Query("/search/?query=a.b.0.0.0.0.0.c"));
+ public void testRepeatedConsecutiveTermsInPhrase() {
+ Result r = execution.search(new Query("/search/?query=%22a.b.0.0.0.0.0.c%22"));
assertNull(r.hits().getErrorHit());
- r = execution.search(new Query("/search/?query=a.b.0.0.0.0.0.0.c"));
+ r = execution.search(new Query("/search/?query=%22a.b.0.0.0.0.0.0.c%22"));
assertNotNull(r.hits().getErrorHit());
+ assertEquals("More than 5 occurrences of term '0' in a row detected in phrase : \"a b 0 0 0 0 0 0 c\"",
+ r.hits().getErrorHit().errorIterator().next().getDetailedMessage());
r = execution.search(new Query("/search/?query=a.b.0.0.0.1.0.0.0.c"));
assertNull(r.hits().getErrorHit());
}
+
@Test
- public final void testThatMaxRepeatedConsecutiveTermsInPhraseIs5() {
- Result r = execution.search(new Query("/search/?query=a.b.0.0.0.0.0.c"));
+ public void testThatMaxRepeatedConsecutiveTermsInPhraseIs5() {
+ Result r = execution.search(new Query("/search/?query=%22a.b.0.0.0.0.0.c%22"));
assertNull(r.hits().getErrorHit());
- r = execution.search(new Query("/search/?query=a.b.0.0.0.0.0.0.c"));
+ r = execution.search(new Query("/search/?query=%22a.b.0.0.0.0.0.0.c%22"));
assertNotNull(r.hits().getErrorHit());
- r = execution.search(new Query("/search/?query=a.b.0.0.0.1.0.0.0.c"));
+ assertEquals("More than 5 occurrences of term '0' in a row detected in phrase : \"a b 0 0 0 0 0 0 c\"",
+ r.hits().getErrorHit().errorIterator().next().getDetailedMessage());
+ r = execution.search(new Query("/search/?query=%22a.b.0.0.0.1.0.0.0.c%22"));
assertNull(r.hits().getErrorHit());
}
+
@Test
- public final void testThatMaxRepeatedTermsInPhraseIs10() {
- Result r = execution.search(new Query("/search/?query=0.a.1.a.2.a.3.a.4.a.5.a.6.a.7.a.9.a"));
+ public void testThatMaxRepeatedTermsInPhraseIs10() {
+ Result r = execution.search(new Query("/search/?query=%220.a.1.a.2.a.3.a.4.a.5.a.6.a.7.a.9.a%22"));
assertNull(r.hits().getErrorHit());
- r = execution.search(new Query("/search/?query=0.a.1.a.2.a.3.a.4.a.5.a.6.a.7.a.8.a.9.a.10.a"));
+ r = execution.search(new Query("/search/?query=%220.a.1.a.2.a.3.a.4.a.5.a.6.a.7.a.8.a.9.a.10.a%22"));
assertNotNull(r.hits().getErrorHit());
+ assertEquals("Phrase contains more than 10 occurrences of term 'a' in phrase : \"0 a 1 a 2 a 3 a 4 a 5 a 6 a 7 a 8 a 9 a 10 a\"",
+ r.hits().getErrorHit().errorIterator().next().getDetailedMessage());
}
+
}
diff --git a/container-search/src/test/java/com/yahoo/search/searchers/test/QueryValidatorTestCase.java b/container-search/src/test/java/com/yahoo/search/searchers/test/QueryValidatorTestCase.java
new file mode 100644
index 00000000000..543c880e525
--- /dev/null
+++ b/container-search/src/test/java/com/yahoo/search/searchers/test/QueryValidatorTestCase.java
@@ -0,0 +1,51 @@
+// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.search.searchers.test;
+
+import com.yahoo.prelude.IndexFacts;
+import com.yahoo.prelude.IndexModel;
+import com.yahoo.prelude.SearchDefinition;
+import com.yahoo.search.Query;
+import com.yahoo.search.searchchain.Execution;
+import com.yahoo.search.searchers.QueryValidator;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+/**
+ * @author bratseth
+ */
+public class QueryValidatorTestCase {
+
+ @Test
+ public void testValidation() {
+ SearchDefinition sd = new SearchDefinition("test");
+ sd.addCommand("mytensor1", "type tensor(x[100]");
+ sd.addCommand("mytensor2", "type tensor<float>(x[100]");
+ sd.addCommand("mystring", "type string");
+ IndexModel model = new IndexModel(sd);
+
+ IndexFacts indexFacts = new IndexFacts(model);
+ Execution execution = new Execution(Execution.Context.createContextStub(indexFacts));
+ new QueryValidator().search(new Query("?query=mystring:foo"), execution);
+
+ try {
+ new QueryValidator().search(new Query("?query=mytensor1:foo"), execution);
+ fail("Expected validation error");
+ }
+ catch (IllegalArgumentException e) {
+ // success
+ assertEquals("Cannot search 'mytensor1': It is a tensor field", e.getMessage());
+ }
+
+ try {
+ new QueryValidator().search(new Query("?query=mytensor2:foo"), execution);
+ fail("Expected validation error");
+ }
+ catch (IllegalArgumentException e) {
+ // success
+ assertEquals("Cannot search 'mytensor2': It is a tensor field", e.getMessage());
+ }
+ }
+
+}
diff --git a/container-search/src/test/java/com/yahoo/search/test/QueryTestCase.java b/container-search/src/test/java/com/yahoo/search/test/QueryTestCase.java
index e71ed308aaf..59178b9419a 100644
--- a/container-search/src/test/java/com/yahoo/search/test/QueryTestCase.java
+++ b/container-search/src/test/java/com/yahoo/search/test/QueryTestCase.java
@@ -16,13 +16,13 @@ import com.yahoo.prelude.IndexFacts;
import com.yahoo.prelude.IndexModel;
import com.yahoo.prelude.SearchDefinition;
import com.yahoo.prelude.query.AndItem;
+import com.yahoo.prelude.query.AndSegmentItem;
import com.yahoo.prelude.query.CompositeItem;
import com.yahoo.prelude.query.Highlight;
import com.yahoo.prelude.query.IndexedItem;
import com.yahoo.prelude.query.IntItem;
import com.yahoo.prelude.query.Item;
import com.yahoo.prelude.query.OrItem;
-import com.yahoo.prelude.query.QueryException;
import com.yahoo.prelude.query.RankItem;
import com.yahoo.prelude.query.WordItem;
import com.yahoo.processing.request.CompoundName;
@@ -32,6 +32,7 @@ import com.yahoo.search.Searcher;
import com.yahoo.search.grouping.GroupingQueryParser;
import com.yahoo.search.query.QueryTree;
import com.yahoo.search.query.SessionId;
+import com.yahoo.search.query.profile.DimensionValues;
import com.yahoo.search.query.profile.QueryProfile;
import com.yahoo.search.query.profile.QueryProfileRegistry;
import com.yahoo.search.query.profile.compiled.CompiledQueryProfileRegistry;
@@ -45,6 +46,7 @@ import org.junit.Test;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@@ -61,7 +63,7 @@ import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
/**
- * @author Arne Bergene Fossaa
+ * @author bratseth
*/
public class QueryTestCase {
@@ -286,13 +288,21 @@ public class QueryTestCase {
try {
new Query(httpEncode("/search?timeout=nalle"));
fail("Above statement should throw");
- } catch (QueryException e) {
+ } catch (IllegalArgumentException e) {
// As expected.
assertTrue(Exceptions.toMessageString(e).contains("Could not set 'timeout' to 'nalle': Error parsing 'nalle': Invalid number 'nalle'"));
}
}
@Test
+ public void testCloneTimeout() {
+ Query q = new Query(httpEncode("/search?timeout=300ms"));
+ assertEquals(300, q.getTimeout());
+ Query clonedQ = q.clone();
+ assertEquals(300, clonedQ.getTimeout());
+ }
+
+ @Test
public void testQueryProfileSubstitution1() {
QueryProfile profile = new QueryProfile("myProfile");
profile.set("myField", "Profile: %{queryProfile}", null);
@@ -345,6 +355,61 @@ public class QueryTestCase {
}
@Test
+ public void testQueryProfileClearAndSet() {
+ QueryProfile profile = new QueryProfile("myProfile");
+ profile.set("b", "b-value", null);
+ Query q = new Query(QueryTestCase.httpEncode("/search?queryProfile=myProfile"), profile.compile(null));
+ assertEquals("b-value", q.properties().get("b"));
+ assertContains(q.properties().listProperties("b"), "b-value");
+
+ q.properties().set("b", null, null);
+ assertContains(q.properties().listProperties("b"), (Object)null);
+
+ q.properties().set("b", "b-value", null);
+ assertEquals("b-value", q.properties().get("b"));
+ assertContains(q.properties().listProperties("b"), "b-value");
+ }
+
+ @Test
+ public void testQueryProfileClearValue() {
+ QueryProfile profile = new QueryProfile("myProfile");
+ profile.set("a", "a-value", null);
+ profile.set("b", "b-value", null);
+ profile.set("b.c", "b.c-value", null);
+ profile.set("b.d", "b.d-value", null);
+ Query q = new Query(QueryTestCase.httpEncode("/search?queryProfile=myProfile"), profile.compile(null));
+ assertEquals("a-value", q.properties().get("a"));
+ assertEquals("b-value", q.properties().get("b"));
+ assertEquals("b.c-value", q.properties().get("b.c"));
+ assertEquals("b.d-value", q.properties().get("b.d"));
+ assertContains(q.properties().listProperties("b"), "b-value", "b.c-value", "b.d-value");
+
+ q.properties().set("a", null, null);
+ assertEquals(null, q.properties().get("a"));
+
+ q.properties().set("b", null, null);
+ assertEquals(null, q.properties().get("b"));
+ assertEquals("b.c-value", q.properties().get("b.c"));
+ assertEquals("b.d-value", q.properties().get("b.d"));
+ assertContains(q.properties().listProperties("b"), null, "b.c-value", "b.d-value");
+
+ q.properties().set("b", "b-value", null);
+ q.properties().set("b.e", "b.e-value", null);
+ q.properties().set("b.f", "b.f-value", null);
+ assertEquals("b-value", q.properties().get("b"));
+ assertEquals("b.e-value", q.properties().get("b.e"));
+ assertContains(q.properties().listProperties("b"), "b-value", "b.c-value", "b.d-value", "b.e-value", "b.f-value");
+
+ q.properties().clearAll("b");
+ assertEquals(null, q.properties().get("b"));
+ assertEquals(null, q.properties().get("b.c"));
+ assertEquals(null, q.properties().get("b.d"));
+ assertEquals(null, q.properties().get("b.e"));
+ assertEquals(null, q.properties().get("b.f"));
+ assertContains(q.properties().listProperties("b"), (Object)null);
+ }
+
+ @Test
public void testNotEqual() {
Query q = new Query("/?query=something+test&nocache");
Query p = new Query("/?query=something+test");
@@ -364,14 +429,13 @@ public class QueryTestCase {
@Test
public void testUtf8Decoding() {
Query q = new Query("/?query=beyonc%C3%A9");
- q.getModel().getQueryTree().toString();
assertEquals("beyonc\u00e9", q.getModel().getQueryTree().toString());
}
@Test
public void testQueryProfileInSubstitution() {
QueryProfile testProfile = new QueryProfile("test");
- testProfile.setOverridable("u", false, null);
+ testProfile.setOverridable("u", false, DimensionValues.empty);
testProfile.set("d","e", null);
testProfile.set("u","11", null);
testProfile.set("foo.bar", "wiz", null);
@@ -504,7 +568,7 @@ public class QueryTestCase {
@Test
public void testQueryPropertyResolveTracing() {
QueryProfile testProfile = new QueryProfile("test");
- testProfile.setOverridable("u", false, null);
+ testProfile.setOverridable("u", false, DimensionValues.empty);
testProfile.set("d","e", null);
testProfile.set("u","11", null);
testProfile.set("foo.bar", "wiz", null);
@@ -807,7 +871,7 @@ public class QueryTestCase {
root.addItem(child);
fail("Expected exception");
}
- catch (QueryException e) {
+ catch (IllegalArgumentException e) {
assertEquals("Cannot add OR (AND ) to (AND ) as it would create a cycle", e.getMessage());
}
@@ -817,7 +881,7 @@ public class QueryTestCase {
child.addItem(root);
fail("Expected exception");
}
- catch (QueryException e) {
+ catch (IllegalArgumentException e) {
assertEquals("Cannot add (AND (OR )) to (OR ) as it would create a cycle", e.getMessage());
}
}
@@ -884,12 +948,12 @@ public class QueryTestCase {
@Test
public void testImplicitPhraseIsDefault() {
Query query = new Query(httpEncode("?query=it's fine"));
- assertEquals("AND 'it s' fine", query.getModel().getQueryTree().toString());
+ assertEquals("AND (SAND it s) fine", query.getModel().getQueryTree().toString());
}
@Test
public void testImplicitPhrase() {
- Query query = new Query(httpEncode("?query=myfield:it's myfield:a-b myfield:c"));
+ Query query = new Query(httpEncode("?query=myfield:it's myfield:a.b myfield:c"));
SearchDefinition test = new SearchDefinition("test");
Index myField = new Index("myfield");
@@ -904,7 +968,7 @@ public class QueryTestCase {
@Test
public void testImplicitAnd() {
- Query query = new Query(httpEncode("?query=myfield:it's myfield:a-b myfield:c"));
+ Query query = new Query(httpEncode("?query=myfield:it's myfield:a.b myfield:c"));
SearchDefinition test = new SearchDefinition("test");
Index myField = new Index("myfield");
@@ -915,6 +979,56 @@ public class QueryTestCase {
query.getModel().setExecution(new Execution(Execution.Context.createContextStub(new IndexFacts(indexModel))));
assertEquals("AND (SAND myfield:it myfield:s) myfield:a myfield:b myfield:c", query.getModel().getQueryTree().toString());
+ // 'it' and 's' should have connectivity 1
+ AndItem root = (AndItem)query.getModel().getQueryTree().getRoot();
+ AndSegmentItem sand = (AndSegmentItem)root.getItem(0);
+ WordItem it = (WordItem)sand.getItem(0);
+ assertEquals("it", it.getWord());
+ WordItem s = (WordItem)sand.getItem(1);
+ assertEquals("s", s.getWord());
+ assertEquals(s, it.getConnectedItem());
+ assertEquals(1.0, it.getConnectivity(), 0.00000001);
+ }
+
+ @Test
+ public void testImplicitAndConnectivity() {
+ SearchDefinition test = new SearchDefinition("test");
+ Index myField = new Index("myfield");
+ myField.addCommand("phrase-segmenting false");
+ test.addIndex(myField);
+ IndexModel indexModel = new IndexModel(test);
+
+ {
+ Query query = new Query(httpEncode("?query=myfield:b.c.d"));
+ query.getModel().setExecution(new Execution(Execution.Context.createContextStub(new IndexFacts(indexModel))));
+ assertEquals("AND myfield:b myfield:c myfield:d", query.getModel().getQueryTree().toString());
+ AndItem root = (AndItem) query.getModel().getQueryTree().getRoot();
+ WordItem b = (WordItem) root.getItem(0);
+ WordItem c = (WordItem) root.getItem(1);
+ WordItem d = (WordItem) root.getItem(2);
+ assertEquals(c, b.getConnectedItem());
+ assertEquals(1.0, b.getConnectivity(), 0.00000001);
+ assertEquals(d, c.getConnectedItem());
+ assertEquals(1.0, c.getConnectivity(), 0.00000001);
+ }
+
+ {
+ Query query = new Query(httpEncode("?query=myfield:a myfield:b.c.d myfield:e"));
+ query.getModel().setExecution(new Execution(Execution.Context.createContextStub(new IndexFacts(indexModel))));
+ assertEquals("AND myfield:a myfield:b myfield:c myfield:d myfield:e", query.getModel().getQueryTree().toString());
+ AndItem root = (AndItem) query.getModel().getQueryTree().getRoot();
+ WordItem a = (WordItem) root.getItem(0);
+ WordItem b = (WordItem) root.getItem(1);
+ WordItem c = (WordItem) root.getItem(2);
+ WordItem d = (WordItem) root.getItem(3);
+ WordItem e = (WordItem) root.getItem(4);
+ assertNull(a.getConnectedItem());
+ assertEquals(c, b.getConnectedItem());
+ assertEquals(1.0, b.getConnectivity(), 0.00000001);
+ assertEquals(d, c.getConnectedItem());
+ assertEquals(1.0, c.getConnectivity(), 0.00000001);
+ assertNull(d.getConnectedItem());
+ }
}
@Test
@@ -929,7 +1043,7 @@ public class QueryTestCase {
IndexModel indexModel = new IndexModel(test);
query.getModel().setExecution(new Execution(Execution.Context.createContextStub(new IndexFacts(indexModel))));
- assertEquals("myfield:\"it s fine\"", query.getModel().getQueryTree().toString());
+ assertEquals("myfield:\"'it s' fine\"", query.getModel().getQueryTree().toString());
}
@Test
@@ -985,6 +1099,19 @@ public class QueryTestCase {
assertEquals(expectedDetectionText, mockLinguistics.detector.lastDetectionText);
}
+ private void assertContains(Map<String, Object> properties, Object ... expectedValues) {
+ if (expectedValues == null) {
+ assertEquals(1, properties.size());
+ assertTrue("Contains value null", properties.containsValue(null));
+ }
+ else {
+ assertEquals(properties + " contains values " + Arrays.toString(expectedValues),
+ expectedValues.length, properties.size());
+ for (Object expectedValue : expectedValues)
+ assertTrue("Contains value " + expectedValue, properties.containsValue(expectedValue));
+ }
+ }
+
/** A linguistics instance which records the last language detection text passed to it */
private static class MockLinguistics extends SimpleLinguistics {
@@ -993,6 +1120,8 @@ public class QueryTestCase {
@Override
public Detector getDetector() { return detector; }
+ @Override
+ public boolean equals(Linguistics other) { return (other instanceof MockLinguistics); }
}
private static class MockDetector extends SimpleDetector {
diff --git a/container-search/src/test/java/com/yahoo/search/yql/MinimalQueryInserterTestCase.java b/container-search/src/test/java/com/yahoo/search/yql/MinimalQueryInserterTestCase.java
index d832ba52ceb..0a502eccc11 100644
--- a/container-search/src/test/java/com/yahoo/search/yql/MinimalQueryInserterTestCase.java
+++ b/container-search/src/test/java/com/yahoo/search/yql/MinimalQueryInserterTestCase.java
@@ -342,11 +342,18 @@ public class MinimalQueryInserterTestCase {
}
@Test
+ public void testAndSegmenting() {
+ Query query = new Query("?yql=select%20%2A%20from%20sources%20%2A%20where%20%5B%7B%22defaultIndex%22%3A%20%22default%22%2C%22grammar%22%3A%20%22web%22%2C%22stem%22%3A%20true%2C%22allowEmpty%22%3A%20true%7D%5DuserInput%28%40animal%29%3B&animal=m%26m%27s&tracelevel=3");
+ execution.search(query);
+ assertEquals("select * from sources * where (default contains \"m\" AND default contains ([{\"origin\": {\"original\": \"m\\'s\", \"offset\": 0, \"length\": 3}, \"andSegmenting\": true}]phrase(\"m\", \"s\")));",
+ query.yqlRepresentation());
+ }
+
+ @Test
public void verifyThatWarmupIsSane() {
assertTrue(MinimalQueryInserter.warmup());
}
-
private static void assertGrouping(String expected, Query query) {
List<String> actual = new ArrayList<>();
for (GroupingRequest request : query.getSelect().getGrouping())
diff --git a/container-search/src/test/java/com/yahoo/search/yql/UserInputTestCase.java b/container-search/src/test/java/com/yahoo/search/yql/UserInputTestCase.java
index 6173d710434..06160e1c6d5 100644
--- a/container-search/src/test/java/com/yahoo/search/yql/UserInputTestCase.java
+++ b/container-search/src/test/java/com/yahoo/search/yql/UserInputTestCase.java
@@ -15,6 +15,8 @@ import com.yahoo.search.Result;
import com.yahoo.search.Searcher;
import com.yahoo.search.searchchain.Execution;
+import java.util.Arrays;
+
import static com.yahoo.container.protect.Error.INVALID_QUERY_PARAMETER;
/**
@@ -195,13 +197,49 @@ public class UserInputTestCase {
assertEquals("select * from sources * where (foo contains \"bamse\" AND foo contains phrase(\"bamse\", \"syntactic\", \"bamse\"));", query.yqlRepresentation());
}
+ @Test
+ public void testReferenceInComparison() {
+ URIBuilder builder = searchUri();
+ builder.setParameter("varref", "1980");
+ builder.setParameter("yql", "select * from sources * where year > @varref;");
+ Query query = searchAndAssertNoErrors(builder);
+ assertEquals("select * from sources * where year > 1980;", query.yqlRepresentation());
+ }
+
+ @Test
+ public void testReferenceInContinuation() {
+ URIBuilder builder = searchUri();
+ builder.setParameter("continuation", "BCBCBCBEBG");
+ builder.setParameter("yql",
+ "select * from sources * where myfield contains 'token'" +
+ "| [{'continuations':[@continuation, 'BCBKCBACBKCCK'] }] all(group(f) each(output(count())));");
+ Query query = searchAndAssertNoErrors(builder);
+ assertEquals("select * from sources * where myfield contains \"token\" | [{ 'continuations':['BCBCBCBEBG', 'BCBKCBACBKCCK'] }]all(group(f) each(output(count())));", query.yqlRepresentation());
+ }
+
+ @Test
+ public void testReferenceInEquiv() {
+ URIBuilder builder = searchUri();
+ builder.setParameter("term", "A");
+ builder.setParameter("yql",
+ "select foo from bar where fieldName contains equiv(@term,'B');");
+ Query query = searchAndAssertNoErrors(builder);
+ assertEquals("select foo from bar where fieldName contains equiv(\"A\", \"B\");", query.yqlRepresentation());
+ }
+
private Query searchAndAssertNoErrors(URIBuilder builder) {
Query query = new Query(builder.toString());
Result r = execution.search(query);
- assertNull(r.hits().getError());
+ assertNull(stackTraceIfAny(r), r.hits().getError());
return query;
}
+ private String stackTraceIfAny(Result r) {
+ if (r.hits().getError() == null) return "";
+ if (r.hits().getError().getCause() == null) return "";
+ return Arrays.toString(r.hits().getError().getCause().getStackTrace());
+ }
+
private URIBuilder searchUri() {
URIBuilder builder = new URIBuilder();
builder.setPath("search/");
@@ -211,8 +249,7 @@ public class UserInputTestCase {
@Test
public void testEmptyUserInput() {
URIBuilder builder = searchUri();
- builder.setParameter("yql",
- "select * from sources * where userInput(\"\");");
+ builder.setParameter("yql", "select * from sources * where userInput(\"\");");
assertQueryFails(builder);
}
@@ -220,8 +257,7 @@ public class UserInputTestCase {
public void testEmptyUserInputFromQueryProperty() {
URIBuilder builder = searchUri();
builder.setParameter("foo", "");
- builder.setParameter("yql",
- "select * from sources * where userInput(@foo);");
+ builder.setParameter("yql", "select * from sources * where userInput(@foo);");
assertQueryFails(builder);
}
diff --git a/container-search/src/test/java/com/yahoo/search/yql/VespaSerializerTestCase.java b/container-search/src/test/java/com/yahoo/search/yql/VespaSerializerTestCase.java
index 1106d8c3999..a44a9f25b62 100644
--- a/container-search/src/test/java/com/yahoo/search/yql/VespaSerializerTestCase.java
+++ b/container-search/src/test/java/com/yahoo/search/yql/VespaSerializerTestCase.java
@@ -119,6 +119,14 @@ public class VespaSerializerTestCase {
}
@Test
+ public void testGeoLocation() {
+ parseAndConfirm("geoLocation(workplace, 63.418417, 10.433033, \"0.5 deg\")");
+ parseAndConfirm("geoLocation(headquarters, 37.41638, -122.024683, \"180.0 deg\")");
+ parseAndConfirm("geoLocation(home, -17.0, 42.0, \"0.0 deg\")");
+ parseAndConfirm("geoLocation(workplace, -12.0, -34.0, \"-1.0 deg\")");
+ }
+
+ @Test
public void testNear() {
parseAndConfirm("title contains near(\"a\", \"b\")");
parseAndConfirm("title contains ([{\"distance\": 50}]near(\"a\", \"b\"))");
@@ -128,6 +136,10 @@ public class VespaSerializerTestCase {
public void testNearestNeighbor() {
parseAndConfirm("[{\"label\": \"foo\", \"targetNumHits\": 1000}]nearestNeighbor(semantic_embedding, my_property)");
parseAndConfirm("[{\"targetNumHits\": 42}]nearestNeighbor(semantic_embedding, my_property)");
+ parseAndConfirm("[{\"targetNumHits\": 1, \"hnsw.exploreAdditionalHits\": 76}]nearestNeighbor(semantic_embedding, my_property)");
+ parseAndConfirm("[{\"targetNumHits\": 2, \"approximate\": false}]nearestNeighbor(semantic_embedding, my_property)");
+ parseAndConfirm("[{\"targetNumHits\": 3, \"hnsw.exploreAdditionalHits\": 67, \"approximate\": false}]nearestNeighbor(semantic_embedding, my_property)");
+ parseAndConfirm("[{\"targetNumHits\": 4, \"distanceThreshold\": 100100.25}]nearestNeighbor(semantic_embedding, my_property)");
}
@Test
@@ -242,9 +254,13 @@ public class VespaSerializerTestCase {
andSegment.addItem(new WordItem("a", "indexNamePlaceholder"));
andSegment.addItem(new WordItem("b", "indexNamePlaceholder"));
andSegment.setLabel("labeled");
- andSegment.lock();
String q = VespaSerializer.serialize(andSegment);
assertEquals("indexNamePlaceholder contains ([{\"origin\": {\"original\": \"abc\", \"offset\": 0, \"length\": 3}, \"andSegmenting\": true}]phrase(\"a\", \"b\"))", q);
+
+ andSegment.setIndexName("someIndexName");
+ andSegment.lock();
+ q = VespaSerializer.serialize(andSegment);
+ assertEquals("someIndexName contains ([{\"origin\": {\"original\": \"abc\", \"offset\": 0, \"length\": 3}, \"andSegmenting\": true}]phrase(\"a\", \"b\"))", q);
}
@Test
diff --git a/container-search/src/test/java/com/yahoo/search/yql/YqlParserTestCase.java b/container-search/src/test/java/com/yahoo/search/yql/YqlParserTestCase.java
index 5eb1f3e3de1..dd2d27eb66c 100644
--- a/container-search/src/test/java/com/yahoo/search/yql/YqlParserTestCase.java
+++ b/container-search/src/test/java/com/yahoo/search/yql/YqlParserTestCase.java
@@ -123,20 +123,32 @@ public class YqlParserTestCase {
}
@Test
+ public void testHitLimit() {
+ assertParse("select artist_name, track_name, track_uri from sources * where (myField contains ([{\"prefix\":true}]\"m\") and ([{\"hitLimit\": 5000, \"descending\": true}]range(static_score,0,Infinity))) limit 30 offset 0;",
+ "AND myField:m* static_score:[0;;-5000]");
+ }
+
+ @Test
public void test() {
assertParse("select foo from bar where title contains \"madonna\";",
"title:madonna");
}
@Test
+ public void testKeywordAsFieldName() {
+ assertParse("select * from sources * where cast contains sameElement(id contains '16');",
+ "cast:{id:16}");
+ }
+
+ @Test
public void testComplexExpression() {
- String queryTreeYql = "rank((((filter contains ([{\"origin\": {\"original\": \"filter:VideoAdsCappingTestCPM\", \"offset\": 7, \"length\": 22}, \"normalizeCase\": false, \"id\": 1}]\"videoadscappingtestcpm\") AND hasRankRestriction contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 2}]\"0\") AND ((objective contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 3}]\"install_app\") AND availableExtendedFields contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 4}]\"cpiparams\")) OR (availableExtendedFields contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 5}]\"appinstallinfo\") AND availableExtendedFields contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 6}]\"appmetroplexinfo\")) OR (dummyField contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 7}]\"default\")) AND !(objective contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 8}]\"install_app\"))) AND advt_age = ([{\"id\": 9}]2147483647) AND advt_gender contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 10}]\"all\") AND advt_all_segments = ([{\"id\": 11}]2147483647) AND advt_keywords contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 12}]\"all\") AND advMobilePlatform = ([{\"id\": 13}]2147483647) AND advMobileDeviceType = ([{\"id\": 14}]2147483647) AND advMobileCon = ([{\"id\": 15}]2147483647) AND advMobileOSVersions = ([{\"id\": 16}]2147483647) AND advCarrier = ([{\"id\": 17}]2147483647) AND ([{\"id\": 18}]weightedSet(advt_supply, {\"all\": 1, \"pub223\": 1, \"sec223\": 1, \"site223\": 1})) AND (advt_day_parting contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 19, \"weight\": 1}]\"adv_tuesday\") OR advt_day_parting contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 20, \"weight\": 1}]\"adv_tuesday_17\") OR advt_day_parting contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 21, \"weight\": 1}]\"adv_tuesday_17_forty_five\") OR advt_day_parting contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 22}]\"all\")) AND isAppReengagementAd = ([{\"id\": 23}]0) AND dummyField contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 24}]\"default\") AND serveWithPromotionOnly = ([{\"id\": 26}]0) AND budgetAdvertiserThrottleRateFilter = ([{\"id\": 27}]0) AND budgetResellerThrottleRateFilter = ([{\"id\": 28}]0) AND (isMystiqueRequired = ([{\"id\": 29}]0) OR (isMystiqueRequired = ([{\"id\": 30}]1) AND useBcFactorFilter = ([{\"id\": 31}]1))) AND (((budgetCampaignThrottleRateBits = ([{\"id\": 32}]55) AND dummyField contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 33}]\"default\"))) AND !(useBcFactorFilter = ([{\"id\": 34}]1)) OR ((useBcFactorFilter = ([{\"id\": 35}]1) AND dummyField contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 36}]\"default\") AND (bcFactorTiers = ([{\"id\": 38}]127) OR bcFactorTiers = ([{\"id\": 39}]0)) AND ((firstPriceEnforced = ([{\"id\": 40}]0) AND (secondPriceEnforced = ([{\"id\": 41}]1) OR isPrivateDeal = ([{\"id\": 42}]0) OR (dummyField contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 43}]\"default\")) AND !(bcActiveTier = ([{\"id\": 44}]0)))) OR mystiqueCampaignThrottleRateBits = ([{\"id\": 45}]18)))) AND !(isOutOfDailyBudget = ([{\"id\": 37}]1))) AND testCreative = ([{\"id\": 46}]0) AND advt_geo = ([{\"id\": 47}]2147483647) AND ((adType contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 48}]\"strm_video\") AND isPortraitVideo = ([{\"id\": 49}]0)) OR adType contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 50}]\"stream_ad\")) AND ((isCPM = ([{\"id\": 51}]0) AND isOCPC = ([{\"id\": 52}]0) AND isECPC = ([{\"id\": 53}]0) AND ((priceType contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 54}]\"cpcv\") AND bid >= ([{\"id\": 55}]0.005)) OR (priceType contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 56}]\"cpv\") AND bid >= ([{\"id\": 57}]0.01)) OR (priceType contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 58}]\"cpc\") AND bid >= ([{\"id\": 59}]0.05)) OR (objective contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 60}]\"promote_content\") AND bid >= ([{\"id\": 61}]0.01)) OR hasFloorPriceUsd = ([{\"id\": 62}]1))) OR isECPC = ([{\"id\": 63}]1) OR (isCPM = ([{\"id\": 64}]1) AND isOCPM = ([{\"id\": 65}]0) AND (([{\"id\": 66}]range(bid, 0.25, Infinity)) OR hasFloorPriceUsd = ([{\"id\": 67}]1)))) AND start_date <= ([{\"id\": 68}]1572976776299L) AND end_date >= ([{\"id\": 69}]1572976776299L))) AND !(isHoldoutAd = ([{\"id\": 25}]1))) AND !((disclaimerExtensionsTypes contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 70}]\"pharma\") OR ([{\"id\": 71}]weightedSet(exclusion_advt_supply, {\"extsite223\": 1, \"pub223\": 1, \"sec223\": 1, \"site223\": 1})) OR isPersonalized = ([{\"id\": 72}]1) OR blacklist_section_ids contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 73}]\"223\") OR blacklist_publisher_ids contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 74}]\"223\") OR blacklist_site_ids contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 75}]\"223\"))), [{\"id\": 76, \"label\": \"ad_ocpc_max_cpc\"}]dotProduct(ocpc_max_cpc, {\"0\": 1}), [{\"id\": 77, \"label\": \"ad_ocpc_min_cpc\"}]dotProduct(ocpc_min_cpc, {\"0\": 1}), [{\"id\": 78, \"label\": \"ad_ocpc_max_alpha\"}]dotProduct(ocpc_max_alpha, {\"0\": 1}), [{\"id\": 79, \"label\": \"ad_ocpc_min_alpha\"}]dotProduct(ocpc_min_alpha, {\"0\": 1}), [{\"id\": 80, \"label\": \"ad_ocpc_alpha_0\"}]dotProduct(ocpc_alpha_0, {\"0\": 1}), [{\"id\": 81, \"label\": \"ad_ocpc_alpha_1\"}]dotProduct(ocpc_alpha_1, {\"0\": 1}), (bidAdjustmentDayParting contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 82, \"weight\": 1}]\"adv_tuesday\") OR bidAdjustmentDayParting contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 83, \"weight\": 1}]\"adv_tuesday_17\") OR bidAdjustmentDayParting contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 84, \"weight\": 1}]\"adv_tuesday_17_forty_five\") OR bidAdjustmentDayPartingForCostCap contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 85, \"weight\": 1}]\"adv_tuesday\") OR bidAdjustmentDayPartingForCostCap contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 86, \"weight\": 1}]\"adv_tuesday_17\") OR bidAdjustmentDayPartingForCostCap contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 87, \"weight\": 1}]\"adv_tuesday_17_forty_five\")), bidAdjustmentForCpi = ([{\"id\": 88, \"weight\": 1}]223), [{\"id\": 89, \"label\": \"boostingForBackfill\"}]dotProduct(boostingForBackfill, {\"priority\": 1000})) limit 0 timeout 3980 | all(group(adTypeForGrouping) each(group(advertiser_id) max(11) output(count() as(groupingCounter)) each(max(1) each(output(summary())))))";
+ String queryTreeYql = "rank((((filter contains ([{\"origin\": {\"original\": \"filter:VideoAdsCappingTestCPM\", \"offset\": 7, \"length\": 22}, \"normalizeCase\": false, \"id\": 1}]\"videoadscappingtestcpm\") AND hasRankRestriction contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 2}]\"0\") AND ((objective contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 3}]\"install_app\") AND availableExtendedFields contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 4}]\"cpiparams\")) OR (availableExtendedFields contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 5}]\"appinstallinfo\") AND availableExtendedFields contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 6}]\"appmetroplexinfo\")) OR (dummyField contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 7}]\"default\")) AND !(objective contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 8}]\"install_app\"))) AND advt_age = ([{\"id\": 9}]2147483647) AND advt_gender contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 10}]\"all\") AND advt_all_segments = ([{\"id\": 11}]2147483647) AND advt_keywords contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 12}]\"all\") AND advMobilePlatform = ([{\"id\": 13}]2147483647) AND advMobileDeviceType = ([{\"id\": 14}]2147483647) AND advMobileCon = ([{\"id\": 15}]2147483647) AND advMobileOSVersions = ([{\"id\": 16}]2147483647) AND advCarrier = ([{\"id\": 17}]2147483647) AND ([{\"id\": 18}]weightedSet(advt_supply, {\"all\": 1, \"pub223\": 1, \"sec223\": 1, \"site223\": 1})) AND (advt_day_parting contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 19, \"weight\": 1}]\"adv_tuesday\") OR advt_day_parting contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 20, \"weight\": 1}]\"adv_tuesday_17\") OR advt_day_parting contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 21, \"weight\": 1}]\"adv_tuesday_17_forty_five\") OR advt_day_parting contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 22}]\"all\")) AND isAppReengagementAd = ([{\"id\": 23}]0) AND dummyField contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 24}]\"default\") AND serveWithPromotionOnly = ([{\"id\": 26}]0) AND budgetAdvertiserThrottleRateFilter = ([{\"id\": 27}]0) AND budgetResellerThrottleRateFilter = ([{\"id\": 28}]0) AND (isMystiqueRequired = ([{\"id\": 29}]0) OR (isMystiqueRequired = ([{\"id\": 30}]1) AND useBcFactorFilter = ([{\"id\": 31}]1))) AND (((budgetCampaignThrottleRateBits = ([{\"id\": 32}]55) AND dummyField contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 33}]\"default\"))) AND !(useBcFactorFilter = ([{\"id\": 34}]1)) OR ((useBcFactorFilter = ([{\"id\": 35}]1) AND dummyField contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 36}]\"default\") AND (bcFactorTiers = ([{\"id\": 38}]127) OR bcFactorTiers = ([{\"id\": 39}]0)) AND ((firstPriceEnforced = ([{\"id\": 40}]0) AND (secondPriceEnforced = ([{\"id\": 41}]1) OR isPrivateDeal = ([{\"id\": 42}]0) OR (dummyField contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 43}]\"default\")) AND !(bcActiveTier = ([{\"id\": 44}]0)))) OR mystiqueCampaignThrottleRateBits = ([{\"id\": 45}]18)))) AND !(isOutOfDailyBudget = ([{\"id\": 37}]1))) AND testCreative = ([{\"id\": 46}]0) AND advt_geo = ([{\"id\": 47}]2147483647) AND ((adType contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 48}]\"strm_video\") AND isPortraitVideo = ([{\"id\": 49}]0)) OR adType contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 50}]\"stream_ad\")) AND ((isCPM = ([{\"id\": 51}]0) AND isOCPC = ([{\"id\": 52}]0) AND isECPC = ([{\"id\": 53}]0) AND ((priceType contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 54}]\"cpcv\") AND bid >= ([{\"id\": 55}]0.005)) OR (priceType contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 56}]\"cpv\") AND bid >= ([{\"id\": 57}]0.01)) OR (priceType contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 58}]\"cpc\") AND bid >= ([{\"id\": 59}]0.05)) OR (objective contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 60}]\"promote_content\") AND bid >= ([{\"id\": 61}]0.01)) OR hasFloorPriceUsd = ([{\"id\": 62}]1))) OR isECPC = ([{\"id\": 63}]1) OR (isCPM = ([{\"id\": 64}]1) AND isOCPM = ([{\"id\": 65}]0) AND (([{\"id\": 66}]range(bid, 0.25, Infinity)) OR hasFloorPriceUsd = ([{\"id\": 67}]1)))) AND start_date <= ([{\"id\": 68}]1572976776299L) AND end_date >= ([{\"id\": 69}]1572976776299L))) AND !(isHoldoutAd = ([{\"id\": 25}]1))) AND !((disclaimerExtensionsTypes contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 70}]\"pharma\") OR ([{\"id\": 71}]weightedSet(exclusion_advt_supply, {\"extsite223\": 1, \"pub223\": 1, \"sec223\": 1, \"site223\": 1})) OR isPersonalized = ([{\"id\": 72}]1) OR blocked_section_ids contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 73}]\"223\") OR blocked_publisher_ids contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 74}]\"223\") OR blocked_site_ids contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 75}]\"223\"))), [{\"id\": 76, \"label\": \"ad_ocpc_max_cpc\"}]dotProduct(ocpc_max_cpc, {\"0\": 1}), [{\"id\": 77, \"label\": \"ad_ocpc_min_cpc\"}]dotProduct(ocpc_min_cpc, {\"0\": 1}), [{\"id\": 78, \"label\": \"ad_ocpc_max_alpha\"}]dotProduct(ocpc_max_alpha, {\"0\": 1}), [{\"id\": 79, \"label\": \"ad_ocpc_min_alpha\"}]dotProduct(ocpc_min_alpha, {\"0\": 1}), [{\"id\": 80, \"label\": \"ad_ocpc_alpha_0\"}]dotProduct(ocpc_alpha_0, {\"0\": 1}), [{\"id\": 81, \"label\": \"ad_ocpc_alpha_1\"}]dotProduct(ocpc_alpha_1, {\"0\": 1}), (bidAdjustmentDayParting contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 82, \"weight\": 1}]\"adv_tuesday\") OR bidAdjustmentDayParting contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 83, \"weight\": 1}]\"adv_tuesday_17\") OR bidAdjustmentDayParting contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 84, \"weight\": 1}]\"adv_tuesday_17_forty_five\") OR bidAdjustmentDayPartingForCostCap contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 85, \"weight\": 1}]\"adv_tuesday\") OR bidAdjustmentDayPartingForCostCap contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 86, \"weight\": 1}]\"adv_tuesday_17\") OR bidAdjustmentDayPartingForCostCap contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 87, \"weight\": 1}]\"adv_tuesday_17_forty_five\")), bidAdjustmentForCpi = ([{\"id\": 88, \"weight\": 1}]223), [{\"id\": 89, \"label\": \"boostingForBackfill\"}]dotProduct(boostingForBackfill, {\"priority\": 1000})) limit 0 timeout 3980 | all(group(adTypeForGrouping) each(group(advertiser_id) max(11) output(count() as(groupingCounter)) each(max(1) each(output(summary())))))";
QueryTree parsed = assertParse("select * from sources * where " + queryTreeYql + ";",
- "RANK (+(+(AND filter:VideoAdsCappingTestCPM hasRankRestriction:0 (OR (AND objective:install_app availableExtendedFields:cpiparams) (AND availableExtendedFields:appinstallinfo availableExtendedFields:appmetroplexinfo) (+dummyField:default -objective:install_app)) advt_age:2147483647 advt_gender:all advt_all_segments:2147483647 advt_keywords:all advMobilePlatform:2147483647 advMobileDeviceType:2147483647 advMobileCon:2147483647 advMobileOSVersions:2147483647 advCarrier:2147483647 WEIGHTEDSET advt_supply{[1]:\"site223\",[1]:\"pub223\",[1]:\"all\",[1]:\"sec223\"} (OR advt_day_parting:adv_tuesday!1 advt_day_parting:adv_tuesday_17!1 advt_day_parting:adv_tuesday_17_forty_five!1 advt_day_parting:all) isAppReengagementAd:0 dummyField:default serveWithPromotionOnly:0 budgetAdvertiserThrottleRateFilter:0 budgetResellerThrottleRateFilter:0 (OR isMystiqueRequired:0 (AND isMystiqueRequired:1 useBcFactorFilter:1)) (OR (+(AND budgetCampaignThrottleRateBits:55 dummyField:default) -useBcFactorFilter:1) (+(AND useBcFactorFilter:1 dummyField:default (OR bcFactorTiers:127 bcFactorTiers:0) (OR (AND firstPriceEnforced:0 (OR secondPriceEnforced:1 isPrivateDeal:0 (+dummyField:default -bcActiveTier:0))) mystiqueCampaignThrottleRateBits:18)) -isOutOfDailyBudget:1)) testCreative:0 advt_geo:2147483647 (OR (AND adType:strm_video isPortraitVideo:0) adType:stream_ad) (OR (AND isCPM:0 isOCPC:0 isECPC:0 (OR (AND priceType:cpcv bid:[0.005;]) (AND priceType:cpv bid:[0.01;]) (AND priceType:cpc bid:[0.05;]) (AND objective:promote_content bid:[0.01;]) hasFloorPriceUsd:1)) isECPC:1 (AND isCPM:1 isOCPM:0 (OR bid:[0.25;] hasFloorPriceUsd:1))) start_date:[;1572976776299] end_date:[1572976776299;]) -isHoldoutAd:1) -(OR disclaimerExtensionsTypes:pharma WEIGHTEDSET exclusion_advt_supply{[1]:\"extsite223\",[1]:\"site223\",[1]:\"pub223\",[1]:\"sec223\"} isPersonalized:1 blacklist_section_ids:223 blacklist_publisher_ids:223 blacklist_site_ids:223)) DOTPRODUCT ocpc_max_cpc{[1]:\"0\"} DOTPRODUCT ocpc_min_cpc{[1]:\"0\"} DOTPRODUCT ocpc_max_alpha{[1]:\"0\"} DOTPRODUCT ocpc_min_alpha{[1]:\"0\"} DOTPRODUCT ocpc_alpha_0{[1]:\"0\"} DOTPRODUCT ocpc_alpha_1{[1]:\"0\"} (OR bidAdjustmentDayParting:adv_tuesday!1 bidAdjustmentDayParting:adv_tuesday_17!1 bidAdjustmentDayParting:adv_tuesday_17_forty_five!1 bidAdjustmentDayPartingForCostCap:adv_tuesday!1 bidAdjustmentDayPartingForCostCap:adv_tuesday_17!1 bidAdjustmentDayPartingForCostCap:adv_tuesday_17_forty_five!1) bidAdjustmentForCpi:223!1 DOTPRODUCT boostingForBackfill{[1000]:\"priority\"}");
+ "RANK (+(+(AND filter:VideoAdsCappingTestCPM hasRankRestriction:0 (OR (AND objective:install_app availableExtendedFields:cpiparams) (AND availableExtendedFields:appinstallinfo availableExtendedFields:appmetroplexinfo) (+dummyField:default -objective:install_app)) advt_age:2147483647 advt_gender:all advt_all_segments:2147483647 advt_keywords:all advMobilePlatform:2147483647 advMobileDeviceType:2147483647 advMobileCon:2147483647 advMobileOSVersions:2147483647 advCarrier:2147483647 WEIGHTEDSET advt_supply{[1]:\"site223\",[1]:\"pub223\",[1]:\"all\",[1]:\"sec223\"} (OR advt_day_parting:adv_tuesday!1 advt_day_parting:adv_tuesday_17!1 advt_day_parting:adv_tuesday_17_forty_five!1 advt_day_parting:all) isAppReengagementAd:0 dummyField:default serveWithPromotionOnly:0 budgetAdvertiserThrottleRateFilter:0 budgetResellerThrottleRateFilter:0 (OR isMystiqueRequired:0 (AND isMystiqueRequired:1 useBcFactorFilter:1)) (OR (+(AND budgetCampaignThrottleRateBits:55 dummyField:default) -useBcFactorFilter:1) (+(AND useBcFactorFilter:1 dummyField:default (OR bcFactorTiers:127 bcFactorTiers:0) (OR (AND firstPriceEnforced:0 (OR secondPriceEnforced:1 isPrivateDeal:0 (+dummyField:default -bcActiveTier:0))) mystiqueCampaignThrottleRateBits:18)) -isOutOfDailyBudget:1)) testCreative:0 advt_geo:2147483647 (OR (AND adType:strm_video isPortraitVideo:0) adType:stream_ad) (OR (AND isCPM:0 isOCPC:0 isECPC:0 (OR (AND priceType:cpcv bid:[0.005;]) (AND priceType:cpv bid:[0.01;]) (AND priceType:cpc bid:[0.05;]) (AND objective:promote_content bid:[0.01;]) hasFloorPriceUsd:1)) isECPC:1 (AND isCPM:1 isOCPM:0 (OR bid:[0.25;] hasFloorPriceUsd:1))) start_date:[;1572976776299] end_date:[1572976776299;]) -isHoldoutAd:1) -(OR disclaimerExtensionsTypes:pharma WEIGHTEDSET exclusion_advt_supply{[1]:\"extsite223\",[1]:\"site223\",[1]:\"pub223\",[1]:\"sec223\"} isPersonalized:1 blocked_section_ids:223 blocked_publisher_ids:223 blocked_site_ids:223)) DOTPRODUCT ocpc_max_cpc{[1]:\"0\"} DOTPRODUCT ocpc_min_cpc{[1]:\"0\"} DOTPRODUCT ocpc_max_alpha{[1]:\"0\"} DOTPRODUCT ocpc_min_alpha{[1]:\"0\"} DOTPRODUCT ocpc_alpha_0{[1]:\"0\"} DOTPRODUCT ocpc_alpha_1{[1]:\"0\"} (OR bidAdjustmentDayParting:adv_tuesday!1 bidAdjustmentDayParting:adv_tuesday_17!1 bidAdjustmentDayParting:adv_tuesday_17_forty_five!1 bidAdjustmentDayPartingForCostCap:adv_tuesday!1 bidAdjustmentDayPartingForCostCap:adv_tuesday_17!1 bidAdjustmentDayPartingForCostCap:adv_tuesday_17_forty_five!1) bidAdjustmentForCpi:223!1 DOTPRODUCT boostingForBackfill{[1000]:\"priority\"}");
String serializedQueryTreeYql = VespaSerializer.serialize(parsed);
// Note: All the details here are not verified
- assertEquals("rank((((filter contains ([{\"normalizeCase\": false, \"id\": 1}]\"VideoAdsCappingTestCPM\") AND hasRankRestriction contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 2}]\"0\") AND ((objective contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 3}]\"install_app\") AND availableExtendedFields contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 4}]\"cpiparams\")) OR (availableExtendedFields contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 5}]\"appinstallinfo\") AND availableExtendedFields contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 6}]\"appmetroplexinfo\")) OR (dummyField contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 7}]\"default\")) AND !(objective contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 8}]\"install_app\"))) AND advt_age = ([{\"id\": 9}]2147483647) AND advt_gender contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 10}]\"all\") AND advt_all_segments = ([{\"id\": 11}]2147483647) AND advt_keywords contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 12}]\"all\") AND advMobilePlatform = ([{\"id\": 13}]2147483647) AND advMobileDeviceType = ([{\"id\": 14}]2147483647) AND advMobileCon = ([{\"id\": 15}]2147483647) AND advMobileOSVersions = ([{\"id\": 16}]2147483647) AND advCarrier = ([{\"id\": 17}]2147483647) AND ([{\"id\": 18}]weightedSet(advt_supply, {\"all\": 1, \"pub223\": 1, \"sec223\": 1, \"site223\": 1})) AND (advt_day_parting contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 19, \"weight\": 1}]\"adv_tuesday\") OR advt_day_parting contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 20, \"weight\": 1}]\"adv_tuesday_17\") OR advt_day_parting contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 21, \"weight\": 1}]\"adv_tuesday_17_forty_five\") OR advt_day_parting contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 22}]\"all\")) AND isAppReengagementAd = ([{\"id\": 23}]0) AND dummyField contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 24}]\"default\") AND serveWithPromotionOnly = ([{\"id\": 26}]0) AND budgetAdvertiserThrottleRateFilter = ([{\"id\": 27}]0) AND budgetResellerThrottleRateFilter = ([{\"id\": 28}]0) AND (isMystiqueRequired = ([{\"id\": 29}]0) OR (isMystiqueRequired = ([{\"id\": 30}]1) AND useBcFactorFilter = ([{\"id\": 31}]1))) AND (((budgetCampaignThrottleRateBits = ([{\"id\": 32}]55) AND dummyField contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 33}]\"default\"))) AND !(useBcFactorFilter = ([{\"id\": 34}]1)) OR ((useBcFactorFilter = ([{\"id\": 35}]1) AND dummyField contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 36}]\"default\") AND (bcFactorTiers = ([{\"id\": 38}]127) OR bcFactorTiers = ([{\"id\": 39}]0)) AND ((firstPriceEnforced = ([{\"id\": 40}]0) AND (secondPriceEnforced = ([{\"id\": 41}]1) OR isPrivateDeal = ([{\"id\": 42}]0) OR (dummyField contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 43}]\"default\")) AND !(bcActiveTier = ([{\"id\": 44}]0)))) OR mystiqueCampaignThrottleRateBits = ([{\"id\": 45}]18)))) AND !(isOutOfDailyBudget = ([{\"id\": 37}]1))) AND testCreative = ([{\"id\": 46}]0) AND advt_geo = ([{\"id\": 47}]2147483647) AND ((adType contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 48}]\"strm_video\") AND isPortraitVideo = ([{\"id\": 49}]0)) OR adType contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 50}]\"stream_ad\")) AND ((isCPM = ([{\"id\": 51}]0) AND isOCPC = ([{\"id\": 52}]0) AND isECPC = ([{\"id\": 53}]0) AND ((priceType contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 54}]\"cpcv\") AND bid >= ([{\"id\": 55}]0.005)) OR (priceType contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 56}]\"cpv\") AND bid >= ([{\"id\": 57}]0.01)) OR (priceType contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 58}]\"cpc\") AND bid >= ([{\"id\": 59}]0.05)) OR (objective contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 60}]\"promote_content\") AND bid >= ([{\"id\": 61}]0.01)) OR hasFloorPriceUsd = ([{\"id\": 62}]1))) OR isECPC = ([{\"id\": 63}]1) OR (isCPM = ([{\"id\": 64}]1) AND isOCPM = ([{\"id\": 65}]0) AND ([{\"id\": 66}]range(bid, 0.25, Infinity) OR hasFloorPriceUsd = ([{\"id\": 67}]1)))) AND start_date <= ([{\"id\": 68}]1572976776299L) AND end_date >= ([{\"id\": 69}]1572976776299L))) AND !(isHoldoutAd = ([{\"id\": 25}]1))) AND !((disclaimerExtensionsTypes contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 70}]\"pharma\") OR ([{\"id\": 71}]weightedSet(exclusion_advt_supply, {\"extsite223\": 1, \"pub223\": 1, \"sec223\": 1, \"site223\": 1})) OR isPersonalized = ([{\"id\": 72}]1) OR blacklist_section_ids contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 73}]\"223\") OR blacklist_publisher_ids contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 74}]\"223\") OR blacklist_site_ids contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 75}]\"223\"))), ([{\"id\": 76, \"label\": \"ad_ocpc_max_cpc\"}]dotProduct(ocpc_max_cpc, {\"0\": 1})), ([{\"id\": 77, \"label\": \"ad_ocpc_min_cpc\"}]dotProduct(ocpc_min_cpc, {\"0\": 1})), ([{\"id\": 78, \"label\": \"ad_ocpc_max_alpha\"}]dotProduct(ocpc_max_alpha, {\"0\": 1})), ([{\"id\": 79, \"label\": \"ad_ocpc_min_alpha\"}]dotProduct(ocpc_min_alpha, {\"0\": 1})), ([{\"id\": 80, \"label\": \"ad_ocpc_alpha_0\"}]dotProduct(ocpc_alpha_0, {\"0\": 1})), ([{\"id\": 81, \"label\": \"ad_ocpc_alpha_1\"}]dotProduct(ocpc_alpha_1, {\"0\": 1})), (bidAdjustmentDayParting contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 82, \"weight\": 1}]\"adv_tuesday\") OR bidAdjustmentDayParting contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 83, \"weight\": 1}]\"adv_tuesday_17\") OR bidAdjustmentDayParting contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 84, \"weight\": 1}]\"adv_tuesday_17_forty_five\") OR bidAdjustmentDayPartingForCostCap contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 85, \"weight\": 1}]\"adv_tuesday\") OR bidAdjustmentDayPartingForCostCap contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 86, \"weight\": 1}]\"adv_tuesday_17\") OR bidAdjustmentDayPartingForCostCap contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 87, \"weight\": 1}]\"adv_tuesday_17_forty_five\")), bidAdjustmentForCpi = ([{\"id\": 88, \"weight\": 1}]223), ([{\"id\": 89, \"label\": \"boostingForBackfill\"}]dotProduct(boostingForBackfill, {\"priority\": 1000})))",
+ assertEquals("rank((((filter contains ([{\"normalizeCase\": false, \"id\": 1}]\"VideoAdsCappingTestCPM\") AND hasRankRestriction contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 2}]\"0\") AND ((objective contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 3}]\"install_app\") AND availableExtendedFields contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 4}]\"cpiparams\")) OR (availableExtendedFields contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 5}]\"appinstallinfo\") AND availableExtendedFields contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 6}]\"appmetroplexinfo\")) OR (dummyField contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 7}]\"default\")) AND !(objective contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 8}]\"install_app\"))) AND advt_age = ([{\"id\": 9}]2147483647) AND advt_gender contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 10}]\"all\") AND advt_all_segments = ([{\"id\": 11}]2147483647) AND advt_keywords contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 12}]\"all\") AND advMobilePlatform = ([{\"id\": 13}]2147483647) AND advMobileDeviceType = ([{\"id\": 14}]2147483647) AND advMobileCon = ([{\"id\": 15}]2147483647) AND advMobileOSVersions = ([{\"id\": 16}]2147483647) AND advCarrier = ([{\"id\": 17}]2147483647) AND ([{\"id\": 18}]weightedSet(advt_supply, {\"all\": 1, \"pub223\": 1, \"sec223\": 1, \"site223\": 1})) AND (advt_day_parting contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 19, \"weight\": 1}]\"adv_tuesday\") OR advt_day_parting contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 20, \"weight\": 1}]\"adv_tuesday_17\") OR advt_day_parting contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 21, \"weight\": 1}]\"adv_tuesday_17_forty_five\") OR advt_day_parting contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 22}]\"all\")) AND isAppReengagementAd = ([{\"id\": 23}]0) AND dummyField contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 24}]\"default\") AND serveWithPromotionOnly = ([{\"id\": 26}]0) AND budgetAdvertiserThrottleRateFilter = ([{\"id\": 27}]0) AND budgetResellerThrottleRateFilter = ([{\"id\": 28}]0) AND (isMystiqueRequired = ([{\"id\": 29}]0) OR (isMystiqueRequired = ([{\"id\": 30}]1) AND useBcFactorFilter = ([{\"id\": 31}]1))) AND (((budgetCampaignThrottleRateBits = ([{\"id\": 32}]55) AND dummyField contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 33}]\"default\"))) AND !(useBcFactorFilter = ([{\"id\": 34}]1)) OR ((useBcFactorFilter = ([{\"id\": 35}]1) AND dummyField contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 36}]\"default\") AND (bcFactorTiers = ([{\"id\": 38}]127) OR bcFactorTiers = ([{\"id\": 39}]0)) AND ((firstPriceEnforced = ([{\"id\": 40}]0) AND (secondPriceEnforced = ([{\"id\": 41}]1) OR isPrivateDeal = ([{\"id\": 42}]0) OR (dummyField contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 43}]\"default\")) AND !(bcActiveTier = ([{\"id\": 44}]0)))) OR mystiqueCampaignThrottleRateBits = ([{\"id\": 45}]18)))) AND !(isOutOfDailyBudget = ([{\"id\": 37}]1))) AND testCreative = ([{\"id\": 46}]0) AND advt_geo = ([{\"id\": 47}]2147483647) AND ((adType contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 48}]\"strm_video\") AND isPortraitVideo = ([{\"id\": 49}]0)) OR adType contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 50}]\"stream_ad\")) AND ((isCPM = ([{\"id\": 51}]0) AND isOCPC = ([{\"id\": 52}]0) AND isECPC = ([{\"id\": 53}]0) AND ((priceType contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 54}]\"cpcv\") AND bid >= ([{\"id\": 55}]0.005)) OR (priceType contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 56}]\"cpv\") AND bid >= ([{\"id\": 57}]0.01)) OR (priceType contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 58}]\"cpc\") AND bid >= ([{\"id\": 59}]0.05)) OR (objective contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 60}]\"promote_content\") AND bid >= ([{\"id\": 61}]0.01)) OR hasFloorPriceUsd = ([{\"id\": 62}]1))) OR isECPC = ([{\"id\": 63}]1) OR (isCPM = ([{\"id\": 64}]1) AND isOCPM = ([{\"id\": 65}]0) AND ([{\"id\": 66}]range(bid, 0.25, Infinity) OR hasFloorPriceUsd = ([{\"id\": 67}]1)))) AND start_date <= ([{\"id\": 68}]1572976776299L) AND end_date >= ([{\"id\": 69}]1572976776299L))) AND !(isHoldoutAd = ([{\"id\": 25}]1))) AND !((disclaimerExtensionsTypes contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 70}]\"pharma\") OR ([{\"id\": 71}]weightedSet(exclusion_advt_supply, {\"extsite223\": 1, \"pub223\": 1, \"sec223\": 1, \"site223\": 1})) OR isPersonalized = ([{\"id\": 72}]1) OR blocked_section_ids contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 73}]\"223\") OR blocked_publisher_ids contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 74}]\"223\") OR blocked_site_ids contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 75}]\"223\"))), ([{\"id\": 76, \"label\": \"ad_ocpc_max_cpc\"}]dotProduct(ocpc_max_cpc, {\"0\": 1})), ([{\"id\": 77, \"label\": \"ad_ocpc_min_cpc\"}]dotProduct(ocpc_min_cpc, {\"0\": 1})), ([{\"id\": 78, \"label\": \"ad_ocpc_max_alpha\"}]dotProduct(ocpc_max_alpha, {\"0\": 1})), ([{\"id\": 79, \"label\": \"ad_ocpc_min_alpha\"}]dotProduct(ocpc_min_alpha, {\"0\": 1})), ([{\"id\": 80, \"label\": \"ad_ocpc_alpha_0\"}]dotProduct(ocpc_alpha_0, {\"0\": 1})), ([{\"id\": 81, \"label\": \"ad_ocpc_alpha_1\"}]dotProduct(ocpc_alpha_1, {\"0\": 1})), (bidAdjustmentDayParting contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 82, \"weight\": 1}]\"adv_tuesday\") OR bidAdjustmentDayParting contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 83, \"weight\": 1}]\"adv_tuesday_17\") OR bidAdjustmentDayParting contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 84, \"weight\": 1}]\"adv_tuesday_17_forty_five\") OR bidAdjustmentDayPartingForCostCap contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 85, \"weight\": 1}]\"adv_tuesday\") OR bidAdjustmentDayPartingForCostCap contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 86, \"weight\": 1}]\"adv_tuesday_17\") OR bidAdjustmentDayPartingForCostCap contains ([{\"normalizeCase\": false, \"implicitTransforms\": false, \"id\": 87, \"weight\": 1}]\"adv_tuesday_17_forty_five\")), bidAdjustmentForCpi = ([{\"id\": 88, \"weight\": 1}]223), ([{\"id\": 89, \"label\": \"boostingForBackfill\"}]dotProduct(boostingForBackfill, {\"priority\": 1000})))",
serializedQueryTreeYql);
}
@@ -449,8 +461,8 @@ public class YqlParserTestCase {
"title contains ([{\"id\": 1, \"connectivity\": {\"id\": 4, \"weight\": 7.0}}]\"madonna\") " +
"and title contains ([{\"id\": 2}]\"saint\") " +
"and title contains ([{\"id\": 3}]\"angel\");",
- new NullPointerException("Item 'title:madonna' was specified to connect to item with ID 4, " +
- "which does not exist in the query."));
+ new IllegalArgumentException("Item 'title:madonna' was specified to connect to item with ID 4, " +
+ "which does not exist in the query."));
}
@Test
@@ -513,7 +525,7 @@ public class YqlParserTestCase {
public void testWand() {
assertParse("select foo from bar where wand(description, {\"a\":1, \"b\":2});",
"WAND(10,0.0,1.0) description{[1]:\"a\",[2]:\"b\"}");
- assertParse("select foo from bar where [ {\"scoreThreshold\": 13.3, \"targetNumHits\": 7, " +
+ assertParse("select foo from bar where [ {\"scoreThreshold\": 13.3, \"targetHits\": 7, " +
"\"thresholdBoostFactor\": 2.3} ]wand(description, {\"a\":1, \"b\":2});",
"WAND(7,13.3,2.3) description{[1]:\"a\",[2]:\"b\"}");
}
@@ -548,11 +560,35 @@ public class YqlParserTestCase {
}
@Test
+ public void testGeoLocation() {
+ assertParse("select foo from bar where geoLocation(workplace, 63.418417, 10.433033, \"0.5 deg\");",
+ "GEO_LOCATION workplace:(2,10433033,63418417,500000,0,1,0,1921876103)");
+ assertParse("select foo from bar where geoLocation(headquarters, \"37.416383\", \"-122.024683\", \"100 miles\");",
+ "GEO_LOCATION headquarters:(2,-122024683,37416383,1450561,0,1,0,3411238761)");
+ assertParse("select foo from bar where geoLocation(home, \"E10.433033\", \"N63.418417\", \"5km\");",
+ "GEO_LOCATION home:(2,10433033,63418417,45066,0,1,0,1921876103)");
+
+ assertParseFail("select foo from bar where geoLocation(qux, 1, 2);",
+ new IllegalArgumentException("Expected 4 arguments, got 3."));
+ assertParseFail("select foo from bar where geoLocation(qux, 2.0, \"N5.0\", \"0.5 deg\");",
+ new IllegalArgumentException(
+ "Invalid geoLocation coordinates 'Latitude: 2.0 degrees' and 'Latitude: 5.0 degrees'"));
+ assertParse("select foo from bar where geoLocation(workplace, -12, -34, \"-77 d\");",
+ "GEO_LOCATION workplace:(2,-34000000,-12000000,-1,0,1,0,4201111954)");
+ }
+
+ @Test
public void testNearestNeighbor() {
assertParse("select foo from bar where nearestNeighbor(semantic_embedding, my_vector);",
- "NEAREST_NEIGHBOR {field=semantic_embedding,queryTensorName=my_vector,targetNumHits=0}");
- assertParse("select foo from bar where [{\"targetNumHits\": 37}]nearestNeighbor(semantic_embedding, my_vector);",
- "NEAREST_NEIGHBOR {field=semantic_embedding,queryTensorName=my_vector,targetNumHits=37}");
+ "NEAREST_NEIGHBOR {field=semantic_embedding,queryTensorName=my_vector,hnsw.exploreAdditionalHits=0,distanceThreshold=Infinity,approximate=true,targetHits=0}");
+ assertParse("select foo from bar where [{\"targetHits\": 37}]nearestNeighbor(semantic_embedding, my_vector);",
+ "NEAREST_NEIGHBOR {field=semantic_embedding,queryTensorName=my_vector,hnsw.exploreAdditionalHits=0,distanceThreshold=Infinity,approximate=true,targetHits=37}");
+ assertParse("select foo from bar where [{\"approximate\": false, \"hnsw.exploreAdditionalHits\": 8, \"targetHits\": 3}]nearestNeighbor(semantic_embedding, my_vector);",
+ "NEAREST_NEIGHBOR {field=semantic_embedding,queryTensorName=my_vector,hnsw.exploreAdditionalHits=8,distanceThreshold=Infinity,approximate=false,targetHits=3}");
+
+ assertParse("select foo from bar where [{\"targetHits\": 7, \"distanceThreshold\": 100100.25}]nearestNeighbor(semantic_embedding, my_vector);",
+ "NEAREST_NEIGHBOR {field=semantic_embedding,queryTensorName=my_vector,hnsw.exploreAdditionalHits=0,distanceThreshold=100100.25,approximate=true,targetHits=7}");
+
}
@Test
@@ -592,16 +628,17 @@ public class YqlParserTestCase {
}
@Test
+ @SuppressWarnings("deprecation")
public void testWeakAnd() {
assertParse("select foo from bar where weakAnd(a contains \"A\", b contains \"B\");",
- "WAND(100) a:A b:B");
- assertParse("select foo from bar where [{\"targetNumHits\": 37}]weakAnd(a contains \"A\", " +
+ "WEAKAND(100) a:A b:B");
+ assertParse("select foo from bar where [{\"targetHits\": 37}]weakAnd(a contains \"A\", " +
"b contains \"B\");",
- "WAND(37) a:A b:B");
+ "WEAKAND(37) a:A b:B");
QueryTree tree = parse("select foo from bar where [{\"scoreThreshold\": 41}]weakAnd(a " +
"contains \"A\", b contains \"B\");");
- assertEquals("WAND(100) a:A b:B", tree.toString());
+ assertEquals("WEAKAND(100) a:A b:B", tree.toString());
assertEquals(WeakAndItem.class, tree.getRoot().getClass());
assertEquals(41, ((WeakAndItem)tree.getRoot()).getScoreThreshold());
}
@@ -656,6 +693,12 @@ public class YqlParserTestCase {
}
@Test
+ public void testSourcesWithDash() {
+ assertSources("select foo from source-a where price <= 500;",
+ Arrays.asList("source-a"));
+ }
+
+ @Test
public void testWildCardSources() {
assertSources("select foo from sources * where price <= 500;",
Collections.<String>emptyList());
@@ -747,12 +790,12 @@ public class YqlParserTestCase {
"select foo from bar where title contains \"madonna\""
+ " order by [{\"function\": \"uca\", \"locale\": \"en_US\", \"strength\": \"IDENTICAL\"}]other desc"
+ " limit 600" + " timeout 3;", "title:madonna");
- final FieldOrder fieldOrder = parser.getSorting().fieldOrders().get(0);
+ FieldOrder fieldOrder = parser.getSorting().fieldOrders().get(0);
assertEquals("other", fieldOrder.getFieldName());
assertEquals(Order.DESCENDING, fieldOrder.getSortOrder());
- final AttributeSorter sorter = fieldOrder.getSorter();
+ AttributeSorter sorter = fieldOrder.getSorter();
assertEquals(UcaSorter.class, sorter.getClass());
- final UcaSorter uca = (UcaSorter) sorter;
+ UcaSorter uca = (UcaSorter) sorter;
assertEquals("en_US", uca.getLocale());
assertEquals(UcaSorter.Strength.IDENTICAL, uca.getStrength());
}
@@ -765,22 +808,20 @@ public class YqlParserTestCase {
+ " [{\"function\": \"lowercase\"}]something asc"
+ " limit 600" + " timeout 3;", "title:madonna");
{
- final FieldOrder fieldOrder = parser.getSorting().fieldOrders()
- .get(0);
+ FieldOrder fieldOrder = parser.getSorting().fieldOrders().get(0);
assertEquals("other", fieldOrder.getFieldName());
assertEquals(Order.DESCENDING, fieldOrder.getSortOrder());
- final AttributeSorter sorter = fieldOrder.getSorter();
+ AttributeSorter sorter = fieldOrder.getSorter();
assertEquals(UcaSorter.class, sorter.getClass());
- final UcaSorter uca = (UcaSorter) sorter;
+ UcaSorter uca = (UcaSorter) sorter;
assertEquals("en_US", uca.getLocale());
assertEquals(UcaSorter.Strength.IDENTICAL, uca.getStrength());
}
{
- final FieldOrder fieldOrder = parser.getSorting().fieldOrders()
- .get(1);
+ FieldOrder fieldOrder = parser.getSorting().fieldOrders().get(1);
assertEquals("something", fieldOrder.getFieldName());
assertEquals(Order.ASCENDING, fieldOrder.getSortOrder());
- final AttributeSorter sorter = fieldOrder.getSorter();
+ AttributeSorter sorter = fieldOrder.getSorter();
assertEquals(LowerCaseSorter.class, sorter.getClass());
}
}
@@ -1018,6 +1059,11 @@ public class YqlParserTestCase {
// success: parsed without exception
}
+ @Test
+ public void testAndSegmenting() {
+ parse("select * from sources * where (default contains ([{\"stem\": false}]\"m\") AND default contains ([{\"origin\": {\"original\": \"m\'s\", \"offset\": 0, \"length\": 3}, \"andSegmenting\": true}]phrase(\"m\", \"s\"))) timeout 472;");
+ }
+
private void assertUrlQuery(String field, Query query, boolean startAnchor, boolean endAnchor, boolean endAnchorIsDefault) {
boolean startAnchorIsDefault = false; // Always
diff --git a/container-search/src/test/java/com/yahoo/select/SelectTestCase.java b/container-search/src/test/java/com/yahoo/select/SelectTestCase.java
index 7b1b4fe6362..d1e46a6a8c2 100644
--- a/container-search/src/test/java/com/yahoo/select/SelectTestCase.java
+++ b/container-search/src/test/java/com/yahoo/select/SelectTestCase.java
@@ -1,6 +1,9 @@
// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.select;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
import com.yahoo.prelude.query.AndItem;
import com.yahoo.prelude.query.ExactStringItem;
import com.yahoo.prelude.query.Item;
@@ -14,21 +17,24 @@ import com.yahoo.prelude.query.SuffixItem;
import com.yahoo.prelude.query.WeakAndItem;
import com.yahoo.prelude.query.WordAlternativesItem;
import com.yahoo.prelude.query.WordItem;
+import com.yahoo.processing.IllegalInputException;
import com.yahoo.search.Query;
import com.yahoo.search.grouping.GroupingRequest;
import com.yahoo.search.grouping.request.AllOperation;
+import com.yahoo.search.grouping.request.AttributeValue;
+import com.yahoo.search.grouping.request.CountAggregator;
+import com.yahoo.search.grouping.request.EachOperation;
+import com.yahoo.search.grouping.request.MaxAggregator;
+import com.yahoo.search.grouping.request.MinAggregator;
import com.yahoo.search.query.QueryTree;
import com.yahoo.search.query.Select;
import com.yahoo.search.query.SelectParser;
import com.yahoo.search.query.parser.Parsable;
import com.yahoo.search.query.parser.ParserEnvironment;
import com.yahoo.search.yql.VespaGroupingStep;
-import org.json.JSONException;
-import org.json.JSONObject;
import org.junit.Test;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.List;
import static org.junit.Assert.assertEquals;
@@ -47,15 +53,18 @@ import static org.junit.Assert.fail;
*/
public class SelectTestCase {
+ private static final ObjectMapper jsonMapper = new ObjectMapper();
+
private final SelectParser parser = new SelectParser(new ParserEnvironment());
//------------------------------------------------------------------- "where" tests
@Test
- public void test_contains() throws Exception {
- JSONObject json = new JSONObject();
- List<String> contains = Arrays.asList("default", "foo");
- json.put("contains", contains);
+ public void test_contains() {
+ ObjectNode json = jsonMapper.createObjectNode();
+ ArrayNode arrayNode = jsonMapper.createArrayNode();
+ arrayNode.add("default").add("foo");
+ json.set("contains", arrayNode);
assertParse(json.toString(), "default:foo");
}
@@ -76,21 +85,21 @@ public class SelectTestCase {
@Test
public void testOr() throws Exception {
- JSONObject json_two_or = new JSONObject();
- JSONObject json_three_or = new JSONObject();
- List<String> contains1 = Arrays.asList("title", "madonna");
- List<String> contains2 = Arrays.asList("title", "saint");
- List<String> contains3 = Arrays.asList("title", "angel");
-
- JSONObject contains_json1 = new JSONObject();
- JSONObject contains_json2 = new JSONObject();
- JSONObject contains_json3 = new JSONObject();
- contains_json1.put("contains", contains1);
- contains_json2.put("contains", contains2);
- contains_json3.put("contains", contains3);
-
- json_two_or.put("or", Arrays.asList(contains_json1, contains_json2));
- json_three_or.put("or", Arrays.asList(contains_json1, contains_json2, contains_json3));
+ ObjectNode json_two_or = jsonMapper.createObjectNode();
+ ObjectNode json_three_or = jsonMapper.createObjectNode();
+ ArrayNode contains1 = jsonMapper.createArrayNode().add("title").add("madonna");
+ ArrayNode contains2 = jsonMapper.createArrayNode().add("title").add("saint");
+ ArrayNode contains3 = jsonMapper.createArrayNode().add("title").add("angel");
+
+ ObjectNode contains_json1 = jsonMapper.createObjectNode();
+ ObjectNode contains_json2 = jsonMapper.createObjectNode();
+ ObjectNode contains_json3 = jsonMapper.createObjectNode();
+ contains_json1.set("contains", contains1);
+ contains_json2.set("contains", contains2);
+ contains_json3.set("contains", contains3);
+
+ json_two_or.set("or", jsonMapper.createArrayNode().add(contains_json1).add(contains_json2));
+ json_three_or.set("or", jsonMapper.createArrayNode().add(contains_json1).add(contains_json2).add(contains_json3));
assertParse(json_two_or.toString(), "OR title:madonna title:saint");
assertParse(json_three_or.toString(), "OR title:madonna title:saint title:angel");
@@ -98,178 +107,178 @@ public class SelectTestCase {
@Test
public void testAnd() throws Exception{
- JSONObject json_two_and = new JSONObject();
- JSONObject json_three_and = new JSONObject();
- List<String> contains1 = Arrays.asList("title", "madonna");
- List<String> contains2 = Arrays.asList("title", "saint");
- List<String> contains3 = Arrays.asList("title", "angel");
-
- JSONObject contains_json1 = new JSONObject();
- JSONObject contains_json2 = new JSONObject();
- JSONObject contains_json3 = new JSONObject();
- contains_json1.put("contains", contains1);
- contains_json2.put("contains", contains2);
- contains_json3.put("contains", contains3);
-
- json_two_and.put("and", Arrays.asList(contains_json1, contains_json2));
- json_three_and.put("and", Arrays.asList(contains_json1, contains_json2, contains_json3));
+ ObjectNode json_two_and = jsonMapper.createObjectNode();
+ ObjectNode json_three_and = jsonMapper.createObjectNode();
+ ArrayNode contains1 = jsonMapper.createArrayNode().add("title").add("madonna");
+ ArrayNode contains2 = jsonMapper.createArrayNode().add("title").add("saint");
+ ArrayNode contains3 = jsonMapper.createArrayNode().add("title").add("angel");
+
+ ObjectNode contains_json1 = jsonMapper.createObjectNode();
+ ObjectNode contains_json2 = jsonMapper.createObjectNode();
+ ObjectNode contains_json3 = jsonMapper.createObjectNode();
+ contains_json1.set("contains", contains1);
+ contains_json2.set("contains", contains2);
+ contains_json3.set("contains", contains3);
+
+ json_two_and.set("and", jsonMapper.createArrayNode().add(contains_json1).add(contains_json2));
+ json_three_and.set("and", jsonMapper.createArrayNode().add(contains_json1).add(contains_json2).add(contains_json3));
assertParse(json_two_and.toString(), "AND title:madonna title:saint");
assertParse(json_three_and.toString(), "AND title:madonna title:saint title:angel");
}
@Test
- public void testAndNot() throws JSONException {
- JSONObject json_and_not = new JSONObject();
- List<String> contains1 = Arrays.asList("title", "madonna");
- List<String> contains2 = Arrays.asList("title", "saint");
+ public void testAndNot() {
+ ObjectNode json_and_not = jsonMapper.createObjectNode();
+ ArrayNode contains1 = jsonMapper.createArrayNode().add("title").add("madonna");
+ ArrayNode contains2 = jsonMapper.createArrayNode().add("title").add("saint");
- JSONObject contains_json1 = new JSONObject();
- JSONObject contains_json2 = new JSONObject();
- contains_json1.put("contains", contains1);
- contains_json2.put("contains", contains2);
+ ObjectNode contains_json1 = jsonMapper.createObjectNode();
+ ObjectNode contains_json2 = jsonMapper.createObjectNode();
+ contains_json1.set("contains", contains1);
+ contains_json2.set("contains", contains2);
- json_and_not.put("and_not", Arrays.asList(contains_json1, contains_json2));
+ json_and_not.set("and_not", jsonMapper.createArrayNode().add(contains_json1).add(contains_json2));
assertParse(json_and_not.toString(),
"+title:madonna -title:saint");
}
@Test
- public void testLessThan() throws JSONException {
- JSONObject range_json = new JSONObject();
- JSONObject operators = new JSONObject();
+ public void testLessThan() {
+ ObjectNode range_json = jsonMapper.createObjectNode();
+ ObjectNode operators = jsonMapper.createObjectNode();
operators.put("<", 500);
- List<Object> range = Arrays.asList("price", operators);
+ ArrayNode range = jsonMapper.createArrayNode().add("price").add(operators);
- range_json.put("range", range);
+ range_json.set("range", range);
assertParse(range_json.toString(),
"price:<500");
}
@Test
- public void testGreaterThan() throws JSONException {
- JSONObject range_json = new JSONObject();
- JSONObject operators = new JSONObject();
+ public void testGreaterThan() {
+ ObjectNode range_json = jsonMapper.createObjectNode();
+ ObjectNode operators = jsonMapper.createObjectNode();
operators.put(">", 500);
- List<Object> range = Arrays.asList("price", operators);
+ ArrayNode range = jsonMapper.createArrayNode().add("price").add(operators);
- range_json.put("range", range);
+ range_json.set("range", range);
assertParse(range_json.toString(),
"price:>500");
}
@Test
- public void testLessThanOrEqual() throws JSONException {
- JSONObject range_json = new JSONObject();
- JSONObject operators = new JSONObject();
+ public void testLessThanOrEqual() {
+ ObjectNode range_json = jsonMapper.createObjectNode();
+ ObjectNode operators = jsonMapper.createObjectNode();
operators.put("<=", 500);
- List<Object> range = Arrays.asList("price", operators);
+ ArrayNode range = jsonMapper.createArrayNode().add("price").add(operators);
- range_json.put("range", range);
+ range_json.set("range", range);
assertParse(range_json.toString(),
"price:[;500]");
}
@Test
- public void testGreaterThanOrEqual() throws JSONException {
- JSONObject range_json = new JSONObject();
- JSONObject operators = new JSONObject();
+ public void testGreaterThanOrEqual() {
+ ObjectNode range_json = jsonMapper.createObjectNode();
+ ObjectNode operators = jsonMapper.createObjectNode();
operators.put(">=", 500);
- List<Object> range = Arrays.asList("price", operators);
+ ArrayNode range = jsonMapper.createArrayNode().add("price").add(operators);
- range_json.put("range", range);
+ range_json.set("range", range);
assertParse(range_json.toString(),
"price:[500;]");
}
@Test
- public void testEquality() throws JSONException {
- JSONObject range_json = new JSONObject();
- JSONObject operators = new JSONObject();
+ public void testEquality() {
+ ObjectNode range_json = jsonMapper.createObjectNode();
+ ObjectNode operators = jsonMapper.createObjectNode();
operators.put("=", 500);
- List<Object> range = Arrays.asList("price", operators);
+ ArrayNode range = jsonMapper.createArrayNode().add("price").add(operators);
- range_json.put("range", range);
+ range_json.set("range", range);
assertParse(range_json.toString(),
"price:500");
}
@Test
- public void testNegativeLessThan() throws JSONException {
- JSONObject range_json = new JSONObject();
- JSONObject operators = new JSONObject();
+ public void testNegativeLessThan() {
+ ObjectNode range_json = jsonMapper.createObjectNode();
+ ObjectNode operators = jsonMapper.createObjectNode();
operators.put("<", -500);
- List<Object> range = Arrays.asList("price", operators);
+ ArrayNode range = jsonMapper.createArrayNode().add("price").add(operators);
- range_json.put("range", range);
+ range_json.set("range", range);
assertParse(range_json.toString(),
"price:<-500");
}
@Test
- public void testNegativeGreaterThan() throws JSONException {
- JSONObject range_json = new JSONObject();
- JSONObject operators = new JSONObject();
+ public void testNegativeGreaterThan() {
+ ObjectNode range_json = jsonMapper.createObjectNode();
+ ObjectNode operators = jsonMapper.createObjectNode();
operators.put(">", -500);
- List<Object> range = Arrays.asList("price", operators);
+ ArrayNode range = jsonMapper.createArrayNode().add("price").add(operators);
- range_json.put("range", range);
+ range_json.set("range", range);
assertParse(range_json.toString(),
"price:>-500");
}
@Test
- public void testNegativeLessThanOrEqual() throws JSONException {
- JSONObject range_json = new JSONObject();
- JSONObject operators = new JSONObject();
+ public void testNegativeLessThanOrEqual() {
+ ObjectNode range_json = jsonMapper.createObjectNode();
+ ObjectNode operators = jsonMapper.createObjectNode();
operators.put("<=", -500);
- List<Object> range = Arrays.asList("price", operators);
+ ArrayNode range = jsonMapper.createArrayNode().add("price").add(operators);
- range_json.put("range", range);
+ range_json.set("range", range);
assertParse(range_json.toString(),
"price:[;-500]");
}
@Test
- public void testNegativeGreaterThanOrEqual() throws JSONException {
- JSONObject range_json = new JSONObject();
- JSONObject operators = new JSONObject();
+ public void testNegativeGreaterThanOrEqual() {
+ ObjectNode range_json = jsonMapper.createObjectNode();
+ ObjectNode operators = jsonMapper.createObjectNode();
operators.put(">=", -500);
- List<Object> range = Arrays.asList("price", operators);
+ ArrayNode range = jsonMapper.createArrayNode().add("price").add(operators);
- range_json.put("range", range);
+ range_json.set("range", range);
assertParse(range_json.toString(),
"price:[-500;]");
}
@Test
- public void testNegativeEquality() throws JSONException {
- JSONObject range_json = new JSONObject();
- JSONObject operators = new JSONObject();
+ public void testNegativeEquality() {
+ ObjectNode range_json = jsonMapper.createObjectNode();
+ ObjectNode operators = jsonMapper.createObjectNode();
operators.put("=", -500);
- List<Object> range = Arrays.asList("price", operators);
+ ArrayNode range = jsonMapper.createArrayNode().add("price").add(operators);
- range_json.put("range", range);
+ range_json.set("range", range);
assertParse(range_json.toString(),
"price:-500");
@@ -423,7 +432,7 @@ public class SelectTestCase {
assertParseFail("{ \"and\": [ {\"contains\" : { \"children\" : [\"title\", \"madonna\"], \"attributes\" : {\"id\": 1, \"connectivity\": {\"id\": 4, \"weight\": 7.0}} } }, " +
"{ \"contains\" : { \"children\" : [\"title\", \"saint\"], \"attributes\" : {\"id\": 2} } }, " +
"{ \"contains\" : { \"children\" : [\"title\", \"angel\"], \"attributes\" : {\"id\": 3} } } ] }",
- new NullPointerException("Item 'title:madonna' was specified to connect to item with ID 4, " +
+ new IllegalArgumentException("Item 'title:madonna' was specified to connect to item with ID 4, " +
"which does not exist in the query."));
}
@@ -473,7 +482,7 @@ public class SelectTestCase {
public void testWand() {
assertParse("{ \"wand\": [\"description\", { \"a\": 1, \"b\": 2 }] }",
"WAND(10,0.0,1.0) description{[1]:\"a\",[2]:\"b\"}");
- assertParse("{ \"wand\": { \"children\": [\"description\", { \"a\": 1, \"b\": 2 }], \"attributes\": { \"scoreThreshold\": 13.3, \"targetNumHits\": 7, \"thresholdBoostFactor\": 2.3 } } }",
+ assertParse("{ \"wand\": { \"children\": [\"description\", { \"a\": 1, \"b\": 2 }], \"attributes\": { \"scoreThreshold\": 13.3, \"targetHits\": 7, \"thresholdBoostFactor\": 2.3 } } }",
"WAND(7,13.3,2.3) description{[1]:\"a\",[2]:\"b\"}");
}
@@ -522,14 +531,36 @@ public class SelectTestCase {
}
@Test
+ public void testGeoLocation() {
+ assertParse("{ \"geoLocation\": [ \"workplace\", 63.418417, 10.433033, \"0.5 deg\" ] }",
+ "GEO_LOCATION workplace:(2,10433033,63418417,500000,0,1,0,1921876103)");
+ assertParse("{ \"geoLocation\": [ \"headquarters\", \"37.416383\", \"-122.024683\", \"100 miles\" ] }",
+ "GEO_LOCATION headquarters:(2,-122024683,37416383,1450561,0,1,0,3411238761)");
+ assertParse("{ \"geoLocation\": [ \"home\", \"E10.433033\", \"N63.418417\", \"5km\" ] }",
+ "GEO_LOCATION home:(2,10433033,63418417,45066,0,1,0,1921876103)");
+ assertParse("{ \"geoLocation\": [ \"workplace\", -12.0, -34.0, \"-77 deg\" ] }",
+ "GEO_LOCATION workplace:(2,-34000000,-12000000,-1,0,1,0,4201111954)");
+ }
+
+ @Test
+ public void testNearestNeighbor() {
+ assertParse("{ \"nearestNeighbor\": [ \"f1field\", \"q2prop\" ] }",
+ "NEAREST_NEIGHBOR {field=f1field,queryTensorName=q2prop,hnsw.exploreAdditionalHits=0,distanceThreshold=Infinity,approximate=true,targetHits=0}");
+
+ assertParse("{ \"nearestNeighbor\": { \"children\" : [ \"f3field\", \"q4prop\" ], \"attributes\" : {\"targetHits\": 37, \"hnsw.exploreAdditionalHits\": 42, \"distanceThreshold\": 100100.25 } }}",
+ "NEAREST_NEIGHBOR {field=f3field,queryTensorName=q4prop,hnsw.exploreAdditionalHits=42,distanceThreshold=100100.25,approximate=true,targetHits=37}");
+ }
+
+ @Test
+ @SuppressWarnings("deprecation")
public void testWeakAnd() {
assertParse("{ \"weakAnd\": [{ \"contains\": [\"a\", \"A\"] }, { \"contains\": [\"b\", \"B\"] } ] }",
- "WAND(100) a:A b:B");
- assertParse("{ \"weakAnd\": { \"children\" : [{ \"contains\": [\"a\", \"A\"] }, { \"contains\": [\"b\", \"B\"] } ], \"attributes\" : {\"targetNumHits\": 37} }}",
- "WAND(37) a:A b:B");
+ "WEAKAND(100) a:A b:B");
+ assertParse("{ \"weakAnd\": { \"children\" : [{ \"contains\": [\"a\", \"A\"] }, { \"contains\": [\"b\", \"B\"] } ], \"attributes\" : {\"targetHits\": 37} }}",
+ "WEAKAND(37) a:A b:B");
QueryTree tree = parseWhere("{ \"weakAnd\": { \"children\" : [{ \"contains\": [\"a\", \"A\"] }, { \"contains\": [\"b\", \"B\"] } ], \"attributes\" : {\"scoreThreshold\": 41}}}");
- assertEquals("WAND(100) a:A b:B", tree.toString());
+ assertEquals("WEAKAND(100) a:A b:B", tree.toString());
assertEquals(WeakAndItem.class, tree.getRoot().getClass());
assertEquals(41, ((WeakAndItem)tree.getRoot()).getScoreThreshold());
}
@@ -597,7 +628,7 @@ public class SelectTestCase {
parseWhere("{ \"range\" : { \"children\":[ \"foo\", { \">=\" : 0, \"<=\" : 1 }], \"attributes\" : {\"hitLimit\": 38, \"ascending\": true, \"descending\": false} } }");
} catch (IllegalArgumentException e) {
assertTrue("Expected information about abuse of settings.",
- e.getMessage().contains("both ascending and descending ordering set"));
+ e.getCause().getMessage().contains("both ascending and descending ordering set"));
gotExceptionFromParse = true;
}
assertTrue(gotExceptionFromParse);
@@ -724,6 +755,7 @@ public class SelectTestCase {
assertEquals("all(group(time.dayofmonth(a)) each(output(count())))", query.getSelect().getGrouping().get(0).toString());
Query clone = query.clone();
+ assertEquals(clone.getSelect().getGroupingExpressionString(), query.getSelect().getGroupingExpressionString());
assertNotSame(query.getSelect(), clone.getSelect());
assertNotSame(query.getSelect().getGrouping(), clone.getSelect().getGrouping());
assertNotSame(query.getSelect().getGrouping().get(0), clone.getSelect().getGrouping().get(0));
@@ -732,8 +764,41 @@ public class SelectTestCase {
assertEquals(query.getSelect().getGroupingString(), clone.getSelect().getGroupingString());
assertEquals(query.getSelect().getGrouping().get(0).toString(), clone.getSelect().getGrouping().get(0).toString());
assertEquals(query.getSelect().getGrouping().get(1).toString(), clone.getSelect().getGrouping().get(1).toString());
+ }
+
+ @Test
+ public void testCloneWithGroupingExpressionString() {
+ Query query = new Query();
+ query.getSelect().setGroupingExpressionString("all(group(foo) each(output(count())))");
+ Query clone = query.clone();
+ assertEquals(clone.getSelect().getGroupingExpressionString(), query.getSelect().getGroupingExpressionString());
+ }
+ @Test
+ public void testProgrammaticBuilding() {
+ String expected =
+ "all(group(myfield) max(10000) each(" +
+ "output(min(foo), max(bar)) " +
+ "all(group(foo) max(10000) output(count()))" +
+ "))";
+ Query query = new Query();
+ GroupingRequest grouping = GroupingRequest.newInstance(query);
+ AllOperation root = new AllOperation();
+ root.setGroupBy(new AttributeValue("myfield"));
+ root.setMax(10000);
+ EachOperation each = new EachOperation();
+ each.addOutput(new MinAggregator(new AttributeValue("foo")));
+ each.addOutput(new MaxAggregator(new AttributeValue("bar")));
+ AllOperation all = new AllOperation();
+ all.setGroupBy(new AttributeValue("foo"));
+ all.setMax(10000);
+ all.addOutput(new CountAggregator());
+ each.addChild(all);
+ root.addChild(each);
+ grouping.setRootOperation(root);
+
+ assertEquals(expected, query.getSelect().getGrouping().get(0).toString());
}
//------------------------------------------------------------------- Assert methods
@@ -746,12 +811,14 @@ public class SelectTestCase {
private void assertParseFail(String where, Throwable expectedException) {
try {
parseWhere(where).toString();
- } catch (Throwable t) {
- assertEquals(expectedException.getClass(), t.getClass());
- assertEquals(expectedException.getMessage(), t.getMessage());
- return;
+ fail("Parse succeeded: " + where);
+ } catch (Throwable outer) {
+ assertEquals(IllegalInputException.class, outer.getClass());
+ assertEquals("Illegal JSON query", outer.getMessage());
+ Throwable cause = outer.getCause();
+ assertEquals(expectedException.getClass(), cause.getClass());
+ assertEquals(expectedException.getMessage(), cause.getMessage());
}
- fail("Parse succeeded: " + where);
}
private void assertRootClass(String where, Class<? extends Item> expectedRootClass) {
diff --git a/container-search/src/test/java/com/yahoo/vespa/streamingvisitors/VdsVisitorTestCase.java b/container-search/src/test/java/com/yahoo/vespa/streamingvisitors/VdsVisitorTestCase.java
index 7841b6f715c..fd8383d6b37 100644
--- a/container-search/src/test/java/com/yahoo/vespa/streamingvisitors/VdsVisitorTestCase.java
+++ b/container-search/src/test/java/com/yahoo/vespa/streamingvisitors/VdsVisitorTestCase.java
@@ -130,7 +130,7 @@ public class VdsVisitorTestCase {
traceLevel = 100;
summary = "fancysummary";
profile = "fancyprofile";
- location = "(1,10000,2000,0,1,0)";
+ location = "(2,10000,2000,0,0,1,0)";
sortSpec = "+surname -yearofbirth";
rankProperties = "rankfeature.something=2";
@@ -247,7 +247,7 @@ public class VdsVisitorTestCase {
if (qa.maxBucketsPerVisitor != 0) {
assertEquals(qa.maxBucketsPerVisitor, params.getMaxBucketsPerVisitor());
} else {
- assertEquals(Integer.MAX_VALUE, params.getMaxBucketsPerVisitor());
+ assertEquals(VdsVisitor.MAX_BUCKETS_PER_VISITOR, params.getMaxBucketsPerVisitor());
}
assertEquals(false, params.getDynamicallyIncreaseMaxBucketsPerVisitor());