// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.model.builder.xml.dom.chains.search; import com.yahoo.component.ComponentId; import com.yahoo.component.ComponentSpecification; import com.yahoo.config.model.builder.xml.test.DomBuilderTest; import com.yahoo.config.model.test.MockRoot; import com.yahoo.container.core.ChainsConfig; import com.yahoo.search.searchchain.model.federation.FederationOptions; import com.yahoo.vespa.model.container.component.chain.ChainedComponent; import com.yahoo.vespa.model.container.search.searchchain.GenericTarget; import com.yahoo.vespa.model.container.search.searchchain.Provider; import com.yahoo.vespa.model.container.search.searchchain.SearchChain; import com.yahoo.vespa.model.container.search.searchchain.SearchChains; import com.yahoo.vespa.model.container.search.searchchain.Source; import org.hamcrest.BaseMatcher; import org.hamcrest.Description; import org.hamcrest.Matcher; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.w3c.dom.Element; import java.util.Arrays; import java.util.Collection; import java.util.List; import static com.yahoo.container.core.ChainsConfig.Chains; import static com.yahoo.container.core.ChainsConfig.Components; import static org.hamcrest.CoreMatchers.hasItem; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.jupiter.api.Assertions.*; /** * Test of Search chains builder. * * @author Tony Vaagenes */ public class DomSchemaChainsBuilderTest extends DomBuilderTest { private SearchChains searchChains; private static final Element element = parse( "", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", ""); @BeforeEach public void createSearchChains() { searchChains = new DomSearchChainsBuilder().build(root.getDeployState(), root, element); } @Test void referToFederationAsSearcher() { final Element element = parse( "", " ", " ", " ", " ", " ", " ", " ", " ", ""); try { MockRoot root = new MockRoot(); new DomSearchChainsBuilder().build(root.getDeployState(), root, element); fail("Expected exception when referring to an outer 'federation' as a 'searcher'."); } catch (RuntimeException e) { assertTrue(e.getMessage().contains("Two different types declared for the component with name 'federationSearcher'")); } } @Test void ensureSearchChainsExists() { for (String id : Arrays.asList("provider:1", "source:1@provider:1", "default")) { assertNotNull(getSearchChain(id), "Missing search chain " + id); } } @Test void ensureSearcherExists() { assertThat(searchChains.allComponents(), hasItem(searcherWithId("searcher:1"))); } private Matcher> searcherWithId(final String componentId) { return new BaseMatcher<>() { @Override public boolean matches(Object o) { return o instanceof ChainedComponent && ((ChainedComponent) o).getComponentId().equals(new ComponentId(componentId)); } @Override public void describeTo(Description description) { description.appendText("a searcher with id ").appendValue(componentId); } }; } @Test void checkProviderFederationOptions() { FederationOptions options = getProvider().federationOptions(); assertTrue(options.getOptional()); assertEquals(2300, options.getTimeoutInMilliseconds()); } @Test void checkSourceFederationOptions() { FederationOptions options = getSource().federationOptions(); assertTrue(options.getOptional()); //inherited assertEquals(12, options.getTimeoutInMilliseconds()); } @Test void checkDefaultTargets() { Collection defaultTargets = getProvider().defaultFederationTargets(); assertEquals(1, defaultTargets.size()); assertEquals(getSearchChain("source:1@provider:1"), first(defaultTargets)); } @Test void checkInnerSearcherIdIsNestedInSearchChainId() { ChainsConfig.Builder builder = new ChainsConfig.Builder(); searchChains.getConfig(builder); ChainsConfig config = new ChainsConfig(builder); checkInnerSearcherIdIsNestedInSearchChainId(config, "federationSearcher", "default"); } private void checkInnerSearcherIdIsNestedInSearchChainId(ChainsConfig config, String partOfSearcherName, String searchChainName) { Components searcher = getSearcherConfig(config.components(), partOfSearcherName); ComponentId searcherId = ComponentId.fromString(searcher.id()); assertEquals(getSearchChain(searchChainName).getComponentId(), searcherId.getNamespace()); Chains searchChain = getSearchChainConfig(config.chains(), searchChainName); assertEquals(searcherId, ComponentId.fromString(searchChain.components(0))); } private Chains getSearchChainConfig(List searchChains, String searchChainName) { for (Chains searchChain : searchChains) { if (ComponentId.fromString(searchChain.id()).getName().equals(searchChainName)) return searchChain; } fail("No search chain matching " + searchChainName); return null; } private Components getSearcherConfig(List searchers, String partOfId) { for (Components searcher : searchers) { if (searcher.id().contains(partOfId)) return searcher; } fail("No searcher matching " + partOfId); return null; } private static T first(Iterable coll) { return coll.iterator().next(); } private Provider getProvider() { return (Provider)getSearchChain("provider:1"); } private Source getSource() { return first(getProvider().getSources()); } private SearchChain getSearchChain(String componentSpecification) { return searchChains.allChains().getComponent(new ComponentSpecification(componentSpecification)); } }