aboutsummaryrefslogtreecommitdiffstats
path: root/config-model/src/test/java/com/yahoo/config/model/ApplicationDeployTest.java
diff options
context:
space:
mode:
Diffstat (limited to 'config-model/src/test/java/com/yahoo/config/model/ApplicationDeployTest.java')
-rw-r--r--config-model/src/test/java/com/yahoo/config/model/ApplicationDeployTest.java379
1 files changed, 379 insertions, 0 deletions
diff --git a/config-model/src/test/java/com/yahoo/config/model/ApplicationDeployTest.java b/config-model/src/test/java/com/yahoo/config/model/ApplicationDeployTest.java
new file mode 100644
index 00000000000..8958300538b
--- /dev/null
+++ b/config-model/src/test/java/com/yahoo/config/model/ApplicationDeployTest.java
@@ -0,0 +1,379 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.config.model;
+
+import com.google.common.io.Files;
+import com.yahoo.config.ConfigInstance;
+import com.yahoo.config.application.api.ApplicationMetaData;
+import com.yahoo.config.application.api.UnparsedConfigDefinition;
+import com.yahoo.config.codegen.CNode;
+import com.yahoo.config.application.api.ApplicationPackage;
+import com.yahoo.config.model.application.provider.*;
+import com.yahoo.config.model.deploy.DeployState;
+import com.yahoo.path.Path;
+import com.yahoo.document.DataType;
+import com.yahoo.document.config.DocumentmanagerConfig;
+import com.yahoo.io.IOUtils;
+import com.yahoo.searchdefinition.Search;
+import com.yahoo.searchdefinition.UnproperSearch;
+import com.yahoo.vespa.config.ConfigDefinition;
+import com.yahoo.vespa.config.ConfigDefinitionKey;
+import com.yahoo.vespa.model.VespaModel;
+import com.yahoo.vespa.model.search.SearchDefinition;
+import org.json.JSONException;
+import org.junit.After;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.xml.sax.SAXException;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.Reader;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.regex.Pattern;
+
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.Matchers.contains;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+public class ApplicationDeployTest {
+
+ private static final String TESTDIR = "src/test/cfg/application/";
+ private static final String TESTSDDIR = TESTDIR + "app1/searchdefinitions/";
+
+ @Rule
+ public TemporaryFolder tmpFolder = new TemporaryFolder();
+
+ @Test
+ public void testVespaModel() throws SAXException, IOException {
+ FilesApplicationPackage app = createAppPkg(TESTDIR + "app1");
+ assertThat(app.getApplicationName(), is("app1"));
+ VespaModel model = new VespaModel(app);
+ List<SearchDefinition> searchDefinitions = getSearchDefinitions(app);
+ assertEquals(searchDefinitions.size(), 5);
+ for (SearchDefinition searchDefinition : searchDefinitions) {
+ Search s = searchDefinition.getSearch();
+ switch (s.getName()) {
+ case "music":
+ case "laptop":
+ case "pc":
+ case "sock":
+ break;
+ case "product":
+ assertTrue(s instanceof UnproperSearch);
+ assertEquals(s.getDocument().getField("title").getDataType(), DataType.STRING);
+ break;
+ default:
+ fail();
+ }
+ }
+ File[] truth = new File[]{new File(TESTSDDIR + "laptop.sd"),
+ new File(TESTSDDIR + "music.sd"),
+ new File(TESTSDDIR + "pc.sd"),
+ new File(TESTSDDIR + "product.sd"),
+ new File(TESTSDDIR + "sock.sd")};
+ Arrays.sort(truth);
+ List<File> appSdFiles = app.getSearchDefinitionFiles();
+ Collections.sort(appSdFiles);
+ assertEquals(appSdFiles, Arrays.asList(truth));
+
+ List<FilesApplicationPackage.Component> components = app.getComponents();
+ assertEquals(1, components.size());
+ Map<String, Bundle.DefEntry> defEntries =
+ defEntries2map(components.get(0).getDefEntries());
+ assertEquals(2, defEntries.size());
+ System.out.println(defEntries);
+ Bundle.DefEntry def1 = defEntries.get("test1");
+ Bundle.DefEntry def2 = defEntries.get("test2");
+ assertNotNull(def1);
+ assertNotNull(def2);
+ assertEquals("namespace=config\nintVal int default=0", def1.contents);
+ assertEquals("namespace=a.b\n\ndoubleVal double default=0.0", def2.contents);
+
+ // Check that getFilename works
+ ArrayList<String> sdFileNames = new ArrayList<>();
+ for (SearchDefinition sd : searchDefinitions) {
+ sdFileNames.add(sd.getFilename());
+ }
+ Collections.sort(sdFileNames);
+ assertThat(sdFileNames.get(0), is("laptop.sd"));
+ assertThat(sdFileNames.get(1), is("music.sd"));
+ assertThat(sdFileNames.get(2), is("pc.sd"));
+ assertThat(sdFileNames.get(3), is("product.sd"));
+ assertThat(sdFileNames.get(4), is("sock.sd"));
+ }
+
+ @Test
+ public void testGetFile() throws IOException {
+ FilesApplicationPackage app = createAppPkg(TESTDIR + "app1");
+ try (Reader foo = app.getFile(Path.fromString("files/foo.json")).createReader()) {
+ assertEquals(IOUtils.readAll(foo), "foo : foo\n");
+ }
+ try (Reader bar = app.getFile(Path.fromString("files/sub/bar.json")).createReader()) {
+ assertEquals(IOUtils.readAll(bar), "bar : bar\n");
+ }
+ assertTrue(app.getFile(Path.createRoot()).exists());
+ assertTrue(app.getFile(Path.createRoot()).isDirectory());
+ }
+
+ /*
+ * Put a list of def entries to a map, with the name as key. This is done because the order
+ * of the def entries in the list cannot be guaranteed.
+ */
+ private Map<String, Bundle.DefEntry> defEntries2map
+ (List<Bundle.DefEntry> defEntries) {
+ Map<String, Bundle.DefEntry> ret =
+ new HashMap<>();
+
+ for (Bundle.DefEntry def : defEntries)
+ ret.put(def.defName, def);
+ return ret;
+ }
+
+ @Test
+ public void testSdFromDocprocBundle() throws IOException, SAXException {
+ String appDir = "src/test/cfg/application/app_sdbundles";
+ FilesApplicationPackage app = createAppPkg(appDir);
+ VespaModel model = new VespaModel(app);
+ // Check that the resulting documentmanager config contains those types
+ DocumentmanagerConfig.Builder b = new DocumentmanagerConfig.Builder();
+ model.getConfig(b, VespaModel.ROOT_CONFIGID);
+ //String docMan = model.getConfig("documentmanager", "").toString();
+ DocumentmanagerConfig dc = new DocumentmanagerConfig(b);
+ String docMan=ConfigInstance.serialize(dc).toString();
+ int pFlags = Pattern.MULTILINE + Pattern.DOTALL;
+ Pattern base = Pattern.compile(".*name.*base\\.header.*", pFlags);
+ Pattern book = Pattern.compile(".*name.*book\\.header.*", pFlags);
+ Pattern music = Pattern.compile(".*name.*music\\.header.*", pFlags);
+ Pattern video = Pattern.compile(".*name.*video\\.header.*", pFlags);
+ Pattern muzak = Pattern.compile(".*name.*muzak\\.header.*", pFlags);
+ assertTrue(base.matcher(docMan).matches());
+ assertTrue(book.matcher(docMan).matches());
+ assertTrue(music.matcher(docMan).matches());
+ assertTrue(video.matcher(docMan).matches());
+ assertTrue(muzak.matcher(docMan).matches());
+ }
+
+ @Test
+ public void include_dirs_are_included() throws Exception {
+ FilesApplicationPackage app = createAppPkg(TESTDIR + "include_dirs");
+
+ List<String> includeDirs = app.getUserIncludeDirs();
+ assertThat(includeDirs, contains("jdisc_dir", "dir1", "dir2", "empty_dir"));
+ }
+
+ @Test
+ public void non_existent_include_dir_is_not_allowed() throws Exception {
+ File appDir = tmpFolder.newFolder("non-existent-include");
+ String services = "<services version='1.0'>" +
+ "<include dir='non-existent' />" +
+ "</services>\n";
+
+ IOUtils.writeFile(new File(appDir, "services.xml"), services, false);
+ try {
+ FilesApplicationPackage.fromFile(appDir);
+ fail("Expected exception due to non-existent include dir");
+ } catch (IllegalArgumentException e) {
+ assertThat(e.getMessage(), containsString("Cannot include directory 'non-existent', as it does not exist"));
+ }
+ }
+
+ @Test
+ public void testThatModelIsRebuiltWhenSearchDefinitionIsAdded() throws IOException {
+ File tmpDir = Files.createTempDir();
+ IOUtils.copyDirectory(new File(TESTDIR, "app1"), tmpDir);
+ FilesApplicationPackage app = createAppPkg(tmpDir.getAbsolutePath());
+ assertThat(getSearchDefinitions(app).size(), is(5));
+ File sdDir = new File(tmpDir, "searchdefinitions");
+ File sd = new File(sdDir, "testfoo.sd");
+ IOUtils.writeFile(sd, "search testfoo { document testfoo { field bar type string { } } }", false);
+ assertThat(getSearchDefinitions(app).size(), is(6));
+ }
+
+ private List<SearchDefinition> getSearchDefinitions(FilesApplicationPackage app) {
+ return new DeployState.Builder().applicationPackage(app).build().getSearchDefinitions();
+ }
+
+ public FilesApplicationPackage createAppPkg(String appPkg) throws IOException {
+ return createAppPkg(appPkg, true);
+ }
+
+ public FilesApplicationPackage createAppPkgDoNotValidateXml(String appPkg) throws IOException {
+ return createAppPkg(appPkg, false);
+ }
+
+ public FilesApplicationPackage createAppPkg(String appPkg, boolean validateXml) throws IOException {
+ final FilesApplicationPackage filesApplicationPackage = FilesApplicationPackage.fromFile(new File(appPkg));
+ if (validateXml) {
+ ApplicationPackageXmlFilesValidator validator = ApplicationPackageXmlFilesValidator.createTestXmlValidator(new File(appPkg));
+ validator.checkApplication();
+ ApplicationPackageXmlFilesValidator.checkIncludedDirs(filesApplicationPackage);
+ }
+ return filesApplicationPackage;
+ }
+
+ @Test
+ public void testThatNewServicesFileNameWorks() throws IOException {
+ String appPkg = TESTDIR + "newfilenames";
+ assertEquals(appPkg + "/services.xml", createAppPkgDoNotValidateXml(appPkg).getServicesSource());
+ }
+
+ @Test
+ public void testThatNewHostsFileNameWorks() throws IOException {
+ String appPkg = TESTDIR + "newfilenames";
+ assertEquals(appPkg + "/hosts.xml", createAppPkgDoNotValidateXml(appPkg).getHostSource());
+ }
+
+ @Test
+ public void testGetJars() throws IOException {
+ String jarName = "src/test/cfg/application/app_sdbundles/components/testbundle.jar";
+ JarFile jar = new JarFile(jarName);
+ Map<String, String> payloads = ApplicationPackage.getBundleSdFiles("", jar);
+ assertEquals(payloads.size(), 4);
+ assertTrue(payloads.get("base.sd").startsWith("search base"));
+ assertTrue(payloads.get("book.sd").startsWith("search book"));
+ assertTrue(payloads.get("music.sd").startsWith("search music"));
+ assertTrue(payloads.get("video.sd").startsWith("search video"));
+ assertTrue(payloads.get("base.sd").endsWith("}"));
+ assertTrue(payloads.get("book.sd").endsWith("}\n"));
+ assertTrue(payloads.get("music.sd").endsWith("}\n"));
+ assertTrue(payloads.get("video.sd").endsWith("}\n"));
+ }
+
+ @Test
+ public void testConfigDefinitionsFromJars() throws IOException {
+ String appName = "src/test/cfg//application/app1";
+ FilesApplicationPackage app = FilesApplicationPackage.fromFile(new File(appName));
+ Map<ConfigDefinitionKey, UnparsedConfigDefinition> defs = app.getAllExistingConfigDefs();
+ assertThat(defs.size(), is(2));
+ }
+
+ @Test
+ public void testMetaData() throws IOException, JSONException {
+ File tmp = Files.createTempDir();
+ String appPkg = TESTDIR + "app1";
+ IOUtils.copyDirectory(new File(appPkg), tmp);
+ final DeployData deployData = new DeployData("foo", "bar", "baz", 13l, 1337l, 3l);
+ FilesApplicationPackage app = FilesApplicationPackage.fromFileWithDeployData(tmp, deployData);
+ app.writeMetaData();
+ FilesApplicationPackage newApp = FilesApplicationPackage.fromFileWithDeployData(tmp, deployData);
+ ApplicationMetaData meta = newApp.getMetaData();
+ assertThat(meta.getDeployedByUser(), is("foo"));
+ assertThat(meta.getDeployPath(), is("bar"));
+ assertThat(meta.getDeployTimestamp(), is(13l));
+ assertThat(meta.getGeneration(), is(1337l));
+ assertThat(meta.getPreviousActiveGeneration(), is(3l));
+ final String checkSum = meta.getCheckSum();
+ assertNotNull(checkSum);
+
+ assertTrue((new File(tmp, "hosts.xml")).delete());
+ FilesApplicationPackage app2 = FilesApplicationPackage.fromFileWithDeployData(tmp, deployData);
+ final String app2CheckSum = app2.getMetaData().getCheckSum();
+ assertThat(app2CheckSum, is(not(checkSum)));
+
+ assertTrue((new File(tmp, "files/foo.json")).delete());
+ FilesApplicationPackage app3 = FilesApplicationPackage.fromFileWithDeployData(tmp, deployData);
+ final String app3CheckSum = app3.getMetaData().getCheckSum();
+ assertThat(app3CheckSum, is(not(app2CheckSum)));
+ }
+
+ @Test
+ public void testGetJarEntryName() {
+ JarEntry e = new JarEntry("/searchdefinitions/foo.sd");
+ assertEquals(ApplicationPackage.getFileName(e), "foo.sd");
+ e = new JarEntry("bar");
+ assertEquals(ApplicationPackage.getFileName(e), "bar");
+ e = new JarEntry("");
+ assertEquals(ApplicationPackage.getFileName(e), "");
+ }
+
+ @After
+ public void cleanDirs() {
+ IOUtils.recursiveDeleteDir(new File(TESTDIR + "app1/myDir"));
+ IOUtils.recursiveDeleteDir(new File(TESTDIR + "app1/searchdefinitions/myDir2"));
+ IOUtils.recursiveDeleteDir(new File(TESTDIR + "app1/myDir3"));
+ }
+
+ @SuppressWarnings("ResultOfMethodCallIgnored")
+ @After
+ public void cleanFiles() {
+ new File(new File(TESTDIR + "app1"),"foo.txt").delete();
+ new File(new File(TESTDIR + "app1"),"searchdefinitions/bar.text").delete();
+ IOUtils.recursiveDeleteDir(new File(TESTDIR + "app1/mySubDir"));
+ }
+
+ /**
+ * Tests that an invalid jar is identified as not being a jar file
+ */
+ @Test
+ public void testInvalidJar() {
+ try {
+ FilesApplicationPackage.getComponents(new File("src/test/cfg/application/validation/invalidjar_app"));
+ fail();
+ } catch (IllegalArgumentException e) {
+ assertThat(e.getMessage(), is("Error opening jar file 'invalid.jar'. Please check that this is a valid jar file"));
+ }
+ }
+
+ /**
+ * Tests that config definitions with namespace are treated properly when they have the format
+ * as in the config definitions dir ($VESPA_HOME/var/db/vespa/config_server/serverdb/classes on a machine
+ * with Vespa packages installed) (does not test when read from user def files). Also tests a config
+ * definition without version in file name
+ */
+ @Test
+ public void testConfigDefinitionsAndNamespaces() {
+ final File appDir = new File("src/test/cfg/application/configdeftest");
+ FilesApplicationPackage app = FilesApplicationPackage.fromFile(appDir);
+
+ DeployState deployState = new DeployState.Builder().applicationPackage(app).build();
+
+ ConfigDefinition def = deployState.getConfigDefinition(new ConfigDefinitionKey("foo", CNode.DEFAULT_NAMESPACE));
+ assertThat(def.getNamespace(), is(CNode.DEFAULT_NAMESPACE));
+
+ def = deployState.getConfigDefinition(new ConfigDefinitionKey("baz", CNode.DEFAULT_NAMESPACE));
+ assertThat(def.getNamespace(), is("xyzzy"));
+
+ def = deployState.getConfigDefinition(new ConfigDefinitionKey("foo", "qux"));
+ assertThat(def.getNamespace(), is("qux"));
+
+ // A config def without version in filename and version in file header
+ def = deployState.getConfigDefinition(new ConfigDefinitionKey("xyzzy", CNode.DEFAULT_NAMESPACE));
+ assertThat(def.getNamespace(), is(CNode.DEFAULT_NAMESPACE));
+ assertThat(def.getName(), is("xyzzy"));
+
+ // Without giving namespace, namespace is really CNode.DEFAULT_NAMESPACE
+ def = deployState.getConfigDefinition(new ConfigDefinitionKey("baz", ""));
+ assertThat(def.getNamespace(), is("xyzzy"));
+
+ // Without giving namespace, namespace is really xyzzy
+ def = deployState.getConfigDefinition(new ConfigDefinitionKey("baz", ""));
+ assertThat(def.getNamespace(), is("xyzzy"));
+
+ // Two defs, one with and one without namespace. The one with namespace should have precedence.
+ def = deployState.getConfigDefinition(new ConfigDefinitionKey("bar", "xyzzy"));
+ assertThat(def.getNamespace(), is("xyzzy"));
+ assertTrue(def.getIntDefs().containsKey("foo")); // xyzzy.baz.def has precedence before baz.def, so foo exists
+ assertThat(def.getIntDefs().get("bar").getDefVal(), is(2));
+ }
+
+ @Test(expected=IllegalArgumentException.class)
+ public void testDifferentNameOfSdFileAndSearchName() throws SAXException, IOException {
+ FilesApplicationPackage app = createAppPkg(TESTDIR + "sdfilenametest");
+ new DeployState.Builder().applicationPackage(app).build();
+ }
+
+}