diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d3f036b9fb2..93bc76e2937 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -55,6 +55,7 @@ jobs: name: test-results if-no-files-found: error path: '**/target/*-reports/*.xml' + build-launcher-win64: runs-on: windows-2019 steps: @@ -71,10 +72,21 @@ jobs: uses: stCarolas/setup-maven@v5 with: maven-version: 3.9.6 - - name: Build + - name: Build native launcher and executable working-directory: features/org.eclipse.equinox.executable.feature/library/win32 - run: .\build.bat test + run: | + .\build.bat + + mkdir $env:GITHUB_WORKSPACE\equinox.binaries\org.eclipse.equinox.executable\bin\win32\win32\x86_64\ + copy eclipse*.exe $env:GITHUB_WORKSPACE\equinox.binaries\org.eclipse.equinox.executable\bin\win32\win32\x86_64\ + mkdir $env:GITHUB_WORKSPACE\equinox.binaries\org.eclipse.equinox.launcher.win32.win32.x86_64\ + del $env:GITHUB_WORKSPACE\equinox.binaries\org.eclipse.equinox.launcher.win32.win32.x86_64\eclipse_*.dll + copy eclipse_*.dll $env:GITHUB_WORKSPACE\equinox.binaries\org.eclipse.equinox.launcher.win32.win32.x86_64\ shell: pwsh + - name: Test native launcher and executable + env: + rt.equinox.binaries.loc: ${{ github.workspace }}/equinox.binaries + run: mvn -B -pl org.eclipse.equinox:org.eclipse.equinox.launcher.tests -am verify - name: Upload artifacts uses: actions/upload-artifact@v4 if: success() @@ -90,6 +102,7 @@ jobs: name: test-results-win64 if-no-files-found: error path: '**/target/*-reports/*.xml' + build-launcher-linux64: runs-on: ubuntu-latest steps: @@ -108,10 +121,21 @@ jobs: maven-version: 3.9.6 - name: Install GTK headers run: sudo apt-get install -y libgtk-3-dev - - name: Build + - name: Build native launcher and executable working-directory: features/org.eclipse.equinox.executable.feature/library/gtk - run: ./build.sh test + run: | + ./build.sh + + mkdir $GITHUB_WORKSPACE\equinox.binaries\org.eclipse.equinox.executable\bin\win32\win32\x86_64\ + cp eclipse*.exe $GITHUB_WORKSPACE\equinox.binaries\org.eclipse.equinox.executable\bin\win32\win32\x86_64\ + mkdir $GITHUB_WORKSPACE\equinox.binaries\org.eclipse.equinox.launcher.win32.win32.x86_64\ + rm $GITHUB_WORKSPACE\equinox.binaries\org.eclipse.equinox.launcher.win32.win32.x86_64\eclipse_*.dll + cp eclipse_*.dll $GITHUB_WORKSPACE\equinox.binaries\org.eclipse.equinox.launcher.win32.win32.x86_64\ shell: bash + - name: Test native launcher and executable + env: + rt.equinox.binaries.loc: ${{ github.workspace }}/equinox.binaries + run: mvn -B -pl org.eclipse.equinox:org.eclipse.equinox.launcher.tests -am verify - name: Upload artifacts uses: actions/upload-artifact@v4 if: success() @@ -127,6 +151,7 @@ jobs: name: test-results-linux64 if-no-files-found: error path: '**/target/*-reports/*.xml' + build-launcher-mac64: runs-on: macos-latest steps: @@ -143,10 +168,21 @@ jobs: uses: stCarolas/setup-maven@v5 with: maven-version: 3.9.6 - - name: Build + - name: Build native launcher and executable working-directory: features/org.eclipse.equinox.executable.feature/library/cocoa - run: ./build.sh test + run: | + ./build.sh + + mkdir $GITHUB_WORKSPACE\equinox.binaries\org.eclipse.equinox.executable\bin\win32\win32\x86_64\ + cp eclipse*.exe $GITHUB_WORKSPACE\equinox.binaries\org.eclipse.equinox.executable\bin\win32\win32\x86_64\ + mkdir $GITHUB_WORKSPACE\equinox.binaries\org.eclipse.equinox.launcher.win32.win32.x86_64\ + rm $GITHUB_WORKSPACE\equinox.binaries\org.eclipse.equinox.launcher.win32.win32.x86_64\eclipse_*.dll + cp eclipse_*.dll $GITHUB_WORKSPACE\equinox.binaries\org.eclipse.equinox.launcher.win32.win32.x86_64\ shell: bash + - name: Test native launcher and executable + env: + rt.equinox.binaries.loc: ${{ github.workspace }}/equinox.binaries + run: mvn -B -pl org.eclipse.equinox:org.eclipse.equinox.launcher.tests -am verify - name: Upload artifacts uses: actions/upload-artifact@v4 if: success() @@ -162,6 +198,7 @@ jobs: name: test-results-mac64 if-no-files-found: error path: '**/target/*-reports/*.xml' + tck: runs-on: ubuntu-latest steps: diff --git a/bundles/org.eclipse.equinox.launcher.tests/.classpath b/bundles/org.eclipse.equinox.launcher.tests/.classpath new file mode 100644 index 00000000000..427e49b0d47 --- /dev/null +++ b/bundles/org.eclipse.equinox.launcher.tests/.classpath @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/features/org.eclipse.equinox.executable.feature/library/org.eclipse.launcher.tests/.project b/bundles/org.eclipse.equinox.launcher.tests/.project similarity index 61% rename from features/org.eclipse.equinox.executable.feature/library/org.eclipse.launcher.tests/.project rename to bundles/org.eclipse.equinox.launcher.tests/.project index f135598dbeb..fd82b2a3535 100644 --- a/features/org.eclipse.equinox.executable.feature/library/org.eclipse.launcher.tests/.project +++ b/bundles/org.eclipse.equinox.launcher.tests/.project @@ -1,6 +1,6 @@ - org.eclipse.launcher.tests + org.eclipse.equinox.launcher.tests @@ -11,13 +11,18 @@ - org.eclipse.m2e.core.maven2Builder + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder - org.eclipse.m2e.core.maven2Nature + org.eclipse.pde.PluginNature org.eclipse.jdt.core.javanature diff --git a/bundles/org.eclipse.equinox.launcher.tests/.settings/org.eclipse.core.resources.prefs b/bundles/org.eclipse.equinox.launcher.tests/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 00000000000..99f26c0203a --- /dev/null +++ b/bundles/org.eclipse.equinox.launcher.tests/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +encoding/=UTF-8 diff --git a/features/org.eclipse.equinox.executable.feature/library/org.eclipse.launcher.tests/.settings/org.eclipse.jdt.core.prefs b/bundles/org.eclipse.equinox.launcher.tests/.settings/org.eclipse.jdt.core.prefs similarity index 56% rename from features/org.eclipse.equinox.executable.feature/library/org.eclipse.launcher.tests/.settings/org.eclipse.jdt.core.prefs rename to bundles/org.eclipse.equinox.launcher.tests/.settings/org.eclipse.jdt.core.prefs index 43c8d716b15..62ef3488cc0 100644 --- a/features/org.eclipse.equinox.executable.feature/library/org.eclipse.launcher.tests/.settings/org.eclipse.jdt.core.prefs +++ b/bundles/org.eclipse.equinox.launcher.tests/.settings/org.eclipse.jdt.core.prefs @@ -1,15 +1,9 @@ eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled org.eclipse.jdt.core.compiler.codegen.targetPlatform=17 -org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve org.eclipse.jdt.core.compiler.compliance=17 -org.eclipse.jdt.core.compiler.debug.lineNumber=generate -org.eclipse.jdt.core.compiler.debug.localVariable=generate -org.eclipse.jdt.core.compiler.debug.sourceFile=generate org.eclipse.jdt.core.compiler.problem.assertIdentifier=error org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning org.eclipse.jdt.core.compiler.release=enabled org.eclipse.jdt.core.compiler.source=17 diff --git a/bundles/org.eclipse.equinox.launcher.tests/META-INF/MANIFEST.MF b/bundles/org.eclipse.equinox.launcher.tests/META-INF/MANIFEST.MF new file mode 100644 index 00000000000..bd7013a84eb --- /dev/null +++ b/bundles/org.eclipse.equinox.launcher.tests/META-INF/MANIFEST.MF @@ -0,0 +1,10 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Tests +Bundle-SymbolicName: org.eclipse.equinox.launcher.tests +Bundle-Version: 1.0.0.qualifier +Fragment-Host: org.eclipse.equinox.launcher +Automatic-Module-Name: org.eclipse.launcher.tests +Bundle-RequiredExecutionEnvironment: JavaSE-17 +Import-Package: org.junit.jupiter.api;version="[5.10.0,6.0.0)", + org.junit.jupiter.api.io;version="[5.10.0,6.0.0)" diff --git a/bundles/org.eclipse.equinox.launcher.tests/build.properties b/bundles/org.eclipse.equinox.launcher.tests/build.properties new file mode 100644 index 00000000000..34d2e4d2dad --- /dev/null +++ b/bundles/org.eclipse.equinox.launcher.tests/build.properties @@ -0,0 +1,4 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + . diff --git a/features/org.eclipse.equinox.executable.feature/library/org.eclipse.launcher.tests/src/org/eclipse/equinox/launcher/TestLauncherApp.java b/bundles/org.eclipse.equinox.launcher.tests/src/org/eclipse/equinox/launcher/TestLauncherApp.java similarity index 78% rename from features/org.eclipse.equinox.executable.feature/library/org.eclipse.launcher.tests/src/org/eclipse/equinox/launcher/TestLauncherApp.java rename to bundles/org.eclipse.equinox.launcher.tests/src/org/eclipse/equinox/launcher/TestLauncherApp.java index 4619d4d73c2..2ec626a49af 100644 --- a/features/org.eclipse.equinox.executable.feature/library/org.eclipse.launcher.tests/src/org/eclipse/equinox/launcher/TestLauncherApp.java +++ b/bundles/org.eclipse.equinox.launcher.tests/src/org/eclipse/equinox/launcher/TestLauncherApp.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2023 Eclipse Foundation, Inc. and others. + * Copyright (c) 2023, 2024 Eclipse Foundation, Inc. and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -39,6 +39,13 @@ */ public class TestLauncherApp { + public static final String ARGS_PARAMETER = "-args"; //$NON-NLS-1$ + public static final String EXITDATA_PARAMETER = "-exitdata"; //$NON-NLS-1$ + public static final String EXITCODE_PARAMETER = "-exitcode"; //$NON-NLS-1$ + public static final String MULTILINE_ARG_VALUE_TERMINATOR = "---"; //$NON-NLS-1$ + + public static final String PORT_ENV_KEY = "eclipse_test_port"; //$NON-NLS-1$ + private static JNIBridge bridge; private static String sharedId; private static String[] args; @@ -84,25 +91,25 @@ private static void parseArgs(String[] args) { } private static void communicateToServer() throws Exception { - String port = System.getenv(TestLauncherConstants.PORT_ENV_KEY); + String port = System.getenv(PORT_ENV_KEY); try (Socket socket = new Socket()) { socket.connect(new InetSocketAddress("localhost", Integer.parseInt(port)), 10000); BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); DataOutputStream out = new DataOutputStream(socket.getOutputStream()); String line; while ((line = in.readLine()) != null) { - if (TestLauncherConstants.ARGS_PARAMETER.equals(line)) { - out.writeBytes(String.join("\n", args) + "\n" + TestLauncherConstants.MULTILINE_ARG_VALUE_TERMINATOR + "\n"); + if (ARGS_PARAMETER.equals(line)) { + out.writeBytes(String.join("\n", args) + "\n" + MULTILINE_ARG_VALUE_TERMINATOR + "\n"); out.flush(); - } else if (TestLauncherConstants.EXITDATA_PARAMETER.equals(line)) { + } else if (EXITDATA_PARAMETER.equals(line)) { while ((line = in.readLine()) != null) { - if (TestLauncherConstants.MULTILINE_ARG_VALUE_TERMINATOR.equals(line)) { + if (MULTILINE_ARG_VALUE_TERMINATOR.equals(line)) { break; } exitData.add(line); } - } else if (TestLauncherConstants.EXITCODE_PARAMETER.equals(line)) { - TestLauncherApp.exitCode = Integer.parseInt(in.readLine()); + } else if (EXITCODE_PARAMETER.equals(line)) { + exitCode = Integer.parseInt(in.readLine()); break; } } diff --git a/features/org.eclipse.equinox.executable.feature/library/org.eclipse.launcher.tests/src/test/java/LauncherTests.java b/bundles/org.eclipse.equinox.launcher.tests/src/org/eclipse/equinox/launcher/tests/LauncherTests.java similarity index 70% rename from features/org.eclipse.equinox.executable.feature/library/org.eclipse.launcher.tests/src/test/java/LauncherTests.java rename to bundles/org.eclipse.equinox.launcher.tests/src/org/eclipse/equinox/launcher/tests/LauncherTests.java index 4766ca5937a..59a9e5ee062 100644 --- a/features/org.eclipse.equinox.executable.feature/library/org.eclipse.launcher.tests/src/test/java/LauncherTests.java +++ b/bundles/org.eclipse.equinox.launcher.tests/src/org/eclipse/equinox/launcher/tests/LauncherTests.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2023 Eclipse Foundation, Inc. and others. + * Copyright (c) 2023, 2024 Eclipse Foundation, Inc. and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -11,7 +11,7 @@ * Contributors: * Umair Sair - initial API and implementation *******************************************************************************/ -package test.java; +package org.eclipse.equinox.launcher.tests; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -19,42 +19,152 @@ import java.io.BufferedReader; import java.io.DataOutputStream; -import java.io.File; -import java.io.FileWriter; import java.io.IOException; import java.io.InputStreamReader; import java.net.ServerSocket; import java.net.Socket; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.Optional; +import java.util.Properties; import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; - -import org.eclipse.equinox.launcher.TestLauncherConstants; +import java.util.jar.Attributes; +import java.util.jar.Attributes.Name; +import java.util.jar.JarOutputStream; +import java.util.jar.Manifest; +import java.util.stream.Stream; +import java.util.zip.ZipEntry; + +import org.eclipse.equinox.launcher.TestLauncherApp; +import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; public class LauncherTests { - private static final String ECLIPSE_INI_PATH_KEY = "ECLIPSE_INI_PATH"; - // eclipse ini file name is relative to eclipse binary. e.g., in mac, it is ../Eclipse/eclipse.ini - // and on other hosts, it is present in same directory as eclipse binary - private static final String ECLIPSE_INI_FILE_NAME = System.getProperty(ECLIPSE_INI_PATH_KEY, - System.getenv(ECLIPSE_INI_PATH_KEY) == null ? "eclipse.ini" : System.getenv(ECLIPSE_INI_PATH_KEY)); - // @formatter:off - private static final String DEFAULT_ECLIPSE_INI_CONTENT = "-startup\n" - + "../test.launcher.jar\n" - + "--launcher.library\n" - + "plugins/org.eclipse.equinox.launcher\n" - + "-vmargs\n" - + "-Xms40m\n" - + ""; - // @formatter:on - public static final Integer EXIT_OK = Integer.valueOf(0); - public static final Integer EXIT_RESTART = Integer.valueOf(23); - public static final Integer EXIT_RELAUNCH = Integer.valueOf(24); + + private static final String OS_NAME = System.getProperty("os.name").toLowerCase(); + private static final String ECLIPSE_EXE_NAME = (OS_NAME.contains("win") ? "eclipsec.exe" : "eclipse"); + private static final String ECLIPSE_INI_FILE_NAME = OS_NAME.contains("mac") ? "./Eclipse/eclipse.ini" + : "eclipse.ini"; + + private static final String DEFAULT_ECLIPSE_INI_CONTENT = """ + -startup + test.launcher.jar + --launcher.library + plugins/org.eclipse.equinox.launcher + -vmargs + -Xms40m + """; + public static final Integer EXIT_OK = 0; + public static final Integer EXIT_RESTART = 23; + public static final Integer EXIT_RELAUNCH = 24; + + @TempDir + static Path eclipseInstallationMockLocation; + + @BeforeAll + static void prepareLauncherSetup() throws Exception { + Path codeSource = Path.of(LauncherTests.class.getProtectionDomain().getCodeSource().getLocation().toURI()); + Path equinoxRepo; + Path classesDirectory; + if (Files.isDirectory(codeSource) && codeSource.endsWith(Path.of("org.eclipse.equinox.launcher.tests"))) { + // Test executed from within the IDE + equinoxRepo = codeSource.getParent().getParent(); + classesDirectory = Path.of("bin"); + } else if (Files.isDirectory(codeSource) + && codeSource.endsWith(Path.of("org.eclipse.equinox.launcher.tests/target/classes"))) { + // Test executed by Maven+Tycho + equinoxRepo = codeSource.getParent().getParent().getParent().getParent(); + classesDirectory = Path.of("target", "classes"); + } else { + throw new IllegalStateException("Unkown state"); + } + + Path binariesRoot = findBinariesRoot(equinoxRepo); + if (!Files.isDirectory(binariesRoot)) { + throw new IllegalArgumentException("Supplied equinox binaries location does not exist: " + binariesRoot); + } + String os = System.getProperty("osgi.os"); + String ws = System.getProperty("osgi.ws"); + String arch = System.getProperty("osgi.arch"); + + // Assemble a Eclipse installation mock in the test-temporary directory + + Path exePath = Path.of("org.eclipse.equinox.executable", "bin", ws, os, arch); + if (os.contains("mac")) { + exePath = exePath.resolve("Eclipse.app/Contents/MacOS/eclipse"); + } else { + exePath = exePath.resolve(ECLIPSE_EXE_NAME); + } + Files.copy(binariesRoot.resolve(exePath), eclipseInstallationMockLocation.resolve(ECLIPSE_EXE_NAME)); + + Properties versions = new Properties(); + try (var in = Files.newInputStream( + equinoxRepo.resolve("features/org.eclipse.equinox.executable.feature/library/make_version.mak"))) { + versions.load(in); + } + String launcherLibrary = "eclipse_" + versions.get("maj_ver") + versions.get("min_ver") + + (os.contains("win") ? ".dll" : ".so"); + String launcherLibFile = "org.eclipse.equinox.launcher." + ws + "." + os + "." + arch + "/" + launcherLibrary; + Files.copy(binariesRoot.resolve(launcherLibFile), + Files.createDirectories(eclipseInstallationMockLocation.resolve("plugins/org.eclipse.equinox.launcher")) + .resolve(launcherLibrary)); + + Manifest manifest = new Manifest(); + Attributes mainAttributes = manifest.getMainAttributes(); + mainAttributes.put(Name.MANIFEST_VERSION, "1.0"); + mainAttributes.putValue("Bundle-ManifestVersion", "2"); + mainAttributes.putValue("Main-Class", "org.eclipse.equinox.launcher.TestLauncherApp"); + + Path launcherJarPath = eclipseInstallationMockLocation.resolve("test.launcher.jar"); + try (var out = Files.newOutputStream(launcherJarPath); + JarOutputStream jar = new JarOutputStream(out, manifest);) { + addProjectsClassFiles(jar, + equinoxRepo.resolve("bundles/org.eclipse.equinox.launcher.tests").resolve(classesDirectory)); + addProjectsClassFiles(jar, + equinoxRepo.resolve("bundles/org.eclipse.equinox.launcher").resolve(classesDirectory)); + } + } + + private static Path findBinariesRoot(Path equinoxRepositoryPath) { + String binariesRootName = "rt.equinox.binaries.loc"; + Optional binariesRepo = Optional + .ofNullable(System.getProperty(binariesRootName, System.getenv(binariesRootName))).map(Path::of); + if (binariesRepo.isEmpty()) { // search for co-located repository with known names + binariesRepo = Stream.of("equinox.binaries", "rt.equinox.binaries") + .map(equinoxRepositoryPath::resolveSibling).filter(Files::isDirectory).findFirst(); + } + return binariesRepo.orElseThrow(() -> new IllegalStateException( + "Location of equinox binaries could not be auto-detected and was not provided via the System.property or environment.variable '" + + binariesRootName + "'.")); + } + + private static void addProjectsClassFiles(JarOutputStream jar, Path classesFolder) throws IOException { + try (Stream classFiles = Files.walk(classesFolder);) { + for (Path classFile : (Iterable) classFiles::iterator) { + if (Files.isRegularFile(classFile)) { + String entryName = classesFolder.relativize(classFile).toString().replace('\\', '/'); + jar.putNextEntry(new ZipEntry(entryName)); + Files.copy(classFile, jar); + } + } + } + } + + @AfterAll + static void cleanUp() throws Exception { + // Some of the processes launched stay alive for a bit too long to be able to + // delete the temp directory + ProcessHandle.current().descendants().forEach(ProcessHandle::destroyForcibly); + Thread.sleep(100); + } private ServerSocket server; @@ -87,7 +197,7 @@ void test_appTerminatesWithCodeZeroOnExit() throws IOException, InterruptedExcep assertTrue(appArgs.containsAll(Arrays.asList("-vmargs", "-Xms40m"))); // Make sure launcher exited with code zero launcherProcess.waitFor(5, TimeUnit.SECONDS); - assertTrue(launcherProcess.exitValue() == 0); + assertEquals(0, launcherProcess.exitValue()); } @Test @@ -113,15 +223,15 @@ void test_eclipseIniChangesShouldBePickedOnRestart() throws IOException { assertTrue(appArgs2.contains("-Dtest")); // Other than exitdata arg, all other args should be same over restarts - appArgs1.remove(appArgs1.indexOf(TestLauncherConstants.EXITDATA_PARAMETER) + 1); - appArgs2.remove(appArgs2.indexOf(TestLauncherConstants.EXITDATA_PARAMETER) + 1); + appArgs1.remove(appArgs1.indexOf(TestLauncherApp.EXITDATA_PARAMETER) + 1); + appArgs2.remove(appArgs2.indexOf(TestLauncherApp.EXITDATA_PARAMETER) + 1); // After restart, only -Dtest arg should be extra, other than that args should // be same appArgs2.remove(appArgs2.indexOf("-Dtest")); // Convert backslashes to forward slashes before comparison so that all paths are consistent - assertEquals(appArgs1.stream().map(s -> s.replace('\\', '/')).collect(Collectors.toList()), - appArgs2.stream().map(s -> s.replace('\\', '/')).collect(Collectors.toList())); + assertEquals(appArgs1.stream().map(s -> s.replace('\\', '/')).toList(), + appArgs2.stream().map(s -> s.replace('\\', '/')).toList()); } @Test @@ -147,8 +257,8 @@ void test_eclipseIniChangesShouldBePickedOnRelaunch() throws IOException { assertTrue(appArgs2.contains("-Dtest")); // Other than exitdata arg, all other args should be same over relaunches - appArgs1.remove(appArgs1.indexOf(TestLauncherConstants.EXITDATA_PARAMETER) + 1); - appArgs2.remove(appArgs2.indexOf(TestLauncherConstants.EXITDATA_PARAMETER) + 1); + appArgs1.remove(appArgs1.indexOf(TestLauncherApp.EXITDATA_PARAMETER) + 1); + appArgs2.remove(appArgs2.indexOf(TestLauncherApp.EXITDATA_PARAMETER) + 1); // After relaunch, -Dtest and -data args should be extra, other than that args should // be same appArgs2.remove(appArgs2.indexOf("-Dtest")); @@ -156,8 +266,8 @@ void test_eclipseIniChangesShouldBePickedOnRelaunch() throws IOException { appArgs2.remove(appArgs2.indexOf("dir1")); // Convert backslashes to forward slashes before comparison so that all paths are consistent - assertEquals(appArgs1.stream().map(s -> s.replace('\\', '/')).collect(Collectors.toList()), - appArgs2.stream().map(s -> s.replace('\\', '/')).collect(Collectors.toList())); + assertEquals(appArgs1.stream().map(s -> s.replace('\\', '/')).toList(), + appArgs2.stream().map(s -> s.replace('\\', '/')).toList()); } @Test @@ -200,7 +310,7 @@ void test_newNonVMArgsForRelaunchShouldOverrideOlderSameArg() throws IOException analyzeLaunchedTestApp(socket, appArgs2, null, EXIT_OK); // Relaunched app should contain '-data dir1 -data dir2' - assertEquals(Collections.frequency(appArgs2, "-data"), 2); + assertEquals(2, Collections.frequency(appArgs2, "-data")); assertTrue(appArgs2.contains("dir1")); assertTrue(appArgs2.contains("dir2")); // dir2 argument should appear later so that it gets effective @@ -478,7 +588,7 @@ void test_ArgsRemainSameOverRestarts() throws IOException { List appArgs1 = new ArrayList<>(); analyzeLaunchedTestApp(socket, appArgs1, null, EXIT_RESTART); - appArgs1.remove(appArgs1.indexOf(TestLauncherConstants.EXITDATA_PARAMETER) + 1); + appArgs1.remove(appArgs1.indexOf(TestLauncherApp.EXITDATA_PARAMETER) + 1); for (int i = 0; i < 10; i++) { socket = server.accept(); @@ -486,11 +596,11 @@ void test_ArgsRemainSameOverRestarts() throws IOException { List appArgs2 = new ArrayList<>(); analyzeLaunchedTestApp(socket, appArgs2, null, i == 9 ? EXIT_OK : EXIT_RESTART); // Other than exitdata arg, all other args should be same over restarts - appArgs2.remove(appArgs2.indexOf(TestLauncherConstants.EXITDATA_PARAMETER) + 1); + appArgs2.remove(appArgs2.indexOf(TestLauncherApp.EXITDATA_PARAMETER) + 1); // Convert backslashes to forward slashes before comparison so that all paths are consistent - assertEquals(appArgs1.stream().map(s -> s.replace('\\', '/')).collect(Collectors.toList()), - appArgs2.stream().map(s -> s.replace('\\', '/')).collect(Collectors.toList())); + assertEquals(appArgs1.stream().map(s -> s.replace('\\', '/')).toList(), + appArgs2.stream().map(s -> s.replace('\\', '/')).toList()); } } @@ -504,7 +614,7 @@ void test_ArgsRemainSameOverRelaunches() throws IOException { List appArgs1 = new ArrayList<>(); analyzeLaunchedTestApp(socket, appArgs1, "--launcher.skipOldUserArgs\n-data\ndir1", EXIT_RELAUNCH); - appArgs1.remove(appArgs1.indexOf(TestLauncherConstants.EXITDATA_PARAMETER) + 1); + appArgs1.remove(appArgs1.indexOf(TestLauncherApp.EXITDATA_PARAMETER) + 1); for (int i = 0; i < 10; i++) { socket = server.accept(); @@ -512,11 +622,11 @@ void test_ArgsRemainSameOverRelaunches() throws IOException { List appArgs2 = new ArrayList<>(); analyzeLaunchedTestApp(socket, appArgs2, "--launcher.skipOldUserArgs\n-data\ndir1", i == 9 ? EXIT_OK : EXIT_RELAUNCH); // Other than exitdata arg, all other args should be same over these relaunches - appArgs2.remove(appArgs2.indexOf(TestLauncherConstants.EXITDATA_PARAMETER) + 1); + appArgs2.remove(appArgs2.indexOf(TestLauncherApp.EXITDATA_PARAMETER) + 1); // Convert backslashes to forward slashes before comparison so that all paths are consistent - assertEquals(appArgs1.stream().map(s -> s.replace('\\', '/')).collect(Collectors.toList()), - appArgs2.stream().map(s -> s.replace('\\', '/')).collect(Collectors.toList())); + assertEquals(appArgs1.stream().map(s -> s.replace('\\', '/')).toList(), + appArgs2.stream().map(s -> s.replace('\\', '/')).toList()); } } @@ -524,48 +634,45 @@ private void analyzeLaunchedTestApp(Socket socket, List appArgs, String throws IOException { BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); DataOutputStream out = new DataOutputStream(socket.getOutputStream()); - out.writeBytes(TestLauncherConstants.ARGS_PARAMETER + "\n"); + out.writeBytes(TestLauncherApp.ARGS_PARAMETER + "\n"); out.flush(); String line = null; System.out.println("--- start ----"); while ((line = in.readLine()) != null) { - if (TestLauncherConstants.MULTILINE_ARG_VALUE_TERMINATOR.equals(line)) + if (TestLauncherApp.MULTILINE_ARG_VALUE_TERMINATOR.equals(line)) { break; + } System.out.println(line); appArgs.add(line); } System.out.println("--- end ----"); { - out.writeBytes(TestLauncherConstants.EXITDATA_PARAMETER + "\n"); - if (restartArgs != null && !restartArgs.isBlank()) + out.writeBytes(TestLauncherApp.EXITDATA_PARAMETER + "\n"); + if (restartArgs != null && !restartArgs.isBlank()) { out.writeBytes(restartArgs + "\n"); - out.writeBytes(TestLauncherConstants.MULTILINE_ARG_VALUE_TERMINATOR + "\n"); + } + out.writeBytes(TestLauncherApp.MULTILINE_ARG_VALUE_TERMINATOR + "\n"); out.flush(); - out.writeBytes(TestLauncherConstants.EXITCODE_PARAMETER + "\n"); + out.writeBytes(TestLauncherApp.EXITCODE_PARAMETER + "\n"); out.writeBytes(appExitCode + "\n"); out.flush(); } } private Process startEclipseLauncher(List args) throws IOException { - String launcherPath = new File( - "eclipse" + (System.getProperty("os.name").toLowerCase().contains("win") ? ".exe" : "")) - .getAbsolutePath(); + Path launcherPath = eclipseInstallationMockLocation.resolve(ECLIPSE_EXE_NAME); List allArgs = new ArrayList<>(); - allArgs.add(launcherPath); + allArgs.add(launcherPath.toString()); allArgs.addAll(args); ProcessBuilder pb = new ProcessBuilder(allArgs); - pb.environment().put(TestLauncherConstants.PORT_ENV_KEY, Integer.toString(server.getLocalPort())); + pb.directory(eclipseInstallationMockLocation.toFile()); + pb.environment().put(TestLauncherApp.PORT_ENV_KEY, Integer.toString(server.getLocalPort())); return pb.start(); } - private void writeEclipseIni(String content) throws IOException { - File iniFile = new File(ECLIPSE_INI_FILE_NAME); - iniFile.createNewFile(); - FileWriter myWriter = new FileWriter(ECLIPSE_INI_FILE_NAME); - myWriter.write(content); - myWriter.close(); + private static void writeEclipseIni(String content) throws IOException { + Files.writeString(eclipseInstallationMockLocation.resolve(ECLIPSE_INI_FILE_NAME), content); } } diff --git a/features/org.eclipse.equinox.executable.feature/library/cocoa/make_cocoa.mak b/features/org.eclipse.equinox.executable.feature/library/cocoa/make_cocoa.mak index b4709142417..1f5438ecd96 100644 --- a/features/org.eclipse.equinox.executable.feature/library/cocoa/make_cocoa.mak +++ b/features/org.eclipse.equinox.executable.feature/library/cocoa/make_cocoa.mak @@ -37,8 +37,6 @@ EXEC = $(PROGRAM_OUTPUT) DLL = $(PROGRAM_LIBRARY) LIBS = -framework Cocoa -LIBRARY_FRAGMENT_NAME ?= org.eclipse.equinox.launcher.$(DEFAULT_WS).$(DEFAULT_OS).$(DEFAULT_OS_ARCH) - ifeq ($(ARCHS),-arch x86_64) LDFLAGS=-pagezero_size 0x1000 endif @@ -91,32 +89,3 @@ install: all clean: rm -f $(EXEC) $(DLL) $(MAIN_OBJS) $(COMMON_OBJS) $(DLL_OBJS) - -dev_build_install: all -ifneq ($(filter "$(origin DEV_ECLIPSE)", "environment" "command line"),) - $(info Copying $(EXEC) and $(DLL) into your development eclipse folder:) - mkdir -p ${DEV_ECLIPSE}/ - cp $(EXEC) ${DEV_ECLIPSE}/ - mkdir -p ${DEV_ECLIPSE}/plugins/$(LIBRARY_FRAGMENT_NAME)/ - cp $(DLL) ${DEV_ECLIPSE}/plugins/$(LIBRARY_FRAGMENT_NAME)/ -else - $(error $(DEV_INSTALL_ERROR_MSG)) -endif - -test: - $(eval export DEV_ECLIPSE=../org.eclipse.launcher.tests/target/test-run) - mvn -f ../org.eclipse.launcher.tests/pom.xml clean verify -Dmaven.test.skip=true - make -f $(firstword $(MAKEFILE_LIST)) dev_build_install LIBRARY_FRAGMENT_NAME=org.eclipse.equinox.launcher - mkdir $(DEV_ECLIPSE)/../Eclipse - mvn -f ../org.eclipse.launcher.tests/pom.xml -DargLine="-DECLIPSE_INI_PATH=../Eclipse/eclipse.ini" test - -define DEV_INSTALL_ERROR_MSG = -Note: - DEV_ECLIPSE environmental variable is not defined. - You can download an integration build eclipse for testing and set DEV_ECLIPSE to point to it's folder - as per output of 'pwd'. Note, without trailing forwardslash. Integration build can be downloaded here: - See: https://download.eclipse.org/eclipse/downloads/ - That way you can automatically build and copy eclipse and eclipse_XXXX.so into the relevant folders for testing. - E.g: you can put something like the following into your .bashrc - export DEV_ECLIPSE="/home/YOUR_USER/Downloads/eclipse-SDK-I20YYMMDD-XXXX-linux-gtk-x86_64/eclipse" -endef diff --git a/features/org.eclipse.equinox.executable.feature/library/gtk/build.sh b/features/org.eclipse.equinox.executable.feature/library/gtk/build.sh index 02e459530a6..f837c0328af 100755 --- a/features/org.eclipse.equinox.executable.feature/library/gtk/build.sh +++ b/features/org.eclipse.equinox.executable.feature/library/gtk/build.sh @@ -16,7 +16,7 @@ # Martin Oberhuber (Wind River) - [517013] Avoid memcpy@GLIBC_2.14 dependency #******************************************************************************* # -# Usage: sh build.sh [] [clean] [test] +# Usage: sh build.sh [] [clean] # # where the optional switches are: # -output - executable filename ("eclipse") @@ -30,8 +30,6 @@ # # Examples: # sh build.sh clean -# sh build.sh test -# sh build.sh clean test # sh build.sh -java /usr/j2se OPTFLAG=-g PICFLAG=-fpic cd `dirname $0` diff --git a/features/org.eclipse.equinox.executable.feature/library/gtk/make_linux.mak b/features/org.eclipse.equinox.executable.feature/library/gtk/make_linux.mak index a0f4a8868a9..575e683444d 100644 --- a/features/org.eclipse.equinox.executable.feature/library/gtk/make_linux.mak +++ b/features/org.eclipse.equinox.executable.feature/library/gtk/make_linux.mak @@ -43,8 +43,7 @@ PROGRAM_LIBRARY = $(PROGRAM_OUTPUT)_$(LIB_VERSION).so EXEC_DIR ?= ../../../../../rt.equinox.binaries/org.eclipse.equinox.executable OUTPUT_DIR ?= $(EXEC_DIR)/bin/$(DEFAULT_WS)/$(DEFAULT_OS)/$(DEFAULT_OS_ARCH) -LIBRARY_FRAGMENT_NAME ?= org.eclipse.equinox.launcher.$(DEFAULT_WS).$(DEFAULT_OS).$(DEFAULT_OS_ARCH) -LIBRARY_DIR ?= $(EXEC_DIR)/../$(LIBRARY_FRAGMENT_NAME) +LIBRARY_DIR ?= $(EXEC_DIR)/../org.eclipse.equinox.launcher.$(DEFAULT_WS).$(DEFAULT_OS).$(DEFAULT_OS_ARCH) # 64 bit specific flag: ifeq ($(M_CFLAGS),) @@ -145,31 +144,3 @@ install: all clean: $(info Clean up:) rm -f $(EXEC) $(DLL) $(MAIN_OBJS) $(COMMON_OBJS) $(DLL_OBJS) - -# Convienience method to install produced output into a developer's eclipse for testing/development. -dev_build_install: all -ifneq ($(filter "$(origin DEV_ECLIPSE)", "environment" "command line"),) - $(info Copying $(EXEC) and $(DLL) into your development eclipse folder:) - mkdir -p ${DEV_ECLIPSE}/ - cp $(EXEC) ${DEV_ECLIPSE}/ - mkdir -p ${DEV_ECLIPSE}/plugins/$(LIBRARY_FRAGMENT_NAME)/ - cp $(DLL) ${DEV_ECLIPSE}/plugins/$(LIBRARY_FRAGMENT_NAME)/ -else - $(error $(DEV_INSTALL_ERROR_MSG)) -endif - -test: - mvn -f ../org.eclipse.launcher.tests/pom.xml clean verify -Dmaven.test.skip=true - make -f $(firstword $(MAKEFILE_LIST)) dev_build_install LIBRARY_FRAGMENT_NAME=org.eclipse.equinox.launcher DEV_ECLIPSE=../org.eclipse.launcher.tests/target/test-run - mvn -f ../org.eclipse.launcher.tests/pom.xml test - -define DEV_INSTALL_ERROR_MSG = -Note: - DEV_ECLIPSE environmental variable is not defined. - You can download an integration build eclipse for testing and set DEV_ECLIPSE to point to it's folder - as per output of 'pwd'. Note, without trailing forwardslash. Integration build can be downloaded here: - See: https://download.eclipse.org/eclipse/downloads/ - That way you can automatically build and copy eclipse and eclipse_XXXX.so into the relevant folders for testing. - E.g: you can put something like the following into your .bashrc - export DEV_ECLIPSE="/home/YOUR_USER/Downloads/eclipse-SDK-I20YYMMDD-XXXX-linux-gtk-x86_64/eclipse" -endef diff --git a/features/org.eclipse.equinox.executable.feature/library/org.eclipse.launcher.tests/.classpath b/features/org.eclipse.equinox.executable.feature/library/org.eclipse.launcher.tests/.classpath deleted file mode 100644 index 3e7d5e55fff..00000000000 --- a/features/org.eclipse.equinox.executable.feature/library/org.eclipse.launcher.tests/.classpath +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/features/org.eclipse.equinox.executable.feature/library/org.eclipse.launcher.tests/.gitignore b/features/org.eclipse.equinox.executable.feature/library/org.eclipse.launcher.tests/.gitignore deleted file mode 100644 index ae3c1726048..00000000000 --- a/features/org.eclipse.equinox.executable.feature/library/org.eclipse.launcher.tests/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/bin/ diff --git a/features/org.eclipse.equinox.executable.feature/library/org.eclipse.launcher.tests/.settings/org.eclipse.m2e.core.prefs b/features/org.eclipse.equinox.executable.feature/library/org.eclipse.launcher.tests/.settings/org.eclipse.m2e.core.prefs deleted file mode 100644 index f897a7f1cb2..00000000000 --- a/features/org.eclipse.equinox.executable.feature/library/org.eclipse.launcher.tests/.settings/org.eclipse.m2e.core.prefs +++ /dev/null @@ -1,4 +0,0 @@ -activeProfiles= -eclipse.preferences.version=1 -resolveWorkspaceProjects=true -version=1 diff --git a/features/org.eclipse.equinox.executable.feature/library/org.eclipse.launcher.tests/pom.xml b/features/org.eclipse.equinox.executable.feature/library/org.eclipse.launcher.tests/pom.xml deleted file mode 100644 index d58f6a61579..00000000000 --- a/features/org.eclipse.equinox.executable.feature/library/org.eclipse.launcher.tests/pom.xml +++ /dev/null @@ -1,58 +0,0 @@ - - 4.0.0 - org.eclipse.launcher.tests - org.eclipse.launcher.tests - 1.0.0 - jar - - - org.junit.jupiter - junit-jupiter-engine - 5.10.0 - - - - src - test.launcher - - - org.apache.maven.plugins - maven-compiler-plugin - 3.11.0 - - 17 - - - - org.apache.maven.plugins - maven-jar-plugin - 3.3.0 - - - default-jar - compile - - jar - - - - - org.eclipse.equinox.launcher.TestLauncherApp - - - - - - - - org.apache.maven.plugins - maven-surefire-plugin - 3.1.2 - - ${project.build.directory}/test-run - true - - - - - \ No newline at end of file diff --git a/features/org.eclipse.equinox.executable.feature/library/org.eclipse.launcher.tests/src/org/eclipse/equinox/launcher/JNIBridge.java b/features/org.eclipse.equinox.executable.feature/library/org.eclipse.launcher.tests/src/org/eclipse/equinox/launcher/JNIBridge.java deleted file mode 120000 index 7a2f31094d8..00000000000 --- a/features/org.eclipse.equinox.executable.feature/library/org.eclipse.launcher.tests/src/org/eclipse/equinox/launcher/JNIBridge.java +++ /dev/null @@ -1 +0,0 @@ -../../../../../../../../../bundles/org.eclipse.equinox.launcher/src/org/eclipse/equinox/launcher/JNIBridge.java \ No newline at end of file diff --git a/features/org.eclipse.equinox.executable.feature/library/org.eclipse.launcher.tests/src/org/eclipse/equinox/launcher/TestLauncherConstants.java b/features/org.eclipse.equinox.executable.feature/library/org.eclipse.launcher.tests/src/org/eclipse/equinox/launcher/TestLauncherConstants.java deleted file mode 100644 index ac87e42833e..00000000000 --- a/features/org.eclipse.equinox.executable.feature/library/org.eclipse.launcher.tests/src/org/eclipse/equinox/launcher/TestLauncherConstants.java +++ /dev/null @@ -1,23 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2023 Eclipse Foundation, Inc. and others. - * - * This program and the accompanying materials - * are made available under the terms of the Eclipse Public License 2.0 - * which accompanies this distribution, and is available at - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Umair Sair - initial API and implementation - *******************************************************************************/ -package org.eclipse.equinox.launcher; - -public interface TestLauncherConstants { - public static final String ARGS_PARAMETER = "-args"; //$NON-NLS-1$ - public static final String EXITDATA_PARAMETER = "-exitdata"; //$NON-NLS-1$ - public static final String EXITCODE_PARAMETER = "-exitcode"; //$NON-NLS-1$ - public static final String MULTILINE_ARG_VALUE_TERMINATOR = "---"; //$NON-NLS-1$ - - public static final String PORT_ENV_KEY = "eclipse_test_port"; //$NON-NLS-1$ -} diff --git a/features/org.eclipse.equinox.executable.feature/library/win32/make_win64.mak b/features/org.eclipse.equinox.executable.feature/library/win32/make_win64.mak index 67b45457054..f2b72b0232e 100644 --- a/features/org.eclipse.equinox.executable.feature/library/win32/make_win64.mak +++ b/features/org.eclipse.equinox.executable.feature/library/win32/make_win64.mak @@ -63,7 +63,6 @@ wcflags = -DUNICODE -I.. -DDEFAULT_OS="\"$(DEFAULT_OS)\"" \ -DDEFAULT_WS="\"$(DEFAULT_WS)\"" \ -I"$(JAVA_HOME)\include" -I"$(JAVA_HOME)\include\win32" \ $(cflags) -LIBRARY_FRAGMENT_NAME = org.eclipse.equinox.launcher.$(DEFAULT_WS).$(DEFAULT_OS).$(DEFAULT_OS_ARCH) all: $(EXEC) $(DLL) $(CONSOLE) eclipseMain.obj: ../eclipseUnicode.h ../eclipseCommon.h ../eclipseMain.c @@ -114,31 +113,3 @@ install: all clean: del $(EXEC) $(DLL) $(MAIN_OBJS) $(MAIN_CONSOLE_OBJS) $(DLL_OBJS) $(COMMON_OBJS) $(RES) - -# Convienience method to install produced output into a developer's eclipse for testing/development. -dev_build_install: all -!ifdef DEV_ECLIPSE - @echo Copying $(EXEC) and $(DLL) into your development eclipse folder - mkdir $(DEV_ECLIPSE) - copy $(EXEC) $(DEV_ECLIPSE) - mkdir $(DEV_ECLIPSE)\plugins - mkdir $(DEV_ECLIPSE)\plugins\$(LIBRARY_FRAGMENT_NAME) - copy $(DLL) $(DEV_ECLIPSE)\plugins\$(LIBRARY_FRAGMENT_NAME) -!else - !error $(DEV_INSTALL_ERROR_MSG) -!endif - -test: - mvn -f ../org.eclipse.launcher.tests/pom.xml clean verify -Dmaven.test.skip=true - nmake -f make_win64.mak dev_build_install LIBRARY_FRAGMENT_NAME=org.eclipse.equinox.launcher DEV_ECLIPSE=..\org.eclipse.launcher.tests\target\test-run - mvn -f ../org.eclipse.launcher.tests/pom.xml test - -DEV_INSTALL_ERROR_MSG =\ -Note:\ - DEV_ECLIPSE environmental variable is not defined.\ - You can download an integration build eclipse for testing and set DEV_ECLIPSE to point to it's folder\ - as per output of 'pwd'. Note, without trailing forwardslash. Integration build can be downloaded here:\ - See: https://download.eclipse.org/eclipse/downloads/\ - That way you can automatically build and copy eclipse and eclipse_XXXX.so into the relevant folders for testing. \ - E.g: you can put something like the following into your .bashrc\ - export DEV_ECLIPSE="/home/YOUR_USER/Downloads/eclipse-SDK-I20YYMMDD-XXXX-linux-win32-x86_64/eclipse" diff --git a/pom.xml b/pom.xml index d943b514468..68986ce3ddb 100644 --- a/pom.xml +++ b/pom.xml @@ -220,6 +220,7 @@ bundles/org.eclipse.equinox.launcher.gtk.linux.ppc64le bundles/org.eclipse.equinox.launcher.gtk.linux.x86_64 bundles/org.eclipse.equinox.launcher.win32.win32.x86_64 + bundles/org.eclipse.equinox.launcher.tests bundles/org.eclipse.osgi.tests