diff options
Diffstat (limited to 'config-model/src/test')
16 files changed, 228 insertions, 136 deletions
diff --git a/config-model/src/test/derived/imported_struct_fields/summarymap.cfg b/config-model/src/test/derived/imported_struct_fields/summarymap.cfg index cd19a75e85f..653b0a26b75 100644 --- a/config-model/src/test/derived/imported_struct_fields/summarymap.cfg +++ b/config-model/src/test/derived/imported_struct_fields/summarymap.cfg @@ -1,4 +1,7 @@ defaultoutputclass -1 +override[].field "documentid" +override[].command "documentid" +override[].arguments "" override[].field "my_elem_array" override[].command "attributecombiner" override[].arguments "" diff --git a/config-model/src/test/java/com/yahoo/schema/derived/SummaryMapTestCase.java b/config-model/src/test/java/com/yahoo/schema/derived/SummaryMapTestCase.java index f0fc58b97e5..2f1b837554d 100644 --- a/config-model/src/test/java/com/yahoo/schema/derived/SummaryMapTestCase.java +++ b/config-model/src/test/java/com/yahoo/schema/derived/SummaryMapTestCase.java @@ -162,23 +162,42 @@ public class SummaryMapTestCase extends AbstractSchemaTestCase { assertFalse(SummaryMap.isDynamicCommand(SummaryTransform.ATTRIBUTE.getName())); } + @Test + public void documentid_summary_field_has_corresponding_summary_transform() throws ParseException { + var schema = buildSchema("field foo type string { indexing: summary }", + joinLines("document-summary bar {", + " summary documentid type string {}", + "}")); + assertOverride(schema, "documentid", SummaryTransform.DOCUMENT_ID.getName(), ""); + } + + @Test + public void documentid_summary_transform_requires_disk_access() { + assertFalse(SummaryTransform.DOCUMENT_ID.isInMemory()); + } + private void assertOverride(String fieldContent, String expFieldName, String expCommand) throws ParseException { - var summaryMap = new SummaryMap(buildSearch(fieldContent)); + assertOverride(buildSchema(fieldContent, ""), expFieldName, expCommand, expFieldName); + } + + private void assertOverride(Schema schema, String expFieldName, String expCommand, String expArguments) throws ParseException { + var summaryMap = new SummaryMap(schema); var cfgBuilder = new SummarymapConfig.Builder(); summaryMap.getConfig(cfgBuilder); var cfg = new SummarymapConfig(cfgBuilder); var override = cfg.override(0); assertEquals(expFieldName, override.field()); assertEquals(expCommand, override.command()); - assertEquals(expFieldName, override.arguments()); + assertEquals(expArguments, override.arguments()); } - private Schema buildSearch(String field) throws ParseException { + private Schema buildSchema(String field, String documentSummary) throws ParseException { var builder = new ApplicationBuilder(new RankProfileRegistry()); builder.addSchema(joinLines("search test {", " document test {", field, " }", + documentSummary, "}")); builder.build(true); return builder.getSchema(); diff --git a/config-model/src/test/java/com/yahoo/schema/processing/RankingExpressionTypeResolverTestCase.java b/config-model/src/test/java/com/yahoo/schema/processing/RankingExpressionTypeResolverTestCase.java index 4b6a22fc81a..f2f2a82b97c 100644 --- a/config-model/src/test/java/com/yahoo/schema/processing/RankingExpressionTypeResolverTestCase.java +++ b/config-model/src/test/java/com/yahoo/schema/processing/RankingExpressionTypeResolverTestCase.java @@ -456,7 +456,7 @@ public class RankingExpressionTypeResolverTestCase { builder.build(true); String message = logger.findMessage("The following query features"); assertNotNull(message); - assertEquals("WARNING: The following query features used in rank profile 'my_rank_profile' are not declared in query profile types and " + + assertEquals("WARNING: The following query features used in rank profile 'my_rank_profile' are not declared and " + "will be interpreted as scalars, not tensors: [query(bar), query(baz), query(foo)]", message); } diff --git a/config-model/src/test/java/com/yahoo/schema/processing/RankingExpressionWithOnnxTestCase.java b/config-model/src/test/java/com/yahoo/schema/processing/RankingExpressionWithOnnxTestCase.java index 94a51d25717..bfd0520c62a 100644 --- a/config-model/src/test/java/com/yahoo/schema/processing/RankingExpressionWithOnnxTestCase.java +++ b/config-model/src/test/java/com/yahoo/schema/processing/RankingExpressionWithOnnxTestCase.java @@ -391,7 +391,7 @@ public class RankingExpressionWithOnnxTestCase { @Override public ApplicationFile getFile(Path file) { - return new MockApplicationFile(file, Path.fromString(root().toString())); + return new MockApplicationFile(file, root()); } @Override diff --git a/config-model/src/test/java/com/yahoo/vespa/model/admin/metricsproxy/MetricsProxyContainerClusterTest.java b/config-model/src/test/java/com/yahoo/vespa/model/admin/metricsproxy/MetricsProxyContainerClusterTest.java index 7bf08461df7..d50aedeafa0 100644 --- a/config-model/src/test/java/com/yahoo/vespa/model/admin/metricsproxy/MetricsProxyContainerClusterTest.java +++ b/config-model/src/test/java/com/yahoo/vespa/model/admin/metricsproxy/MetricsProxyContainerClusterTest.java @@ -70,7 +70,7 @@ public class MetricsProxyContainerClusterTest { @Test public void http_handlers_are_set_up() { VespaModel model = getModel(servicesWithAdminOnly(), self_hosted); - Collection<Handler<?>> handlers = model.getAdmin().getMetricsProxyCluster().getHandlers(); + Collection<Handler> handlers = model.getAdmin().getMetricsProxyCluster().getHandlers(); Collection<ComponentSpecification> handlerClasses = handlers.stream().map(Component::getClassId).collect(toList()); assertTrue(handlerClasses.contains(ComponentSpecification.fromString(MetricsV1Handler.class.getName()))); diff --git a/config-model/src/test/java/com/yahoo/vespa/model/application/validation/ComplexAttributeFieldsValidatorTestCase.java b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/ComplexFieldsValidatorTestCase.java index 85050aa0cf9..11e4ae855a5 100644 --- a/config-model/src/test/java/com/yahoo/vespa/model/application/validation/ComplexAttributeFieldsValidatorTestCase.java +++ b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/ComplexFieldsValidatorTestCase.java @@ -22,7 +22,7 @@ import static com.yahoo.config.model.test.TestUtil.joinLines; /** * @author geirst */ -public class ComplexAttributeFieldsValidatorTestCase { +public class ComplexFieldsValidatorTestCase { @SuppressWarnings("deprecation") @Rule @@ -78,6 +78,30 @@ public class ComplexAttributeFieldsValidatorTestCase { } @Test + public void throws_when_complex_fields_have_struct_fields_with_index() throws IOException, SAXException { + exceptionRule.expect(IllegalArgumentException.class); + exceptionRule.expectMessage("For cluster 'mycluster', schema 'test': " + + "The following complex fields have struct fields with 'indexing: index' which is not supported: " + + "topics (topics.id, topics.label). Change to 'indexing: attribute' instead"); + createModelAndValidate(joinLines( + "schema test {", + "document test {", + "struct topic {", + " field id type string {}", + " field label type string {}", + " field desc type string {}", + "}", + "field topics type array<topic> {", + " indexing: summary", + " struct-field id { indexing: index }", + " struct-field label { indexing: index | attribute }", + " struct-field desc { indexing: attribute }", + "}", + "}", + "}")); + } + + @Test public 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/QuotaValidatorTest.java b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/QuotaValidatorTest.java index 8750d3caa47..5e746d462b5 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 @@ -47,7 +47,7 @@ public class QuotaValidatorTest { tester.deploy(null, getServices("testCluster", 10), Environment.prod, null); fail(); } catch (RuntimeException e) { - assertEquals("Deployment would make your tenant exceed its quota and has been blocked! Please contact support to update your plan.", e.getMessage()); + assertEquals("Deployment exceeds its quota and has been blocked! Please contact support to update your plan: Quota is $1.25, but at least $1.63 is required", e.getMessage()); } } @@ -58,7 +58,7 @@ public class QuotaValidatorTest { tester.deploy(null, getServices("testCluster", 10), Environment.prod, null); fail(); } catch (RuntimeException e) { - assertEquals("publiccd: Deployment would make your tenant exceed its quota and has been blocked! Please contact support to update your plan.", e.getMessage()); + assertEquals("publiccd: Deployment exceeds its quota and has been blocked! Please contact support to update your plan: Quota is $1.00, but at least $1.63 is required", e.getMessage()); } } @@ -69,7 +69,7 @@ public class QuotaValidatorTest { tester.deploy(null, getServices("testCluster", 10), Environment.prod, null); fail(); } catch (RuntimeException e) { - assertEquals("publiccd: Deployment would make your tenant exceed its quota and has been blocked! Please contact support to update your plan.", e.getMessage()); + assertEquals("publiccd: Deployment exceeds its quota and has been blocked! Please contact support to update your plan: Quota is $1.25, but at least $1.63 is required", e.getMessage()); } } @@ -82,7 +82,7 @@ public class QuotaValidatorTest { tester.deploy(null, getServices("testCluster", 10), Environment.prod, null); fail(); } catch (RuntimeException e) { - assertEquals("Please free up some capacity! This deployment's quota use is ($-.--) and reserved quota is below zero! ($--.--)", + assertEquals("Please free up some capacity: Quota is $--.--, but at least $-.-- is required", ValidationTester.censorNumbers(e.getMessage())); } } diff --git a/config-model/src/test/java/com/yahoo/vespa/model/builder/xml/dom/DomAdminV2BuilderTest.java b/config-model/src/test/java/com/yahoo/vespa/model/builder/xml/dom/DomAdminV2BuilderTest.java index 1a41d2689a2..072f88602a6 100755 --- a/config-model/src/test/java/com/yahoo/vespa/model/builder/xml/dom/DomAdminV2BuilderTest.java +++ b/config-model/src/test/java/com/yahoo/vespa/model/builder/xml/dom/DomAdminV2BuilderTest.java @@ -36,16 +36,6 @@ public class DomAdminV2BuilderTest extends DomBuilderTest { root = new MockRoot("root"); } - // Supported for backwards compatibility - private Element servicesConfigserver() { - return XML.getDocument( - "<admin version=\"2.0\">" + - " <configserver hostalias=\"mockhost\"/>" + - " <adminserver hostalias=\"mockhost\"/>" + - "</admin>").getDocumentElement(); - - } - private Element servicesOverride() { return XML.getDocument( "<admin version=\"2.0\">" + @@ -131,15 +121,6 @@ public class DomAdminV2BuilderTest extends DomBuilderTest { } /** - * Tests that configserver works (deprecated, but allowed in admin 2.0) - */ - @Test - public void adminWithConfigserverElement() { - Admin admin = buildAdmin(servicesConfigserver()); - assertEquals(1, admin.getConfigservers().size()); - } - - /** * Tests that configservers/configserver works */ @Test diff --git a/config-model/src/test/java/com/yahoo/vespa/model/container/xml/AccessLogTest.java b/config-model/src/test/java/com/yahoo/vespa/model/container/xml/AccessLogTest.java index 81b6de8f2ee..d9659cf92d4 100644 --- a/config-model/src/test/java/com/yahoo/vespa/model/container/xml/AccessLogTest.java +++ b/config-model/src/test/java/com/yahoo/vespa/model/container/xml/AccessLogTest.java @@ -89,7 +89,7 @@ public class AccessLogTest extends ContainerModelBuilderTestBase { assertNotNull(getVespaAccessLog("default")); { // vespa - Component<?, ?> accessLogComponent = getContainerComponent("default", VespaAccessLog.class.getName()); + Component<?, ?> accessLogComponent = getComponent("default", VespaAccessLog.class.getName()); assertNotNull(accessLogComponent); assertEquals(VespaAccessLog.class.getName(), accessLogComponent.getClassId().getName(), VespaAccessLog.class.getName()); AccessLogConfig config = root.getConfig(AccessLogConfig.class, "default/component/com.yahoo.container.logging.VespaAccessLog"); @@ -101,7 +101,7 @@ public class AccessLogTest extends ContainerModelBuilderTestBase { } { // json - Component<?, ?> accessLogComponent = getContainerComponent("default", JSONAccessLog.class.getName()); + Component<?, ?> accessLogComponent = getComponent("default", JSONAccessLog.class.getName()); assertNotNull(accessLogComponent); assertEquals(JSONAccessLog.class.getName(), accessLogComponent.getClassId().getName(), JSONAccessLog.class.getName()); AccessLogConfig config = root.getConfig(AccessLogConfig.class, "default/component/com.yahoo.container.logging.JSONAccessLog"); @@ -124,7 +124,7 @@ public class AccessLogTest extends ContainerModelBuilderTestBase { nodesXml, "</container>" ); createModel(root, clusterElem); - Component<?, ?> connectionLogComponent = getContainerComponent("default", FileConnectionLog.class.getName()); + Component<?, ?> connectionLogComponent = getComponent("default", FileConnectionLog.class.getName()); assertNotNull(connectionLogComponent); ConnectionLogConfig config = root.getConfig(ConnectionLogConfig.class, "default/component/com.yahoo.container.logging.FileConnectionLog"); assertEquals("default", config.cluster()); @@ -140,7 +140,7 @@ public class AccessLogTest extends ContainerModelBuilderTestBase { nodesXml, "</container>" ); createModel(root, clusterElem); - Component<?, ?> fileConnectionLogComponent = getContainerComponent("default", FileConnectionLog.class.getName()); + Component<?, ?> fileConnectionLogComponent = getComponent("default", FileConnectionLog.class.getName()); assertNull(fileConnectionLogComponent); } diff --git a/config-model/src/test/java/com/yahoo/vespa/model/container/xml/BundleInstantiationSpecificationBuilderTest.java b/config-model/src/test/java/com/yahoo/vespa/model/container/xml/BundleInstantiationSpecificationBuilderTest.java index 686f7bbd1f1..125f1823fec 100644 --- a/config-model/src/test/java/com/yahoo/vespa/model/container/xml/BundleInstantiationSpecificationBuilderTest.java +++ b/config-model/src/test/java/com/yahoo/vespa/model/container/xml/BundleInstantiationSpecificationBuilderTest.java @@ -29,7 +29,7 @@ public class BundleInstantiationSpecificationBuilderTest { @Test public void bundle_is_replaced_for_internal_class() { String internalClass = GroupingValidator.class.getName(); - verifyExpectedBundle(internalClass, null, PlatformBundles.searchAndDocprocBundle); + verifyExpectedBundle(internalClass, null, PlatformBundles.SEARCH_AND_DOCPROC_BUNDLE); } @Test diff --git a/config-model/src/test/java/com/yahoo/vespa/model/container/xml/ContainerDocumentApiBuilderTest.java b/config-model/src/test/java/com/yahoo/vespa/model/container/xml/ContainerDocumentApiBuilderTest.java index ca0b4681e51..4a9d44ea2f8 100644 --- a/config-model/src/test/java/com/yahoo/vespa/model/container/xml/ContainerDocumentApiBuilderTest.java +++ b/config-model/src/test/java/com/yahoo/vespa/model/container/xml/ContainerDocumentApiBuilderTest.java @@ -30,11 +30,11 @@ import static org.junit.Assert.assertTrue; */ public class ContainerDocumentApiBuilderTest extends ContainerModelBuilderTestBase { - private Map<String, Handler<?>> getHandlers(String clusterName) { + private Map<String, Handler> getHandlers(String clusterName) { ContainerCluster<?> cluster = (ContainerCluster<?>) root.getChildren().get(clusterName); - Map<String, Handler<?>> handlerMap = new HashMap<>(); - Collection<Handler<?>> handlers = cluster.getHandlers(); - for (Handler<?> handler : handlers) { + Map<String, Handler> handlerMap = new HashMap<>(); + Collection<Handler> handlers = cluster.getHandlers(); + for (Handler handler : handlers) { assertFalse(handlerMap.containsKey(handler.getComponentId().toString())); //die on overwrites handlerMap.put(handler.getComponentId().toString(), handler); } @@ -56,7 +56,7 @@ public class ContainerDocumentApiBuilderTest extends ContainerModelBuilderTestBa } private void verifyCustomBindings(String id) { - Handler<?> handler = getHandlers("cluster1").get(id); + Handler handler = getHandlers("cluster1").get(id); assertTrue(handler.getServerBindings().contains(UserBindingPattern.fromHttpPath("/document-api/reserved-for-internal-use/feedapi"))); assertTrue(handler.getServerBindings().contains(UserBindingPattern.fromHttpPath("/document-api/reserved-for-internal-use/feedapi/"))); @@ -73,7 +73,7 @@ public class ContainerDocumentApiBuilderTest extends ContainerModelBuilderTestBa "</container>"); createModel(root, elem); - Map<String, Handler<?>> handlerMap = getHandlers("cluster1"); + Map<String, Handler> handlerMap = getHandlers("cluster1"); assertNotNull(handlerMap.get("com.yahoo.container.handler.VipStatusHandler")); assertNotNull(handlerMap.get("com.yahoo.container.handler.observability.ApplicationStatusHandler")); @@ -91,8 +91,10 @@ public class ContainerDocumentApiBuilderTest extends ContainerModelBuilderTestBa public void nonexisting_fields_can_be_ignored() { Element elem = DomBuilderTest.parse( "<container id='cluster1' version='1.0'>", - " <document-api ignore-undefined-fields='true' />", + " <document-api>" + + " <ignore-undefined-fields>true</ignore-undefined-fields>" + nodesXml, + " </document-api>" + "</container>"); ContainerModel model = createModel(root, elem).get(0); @@ -110,8 +112,8 @@ public class ContainerDocumentApiBuilderTest extends ContainerModelBuilderTestBa "</container>"); root = new MockRoot("root", new MockApplicationPackage.Builder().build()); createModel(root, elem); - Map<String, Handler<?>> handlers = getHandlers("cluster1"); - Handler<?> feedApiHandler = handlers.get("com.yahoo.vespa.http.server.FeedHandler"); + Map<String, Handler> handlers = getHandlers("cluster1"); + Handler feedApiHandler = handlers.get("com.yahoo.vespa.http.server.FeedHandler"); Set<String> injectedComponentIds = feedApiHandler.getInjectedComponentIds(); assertTrue(injectedComponentIds.contains("threadpool@feedapi-handler")); 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 3a241d9607f..1d43c031a1b 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 @@ -42,6 +42,7 @@ import com.yahoo.vespa.model.container.ApplicationContainerCluster; import com.yahoo.vespa.model.container.ContainerCluster; import com.yahoo.vespa.model.container.ContainerModelEvaluation; import com.yahoo.vespa.model.container.component.Component; +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; @@ -60,19 +61,15 @@ import java.util.stream.Collectors; import static com.yahoo.config.model.test.TestUtil.joinLines; import static com.yahoo.test.LinePatternMatcher.containsLineWithPattern; import static com.yahoo.vespa.defaults.Defaults.getDefaults; -import static com.yahoo.vespa.model.container.ContainerCluster.ROOT_HANDLER_BINDING; -import static com.yahoo.vespa.model.container.ContainerCluster.STATE_HANDLER_BINDING_1; -import static org.hamcrest.CoreMatchers.is; +import static com.yahoo.vespa.model.container.component.chain.ProcessingHandler.PROCESSING_HANDLER_CLASS; import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.hasItem; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -198,6 +195,17 @@ public class ContainerModelBuilderTest extends ContainerModelBuilderTestBase { } @Test + public void builtin_handlers_get_default_threadpool() { + createBasicContainerModel(); + + Handler h1 = getHandler("default", ApplicationStatusHandler.class.getName()); + assertTrue(h1.getInjectedComponentIds().contains("threadpool@default-handler-common")); + + Handler h2 = getHandler("default", BindingsOverviewHandler.class.getName()); + assertTrue(h2.getInjectedComponentIds().contains("threadpool@default-handler-common")); + } + + @Test public void verify_bindings_for_builtin_handlers() { createBasicContainerModel(); JdiscBindingsConfig config = root.getConfig(JdiscBindingsConfig.class, "default/container.0"); @@ -216,68 +224,6 @@ public class ContainerModelBuilderTest extends ContainerModelBuilderTestBase { } @Test - public void default_root_handler_binding_can_be_stolen_by_user_configured_handler() { - Element clusterElem = DomBuilderTest.parse( - "<container id='default' version='1.0'>" + - " <handler id='userRootHandler'>" + - " <binding>" + ROOT_HANDLER_BINDING.patternString() + "</binding>" + - " </handler>" + - "</container>"); - createModel(root, clusterElem); - - // The handler is still set up. - ComponentsConfig.Components userRootHandler = getComponent(componentsConfig(), BindingsOverviewHandler.class.getName()); - assertNotNull(userRootHandler); - - // .. but it has no bindings - var discBindingsConfig = root.getConfig(JdiscBindingsConfig.class, "default"); - assertNull(discBindingsConfig.handlers(BindingsOverviewHandler.class.getName())); - } - - @Test - public void reserved_binding_cannot_be_stolen_by_user_configured_handler() { - Element clusterElem = DomBuilderTest.parse( - "<container id='default' version='1.0'>" + - " <handler id='userHandler'>" + - " <binding>" + STATE_HANDLER_BINDING_1.patternString() + "</binding>" + - " </handler>" + - "</container>"); - try { - createModel(root, clusterElem); - fail("Expected exception when stealing a reserved binding."); - } catch (IllegalArgumentException e) { - assertThat(e.getMessage(), is("Binding 'http://*/state/v1' is a reserved Vespa binding " + - "and cannot be used by handler: userHandler")); - } - } - - @Test - public void handler_bindings_are_included_in_discBindings_config() { - createClusterWithJDiscHandler(); - String discBindingsConfig = root.getConfig(JdiscBindingsConfig.class, "default").toString(); - assertThat(discBindingsConfig, containsString(".serverBindings[0] \"http://*/binding0\"")); - assertThat(discBindingsConfig, containsString(".serverBindings[1] \"http://*/binding1\"")); - } - - @Test - public void handlers_are_included_in_components_config() { - createClusterWithJDiscHandler(); - assertThat(componentsConfig().toString(), containsString(".id \"discHandler\"")); - } - - private void createClusterWithJDiscHandler() { - Element clusterElem = DomBuilderTest.parse( - "<container id='default' version='1.0'>", - " <handler id='discHandler'>", - " <binding>http://*/binding0</binding>", - " <binding>http://*/binding1</binding>", - " </handler>", - "</container>"); - - createModel(root, clusterElem); - } - - @Test public void processing_handler_bindings_can_be_overridden() { Element clusterElem = DomBuilderTest.parse( "<container id='default' version='1.0'>", @@ -324,12 +270,19 @@ public class ContainerModelBuilderTest extends ContainerModelBuilderTestBase { @Test public void processingHandler_gets_only_processing_chains_in_chains_config() { createClusterWithProcessingAndSearchChains(); - String processingHandlerConfigId = "default/component/com.yahoo.processing.handler.ProcessingHandler"; + String processingHandlerConfigId = "default/component/" + PROCESSING_HANDLER_CLASS; String chainsConfig = getChainsConfig(processingHandlerConfigId); assertThat(chainsConfig, containsLineWithPattern(".*\\.id \"testProcessor@default\"$")); assertThat(chainsConfig, not(containsLineWithPattern(".*\\.id \"testSearcher@default\"$"))); } + @Test + public void processingHandler_is_instantiated_from_the_default_bundle() { + createClusterWithProcessingAndSearchChains(); + ComponentsConfig.Components config = getComponentInConfig(componentsConfig(), PROCESSING_HANDLER_CLASS); + assertEquals(PROCESSING_HANDLER_CLASS, config.bundle()); + } + private void createClusterWithProcessingAndSearchChains() { Element clusterElem = DomBuilderTest.parse( "<container id='default' version='1.0'>" + @@ -375,20 +328,6 @@ public class ContainerModelBuilderTest extends ContainerModelBuilderTestBase { } @Test - public void nested_components_are_injected_to_handlers() { - Element clusterElem = DomBuilderTest.parse( - "<container id='default' version='1.0'>", - " <handler id='myHandler'>", - " <component id='injected' />", - " </handler>", - "</container>"); - - createModel(root, clusterElem); - Component<?,?> handler = getContainerComponent("default", "myHandler"); - assertThat(handler.getInjectedComponentIds(), hasItem("injected@myHandler")); - } - - @Test public void component_includes_are_added() { VespaModelCreatorWithFilePkg creator = new VespaModelCreatorWithFilePkg("src/test/cfg/application/include_dirs"); VespaModel model = creator.create(true); diff --git a/config-model/src/test/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilderTestBase.java b/config-model/src/test/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilderTestBase.java index 3d7b17d37e0..dc831ef863d 100644 --- a/config-model/src/test/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilderTestBase.java +++ b/config-model/src/test/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilderTestBase.java @@ -13,6 +13,7 @@ import com.yahoo.vespa.model.container.ApplicationContainerCluster; import com.yahoo.vespa.model.container.ContainerCluster; import com.yahoo.vespa.model.container.ContainerModel; import com.yahoo.vespa.model.container.component.Component; +import com.yahoo.vespa.model.container.component.Handler; import com.yahoo.vespa.model.container.search.ContainerSearch; import org.junit.Before; import org.w3c.dom.Element; @@ -94,7 +95,7 @@ public abstract class ContainerModelBuilderTestBase { return root.getConfig(ComponentsConfig.class, "default"); } - protected ComponentsConfig.Components getComponent(ComponentsConfig componentsConfig, String id) { + protected ComponentsConfig.Components getComponentInConfig(ComponentsConfig componentsConfig, String id) { for (ComponentsConfig.Components component : componentsConfig.components()) { if (component.id().equals(id)) return component; @@ -106,11 +107,18 @@ public abstract class ContainerModelBuilderTestBase { return (ApplicationContainerCluster) root.getChildren().get(clusterId); } - public Component<?, ?> getContainerComponent(String clusterId, String componentId) { + public Component<?, ?> getComponent(String clusterId, String componentId) { return getContainerCluster(clusterId).getComponentsMap().get( ComponentId.fromString(componentId)); } + public Handler getHandler(String clusterId, String componentId) { + Component<?,?> component = getComponent(clusterId, componentId); + if (! (component instanceof Handler)) + throw new RuntimeException("Component is not a handler: " + componentId); + return (Handler) component; + } + void assertComponentConfigured(ApplicationContainerCluster cluster, String componentId) { Component<?, ?> component = cluster.getComponentsMap().get(ComponentId.fromString(componentId)); assertNotNull(component); diff --git a/config-model/src/test/java/com/yahoo/vespa/model/container/xml/HandlerBuilderTest.java b/config-model/src/test/java/com/yahoo/vespa/model/container/xml/HandlerBuilderTest.java new file mode 100644 index 00000000000..42cda0d8034 --- /dev/null +++ b/config-model/src/test/java/com/yahoo/vespa/model/container/xml/HandlerBuilderTest.java @@ -0,0 +1,118 @@ +package com.yahoo.vespa.model.container.xml; + +import com.yahoo.config.model.builder.xml.test.DomBuilderTest; +import com.yahoo.container.ComponentsConfig; +import com.yahoo.container.jdisc.JdiscBindingsConfig; +import com.yahoo.container.usability.BindingsOverviewHandler; +import com.yahoo.vespa.model.container.ApplicationContainerCluster; +import com.yahoo.vespa.model.container.component.Component; +import com.yahoo.vespa.model.container.component.Handler; +import org.junit.Test; +import org.w3c.dom.Element; + +import static com.yahoo.vespa.model.container.ContainerCluster.ROOT_HANDLER_BINDING; +import static com.yahoo.vespa.model.container.ContainerCluster.STATE_HANDLER_BINDING_1; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.hasItem; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +/** + * Tests for container model building with custom handlers. + * + * @author gjoranv + */ +public class HandlerBuilderTest extends ContainerModelBuilderTestBase { + + @Test + public void handlers_are_included_in_components_config() { + createClusterWithJDiscHandler(); + assertThat(componentsConfig().toString(), containsString(".id \"discHandler\"")); + } + + @Test + public void handler_bindings_are_included_in_discBindings_config() { + createClusterWithJDiscHandler(); + String discBindingsConfig = root.getConfig(JdiscBindingsConfig.class, "default").toString(); + assertThat(discBindingsConfig, containsString(".serverBindings[0] \"http://*/binding0\"")); + assertThat(discBindingsConfig, containsString(".serverBindings[1] \"http://*/binding1\"")); + } + + @Test + public void nested_components_are_injected_to_handlers() { + Element clusterElem = DomBuilderTest.parse( + "<container id='default' version='1.0'>", + " <handler id='myHandler'>", + " <component id='injected' />", + " </handler>", + "</container>"); + + createModel(root, clusterElem); + Component<?,?> handler = getComponent("default", "myHandler"); + assertThat(handler.getInjectedComponentIds(), hasItem("injected@myHandler")); + } + + @Test + public void default_root_handler_binding_can_be_stolen_by_user_configured_handler() { + Element clusterElem = DomBuilderTest.parse( + "<container id='default' version='1.0'>" + + " <handler id='userRootHandler'>" + + " <binding>" + ROOT_HANDLER_BINDING.patternString() + "</binding>" + + " </handler>" + + "</container>"); + createModel(root, clusterElem); + + // The handler is still set up. + ComponentsConfig.Components userRootHandler = getComponentInConfig(componentsConfig(), BindingsOverviewHandler.class.getName()); + assertNotNull(userRootHandler); + + // .. but it has no bindings + var discBindingsConfig = root.getConfig(JdiscBindingsConfig.class, "default"); + assertNull(discBindingsConfig.handlers(BindingsOverviewHandler.class.getName())); + } + + @Test + public void reserved_binding_cannot_be_stolen_by_user_configured_handler() { + Element clusterElem = DomBuilderTest.parse( + "<container id='default' version='1.0'>" + + " <handler id='userHandler'>" + + " <binding>" + STATE_HANDLER_BINDING_1.patternString() + "</binding>" + + " </handler>" + + "</container>"); + try { + createModel(root, clusterElem); + fail("Expected exception when stealing a reserved binding."); + } catch (IllegalArgumentException e) { + assertThat(e.getMessage(), is("Binding 'http://*/state/v1' is a reserved Vespa binding " + + "and cannot be used by handler: userHandler")); + } + } + + @Test + public void custom_handler_gets_default_threadpool() { + createClusterWithJDiscHandler(); + ApplicationContainerCluster cluster = (ApplicationContainerCluster)root.getChildren().get("default"); + Handler handler = cluster.getHandlers().stream() + .filter(h -> h.getComponentId().toString().equals("discHandler")) + .findAny().orElseThrow(); + + assertTrue(handler.getInjectedComponentIds().contains("threadpool@default-handler-common")); + } + + private void createClusterWithJDiscHandler() { + Element clusterElem = DomBuilderTest.parse( + "<container id='default' version='1.0'>", + " <handler id='discHandler'>", + " <binding>http://*/binding0</binding>", + " <binding>http://*/binding1</binding>", + " </handler>", + "</container>"); + + createModel(root, clusterElem); + } + +} diff --git a/config-model/src/test/java/com/yahoo/vespa/model/container/xml/ApplicationBuilderTest.java b/config-model/src/test/java/com/yahoo/vespa/model/container/xml/SearchBuilderTest.java index ca59e053a89..c41373b9f85 100644 --- a/config-model/src/test/java/com/yahoo/vespa/model/container/xml/ApplicationBuilderTest.java +++ b/config-model/src/test/java/com/yahoo/vespa/model/container/xml/SearchBuilderTest.java @@ -31,7 +31,7 @@ import static org.junit.Assert.fail; /** * @author gjoranv */ -public class ApplicationBuilderTest extends ContainerModelBuilderTestBase { +public class SearchBuilderTest extends ContainerModelBuilderTestBase { private ChainsConfig chainsConfig() { return root.getConfig(ChainsConfig.class, "default/component/com.yahoo.search.handler.SearchHandler"); @@ -53,7 +53,7 @@ public class ApplicationBuilderTest extends ContainerModelBuilderTestBase { ApplicationContainerCluster cluster = (ApplicationContainerCluster)root.getChildren().get("default"); GUIHandler guiHandler = null; - for (Handler<?> handler : cluster.getHandlers()) { + for (Handler handler : cluster.getHandlers()) { if (handler instanceof GUIHandler) { guiHandler = (GUIHandler) handler; } @@ -230,12 +230,7 @@ public class ApplicationBuilderTest extends ContainerModelBuilderTestBase { createModel(root, clusterElem); - ApplicationContainerCluster cluster = (ApplicationContainerCluster)root.getChildren().get("default"); - Handler<?> searchHandler = cluster.getHandlers().stream() - .filter(h -> h.getComponentId().toString().equals(SearchHandler.HANDLER_CLASS)) - .findAny() - .get(); - + Handler searchHandler = getHandler("default", SearchHandler.HANDLER_CLASS); assertTrue(searchHandler.getInjectedComponentIds().contains("threadpool@search-handler")); ContainerThreadpoolConfig config = root.getConfig( diff --git a/config-model/src/test/schema-test-files/services.xml b/config-model/src/test/schema-test-files/services.xml index 4fb81963152..df87d2b9f3d 100644 --- a/config-model/src/test/schema-test-files/services.xml +++ b/config-model/src/test/schema-test-files/services.xml @@ -193,6 +193,9 @@ <handler id="jdisc-handler"> <binding>http://*:*/HelloWorld</binding> <binding>http://*:*/Status</binding> + <component id="injected-to-handler"> + <config name="foo"/> + </component> </handler> <server id="server-provider"> |