Skip to content

Commit

Permalink
ci: use better default options for NeonBee in tests
Browse files Browse the repository at this point in the history
During investigation of build problems the issue was located that in our tests we have had multiple different ways we used to initialize NeonBee sometimes with and sometimes without a associated NeonBee instance:

- NeonBee.create
- registerNeonBeeMock
- NeonBeeExtension/NeonBeeInstanceConfiguration

Each time NeonBee was initialized we used a different set of options. Especially for tests particular set of NeonBeeOptions is important, e.g. not to scan the class path or not starting the WatchVerticles. Because of the different options how to start Vert.x these options have often been neglected. This commit uses the same set of default options for all the different ways a NeonBee instance is created.

Now when creating a request (with the NeonBeeTestBase.createRequest method), in case the server port is specified in the options, it is preferred over the server port in the server verticle configuration file.
  • Loading branch information
kristian committed Oct 4, 2021
1 parent a2c3a5d commit 1412851
Show file tree
Hide file tree
Showing 14 changed files with 347 additions and 147 deletions.
2 changes: 1 addition & 1 deletion src/main/java/io/neonbee/NeonBee.java
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ public class NeonBee {

private static final String SHARED_MAP_NAME = "#sharedMap";

private static final int NUMBER_DEFAULT_INSTANCES = 16;
private static final int NUMBER_DEFAULT_INSTANCES = 4;

@VisibleForTesting
NeonBeeConfig config;
Expand Down
43 changes: 9 additions & 34 deletions src/test/java/io/neonbee/NeonBeeExtension.java
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
package io.neonbee;

import static ch.qos.logback.classic.util.ContextInitializer.CONFIG_FILE_PROPERTY;
import static io.neonbee.test.helper.OptionsHelper.options;
import static java.lang.System.setProperty;

import java.io.IOException;
import java.lang.reflect.Method;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
Expand All @@ -34,10 +31,8 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.Strings;
import com.hazelcast.core.LifecycleService;

import io.neonbee.test.helper.SystemHelper;
import io.vertx.core.Vertx;
import io.vertx.core.VertxException;
import io.vertx.core.impl.VertxImpl;
Expand All @@ -46,7 +41,7 @@
import io.vertx.junit5.VertxTestContext;
import io.vertx.spi.cluster.hazelcast.HazelcastClusterManager;

@SuppressWarnings("rawtypes")
@SuppressWarnings({ "rawtypes", "PMD.GodClass" })
public class NeonBeeExtension implements ParameterResolver, BeforeTestExecutionCallback, AfterTestExecutionCallback,
BeforeEachCallback, AfterEachCallback, BeforeAllCallback, AfterAllCallback {

Expand Down Expand Up @@ -85,14 +80,16 @@ public Object resolveParameter(ParameterContext parameterContext, ExtensionConte
throws ParameterResolutionException {
Class<?> type = parameterContext.getParameter().getType();
if (type == NeonBee.class) {
NeonBeeOptions options;

try {
NeonBeeOptions options = options(parameterContext);
return unpack(store(extensionContext).getOrComputeIfAbsent(options.getInstanceName(),
key -> new ScopedObject<NeonBee>(createNeonBee(options), closeNeonBee())));
} catch (IOException e) {
LOGGER.error("Error while finding a free port for server verticle.", e);
options = options(parameterContext.findAnnotation(NeonBeeInstanceConfiguration.class));
} catch (RuntimeException e) {
throw new ParameterResolutionException("Error while finding a free port for server verticle.", e);
}

return unpack(store(extensionContext).getOrComputeIfAbsent(options.getInstanceName(),
key -> new ScopedObject<NeonBee>(createNeonBee(options), closeNeonBee())));
}
if (type == VertxTestContext.class) {
return newTestContext(extensionContext);
Expand All @@ -107,28 +104,6 @@ private Object unpack(Object object) {
return object;
}

private NeonBeeOptions options(ParameterContext parameterContext) throws IOException {
NeonBeeOptions.Mutable options = new NeonBeeOptions.Mutable();
NeonBeeInstanceConfiguration config =
parameterContext.getParameter().getAnnotation(NeonBeeInstanceConfiguration.class);
if (config == null) {
return options.setWorkingDirectory(Paths.get("./working_dir/")).setServerPort(SystemHelper.getFreePort())
.setActiveProfiles(List.<NeonBeeProfile>of());
} else {
options.setActiveProfiles(Arrays.<NeonBeeProfile>asList(config.activeProfiles()))
.setClusterConfigResource(config.clusterConfigFile()).setClustered(config.clustered())
.setClusterPort(config.clusterPort()).setDisableJobScheduling(config.disableJobScheduling())
.setDoNotWatchFiles(config.doNotWatchFiles()).setEventLoopPoolSize(config.eventLoopPoolSize())
.setIgnoreClassPath(config.ignoreClassPath()).setServerPort(SystemHelper.getFreePort())
.setWorkerPoolSize(config.workerPoolSize())
.setWorkingDirectory(Paths.get(config.workingDirectoryPath()));
if (!Strings.isNullOrEmpty(config.instanceName())) {
options.setInstanceName(config.instanceName());
}
}
return options;
}

private VertxTestContext newTestContext(ExtensionContext extensionContext) {
Store store = store(extensionContext);
ContextList contexts = (ContextList) store.getOrComputeIfAbsent(TEST_CONTEXT_KEY, key -> new ContextList());
Expand Down
35 changes: 18 additions & 17 deletions src/test/java/io/neonbee/NeonBeeExtensionBasedTest.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package io.neonbee;

import static com.google.common.truth.Truth.assertThat;
import static io.neonbee.NeonBeeProfile.ALL;
import static io.neonbee.NeonBeeProfile.CORE;
import static io.neonbee.NeonBeeProfile.STABLE;
import static io.neonbee.NeonBeeProfile.WEB;
import static io.vertx.core.Future.succeededFuture;

import java.util.concurrent.TimeUnit;
Expand All @@ -24,21 +28,20 @@

@ExtendWith(NeonBeeExtension.class)
class NeonBeeExtensionBasedTest {

@Test
@Timeout(value = 10, timeUnit = TimeUnit.SECONDS)
@DisplayName("NeonBee should start with default options / default working directory")
void testNeonBeeDefault(@NeonBeeInstanceConfiguration(activeProfiles = NeonBeeProfile.ALL) NeonBee neonBee) {
void testNeonBeeDefault(@NeonBeeInstanceConfiguration(activeProfiles = ALL) NeonBee neonBee) {
assertThat(neonBee).isNotNull();
assertThat(isClustered(neonBee)).isFalse();
}

@Test
@Timeout(value = 10, timeUnit = TimeUnit.SECONDS)
@DisplayName("NeonBee should start with NONE profile. Only system verticle should be deployed")
@DisplayName("NeonBee should start with ALL profile by default")
void testNeonBeeWithNoneProfile(NeonBee neonBee) {
assertThat(neonBee).isNotNull();
assertThat(neonBee.getOptions().getActiveProfiles()).isEmpty();
assertThat(neonBee.getOptions().getActiveProfiles()).containsExactly(ALL);
assertThat(isClustered(neonBee)).isFalse();
}

Expand All @@ -53,11 +56,10 @@ void testSameNeonBeeInstance(@NeonBeeInstanceConfiguration(instanceName = "node1
@Test
@Timeout(value = 10, timeUnit = TimeUnit.SECONDS)
@DisplayName("NeonBee should start with CORE profile and deploy CoreDataVerticle")
void testNeonBeeWithCoreDeployment(
@NeonBeeInstanceConfiguration(activeProfiles = NeonBeeProfile.CORE) NeonBee neonBee,
void testNeonBeeWithCoreDeployment(@NeonBeeInstanceConfiguration(activeProfiles = CORE) NeonBee neonBee,
VertxTestContext testContext) {
assertThat(neonBee).isNotNull();
assertThat(neonBee.getOptions().getActiveProfiles()).contains(NeonBeeProfile.CORE);
assertThat(neonBee.getOptions().getActiveProfiles()).contains(CORE);
Vertx vertx = neonBee.getVertx();
vertx.deployVerticle(new CoreDataVerticle(), testContext.succeeding(id -> {
assertThat(DeploymentHelper.isVerticleDeployed(vertx, CoreDataVerticle.class)).isTrue();
Expand All @@ -68,8 +70,8 @@ void testNeonBeeWithCoreDeployment(
@Test
@Timeout(value = 10, timeUnit = TimeUnit.SECONDS)
@DisplayName("NeonBee should start with NONE profile and deploy CoreDataVerticle manually")
void testNeonBeeWithNoneDeploymentAndManualDeployment(@NeonBeeInstanceConfiguration() NeonBee neonBee,
VertxTestContext testContext) {
void testNeonBeeWithNoneDeploymentAndManualDeployment(
@NeonBeeInstanceConfiguration(activeProfiles = {}) NeonBee neonBee, VertxTestContext testContext) {
assertThat(neonBee).isNotNull();
assertThat(neonBee.getOptions().getActiveProfiles()).isEmpty();
Vertx vertx = neonBee.getVertx();
Expand All @@ -83,29 +85,28 @@ void testNeonBeeWithNoneDeploymentAndManualDeployment(@NeonBeeInstanceConfigurat
@Test
@Timeout(value = 20, timeUnit = TimeUnit.SECONDS)
@DisplayName("3 NeonBee instances with WEB, CORE and STABLE profiles should be started and join one cluster.")
void testNeonBeeWithClusters(
@NeonBeeInstanceConfiguration(activeProfiles = NeonBeeProfile.WEB, clustered = true) NeonBee web,
@NeonBeeInstanceConfiguration(activeProfiles = NeonBeeProfile.CORE, clustered = true) NeonBee core,
@NeonBeeInstanceConfiguration(activeProfiles = NeonBeeProfile.STABLE, clustered = true) NeonBee stable) {
void testNeonBeeWithClusters(@NeonBeeInstanceConfiguration(activeProfiles = WEB, clustered = true) NeonBee web,
@NeonBeeInstanceConfiguration(activeProfiles = CORE, clustered = true) NeonBee core,
@NeonBeeInstanceConfiguration(activeProfiles = STABLE, clustered = true) NeonBee stable) {
assertThat(web).isNotNull();
assertThat(web.getOptions().getActiveProfiles()).contains(NeonBeeProfile.WEB);
assertThat(web.getOptions().getActiveProfiles()).contains(WEB);
assertThat(web.getVertx().isClustered()).isTrue();
assertThat(isClustered(web)).isTrue();

assertThat(core).isNotNull();
assertThat(core.getOptions().getActiveProfiles()).contains(NeonBeeProfile.CORE);
assertThat(core.getOptions().getActiveProfiles()).contains(CORE);
assertThat(core.getVertx().isClustered()).isTrue();
assertThat(isClustered(core)).isTrue();

assertThat(stable).isNotNull();
assertThat(stable.getOptions().getActiveProfiles()).contains(NeonBeeProfile.STABLE);
assertThat(stable.getOptions().getActiveProfiles()).contains(STABLE);
assertThat(stable.getVertx().isClustered()).isTrue();
assertThat(isClustered(stable)).isTrue();

assertThat(Hazelcast.getAllHazelcastInstances().size()).isAtLeast(3);
}

@NeonBeeDeployable(profile = NeonBeeProfile.CORE)
@NeonBeeDeployable(profile = CORE)
public static class CoreDataVerticle extends DataVerticle<String> {
private static final String NAME = "CoreDataVerticle";

Expand Down
10 changes: 6 additions & 4 deletions src/test/java/io/neonbee/NeonBeeInstanceConfiguration.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package io.neonbee;

import static io.neonbee.NeonBeeProfile.ALL;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
Expand All @@ -16,9 +18,9 @@
@Target(ElementType.PARAMETER)
@SuppressWarnings("checkstyle:MissingJavadocMethod")
public @interface NeonBeeInstanceConfiguration {
int eventLoopPoolSize() default 4;
int eventLoopPoolSize() default 1;

int workerPoolSize() default 4;
int workerPoolSize() default 1;

int clusterPort() default 0;

Expand All @@ -34,7 +36,7 @@

boolean doNotWatchFiles() default true;

boolean disableJobScheduling() default false;
boolean disableJobScheduling() default true;

NeonBeeProfile[] activeProfiles() default {};
NeonBeeProfile[] activeProfiles() default { ALL };
}
84 changes: 78 additions & 6 deletions src/test/java/io/neonbee/NeonBeeMockHelper.java
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
package io.neonbee;

import static io.vertx.core.Future.succeededFuture;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;

import java.util.Optional;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.neonbee.config.NeonBeeConfig;
import io.neonbee.test.helper.OptionsHelper;
import io.neonbee.test.helper.ReflectionHelper;
import io.vertx.core.Future;
import io.vertx.core.Vertx;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.file.FileSystem;
Expand Down Expand Up @@ -40,20 +45,84 @@ public static Vertx defaultVertxMock() {
}

/**
* Convenience method for registering a new (empty) NeonBee instance for an (existing) Vert.x mock.
* Convenience method for creating a new NeonBee instance for an (existing) Vert.x mock or instance.
*
* Attention: This method actually does NOT care whether the provided Vert.x instance is actually a mock or not. In
* case you pass a "real" Vert.x instance, NeonBee will more or less start normally with the options / config
* provided. This includes, among other things, deployment of all system verticles.
*
* @param vertx the Vert.x instance
* @return the mocked NeonBee instance
*/
public static Future<NeonBee> createNeonBee(Vertx vertx) {
return createNeonBee(vertx, null);
}

/**
* Convenience method for creating a new NeonBee instance for an (existing) Vert.x mock or instance.
*
* Attention: This method actually does NOT care whether the provided Vert.x instance is actually a mock or not. In
* case you pass a "real" Vert.x instance, NeonBee will more or less start normally with the options / config
* provided. This includes, among other things, deployment of all system verticles.
*
* @param vertx the Vert.x instance
* @param options the NeonBee options
* @return the mocked NeonBee instance
*/
public static Future<NeonBee> createNeonBee(Vertx vertx, NeonBeeOptions options) {
return NeonBee.create(() -> succeededFuture(vertx), options);
}

/**
* Convenience method for registering a new (empty) NeonBee instance for an (existing) Vert.x mock or instance.
*
* Attention: This method actually does NOT care whether the provided Vert.x instance is actually a mock or not. In
* case you pass a "real" Vert.x instance, NeonBee will more or less start normally with the options / config
* provided. This includes, among other things, deployment of all system verticles.
*
* @param vertx the Vert.x instance
* @return the mocked NeonBee instance
*/
public static NeonBee registerNeonBeeMock(Vertx vertx) {
return registerNeonBeeMock(vertx, null, null);
}

/**
* Convenience method for registering a new (empty) NeonBee instance for an (existing) Vert.x mock or instance.
*
* Attention: This method actually does NOT care whether the provided Vert.x instance is actually a mock or not. In
* case you pass a "real" Vert.x instance, NeonBee will more or less start normally with the options / config
* provided. This includes, among other things, deployment of all system verticles.
*
* @param vertx the Vert.x instance
* @param options the NeonBee options
* @return the mocked NeonBee instance
*/
public static NeonBee registerNeonBeeMock(Vertx vertx, NeonBeeOptions options) {
createLogger(); // the logger is only created internally, create one manually if required
return registerNeonBeeMock(vertx, options, null);
}

return new NeonBee(vertx, options);
/**
* Convenience method for registering a new (empty) NeonBee instance for an (existing) Vert.x mock or instance.
*
* Attention: This method actually does NOT care whether the provided Vert.x instance is actually a mock or not. In
* case you pass a "real" Vert.x instance, NeonBee will more or less start normally with the options / config
* provided. This includes, among other things, deployment of all system verticles.
*
* @param vertx the Vert.x instance
* @param config the NeonBee config
* @return the mocked NeonBee instance
*/
public static NeonBee registerNeonBeeMock(Vertx vertx, NeonBeeConfig config) {
return registerNeonBeeMock(vertx, null, config);
}

/**
* Convenience method for registering a new (empty) NeonBee instance for an (existing) Vert.x mock.
* Convenience method for registering a new (empty) NeonBee instance for an (existing) Vert.x mock or instance.
*
* Attention: This method actually does NOT care whether the provided Vert.x instance is actually a mock or not. In
* case you pass a "real" Vert.x instance, NeonBee will more or less start normally with the options / config
* provided. This includes, among other things, deployment of all system verticles.
*
* @param vertx the Vert.x instance
* @param options the NeonBee options
Expand All @@ -63,8 +132,11 @@ public static NeonBee registerNeonBeeMock(Vertx vertx, NeonBeeOptions options) {
public static NeonBee registerNeonBeeMock(Vertx vertx, NeonBeeOptions options, NeonBeeConfig config) {
createLogger(); // the logger is only created internally, create one manually if required

NeonBee neonBee = new NeonBee(vertx, options);
neonBee.config = config;
NeonBee neonBee = new NeonBee(vertx, Optional.ofNullable(options).orElseGet(OptionsHelper::defaultOptions));
if (config != null) {
neonBee.config = config;
}

return neonBee;
}

Expand Down
11 changes: 4 additions & 7 deletions src/test/java/io/neonbee/NeonBeeTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,10 @@
import static io.neonbee.NeonBeeProfile.INCUBATOR;
import static io.neonbee.NeonBeeProfile.STABLE;
import static io.neonbee.internal.helper.StringHelper.EMPTY;
import static org.mockito.Mockito.mock;
import static io.neonbee.test.helper.OptionsHelper.defaultOptions;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import java.lang.reflect.Method;
import java.nio.file.Files;
import java.util.List;
import java.util.concurrent.TimeUnit;

Expand Down Expand Up @@ -79,7 +77,7 @@ void testStartWithEmptyWorkingDirectory() {
@Timeout(value = 2, timeUnit = TimeUnit.SECONDS)
@DisplayName("Vert.x should start in non-clustered mode. ")
void testStandaloneInitialization(VertxTestContext testContext) {
NeonBee.newVertx(new NeonBeeOptions.Mutable()).onComplete(testContext.succeeding(vertx -> {
NeonBee.newVertx(defaultOptions()).onComplete(testContext.succeeding(vertx -> {
assertThat(vertx.isClustered()).isFalse();
testContext.completeNow();
}));
Expand All @@ -89,8 +87,7 @@ void testStandaloneInitialization(VertxTestContext testContext) {
@Timeout(value = 10, timeUnit = TimeUnit.SECONDS)
@DisplayName("Vert.x should start in clustered mode.")
void testClusterInitialization(VertxTestContext testContext) {
NeonBee.newVertx(
new NeonBeeOptions.Mutable().setClustered(true).setClusterConfigResource("hazelcast-local.xml"))
NeonBee.newVertx(defaultOptions().setClustered(true).setClusterConfigResource("hazelcast-local.xml"))
.onComplete(testContext.succeeding(vertx -> {
assertThat(vertx.isClustered()).isTrue();
testContext.completeNow();
Expand All @@ -113,7 +110,7 @@ void testRegisterAndUnregisterLocalConsumer() {
@DisplayName("Vert.x should add eventbus interceptors.")
void testDecorateEventbus() throws Exception {
Vertx vertx = NeonBeeMockHelper.defaultVertxMock();
NeonBee neonBee = NeonBeeMockHelper.registerNeonBeeMock(vertx, new NeonBeeOptions.Mutable(),
NeonBee neonBee = NeonBeeMockHelper.registerNeonBeeMock(vertx,
new NeonBeeConfig(new JsonObject().put("trackingDataHandlingStrategy", "wrongvalue")));
EventBus eventBus = mock(EventBus.class);
when(vertx.eventBus()).thenReturn(eventBus);
Expand Down
Loading

0 comments on commit 1412851

Please sign in to comment.