From 013836179ad14e3a490027cb62459123a47834af Mon Sep 17 00:00:00 2001 From: Constructor Date: Mon, 9 Dec 2024 22:31:28 +0100 Subject: [PATCH] TS-38628 Installer Test Migration --- installer/build.gradle.kts | 1 + .../installer/AllPlatformsInstallerTest.java | 145 ------------- .../installer/EnvironmentMapTest.java | 24 --- .../installer/LinuxInstallerTest.java | 181 ---------------- .../installer/WindowsInstallerTest.java | 96 --------- ...stallWindowsSystemEnvironmentStepTest.java | 74 ------- .../installer/utils/MockRegistry.java | 40 ---- .../installer/utils/MockTeamscale.java | 47 ---- .../installer/utils/TeamscaleUtilsTest.java | 52 ----- .../profiler/installer/utils/TestUtils.java | 58 ----- .../utils/UninstallErrorReporterAssert.java | 32 --- .../windows/WindowsRegistryTest.java | 40 ---- .../installer/AllPlatformsInstallerTest.kt | 152 +++++++++++++ .../profiler/installer/EnvironmentMapTest.kt | 23 ++ .../profiler/installer/LinuxInstallerTest.kt | 204 ++++++++++++++++++ .../installer/WindowsInstallerTest.kt | 107 +++++++++ ...InstallWindowsSystemEnvironmentStepTest.kt | 81 +++++++ .../profiler/installer/utils/MockRegistry.kt | 30 +++ .../profiler/installer/utils/MockTeamscale.kt | 42 ++++ .../installer/utils/TeamscaleUtilsTest.kt | 52 +++++ .../profiler/installer/utils/TestUtils.kt | 59 +++++ .../utils/UninstallErrorReporterAssert.kt | 29 +++ .../installer/windows/WindowsRegistryTest.kt | 43 ++++ 23 files changed, 823 insertions(+), 789 deletions(-) delete mode 100644 installer/src/test/java/com/teamscale/profiler/installer/AllPlatformsInstallerTest.java delete mode 100644 installer/src/test/java/com/teamscale/profiler/installer/EnvironmentMapTest.java delete mode 100644 installer/src/test/java/com/teamscale/profiler/installer/LinuxInstallerTest.java delete mode 100644 installer/src/test/java/com/teamscale/profiler/installer/WindowsInstallerTest.java delete mode 100644 installer/src/test/java/com/teamscale/profiler/installer/steps/InstallWindowsSystemEnvironmentStepTest.java delete mode 100644 installer/src/test/java/com/teamscale/profiler/installer/utils/MockRegistry.java delete mode 100644 installer/src/test/java/com/teamscale/profiler/installer/utils/MockTeamscale.java delete mode 100644 installer/src/test/java/com/teamscale/profiler/installer/utils/TeamscaleUtilsTest.java delete mode 100644 installer/src/test/java/com/teamscale/profiler/installer/utils/TestUtils.java delete mode 100644 installer/src/test/java/com/teamscale/profiler/installer/utils/UninstallErrorReporterAssert.java delete mode 100644 installer/src/test/java/com/teamscale/profiler/installer/windows/WindowsRegistryTest.java create mode 100644 installer/src/test/kotlin/com/teamscale/profiler/installer/AllPlatformsInstallerTest.kt create mode 100644 installer/src/test/kotlin/com/teamscale/profiler/installer/EnvironmentMapTest.kt create mode 100644 installer/src/test/kotlin/com/teamscale/profiler/installer/LinuxInstallerTest.kt create mode 100644 installer/src/test/kotlin/com/teamscale/profiler/installer/WindowsInstallerTest.kt create mode 100644 installer/src/test/kotlin/com/teamscale/profiler/installer/steps/InstallWindowsSystemEnvironmentStepTest.kt create mode 100644 installer/src/test/kotlin/com/teamscale/profiler/installer/utils/MockRegistry.kt create mode 100644 installer/src/test/kotlin/com/teamscale/profiler/installer/utils/MockTeamscale.kt create mode 100644 installer/src/test/kotlin/com/teamscale/profiler/installer/utils/TeamscaleUtilsTest.kt create mode 100644 installer/src/test/kotlin/com/teamscale/profiler/installer/utils/TestUtils.kt create mode 100644 installer/src/test/kotlin/com/teamscale/profiler/installer/utils/UninstallErrorReporterAssert.kt create mode 100644 installer/src/test/kotlin/com/teamscale/profiler/installer/windows/WindowsRegistryTest.kt diff --git a/installer/build.gradle.kts b/installer/build.gradle.kts index daa56e493..8d9467116 100644 --- a/installer/build.gradle.kts +++ b/installer/build.gradle.kts @@ -1,6 +1,7 @@ import org.beryx.jlink.util.JdkUtil plugins { + kotlin("jvm") application com.teamscale.`java-convention` com.teamscale.coverage diff --git a/installer/src/test/java/com/teamscale/profiler/installer/AllPlatformsInstallerTest.java b/installer/src/test/java/com/teamscale/profiler/installer/AllPlatformsInstallerTest.java deleted file mode 100644 index 9156c8a3d..000000000 --- a/installer/src/test/java/com/teamscale/profiler/installer/AllPlatformsInstallerTest.java +++ /dev/null @@ -1,145 +0,0 @@ -package com.teamscale.profiler.installer; - -import com.teamscale.profiler.installer.utils.MockRegistry; -import com.teamscale.profiler.installer.utils.MockTeamscale; -import com.teamscale.profiler.installer.utils.TestUtils; -import com.teamscale.test.commons.SystemTestUtils; -import okhttp3.HttpUrl; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.StandardOpenOption; -import java.util.Properties; - -import static com.teamscale.profiler.installer.utils.UninstallErrorReporterAssert.assertThat; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; - -class AllPlatformsInstallerTest { - - private static final String FILE_TO_INSTALL_CONTENT = "install-me"; - private static final String NESTED_FILE_CONTENT = "nested-file"; - private static final String TEAMSCALE_URL = "http://localhost:" + SystemTestUtils.TEAMSCALE_PORT + "/"; - - - private Path sourceDirectory; - private Path targetDirectory; - private Path etcDirectory; - - private Path installedFile; - private Path installedNestedFile; - private Path installedTeamscaleProperties; - - private static MockTeamscale mockTeamscale; - - @BeforeEach - void setUpSourceDirectory() throws IOException { - sourceDirectory = Files.createTempDirectory("InstallerTest-source"); - targetDirectory = Files.createTempDirectory("InstallerTest-target").resolve("profiler"); - etcDirectory = Files.createTempDirectory("InstallerTest-etc"); - - Path fileToInstall = sourceDirectory.resolve("install-me.txt"); - Files.writeString(fileToInstall, FILE_TO_INSTALL_CONTENT, StandardOpenOption.CREATE); - - Path nestedFileToInstall = sourceDirectory.resolve("lib/teamscale-jacoco-agent.jar"); - Files.createDirectories(nestedFileToInstall.getParent()); - Files.writeString(nestedFileToInstall, NESTED_FILE_CONTENT, - StandardOpenOption.CREATE); - - installedFile = targetDirectory.resolve(sourceDirectory.relativize(fileToInstall)); - installedNestedFile = targetDirectory.resolve(sourceDirectory.relativize(nestedFileToInstall)); - installedTeamscaleProperties = targetDirectory.resolve("teamscale.properties"); - } - - @BeforeAll - static void startFakeTeamscale() { - mockTeamscale = new MockTeamscale(SystemTestUtils.TEAMSCALE_PORT); - } - - @AfterAll - static void stopFakeTeamscale() { - mockTeamscale.shutdown(); - } - - @Test - void successfulInstallation() throws FatalInstallerError, IOException { - install(); - - assertThat(installedFile).exists().content().isEqualTo(FILE_TO_INSTALL_CONTENT); - assertThat(installedNestedFile).exists().content().isEqualTo(NESTED_FILE_CONTENT); - assertThat(installedTeamscaleProperties).exists(); - - Properties properties = new Properties(); - properties.load(Files.newInputStream(installedTeamscaleProperties)); - assertThat(properties.keySet()).containsExactlyInAnyOrder("url", "username", "accesskey"); - assertThat(properties.getProperty("url")).isEqualTo(TEAMSCALE_URL); - assertThat(properties.getProperty("username")).isEqualTo("user"); - assertThat(properties.getProperty("accesskey")).isEqualTo("accesskey"); - } - - @Test - void distributionChangedByUser() throws IOException { - Files.delete(sourceDirectory.resolve("lib/teamscale-jacoco-agent.jar")); - assertThatThrownBy(this::install) - .hasMessageContaining("It looks like you moved the installer"); - } - - @Test - void successfulUninstallation() throws FatalInstallerError { - install(); - Installer.UninstallerErrorReporter errorReporter = uninstall(); - assertThat(errorReporter).hadNoErrors(); - } - - @Test - void nonexistantTeamscaleUrl() { - assertThatThrownBy(() -> install("http://does-not-exist:8080")) - .hasMessageContaining("could not be resolved"); - assertThat(targetDirectory).doesNotExist(); - } - - @Test - void connectionRefused() { - assertThatThrownBy(() -> install("http://localhost:" + (SystemTestUtils.TEAMSCALE_PORT + 1))) - .hasMessageContaining("refused a connection"); - assertThat(targetDirectory).doesNotExist(); - } - - @Test - void httpsInsteadOfHttp() { - assertThatThrownBy(() -> install("https://localhost:" + (int) SystemTestUtils.TEAMSCALE_PORT)) - .hasMessageContaining("configured for HTTPS, not HTTP"); - assertThat(targetDirectory).doesNotExist(); - } - - @Test - void profilerAlreadyInstalled() throws IOException { - Files.createDirectories(targetDirectory); - assertThatThrownBy(this::install).hasMessageContaining("Path already exists"); - } - - @Test - void installDirectoryNotWritable() throws Exception { - TestUtils.makePathReadOnly(targetDirectory.getParent()); - assertThatThrownBy(() -> install(TEAMSCALE_URL)).hasMessageContaining("Cannot create directory"); - } - - private void install() throws FatalInstallerError { - install(TEAMSCALE_URL); - } - - private void install(String teamscaleUrl) throws FatalInstallerError { - new Installer(sourceDirectory, targetDirectory, etcDirectory, false, new MockRegistry()).runInstall( - new TeamscaleCredentials(HttpUrl.get(teamscaleUrl), "user", "accesskey")); - } - - private Installer.UninstallerErrorReporter uninstall() { - return new Installer(sourceDirectory, targetDirectory, etcDirectory, false, new MockRegistry()).runUninstall(); - } - -} diff --git a/installer/src/test/java/com/teamscale/profiler/installer/EnvironmentMapTest.java b/installer/src/test/java/com/teamscale/profiler/installer/EnvironmentMapTest.java deleted file mode 100644 index 0f8ef3a52..000000000 --- a/installer/src/test/java/com/teamscale/profiler/installer/EnvironmentMapTest.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.teamscale.profiler.installer; - -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.Assertions.assertThat; - -class EnvironmentMapTest { - - @Test - void testQuoting() { - assertThat(new JvmEnvironmentMap("V", "a b").getSystemdString()).isEqualTo("\"V=a b\""); - assertThat(new JvmEnvironmentMap("V", "a b").getEtcEnvironmentLinesList()).containsExactlyInAnyOrder( - "V=\"a b\""); - assertThat(new JvmEnvironmentMap("V", "a b").getEnvironmentVariableMap()).containsEntry("V", "\"a b\""); - } - - @Test - void testMultipleEntries() { - assertThat(new JvmEnvironmentMap("V", "a", "E", "b").getSystemdString()).isEqualTo("E=b V=a"); - assertThat(new JvmEnvironmentMap("V", "a", "E", "b").getEtcEnvironmentLinesList()).containsExactlyInAnyOrder( - "E=b", "V=a"); - } - -} \ No newline at end of file diff --git a/installer/src/test/java/com/teamscale/profiler/installer/LinuxInstallerTest.java b/installer/src/test/java/com/teamscale/profiler/installer/LinuxInstallerTest.java deleted file mode 100644 index 7ff9b4538..000000000 --- a/installer/src/test/java/com/teamscale/profiler/installer/LinuxInstallerTest.java +++ /dev/null @@ -1,181 +0,0 @@ -package com.teamscale.profiler.installer; - -import com.teamscale.profiler.installer.utils.MockTeamscale; -import com.teamscale.profiler.installer.utils.TestUtils; -import com.teamscale.profiler.installer.windows.WindowsRegistry; -import okhttp3.HttpUrl; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.condition.EnabledOnOs; -import org.junit.jupiter.api.condition.OS; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.StandardOpenOption; - -import static com.teamscale.profiler.installer.utils.UninstallErrorReporterAssert.assertThat; -import static java.nio.file.attribute.PosixFilePermission.OTHERS_READ; -import static org.assertj.core.api.Assertions.assertThat; - -@EnabledOnOs(OS.LINUX) -class LinuxInstallerTest { - - private static final int TEAMSCALE_PORT = 8059; - private static final String FILE_TO_INSTALL_CONTENT = "install-me"; - private static final String NESTED_FILE_CONTENT = "nested-file"; - private static final String ENVIRONMENT_CONTENT = "#this is /etc/environment\nPATH=/usr/bin"; - private static final String TEAMSCALE_URL = "http://localhost:" + TEAMSCALE_PORT + "/"; - - - private Path sourceDirectory; - private Path targetDirectory; - private Path etcDirectory; - - private Path installedFile; - private Path installedTeamscaleProperties; - private Path installedAgentLibrary; - - private Path environmentFile; - private Path systemdDirectory; - private Path systemdConfig; - - private static MockTeamscale mockTeamscale; - - @BeforeEach - void setUpSourceDirectory() throws IOException { - sourceDirectory = Files.createTempDirectory("InstallerTest-source"); - targetDirectory = Files.createTempDirectory("InstallerTest-target").resolve("profiler"); - etcDirectory = Files.createTempDirectory("InstallerTest-etc"); - - environmentFile = etcDirectory.resolve("environment"); - Files.writeString(environmentFile, ENVIRONMENT_CONTENT); - - systemdDirectory = etcDirectory.resolve("systemd"); - Files.createDirectory(systemdDirectory); - systemdConfig = systemdDirectory.resolve("system.conf.d/teamscale-java-profiler.conf"); - - Path fileToInstall = sourceDirectory.resolve("install-me.txt"); - Files.writeString(fileToInstall, FILE_TO_INSTALL_CONTENT, StandardOpenOption.CREATE); - - Path nestedFileToInstall = sourceDirectory.resolve("lib/teamscale-jacoco-agent.jar"); - Files.createDirectories(nestedFileToInstall.getParent()); - Files.writeString(nestedFileToInstall, NESTED_FILE_CONTENT, StandardOpenOption.CREATE); - - installedFile = targetDirectory.resolve(sourceDirectory.relativize(fileToInstall)); - installedTeamscaleProperties = targetDirectory.resolve("teamscale.properties"); - installedAgentLibrary = targetDirectory.resolve("lib/teamscale-jacoco-agent.jar"); - } - - @BeforeAll - static void startFakeTeamscale() { - mockTeamscale = new MockTeamscale(TEAMSCALE_PORT); - } - - @AfterAll - static void stopFakeTeamscale() { - mockTeamscale.shutdown(); - } - - @Test - void successfulInstallation() throws FatalInstallerError, IOException { - install(); - - assertThat(Files.getPosixFilePermissions(installedTeamscaleProperties)).contains(OTHERS_READ); - assertThat(Files.getPosixFilePermissions(installedFile)).contains(OTHERS_READ); - - assertThat(environmentFile).content().isEqualTo(ENVIRONMENT_CONTENT - + "\nJAVA_TOOL_OPTIONS=-javaagent:" + installedAgentLibrary - + "\n_JAVA_OPTIONS=-javaagent:" + installedAgentLibrary + "\n"); - - assertThat(systemdConfig).content().isEqualTo("[Manager]" - + "\nDefaultEnvironment=JAVA_TOOL_OPTIONS=-javaagent:" + installedAgentLibrary - + " _JAVA_OPTIONS=-javaagent:" + installedAgentLibrary + "\n"); - } - - @Test - void successfulUninstallation() throws FatalInstallerError { - install(); - Installer.UninstallerErrorReporter errorReporter = uninstall(); - assertThat(errorReporter).hadNoErrors(); - - assertThat(targetDirectory).doesNotExist(); - assertThat(environmentFile).exists().content().isEqualTo(ENVIRONMENT_CONTENT); - assertThat(systemdConfig).doesNotExist(); - } - - @Test - void uninstallSuccessfullyEvenIfSystemDConfigWasManuallyRemoved() throws FatalInstallerError, IOException { - install(); - Files.delete(systemdConfig); - Installer.UninstallerErrorReporter errorReporter = uninstall(); - assertThat(errorReporter).hadNoErrors(); - } - - @Test - void uninstallSuccessfullyEvenIfEnvironmentFileDoesntExist() throws FatalInstallerError, IOException { - install(); - Files.delete(environmentFile); - Installer.UninstallerErrorReporter errorReporter = uninstall(); - assertThat(errorReporter).hadNoErrors(); - } - - @Test - void uninstallDeletingAgentDirectoryFails() throws Exception { - install(); - TestUtils.makePathReadOnly(targetDirectory); - TestUtils.makePathReadOnly(installedTeamscaleProperties); - - Installer.UninstallerErrorReporter errorReporter = uninstall(); - assertThat(errorReporter).hadErrors(); - - assertThat(targetDirectory).exists(); - assertThat(installedTeamscaleProperties).exists(); - assertThat(environmentFile).exists().content().isEqualTo(ENVIRONMENT_CONTENT); - assertThat(systemdConfig).doesNotExist(); - } - - @Test - void uninstallChangingEtcEnvironmentFails() throws Exception { - install(); - TestUtils.makePathReadOnly(environmentFile); - - Installer.UninstallerErrorReporter errorReporter = uninstall(); - assertThat(errorReporter).hadErrors(); - - assertThat(environmentFile).exists().content().contains("_JAVA_OPTIONS"); - - // ensure that the agent uninstall step did not run because the preceding environment step failed - assertThat(targetDirectory).exists(); - assertThat(installedTeamscaleProperties).exists(); - } - - @Test - void noEtcEnvironment() throws FatalInstallerError, IOException { - Files.delete(environmentFile); - install(); - - assertThat(environmentFile).doesNotExist(); - } - - @Test - void noSystemd() throws FatalInstallerError, IOException { - Files.delete(systemdDirectory); - install(); - - assertThat(systemdConfig).doesNotExist(); - } - - private void install() throws FatalInstallerError { - new Installer(sourceDirectory, targetDirectory, etcDirectory, false, WindowsRegistry.INSTANCE).runInstall( - new TeamscaleCredentials(HttpUrl.get(LinuxInstallerTest.TEAMSCALE_URL), "user", "accesskey")); - } - - private Installer.UninstallerErrorReporter uninstall() { - return new Installer(sourceDirectory, targetDirectory, - etcDirectory, false, WindowsRegistry.INSTANCE).runUninstall(); - } - -} diff --git a/installer/src/test/java/com/teamscale/profiler/installer/WindowsInstallerTest.java b/installer/src/test/java/com/teamscale/profiler/installer/WindowsInstallerTest.java deleted file mode 100644 index 361b61c5d..000000000 --- a/installer/src/test/java/com/teamscale/profiler/installer/WindowsInstallerTest.java +++ /dev/null @@ -1,96 +0,0 @@ -package com.teamscale.profiler.installer; - -import com.teamscale.profiler.installer.utils.MockRegistry; -import com.teamscale.profiler.installer.utils.MockTeamscale; -import com.teamscale.profiler.installer.utils.UninstallErrorReporterAssert; -import okhttp3.HttpUrl; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.condition.EnabledOnOs; -import org.junit.jupiter.api.condition.OS; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.nio.file.StandardOpenOption; - -import static org.assertj.core.api.Assertions.assertThat; - -@EnabledOnOs(OS.WINDOWS) -class WindowsInstallerTest { - - private static final int TEAMSCALE_PORT = 8059; - private static final String FILE_TO_INSTALL_CONTENT = "install-me"; - private static final String NESTED_FILE_CONTENT = "nested-file"; - private static final String TEAMSCALE_URL = "http://localhost:" + TEAMSCALE_PORT + "/"; - - - private Path sourceDirectory; - private Path targetDirectory; - - private Path installedAgentLibrary; - - private static MockTeamscale mockTeamscale; - - private MockRegistry registry; - - @BeforeEach - void setUpSourceDirectory() throws IOException { - sourceDirectory = Files.createTempDirectory("InstallerTest-source"); - targetDirectory = Files.createTempDirectory("InstallerTest-target").resolve("profiler"); - - Path fileToInstall = sourceDirectory.resolve("install-me.txt"); - Files.writeString(fileToInstall, FILE_TO_INSTALL_CONTENT, StandardOpenOption.CREATE); - - Path nestedFileToInstall = sourceDirectory.resolve("lib/teamscale-jacoco-agent.jar"); - Files.createDirectories(nestedFileToInstall.getParent()); - Files.writeString(nestedFileToInstall, NESTED_FILE_CONTENT, - StandardOpenOption.CREATE); - - installedAgentLibrary = targetDirectory.resolve("lib/teamscale-jacoco-agent.jar"); - - registry = new MockRegistry(); - } - - @BeforeAll - static void startFakeTeamscale() { - mockTeamscale = new MockTeamscale(TEAMSCALE_PORT); - } - - @AfterAll - static void stopFakeTeamscale() { - mockTeamscale.shutdown(); - } - - @Test - void successfulInstallation() throws FatalInstallerError { - install(); - - assertThat(registry.getVariable("_JAVA_OPTIONS")).isEqualTo("-javaagent:" + installedAgentLibrary); - assertThat(registry.getVariable("JAVA_TOOL_OPTIONS")).isEqualTo("-javaagent:" + installedAgentLibrary); - } - - @Test - void successfulUninstallation() throws FatalInstallerError { - install(); - Installer.UninstallerErrorReporter errorReporter = uninstall(); - UninstallErrorReporterAssert.assertThat(errorReporter).hadNoErrors(); - - assertThat(registry.getVariable("_JAVA_OPTIONS")).isNull(); - assertThat(registry.getVariable("JAVA_TOOL_OPTIONS")).isNull(); - } - - private void install() throws FatalInstallerError { - new Installer(sourceDirectory, targetDirectory, Paths.get("/etc"), false, registry).runInstall( - new TeamscaleCredentials(HttpUrl.get(WindowsInstallerTest.TEAMSCALE_URL), "user", "accesskey")); - } - - private Installer.UninstallerErrorReporter uninstall() { - return new Installer(sourceDirectory, targetDirectory, - Paths.get("/etc"), false, registry).runUninstall(); - } - -} diff --git a/installer/src/test/java/com/teamscale/profiler/installer/steps/InstallWindowsSystemEnvironmentStepTest.java b/installer/src/test/java/com/teamscale/profiler/installer/steps/InstallWindowsSystemEnvironmentStepTest.java deleted file mode 100644 index 889f3cb92..000000000 --- a/installer/src/test/java/com/teamscale/profiler/installer/steps/InstallWindowsSystemEnvironmentStepTest.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.teamscale.profiler.installer.steps; - -import com.teamscale.profiler.installer.JvmEnvironmentMap; -import com.teamscale.profiler.installer.FatalInstallerError; -import com.teamscale.profiler.installer.Installer; -import com.teamscale.profiler.installer.utils.MockRegistry; -import com.teamscale.profiler.installer.TeamscaleCredentials; -import okhttp3.HttpUrl; -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Tests the installation step that sets Windows environment variables. This test mocks the registry so we can test this - * step on any OS. - */ -class InstallWindowsSystemEnvironmentStepTest { - - private static final TeamscaleCredentials CREDENTIALS = new TeamscaleCredentials( - HttpUrl.get("http://localhost:" + 8058 + "/"), "user", "accesskey"); - - private static final JvmEnvironmentMap ENVIRONMENT = new JvmEnvironmentMap( - "_JAVA_OPTIONS", "-javaagent:C:\\Program Files\\foo.jar", - "JAVA_TOOL_OPTIONS", "-javaagent:C:\\Programs\\foo.jar"); - - @Test - void successfulInstall() throws FatalInstallerError { - MockRegistry registry = new MockRegistry(); - new InstallWindowsSystemEnvironmentStep(ENVIRONMENT, registry).install(CREDENTIALS); - - assertThat(registry.getVariable("_JAVA_OPTIONS")).isEqualTo("\"-javaagent:C:\\Program Files\\foo.jar\""); - assertThat(registry.getVariable("JAVA_TOOL_OPTIONS")).isEqualTo("-javaagent:C:\\Programs\\foo.jar"); - } - - @Test - void successfulUninstall() throws FatalInstallerError { - MockRegistry registry = new MockRegistry(); - Installer.UninstallerErrorReporter errorReporter = new Installer.UninstallerErrorReporter(); - - new InstallWindowsSystemEnvironmentStep(ENVIRONMENT, registry).install(CREDENTIALS); - new InstallWindowsSystemEnvironmentStep(ENVIRONMENT, registry).uninstall(errorReporter); - - assertThat(errorReporter.wereErrorsReported()).isFalse(); - assertThat(registry.getVariable("_JAVA_OPTIONS")).isNull(); - } - - @Test - void addAndRemoveProfiler() throws FatalInstallerError { - MockRegistry registry = new MockRegistry(); - - InstallWindowsSystemEnvironmentStep.addProfiler("_JAVA_OPTIONS", "-javaagent:foo.jar", registry); - assertThat(registry.getVariable("_JAVA_OPTIONS")).isEqualTo("-javaagent:foo.jar"); - - InstallWindowsSystemEnvironmentStep.removeProfiler("_JAVA_OPTIONS", "-javaagent:foo.jar", registry); - assertThat(registry.getVariable("_JAVA_OPTIONS")).isNullOrEmpty(); - } - - @Test - void addAndRemoveProfilerWithPreviousValue() throws FatalInstallerError { - MockRegistry registry = new MockRegistry(); - - registry.setVariable("_JAVA_OPTIONS", "-javaagent:other.jar"); - InstallWindowsSystemEnvironmentStep.addProfiler("_JAVA_OPTIONS", "-javaagent:foo.jar", registry); - assertThat(registry.getVariable("_JAVA_OPTIONS")).isEqualTo("-javaagent:foo.jar -javaagent:other.jar"); - - InstallWindowsSystemEnvironmentStep.removeProfiler("_JAVA_OPTIONS", "-javaagent:foo.jar", registry); - assertThat(registry.getVariable("_JAVA_OPTIONS")).isEqualTo("-javaagent:other.jar"); - - // removing it again should do nothing - InstallWindowsSystemEnvironmentStep.removeProfiler("_JAVA_OPTIONS", "-javaagent:foo.jar", registry); - assertThat(registry.getVariable("_JAVA_OPTIONS")).isEqualTo("-javaagent:other.jar"); - } - -} \ No newline at end of file diff --git a/installer/src/test/java/com/teamscale/profiler/installer/utils/MockRegistry.java b/installer/src/test/java/com/teamscale/profiler/installer/utils/MockRegistry.java deleted file mode 100644 index 43c6a4f8a..000000000 --- a/installer/src/test/java/com/teamscale/profiler/installer/utils/MockRegistry.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.teamscale.profiler.installer.utils; - -import com.teamscale.profiler.installer.windows.IRegistry; -import com.teamscale.profiler.installer.windows.WindowsRegistry; - -import java.util.HashMap; -import java.util.Map; - -/** - * Mock of {@link IRegistry} to allow tests without actually changing the Windows registry. - */ -public class MockRegistry implements IRegistry { - - private final Map values = new HashMap<>(); - - @Override - public String getHklmValue(String key, String name) { - return values.get(key + "\\" + name); - } - - @Override - public void setHklmValue(String key, String name, String value) { - values.put(key + "\\" + name, value); - } - - @Override - public void deleteHklmValue(String key, String name) { - values.remove(key + "\\" + name); - } - - /** Reads the given environment variable from the registry. */ - public String getVariable(String name) { - return getHklmValue(WindowsRegistry.ENVIRONMENT_REGISTRY_KEY, name); - } - - /** Sets the given environment variable in the registry. */ - public void setVariable(String name, String value) { - setHklmValue(WindowsRegistry.ENVIRONMENT_REGISTRY_KEY, name, value); - } -} diff --git a/installer/src/test/java/com/teamscale/profiler/installer/utils/MockTeamscale.java b/installer/src/test/java/com/teamscale/profiler/installer/utils/MockTeamscale.java deleted file mode 100644 index fc7d7d7a4..000000000 --- a/installer/src/test/java/com/teamscale/profiler/installer/utils/MockTeamscale.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.teamscale.profiler.installer.utils; - -import spark.Request; -import spark.Response; -import spark.Service; - -import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR; -import static javax.servlet.http.HttpServletResponse.SC_OK; - -/** - * Mocks Teamscale. Returns a fixed status code for all requests. - * By default: status 200 - */ -public class MockTeamscale { - - private final Service service; - - private int statusCode = SC_OK; - - public MockTeamscale(int port) { - service = Service.ignite(); - service.port(port); - service.get("/*", (Request request, Response response) -> { - response.status(statusCode); - response.body("fake content"); - return response; - }); - service.exception(Exception.class, (Exception exception, Request request, Response response) -> { - response.status(SC_INTERNAL_SERVER_ERROR); - response.body("Exception: " + exception.getMessage()); - }); - service.awaitInitialization(); - } - - public void setStatusCode(int statusCode) { - this.statusCode = statusCode; - } - - /** - * Shuts down the mock server and waits for it to be stopped. - */ - public void shutdown() { - service.stop(); - service.awaitStop(); - } - -} diff --git a/installer/src/test/java/com/teamscale/profiler/installer/utils/TeamscaleUtilsTest.java b/installer/src/test/java/com/teamscale/profiler/installer/utils/TeamscaleUtilsTest.java deleted file mode 100644 index de5851977..000000000 --- a/installer/src/test/java/com/teamscale/profiler/installer/utils/TeamscaleUtilsTest.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.teamscale.profiler.installer.utils; - -import com.teamscale.profiler.installer.FatalInstallerError; -import com.teamscale.profiler.installer.TeamscaleCredentials; -import okhttp3.HttpUrl; -import org.assertj.core.api.Assertions; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; - -class TeamscaleUtilsTest { - - private static MockTeamscale mockTeamscale; - private static final int TEAMSCALE_PORT = 8758; - - @BeforeAll - static void startMockTeamscale() { - mockTeamscale = new MockTeamscale(TEAMSCALE_PORT); - } - - @AfterAll - static void stopMockTeamscale() { - mockTeamscale.shutdown(); - } - - @Test - void unresolvableUrl() { - Assertions.assertThatThrownBy(() -> - checkTeamscaleConnection("http://totally.invalid:9999") - ).hasMessageContaining("The host http://totally.invalid:9999/ could not be resolved"); - } - - @Test - void unreachableUrl() { - Assertions.assertThatThrownBy(() -> - checkTeamscaleConnection("http://localhost:9999") - ).hasMessageContaining("The host http://localhost:9999/ refused a connection"); - } - - @Test - void incorrectCredentials() { - mockTeamscale.setStatusCode(401); - Assertions.assertThatThrownBy(() -> - checkTeamscaleConnection("http://localhost:" + TEAMSCALE_PORT) - ).hasMessageContaining("You provided incorrect credentials"); - } - - private void checkTeamscaleConnection(String url) throws FatalInstallerError { - TeamscaleUtils.checkTeamscaleConnection(new TeamscaleCredentials(HttpUrl.get(url), "user", "key")); - } - -} \ No newline at end of file diff --git a/installer/src/test/java/com/teamscale/profiler/installer/utils/TestUtils.java b/installer/src/test/java/com/teamscale/profiler/installer/utils/TestUtils.java deleted file mode 100644 index 23377a8d5..000000000 --- a/installer/src/test/java/com/teamscale/profiler/installer/utils/TestUtils.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.teamscale.profiler.installer.utils; - -import org.apache.commons.lang3.SystemUtils; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.attribute.AclEntry; -import java.nio.file.attribute.AclEntryFlag; -import java.nio.file.attribute.AclEntryPermission; -import java.nio.file.attribute.AclEntryType; -import java.nio.file.attribute.AclFileAttributeView; -import java.nio.file.attribute.DosFileAttributeView; -import java.nio.file.attribute.UserPrincipal; -import java.util.ArrayList; -import java.util.EnumSet; -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; - -/** Generic utilities for tests. */ -public class TestUtils { - - private static final EnumSet READ_ONLY_DENIED_PERMISSIONS = EnumSet.of( - AclEntryPermission.WRITE_DATA, AclEntryPermission.DELETE, AclEntryPermission.DELETE_CHILD, - AclEntryPermission.ADD_FILE, AclEntryPermission.ADD_SUBDIRECTORY, AclEntryPermission.APPEND_DATA, - AclEntryPermission.WRITE_ATTRIBUTES); - - /** - * Changes the given path to read-only and asserts that the change was successful. Depending on the operating - * system, this may or may not also mark subpaths as read-only, so do not rely on this. - */ - public static void makePathReadOnly(Path path) throws IOException { - if (SystemUtils.IS_OS_WINDOWS) { - // File#setWritable doesn't work under Windows 11 (always returns false). - // So we manually set the readonly attribute and some ACLs. Unlike under Linux, this only prevent deletion - // of this specific path, not its subpaths. - // Adapted from https://stackoverflow.com/a/25747561/1396068 - DosFileAttributeView dosAttributes = Files.getFileAttributeView(path, DosFileAttributeView.class); - dosAttributes.setReadOnly(true); - - AclFileAttributeView view = Files.getFileAttributeView(path, AclFileAttributeView.class); - UserPrincipal owner = view.getOwner(); - - List newAcl = new ArrayList<>(view.getAcl()); - newAcl.add(0, AclEntry.newBuilder() - .setType(AclEntryType.DENY) - .setPrincipal(owner) - .setPermissions(READ_ONLY_DENIED_PERMISSIONS) - .setFlags(AclEntryFlag.FILE_INHERIT, AclEntryFlag.DIRECTORY_INHERIT) - .build()); - view.setAcl(newAcl); - } else { - assertThat(path.toFile().setWritable(false, false)) - .withFailMessage("Failed to mark " + path + " as writable = " + false).isTrue(); - } - } -} diff --git a/installer/src/test/java/com/teamscale/profiler/installer/utils/UninstallErrorReporterAssert.java b/installer/src/test/java/com/teamscale/profiler/installer/utils/UninstallErrorReporterAssert.java deleted file mode 100644 index 4016d1112..000000000 --- a/installer/src/test/java/com/teamscale/profiler/installer/utils/UninstallErrorReporterAssert.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.teamscale.profiler.installer.utils; - -import com.teamscale.profiler.installer.Installer; -import org.assertj.core.api.AbstractAssert; - -/** Assertions for {@link com.teamscale.profiler.installer.Installer.UninstallerErrorReporter} */ -public class UninstallErrorReporterAssert extends AbstractAssert { - - protected UninstallErrorReporterAssert(Installer.UninstallerErrorReporter uninstallerErrorReporter, - Class selfType) { - super(uninstallerErrorReporter, selfType); - } - - /** Asserts that no errors were reported. */ - public void hadNoErrors() { - if (actual.wereErrorsReported()) { - failWithMessage("Expected no errors to be reported during the uninstallation, but at least one occurred."); - } - } - - /** Asserts at least one error was reported. */ - public void hadErrors() { - if (!actual.wereErrorsReported()) { - failWithMessage("Unexpectedly, no errors were reported during the uninstallation."); - } - } - - /** Creates an assert for the given reporter. */ - public static UninstallErrorReporterAssert assertThat(Installer.UninstallerErrorReporter reporter) { - return new UninstallErrorReporterAssert(reporter, UninstallErrorReporterAssert.class); - } -} diff --git a/installer/src/test/java/com/teamscale/profiler/installer/windows/WindowsRegistryTest.java b/installer/src/test/java/com/teamscale/profiler/installer/windows/WindowsRegistryTest.java deleted file mode 100644 index 675cdfc93..000000000 --- a/installer/src/test/java/com/teamscale/profiler/installer/windows/WindowsRegistryTest.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.teamscale.profiler.installer.windows; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.condition.EnabledOnOs; -import org.junit.jupiter.api.condition.OS; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Tests our registry access class. - */ -@EnabledOnOs(OS.WINDOWS) -class WindowsRegistryTest { - - private static final String VARIABLE = "TEAMSCALE_JAVA_PROFILER_WINDOWS_REGISTRY_TEST"; - - @BeforeEach - void clearRegistry() throws Exception { - Runtime.getRuntime() - .exec(new String[]{"reg", "delete", "HKLM\\" + WindowsRegistry.ENVIRONMENT_REGISTRY_KEY, "/v", VARIABLE}); - } - - @Test - void testAllFunctions() throws Exception { - assertThat(WindowsRegistry.INSTANCE.getHklmValue(WindowsRegistry.ENVIRONMENT_REGISTRY_KEY, VARIABLE)).isNull(); - - WindowsRegistry.INSTANCE.setHklmValue(WindowsRegistry.ENVIRONMENT_REGISTRY_KEY, VARIABLE, "foobar"); - assertThat(WindowsRegistry.INSTANCE.getHklmValue(WindowsRegistry.ENVIRONMENT_REGISTRY_KEY, VARIABLE)).isEqualTo( - "foobar"); - - WindowsRegistry.INSTANCE.setHklmValue(WindowsRegistry.ENVIRONMENT_REGISTRY_KEY, VARIABLE, "goo"); - assertThat(WindowsRegistry.INSTANCE.getHklmValue(WindowsRegistry.ENVIRONMENT_REGISTRY_KEY, VARIABLE)).isEqualTo( - "goo"); - - WindowsRegistry.INSTANCE.deleteHklmValue(WindowsRegistry.ENVIRONMENT_REGISTRY_KEY, VARIABLE); - assertThat(WindowsRegistry.INSTANCE.getHklmValue(WindowsRegistry.ENVIRONMENT_REGISTRY_KEY, VARIABLE)).isNull(); - } - -} \ No newline at end of file diff --git a/installer/src/test/kotlin/com/teamscale/profiler/installer/AllPlatformsInstallerTest.kt b/installer/src/test/kotlin/com/teamscale/profiler/installer/AllPlatformsInstallerTest.kt new file mode 100644 index 000000000..253bfb542 --- /dev/null +++ b/installer/src/test/kotlin/com/teamscale/profiler/installer/AllPlatformsInstallerTest.kt @@ -0,0 +1,152 @@ +package com.teamscale.profiler.installer + +import com.teamscale.profiler.installer.Installer.UninstallerErrorReporter +import com.teamscale.profiler.installer.utils.MockRegistry +import com.teamscale.profiler.installer.utils.MockTeamscale +import com.teamscale.profiler.installer.utils.TestUtils +import com.teamscale.profiler.installer.utils.UninstallErrorReporterAssert +import com.teamscale.test.commons.SystemTestUtils +import okhttp3.HttpUrl.Companion.toHttpUrl +import org.assertj.core.api.Assertions +import org.junit.jupiter.api.AfterAll +import org.junit.jupiter.api.BeforeAll +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import java.io.IOException +import java.nio.file.Files +import java.nio.file.Path +import java.nio.file.StandardOpenOption +import java.util.* + +internal class AllPlatformsInstallerTest { + private lateinit var sourceDirectory: Path + private lateinit var targetDirectory: Path + private lateinit var etcDirectory: Path + + private lateinit var installedFile: Path + private lateinit var installedNestedFile: Path + private lateinit var installedTeamscaleProperties: Path + + @BeforeEach + @Throws(IOException::class) + fun setUpSourceDirectory() { + sourceDirectory = Files.createTempDirectory("InstallerTest-source") + targetDirectory = Files.createTempDirectory("InstallerTest-target").resolve("profiler") + etcDirectory = Files.createTempDirectory("InstallerTest-etc") + + val fileToInstall = sourceDirectory.resolve("install-me.txt") + Files.writeString(fileToInstall, FILE_TO_INSTALL_CONTENT, StandardOpenOption.CREATE) + + val nestedFileToInstall = sourceDirectory.resolve("lib/teamscale-jacoco-agent.jar") + Files.createDirectories(nestedFileToInstall.parent) + Files.writeString( + nestedFileToInstall, NESTED_FILE_CONTENT, + StandardOpenOption.CREATE + ) + + installedFile = targetDirectory.resolve(sourceDirectory.relativize(fileToInstall)) + installedNestedFile = targetDirectory.resolve(sourceDirectory.relativize(nestedFileToInstall)) + installedTeamscaleProperties = targetDirectory.resolve("teamscale.properties") + } + + @Test + @Throws(FatalInstallerError::class, IOException::class) + fun successfulInstallation() { + install() + + Assertions.assertThat(installedFile).exists().content().isEqualTo(FILE_TO_INSTALL_CONTENT) + Assertions.assertThat(installedNestedFile).exists().content().isEqualTo(NESTED_FILE_CONTENT) + Assertions.assertThat(installedTeamscaleProperties).exists() + + Properties().apply { + load(Files.newInputStream(installedTeamscaleProperties)) + Assertions.assertThat(keys).containsExactlyInAnyOrder("url", "username", "accesskey") + Assertions.assertThat(getProperty("url")).isEqualTo(TEAMSCALE_URL) + Assertions.assertThat(getProperty("username")).isEqualTo("user") + Assertions.assertThat(getProperty("accesskey")).isEqualTo("accesskey") + } + } + + @Test + @Throws(IOException::class) + fun distributionChangedByUser() { + Files.delete(sourceDirectory.resolve("lib/teamscale-jacoco-agent.jar")) + Assertions.assertThatThrownBy { install() } + .hasMessageContaining("It looks like you moved the installer") + } + + @Test + @Throws(FatalInstallerError::class) + fun successfulUninstallation() { + install() + val errorReporter = uninstall() + UninstallErrorReporterAssert.assertThat(errorReporter).hadNoErrors() + } + + @Test + fun nonexistantTeamscaleUrl() { + Assertions.assertThatThrownBy { install("http://does-not-exist:8080") } + .hasMessageContaining("could not be resolved") + Assertions.assertThat(targetDirectory).doesNotExist() + } + + @Test + fun connectionRefused() { + Assertions.assertThatThrownBy { install("http://localhost:" + (SystemTestUtils.TEAMSCALE_PORT + 1)) } + .hasMessageContaining("refused a connection") + Assertions.assertThat(targetDirectory).doesNotExist() + } + + @Test + fun httpsInsteadOfHttp() { + Assertions.assertThatThrownBy { install("https://localhost:" + SystemTestUtils.TEAMSCALE_PORT) } + .hasMessageContaining("configured for HTTPS, not HTTP") + Assertions.assertThat(targetDirectory).doesNotExist() + } + + @Test + @Throws(IOException::class) + fun profilerAlreadyInstalled() { + Files.createDirectories(targetDirectory) + Assertions.assertThatThrownBy { install() }.hasMessageContaining("Path already exists") + } + + @Test + @Throws(Exception::class) + fun installDirectoryNotWritable() { + TestUtils.makePathReadOnly(targetDirectory.parent) + Assertions.assertThatThrownBy { install(TEAMSCALE_URL) } + .hasMessageContaining("Cannot create directory") + } + + @Throws(FatalInstallerError::class) + private fun install(teamscaleUrl: String = TEAMSCALE_URL) { + Installer(sourceDirectory, targetDirectory, etcDirectory, false, MockRegistry()).runInstall( + TeamscaleCredentials(teamscaleUrl.toHttpUrl(), "user", "accesskey") + ) + } + + private fun uninstall(): UninstallerErrorReporter { + return Installer(sourceDirectory, targetDirectory, etcDirectory, false, MockRegistry()).runUninstall() + } + + companion object { + private const val FILE_TO_INSTALL_CONTENT = "install-me" + private const val NESTED_FILE_CONTENT = "nested-file" + private val TEAMSCALE_URL = "http://localhost:" + SystemTestUtils.TEAMSCALE_PORT + "/" + + private var mockTeamscale: MockTeamscale? = null + + @JvmStatic + @BeforeAll + fun startFakeTeamscale() { + mockTeamscale = MockTeamscale(SystemTestUtils.TEAMSCALE_PORT) + } + + @JvmStatic + @AfterAll + fun stopFakeTeamscale() { + mockTeamscale?.shutdown() + } + } +} diff --git a/installer/src/test/kotlin/com/teamscale/profiler/installer/EnvironmentMapTest.kt b/installer/src/test/kotlin/com/teamscale/profiler/installer/EnvironmentMapTest.kt new file mode 100644 index 000000000..6604605af --- /dev/null +++ b/installer/src/test/kotlin/com/teamscale/profiler/installer/EnvironmentMapTest.kt @@ -0,0 +1,23 @@ +package com.teamscale.profiler.installer + +import org.assertj.core.api.Assertions +import org.junit.jupiter.api.Test + +internal class EnvironmentMapTest { + @Test + fun testQuoting() { + Assertions.assertThat(JvmEnvironmentMap("V", "a b").systemdString).isEqualTo("\"V=a b\"") + Assertions.assertThat(JvmEnvironmentMap("V", "a b").etcEnvironmentLinesList).containsExactlyInAnyOrder( + "V=\"a b\"" + ) + Assertions.assertThat(JvmEnvironmentMap("V", "a b").environmentVariableMap).containsEntry("V", "\"a b\"") + } + + @Test + fun testMultipleEntries() { + Assertions.assertThat(JvmEnvironmentMap("V", "a", "E", "b").systemdString).isEqualTo("E=b V=a") + Assertions.assertThat(JvmEnvironmentMap("V", "a", "E", "b").etcEnvironmentLinesList).containsExactlyInAnyOrder( + "E=b", "V=a" + ) + } +} \ No newline at end of file diff --git a/installer/src/test/kotlin/com/teamscale/profiler/installer/LinuxInstallerTest.kt b/installer/src/test/kotlin/com/teamscale/profiler/installer/LinuxInstallerTest.kt new file mode 100644 index 000000000..b76c9a7aa --- /dev/null +++ b/installer/src/test/kotlin/com/teamscale/profiler/installer/LinuxInstallerTest.kt @@ -0,0 +1,204 @@ +package com.teamscale.profiler.installer + +import com.teamscale.profiler.installer.Installer.UninstallerErrorReporter +import com.teamscale.profiler.installer.utils.MockTeamscale +import com.teamscale.profiler.installer.utils.TestUtils +import com.teamscale.profiler.installer.utils.UninstallErrorReporterAssert +import com.teamscale.profiler.installer.windows.WindowsRegistry +import okhttp3.HttpUrl.Companion.toHttpUrl +import org.assertj.core.api.Assertions +import org.junit.jupiter.api.AfterAll +import org.junit.jupiter.api.BeforeAll +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.condition.EnabledOnOs +import org.junit.jupiter.api.condition.OS +import java.io.IOException +import java.nio.file.Files +import java.nio.file.Path +import java.nio.file.StandardOpenOption +import java.nio.file.attribute.PosixFilePermission + +@EnabledOnOs(OS.LINUX) +internal class LinuxInstallerTest { + private lateinit var sourceDirectory: Path + private lateinit var targetDirectory: Path + private lateinit var etcDirectory: Path + + private lateinit var installedFile: Path + private lateinit var installedTeamscaleProperties: Path + private lateinit var installedAgentLibrary: Path + + private lateinit var environmentFile: Path + private lateinit var systemdDirectory: Path + private lateinit var systemdConfig: Path + + @BeforeEach + @Throws(IOException::class) + fun setUpSourceDirectory() { + sourceDirectory = Files.createTempDirectory("InstallerTest-source") + targetDirectory = Files.createTempDirectory("InstallerTest-target").resolve("profiler") + etcDirectory = Files.createTempDirectory("InstallerTest-etc") + + environmentFile = etcDirectory.resolve("environment") + Files.writeString(environmentFile, ENVIRONMENT_CONTENT) + + systemdDirectory = etcDirectory.resolve("systemd") + Files.createDirectory(systemdDirectory) + systemdConfig = systemdDirectory.resolve("system.conf.d/teamscale-java-profiler.conf") + + val fileToInstall = sourceDirectory.resolve("install-me.txt") + Files.writeString(fileToInstall, FILE_TO_INSTALL_CONTENT, StandardOpenOption.CREATE) + + val nestedFileToInstall = sourceDirectory.resolve("lib/teamscale-jacoco-agent.jar") + Files.createDirectories(nestedFileToInstall.parent) + Files.writeString(nestedFileToInstall, NESTED_FILE_CONTENT, StandardOpenOption.CREATE) + + installedFile = targetDirectory.resolve(sourceDirectory.relativize(fileToInstall)) + installedTeamscaleProperties = targetDirectory.resolve("teamscale.properties") + installedAgentLibrary = targetDirectory.resolve("lib/teamscale-jacoco-agent.jar") + } + + @Test + @Throws(FatalInstallerError::class, IOException::class) + fun successfulInstallation() { + install() + + Assertions.assertThat(Files.getPosixFilePermissions(installedTeamscaleProperties)) + .contains(PosixFilePermission.OTHERS_READ) + Assertions.assertThat(Files.getPosixFilePermissions(installedFile)).contains(PosixFilePermission.OTHERS_READ) + + Assertions.assertThat(environmentFile).content().isEqualToIgnoringWhitespace( + """ + $ENVIRONMENT_CONTENT + JAVA_TOOL_OPTIONS=-javaagent:$installedAgentLibrary + _JAVA_OPTIONS=-javaagent:$installedAgentLibrary + """ + ) + + Assertions.assertThat(systemdConfig).content().isEqualToIgnoringWhitespace( + """ + [Manager] + DefaultEnvironment=JAVA_TOOL_OPTIONS=-javaagent:$installedAgentLibrary + _JAVA_OPTIONS=-javaagent:$installedAgentLibrary + """ + ) + } + + @Test + @Throws(FatalInstallerError::class) + fun successfulUninstallation() { + install() + val errorReporter = uninstall() + UninstallErrorReporterAssert.assertThat(errorReporter).hadNoErrors() + + Assertions.assertThat(targetDirectory).doesNotExist() + Assertions.assertThat(environmentFile).exists().content().isEqualTo(ENVIRONMENT_CONTENT) + Assertions.assertThat(systemdConfig).doesNotExist() + } + + @Test + @Throws(FatalInstallerError::class, IOException::class) + fun uninstallSuccessfullyEvenIfSystemDConfigWasManuallyRemoved() { + install() + Files.delete(systemdConfig) + val errorReporter = uninstall() + UninstallErrorReporterAssert.assertThat(errorReporter).hadNoErrors() + } + + @Test + @Throws(FatalInstallerError::class, IOException::class) + fun uninstallSuccessfullyEvenIfEnvironmentFileDoesntExist() { + install() + Files.delete(environmentFile) + val errorReporter = uninstall() + UninstallErrorReporterAssert.assertThat(errorReporter).hadNoErrors() + } + + @Test + @Throws(Exception::class) + fun uninstallDeletingAgentDirectoryFails() { + install() + TestUtils.makePathReadOnly(targetDirectory) + TestUtils.makePathReadOnly(installedTeamscaleProperties) + + val errorReporter = uninstall() + UninstallErrorReporterAssert.assertThat(errorReporter).hadErrors() + + Assertions.assertThat(targetDirectory).exists() + Assertions.assertThat(installedTeamscaleProperties).exists() + Assertions.assertThat(environmentFile).exists().content().isEqualTo(ENVIRONMENT_CONTENT) + Assertions.assertThat(systemdConfig).doesNotExist() + } + + @Test + @Throws(Exception::class) + fun uninstallChangingEtcEnvironmentFails() { + install() + TestUtils.makePathReadOnly(environmentFile) + + val errorReporter = uninstall() + UninstallErrorReporterAssert.assertThat(errorReporter).hadErrors() + + Assertions.assertThat(environmentFile).exists().content().contains("_JAVA_OPTIONS") + + // ensure that the agent uninstall step did not run because the preceding environment step failed + Assertions.assertThat(targetDirectory).exists() + Assertions.assertThat(installedTeamscaleProperties).exists() + } + + @Test + @Throws(FatalInstallerError::class, IOException::class) + fun noEtcEnvironment() { + Files.delete(environmentFile) + install() + + Assertions.assertThat(environmentFile).doesNotExist() + } + + @Test + @Throws(FatalInstallerError::class, IOException::class) + fun noSystemd() { + Files.delete(systemdDirectory) + install() + + Assertions.assertThat(systemdConfig).doesNotExist() + } + + @Throws(FatalInstallerError::class) + private fun install() { + Installer(sourceDirectory, targetDirectory, etcDirectory, false, WindowsRegistry.INSTANCE).runInstall( + TeamscaleCredentials(TEAMSCALE_URL.toHttpUrl(), "user", "accesskey") + ) + } + + private fun uninstall(): UninstallerErrorReporter { + return Installer( + sourceDirectory, targetDirectory, + etcDirectory, false, WindowsRegistry.INSTANCE + ).runUninstall() + } + + companion object { + private const val TEAMSCALE_PORT = 8059 + private const val FILE_TO_INSTALL_CONTENT = "install-me" + private const val NESTED_FILE_CONTENT = "nested-file" + private const val ENVIRONMENT_CONTENT = "#this is /etc/environment\nPATH=/usr/bin" + private const val TEAMSCALE_URL = "http://localhost:$TEAMSCALE_PORT/" + + + private var mockTeamscale: MockTeamscale? = null + + @JvmStatic + @BeforeAll + fun startFakeTeamscale() { + mockTeamscale = MockTeamscale(TEAMSCALE_PORT) + } + + @JvmStatic + @AfterAll + fun stopFakeTeamscale() { + mockTeamscale?.shutdown() + } + } +} diff --git a/installer/src/test/kotlin/com/teamscale/profiler/installer/WindowsInstallerTest.kt b/installer/src/test/kotlin/com/teamscale/profiler/installer/WindowsInstallerTest.kt new file mode 100644 index 000000000..6b6d1eba5 --- /dev/null +++ b/installer/src/test/kotlin/com/teamscale/profiler/installer/WindowsInstallerTest.kt @@ -0,0 +1,107 @@ +package com.teamscale.profiler.installer + +import com.teamscale.profiler.installer.Installer.UninstallerErrorReporter +import com.teamscale.profiler.installer.utils.MockRegistry +import com.teamscale.profiler.installer.utils.MockTeamscale +import com.teamscale.profiler.installer.utils.UninstallErrorReporterAssert +import okhttp3.HttpUrl.Companion.toHttpUrl +import org.assertj.core.api.Assertions +import org.junit.jupiter.api.AfterAll +import org.junit.jupiter.api.BeforeAll +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.condition.EnabledOnOs +import org.junit.jupiter.api.condition.OS +import java.io.IOException +import java.nio.file.Files +import java.nio.file.Path +import java.nio.file.Paths +import java.nio.file.StandardOpenOption + +@EnabledOnOs(OS.WINDOWS) +internal class WindowsInstallerTest { + private lateinit var sourceDirectory: Path + private lateinit var targetDirectory: Path + + private lateinit var installedAgentLibrary: Path + + private lateinit var registry: MockRegistry + + @BeforeEach + @Throws(IOException::class) + fun setUpSourceDirectory() { + sourceDirectory = Files.createTempDirectory("InstallerTest-source") + targetDirectory = Files.createTempDirectory("InstallerTest-target").resolve("profiler") + + val fileToInstall = sourceDirectory.resolve("install-me.txt") + Files.writeString(fileToInstall, FILE_TO_INSTALL_CONTENT, StandardOpenOption.CREATE) + + val nestedFileToInstall = sourceDirectory.resolve("lib/teamscale-jacoco-agent.jar") + Files.createDirectories(nestedFileToInstall.parent) + Files.writeString( + nestedFileToInstall, NESTED_FILE_CONTENT, + StandardOpenOption.CREATE + ) + + installedAgentLibrary = targetDirectory.resolve("lib/teamscale-jacoco-agent.jar") + + registry = MockRegistry() + } + + @Test + @Throws(FatalInstallerError::class) + fun successfulInstallation() { + install() + + Assertions.assertThat(registry.getVariable("_JAVA_OPTIONS")).isEqualTo("-javaagent:$installedAgentLibrary") + Assertions.assertThat(registry.getVariable("JAVA_TOOL_OPTIONS")) + .isEqualTo("-javaagent:$installedAgentLibrary") + } + + @Test + @Throws(FatalInstallerError::class) + fun successfulUninstallation() { + install() + val errorReporter = uninstall() + UninstallErrorReporterAssert.assertThat(errorReporter).hadNoErrors() + + Assertions.assertThat(registry.getVariable("_JAVA_OPTIONS")).isNull() + Assertions.assertThat(registry.getVariable("JAVA_TOOL_OPTIONS")).isNull() + } + + @Throws(FatalInstallerError::class) + private fun install() { + Installer(sourceDirectory, targetDirectory, Paths.get("/etc"), false, registry).runInstall( + TeamscaleCredentials(TEAMSCALE_URL.toHttpUrl(), "user", "accesskey") + ) + } + + private fun uninstall(): UninstallerErrorReporter { + return Installer( + sourceDirectory, targetDirectory, + Paths.get("/etc"), false, registry + ).runUninstall() + } + + companion object { + private const val TEAMSCALE_PORT = 8059 + private const val FILE_TO_INSTALL_CONTENT = "install-me" + private const val NESTED_FILE_CONTENT = "nested-file" + private const val TEAMSCALE_URL = "http://localhost:$TEAMSCALE_PORT/" + + + private var mockTeamscale: MockTeamscale? = null + + @JvmStatic + @BeforeAll + fun startFakeTeamscale() { + mockTeamscale = MockTeamscale(TEAMSCALE_PORT) + } + + @JvmStatic + @AfterAll + fun stopFakeTeamscale() { + mockTeamscale?.shutdown() + } + } +} diff --git a/installer/src/test/kotlin/com/teamscale/profiler/installer/steps/InstallWindowsSystemEnvironmentStepTest.kt b/installer/src/test/kotlin/com/teamscale/profiler/installer/steps/InstallWindowsSystemEnvironmentStepTest.kt new file mode 100644 index 000000000..3e72436a0 --- /dev/null +++ b/installer/src/test/kotlin/com/teamscale/profiler/installer/steps/InstallWindowsSystemEnvironmentStepTest.kt @@ -0,0 +1,81 @@ +package com.teamscale.profiler.installer.steps + +import com.teamscale.profiler.installer.FatalInstallerError +import com.teamscale.profiler.installer.Installer.UninstallerErrorReporter +import com.teamscale.profiler.installer.JvmEnvironmentMap +import com.teamscale.profiler.installer.TeamscaleCredentials +import com.teamscale.profiler.installer.utils.MockRegistry +import okhttp3.HttpUrl.Companion.toHttpUrl +import org.assertj.core.api.Assertions +import org.junit.jupiter.api.Test + +/** + * Tests the installation step that sets Windows environment variables. This test mocks the registry so we can test this + * step on any OS. + */ +internal class InstallWindowsSystemEnvironmentStepTest { + @Test + @Throws(FatalInstallerError::class) + fun successfulInstall() { + val registry = MockRegistry() + InstallWindowsSystemEnvironmentStep(ENVIRONMENT, registry).install(CREDENTIALS) + + Assertions.assertThat(registry.getVariable("_JAVA_OPTIONS")) + .isEqualTo("\"-javaagent:C:\\Program Files\\foo.jar\"") + Assertions.assertThat(registry.getVariable("JAVA_TOOL_OPTIONS")).isEqualTo("-javaagent:C:\\Programs\\foo.jar") + } + + @Test + @Throws(FatalInstallerError::class) + fun successfulUninstall() { + val registry = MockRegistry() + val errorReporter = UninstallerErrorReporter() + + InstallWindowsSystemEnvironmentStep(ENVIRONMENT, registry).install(CREDENTIALS) + InstallWindowsSystemEnvironmentStep(ENVIRONMENT, registry).uninstall(errorReporter) + + Assertions.assertThat(errorReporter.wereErrorsReported()).isFalse() + Assertions.assertThat(registry.getVariable("_JAVA_OPTIONS")).isNull() + } + + @Test + @Throws(FatalInstallerError::class) + fun addAndRemoveProfiler() { + val registry = MockRegistry() + + InstallWindowsSystemEnvironmentStep.addProfiler("_JAVA_OPTIONS", "-javaagent:foo.jar", registry) + Assertions.assertThat(registry.getVariable("_JAVA_OPTIONS")).isEqualTo("-javaagent:foo.jar") + + InstallWindowsSystemEnvironmentStep.removeProfiler("_JAVA_OPTIONS", "-javaagent:foo.jar", registry) + Assertions.assertThat(registry.getVariable("_JAVA_OPTIONS")).isNullOrEmpty() + } + + @Test + @Throws(FatalInstallerError::class) + fun addAndRemoveProfilerWithPreviousValue() { + val registry = MockRegistry() + + registry.setVariable("_JAVA_OPTIONS", "-javaagent:other.jar") + InstallWindowsSystemEnvironmentStep.addProfiler("_JAVA_OPTIONS", "-javaagent:foo.jar", registry) + Assertions.assertThat(registry.getVariable("_JAVA_OPTIONS")) + .isEqualTo("-javaagent:foo.jar -javaagent:other.jar") + + InstallWindowsSystemEnvironmentStep.removeProfiler("_JAVA_OPTIONS", "-javaagent:foo.jar", registry) + Assertions.assertThat(registry.getVariable("_JAVA_OPTIONS")).isEqualTo("-javaagent:other.jar") + + // removing it again should do nothing + InstallWindowsSystemEnvironmentStep.removeProfiler("_JAVA_OPTIONS", "-javaagent:foo.jar", registry) + Assertions.assertThat(registry.getVariable("_JAVA_OPTIONS")).isEqualTo("-javaagent:other.jar") + } + + companion object { + private val CREDENTIALS = TeamscaleCredentials( + "http://localhost:8058/".toHttpUrl(), "user", "accesskey" + ) + + private val ENVIRONMENT = JvmEnvironmentMap( + "_JAVA_OPTIONS", "-javaagent:C:\\Program Files\\foo.jar", + "JAVA_TOOL_OPTIONS", "-javaagent:C:\\Programs\\foo.jar" + ) + } +} \ No newline at end of file diff --git a/installer/src/test/kotlin/com/teamscale/profiler/installer/utils/MockRegistry.kt b/installer/src/test/kotlin/com/teamscale/profiler/installer/utils/MockRegistry.kt new file mode 100644 index 000000000..e915244c4 --- /dev/null +++ b/installer/src/test/kotlin/com/teamscale/profiler/installer/utils/MockRegistry.kt @@ -0,0 +1,30 @@ +package com.teamscale.profiler.installer.utils + +import com.teamscale.profiler.installer.windows.IRegistry +import com.teamscale.profiler.installer.windows.WindowsRegistry + +/** + * Mock of [IRegistry] to allow tests without actually changing the Windows registry. + */ +class MockRegistry : IRegistry { + private val values = mutableMapOf() + + override fun getHklmValue(key: String, name: String) = values["$key\\$name"] + + override fun setHklmValue(key: String, name: String, value: String) { + values["$key\\$name"] = value + } + + override fun deleteHklmValue(key: String, name: String) { + values.remove("$key\\$name") + } + + /** Reads the given environment variable from the registry. */ + fun getVariable(name: String) = + getHklmValue(WindowsRegistry.ENVIRONMENT_REGISTRY_KEY, name) + + /** Sets the given environment variable in the registry. */ + fun setVariable(name: String, value: String) { + setHklmValue(WindowsRegistry.ENVIRONMENT_REGISTRY_KEY, name, value) + } +} diff --git a/installer/src/test/kotlin/com/teamscale/profiler/installer/utils/MockTeamscale.kt b/installer/src/test/kotlin/com/teamscale/profiler/installer/utils/MockTeamscale.kt new file mode 100644 index 000000000..ea805f567 --- /dev/null +++ b/installer/src/test/kotlin/com/teamscale/profiler/installer/utils/MockTeamscale.kt @@ -0,0 +1,42 @@ +package com.teamscale.profiler.installer.utils + +import spark.Service +import javax.servlet.http.HttpServletResponse + +/** + * Mocks Teamscale. Returns a fixed status code for all requests. + * By default: status 200 + */ +class MockTeamscale(port: Int) { + private val service = Service.ignite() + + private var statusCode = HttpServletResponse.SC_OK + + init { + service.port(port) + service["/*", { _, response -> + response.status(statusCode) + response.body("fake content") + response + }] + service.exception( + Exception::class.java + ) { exception, _, response -> + response.status(HttpServletResponse.SC_INTERNAL_SERVER_ERROR) + response.body("Exception: " + exception.message) + } + service.awaitInitialization() + } + + fun setStatusCode(statusCode: Int) { + this.statusCode = statusCode + } + + /** + * Shuts down the mock server and waits for it to be stopped. + */ + fun shutdown() { + service.stop() + service.awaitStop() + } +} diff --git a/installer/src/test/kotlin/com/teamscale/profiler/installer/utils/TeamscaleUtilsTest.kt b/installer/src/test/kotlin/com/teamscale/profiler/installer/utils/TeamscaleUtilsTest.kt new file mode 100644 index 000000000..d3360d740 --- /dev/null +++ b/installer/src/test/kotlin/com/teamscale/profiler/installer/utils/TeamscaleUtilsTest.kt @@ -0,0 +1,52 @@ +package com.teamscale.profiler.installer.utils + +import com.teamscale.profiler.installer.FatalInstallerError +import com.teamscale.profiler.installer.TeamscaleCredentials +import okhttp3.HttpUrl.Companion.toHttpUrl +import org.assertj.core.api.Assertions +import org.junit.jupiter.api.AfterAll +import org.junit.jupiter.api.BeforeAll +import org.junit.jupiter.api.Test + +internal class TeamscaleUtilsTest { + @Test + fun unresolvableUrl() { + Assertions.assertThatThrownBy { checkTeamscaleConnection("http://totally.invalid:9999") } + .hasMessageContaining("The host http://totally.invalid:9999/ could not be resolved") + } + + @Test + fun unreachableUrl() { + Assertions.assertThatThrownBy { checkTeamscaleConnection("http://localhost:9999") } + .hasMessageContaining("The host http://localhost:9999/ refused a connection") + } + + @Test + fun incorrectCredentials() { + mockTeamscale?.setStatusCode(401) + Assertions.assertThatThrownBy { checkTeamscaleConnection("http://localhost:$TEAMSCALE_PORT") } + .hasMessageContaining("You provided incorrect credentials") + } + + @Throws(FatalInstallerError::class) + private fun checkTeamscaleConnection(url: String) { + TeamscaleUtils.checkTeamscaleConnection(TeamscaleCredentials(url.toHttpUrl(), "user", "key")) + } + + companion object { + private var mockTeamscale: MockTeamscale? = null + private const val TEAMSCALE_PORT = 8758 + + @JvmStatic + @BeforeAll + fun startMockTeamscale() { + mockTeamscale = MockTeamscale(TEAMSCALE_PORT) + } + + @JvmStatic + @AfterAll + fun stopMockTeamscale() { + mockTeamscale?.shutdown() + } + } +} \ No newline at end of file diff --git a/installer/src/test/kotlin/com/teamscale/profiler/installer/utils/TestUtils.kt b/installer/src/test/kotlin/com/teamscale/profiler/installer/utils/TestUtils.kt new file mode 100644 index 000000000..4d304b1db --- /dev/null +++ b/installer/src/test/kotlin/com/teamscale/profiler/installer/utils/TestUtils.kt @@ -0,0 +1,59 @@ +package com.teamscale.profiler.installer.utils + +import org.apache.commons.lang3.SystemUtils +import org.assertj.core.api.Assertions +import java.io.IOException +import java.nio.file.Files +import java.nio.file.Path +import java.nio.file.attribute.* +import java.util.* + +/** Generic utilities for tests. */ +object TestUtils { + private val READ_ONLY_DENIED_PERMISSIONS = EnumSet.of( + AclEntryPermission.WRITE_DATA, + AclEntryPermission.DELETE, + AclEntryPermission.DELETE_CHILD, + AclEntryPermission.ADD_FILE, + AclEntryPermission.ADD_SUBDIRECTORY, + AclEntryPermission.APPEND_DATA, + AclEntryPermission.WRITE_ATTRIBUTES + ) + + /** + * Changes the given path to read-only and asserts that the change was successful. Depending on the operating + * system, this may or may not also mark subpaths as read-only, so do not rely on this. + */ + @Throws(IOException::class) + fun makePathReadOnly(path: Path) { + if (SystemUtils.IS_OS_WINDOWS) { + // File#setWritable doesn't work under Windows 11 (always returns false). + // So we manually set the readonly attribute and some ACLs. Unlike under Linux, this only prevent deletion + // of this specific path, not its subpaths. + // Adapted from https://stackoverflow.com/a/25747561/1396068 + val dosAttributes = Files.getFileAttributeView( + path, + DosFileAttributeView::class.java + ) + dosAttributes.setReadOnly(true) + + val view = Files.getFileAttributeView( + path, + AclFileAttributeView::class.java + ) + val owner = view.owner + view.acl = view.acl.toTypedArray().toMutableList().apply { + val element = AclEntry.newBuilder() + .setType(AclEntryType.DENY) + .setPrincipal(owner) + .setPermissions(READ_ONLY_DENIED_PERMISSIONS) + .setFlags(AclEntryFlag.FILE_INHERIT, AclEntryFlag.DIRECTORY_INHERIT) + .build() + add(0, element) + } + } else { + Assertions.assertThat(path.toFile().setWritable(false, false)) + .withFailMessage("Failed to mark $path as writable = false").isTrue() + } + } +} diff --git a/installer/src/test/kotlin/com/teamscale/profiler/installer/utils/UninstallErrorReporterAssert.kt b/installer/src/test/kotlin/com/teamscale/profiler/installer/utils/UninstallErrorReporterAssert.kt new file mode 100644 index 000000000..3f4c0a348 --- /dev/null +++ b/installer/src/test/kotlin/com/teamscale/profiler/installer/utils/UninstallErrorReporterAssert.kt @@ -0,0 +1,29 @@ +package com.teamscale.profiler.installer.utils + +import com.teamscale.profiler.installer.Installer.UninstallerErrorReporter +import org.assertj.core.api.AbstractAssert + +/** Assertions for [com.teamscale.profiler.installer.Installer.UninstallerErrorReporter] */ +class UninstallErrorReporterAssert( + uninstallerErrorReporter: UninstallerErrorReporter, + selfType: Class<*> +) : AbstractAssert(uninstallerErrorReporter, selfType) { + + /** Asserts that no errors were reported. */ + fun hadNoErrors() { + if (!actual.wereErrorsReported()) return + failWithMessage("Expected no errors to be reported during the uninstallation, but at least one occurred.") + } + + /** Asserts at least one error was reported. */ + fun hadErrors() { + if (actual.wereErrorsReported()) return + failWithMessage("Unexpectedly, no errors were reported during the uninstallation.") + } + + companion object { + /** Creates an assertion for the given reporter. */ + fun assertThat(reporter: UninstallerErrorReporter) = + UninstallErrorReporterAssert(reporter, UninstallErrorReporterAssert::class.java) + } +} diff --git a/installer/src/test/kotlin/com/teamscale/profiler/installer/windows/WindowsRegistryTest.kt b/installer/src/test/kotlin/com/teamscale/profiler/installer/windows/WindowsRegistryTest.kt new file mode 100644 index 000000000..15d05ebf1 --- /dev/null +++ b/installer/src/test/kotlin/com/teamscale/profiler/installer/windows/WindowsRegistryTest.kt @@ -0,0 +1,43 @@ +package com.teamscale.profiler.installer.windows + +import org.assertj.core.api.Assertions +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.condition.EnabledOnOs +import org.junit.jupiter.api.condition.OS + +/** + * Tests our registry access class. + */ +@EnabledOnOs(OS.WINDOWS) +internal class WindowsRegistryTest { + @BeforeEach + @Throws(Exception::class) + fun clearRegistry() { + Runtime.getRuntime() + .exec(arrayOf("reg", "delete", "HKLM\\${WindowsRegistry.ENVIRONMENT_REGISTRY_KEY}", "/v", VARIABLE)) + } + + @Test + @Throws(Exception::class) + fun testAllFunctions() { + Assertions.assertThat(WindowsRegistry.INSTANCE.getHklmValue(WindowsRegistry.ENVIRONMENT_REGISTRY_KEY, VARIABLE)) + .isNull() + + WindowsRegistry.INSTANCE.setHklmValue(WindowsRegistry.ENVIRONMENT_REGISTRY_KEY, VARIABLE, "foobar") + Assertions.assertThat(WindowsRegistry.INSTANCE.getHklmValue(WindowsRegistry.ENVIRONMENT_REGISTRY_KEY, VARIABLE)) + .isEqualTo("foobar") + + WindowsRegistry.INSTANCE.setHklmValue(WindowsRegistry.ENVIRONMENT_REGISTRY_KEY, VARIABLE, "goo") + Assertions.assertThat(WindowsRegistry.INSTANCE.getHklmValue(WindowsRegistry.ENVIRONMENT_REGISTRY_KEY, VARIABLE)) + .isEqualTo("goo") + + WindowsRegistry.INSTANCE.deleteHklmValue(WindowsRegistry.ENVIRONMENT_REGISTRY_KEY, VARIABLE) + Assertions.assertThat(WindowsRegistry.INSTANCE.getHklmValue(WindowsRegistry.ENVIRONMENT_REGISTRY_KEY, VARIABLE)) + .isNull() + } + + companion object { + private const val VARIABLE = "TEAMSCALE_JAVA_PROFILER_WINDOWS_REGISTRY_TEST" + } +} \ No newline at end of file