diff --git a/runtime/tests/org.eclipse.core.tests.harness/src/org/eclipse/core/tests/harness/session/CustomSessionConfiguration.java b/runtime/tests/org.eclipse.core.tests.harness/src/org/eclipse/core/tests/harness/session/CustomSessionConfiguration.java new file mode 100644 index 00000000000..3c1ac441c95 --- /dev/null +++ b/runtime/tests/org.eclipse.core.tests.harness/src/org/eclipse/core/tests/harness/session/CustomSessionConfiguration.java @@ -0,0 +1,69 @@ +/******************************************************************************* + * Copyright (c) 2024 Vector Informatik GmbH and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package org.eclipse.core.tests.harness.session; + +import java.nio.file.Path; +import org.eclipse.core.tests.harness.session.customization.SessionCustomization; +import org.osgi.framework.Bundle; + +/** + * A session customization to use a custom session configuration, i.e., a custom + * "config.ini" file with a defined set of bundles to be used. + */ +public interface CustomSessionConfiguration extends SessionCustomization { + + /** + * Sets the given configuration directory. If not called, a temporary folder is + * used as the configuration directory. + * + * @param configurationDirectory the path of the directory to place the + * configuration in, must not be {@code null} + * + * @return this + */ + public CustomSessionConfiguration setConfigurationDirectory(Path configurationDirectory); + + /** + * Adds the bundle containing the given class to the session configuration. + * + * @param classFromBundle a class from the bundle to add, must not be + * {@code null} + * + * @return this + */ + public CustomSessionConfiguration addBundle(Class classFromBundle); + + /** + * Adds the bundle to the session configuration. + * + * @param bundle the bundle to add, must not be {@code null} + * + * @return this + */ + public CustomSessionConfiguration addBundle(Bundle bundle); + + /** + * Activates the "osgi.configuration.cascaded" option for this configuration. + * + * @return this + */ + public CustomSessionConfiguration setCascaded(); + + /** + * Marks the configuration area as read only. This will be effective from the + * second session on, since the the first session requires a writable + * configuration area for initial setup. + * + * @return this + */ + public CustomSessionConfiguration setReadOnly(); + +} diff --git a/runtime/tests/org.eclipse.core.tests.harness/src/org/eclipse/core/tests/harness/session/SessionTestExtension.java b/runtime/tests/org.eclipse.core.tests.harness/src/org/eclipse/core/tests/harness/session/SessionTestExtension.java index 706c70c0554..de72e21c205 100644 --- a/runtime/tests/org.eclipse.core.tests.harness/src/org/eclipse/core/tests/harness/session/SessionTestExtension.java +++ b/runtime/tests/org.eclipse.core.tests.harness/src/org/eclipse/core/tests/harness/session/SessionTestExtension.java @@ -14,6 +14,8 @@ import java.util.HashSet; import java.util.Objects; import java.util.Set; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.tests.harness.session.customization.CustomSessionConfigurationImpl; import org.eclipse.core.tests.harness.session.customization.CustomSessionWorkspaceImpl; import org.eclipse.core.tests.harness.session.customization.SessionCustomization; import org.eclipse.core.tests.harness.session.samples.SampleSessionTests; @@ -149,6 +151,44 @@ public SessionTestExtensionBuilder withCustomization(CustomSessionWorkspace sess return this; } + /** + * Sets the given session configuration that uses a custom "config.ini" file + * with a defined set of bundles to be used. The customization can be + * instantiated via + * {@link SessionTestExtension#createCustomSessionConfiguration()}. By default, + * a temporary folder is used as a configuration directory. + *

+ * Example usage with default configuration directory: + * + *

+		 * @RegisterExtension
+		 * SessionTestExtension sessionTestExtension = SessionTestExtension.forPlugin("")
+		 * 		.withConfiguration(SessionTestExtension.createCustomConfiguration()).create();
+		 * 
+ * + * Example usage with custom configuration directory: + * + *
+		 * @TempDir
+		 * Path configurationDirectory;
+		 *
+		 * @RegisterExtension
+		 * SessionTestExtension extension = SessionTestExtension.forPlugin("")
+		 * 		.withConfiguration(
+		 * 				SessionTestExtension.createCustomConfiguration().setConfigurationDirectory(configurationDirectory))
+		 * 		.create();
+		 * 
+ * + * @param sessionConfiguration the custom configuration to use for the session + * tests + */ + public SessionTestExtensionBuilder withCustomization(CustomSessionConfiguration sessionConfiguration) { + Objects.requireNonNull(sessionConfiguration); + sessionConfiguration.addBundle(Platform.getBundle(storedPluginId)); + this.storedSessionCustomizations.add(sessionConfiguration); + return this; + } + /** * {@return a SessionTestExtension created with the information in * this builder} @@ -172,6 +212,14 @@ public static CustomSessionWorkspace createCustomWorkspace() { return new CustomSessionWorkspaceImpl(); } + /** + * {@return a custom Eclipse instance configuration that, by default, uses a + * temporary folder to store the configuration files} + */ + public static CustomSessionConfiguration createCustomConfiguration() { + return new CustomSessionConfigurationImpl(); + } + public void setEclipseArgument(String key, String value) { setup.setEclipseArgument(key, value); } diff --git a/runtime/tests/org.eclipse.core.tests.harness/src/org/eclipse/core/tests/harness/session/customization/CustomSessionConfigurationImpl.java b/runtime/tests/org.eclipse.core.tests.harness/src/org/eclipse/core/tests/harness/session/customization/CustomSessionConfigurationImpl.java new file mode 100644 index 00000000000..1e8e92912dd --- /dev/null +++ b/runtime/tests/org.eclipse.core.tests.harness/src/org/eclipse/core/tests/harness/session/customization/CustomSessionConfigurationImpl.java @@ -0,0 +1,258 @@ +/******************************************************************************* + * Copyright (c) 2024 Vector Informatik GmbH and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package org.eclipse.core.tests.harness.session.customization; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Objects; +import java.util.Optional; +import java.util.Properties; +import java.util.stream.Collectors; +import org.eclipse.core.internal.runtime.InternalPlatform; +import org.eclipse.core.runtime.FileLocator; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.tests.harness.session.CustomSessionConfiguration; +import org.eclipse.core.tests.session.ConfigurationSessionTestSuite; +import org.eclipse.core.tests.session.Setup; +import org.junit.Assert; +import org.osgi.framework.Bundle; +import org.osgi.framework.Constants; +import org.osgi.framework.FrameworkUtil; +import org.osgi.framework.Version; + +@SuppressWarnings("restriction") +public class CustomSessionConfigurationImpl implements CustomSessionConfiguration { + private static final String PROP_BUNDLES = "osgi.bundles"; + private static final String PROP_FRAMEWORK = "osgi.framework"; + private static final String PROP_BUNDLES_DEFAULT_START_LEVEL = "osgi.bundles.defaultStartLevel"; + private static final String PROP_INSTALL_AREA = "osgi.install.area"; + private static final String PROP_CONFIG_AREA_READ_ONLY = InternalPlatform.PROP_CONFIG_AREA + ".readOnly"; + private static final String PROP_CONFIG_CASCADED = "osgi.configuration.cascaded"; + + private final Collection bundleReferences = new ArrayList<>(); + private Path configurationDirectory; + private boolean readOnly = false; + private boolean cascaded = false; + private boolean firstExecutedSession = true; + + public CustomSessionConfigurationImpl() { + addMinimalBundleSet(); + } + + @SuppressWarnings("deprecation") + private void addMinimalBundleSet() { + // Just use any class from the bundles we want to add as minimal bundle set + + addBundle(org.eclipse.core.runtime.FileLocator.class, "@2:start"); // org.eclipse.equinox.common + addBundle(org.eclipse.core.runtime.Platform.class, "@:start"); // org.eclipse.core.runtime + addBundle(org.eclipse.core.runtime.jobs.Job.class); // org.eclipse.core.jobs + addBundle(org.eclipse.core.runtime.IExtension.class); // org.eclipse.equinox.registry + addBundle(org.eclipse.core.runtime.preferences.IEclipsePreferences.class); // org.eclipse.equinox.preferences + addBundle(org.osgi.service.prefs.Preferences.class); // org.osgi.service.prefs + addBundle(org.eclipse.core.runtime.content.IContentType.class); // org.eclipse.core.contenttype + addBundle(org.eclipse.equinox.app.IApplication.class); // org.eclipse.equinox.app + + addBundle(org.eclipse.core.tests.harness.TestHarnessPlugin.class); // org.eclipse.core.tests.harness + addBundle(org.eclipse.test.performance.Performance.class); // org.eclipse.test.performance + + addBundle(org.eclipse.jdt.internal.junit.runner.ITestLoader.class); // org.eclipse.jdt.junit.runtime + addBundle(org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.class); // org.eclipse.jdt.junit4.runtime + addBundle(org.eclipse.jdt.internal.junit5.runner.JUnit5TestLoader.class); // org.eclipse.jdt.junit5.runtime + addBundle(org.eclipse.pde.internal.junit.runtime.CoreTestApplication.class); // org.eclipse.pde.junit.runtime + + addBundle(net.bytebuddy.ByteBuddy.class); // net.bytebuddy for org.assertj.core.api + addBundle(org.assertj.core.api.Assertions.class); // org.assertj.core.api + addBundle(org.hamcrest.CoreMatchers.class); // org.hamcrest.core + + // The org.junit bundle requires an org.hamcrest.core bundle, but as of version + // 2.x, the org.hamcrest bundle above provides the actual classes. So we need to + // ensure that the actual org.hamcrest.core bundle required by org.junit is + // added too. + if ("org.hamcrest".equals(FrameworkUtil.getBundle(org.hamcrest.CoreMatchers.class).getSymbolicName())) { + Bundle maxHamcrestCoreBundle = null; + Version maxHamcrestCoreVersion = null; + for (Bundle bundle : FrameworkUtil.getBundle(ConfigurationSessionTestSuite.class).getBundleContext() + .getBundles()) { + if ("org.hamcrest.core".equals(bundle.getSymbolicName())) { + Version version = bundle.getVersion(); + if (maxHamcrestCoreVersion == null || maxHamcrestCoreVersion.compareTo(version) < 0) { + maxHamcrestCoreVersion = version; + maxHamcrestCoreBundle = bundle; + } + } + } + if (maxHamcrestCoreBundle != null) { + addBundle(maxHamcrestCoreBundle, null); + } + } + + addBundle(org.junit.Test.class); // org.junit + addBundle(org.junit.jupiter.api.Test.class); // junit-jupiter-api + addBundle(org.junit.jupiter.engine.JupiterTestEngine.class); // junit-jupiter-engine + addBundle(org.junit.jupiter.migrationsupport.EnableJUnit4MigrationSupport.class); // junit-jupiter-migrationsupport + addBundle(org.junit.jupiter.params.ParameterizedTest.class); // junit-jupiter-params + addBundle(org.junit.vintage.engine.VintageTestEngine.class); // junit-vintage-engine + addBundle(org.junit.platform.commons.JUnitException.class); // junit-platform-commons + addBundle(org.junit.platform.engine.TestEngine.class); // junit-platform-engine + addBundle(org.junit.platform.launcher.Launcher.class); // junit-platform-launcher + addBundle(org.junit.platform.runner.JUnitPlatform.class); // junit-platform-runner + addBundle(org.junit.platform.suite.api.Suite.class); // junit-platform-suite-api + addBundle(org.junit.platform.suite.commons.SuiteLauncherDiscoveryRequestBuilder.class); // junit-platform-suite-commons + addBundle(org.junit.platform.suite.engine.SuiteTestEngine.class); // junit-platform-suite-engine + addBundle(org.apiguardian.api.API.class); // org.apiguardian.api + addBundle(org.opentest4j.AssertionFailedError.class); // org.opentest4j + } + + @Override + public CustomSessionConfiguration setCascaded() { + this.cascaded = true; + return this; + } + + @Override + public CustomSessionConfiguration setReadOnly() { + this.readOnly = true; + return this; + } + + @Override + public CustomSessionConfiguration setConfigurationDirectory(Path configurationDirectory) { + Objects.requireNonNull(configurationDirectory); + this.configurationDirectory = configurationDirectory; + return this; + } + + private Path getConfigurationDirectory() throws IOException { + if (configurationDirectory == null) { + this.configurationDirectory = Files.createTempDirectory(null); + this.configurationDirectory.toFile().deleteOnExit(); + } + return configurationDirectory; + } + + @Override + public void prepareSession(Setup setup) throws IOException { + if (firstExecutedSession) { + // configuration area needs to be written on first start + overwriteConfigurationAreaWritability(setup); + } + setCustomConfigurationArea(setup); + if (firstExecutedSession) { + createOrRefreshConfigIni(); + } + } + + @Override + public void cleanupSession(Setup setup) { + if (firstExecutedSession) { + // after first session, use configuration area's readability configuration + removeConfigurationAreaWritabilityOverwrite(setup); + } + firstExecutedSession = false; + } + + private void overwriteConfigurationAreaWritability(Setup setup) { + setup.setSystemProperty(PROP_CONFIG_AREA_READ_ONLY, Boolean.FALSE.toString()); + } + + private void removeConfigurationAreaWritabilityOverwrite(Setup setup) { + setup.setSystemProperty(PROP_CONFIG_AREA_READ_ONLY, null); + } + + private void setCustomConfigurationArea(Setup setup) throws IOException { + // the base implementation will have set this to the host configuration + setup.setEclipseArgument(Setup.CONFIGURATION, null); + setup.setSystemProperty(InternalPlatform.PROP_CONFIG_AREA, getConfigurationDirectory().toString()); + } + + private void createOrRefreshConfigIni() throws IOException { + Properties contents = new Properties(); + contents.put(PROP_BUNDLES, String.join(",", getBundleUrls())); + contents.put(PROP_FRAMEWORK, getOsgiFrameworkBundleUrl()); + contents.put(PROP_BUNDLES_DEFAULT_START_LEVEL, "4"); + contents.put(PROP_INSTALL_AREA, Platform.getInstallLocation().getURL().toExternalForm()); + contents.put(PROP_CONFIG_CASCADED, Boolean.valueOf(cascaded).toString()); + contents.put(PROP_CONFIG_AREA_READ_ONLY, Boolean.valueOf(readOnly).toString()); + // save the properties + Path configINI = getConfigurationDirectory().resolve("config.ini"); + try (OutputStream out = Files.newOutputStream(configINI)) { + contents.store(out, null); + } + } + + @Override + public CustomSessionConfiguration addBundle(Class classFromBundle) { + Objects.requireNonNull(classFromBundle); + addBundle(classFromBundle, null); + return this; + } + + private void addBundle(Class classFromBundle, String suffix) { + Bundle bundle = FrameworkUtil.getBundle(classFromBundle); + Assert.assertNotNull("Class is not from a bundle: " + classFromBundle, bundle); + addBundle(bundle, suffix); + } + + @Override + public CustomSessionConfiguration addBundle(Bundle bundle) { + Objects.requireNonNull(bundle); + addBundle(bundle, ""); + return this; + } + + private void addBundle(Bundle bundle, String suffix) { + bundleReferences.add(new BundleReference(bundle, suffix)); + } + + private Collection getBundleUrls() { + assertThat(bundleReferences).as("check bundles are not empty").isNotEmpty(); + return bundleReferences.stream().map(BundleReference::toURL).collect(Collectors.toList()); + } + + private static String getOsgiFrameworkBundleUrl() { + Bundle osgiFrameworkBundle = FrameworkUtil.getBundle(CustomSessionConfigurationImpl.class).getBundleContext() + .getBundle(Constants.SYSTEM_BUNDLE_LOCATION); + BundleReference osgiFrameworkBundleReference = new BundleReference(osgiFrameworkBundle); + return osgiFrameworkBundleReference.toURL(); + } + + private record BundleReference(Bundle bundle, String suffix) { + BundleReference(Bundle bundle, String suffix) { + this.bundle = bundle; + this.suffix = suffix != null ? suffix : ""; + } + + BundleReference(Bundle bundle) { + this(bundle, null); + } + + String toURL() { + Optional location = FileLocator.getBundleFileLocation(bundle); + assertTrue("Unable to locate bundle with id: " + bundle.getSymbolicName(), location.isPresent()); + String externalForm; + try { + externalForm = location.get().toURI().toURL().toExternalForm(); + } catch (Exception e) { + throw new IllegalArgumentException("Failed to convert file to URL string:" + location.get(), e); + } + // workaround for bug 88070 + return "reference:" + externalForm + suffix; + } + } +} diff --git a/runtime/tests/org.eclipse.core.tests.harness/src/org/eclipse/core/tests/harness/session/customization/CustomSessionWorkspaceImpl.java b/runtime/tests/org.eclipse.core.tests.harness/src/org/eclipse/core/tests/harness/session/customization/CustomSessionWorkspaceImpl.java index 111648d3d47..e98f0677f72 100644 --- a/runtime/tests/org.eclipse.core.tests.harness/src/org/eclipse/core/tests/harness/session/customization/CustomSessionWorkspaceImpl.java +++ b/runtime/tests/org.eclipse.core.tests.harness/src/org/eclipse/core/tests/harness/session/customization/CustomSessionWorkspaceImpl.java @@ -29,7 +29,7 @@ public CustomSessionWorkspaceImpl() { @Override public CustomSessionWorkspace setWorkspaceDirectory(Path workspaceDirectory) { - Objects.nonNull(workspaceDirectory); + Objects.requireNonNull(workspaceDirectory); this.workspaceDirectory = workspaceDirectory; return this; } diff --git a/runtime/tests/org.eclipse.core.tests.runtime/META-INF/MANIFEST.MF b/runtime/tests/org.eclipse.core.tests.runtime/META-INF/MANIFEST.MF index a07c556715e..0a1d5b5b418 100644 --- a/runtime/tests/org.eclipse.core.tests.runtime/META-INF/MANIFEST.MF +++ b/runtime/tests/org.eclipse.core.tests.runtime/META-INF/MANIFEST.MF @@ -17,6 +17,7 @@ Require-Bundle: org.junit, Import-Package: org.assertj.core.api, org.junit.jupiter.api, org.junit.jupiter.api.extension, + org.junit.jupiter.api.function, org.junit.jupiter.api.io, org.junit.platform.suite.api Bundle-ActivationPolicy: lazy diff --git a/runtime/tests/org.eclipse.core.tests.runtime/src/org/eclipse/core/tests/internal/runtime/PlatformURLSessionTest.java b/runtime/tests/org.eclipse.core.tests.runtime/src/org/eclipse/core/tests/internal/runtime/PlatformURLSessionTest.java index b5b134e803e..0e185d1dd71 100644 --- a/runtime/tests/org.eclipse.core.tests.runtime/src/org/eclipse/core/tests/internal/runtime/PlatformURLSessionTest.java +++ b/runtime/tests/org.eclipse.core.tests.runtime/src/org/eclipse/core/tests/internal/runtime/PlatformURLSessionTest.java @@ -15,8 +15,11 @@ package org.eclipse.core.tests.internal.runtime; import static org.eclipse.core.tests.runtime.RuntimeTestsPlugin.PI_RUNTIME_TESTS; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertThrows; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.BufferedReader; import java.io.ByteArrayInputStream; @@ -28,14 +31,25 @@ import java.net.URL; import java.net.URLConnection; import java.util.stream.Collectors; -import junit.framework.Test; -import junit.framework.TestCase; import org.eclipse.core.runtime.FileLocator; import org.eclipse.core.runtime.Platform; -import org.eclipse.core.tests.session.ConfigurationSessionTestSuite; +import org.eclipse.core.tests.harness.session.SessionTestExtension; import org.eclipse.osgi.service.datalocation.Location; - -public class PlatformURLSessionTest extends TestCase { +import org.junit.jupiter.api.MethodOrderer; +import org.junit.jupiter.api.Order; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.api.TestInstance.Lifecycle; +import org.junit.jupiter.api.TestMethodOrder; +import org.junit.jupiter.api.extension.RegisterExtension; + +@TestMethodOrder(MethodOrderer.OrderAnnotation.class) +@TestInstance(Lifecycle.PER_CLASS) +public class PlatformURLSessionTest { + + @RegisterExtension + SessionTestExtension extension = SessionTestExtension.forPlugin(PI_RUNTIME_TESTS) + .withCustomization(SessionTestExtension.createCustomConfiguration().setCascaded().setReadOnly()).create(); private static final String CONFIG_URL = "platform:/config/" + PI_RUNTIME_TESTS + "/"; private static final String DATA_CHILD = "child"; @@ -45,41 +59,28 @@ public class PlatformURLSessionTest extends TestCase { private static final String FILE_CHILD_ONLY = "child.txt"; private static final String FILE_PARENT_ONLY = "parent.txt"; - public static void assertEquals(String tag, URL expected, URL actual, boolean external) { - if (external) { - assertEquals(tag, expected, actual); - return; - } - assertEquals(tag + " different protocol", expected.getProtocol(), actual.getProtocol()); - assertEquals(tag + " different host", expected.getHost(), actual.getHost()); - assertEquals(tag + " different path", expected.getPath(), actual.getPath()); - assertEquals(tag + " different port", expected.getPort(), actual.getPort()); - } - - private static String readContents(String tag, URL url) throws IOException { - try (BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream()))) { - return reader.lines().collect(Collectors.joining()); - } - } - - public static Test suite() { - ConfigurationSessionTestSuite suite = new ConfigurationSessionTestSuite(PI_RUNTIME_TESTS, PlatformURLSessionTest.class); - suite.setReadOnly(true); - suite.setCascaded(true); - suite.addMinimalBundleSet(); - suite.addThisBundle(); - return suite; - } - - public PlatformURLSessionTest(String name) { - super(name); + /** + * Creates test data in both child and parent configurations. + */ + @Order(0) + @Test + public void test0FirstSession() throws IOException { + createData(); + // try to modify a file in the parent configuration area - should fail + URL configURL = new URL(CONFIG_URL + FILE_ANOTHER_PARENT_ONLY); + URLConnection connection = configURL.openConnection(); + connection.setDoOutput(true); + assertThrows(IOException.class, () -> { + try (var o = connection.getOutputStream()) { + } + }); } - private void createData(String tag) throws IOException { + private void createData() throws IOException { // create some data for this and following test cases URL childConfigURL = Platform.getConfigurationLocation().getURL(); // tests run with file based configuration - assertEquals(tag + ".1", "file", childConfigURL.getProtocol()); + assertEquals("file", childConfigURL.getProtocol()); File childConfigPrivateDir = new File(childConfigURL.getPath(), PI_RUNTIME_TESTS); childConfigPrivateDir.mkdirs(); createFileWithContents(new File(childConfigPrivateDir, FILE_CHILD_ONLY), DATA_CHILD); @@ -87,10 +88,10 @@ private void createData(String tag) throws IOException { Location parent = Platform.getConfigurationLocation().getParentLocation(); // tests run with cascaded configuration - assertNotNull(tag + ".3", parent); + assertNotNull(parent); URL parentConfigURL = parent.getURL(); // tests run with file based configuration - assertEquals(tag + ".4", "file", parentConfigURL.getProtocol()); + assertEquals("file", parentConfigURL.getProtocol()); File parentConfigPrivateDir = new File(parentConfigURL.getPath(), PI_RUNTIME_TESTS); parentConfigPrivateDir.mkdirs(); createFileWithContents(new File(parentConfigPrivateDir, FILE_PARENT_ONLY), DATA_PARENT); @@ -99,27 +100,15 @@ private void createData(String tag) throws IOException { } private void createFileWithContents(File file, String contents) throws IOException { - try (InputStream input = new ByteArrayInputStream(contents.getBytes()); FileOutputStream output = new FileOutputStream(file)) { + try (InputStream input = new ByteArrayInputStream(contents.getBytes()); + FileOutputStream output = new FileOutputStream(file)) { input.transferTo(output); } } - /** - * Creates test data in both child and parent configurations. - */ - public void test0FirstSession() throws IOException { - createData("1"); - // try to modify a file in the parent configuration area - should fail - URL configURL = new URL(CONFIG_URL + FILE_ANOTHER_PARENT_ONLY); - URLConnection connection = configURL.openConnection(); - connection.setDoOutput(true); - assertThrows(IOException.class, () -> { - try (var o = connection.getOutputStream()) { - } - }); - } - + @Order(1) + @Test public void test1OutputOnReadOnly() throws IOException { // try to modify a file in the configuration area - should fail URL configURL = new URL(CONFIG_URL + FILE_CHILD_ONLY); @@ -131,19 +120,27 @@ public void test1OutputOnReadOnly() throws IOException { }); } + @Order(2) + @Test public void test2Resolution() throws IOException { URL parent = new URL(CONFIG_URL + FILE_PARENT_ONLY); URL child = new URL(CONFIG_URL + FILE_CHILD_ONLY); URL both = new URL(CONFIG_URL + FILE_BOTH_PARENT_AND_CHILD); URL none = new URL(CONFIG_URL + "none.txt"); - assertEquals("1.0", DATA_PARENT, readContents("1.1", parent)); - assertEquals("2.0", DATA_CHILD, readContents("2.1", child)); - assertEquals("3.0", DATA_CHILD, readContents("3.1", both)); + assertEquals(DATA_PARENT, readContents("1.1", parent)); + assertEquals(DATA_CHILD, readContents("2.1", child)); + assertEquals(DATA_CHILD, readContents("3.1", both)); URL resolvedURL = FileLocator.resolve(none); - assertNotEquals("4.1", none, resolvedURL); - assertTrue("4.2", + assertNotEquals(none, resolvedURL); + assertTrue( resolvedURL.toExternalForm().startsWith(Platform.getConfigurationLocation().getURL().toExternalForm())); } + private static String readContents(String tag, URL url) throws IOException { + try (BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream()))) { + return reader.lines().collect(Collectors.joining()); + } + } + }