aboutsummaryrefslogtreecommitdiffstats
path: root/config-model/src/test/java/com/yahoo/vespa
diff options
context:
space:
mode:
Diffstat (limited to 'config-model/src/test/java/com/yahoo/vespa')
-rw-r--r--config-model/src/test/java/com/yahoo/vespa/model/ClusterInfoTest.java2
-rw-r--r--config-model/src/test/java/com/yahoo/vespa/model/admin/otel/OpenTelemetryConfigGeneratorTest.java55
-rw-r--r--config-model/src/test/java/com/yahoo/vespa/model/application/validation/ComplexFieldsValidatorTestCase.java26
-rw-r--r--config-model/src/test/java/com/yahoo/vespa/model/application/validation/JvmHeapSizeValidatorTest.java4
-rw-r--r--config-model/src/test/java/com/yahoo/vespa/model/application/validation/QuotaValidatorTest.java6
-rw-r--r--config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/RestartOnDeployForLocalLLMValidatorTest.java79
-rw-r--r--config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/RestartOnDeployForOnnxModelChangesValidatorTest.java10
-rw-r--r--config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/search/ContentClusterFixture.java15
-rw-r--r--config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/search/IndexingScriptChangeValidatorTest.java40
-rw-r--r--config-model/src/test/java/com/yahoo/vespa/model/container/ContainerClusterTest.java18
-rw-r--r--config-model/src/test/java/com/yahoo/vespa/model/container/search/searchchain/SchemaChainsTest.java5
-rw-r--r--config-model/src/test/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilderTest.java27
-rw-r--r--config-model/src/test/java/com/yahoo/vespa/model/content/ContentClusterTest.java84
-rw-r--r--config-model/src/test/java/com/yahoo/vespa/model/ml/ImportedModelTester.java25
-rw-r--r--config-model/src/test/java/com/yahoo/vespa/model/ml/ModelEvaluationTest.java2
-rw-r--r--config-model/src/test/java/com/yahoo/vespa/model/significance/test/SignificanceModelTestCase.java3
16 files changed, 356 insertions, 45 deletions
diff --git a/config-model/src/test/java/com/yahoo/vespa/model/ClusterInfoTest.java b/config-model/src/test/java/com/yahoo/vespa/model/ClusterInfoTest.java
index 4df9f261dfe..7aa6eb76995 100644
--- a/config-model/src/test/java/com/yahoo/vespa/model/ClusterInfoTest.java
+++ b/config-model/src/test/java/com/yahoo/vespa/model/ClusterInfoTest.java
@@ -258,7 +258,7 @@ public class ClusterInfoTest {
.provisioned(provisioner.provisioned())
.build();
new VespaModel(new NullConfigModelRegistry(), deployState);
- return deployState.provisioned().all();
+ return deployState.provisioned().capacities();
}
}
diff --git a/config-model/src/test/java/com/yahoo/vespa/model/admin/otel/OpenTelemetryConfigGeneratorTest.java b/config-model/src/test/java/com/yahoo/vespa/model/admin/otel/OpenTelemetryConfigGeneratorTest.java
index 7c4968aac84..c24fcb27dc9 100644
--- a/config-model/src/test/java/com/yahoo/vespa/model/admin/otel/OpenTelemetryConfigGeneratorTest.java
+++ b/config-model/src/test/java/com/yahoo/vespa/model/admin/otel/OpenTelemetryConfigGeneratorTest.java
@@ -2,8 +2,24 @@
package com.yahoo.vespa.model.admin.otel;
import com.yahoo.config.model.ApplicationConfigProducerRoot.StatePortInfo;
+import com.yahoo.config.model.producer.TreeConfigProducer;
+import com.yahoo.config.model.test.MockRoot;
+import com.yahoo.config.provision.ApplicationId;
+import com.yahoo.config.provision.ClusterMembership;
+import com.yahoo.config.provision.Environment;
+import com.yahoo.config.provision.HostSpec;
+import com.yahoo.config.provision.NodeResources;
+import com.yahoo.config.provision.RegionName;
+import com.yahoo.config.provision.SystemName;
+import com.yahoo.config.provision.Zone;
+import com.yahoo.vespa.model.AbstractService;
+import com.yahoo.vespa.model.Host;
+import com.yahoo.vespa.model.HostResource;
+import com.yahoo.vespa.model.AbstractService;
+import com.yahoo.vespa.model.PortAllocBridge;
import org.junit.jupiter.api.Test;
import java.util.List;
+import java.util.Optional;
import static org.junit.jupiter.api.Assertions.*;
/**
@@ -13,10 +29,45 @@ public class OpenTelemetryConfigGeneratorTest {
@Test
void testBuildsYaml() {
- var generator = new OpenTelemetryConfigGenerator(null);
- generator.addStatePorts(List.of(new StatePortInfo("localhost", 19098, "config-sentinel", "sentinel")));
+ var mockZone = new Zone(SystemName.PublicCd, Environment.prod, RegionName.from("mock"));
+ var app = ApplicationId.from("mytenant", "myapp", "myinstance");
+ var generator = new OpenTelemetryConfigGenerator(mockZone, app);
+ var root = new MockRoot();
+
+ var mockHost = new Host(root, "localhost2.local");
+ var mockVersion = new com.yahoo.component.Version(8);
+ var mockCluster = ClusterMembership.from("container/feeding/2/3", mockVersion, Optional.empty());
+ var noResource = NodeResources.unspecified();
+ var mockHostSpec = new HostSpec("localhost1.local",
+ noResource, noResource, noResource,
+ mockCluster,
+ Optional.empty(), Optional.empty(), Optional.empty());
+ var mockHostResource = new HostResource(mockHost, mockHostSpec);
+ var mockSvc1 = new MockService(root, "sentinel");
+ mockSvc1.setHostResource(mockHostResource);
+ var mockPort1 = new StatePortInfo("localhost", 19098, mockSvc1);
+
+ var mockSvc2 = new MockService(root, "searchnode");
+ mockSvc2.setProp("clustername", "mycluster");
+ mockSvc2.setProp("clustertype", "mockup");
+ var mockPort2 = new StatePortInfo("other.host.local", 19102, mockSvc2);
+
+ generator.addStatePorts(List.of(mockPort1, mockPort2));
String yaml = generator.generate();
+ // System.err.println(">>>\n" + yaml + "\n<<<");
assertTrue(yaml.contains("sentinel"));
}
+ static class MockService extends AbstractService {
+ private final String name;
+ public MockService(TreeConfigProducer<?> parent, String name) {
+ super(parent, name);
+ this.name = name;
+ }
+ public String getServiceName() { return name; }
+ public String getServiceType() { return "dummy"; }
+ @Override public int getPortCount() { return 0; }
+ @Override public void allocatePorts(int start, PortAllocBridge from) { }
+ }
+
}
diff --git a/config-model/src/test/java/com/yahoo/vespa/model/application/validation/ComplexFieldsValidatorTestCase.java b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/ComplexFieldsValidatorTestCase.java
index ae1db366c9f..2e51a425f6d 100644
--- a/config-model/src/test/java/com/yahoo/vespa/model/application/validation/ComplexFieldsValidatorTestCase.java
+++ b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/ComplexFieldsValidatorTestCase.java
@@ -143,6 +143,32 @@ public class ComplexFieldsValidatorTestCase {
}
@Test
+ void logs_warning_when_complex_fields_have_struct_fields_with_index_and_exact_match() throws IOException, SAXException {
+ var logger = new MyLogger();
+ createModelAndValidate(joinLines(
+ "schema test {",
+ " document test {",
+ " field nesteds type array<nested> {",
+ " struct-field foo {",
+ " indexing: attribute | index",
+ " match {",
+ " exact",
+ " exact-terminator: '@@'",
+ " }",
+ " }",
+ " }",
+ " struct nested {",
+ " field foo type string {}",
+ " }",
+ " }",
+ "}"), logger);
+ assertTrue(logger.message.toString().contains("For cluster 'mycluster', schema 'test': " +
+ "The following complex fields have struct fields with 'indexing: index' which is " +
+ "not supported and has no effect: nesteds (nesteds.foo). " +
+ "Remove setting or change to 'indexing: attribute' if needed for matching."));
+ }
+
+ @Test
void validation_passes_when_only_supported_struct_field_attributes_are_used() throws IOException, SAXException {
createModelAndValidate(joinLines("search test {",
" document test {",
diff --git a/config-model/src/test/java/com/yahoo/vespa/model/application/validation/JvmHeapSizeValidatorTest.java b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/JvmHeapSizeValidatorTest.java
index 45125c8eb68..340968f89d1 100644
--- a/config-model/src/test/java/com/yahoo/vespa/model/application/validation/JvmHeapSizeValidatorTest.java
+++ b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/JvmHeapSizeValidatorTest.java
@@ -45,10 +45,10 @@ class JvmHeapSizeValidatorTest {
@Test
void fails_on_too_low_heap_size() throws IOException, SAXException {
- var deployState = createDeployState(2.2, 1024L * 1024 * 1024);
+ var deployState = createDeployState(2.3, 1024L * 1024 * 1024);
var model = new VespaModel(new NullConfigModelRegistry(), deployState);
ValidationTester.expect(new JvmHeapSizeValidator(), model, deployState,
- "Allocated memory to JVM in cluster 'container' is too low (0.50GB < 0.60GB). Estimated cost of ONNX models is 1.00GB.");
+ "Allocated memory to JVM in cluster 'container' is too low (0.51GB < 0.60GB). Estimated cost of ONNX models is 1.00GB.");
}
@Test
diff --git a/config-model/src/test/java/com/yahoo/vespa/model/application/validation/QuotaValidatorTest.java b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/QuotaValidatorTest.java
index 89f81dfdaef..590433757c3 100644
--- a/config-model/src/test/java/com/yahoo/vespa/model/application/validation/QuotaValidatorTest.java
+++ b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/QuotaValidatorTest.java
@@ -54,6 +54,12 @@ public class QuotaValidatorTest {
}
@Test
+ void test_deploy_within_quota_budget_because_in_dev() {
+ var tester = new ValidationTester(13, false, new TestProperties().setHostedVespa(true).setQuota(quota).setZone(devZone));
+ tester.deploy(null, getServices(10), Environment.dev, null, CONTAINER_CLUSTER);
+ }
+
+ @Test
void test_deploy_above_quota_budget_in_publiccd() {
var tester = new ValidationTester(13, false, new TestProperties().setHostedVespa(true).setQuota(quota.withBudget(BigDecimal.ONE)).setZone(publicCdZone));
try {
diff --git a/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/RestartOnDeployForLocalLLMValidatorTest.java b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/RestartOnDeployForLocalLLMValidatorTest.java
new file mode 100644
index 00000000000..13e91f60712
--- /dev/null
+++ b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/RestartOnDeployForLocalLLMValidatorTest.java
@@ -0,0 +1,79 @@
+// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.vespa.model.application.validation.change;
+
+import com.yahoo.config.model.api.ConfigChangeAction;
+import com.yahoo.config.model.deploy.DeployState;
+import com.yahoo.config.model.deploy.TestProperties;
+import com.yahoo.vespa.model.VespaModel;
+import com.yahoo.vespa.model.application.validation.ValidationTester;
+import com.yahoo.vespa.model.test.utils.VespaModelCreatorWithMockPkg;
+import org.junit.jupiter.api.Test;
+
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * @author lesters
+ */
+public class RestartOnDeployForLocalLLMValidatorTest {
+
+ private static final String LOCAL_LLM_COMPONENT = RestartOnDeployForLocalLLMValidator.LOCAL_LLM_COMPONENT;
+
+ @Test
+ void validate_no_restart_on_deploy() {
+ VespaModel current = createModel();
+ VespaModel next = createModel(withComponent(LOCAL_LLM_COMPONENT));
+ List<ConfigChangeAction> result = validateModel(current, next);
+ assertEquals(0, result.size());
+ }
+
+ @Test
+ void validate_restart_on_deploy() {
+ VespaModel current = createModel(withComponent(LOCAL_LLM_COMPONENT));
+ VespaModel next = createModel(withComponent(LOCAL_LLM_COMPONENT));
+ List<ConfigChangeAction> result = validateModel(current, next);
+ assertEquals(1, result.size());
+ assertTrue(result.get(0).validationId().isEmpty());
+ assertEquals("Need to restart services in cluster 'cluster1' due to use of local LLM", result.get(0).getMessage());
+ }
+
+ private static List<ConfigChangeAction> validateModel(VespaModel current, VespaModel next) {
+ return ValidationTester.validateChanges(new RestartOnDeployForLocalLLMValidator(),
+ next,
+ deployStateBuilder().previousModel(current).build());
+ }
+
+ private static VespaModel createModel(String component) {
+ var xml = """
+ <services version='1.0'>
+ <container id='cluster1' version='1.0'>
+ <http>
+ <server id='server1' port='8080'/>
+ </http>
+ %s
+ </container>
+ </services>
+ """.formatted(component);
+ DeployState.Builder builder = deployStateBuilder();
+ return new VespaModelCreatorWithMockPkg(null, xml).create(builder);
+ }
+
+ private static VespaModel createModel() {
+ return createModel("");
+ }
+
+ private static String withComponent(String componentClass) {
+ return "<component id='llm' class='%s' />".formatted(componentClass);
+ }
+
+ private static DeployState.Builder deployStateBuilder() {
+ return new DeployState.Builder().properties(new TestProperties());
+ }
+
+ private static void assertStartsWith(String expected, List<ConfigChangeAction> result) {
+ assertTrue(result.get(0).getMessage().startsWith(expected));
+ }
+
+}
diff --git a/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/RestartOnDeployForOnnxModelChangesValidatorTest.java b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/RestartOnDeployForOnnxModelChangesValidatorTest.java
index 4c0786ea879..484a938476d 100644
--- a/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/RestartOnDeployForOnnxModelChangesValidatorTest.java
+++ b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/RestartOnDeployForOnnxModelChangesValidatorTest.java
@@ -33,7 +33,7 @@ public class RestartOnDeployForOnnxModelChangesValidatorTest {
// Must be so large that changing model set or options requires restart (due to using more memory than available),
// but not so large that deployment will not work at all with one model
- private static final long defaultCost = 723456789;
+ private static final long defaultCost = 635241309;
private static final long defaultHash = 0;
@@ -47,8 +47,8 @@ public class RestartOnDeployForOnnxModelChangesValidatorTest {
@Test
void validate_changed_estimated_cost() {
- VespaModel current = createModel(onnxModelCost(70000000, defaultHash));
- VespaModel next = createModel(onnxModelCost(723456789, defaultHash));
+ VespaModel current = createModel(onnxModelCost(defaultCost, defaultHash));
+ VespaModel next = createModel(onnxModelCost(19 * defaultCost / 20, defaultHash));
List<ConfigChangeAction> result = validateModel(current, next);
assertEquals(1, result.size());
assertTrue(result.get(0).validationId().isEmpty());
@@ -58,8 +58,8 @@ public class RestartOnDeployForOnnxModelChangesValidatorTest {
@Test
void validate_changed_estimated_cost_non_hosted() {
boolean hosted = false;
- VespaModel current = createModel(onnxModelCost(70000000, defaultHash), hosted);
- VespaModel next = createModel(onnxModelCost(723456789, defaultHash), hosted);
+ VespaModel current = createModel(onnxModelCost(defaultCost, defaultHash), hosted);
+ VespaModel next = createModel(onnxModelCost(19 * defaultCost / 20, defaultHash), hosted);
List<ConfigChangeAction> result = validateModel(current, next, hosted);
assertEquals(0, result.size());
}
diff --git a/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/search/ContentClusterFixture.java b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/search/ContentClusterFixture.java
index 8778f0c26c0..0677cabafb0 100644
--- a/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/search/ContentClusterFixture.java
+++ b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/search/ContentClusterFixture.java
@@ -29,11 +29,18 @@ public abstract class ContentClusterFixture {
nextCluster = createCluster(nextSd);
}
+ protected ContentClusterFixture(ContentCluster currentCluster, ContentCluster nextCluster) {
+ this.currentCluster = currentCluster;
+ this.nextCluster = nextCluster;
+ }
+
public ContentClusterFixture(String entireSd) throws Exception {
- currentCluster = new ContentClusterBuilder().build(
- ContentClusterUtils.createMockRoot(List.of(entireSd)));
- nextCluster = new ContentClusterBuilder().build(
- ContentClusterUtils.createMockRoot(List.of(entireSd)));
+ currentCluster = createClusterFromEntireSd(entireSd);
+ nextCluster = createClusterFromEntireSd(entireSd);
+ }
+
+ protected static ContentCluster createClusterFromEntireSd(String sdContent) throws Exception {
+ return new ContentClusterBuilder().build(ContentClusterUtils.createMockRoot(List.of(sdContent)));
}
private static ContentCluster createCluster(String sdContent) throws Exception {
diff --git a/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/search/IndexingScriptChangeValidatorTest.java b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/search/IndexingScriptChangeValidatorTest.java
index cd54a20523f..247f01068fa 100644
--- a/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/search/IndexingScriptChangeValidatorTest.java
+++ b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/search/IndexingScriptChangeValidatorTest.java
@@ -39,6 +39,21 @@ public class IndexingScriptChangeValidatorTest {
}
}
+ private static class ComplexFixture extends ContentClusterFixture {
+ IndexingScriptChangeValidator validator;
+ public ComplexFixture(String currentSd, String nextSd) throws Exception {
+ super(createClusterFromEntireSd(currentSd), createClusterFromEntireSd(nextSd));
+ validator = new IndexingScriptChangeValidator(ClusterSpec.Id.from("test"),
+ currentDb().getDerivedConfiguration().getSchema(),
+ nextDb().getDerivedConfiguration().getSchema());
+ }
+
+ @Override
+ public List<VespaConfigChangeAction> validate() {
+ return validator.validate();
+ }
+ }
+
private static class ScriptFixture {
private final ScriptExpression currentScript;
@@ -56,6 +71,9 @@ public class IndexingScriptChangeValidatorTest {
private static final String FIELD = "field f1 type string";
private static final String FIELD_F2 = "field f2 type string";
+ private static final String TENSOR_FIELD_F1 = "field f1 type tensor(x[2])";
+ private static final String TENSOR_FIELD_F2 = "field f2 type tensor(x[2])";
+ private static final String TENSOR_FIELD_F3 = "field f3 type tensor(x[2])";
private static VespaConfigChangeAction expectedReindexingAction(String changedMsg, String fromScript, String toScript) {
return expectedReindexingAction("f1", changedMsg, fromScript, toScript);
@@ -115,6 +133,28 @@ public class IndexingScriptChangeValidatorTest {
}
@Test
+ void requireThatAddingIndexAspectForExtraTensorFieldWithChangedInputRequireReindexing() throws Exception {
+ new ComplexFixture(joinLines("schema test {",
+ " document test {",
+ " " + TENSOR_FIELD_F1 + " { }",
+ " " + TENSOR_FIELD_F2 + " { }",
+ " }",
+ " " + TENSOR_FIELD_F3 + " { indexing: input f1 | attribute }",
+ "}"),
+ joinLines("schema test {",
+ " document test {",
+ " " + TENSOR_FIELD_F1 + " { }",
+ " " + TENSOR_FIELD_F2 + " { }",
+ " }",
+ " " + TENSOR_FIELD_F3 + " { indexing: input f2 | index | attribute }",
+ "}")).
+ assertValidation(List.of(expectedReindexingAction("f3", "add index aspect",
+ "{ input f1 | attribute f3; }",
+ "{ input f2 | index f3 | attribute f3; }")));
+ }
+
+
+ @Test
void requireThatSettingDynamicSummaryIsOk() throws Exception {
new Fixture(FIELD + " { indexing: summary }",
FIELD + " { indexing: summary \n summary: dynamic }").
diff --git a/config-model/src/test/java/com/yahoo/vespa/model/container/ContainerClusterTest.java b/config-model/src/test/java/com/yahoo/vespa/model/container/ContainerClusterTest.java
index 2ea4249883d..9cf34b55ebf 100644
--- a/config-model/src/test/java/com/yahoo/vespa/model/container/ContainerClusterTest.java
+++ b/config-model/src/test/java/com/yahoo/vespa/model/container/ContainerClusterTest.java
@@ -221,24 +221,6 @@ public class ContainerClusterTest {
}
@Test
- void requireThatJvmOmitStackTraceInFastThrowOptionWorks() {
- // Empty option if option not set in property
- MockRoot root = createRoot(new DeployState.Builder().build());
- ApplicationContainerCluster cluster = newClusterWithSearch(root);
- addContainer(root, cluster, "c1", "host-c1");
- ApplicationContainer container = cluster.getContainers().get(0);
- assertEquals("", container.getJvmOptions());
-
- String jvmOption = "-XX:-foo";
- DeployState deployState = new DeployState.Builder().properties(new TestProperties().setJvmOmitStackTraceInFastThrowOption(jvmOption)).build();
- root = createRoot(deployState);
- cluster = newClusterWithSearch(root);
- addContainer(root, cluster, "c1", "host-c1");
- container = cluster.getContainers().get(0);
- assertEquals(jvmOption, container.getJvmOptions());
- }
-
- @Test
void requireThatWeCanHandleNullJvmOptions() {
MockRoot root = createRoot(false);
ApplicationContainerCluster cluster = newClusterWithSearch(root);
diff --git a/config-model/src/test/java/com/yahoo/vespa/model/container/search/searchchain/SchemaChainsTest.java b/config-model/src/test/java/com/yahoo/vespa/model/container/search/searchchain/SchemaChainsTest.java
index ea43f5c8124..b782366655f 100644
--- a/config-model/src/test/java/com/yahoo/vespa/model/container/search/searchchain/SchemaChainsTest.java
+++ b/config-model/src/test/java/com/yahoo/vespa/model/container/search/searchchain/SchemaChainsTest.java
@@ -142,7 +142,7 @@ public class SchemaChainsTest extends SchemaChainsTestBase {
assertTrue(chain.phases().isEmpty());
assertEquals(1, chain.inherits().size());
assertEquals("native", chain.inherits(0));
- assertEquals(10, chain.components().size());
+ assertEquals(11, chain.components().size());
assertEquals("com.yahoo.prelude.querytransform.PhrasingSearcher@vespa", chain.components(0));
assertEquals("com.yahoo.prelude.searcher.FieldCollapsingSearcher@vespa", chain.components(1));
assertEquals("com.yahoo.search.yql.MinimalQueryInserter@vespa", chain.components(2));
@@ -153,13 +153,14 @@ public class SchemaChainsTest extends SchemaChainsTestBase {
assertEquals("com.yahoo.prelude.semantics.SemanticSearcher@vespa", chain.components(7));
assertEquals("com.yahoo.search.grouping.GroupingQueryParser@vespa", chain.components(8));
assertEquals("com.yahoo.search.querytransform.WeakAndReplacementSearcher@vespa", chain.components(9));
+ assertEquals("com.yahoo.search.searchers.OpportunisticWeakAndSearcher@vespa", chain.components(10));
assertTrue(chain.excludes().isEmpty());
assertEquals(ChainsConfig.Chains.Type.SEARCH, chain.type());
}
@Test
public void require_all_default_chains_are_correct() {
- assertEquals(63, chainsConfig.components().size());
+ assertEquals(64, chainsConfig.components().size());
assertEquals(10, chainsConfig.chains().size());
validateVespaPhasesChain(findChain("vespaPhases"));
validateNativeChain(findChain("native"));
diff --git a/config-model/src/test/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilderTest.java b/config-model/src/test/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilderTest.java
index e704da08d18..60ea37cad3f 100644
--- a/config-model/src/test/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilderTest.java
+++ b/config-model/src/test/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilderTest.java
@@ -17,6 +17,7 @@ import com.yahoo.config.model.provision.InMemoryProvisioner;
import com.yahoo.config.model.provision.SingleNodeProvisioner;
import com.yahoo.config.model.test.MockApplicationPackage;
import com.yahoo.config.model.test.MockRoot;
+import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.CloudAccount;
import com.yahoo.config.provision.Environment;
import com.yahoo.config.provision.Flavor;
@@ -49,6 +50,7 @@ import com.yahoo.vespa.model.container.component.Handler;
import com.yahoo.vespa.model.content.utils.ContentClusterUtils;
import com.yahoo.vespa.model.test.VespaModelTester;
import com.yahoo.vespa.model.test.utils.VespaModelCreatorWithFilePkg;
+import com.yahoo.yolean.Exceptions;
import org.junit.jupiter.api.Test;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;
@@ -598,7 +600,7 @@ public class ContainerModelBuilderTest extends ContainerModelBuilderTestBase {
.setCloudAccount(cloudAccount))
.build());
assertEquals(2, model.hostSystem().getHosts().size());
- assertEquals(List.of(cloudAccount), model.provisioned().all().values()
+ assertEquals(List.of(cloudAccount), model.provisioned().capacities().values()
.stream()
.map(capacity -> capacity.cloudAccount().get())
.toList());
@@ -741,6 +743,29 @@ public class ContainerModelBuilderTest extends ContainerModelBuilderTestBase {
}
@Test
+ void testerContainer() {
+ createModelWithTesterNodes("<nodes count='1' docker-image='foo/bar/baz'><resources vcpu='0.1' memory='1Gb' disk='1Gb'/></nodes>");
+
+ assertEquals("In container cluster 'default': tester cannot run on more than 1 node, but 2 nodes were specified",
+ Exceptions.toMessageString(assertThrows(IllegalArgumentException.class,
+ () -> createModelWithTesterNodes("<nodes count='2'/>"))));
+
+ assertEquals("In container cluster 'default': tester resources must be absolute, but min and max resources differ: specification of dedicated " +
+ "min 1 nodes with [vcpu: 0.0, memory: 1.0 Gb, disk: 0.0 Gb, bandwidth: 0.3 Gbps, architecture: any] " +
+ "max 1 nodes with [vcpu: 0.0, memory: 2.0 Gb, disk: 0.0 Gb, bandwidth: 0.3 Gbps, architecture: any]",
+ Exceptions.toMessageString(assertThrows(IllegalArgumentException.class,
+ () -> createModelWithTesterNodes("<nodes><resources memory='[1Gb, 2Gb]'/></nodes>"))));
+ }
+
+ void createModelWithTesterNodes(String testerNodesXml) {
+ String containerXml = "<container id='default' version='1.0'>%s</container>".formatted(testerNodesXml);
+ VespaModelTester tester = new VespaModelTester();
+ tester.setApplicationId("t", "a", "i-t");
+ tester.addHosts(3);
+ tester.createModel(containerXml, true);
+ }
+
+ @Test
void cluster_with_zookeeper() {
Function<Integer, String> servicesXml = (nodeCount) -> "<container version='1.0' id='default'>" +
"<nodes count='" + nodeCount + "'/>" +
diff --git a/config-model/src/test/java/com/yahoo/vespa/model/content/ContentClusterTest.java b/config-model/src/test/java/com/yahoo/vespa/model/content/ContentClusterTest.java
index 786caa4b317..5dca5a9eaa1 100644
--- a/config-model/src/test/java/com/yahoo/vespa/model/content/ContentClusterTest.java
+++ b/config-model/src/test/java/com/yahoo/vespa/model/content/ContentClusterTest.java
@@ -1,6 +1,7 @@
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.model.content;
+import com.yahoo.config.application.api.DeployLogger;
import com.yahoo.config.model.api.ApplicationClusterEndpoint;
import com.yahoo.config.model.api.ContainerEndpoint;
import com.yahoo.config.model.api.ModelContext;
@@ -48,6 +49,8 @@ import java.util.Map;
import java.util.Optional;
import java.util.OptionalInt;
import java.util.Set;
+import java.util.function.Consumer;
+import java.util.logging.Level;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
@@ -941,8 +944,19 @@ public class ContentClusterTest extends ContentBaseTest {
}
private static ContentCluster createOneNodeCluster(String clusterXml, TestProperties props, Optional<Flavor> flavor) throws Exception {
+ return createOneNodeCluster(clusterXml, props, flavor, new StringBuffer());
+ }
+
+ private static ContentCluster createOneNodeCluster(String clusterXml, TestProperties props,
+ Optional<Flavor> flavor, StringBuffer deployWarningsBuffer) throws Exception {
+ DeployLogger logger = (level, message) -> {
+ if (level == Level.WARNING) { // only care about warnings
+ deployWarningsBuffer.append("%s\n".formatted(message));
+ }
+ };
DeployState.Builder deployStateBuilder = new DeployState.Builder()
- .properties(props);
+ .properties(props)
+ .deployLogger(logger);
MockRoot root = flavor.isPresent() ?
ContentClusterUtils.createMockRoot(new SingleNodeProvisioner(flavor.get()),
List.of(), deployStateBuilder) :
@@ -1471,13 +1485,18 @@ public class ContentClusterTest extends ContentBaseTest {
assertEquals(expectedGroupsAllowedDown, config.max_number_of_groups_allowed_to_be_down());
}
- private boolean resolveDistributorOperationCancellationConfig(Integer featureLevel) throws Exception {
+ private StorDistributormanagerConfig resolveDistributorConfig(Consumer<TestProperties> propertyMutator) throws Exception {
var properties = new TestProperties();
- if (featureLevel != null) {
- properties.setContentLayerMetadataFeatureLevel(featureLevel);
- }
- var cfg = resolveStorDistributormanagerConfig(properties);
- return cfg.enable_operation_cancellation();
+ propertyMutator.accept(properties);
+ return resolveStorDistributormanagerConfig(properties);
+ }
+
+ private boolean resolveDistributorOperationCancellationConfig(Integer featureLevel) throws Exception {
+ return resolveDistributorConfig((props) -> {
+ if (featureLevel != null) {
+ props.setContentLayerMetadataFeatureLevel(featureLevel);
+ }
+ }).enable_operation_cancellation();
}
@Test
@@ -1488,6 +1507,21 @@ public class ContentClusterTest extends ContentBaseTest {
assertTrue(resolveDistributorOperationCancellationConfig(2));
}
+ private boolean resolveDistributorSymmetricReplicaSelectionConfig(Boolean flagValue) throws Exception {
+ return resolveDistributorConfig((props) -> {
+ if (flagValue != null) {
+ props.setSymmetricPutAndActivateReplicaSelection(flagValue);
+ }
+ }).symmetric_put_and_activate_replica_selection();
+ }
+
+ @Test
+ void distributor_symmetric_replica_selection_config_controlled_by_properties() throws Exception {
+ assertFalse(resolveDistributorSymmetricReplicaSelectionConfig(null)); // defaults to false
+ assertFalse(resolveDistributorSymmetricReplicaSelectionConfig(false));
+ assertTrue(resolveDistributorSymmetricReplicaSelectionConfig(true));
+ }
+
@Test
void node_distribution_key_outside_legal_range_is_disallowed() {
// Only [0, UINT16_MAX - 1] is a valid range. UINT16_MAX is a special content layer-internal
@@ -1506,6 +1540,42 @@ public class ContentClusterTest extends ContentBaseTest {
}
}
+ private String createClusterAndGetDeploymentWarnings(String xml) {
+ var warningBuf = new StringBuffer();
+ try {
+ createOneNodeCluster(xml, new TestProperties(), Optional.empty(), warningBuf);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ return warningBuf.toString();
+ };
+
+ private static String clusterXmlWithNodeDistributionKey(int key) {
+ return "<content version=\"1.0\" id=\"mockcluster\">" +
+ " <redundancy>1</redundancy>" +
+ " <documents/>" +
+ " <group>" +
+ " <node distribution-key=\"%d\" hostalias=\"mockhost\"/>".formatted(key) +
+ " </group>" +
+ "</content>";
+ }
+
+ @Test
+ void distribution_key_much_higher_than_node_count_logs_deployment_warning() {
+ // "much higher" is somewhat arbitrary, but needs to be kept in track with threshold in `ContentCluster`.
+ String warnings = createClusterAndGetDeploymentWarnings(clusterXmlWithNodeDistributionKey(101));
+ assertEquals(warnings, "Content cluster 'mockcluster' has 1 node(s), but the highest distribution " +
+ "key is 101. Having much higher distribution keys than the number of nodes " +
+ "is not recommended, as it may negatively affect performance. " +
+ "See https://docs.vespa.ai/en/reference/services-content.html#node\n");
+ }
+
+ @Test
+ void distribution_key_not_much_higher_than_node_count_does_not_log_deployment_warning() {
+ String warnings = createClusterAndGetDeploymentWarnings(clusterXmlWithNodeDistributionKey(100));
+ assertEquals(warnings, "");
+ }
+
private String servicesWithGroups(int groupCount, double minGroupUpRatio) {
String services = String.format("<?xml version='1.0' encoding='UTF-8' ?>" +
"<services version='1.0'>" +
diff --git a/config-model/src/test/java/com/yahoo/vespa/model/ml/ImportedModelTester.java b/config-model/src/test/java/com/yahoo/vespa/model/ml/ImportedModelTester.java
index 4fd61f59ed7..6114cc7d8bf 100644
--- a/config-model/src/test/java/com/yahoo/vespa/model/ml/ImportedModelTester.java
+++ b/config-model/src/test/java/com/yahoo/vespa/model/ml/ImportedModelTester.java
@@ -8,9 +8,14 @@ import ai.vespa.rankingexpression.importer.tensorflow.TensorFlowImporter;
import ai.vespa.rankingexpression.importer.vespa.VespaImporter;
import ai.vespa.rankingexpression.importer.xgboost.XGBoostImporter;
import com.yahoo.config.FileReference;
+import com.yahoo.config.application.api.ApplicationFile;
import com.yahoo.config.model.ApplicationPackageTester;
import com.yahoo.config.model.api.ApplicationClusterEndpoint;
import com.yahoo.config.model.api.ContainerEndpoint;
+import com.yahoo.config.model.api.OnnxModelCost;
+import com.yahoo.config.model.api.OnnxModelCost.Calculator;
+import com.yahoo.config.model.api.OnnxModelCost.ModelInfo;
+import com.yahoo.config.model.api.OnnxModelOptions;
import com.yahoo.config.model.deploy.DeployState;
import com.yahoo.io.GrowableByteBuffer;
import com.yahoo.io.IOUtils;
@@ -22,7 +27,10 @@ import org.xml.sax.SAXException;
import java.io.IOException;
import java.io.UncheckedIOException;
+import java.net.URI;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.Optional;
import java.util.Set;
@@ -47,6 +55,7 @@ public class ImportedModelTester {
private final String modelName;
private final Path applicationDir;
private final DeployState deployState;
+ public final Calculator calculator = new MockCalculator();
public ImportedModelTester(String modelName, Path applicationDir) {
this(modelName, applicationDir, new DeployState.Builder());
@@ -58,6 +67,7 @@ public class ImportedModelTester {
deployState = deployStateBuilder.applicationPackage(ApplicationPackageTester.create(applicationDir.toString()).app())
.endpoints(Set.of(new ContainerEndpoint("container", ApplicationClusterEndpoint.Scope.zone, List.of("default.example.com"))))
.modelImporters(importers)
+ .onnxModelCost((pkg, app, cluster) -> calculator)
.build();
}
@@ -98,4 +108,19 @@ public class ImportedModelTester {
}
}
+ public static class MockCalculator implements OnnxModelCost.Calculator {
+ private final Map<String, ModelInfo> models = new HashMap<>();
+ @Override public long aggregatedModelCostInBytes() { return models.size(); }
+ @Override public void registerModel(ApplicationFile path, OnnxModelOptions onnxModelOptions) {
+ models.put(path.toString(), new ModelInfo(path.toString(), 1, 1, onnxModelOptions));
+ }
+ @Override public void registerModel(URI uri, OnnxModelOptions onnxModelOptions) {
+ models.put(uri.toString(), new ModelInfo(uri.toString(), 1, 1, onnxModelOptions));
+ }
+ @Override public Map<String, ModelInfo> models() { return Map.copyOf(models); }
+ @Override public void setRestartOnDeploy() { }
+ @Override public boolean restartOnDeploy() { return false; }
+ @Override public void store() { }
+ }
+
}
diff --git a/config-model/src/test/java/com/yahoo/vespa/model/ml/ModelEvaluationTest.java b/config-model/src/test/java/com/yahoo/vespa/model/ml/ModelEvaluationTest.java
index cc33c8561fc..bced4c546c6 100644
--- a/config-model/src/test/java/com/yahoo/vespa/model/ml/ModelEvaluationTest.java
+++ b/config-model/src/test/java/com/yahoo/vespa/model/ml/ModelEvaluationTest.java
@@ -55,6 +55,7 @@ public class ModelEvaluationTest {
RankProfilesConfig config = new RankProfilesConfig(b);
assertEquals(0, config.rankprofile().size());
+ assertEquals(0, tester.calculator.aggregatedModelCostInBytes());
}
finally {
IOUtils.recursiveDeleteDir(appDir.append(ApplicationPackage.MODELS_GENERATED_DIR).toFile());
@@ -69,6 +70,7 @@ public class ModelEvaluationTest {
try {
ImportedModelTester tester = new ImportedModelTester("ml_serving", appDir);
assertHasMlModels(tester.createVespaModel(), appDir);
+ assertEquals(3, tester.calculator.aggregatedModelCostInBytes());
// At this point the expression is stored - copy application to another location which do not have a models dir
storedAppDir.toFile().mkdirs();
diff --git a/config-model/src/test/java/com/yahoo/vespa/model/significance/test/SignificanceModelTestCase.java b/config-model/src/test/java/com/yahoo/vespa/model/significance/test/SignificanceModelTestCase.java
index 00e95a34287..26e8c67a226 100644
--- a/config-model/src/test/java/com/yahoo/vespa/model/significance/test/SignificanceModelTestCase.java
+++ b/config-model/src/test/java/com/yahoo/vespa/model/significance/test/SignificanceModelTestCase.java
@@ -37,9 +37,6 @@ public class SignificanceModelTestCase {
ApplicationContainerCluster containerCluster = vespaModel.getContainerClusters().get("container");
var significanceConfig = assertSignificancePresent(containerCluster);
assertEquals(3, significanceConfig.model().size());
- assertEquals("en", significanceConfig.model().get(0).language());
- assertEquals("no", significanceConfig.model().get(1).language());
- assertEquals("ru", significanceConfig.model().get(2).language());
assertEquals("models/idf-norwegian-wiki.json.zst", modelReference(significanceConfig.model().get(1), "path").path().orElseThrow().value());
assertEquals("https://some/uri/blob.json", modelReference(significanceConfig.model().get(2), "path").url().orElseThrow().value());