Skip to content

Commit

Permalink
Add test annotation for changing config profiles
Browse files Browse the repository at this point in the history
  • Loading branch information
adrienlauer committed Jan 26, 2018
1 parent 70c1deb commit 58f0f3d
Show file tree
Hide file tree
Showing 12 changed files with 221 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,17 +41,10 @@ public void process(MapNode configuration) {
Matcher matcher = keyWithProfilePattern.matcher(namedNode.name());
if (matcher.matches()) {
if (parseProfiles(matcher.group(2)).stream().noneMatch(activeProfiles::contains)) {
List<String> strings = toRemove.get(mapNode);
if (strings == null) {
toRemove.put(mapNode, strings = new ArrayList<>());
}
strings.add(namedNode.name());
toRemove.computeIfAbsent(mapNode, k -> new ArrayList<>()).add(namedNode.name());
} else {
Map<String, String> move = moves.get(mapNode);
if (move == null) {
moves.put(mapNode, move = new HashMap<>());
}
move.put(matcher.group(0), matcher.group(1));
moves.computeIfAbsent(mapNode, k -> new HashMap<>())
.put(matcher.group(0), matcher.group(1));
}
}
}));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@
import org.junit.Test;
import org.junit.runner.RunWith;
import org.seedstack.seed.Application;
import org.seedstack.seed.testing.ConfigurationProfiles;
import org.seedstack.seed.testing.LaunchMode;
import org.seedstack.seed.testing.LaunchWith;
import org.seedstack.seed.testing.SystemProperty;
import org.seedstack.seed.testing.junit4.SeedITRunner;

@RunWith(SeedITRunner.class)
Expand All @@ -31,26 +31,26 @@ public void noProfile() {
}

@Test
@SystemProperty(name = "seedstack.profiles", value = "dev")
@ConfigurationProfiles("dev")
public void devProfile() {
Assertions.assertThat(getValue("testProperty")).isEqualTo("devValue");
}

@Test
@SystemProperty(name = "seedstack.profiles", value = "preprod")
@ConfigurationProfiles("preprod")
public void preprodProfile() {
Assertions.assertThat(getValue("testProperty")).isEqualTo("preprodValue");
}

@Test
@SystemProperty(name = "seedstack.profiles", value = "prod")
@ConfigurationProfiles("prod")
public void prodProfile() {
Assertions.assertThat(getValue("testProperty.subProperty1")).isEqualTo("prodValue");
Assertions.assertThat(getValue("testProperty.subProperty2")).isEqualTo("prodValue");
}

@Test
@SystemProperty(name = "seedstack.profiles", value = "dev, debug")
@ConfigurationProfiles({"dev", "debug"})
public void devDebugProfiles() {
Assertions.assertThat(getValue("testProperty")).isEqualTo("devValue");
Assertions.assertThat(getValue("debugMode")).isEqualTo("true");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/*
* Copyright © 2013-2018, The SeedStack authors <http://seedstack.org>
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

package org.seedstack.seed.testing.internal;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicBoolean;
import org.seedstack.seed.testing.ConfigurationProfiles;
import org.seedstack.seed.testing.spi.TestContext;
import org.seedstack.seed.testing.spi.TestPlugin;

public class ConfigurationProfilesTestPlugin implements TestPlugin {
private static final String DUMMY_VALUE = "__DUMMY__";
private static final String SEEDSTACK_PROFILES = "seedstack.profiles";
private static String previousValue;

@Override
public boolean enabled(TestContext testContext) {
return true;
}

@Override
public void beforeLaunch(TestContext testContext) {
overrideProfiles(testContext);
}

@Override
public void afterShutdown(TestContext testContext) {
restoreProfiles();
}

private static synchronized void overrideProfiles(TestContext testContext) {
Optional<String> profiles = gatherConfigurationProfiles(testContext);
if (profiles.isPresent()) {
if (previousValue != null) {
throw new IllegalStateException("Attempt to override configuration profiles concurrently");
} else {
previousValue = System.getProperty(SEEDSTACK_PROFILES, DUMMY_VALUE);
System.setProperty(SEEDSTACK_PROFILES, profiles.get());
}
}
}

private static synchronized void restoreProfiles() {
if (previousValue != null) {
try {
if (DUMMY_VALUE.equals(previousValue)) {
System.clearProperty(SEEDSTACK_PROFILES);
} else {
System.setProperty(SEEDSTACK_PROFILES, previousValue);
}
} finally {
previousValue = null;
}
}
}

private static Optional<String> gatherConfigurationProfiles(TestContext testContext) {
List<String> allProfiles = new ArrayList<>();
AtomicBoolean annotationPresent = new AtomicBoolean(false);

// Configuration profiles on the class
ConfigurationProfiles classProfiles = testContext.testClass().getAnnotation(ConfigurationProfiles.class);
if (classProfiles != null) {
annotationPresent.set(true);
allProfiles.addAll(Arrays.asList(classProfiles.value()));
}

// Configuration profiles on the method (taking precedence)
testContext.testMethod().ifPresent(testMethod -> {
ConfigurationProfiles methodProfiles = testMethod.getAnnotation(ConfigurationProfiles.class);
if (methodProfiles != null) {
annotationPresent.set(true);
if (!methodProfiles.append()) {
allProfiles.clear();
}
allProfiles.addAll(Arrays.asList(methodProfiles.value()));
}
});

return annotationPresent.get() ? Optional.of(String.join(",", allProfiles)) : Optional.empty();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

package org.seedstack.seed.testing.internal;

import java.util.HashMap;
import java.util.Map;
import org.seedstack.seed.testing.ConfigurationProperty;
import org.seedstack.seed.testing.spi.TestPlugin;
import org.seedstack.seed.testing.spi.TestContext;
import org.seedstack.seed.testing.spi.TestPlugin;

public class ConfigurationPropertiesTestPlugin implements TestPlugin {
@Override
Expand All @@ -26,16 +27,27 @@ public Map<String, String> configurationProperties(TestContext testContext) {
// Configuration property on the class
for (ConfigurationProperty configProperty : testContext.testClass()
.getAnnotationsByType(ConfigurationProperty.class)) {
configuration.put(configProperty.name(), configProperty.value());
configuration.put(buildPropertyName(configProperty), configProperty.value());
}

// Configuration property on the method (completing/overriding class configuration properties)
testContext.testMethod().ifPresent(testMethod -> {
for (ConfigurationProperty configProperty : testMethod.getAnnotationsByType(ConfigurationProperty.class)) {
configuration.put(configProperty.name(), configProperty.value());
configuration.put(buildPropertyName(configProperty), configProperty.value());
}
});

return configuration;
}

private String buildPropertyName(ConfigurationProperty configProperty) {
String[] profiles = configProperty.profiles();
String name;
if (profiles.length > 0) {
name = String.format("%s<%s>", configProperty.name(), String.join(",", profiles));
} else {
name = configProperty.name();
}
return name;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,17 @@ public void afterShutdown(TestContext testContext) {
}

private static synchronized void overrideProperties(TestContext testContext) {
if (previousProperties != null) {
throw new IllegalStateException("Attempt to override system properties concurrently");
}
previousProperties = new HashMap<>();
Properties overridingProperties = gatherSystemProperties(testContext);
for (String propertyName : overridingProperties.stringPropertyNames()) {
previousProperties.put(propertyName, System.getProperty(propertyName));
System.setProperty(propertyName, overridingProperties.getProperty(propertyName));
if (!overridingProperties.isEmpty()) {
if (previousProperties != null) {
throw new IllegalStateException("Attempt to override system properties concurrently");
} else {
previousProperties = new HashMap<>();
for (String propertyName : overridingProperties.stringPropertyNames()) {
previousProperties.put(propertyName, System.getProperty(propertyName));
System.setProperty(propertyName, overridingProperties.getProperty(propertyName));
}
}
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
org.seedstack.seed.testing.internal.ArgumentsTestPlugin
org.seedstack.seed.testing.internal.ConfigurationPropertiesTestPlugin
org.seedstack.seed.testing.internal.ConfigurationProfilesTestPlugin
org.seedstack.seed.testing.internal.ExpectedTestPlugin
org.seedstack.seed.testing.internal.KernelParametersTestPlugin
org.seedstack.seed.testing.internal.LaunchTestPlugin
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@
import io.nuun.kernel.api.Kernel;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Optional;
import java.util.ServiceLoader;
Expand Down Expand Up @@ -47,8 +49,8 @@ public class JUnit4Runner extends BlockJUnit4ClassRunner {
.map(c -> (Class<? extends SeedLauncher>) c.asSubclass(SeedLauncher.class))
.orElse(null);
private final JUnit4TestContext testContext;
private final List<TestPlugin> plugins = new ArrayList<>();
private final List<Class<? extends TestDecorator>> decorators = new ArrayList<>();
private final List<TestPlugin> plugins;
private final List<Class<? extends TestDecorator>> decorators;
private final LaunchMode launchMode;
private SeedLauncher seedLauncher;

Expand All @@ -59,17 +61,21 @@ public JUnit4Runner(Class<?> someClass) throws InitializationError {
testContext = new JUnit4TestContext(someClass);

// Discover test plugins
List<TestPlugin> discoveredPlugins = new ArrayList<>();
for (TestPlugin testPlugin : ServiceLoader.load(TestPlugin.class,
ClassLoaders.findMostCompleteClassLoader(JUnit4Runner.class))) {
if (testPlugin.enabled(testContext)) {
plugins.add(testPlugin);
discoveredPlugins.add(testPlugin);
}
}
sortByPriority(plugins, PriorityUtils::priorityOfClassOf);
sortByPriority(discoveredPlugins, PriorityUtils::priorityOfClassOf);
plugins = Collections.unmodifiableList(discoveredPlugins);

// Discover decorators
plugins.forEach(plugin -> decorators.addAll(plugin.decorators()));
sortByPriority(decorators, PriorityUtils::priorityOf);
List<Class<? extends TestDecorator>> discoveredDecorators = new ArrayList<>();
plugins.forEach(plugin -> discoveredDecorators.addAll(plugin.decorators()));
sortByPriority(discoveredDecorators, PriorityUtils::priorityOf);
decorators = Collections.unmodifiableList(discoveredDecorators);

// Determine launch mode
launchMode = gatherLaunchMode();
Expand Down Expand Up @@ -110,8 +116,11 @@ protected void runChild(FrameworkMethod method, RunNotifier notifier) {
decoratorInstances.forEach(decorator -> decorator.beforeTest(testContext));
super.runChild(method, notifier);
} finally {
// Invoke decorator afterTest()
decoratorInstances.forEach(decorator -> decorator.afterTest(testContext));
// Invoke decorator afterTest() in reverse order
ListIterator<? extends TestDecorator> it = decoratorInstances.listIterator(decoratorInstances.size());
while (it.hasPrevious()) {
it.previous().afterTest(testContext);
}
}
} catch (Throwable t) {
notifyFailure(t, notifier);
Expand Down Expand Up @@ -332,8 +341,11 @@ private void doStop() {
testContext.setKernel(null);
seedLauncher = null;

// Invoke plugin afterShutdown()
plugins.forEach(plugin -> plugin.afterShutdown(testContext));
// Invoke plugin afterShutdown() in reverse order
ListIterator<TestPlugin> it = plugins.listIterator(plugins.size());
while (it.hasPrevious()) {
it.previous().afterShutdown(testContext);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import org.junit.runner.RunWith;
import org.seedstack.seed.Application;
import org.seedstack.seed.testing.Arguments;
import org.seedstack.seed.testing.ConfigurationProfiles;
import org.seedstack.seed.testing.ConfigurationProperty;
import org.seedstack.seed.testing.KernelParameter;
import org.seedstack.seed.testing.LaunchWith;
Expand All @@ -23,6 +24,7 @@

@RunWith(SeedITRunner.class)
@ConfigurationProperty(name = "someTestKey", value = "testValue")
@ConfigurationProfiles({"profile1", "profile2"})
@KernelParameter(name = "seedstack.config.someKernelParam", value = "testValue")
@Arguments({"testArg", "-o", "testOption"})
@SystemProperty(name = "seedstack.someTestProperty", value = "testValue")
Expand Down Expand Up @@ -57,4 +59,9 @@ public void arguments() {
public void systemProperty() {
assertThat(System.getProperty("seedstack.someTestProperty")).isEqualTo("testValue");
}

@Test
public void configurationProfiles() {
assertThat(System.getProperty("seedstack.profiles")).isEqualTo("profile1,profile2");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import org.junit.runner.RunWith;
import org.seedstack.seed.Application;
import org.seedstack.seed.testing.Arguments;
import org.seedstack.seed.testing.ConfigurationProfiles;
import org.seedstack.seed.testing.ConfigurationProperty;
import org.seedstack.seed.testing.KernelParameter;
import org.seedstack.seed.testing.LaunchMode;
Expand All @@ -27,6 +28,7 @@
@RunWith(SeedITRunner.class)
@LaunchWith(value = TestITLauncher.class, mode = LaunchMode.PER_TEST)
@ConfigurationProperty(name = "someTestKey", value = "testValue")
@ConfigurationProfiles({"profile1", "profile2"})
@KernelParameter(name = "seedstack.config.someKernelParam", value = "testValue")
@Arguments({"testArg", "-o", "testOption"})
@SystemProperty(name = "seedstack.someTestProperty", value = "testValue")
Expand Down Expand Up @@ -127,4 +129,21 @@ public void appendSystemProperty() {
public void overrideSystemProperty() {
assertThat(System.getProperty("seedstack.someTestProperty")).isEqualTo("testValue2");
}

@Test
public void configurationProfiles() {
assertThat(System.getProperty("seedstack.profiles")).isEqualTo("profile1,profile2");
}

@Test
@ConfigurationProfiles("profile3")
public void appendConfigurationProfiles() {
assertThat(System.getProperty("seedstack.profiles")).isEqualTo("profile1,profile2,profile3");
}

@Test
@ConfigurationProfiles(value = "profile3", append = false)
public void overrideConfigurationProfiles() {
assertThat(System.getProperty("seedstack.profiles")).isEqualTo("profile3");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

package org.seedstack.seed.testing.junit4.fixtures;

import java.io.File;
Expand Down

0 comments on commit 58f0f3d

Please sign in to comment.