diff options
Diffstat (limited to 'container-search/src')
15 files changed, 157 insertions, 117 deletions
diff --git a/container-search/src/main/java/com/yahoo/search/dispatch/ReconfigurableDispatcher.java b/container-search/src/main/java/com/yahoo/search/dispatch/ReconfigurableDispatcher.java index 625a8bcb6da..c86c21d677f 100644 --- a/container-search/src/main/java/com/yahoo/search/dispatch/ReconfigurableDispatcher.java +++ b/container-search/src/main/java/com/yahoo/search/dispatch/ReconfigurableDispatcher.java @@ -1,20 +1,17 @@ package com.yahoo.search.dispatch; import com.yahoo.component.ComponentId; +import com.yahoo.component.annotation.Inject; import com.yahoo.config.subscription.ConfigSubscriber; +import com.yahoo.container.QrConfig; import com.yahoo.container.handler.VipStatus; -import com.yahoo.messagebus.network.rpc.SlobrokConfigSubscriber; import com.yahoo.vespa.config.search.DispatchConfig; import com.yahoo.vespa.config.search.DispatchNodesConfig; import com.yahoo.yolean.UncheckedInterruptedException; -import java.util.Objects; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; -import static java.util.Objects.requireNonNull; - /** * @author jonmv */ @@ -22,10 +19,20 @@ public class ReconfigurableDispatcher extends Dispatcher { private final ConfigSubscriber subscriber; - public ReconfigurableDispatcher(ComponentId clusterId, DispatchConfig dispatchConfig, VipStatus vipStatus) { + @Inject + public ReconfigurableDispatcher(ComponentId clusterId, DispatchConfig dispatchConfig, QrConfig qrConfig, VipStatus vipStatus) { super(clusterId, dispatchConfig, new DispatchNodesConfig.Builder().build(), vipStatus); this.subscriber = new ConfigSubscriber(); - this.subscriber.subscribe(this::updateWithNewConfig, DispatchNodesConfig.class, clusterId.stringValue()); + CountDownLatch configured = new CountDownLatch(1); + this.subscriber.subscribe(config -> { updateWithNewConfig(config); configured.countDown(); }, + DispatchNodesConfig.class, configId(clusterId, qrConfig)); + try { + if ( ! configured.await(1, TimeUnit.MINUTES)) + throw new IllegalStateException("timed out waiting for initial dispatch nodes config for " + clusterId.getName()); + } + catch (InterruptedException e) { + throw new UncheckedInterruptedException("interrupted waiting for initial dispatch nodes config for " + clusterId.getName(), e); + } } @Override @@ -34,4 +41,8 @@ public class ReconfigurableDispatcher extends Dispatcher { super.deconstruct(); } + private static String configId(ComponentId clusterId, QrConfig qrConfig) { + return qrConfig.clustername() + "/component/" + clusterId.getName(); + } + } diff --git a/container-search/src/main/java/com/yahoo/search/handler/Json2SingleLevelMap.java b/container-search/src/main/java/com/yahoo/search/handler/Json2SingleLevelMap.java index c931c6a356f..45a0c606584 100644 --- a/container-search/src/main/java/com/yahoo/search/handler/Json2SingleLevelMap.java +++ b/container-search/src/main/java/com/yahoo/search/handler/Json2SingleLevelMap.java @@ -77,7 +77,7 @@ class Json2SingleLevelMap { } else if (token == JsonToken.START_ARRAY) { map.put(fieldName, skipChildren(parser, buf)); } else if (token == JsonToken.START_OBJECT) { - if (fieldName.equals("select.where") || fieldName.equals("select.grouping")) { + if (fieldName.startsWith("input.") || fieldName.equals("select.where") || fieldName.equals("select.grouping")) { map.put(fieldName, skipChildren(parser, buf)); } else { parse(map, fieldName + "."); diff --git a/container-search/src/main/java/com/yahoo/search/logging/AbstractSpoolingLogger.java b/container-search/src/main/java/com/yahoo/search/logging/AbstractSpoolingLogger.java index 601da11ab33..ec8e7dd3a79 100644 --- a/container-search/src/main/java/com/yahoo/search/logging/AbstractSpoolingLogger.java +++ b/container-search/src/main/java/com/yahoo/search/logging/AbstractSpoolingLogger.java @@ -3,7 +3,6 @@ package com.yahoo.search.logging; import com.yahoo.concurrent.DaemonThreadFactory; -import java.io.IOException; import java.time.Clock; import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.ScheduledExecutorService; @@ -54,8 +53,15 @@ public abstract class AbstractSpoolingLogger extends AbstractThreadedLogger impl return true; } - // TODO Call from a component or make this class a component - public void shutdown() { + @Deprecated + /* + @deprecated use {@link #deconstruct()} instead + */ + public void shutdown() { deconstruct(); } + + @Override + public void deconstruct() { + super.deconstruct(); executorService.shutdown(); try { if ( ! executorService.awaitTermination(10, TimeUnit.SECONDS)) diff --git a/container-search/src/main/java/com/yahoo/search/logging/AbstractThreadedLogger.java b/container-search/src/main/java/com/yahoo/search/logging/AbstractThreadedLogger.java index ffc916bad65..db5d0494822 100644 --- a/container-search/src/main/java/com/yahoo/search/logging/AbstractThreadedLogger.java +++ b/container-search/src/main/java/com/yahoo/search/logging/AbstractThreadedLogger.java @@ -2,6 +2,8 @@ package com.yahoo.search.logging; +import com.yahoo.component.AbstractComponent; + import java.util.concurrent.Executor; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.RejectedExecutionException; @@ -10,7 +12,7 @@ import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.logging.Level; -abstract class AbstractThreadedLogger implements Logger { +abstract class AbstractThreadedLogger extends AbstractComponent implements Logger { private final static java.util.logging.Logger log = java.util.logging.Logger.getLogger(AbstractThreadedLogger.class.getName()); @@ -51,10 +53,15 @@ abstract class AbstractThreadedLogger implements Logger { } /** - * Actually transports the entry to it's destination + * Actually transports the entry to its destination */ public abstract boolean transport(LoggerEntry entry); + /** Synchronously shuts down and waits for enqueued entries to be sent. */ + @Override + public void deconstruct() { + executor.close(); + } private static class WorkerThread extends Thread { diff --git a/container-search/src/main/java/com/yahoo/search/query/profile/QueryProfileProperties.java b/container-search/src/main/java/com/yahoo/search/query/profile/QueryProfileProperties.java index f73ed52246c..7b9fe7da7a2 100644 --- a/container-search/src/main/java/com/yahoo/search/query/profile/QueryProfileProperties.java +++ b/container-search/src/main/java/com/yahoo/search/query/profile/QueryProfileProperties.java @@ -108,7 +108,7 @@ public class QueryProfileProperties extends Properties { /** * Sets a value in this query profile * - * @throws IllegalArgumentException if this property cannot be set in the wrapped query profile + * @throws IllegalInputException if this property cannot be set in the wrapped query profile */ @Override public void set(CompoundName name, Object value, Map<String, String> context) { diff --git a/container-search/src/main/java/com/yahoo/search/query/properties/QueryProperties.java b/container-search/src/main/java/com/yahoo/search/query/properties/QueryProperties.java index 896a916aa50..99d6959441a 100644 --- a/container-search/src/main/java/com/yahoo/search/query/properties/QueryProperties.java +++ b/container-search/src/main/java/com/yahoo/search/query/properties/QueryProperties.java @@ -91,6 +91,7 @@ public class QueryProperties extends Properties { addDualCasedRM(map, Matching.MINHITSPERTHREAD, GetterSetter.of(query -> query.getRanking().getMatching().getMinHitsPerThread(), (query, value) -> query.getRanking().getMatching().setMinHitsPerThread(asInteger(value, 0)))); addDualCasedRM(map, Matching.POST_FILTER_THRESHOLD, GetterSetter.of(query -> query.getRanking().getMatching().getPostFilterThreshold(), (query, value) -> query.getRanking().getMatching().setPostFilterThreshold(asDouble(value, 1.0)))); addDualCasedRM(map, Matching.APPROXIMATE_THRESHOLD, GetterSetter.of(query -> query.getRanking().getMatching().getApproximateThreshold(), (query, value) -> query.getRanking().getMatching().setApproximateThreshold(asDouble(value, 0.05)))); + addDualCasedRM(map, Matching.TARGET_HITS_MAX_ADJUSTMENT_FACTOR, GetterSetter.of(query -> query.getRanking().getMatching().getTargetHitsMaxAdjustmentFactor(), (query, value) -> query.getRanking().getMatching().setTargetHitsMaxAdjustmentFactor(asDouble(value, 20.0)))); map.put(CompoundName.fromComponents(Ranking.RANKING, Ranking.MATCH_PHASE, MatchPhase.ATTRIBUTE), GetterSetter.of(query -> query.getRanking().getMatchPhase().getAttribute(), (query, value) -> query.getRanking().getMatchPhase().setAttribute(asString(value, null)))); map.put(CompoundName.fromComponents(Ranking.RANKING, Ranking.MATCH_PHASE, MatchPhase.ASCENDING), GetterSetter.of(query -> query.getRanking().getMatchPhase().getAscending(), (query, value) -> query.getRanking().getMatchPhase().setAscending(asBoolean(value, false)))); @@ -169,7 +170,6 @@ public class QueryProperties extends Properties { return; } - //TODO Why is there error handling in set path and not in get path ? if (key.first().equals(Ranking.RANKING)) { if (key.size() > 2) { String restKey = key.rest().rest().toString(); @@ -189,6 +189,7 @@ public class QueryProperties extends Properties { } } if (reservedPrefix.contains(key.first())) { + // Setting a property under the reserved paths are illegal, while retrieving(get) one is not. throwIllegalParameter(key.rest().toString(), key.first()); } else { super.set(key, value, context); diff --git a/container-search/src/main/java/com/yahoo/search/query/properties/RankProfileInputProperties.java b/container-search/src/main/java/com/yahoo/search/query/properties/RankProfileInputProperties.java index 6c65a5e898a..6203eadffad 100644 --- a/container-search/src/main/java/com/yahoo/search/query/properties/RankProfileInputProperties.java +++ b/container-search/src/main/java/com/yahoo/search/query/properties/RankProfileInputProperties.java @@ -3,6 +3,7 @@ package com.yahoo.search.query.properties; import com.yahoo.api.annotations.Beta; import com.yahoo.language.process.Embedder; +import com.yahoo.processing.IllegalInputException; import com.yahoo.processing.request.CompoundName; import com.yahoo.search.Query; import com.yahoo.search.schema.SchemaInfo; @@ -46,7 +47,7 @@ public class RankProfileInputProperties extends Properties { query.getModel().getLanguage()); } catch (IllegalArgumentException e) { - throw new IllegalArgumentException("Could not set '" + name + "' to '" + value + "'", e); + throw new IllegalInputException("Could not set '" + name + "' to '" + value + "'", e); } } } @@ -84,7 +85,7 @@ public class RankProfileInputProperties extends Properties { } private void throwIllegalInput(CompoundName name, Object value, TensorType expectedType) { - throw new IllegalArgumentException("Could not set '" + name + "' to '" + value + "': " + + throw new IllegalInputException("Could not set '" + name + "' to '" + value + "': " + "This input is declared in rank profile '" + query.getRanking().getProfile() + "' as " + expectedType); } diff --git a/container-search/src/main/java/com/yahoo/search/query/ranking/Matching.java b/container-search/src/main/java/com/yahoo/search/query/ranking/Matching.java index 35fbd52f967..4d21f32d16d 100644 --- a/container-search/src/main/java/com/yahoo/search/query/ranking/Matching.java +++ b/container-search/src/main/java/com/yahoo/search/query/ranking/Matching.java @@ -24,6 +24,7 @@ public class Matching implements Cloneable { public static final String MINHITSPERTHREAD = "minHitsPerThread"; public static final String POST_FILTER_THRESHOLD = "postFilterThreshold"; public static final String APPROXIMATE_THRESHOLD = "approximateThreshold"; + public static final String TARGET_HITS_MAX_ADJUSTMENT_FACTOR = "targetHitsMaxAdjustmentFactor"; static { argumentType =new QueryProfileType(Ranking.MATCHING); @@ -35,6 +36,7 @@ public class Matching implements Cloneable { argumentType.addField(new FieldDescription(MINHITSPERTHREAD, "integer")); argumentType.addField(new FieldDescription(POST_FILTER_THRESHOLD, "double")); argumentType.addField(new FieldDescription(APPROXIMATE_THRESHOLD, "double")); + argumentType.addField(new FieldDescription(TARGET_HITS_MAX_ADJUSTMENT_FACTOR, "double")); argumentType.freeze(); } @@ -46,6 +48,7 @@ public class Matching implements Cloneable { private Integer minHitsPerThread = null; private Double postFilterThreshold = null; private Double approximateThreshold = null; + private Double targetHitsMaxAdjustmentFactor = null; public Double getTermwiseLimit() { return termwiseLimit; } public Integer getNumThreadsPerSearch() { return numThreadsPerSearch; } @@ -53,6 +56,7 @@ public class Matching implements Cloneable { public Integer getMinHitsPerThread() { return minHitsPerThread; } public Double getPostFilterThreshold() { return postFilterThreshold; } public Double getApproximateThreshold() { return approximateThreshold; } + public Double getTargetHitsMaxAdjustmentFactor() { return targetHitsMaxAdjustmentFactor; } public void setTermwiselimit(double value) { if ((value < 0.0) || (value > 1.0)) { @@ -75,6 +79,9 @@ public class Matching implements Cloneable { public void setApproximateThreshold(double threshold) { approximateThreshold = threshold; } + public void setTargetHitsMaxAdjustmentFactor(double factor) { + targetHitsMaxAdjustmentFactor = factor; + } /** Internal operation - DO NOT USE */ public void prepare(RankProperties rankProperties) { @@ -97,6 +104,9 @@ public class Matching implements Cloneable { if (approximateThreshold != null) { rankProperties.put("vespa.matching.global_filter.lower_limit", String.valueOf(approximateThreshold)); } + if (targetHitsMaxAdjustmentFactor != null) { + rankProperties.put("vespa.matching.nns.target_hits_max_adjustment_factor", String.valueOf(targetHitsMaxAdjustmentFactor)); + } } @Override @@ -119,12 +129,14 @@ public class Matching implements Cloneable { Objects.equals(numSearchPartitions, matching.numSearchPartitions) && Objects.equals(minHitsPerThread, matching.minHitsPerThread) && Objects.equals(postFilterThreshold, matching.postFilterThreshold) && - Objects.equals(approximateThreshold, matching.approximateThreshold); + Objects.equals(approximateThreshold, matching.approximateThreshold) && + Objects.equals(targetHitsMaxAdjustmentFactor, matching.targetHitsMaxAdjustmentFactor); } @Override public int hashCode() { - return Objects.hash(termwiseLimit, numThreadsPerSearch, numSearchPartitions, minHitsPerThread, postFilterThreshold, approximateThreshold); + return Objects.hash(termwiseLimit, numThreadsPerSearch, numSearchPartitions, minHitsPerThread, + postFilterThreshold, approximateThreshold, targetHitsMaxAdjustmentFactor); } } diff --git a/container-search/src/main/java/com/yahoo/search/query/ranking/RankFeatures.java b/container-search/src/main/java/com/yahoo/search/query/ranking/RankFeatures.java index f288010a633..724325051f9 100644 --- a/container-search/src/main/java/com/yahoo/search/query/ranking/RankFeatures.java +++ b/container-search/src/main/java/com/yahoo/search/query/ranking/RankFeatures.java @@ -95,7 +95,9 @@ public class RankFeatures implements Cloneable { if (feature == null) return Optional.empty(); if (feature instanceof Tensor) return Optional.of((Tensor)feature); if (feature instanceof Double) return Optional.of(Tensor.from((Double)feature)); - throw new IllegalArgumentException("Expected '" + name + "' to be a tensor, but it is the string '" + feature + "'"); + throw new IllegalArgumentException("Expected '" + name + "' to be a tensor, but it is the string '" + feature + + "', this usually means that '" + name + "' is not defined in the schema. " + + "See https://docs.vespa.ai/en/tensor-user-guide.html#querying-with-tensors"); } /** 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 62b56e6e8ff..4956698cc2f 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 @@ -7,7 +7,6 @@ import com.yahoo.search.dispatch.LoadBalancer.GroupStatus; import com.yahoo.search.dispatch.searchcluster.Group; import com.yahoo.search.dispatch.searchcluster.Node; import org.junit.jupiter.api.Test; -import org.opentest4j.AssertionFailedError; import java.time.Duration; import java.time.Instant; @@ -34,7 +33,7 @@ public class LoadBalancerTest { Optional<Group> grp = lb.takeGroup(null); Group group = grp.orElseThrow(() -> { - throw new AssertionFailedError("Expected a SearchCluster.Group"); + throw new IllegalStateException("Expected a SearchCluster.Group"); }); assertEquals(1, group.nodes().size()); } @@ -47,7 +46,7 @@ public class LoadBalancerTest { Optional<Group> grp = lb.takeGroup(null); Group group = grp.orElseThrow(() -> { - throw new AssertionFailedError("Expected a SearchCluster.Group"); + throw new IllegalStateException("Expected a SearchCluster.Group"); }); assertEquals(1, group.nodes().size()); } diff --git a/container-search/src/test/java/com/yahoo/search/grouping/vespa/RequestBuilderTestCase.java b/container-search/src/test/java/com/yahoo/search/grouping/vespa/RequestBuilderTestCase.java index f8e67a10076..6d02721c15e 100644 --- a/container-search/src/test/java/com/yahoo/search/grouping/vespa/RequestBuilderTestCase.java +++ b/container-search/src/test/java/com/yahoo/search/grouping/vespa/RequestBuilderTestCase.java @@ -25,10 +25,8 @@ import com.yahoo.searchlib.expression.StrCatFunctionNode; import com.yahoo.searchlib.expression.StringResultNode; import com.yahoo.searchlib.expression.TimeStampFunctionNode; import com.yahoo.searchlib.expression.ToStringFunctionNode; -import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; -import java.util.Arrays; import java.util.Collections; import java.util.LinkedList; import java.util.List; @@ -468,29 +466,29 @@ public class RequestBuilderTestCase { String expectedA = "[{ Attribute, result = [Count] }]"; assertLayout("all(group(a) each(output(count())))", - Arrays.asList(expectedA).toString()); + List.of(expectedA).toString()); assertLayout("all(group(a) each(output(count()) all()))", - Arrays.asList(expectedA).toString()); + List.of(expectedA).toString()); assertLayout("all(group(a) each(output(count()) all(group(b))))", - Arrays.asList(expectedA).toString()); + List.of(expectedA).toString()); assertLayout("all(group(a) each(output(count()) all(group(b) each())))", - Arrays.asList(expectedA).toString()); + List.of(expectedA).toString()); assertLayout("all(group(a) each(output(count()) all(group(b) each())))", - Arrays.asList(expectedA).toString()); + List.of(expectedA).toString()); assertLayout("all(group(a) each(output(count()) all(group(b) each())) as(foo)" + " each())", - Arrays.asList(expectedA).toString()); + List.of(expectedA).toString()); assertLayout("all(group(a) each(output(count()) all(group(b) each())) as(foo)" + " each(group(b)))", - Arrays.asList(expectedA).toString()); + List.of(expectedA).toString()); assertLayout("all(group(a) each(output(count()) all(group(b) each())) as(foo)" + " each(group(b) each()))", - Arrays.asList(expectedA).toString()); + List.of(expectedA).toString()); String expectedB = "[{ Attribute }, { Attribute, result = [Count] }]"; assertLayout("all(group(a) each(output(count()) all(group(b) each())) as(foo)" + " each(group(b) each(output(count()))))", - Arrays.asList(expectedB, expectedA).toString()); + List.of(expectedB, expectedA).toString()); } @Test @@ -650,8 +648,8 @@ public class RequestBuilderTestCase { @Test void requireThatTimeZoneIsAppliedToTimeFunctions() { - for (String timePart : Arrays.asList("dayofmonth", "dayofweek", "dayofyear", "hourofday", - "minuteofhour", "monthofyear", "secondofminute", "year")) + for (String timePart : List.of("dayofmonth", "dayofweek", "dayofyear", "hourofday", + "minuteofhour", "monthofyear", "secondofminute", "year")) { String request = "all(output(avg(time." + timePart + "(foo))))"; assertTimeZone(request, "GMT-2", -7200L); @@ -686,7 +684,7 @@ public class RequestBuilderTestCase { test.expectedOutput = Boolean.toString(true); test.request = "all(output(avg(now() - foo)))"; test.outputWriter = new OutputWriter() { - long before = System.currentTimeMillis(); + final long before = System.currentTimeMillis(); @Override public String write(List<Grouping> groupingList, GroupingTransform transform) { @@ -836,7 +834,7 @@ public class RequestBuilderTestCase { builder.build(); fail(); } catch (IllegalInputException e) { - Assertions.assertThat(e.getMessage()).contains(errorSubstring); + assertTrue(e.getMessage().contains(errorSubstring)); } } @@ -924,7 +922,7 @@ public class RequestBuilderTestCase { RequestBuilder builder = new RequestBuilder(0); builder.setRootOperation(GroupingOperation.fromString(test.request)); builder.setTimeZone(TimeZone.getTimeZone(test.timeZone)); - builder.addContinuations(Arrays.asList(test.continuation)); + builder.addContinuations(test.continuation != null ? List.of(test.continuation) : List.of()); try { builder.build(); if (test.expectedException != null) { diff --git a/container-search/src/test/java/com/yahoo/search/handler/JSONSearchHandlerTestCase.java b/container-search/src/test/java/com/yahoo/search/handler/JSONSearchHandlerTestCase.java index 83022ccf3ff..7b8015044c6 100644 --- a/container-search/src/test/java/com/yahoo/search/handler/JSONSearchHandlerTestCase.java +++ b/container-search/src/test/java/com/yahoo/search/handler/JSONSearchHandlerTestCase.java @@ -16,7 +16,6 @@ import com.yahoo.search.searchchain.config.test.SearchChainConfigurerTestCase; import com.yahoo.slime.Inspector; import com.yahoo.slime.SlimeUtils; import com.yahoo.test.json.JsonTestHelper; -import org.assertj.core.api.Assertions; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; @@ -149,7 +148,7 @@ public class JSONSearchHandlerTestCase { configurer.reloadConfig(); SearchHandler newSearchHandler = fetchSearchHandler(configurer); - assertTrue(searchHandler != newSearchHandler, "Do I have a new instance of the search handler?"); + assertNotSame(searchHandler, newSearchHandler, "Do I have a new instance of the search handler?"); try (RequestHandlerTestDriver newDriver = new RequestHandlerTestDriver(newSearchHandler)) { ObjectNode json = jsonMapper.createObjectNode(); json.put("yql", "selectz * from foo where bar > 1453501295"); @@ -193,13 +192,15 @@ public class JSONSearchHandlerTestCase { ObjectNode json = jsonMapper.createObjectNode(); json.put("format", "xml"); - assertEquals("<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n" + - "<result total-hit-count=\"0\">\n" + - " <hit relevancy=\"1.0\">\n" + - " <field name=\"relevancy\">1.0</field>\n" + - " <field name=\"uri\">testHit</field>\n" + - " </hit>\n" + - "</result>\n", driver.sendRequest(uri, com.yahoo.jdisc.http.HttpRequest.Method.POST, json.toString(), JSON_CONTENT_TYPE).readAll()); + assertEquals(""" + <?xml version="1.0" encoding="utf-8" ?> + <result total-hit-count="0"> + <hit relevancy="1.0"> + <field name="relevancy">1.0</field> + <field name="uri">testHit</field> + </hit> + </result> + """, driver.sendRequest(uri, com.yahoo.jdisc.http.HttpRequest.Method.POST, json.toString(), JSON_CONTENT_TYPE).readAll()); } @Test @@ -253,13 +254,15 @@ public class JSONSearchHandlerTestCase { } private static final String xmlResult = - "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n" + - "<result total-hit-count=\"0\">\n" + - " <hit relevancy=\"1.0\">\n" + - " <field name=\"relevancy\">1.0</field>\n" + - " <field name=\"uri\">testHit</field>\n" + - " </hit>\n" + - "</result>\n"; + """ + <?xml version="1.0" encoding="utf-8" ?> + <result total-hit-count="0"> + <hit relevancy="1.0"> + <field name="relevancy">1.0</field> + <field name="uri">testHit</field> + </hit> + </result> + """; private void assertXmlResult(JsonNode json, RequestHandlerTestDriver driver) { assertOkResult(driver.sendRequest(uri, com.yahoo.jdisc.http.HttpRequest.Method.POST, json.toString(), JSON_CONTENT_TYPE), xmlResult); @@ -276,19 +279,6 @@ public class JSONSearchHandlerTestCase { } - private static final String pageResult = - "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n" + - "<page version=\"1.0\">\n" + - "\n" + - " <content>\n" + - " <hit relevance=\"1.0\">\n" + - " <id>testHit</id>\n" + - " <uri>testHit</uri>\n" + - " </hit>\n" + - " </content>\n" + - "\n" + - "</page>\n"; - private void assertOkResult(RequestHandlerTestDriver.MockResponseHandler response, String expected) { assertEquals(expected, response.readAll()); assertEquals(200, response.getStatus()); @@ -302,11 +292,26 @@ public class JSONSearchHandlerTestCase { configurer.reloadConfig(); SearchHandler newSearchHandler = fetchSearchHandler(configurer); - assertTrue(searchHandler != newSearchHandler, "Do I have a new instance of the search handler?"); + assertNotSame(searchHandler, newSearchHandler, "Do I have a new instance of the search handler?"); return new RequestHandlerTestDriver(newSearchHandler); } @Test + void testInputParameters() throws IOException { + String json = """ + { + "input": { + "query(q_category)": { "Tablet Keyboard Cases": 42.5 }, + "query(q_vector)": [ 1, 2.5, 3 ] + } + } + """; + Map<String, String> map = new Json2SingleLevelMap(new ByteArrayInputStream(json.getBytes(StandardCharsets.UTF_8))).parse(); + assertEquals("{ \"Tablet Keyboard Cases\": 42.5 }", map.get("input.query(q_category)")); + assertEquals("[ 1, 2.5, 3 ]", map.get("input.query(q_vector)")); + } + + @Test void testSelectParameters() throws IOException { ObjectNode json = jsonMapper.createObjectNode(); @@ -353,23 +358,25 @@ public class JSONSearchHandlerTestCase { @Test void testJsonWithWhereAndGroupingUnderSelect() { - String query = "{\n" + - " \"select\": {\n" + - " \"where\": {\n" + - " \"contains\": [\n" + - " \"field\",\n" + - " \"term\"\n" + - " ]\n" + - " },\n" + - " \"grouping\":[\n" + - " {\n" + - " \"all\": {\n" + - " \"output\": \"count()\"\n" + - " }\n" + - " }\n" + - " ]\n" + - " }\n" + - "}\n"; + String query = """ + { + "select": { + "where": { + "contains": [ + "field", + "term" + ] + }, + "grouping":[ + { + "all": { + "output": "count()" + } + } + ] + } + } + """; String result = driver.sendRequest(uri + "searchChain=echoingQuery", com.yahoo.jdisc.http.HttpRequest.Method.POST, query, JSON_CONTENT_TYPE).readAll(); String expected = "{\"root\":{\"id\":\"toplevel\",\"relevance\":1.0,\"fields\":{\"totalCount\":0},\"children\":[{\"id\":\"Query\",\"relevance\":1.0,\"fields\":{\"query\":\"select * from sources * where field contains \\\"term\\\" | all(output(count()))\"}}]}}"; @@ -378,21 +385,23 @@ public class JSONSearchHandlerTestCase { @Test void testJsonWithWhereAndGroupingSeparate() { - String query = "{\n" + - " \"select.where\": {\n" + - " \"contains\": [\n" + - " \"field\",\n" + - " \"term\"\n" + - " ]\n" + - " },\n" + - " \"select.grouping\":[\n" + - " {\n" + - " \"all\": {\n" + - " \"output\": \"count()\"\n" + - " }\n" + - " }\n" + - " ]\n" + - "}\n"; + String query = """ + { + "select.where": { + "contains": [ + "field", + "term" + ] + }, + "select.grouping":[ + { + "all": { + "output": "count()" + } + } + ] + } + """; String result = driver.sendRequest(uri + "searchChain=echoingQuery", com.yahoo.jdisc.http.HttpRequest.Method.POST, query, JSON_CONTENT_TYPE).readAll(); String expected = "{\"root\":{\"id\":\"toplevel\",\"relevance\":1.0,\"fields\":{\"totalCount\":0},\"children\":[{\"id\":\"Query\",\"relevance\":1.0,\"fields\":{\"query\":\"select * from sources * where field contains \\\"term\\\" | all(output(count()))\"}}]}}"; @@ -524,7 +533,7 @@ public class JSONSearchHandlerTestCase { // Get mapping Map<String, String> propertyMap = request.propertyMap(); - Assertions.assertThat(propertyMap).isEqualTo(map); + assertEquals(propertyMap, map); } @Test diff --git a/container-search/src/test/java/com/yahoo/search/logging/LocalDiskLoggerTest.java b/container-search/src/test/java/com/yahoo/search/logging/LocalDiskLoggerTest.java index 6ed1154e58a..e94068fa988 100644 --- a/container-search/src/test/java/com/yahoo/search/logging/LocalDiskLoggerTest.java +++ b/container-search/src/test/java/com/yahoo/search/logging/LocalDiskLoggerTest.java @@ -32,21 +32,11 @@ public class LocalDiskLoggerTest { .blob("my entry blob content".getBytes()) .track("my-track") .send(); - waitForFile(logFile); + logger.deconstruct(); String test = IOUtils.readAll(new FileReader(logFile)); assertTrue(test.contains(Base64.getEncoder().encodeToString("my entry blob content".getBytes()))); assertTrue(test.contains("my-track")); } - private void waitForFile(File file) throws InterruptedException { - int waitFor = 10; - while ( ! file.exists() && --waitFor > 0) { - Thread.sleep(10); - } - if ( ! file.exists()) { - fail("Local disk logger file was not created"); - } - } - } 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 e3a1eb18a33..37d0e9e1072 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 @@ -20,6 +20,7 @@ public class MatchingTestCase { assertNull(query.getRanking().getMatching().getMinHitsPerThread()); assertNull(query.getRanking().getMatching().getPostFilterThreshold()); assertNull(query.getRanking().getMatching().getApproximateThreshold()); + assertNull(query.getRanking().getMatching().getTargetHitsMaxAdjustmentFactor()); } @Test @@ -30,13 +31,15 @@ public class MatchingTestCase { "&ranking.matching.numSearchPartitions=13" + "&ranking.matching.minHitsPerThread=3" + "&ranking.matching.postFilterThreshold=0.8" + - "&ranking.matching.approximateThreshold=0.3"); + "&ranking.matching.approximateThreshold=0.3" + + "&ranking.matching.targetHitsMaxAdjustmentFactor=2.5"); 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()); assertEquals(Integer.valueOf(3), query.getRanking().getMatching().getMinHitsPerThread()); assertEquals(Double.valueOf(0.8), query.getRanking().getMatching().getPostFilterThreshold()); assertEquals(Double.valueOf(0.3), query.getRanking().getMatching().getApproximateThreshold()); + assertEquals(Double.valueOf(2.5), query.getRanking().getMatching().getTargetHitsMaxAdjustmentFactor()); query.prepare(); assertEquals("0.7", query.getRanking().getProperties().get("vespa.matching.termwise_limit").get(0)); @@ -45,6 +48,7 @@ public class MatchingTestCase { assertEquals("3", query.getRanking().getProperties().get("vespa.matching.minhitsperthread").get(0)); assertEquals("0.8", query.getRanking().getProperties().get("vespa.matching.global_filter.upper_limit").get(0)); assertEquals("0.3", query.getRanking().getProperties().get("vespa.matching.global_filter.lower_limit").get(0)); + assertEquals("2.5", query.getRanking().getProperties().get("vespa.matching.nns.target_hits_max_adjustment_factor").get(0)); } @Test diff --git a/container-search/src/test/java/com/yahoo/search/query/SortingTestCase.java b/container-search/src/test/java/com/yahoo/search/query/SortingTestCase.java index 8422196638a..b325bde05d9 100644 --- a/container-search/src/test/java/com/yahoo/search/query/SortingTestCase.java +++ b/container-search/src/test/java/com/yahoo/search/query/SortingTestCase.java @@ -81,8 +81,8 @@ public class SortingTestCase { private void requireThatChineseHasCorrectRules(Collator col) { final int reorderCodes [] = {UScript.HAN}; - assertEquals("14.0.0.0", col.getUCAVersion().toString()); - assertEquals("153.112.40.0", col.getVersion().toString()); + assertEquals("15.0.0.0", col.getUCAVersion().toString()); + assertEquals("153.120.43.8", col.getVersion().toString()); assertEquals(Arrays.toString(reorderCodes), Arrays.toString(col.getReorderCodes())); assertNotEquals("", ((RuleBasedCollator) col).getRules()); |