Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -149,8 +149,9 @@ echo Usage:
echo(
echo service install ^<options^> , where the options are:
echo(
echo /startup : Set the service to auto start
echo Not specifying sets the service to manual
echo /startup ^<startup type^> : Set the service start to Automatic or Automatic (Delayed Start)
echo Not specifying sets the service to manual,
echo Specifying without parameter set the service to Automatic start
echo(
echo /jbossuser ^<username^> : JBoss username to use for the shutdown command.
echo(
Expand Down Expand Up @@ -248,7 +249,16 @@ if /I "%~1"== "/debug" (
goto LoopArgs
)
if /I "%~1"== "/startup" (
set STARTUP_MODE=auto
if /I not "%~2"=="manual" if /I not "%~2"=="auto" if /I not "%~2"=="delayed" if /I not "%~2"=="" (
echo ERROR: /startup must be set to manual, auto or delayed ^(Case insensitive^)
goto endBatch
)
if "%~2"=="" (
set STARTUP_MODE=auto
) else (
set STARTUP_MODE=%~2
)
shift
shift
goto LoopArgs
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,7 @@ private static Path copy(final String targetName) {
}
}

private static void copyDirectory(final Path source, final Path target) throws IOException {
public static void copyDirectory(final Path source, final Path target) throws IOException {
Files.walkFileTree(source, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(final Path file, final BasicFileAttributes attrs) throws IOException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,17 @@ public class ScriptProcess extends Process implements AutoCloseable {
private Process delegate;
private Path stdoutLog;
private String lastExecutedCmd;
private boolean skipFormatter;

ScriptProcess(final Path containerHome, final String scriptBaseName, final Shell shell, final long timeout, final boolean skipFormatter) {
this.containerHome = containerHome;
final String scriptName = scriptBaseName + shell.getExtension();
this.script = containerHome.resolve("bin").resolve(scriptName);
this.timeout = timeout;
this.prefixCmds = Arrays.asList(shell.getPrefix());
this.skipFormatter = skipFormatter;
lastExecutedCmd = "";
}

ScriptProcess(final Path containerHome, final String scriptBaseName, final Shell shell, final long timeout) {
this.containerHome = containerHome;
Expand Down Expand Up @@ -173,7 +184,11 @@ private List<String> getCommand(final Collection<String> arguments) {
cmd.add(script.toString());
if (TestSuiteEnvironment.isWindows()) {
for (String arg : arguments) {
cmd.add(WINDOWS_ARG_FORMATTER.apply(arg));
if (skipFormatter) {
cmd.add(arg);
} else {
cmd.add(WINDOWS_ARG_FORMATTER.apply(arg));
}
}
} else {
cmd.addAll(arguments);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,289 @@
/*
* Copyright The WildFly Authors
* SPDX-License-Identifier: Apache-2.0
*/

package org.wildfly.scripts.test;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeoutException;

import org.jboss.as.test.shared.TestSuiteEnvironment;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.Assume;
import org.junit.BeforeClass;
import org.junit.Test;
import org.wildfly.common.test.ServerConfigurator;
import org.wildfly.common.test.ServerHelper;

/**
* Tests for the Windows service.bat script.
*
*/
public class ServiceScriptTestCase extends ScriptTestCase {

private static final String TEST_SERVICE_NAME = "WildFlyTest";
private static final String POWERSHELL = "powershell";
private static final List<Path> copiedScripts = new ArrayList<>();
private String installedServiceName = null;

public ServiceScriptTestCase() {
super("service");
}

@BeforeClass
public static void setupServiceScript() throws IOException {
for (Path containerHome : ServerConfigurator.PATHS) {
final Path sourceScript = containerHome.resolve("docs").resolve("contrib").resolve("scripts")
.resolve("service").resolve("service.bat");
final Path targetScript = containerHome.resolve("bin").resolve("service.bat");

if (Files.exists(sourceScript) && !Files.exists(targetScript)) {
Files.copy(sourceScript, targetScript);
copiedScripts.add(targetScript);
}
}
}

@AfterClass
public static void cleanupServiceScript() throws IOException {
for (Path script : copiedScripts) {
if (Files.exists(script)) {
Files.delete(script);
}
}
copiedScripts.clear();
}

@After
public void cleanupService() throws InterruptedException, TimeoutException, IOException {
if (installedServiceName != null && TestSuiteEnvironment.isWindows()) {
try {
if (isServiceInstalled(installedServiceName)) {
uninstallService(installedServiceName);
}
} finally {
installedServiceName = null;
}
}
}

@Test
public void testBatchScript() throws Exception {
Assume.assumeTrue("Service script doesnt run without parameters", false);
}

@Test
public void testPowerShellScript() throws Exception {
Assume.assumeTrue("Service script doesnt have powershell variant", false);
}

@Override
void testScript(final ScriptProcess script) throws InterruptedException, TimeoutException, IOException {
Assume.assumeTrue("Service script only runs on Windows", TestSuiteEnvironment.isWindows());
}

@Test
public void testActualServiceInstallWithAutoStartupParameter() throws Exception {
Assume.assumeTrue("Service installation test only runs on Windows", TestSuiteEnvironment.isWindows());
Assume.assumeTrue("PowerShell must be available", Shell.POWERSHELL.isSupported());
Assume.assumeTrue("Service installation requires administrator privileges", isRunningAsAdmin());

testServiceInstallationWithStartupType("auto", "Auto");
}

@Test
public void testActualServiceInstallWithEmptyStartupParameter() throws Exception {
Assume.assumeTrue("Service installation test only runs on Windows", TestSuiteEnvironment.isWindows());
Assume.assumeTrue("PowerShell must be available", Shell.POWERSHELL.isSupported());
Assume.assumeTrue("Service installation requires administrator privileges", isRunningAsAdmin());

testServiceInstallationWithStartupType("", "Auto");
}

@Test
public void testActualServiceInstallWithDelayedStartupParameter() throws Exception {
Assume.assumeTrue("Service installation test only runs on Windows", TestSuiteEnvironment.isWindows());
Assume.assumeTrue("PowerShell must be available", Shell.POWERSHELL.isSupported());
Assume.assumeTrue("Service installation requires administrator privileges", isRunningAsAdmin());

testServiceInstallationWithStartupType("delayed", "Delayed");
}

@Test
public void testActualServiceInstallWithManualStartupParameter() throws Exception {
Assume.assumeTrue("Service installation test only runs on Windows", TestSuiteEnvironment.isWindows());
Assume.assumeTrue("PowerShell must be available", Shell.POWERSHELL.isSupported());
Assume.assumeTrue("Service installation requires administrator privileges", isRunningAsAdmin());

testServiceInstallationWithStartupType("manual", "Manual");
}

@Test
public void testActualServiceInstallWithoutStartupParameter() throws Exception {
Assume.assumeTrue("Service installation test only runs on Windows", TestSuiteEnvironment.isWindows());
Assume.assumeTrue("PowerShell must be available", Shell.POWERSHELL.isSupported());
Assume.assumeTrue("Service installation requires administrator privileges", isRunningAsAdmin());

final String serviceName = TEST_SERVICE_NAME + "_none";
installedServiceName = serviceName;

try (ScriptProcess script = new ScriptProcess(ServerHelper.JBOSS_HOME, "service", Shell.BATCH, 60, true)) {
script.start("install", "/name", serviceName);
validateProcess(script);

Assert.assertTrue("Service should be installed", isServiceInstalled(serviceName));

final String actualStartMode = getServiceStartupType(serviceName);

Assert.assertEquals(
String.format("Service startup type should be %s but was %s", "Manual", actualStartMode),
"Manual",
actualStartMode);
}
}

private void testServiceInstallationWithStartupType(final String startupParam, String expectedStartMode)
throws InterruptedException, TimeoutException, IOException {

final String serviceName = TEST_SERVICE_NAME + "_" + startupParam;
installedServiceName = serviceName;

try (ScriptProcess script = new ScriptProcess(ServerHelper.JBOSS_HOME, "service", Shell.BATCH, 60, true)) {
script.start("install", "/startup", startupParam, "/name", serviceName);
validateProcess(script);

Assert.assertTrue("Service should be installed", isServiceInstalled(serviceName));

final String actualStartMode = getServiceStartupType(serviceName);

Assert.assertEquals(
String.format("Service startup type should be %s but was %s", expectedStartMode, actualStartMode),
expectedStartMode,
actualStartMode);
}
}

private boolean isServiceInstalled(final String serviceName) throws IOException {
ProcessBuilder builder = new ProcessBuilder(
POWERSHELL,
"-NoProfile",
"-NonInteractive",
"-ExecutionPolicy", "Bypass",
"-Command",
"Get-Service -Name " + serviceName + " -ErrorAction SilentlyContinue | select -property name"
);

Process powerShellProcess = builder.start();
powerShellProcess.getOutputStream().close();

BufferedReader stdout = new BufferedReader(new InputStreamReader(powerShellProcess.getInputStream()));
String line;
while ((line = stdout.readLine()) != null) {
if (line.contains(serviceName)) {
return true;
}
}

return false;
}

private String getServiceStartupType(final String serviceName) throws IOException {
String command = String.format(
"$svc = Get-CimInstance -ClassName Win32_Service | Where-Object {$_.Name -eq '%s'}; " +
"if ($svc) { " +
"Write-Host \"StartMode:$($svc.StartMode)\"; " +
"Write-Host \"DelayedAutoStart:$($svc.DelayedAutoStart)\" " +
"}",
serviceName
);

ProcessBuilder builder = new ProcessBuilder(
POWERSHELL,
"-NoProfile",
"-NonInteractive",
"-ExecutionPolicy", "Bypass",
"-Command",
command
);
final Process process = builder.start();
process.getOutputStream().close();

String startMode = null;
Boolean delayedAutoStart = null;

try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
String line;
while ((line = reader.readLine()) != null) {
final String trimmed = line.trim();
if (trimmed.startsWith("StartMode:")) {
startMode = trimmed.substring("StartMode:".length()).trim();
} else if (trimmed.startsWith("DelayedAutoStart:")) {
String value = trimmed.substring("DelayedAutoStart:".length()).trim();
delayedAutoStart = Boolean.parseBoolean(value);
}
}
}

if (startMode != null) {
if ("Auto".equalsIgnoreCase(startMode)) {
if (Boolean.TRUE.equals(delayedAutoStart)) {
return "Delayed";
} else {
return "Auto";
}
} else if ("Manual".equalsIgnoreCase(startMode)) {
return "Manual";
} else if ("Disabled".equalsIgnoreCase(startMode)) {
return "Disabled";
} else {
return startMode;
}
}

return "Unknown";
}

private void uninstallService(final String serviceName) throws InterruptedException, TimeoutException, IOException {
try (ScriptProcess script = new ScriptProcess(ServerHelper.JBOSS_HOME, "service", Shell.BATCH, 60)) {
script.start("uninstall", "/name", serviceName);
script.waitFor(30, java.util.concurrent.TimeUnit.SECONDS);
}
}

private boolean isRunningAsAdmin() throws IOException {
ProcessBuilder builder = new ProcessBuilder(
POWERSHELL,
"-NoProfile",
"-NonInteractive",
"-ExecutionPolicy", "Bypass",
"-Command",
"([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)"
);

Process process = builder.start();
process.getOutputStream().close();

try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
String line;
while ((line = reader.readLine()) != null) {
String trimmed = line.trim();
if (trimmed.equalsIgnoreCase("True")) {
return true;
} else if (trimmed.equalsIgnoreCase("False")) {
return false;
}
}
}

return false;
}
}
Loading