diff --git a/distribution/src/bin/elasticsearch-service.bat b/distribution/src/bin/elasticsearch-service.bat index e03581ddfa6..f566c34c958 100644 --- a/distribution/src/bin/elasticsearch-service.bat +++ b/distribution/src/bin/elasticsearch-service.bat @@ -34,6 +34,7 @@ if /i %SERVICE_CMD% == start goto doStart if /i %SERVICE_CMD% == stop goto doStop if /i %SERVICE_CMD% == manager goto doManagment echo Unknown option "%SERVICE_CMD%" +exit /B 1 :displayUsage echo. @@ -44,6 +45,7 @@ goto:eof "%EXECUTABLE%" //ES//%SERVICE_ID% %LOG_OPTS% if not errorlevel 1 goto started echo Failed starting '%SERVICE_ID%' service +exit /B 1 goto:eof :started echo The service '%SERVICE_ID%' has been started @@ -53,16 +55,18 @@ goto:eof "%EXECUTABLE%" //SS//%SERVICE_ID% %LOG_OPTS% if not errorlevel 1 goto stopped echo Failed stopping '%SERVICE_ID%' service +exit /B 1 goto:eof :stopped echo The service '%SERVICE_ID%' has been stopped goto:eof :doManagment -set EXECUTABLE_MGR=%ES_HOME%\bin\elasticsearch-service-mgr.exe +set EXECUTABLE_MGR=%ES_HOME%\bin\elasticsearch-service-mgr "%EXECUTABLE_MGR%" //ES//%SERVICE_ID% if not errorlevel 1 goto managed echo Failed starting service manager for '%SERVICE_ID%' +exit /B 1 goto:eof :managed echo Successfully started service manager for '%SERVICE_ID%'. @@ -73,6 +77,7 @@ rem Remove the service "%EXECUTABLE%" //DS//%SERVICE_ID% %LOG_OPTS% if not errorlevel 1 goto removed echo Failed removing '%SERVICE_ID%' service +exit /B 1 goto:eof :removed echo The service '%SERVICE_ID%' has been removed @@ -177,6 +182,7 @@ if not "%SERVICE_USERNAME%" == "" ( if not errorlevel 1 goto installed echo Failed installing '%SERVICE_ID%' service +exit /B 1 goto:eof :installed diff --git a/qa/vagrant/src/main/java/org/elasticsearch/packaging/PackagingTests.java b/qa/vagrant/src/main/java/org/elasticsearch/packaging/PackagingTests.java index 57b647e1207..a2b11eaff55 100644 --- a/qa/vagrant/src/main/java/org/elasticsearch/packaging/PackagingTests.java +++ b/qa/vagrant/src/main/java/org/elasticsearch/packaging/PackagingTests.java @@ -19,20 +19,20 @@ package org.elasticsearch.packaging; -import org.elasticsearch.packaging.test.DefaultDebPreservationTests; import org.elasticsearch.packaging.test.DefaultDebBasicTests; -import org.elasticsearch.packaging.test.DefaultRpmPreservationTests; +import org.elasticsearch.packaging.test.DefaultDebPreservationTests; import org.elasticsearch.packaging.test.DefaultRpmBasicTests; -import org.elasticsearch.packaging.test.OssDebPreservationTests; -import org.elasticsearch.packaging.test.OssDebBasicTests; -import org.elasticsearch.packaging.test.OssRpmPreservationTests; -import org.elasticsearch.packaging.test.OssRpmBasicTests; -import org.elasticsearch.packaging.test.OssTarTests; -import org.elasticsearch.packaging.test.OssZipTests; +import org.elasticsearch.packaging.test.DefaultRpmPreservationTests; import org.elasticsearch.packaging.test.DefaultTarTests; +import org.elasticsearch.packaging.test.DefaultWindowsServiceTests; import org.elasticsearch.packaging.test.DefaultZipTests; -import org.elasticsearch.packaging.test.PackageDependenciesTests; - +import org.elasticsearch.packaging.test.OssDebBasicTests; +import org.elasticsearch.packaging.test.OssDebPreservationTests; +import org.elasticsearch.packaging.test.OssRpmBasicTests; +import org.elasticsearch.packaging.test.OssRpmPreservationTests; +import org.elasticsearch.packaging.test.OssTarTests; +import org.elasticsearch.packaging.test.OssWindowsServiceTests; +import org.elasticsearch.packaging.test.OssZipTests; import org.junit.runner.RunWith; import org.junit.runners.Suite; import org.junit.runners.Suite.SuiteClasses; @@ -43,7 +43,6 @@ import org.junit.runners.Suite.SuiteClasses; OssTarTests.class, DefaultZipTests.class, OssZipTests.class, - PackageDependenciesTests.class, DefaultRpmBasicTests.class, OssRpmBasicTests.class, DefaultDebBasicTests.class, @@ -51,6 +50,8 @@ import org.junit.runners.Suite.SuiteClasses; DefaultDebPreservationTests.class, OssDebPreservationTests.class, DefaultRpmPreservationTests.class, - OssRpmPreservationTests.class + OssRpmPreservationTests.class, + DefaultWindowsServiceTests.class, + OssWindowsServiceTests.class }) public class PackagingTests {} diff --git a/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/ArchiveTestCase.java b/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/ArchiveTestCase.java index 0108f88ecd1..341ecc78bc9 100644 --- a/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/ArchiveTestCase.java +++ b/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/ArchiveTestCase.java @@ -22,15 +22,12 @@ package org.elasticsearch.packaging.test; import com.carrotsearch.randomizedtesting.annotations.TestCaseOrdering; import org.apache.http.client.fluent.Request; import org.elasticsearch.packaging.util.Archives; +import org.elasticsearch.packaging.util.Distribution; +import org.elasticsearch.packaging.util.Installation; import org.elasticsearch.packaging.util.Platforms; import org.elasticsearch.packaging.util.ServerUtils; import org.elasticsearch.packaging.util.Shell; import org.elasticsearch.packaging.util.Shell.Result; -import org.junit.Before; -import org.junit.BeforeClass; - -import org.elasticsearch.packaging.util.Distribution; -import org.elasticsearch.packaging.util.Installation; import java.io.IOException; import java.nio.file.Files; @@ -40,7 +37,6 @@ import java.util.stream.Stream; import static java.util.stream.Collectors.joining; import static org.elasticsearch.packaging.util.Archives.ARCHIVE_OWNER; -import static org.elasticsearch.packaging.util.Cleanup.cleanEverything; import static org.elasticsearch.packaging.util.Archives.installArchive; import static org.elasticsearch.packaging.util.Archives.verifyArchiveInstallation; import static org.elasticsearch.packaging.util.FileMatcher.Fileness.File; @@ -55,12 +51,8 @@ import static org.elasticsearch.packaging.util.ServerUtils.makeRequest; import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; -import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.isEmptyString; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; import static org.junit.Assume.assumeThat; -import static org.junit.Assume.assumeTrue; /** * Tests that apply to the archive distributions (tar, zip). To add a case for a distribution, subclass and @@ -69,22 +61,6 @@ import static org.junit.Assume.assumeTrue; @TestCaseOrdering(TestCaseOrdering.AlphabeticOrder.class) public abstract class ArchiveTestCase extends PackagingTestCase { - private static Installation installation; - - /** The {@link Distribution} that should be tested in this case */ - protected abstract Distribution distribution(); - - @BeforeClass - public static void cleanup() { - installation = null; - cleanEverything(); - } - - @Before - public void onlyCompatibleDistributions() { - assumeTrue("only compatible distributions", distribution().packaging.compatible); - } - public void test10Install() { installation = installArchive(distribution()); verifyArchiveInstallation(installation, distribution()); diff --git a/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/DefaultWindowsServiceTests.java b/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/DefaultWindowsServiceTests.java new file mode 100644 index 00000000000..072c3da6886 --- /dev/null +++ b/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/DefaultWindowsServiceTests.java @@ -0,0 +1,30 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.elasticsearch.packaging.test; + +import org.elasticsearch.packaging.util.Distribution; + +public class DefaultWindowsServiceTests extends WindowsServiceTestCase { + + @Override + protected Distribution distribution() { + return Distribution.DEFAULT_ZIP; + } +} diff --git a/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/OssDebBasicTests.java b/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/OssDebBasicTests.java index 5d779ac4653..38ef9c36a29 100644 --- a/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/OssDebBasicTests.java +++ b/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/OssDebBasicTests.java @@ -19,7 +19,17 @@ package org.elasticsearch.packaging.test; +import junit.framework.TestCase; import org.elasticsearch.packaging.util.Distribution; +import org.elasticsearch.packaging.util.Platforms; +import org.elasticsearch.packaging.util.Shell; + +import java.util.regex.Pattern; + +import static org.elasticsearch.packaging.util.Distribution.DEFAULT_DEB; +import static org.elasticsearch.packaging.util.Distribution.OSS_DEB; +import static org.elasticsearch.packaging.util.FileUtils.getDistributionFile; +import static org.junit.Assume.assumeTrue; public class OssDebBasicTests extends PackageTestCase { @@ -27,4 +37,19 @@ public class OssDebBasicTests extends PackageTestCase { protected Distribution distribution() { return Distribution.OSS_DEB; } + + public void test11DebDependencies() { + assumeTrue(Platforms.isDPKG()); + + final Shell sh = new Shell(); + + final Shell.Result defaultResult = sh.run("dpkg -I " + getDistributionFile(DEFAULT_DEB)); + final Shell.Result ossResult = sh.run("dpkg -I " + getDistributionFile(OSS_DEB)); + + TestCase.assertTrue(Pattern.compile("(?m)^ Depends:.*bash.*").matcher(defaultResult.stdout).find()); + TestCase.assertTrue(Pattern.compile("(?m)^ Depends:.*bash.*").matcher(ossResult.stdout).find()); + + TestCase.assertTrue(Pattern.compile("(?m)^ Conflicts: elasticsearch-oss$").matcher(defaultResult.stdout).find()); + TestCase.assertTrue(Pattern.compile("(?m)^ Conflicts: elasticsearch$").matcher(ossResult.stdout).find()); + } } diff --git a/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/OssRpmBasicTests.java b/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/OssRpmBasicTests.java index d3320c07955..91abb5e0c5c 100644 --- a/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/OssRpmBasicTests.java +++ b/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/OssRpmBasicTests.java @@ -19,7 +19,17 @@ package org.elasticsearch.packaging.test; +import junit.framework.TestCase; import org.elasticsearch.packaging.util.Distribution; +import org.elasticsearch.packaging.util.Platforms; +import org.elasticsearch.packaging.util.Shell; + +import java.util.regex.Pattern; + +import static org.elasticsearch.packaging.util.Distribution.DEFAULT_RPM; +import static org.elasticsearch.packaging.util.Distribution.OSS_RPM; +import static org.elasticsearch.packaging.util.FileUtils.getDistributionFile; +import static org.junit.Assume.assumeTrue; public class OssRpmBasicTests extends PackageTestCase { @@ -27,4 +37,22 @@ public class OssRpmBasicTests extends PackageTestCase { protected Distribution distribution() { return Distribution.OSS_RPM; } + + public void test11RpmDependencies() { + assumeTrue(Platforms.isRPM()); + + final Shell sh = new Shell(); + + final Shell.Result defaultDeps = sh.run("rpm -qpR " + getDistributionFile(DEFAULT_RPM)); + final Shell.Result ossDeps = sh.run("rpm -qpR " + getDistributionFile(OSS_RPM)); + + TestCase.assertTrue(Pattern.compile("(?m)^/bin/bash\\s*$").matcher(defaultDeps.stdout).find()); + TestCase.assertTrue(Pattern.compile("(?m)^/bin/bash\\s*$").matcher(ossDeps.stdout).find()); + + final Shell.Result defaultConflicts = sh.run("rpm -qp --conflicts " + getDistributionFile(DEFAULT_RPM)); + final Shell.Result ossConflicts = sh.run("rpm -qp --conflicts " + getDistributionFile(OSS_RPM)); + + TestCase.assertTrue(Pattern.compile("(?m)^elasticsearch-oss\\s*$").matcher(defaultConflicts.stdout).find()); + TestCase.assertTrue(Pattern.compile("(?m)^elasticsearch\\s*$").matcher(ossConflicts.stdout).find()); + } } diff --git a/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/OssWindowsServiceTests.java b/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/OssWindowsServiceTests.java new file mode 100644 index 00000000000..f4de95f67b6 --- /dev/null +++ b/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/OssWindowsServiceTests.java @@ -0,0 +1,30 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.elasticsearch.packaging.test; + +import org.elasticsearch.packaging.util.Distribution; + +public class OssWindowsServiceTests extends WindowsServiceTestCase { + + @Override + protected Distribution distribution() { + return Distribution.OSS_ZIP; + } +} diff --git a/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/PackageDependenciesTests.java b/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/PackageDependenciesTests.java deleted file mode 100644 index 6861ef0a3ff..00000000000 --- a/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/PackageDependenciesTests.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.elasticsearch.packaging.test; - -import org.elasticsearch.packaging.util.Platforms; -import org.elasticsearch.packaging.util.Shell; -import org.elasticsearch.packaging.util.Shell.Result; - -import java.util.regex.Pattern; - -import static junit.framework.TestCase.assertTrue; -import static org.elasticsearch.packaging.util.Distribution.DEFAULT_DEB; -import static org.elasticsearch.packaging.util.Distribution.DEFAULT_RPM; -import static org.elasticsearch.packaging.util.Distribution.OSS_DEB; -import static org.elasticsearch.packaging.util.Distribution.OSS_RPM; -import static org.elasticsearch.packaging.util.FileUtils.getDistributionFile; -import static org.junit.Assume.assumeTrue; - -/** - * Tests that linux packages correctly declare their dependencies and their conflicts - */ -public class PackageDependenciesTests extends PackagingTestCase { - - public void testDebDependencies() { - assumeTrue(Platforms.isDPKG()); - - final Shell sh = new Shell(); - - final Result defaultResult = sh.run("dpkg -I " + getDistributionFile(DEFAULT_DEB)); - final Result ossResult = sh.run("dpkg -I " + getDistributionFile(OSS_DEB)); - - assertTrue(Pattern.compile("(?m)^ Depends:.*bash.*").matcher(defaultResult.stdout).find()); - assertTrue(Pattern.compile("(?m)^ Depends:.*bash.*").matcher(ossResult.stdout).find()); - - assertTrue(Pattern.compile("(?m)^ Conflicts: elasticsearch-oss$").matcher(defaultResult.stdout).find()); - assertTrue(Pattern.compile("(?m)^ Conflicts: elasticsearch$").matcher(ossResult.stdout).find()); - } - - public void testRpmDependencies() { - assumeTrue(Platforms.isRPM()); - - final Shell sh = new Shell(); - - final Result defaultDeps = sh.run("rpm -qpR " + getDistributionFile(DEFAULT_RPM)); - final Result ossDeps = sh.run("rpm -qpR " + getDistributionFile(OSS_RPM)); - - assertTrue(Pattern.compile("(?m)^/bin/bash\\s*$").matcher(defaultDeps.stdout).find()); - assertTrue(Pattern.compile("(?m)^/bin/bash\\s*$").matcher(ossDeps.stdout).find()); - - final Result defaultConflicts = sh.run("rpm -qp --conflicts " + getDistributionFile(DEFAULT_RPM)); - final Result ossConflicts = sh.run("rpm -qp --conflicts " + getDistributionFile(OSS_RPM)); - - assertTrue(Pattern.compile("(?m)^elasticsearch-oss\\s*$").matcher(defaultConflicts.stdout).find()); - assertTrue(Pattern.compile("(?m)^elasticsearch\\s*$").matcher(ossConflicts.stdout).find()); - } -} diff --git a/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/PackageTestCase.java b/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/PackageTestCase.java index 95705e94a43..db31babca57 100644 --- a/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/PackageTestCase.java +++ b/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/PackageTestCase.java @@ -20,13 +20,9 @@ package org.elasticsearch.packaging.test; import com.carrotsearch.randomizedtesting.annotations.TestCaseOrdering; -import org.elasticsearch.packaging.util.Distribution; -import org.elasticsearch.packaging.util.Installation; import org.elasticsearch.packaging.util.Shell; - import org.elasticsearch.packaging.util.Shell.Result; import org.junit.Before; -import org.junit.BeforeClass; import java.io.IOException; import java.nio.file.Files; @@ -35,7 +31,6 @@ import java.nio.file.Paths; import java.util.regex.Matcher; import java.util.regex.Pattern; -import static org.elasticsearch.packaging.util.Cleanup.cleanEverything; import static org.elasticsearch.packaging.util.FileUtils.assertPathsDontExist; import static org.elasticsearch.packaging.util.FileUtils.mv; import static org.elasticsearch.packaging.util.Packages.SYSTEMD_SERVICE; @@ -49,31 +44,17 @@ import static org.elasticsearch.packaging.util.Packages.verifyPackageInstallatio import static org.elasticsearch.packaging.util.Platforms.getOsRelease; import static org.elasticsearch.packaging.util.Platforms.isSystemd; import static org.elasticsearch.packaging.util.ServerUtils.runElasticsearchTests; - import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.CoreMatchers.notNullValue; -import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.isEmptyString; - import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertFalse; import static org.junit.Assume.assumeThat; import static org.junit.Assume.assumeTrue; @TestCaseOrdering(TestCaseOrdering.AlphabeticOrder.class) public abstract class PackageTestCase extends PackagingTestCase { - private static Installation installation; - - protected abstract Distribution distribution(); - - @BeforeClass - public static void cleanup() { - installation = null; - cleanEverything(); - } - @Before public void onlyCompatibleDistributions() { assumeTrue("only compatible distributions", distribution().packaging.compatible); diff --git a/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/PackagingTestCase.java b/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/PackagingTestCase.java index 77644b70f28..81d4a90b2a0 100644 --- a/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/PackagingTestCase.java +++ b/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/PackagingTestCase.java @@ -21,23 +21,32 @@ package org.elasticsearch.packaging.test; import com.carrotsearch.randomizedtesting.JUnit3MethodProvider; import com.carrotsearch.randomizedtesting.RandomizedRunner; +import com.carrotsearch.randomizedtesting.annotations.TestCaseOrdering; import com.carrotsearch.randomizedtesting.annotations.TestMethodProviders; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.elasticsearch.packaging.util.Distribution; +import org.elasticsearch.packaging.util.Installation; +import org.junit.Assert; import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Rule; import org.junit.rules.TestName; import org.junit.runner.RunWith; +import static org.elasticsearch.packaging.util.Cleanup.cleanEverything; +import static org.junit.Assume.assumeTrue; + @RunWith(RandomizedRunner.class) @TestMethodProviders({ JUnit3MethodProvider.class }) +@TestCaseOrdering(TestCaseOrdering.AlphabeticOrder.class) /** * Class that all packaging test cases should inherit from. This makes working with the packaging tests more similar to what we're * familiar with from {@link org.elasticsearch.test.ESTestCase} without having to apply its behavior that's not relevant here */ -public abstract class PackagingTestCase { +public abstract class PackagingTestCase extends Assert { protected final Log logger = LogFactory.getLog(getClass()); @@ -45,7 +54,21 @@ public abstract class PackagingTestCase { public final TestName testNameRule = new TestName(); @Before - public void logTestNameBefore() { + public void setup() { + assumeTrue("only compatible distributions", distribution().packaging.compatible); logger.info("[" + testNameRule.getMethodName() + "]: before test"); } + + protected static Installation installation; + + @BeforeClass + public static void cleanup() { + installation = null; + cleanEverything(); + } + + /** The {@link Distribution} that should be tested in this case */ + protected abstract Distribution distribution(); + + } diff --git a/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/WindowsServiceTestCase.java b/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/WindowsServiceTestCase.java new file mode 100644 index 00000000000..e9c514ea6bc --- /dev/null +++ b/qa/vagrant/src/main/java/org/elasticsearch/packaging/test/WindowsServiceTestCase.java @@ -0,0 +1,253 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.elasticsearch.packaging.test; + +import junit.framework.TestCase; +import org.elasticsearch.packaging.util.FileUtils; +import org.elasticsearch.packaging.util.Platforms; +import org.elasticsearch.packaging.util.ServerUtils; +import org.elasticsearch.packaging.util.Shell; +import org.elasticsearch.packaging.util.Shell.Result; +import org.junit.After; +import org.junit.Before; +import org.junit.BeforeClass; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Arrays; + +import static com.carrotsearch.randomizedtesting.RandomizedTest.assumeTrue; +import static java.util.stream.Collectors.joining; +import static org.elasticsearch.packaging.util.Archives.installArchive; +import static org.elasticsearch.packaging.util.Archives.verifyArchiveInstallation; +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.Matchers.equalTo; + +public abstract class WindowsServiceTestCase extends PackagingTestCase { + + private static final String DEFAULT_ID = "elasticsearch-service-x64"; + private static final String DEFAULT_DISPLAY_NAME = "Elasticsearch " + FileUtils.getCurrentVersion() + " (elasticsearch-service-x64)"; + private static String serviceScript; + + private Shell sh; + + @Before + public void createShell() { + sh = new Shell(); + } + + @BeforeClass + public static void ensureWindows() { + assumeTrue(Platforms.WINDOWS); + } + + @After + public void uninstallService() { + sh.runIgnoreExitCode(serviceScript + " remove"); + } + + private Result runWithoutJava(String script) { + // on windows, removing java from PATH and removing JAVA_HOME is less involved than changing the permissions of the java + // executable. we also don't check permissions in the windows scripts anyway + final String originalPath = sh.run("$Env:PATH").stdout.trim(); + final String newPath = Arrays.stream(originalPath.split(";")) + .filter(path -> path.contains("Java") == false) + .collect(joining(";")); + + // note the lack of a $ when clearing the JAVA_HOME env variable - with a $ it deletes the java home directory + // https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/providers/environment-provider?view=powershell-6 + // + // this won't persist to another session so we don't have to reset anything + return sh.runIgnoreExitCode( + "$Env:PATH = '" + newPath + "'; " + + "Remove-Item Env:JAVA_HOME; " + + script + ); + } + + private void assertService(String id, String status, String displayName) { + Result result = sh.run("Get-Service " + id + " | Format-List -Property Name, Status, DisplayName"); + assertThat(result.stdout, containsString("Name : " + id)); + assertThat(result.stdout, containsString("Status : " + status)); + assertThat(result.stdout, containsString("DisplayName : " + displayName)); + } + + // runs the service command, dumping all log files on failure + private void assertCommand(String script) { + Result result = sh.runIgnoreExitCode(script); + if (result.exitCode != 0) { + logger.error("---- Failed to run script: " + script); + logger.error(result); + logger.error("Dumping log files\n"); + Result logs = sh.run("$files = Get-ChildItem \"" + installation.logs + "\\elasticsearch.log\"; " + + "Write-Output $files; " + + "foreach ($file in $files) {" + + "Write-Output \"$file\"; " + + "Get-Content \"$file\" " + + "}"); + logger.error(logs.stdout); + fail(); + } else { + logger.info("\nscript: " + script + "\nstdout: " + result.stdout + "\nstderr: " + result.stderr); + } + } + + public void test10InstallArchive() { + installation = installArchive(distribution()); + verifyArchiveInstallation(installation, distribution()); + serviceScript = installation.bin("elasticsearch-service.bat").toString(); + } + + public void test11InstallServiceExeMissing() throws IOException { + Path serviceExe = installation.bin("elasticsearch-service-x64.exe"); + Path tmpServiceExe = serviceExe.getParent().resolve(serviceExe.getFileName() + ".tmp"); + Files.move(serviceExe, tmpServiceExe); + Result result = sh.runIgnoreExitCode(serviceScript + " install"); + assertThat(result.exitCode, equalTo(1)); + assertThat(result.stdout, containsString("elasticsearch-service-x64.exe was not found...")); + Files.move(tmpServiceExe, serviceExe); + } + + public void test12InstallService() { + sh.run(serviceScript + " install"); + assertService(DEFAULT_ID, "Stopped", DEFAULT_DISPLAY_NAME); + sh.run(serviceScript + " remove"); + } + + public void test13InstallMissingJava() throws IOException { + Result result = runWithoutJava(serviceScript + " install"); + assertThat(result.exitCode, equalTo(1)); + assertThat(result.stderr, containsString("could not find java; set JAVA_HOME or ensure java is in PATH")); + } + + public void test14RemoveNotInstalled() { + Result result = sh.runIgnoreExitCode(serviceScript + " remove"); + assertThat(result.stdout, result.exitCode, equalTo(1)); + assertThat(result.stdout, containsString("Failed removing '" + DEFAULT_ID + "' service")); + } + + public void test20CustomizeServiceId() { + String serviceId = "my-es-service"; + String displayName = DEFAULT_DISPLAY_NAME.replace(DEFAULT_ID, serviceId); + sh.getEnv().put("SERVICE_ID", serviceId); + sh.run(serviceScript + " install"); + assertService(serviceId, "Stopped", displayName); + sh.run(serviceScript + " remove"); + } + + public void test21CustomizeServiceDisplayName() { + String displayName = "my es service display name"; + sh.getEnv().put("SERVICE_DISPLAY_NAME", displayName); + sh.run(serviceScript + " install"); + assertService(DEFAULT_ID, "Stopped", displayName); + sh.run(serviceScript + " remove"); + } + + // NOTE: service description is not attainable through any powershell api, so checking it is not possible... + + public void test30StartStop() throws IOException { + sh.run(serviceScript + " install"); + assertCommand(serviceScript + " start"); + ServerUtils.waitForElasticsearch(); + ServerUtils.runElasticsearchTests(); + + assertCommand(serviceScript + " stop"); + assertService(DEFAULT_ID, "Stopped", DEFAULT_DISPLAY_NAME); + // the process is stopped async, and can become a zombie process, so we poll for the process actually being gone + assertCommand("$p = Get-Service -Name \"elasticsearch-service-x64\" -ErrorAction SilentlyContinue;" + + "$i = 0;" + + "do {" + + "$p = Get-Process -Name \"elasticsearch-service-x64\" -ErrorAction SilentlyContinue;" + + "echo \"$p\";" + + "if ($p -eq $Null) {" + + " Write-Host \"exited after $i seconds\";" + + " exit 0;" + + "}" + + "Start-Sleep -Seconds 1;" + + "$i += 1;" + + "} while ($i -lt 300);" + + "exit 9;"); + + assertCommand(serviceScript + " remove"); + assertCommand("$p = Get-Service -Name \"elasticsearch-service-x64\" -ErrorAction SilentlyContinue;" + + "echo \"$p\";" + + "if ($p -eq $Null) {" + + " exit 0;" + + "} else {" + + " exit 1;" + + "}"); + } + + public void test31StartNotInstalled() throws IOException { + Result result = sh.runIgnoreExitCode(serviceScript + " start"); + assertThat(result.stdout, result.exitCode, equalTo(1)); + assertThat(result.stdout, containsString("Failed starting '" + DEFAULT_ID + "' service")); + } + + public void test32StopNotStarted() throws IOException { + sh.run(serviceScript + " install"); + Result result = sh.run(serviceScript + " stop"); // stop is ok when not started + assertThat(result.stdout, containsString("The service '" + DEFAULT_ID + "' has been stopped")); + } + + /* + // TODO: need to make JAVA_HOME resolve at install time for this to work + // see https://github.com/elastic/elasticsearch/issues/23097 + public void test33JavaChanged() throws IOException { + sh.run(serviceScript + " install"); + runWithoutJava(serviceScript + "start"); + ServerUtils.waitForElasticsearch(); + sh.run(serviceScript + " stop"); + sh.runIgnoreExitCode("Wait-Process -Name \"elasticsearch-service-x64\" -Timeout 10"); + sh.run(serviceScript + " remove"); + }*/ + + public void test60Manager() throws IOException { + Path serviceMgr = installation.bin("elasticsearch-service-mgr.exe"); + Path tmpServiceMgr = serviceMgr.getParent().resolve(serviceMgr.getFileName() + ".tmp"); + Files.move(serviceMgr, tmpServiceMgr); + Path fakeServiceMgr = serviceMgr.getParent().resolve("elasticsearch-service-mgr.bat"); + Files.write(fakeServiceMgr, Arrays.asList("echo \"Fake Service Manager GUI\"")); + Shell sh = new Shell(); + Result result = sh.run(serviceScript + " manager"); + assertThat(result.stdout, containsString("Fake Service Manager GUI")); + + // check failure too + Files.write(fakeServiceMgr, Arrays.asList("echo \"Fake Service Manager GUI Failure\"", "exit 1")); + result = sh.runIgnoreExitCode(serviceScript + " manager"); + TestCase.assertEquals(1, result.exitCode); + TestCase.assertTrue(result.stdout, result.stdout.contains("Fake Service Manager GUI Failure")); + Files.move(tmpServiceMgr, serviceMgr); + } + + public void test70UnknownCommand() { + Result result = sh.runIgnoreExitCode(serviceScript + " bogus"); + assertThat(result.exitCode, equalTo(1)); + assertThat(result.stdout, containsString("Unknown option \"bogus\"")); + } + + // TODO: + // custom SERVICE_USERNAME/SERVICE_PASSWORD + // custom SERVICE_LOG_DIR + // custom LOG_OPTS (looks like it currently conflicts with setting custom log dir) + // install and run with java opts + // install and run java opts Xmx/s (each data size type) +}