diff --git a/entity-service/build.gradle.kts b/entity-service/build.gradle.kts index bd8ee17c..501a3af2 100644 --- a/entity-service/build.gradle.kts +++ b/entity-service/build.gradle.kts @@ -1,10 +1,3 @@ -import com.bmuschko.gradle.docker.tasks.container.DockerCreateContainer -import com.bmuschko.gradle.docker.tasks.container.DockerStartContainer -import com.bmuschko.gradle.docker.tasks.container.DockerStopContainer -import com.bmuschko.gradle.docker.tasks.image.DockerPullImage -import com.bmuschko.gradle.docker.tasks.network.DockerCreateNetwork -import com.bmuschko.gradle.docker.tasks.network.DockerRemoveNetwork - plugins { java application @@ -15,42 +8,8 @@ plugins { id("org.hypertrace.jacoco-report-plugin") } -tasks.register("createIntegrationTestNetwork") { - networkName.set("entity-svc-int-test") -} - -tasks.register("removeIntegrationTestNetwork") { - networkId.set("entity-svc-int-test") -} - -tasks.register("pullMongoImage") { - image.set("mongo:4.4.0") -} - -tasks.register("createMongoContainer") { - dependsOn("createIntegrationTestNetwork") - dependsOn("pullMongoImage") - targetImageId(tasks.getByName("pullMongoImage").image) - containerName.set("mongo-local") - hostConfig.network.set(tasks.getByName("createIntegrationTestNetwork").networkId) - hostConfig.portBindings.set(listOf("27017:27017")) - hostConfig.autoRemove.set(true) -} - -tasks.register("startMongoContainer") { - dependsOn("createMongoContainer") - targetContainerId(tasks.getByName("createMongoContainer").containerId) -} - -tasks.register("stopMongoContainer") { - targetContainerId(tasks.getByName("createMongoContainer").containerId) - finalizedBy("removeIntegrationTestNetwork") -} - tasks.integrationTest { useJUnitPlatform() - dependsOn("startMongoContainer") - finalizedBy("stopMongoContainer") } dependencies { @@ -78,10 +37,13 @@ dependencies { // Config implementation("com.typesafe:config:1.4.1") + // integration test integrationTestImplementation(project(":entity-service-client")) integrationTestImplementation("org.hypertrace.core.grpcutils:grpc-context-utils:0.4.0") integrationTestImplementation("org.junit.jupiter:junit-jupiter:5.7.1") integrationTestImplementation("org.hypertrace.core.serviceframework:integrationtest-service-framework:0.1.23") + integrationTestImplementation("org.testcontainers:testcontainers:1.15.2") + integrationTestImplementation("com.github.stefanbirkner:system-lambda:1.2.0") } application { diff --git a/entity-service/src/integrationTest/java/org/hypertrace/entity/service/service/EntityDataServiceRelationshipsTest.java b/entity-service/src/integrationTest/java/org/hypertrace/entity/service/service/EntityDataServiceRelationshipsTest.java index 835f8971..bbba97c9 100644 --- a/entity-service/src/integrationTest/java/org/hypertrace/entity/service/service/EntityDataServiceRelationshipsTest.java +++ b/entity-service/src/integrationTest/java/org/hypertrace/entity/service/service/EntityDataServiceRelationshipsTest.java @@ -1,7 +1,9 @@ package org.hypertrace.entity.service.service; -import io.grpc.Channel; -import io.grpc.ClientInterceptors; +import static com.github.stefanbirkner.systemlambda.SystemLambda.withEnvironmentVariable; + +import com.typesafe.config.ConfigFactory; +import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; import java.util.ArrayList; import java.util.Collections; @@ -24,41 +26,65 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.containers.output.Slf4jLogConsumer; +import org.testcontainers.containers.wait.strategy.Wait; +import org.testcontainers.utility.DockerImageName; /** Test case for testing relationships CRUD with {@link EntityDataServiceClient} */ public class EntityDataServiceRelationshipsTest { + private static final Logger LOG = + LoggerFactory.getLogger(EntityDataServiceRelationshipsTest.class); + private static final Slf4jLogConsumer logConsumer = new Slf4jLogConsumer(LOG); + private static EntityDataServiceClient entityDataServiceClient; private static final String TENANT_ID = "__testTenant__" + EntityDataServiceTest.class.getSimpleName(); + private static final int CONTAINER_STARTUP_ATTEMPTS = 5; + + private static GenericContainer mongo; + private static ManagedChannel channel; @BeforeAll - public static void setUp() { - IntegrationTestServerUtil.startServices(new String[] {"entity-service"}); - EntityServiceClientConfig esConfig = EntityServiceTestConfig.getClientConfig(); - Channel channel = - ClientInterceptors.intercept( - ManagedChannelBuilder.forAddress(esConfig.getHost(), esConfig.getPort()) - .usePlaintext() - .build()); + public static void setUp() throws Exception { + + mongo = + new GenericContainer<>(DockerImageName.parse("hypertrace/mongodb:main")) + .withExposedPorts(27017) + .withStartupAttempts(CONTAINER_STARTUP_ATTEMPTS) + .waitingFor(Wait.forListeningPort()) + .withLogConsumer(logConsumer); + mongo.start(); + + withEnvironmentVariable("MONGO_HOST", mongo.getHost()) + .and("MONGO_PORT", mongo.getMappedPort(27017).toString()) + .execute( + () -> { + ConfigFactory.invalidateCaches(); + IntegrationTestServerUtil.startServices(new String[] {"entity-service"}); + }); + EntityServiceClientConfig entityServiceTestConfig = EntityServiceTestConfig.getClientConfig(); + channel = + ManagedChannelBuilder.forAddress( + entityServiceTestConfig.getHost(), entityServiceTestConfig.getPort()) + .usePlaintext() + .build(); + entityDataServiceClient = new EntityDataServiceClient(channel); setupEntityTypes(); } @AfterAll public static void teardown() { + channel.shutdown(); IntegrationTestServerUtil.shutdownServices(); + mongo.stop(); } private static void setupEntityTypes() { - Channel channel = - ClientInterceptors.intercept( - ManagedChannelBuilder.forAddress( - EntityServiceTestConfig.getClientConfig().getHost(), - EntityServiceTestConfig.getClientConfig().getPort()) - .usePlaintext() - .build()); - EntityTypeServiceClient entityTypeServiceClient = new EntityTypeServiceClient(channel); entityTypeServiceClient.upsertEntityType( TENANT_ID, diff --git a/entity-service/src/integrationTest/java/org/hypertrace/entity/service/service/EntityDataServiceTest.java b/entity-service/src/integrationTest/java/org/hypertrace/entity/service/service/EntityDataServiceTest.java index 020d8a76..1750840b 100644 --- a/entity-service/src/integrationTest/java/org/hypertrace/entity/service/service/EntityDataServiceTest.java +++ b/entity-service/src/integrationTest/java/org/hypertrace/entity/service/service/EntityDataServiceTest.java @@ -1,5 +1,6 @@ package org.hypertrace.entity.service.service; +import static com.github.stefanbirkner.systemlambda.SystemLambda.withEnvironmentVariable; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotEquals; @@ -9,6 +10,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import com.google.common.collect.ImmutableMap; +import com.typesafe.config.ConfigFactory; import io.grpc.Channel; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; @@ -60,24 +62,49 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.containers.output.Slf4jLogConsumer; +import org.testcontainers.containers.wait.strategy.Wait; +import org.testcontainers.utility.DockerImageName; /** Test case for {@link EntityDataServiceClient} */ public class EntityDataServiceTest { + private static final Logger LOG = LoggerFactory.getLogger(EntityDataServiceTest.class); + private static final Slf4jLogConsumer logConsumer = new Slf4jLogConsumer(LOG); private static final String TENANT_ID = "__testTenant__" + EntityDataServiceTest.class.getSimpleName(); private static final String TEST_ENTITY_TYPE_V2 = "TEST_ENTITY"; private static EntityDataServiceClient entityDataServiceClient; private static ManagedChannel channel; + private static final int CONTAINER_STARTUP_ATTEMPTS = 5; + private static GenericContainer mongo; @BeforeAll - public static void setUp() { - IntegrationTestServerUtil.startServices(new String[] {"entity-service"}); - EntityServiceClientConfig esConfig = EntityServiceTestConfig.getClientConfig(); + public static void setUp() throws Exception { + mongo = + new GenericContainer<>(DockerImageName.parse("hypertrace/mongodb:main")) + .withExposedPorts(27017) + .withStartupAttempts(CONTAINER_STARTUP_ATTEMPTS) + .waitingFor(Wait.forListeningPort()) + .withLogConsumer(logConsumer); + mongo.start(); + + withEnvironmentVariable("MONGO_HOST", mongo.getHost()) + .and("MONGO_PORT", mongo.getMappedPort(27017).toString()) + .execute( + () -> { + ConfigFactory.invalidateCaches(); + IntegrationTestServerUtil.startServices(new String[] {"entity-service"}); + }); + EntityServiceClientConfig entityServiceTestConfig = EntityServiceTestConfig.getClientConfig(); channel = - ManagedChannelBuilder.forAddress(esConfig.getHost(), esConfig.getPort()) + ManagedChannelBuilder.forAddress("localhost", entityServiceTestConfig.getPort()) .usePlaintext() .build(); + entityDataServiceClient = new EntityDataServiceClient(channel); setupEntityTypes(channel, TENANT_ID); } @@ -86,6 +113,7 @@ public static void setUp() { public static void teardown() { channel.shutdown(); IntegrationTestServerUtil.shutdownServices(); + mongo.stop(); } private static void setupEntityTypes(Channel channel, String tenant) { diff --git a/entity-service/src/integrationTest/java/org/hypertrace/entity/service/service/EntityQueryServiceTest.java b/entity-service/src/integrationTest/java/org/hypertrace/entity/service/service/EntityQueryServiceTest.java index 4df833d0..116a86f7 100644 --- a/entity-service/src/integrationTest/java/org/hypertrace/entity/service/service/EntityQueryServiceTest.java +++ b/entity-service/src/integrationTest/java/org/hypertrace/entity/service/service/EntityQueryServiceTest.java @@ -1,5 +1,6 @@ package org.hypertrace.entity.service.service; +import static com.github.stefanbirkner.systemlambda.SystemLambda.withEnvironmentVariable; import static org.hypertrace.entity.service.constants.EntityCollectionConstants.ENTITY_TYPES_COLLECTION; import static org.hypertrace.entity.service.constants.EntityCollectionConstants.RAW_ENTITIES_COLLECTION; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -11,7 +12,7 @@ import com.typesafe.config.Config; import com.typesafe.config.ConfigFactory; import io.grpc.Channel; -import io.grpc.ClientInterceptors; +import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; import java.time.Instant; import java.util.ArrayList; @@ -54,14 +55,24 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.containers.output.Slf4jLogConsumer; +import org.testcontainers.containers.wait.strategy.Wait; +import org.testcontainers.utility.DockerImageName; /** Test for {@link org.hypertrace.entity.query.service.client.EntityQueryServiceClient} */ public class EntityQueryServiceTest { + + private static final Logger LOG = LoggerFactory.getLogger(EntityQueryServiceTest.class); + private static final Slf4jLogConsumer logConsumer = new Slf4jLogConsumer(LOG); + private static EntityQueryServiceClient entityQueryServiceClient; // needed to create entities private static EntityDataServiceClient entityDataServiceClient; - private static Channel channel; + private static ManagedChannel channel; private static Datastore datastore; private static final String TENANT_ID = @@ -74,18 +85,36 @@ public class EntityQueryServiceTest { // attributes defined in application.conf in attribute map private static final String API_DISCOVERY_STATE_ATTR = "API.apiDiscoveryState"; private static final String API_HTTP_METHOD_ATTR = "API.httpMethod"; + private static final int CONTAINER_STARTUP_ATTEMPTS = 5; + private static GenericContainer mongo; @BeforeAll - public static void setUp() { - IntegrationTestServerUtil.startServices(new String[] {"entity-service"}); - EntityServiceClientConfig esConfig = EntityServiceTestConfig.getClientConfig(); + public static void setUp() throws Exception { + mongo = + new GenericContainer<>(DockerImageName.parse("hypertrace/mongodb:main")) + .withExposedPorts(27017) + .withStartupAttempts(CONTAINER_STARTUP_ATTEMPTS) + .waitingFor(Wait.forListeningPort()) + .withLogConsumer(logConsumer); + mongo.start(); + + withEnvironmentVariable("MONGO_HOST", mongo.getHost()) + .and("MONGO_PORT", mongo.getMappedPort(27017).toString()) + .execute( + () -> { + ConfigFactory.invalidateCaches(); + IntegrationTestServerUtil.startServices(new String[] {"entity-service"}); + }); + + EntityServiceClientConfig entityServiceTestConfig = EntityServiceTestConfig.getClientConfig(); channel = - ClientInterceptors.intercept( - ManagedChannelBuilder.forAddress(esConfig.getHost(), esConfig.getPort()) - .usePlaintext() - .build()); + ManagedChannelBuilder.forAddress( + entityServiceTestConfig.getHost(), entityServiceTestConfig.getPort()) + .usePlaintext() + .build(); entityQueryServiceClient = new EntityQueryServiceClient(channel); entityDataServiceClient = new EntityDataServiceClient(channel); + datastore = getDatastore(); Map> attributesMap = getAttributesMap(); @@ -96,7 +125,6 @@ public static void setUp() { public void clearCollections() { clearCollection(ENTITY_TYPES_COLLECTION); clearCollection(RAW_ENTITIES_COLLECTION); - setupEntityTypes(channel); } @@ -107,7 +135,9 @@ private static void clearCollection(String collName) { @AfterAll public static void teardown() { + channel.shutdown(); IntegrationTestServerUtil.shutdownServices(); + mongo.stop(); } private static void setupEntityTypes(Channel channel) { @@ -433,6 +463,7 @@ public void testCreateAndGetEntities() { @Nested class TotalEntities { + @Test public void testTotal() { // creating an api entity with attributes @@ -541,9 +572,12 @@ private static Datastore getDatastore() { Config config = ConfigFactory.parseResources("configs/entity-service/application.conf"); EntityServiceConfig entityServiceConfig = new EntityServiceConfig(config.getConfig("entity.service.config")); + Map mongoConfig = new HashMap<>(); + mongoConfig.putIfAbsent("host", mongo.getHost()); + mongoConfig.putIfAbsent("port", mongo.getMappedPort(27017).toString()); + Config dataStoreConfig = ConfigFactory.parseMap(mongoConfig); String dataStoreType = entityServiceConfig.getDataStoreType(); - return DatastoreProvider.getDatastore( - dataStoreType, entityServiceConfig.getDataStoreConfig(dataStoreType)); + return DatastoreProvider.getDatastore(dataStoreType, dataStoreConfig); } private static Map> getAttributesMap() { diff --git a/entity-service/src/integrationTest/java/org/hypertrace/entity/service/service/EntityTypeServiceTest.java b/entity-service/src/integrationTest/java/org/hypertrace/entity/service/service/EntityTypeServiceTest.java index c7d4aed7..c0174e64 100644 --- a/entity-service/src/integrationTest/java/org/hypertrace/entity/service/service/EntityTypeServiceTest.java +++ b/entity-service/src/integrationTest/java/org/hypertrace/entity/service/service/EntityTypeServiceTest.java @@ -1,10 +1,13 @@ package org.hypertrace.entity.service.service; -import io.grpc.Channel; -import io.grpc.ClientInterceptors; +import static com.github.stefanbirkner.systemlambda.SystemLambda.withEnvironmentVariable; + +import com.typesafe.config.ConfigFactory; +import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; import java.util.List; import org.hypertrace.core.serviceframework.IntegrationTestServerUtil; +import org.hypertrace.entity.service.client.config.EntityServiceClientConfig; import org.hypertrace.entity.service.client.config.EntityServiceTestConfig; import org.hypertrace.entity.type.service.client.EntityTypeServiceClient; import org.hypertrace.entity.type.service.v1.AttributeKind; @@ -19,31 +22,58 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.containers.output.Slf4jLogConsumer; +import org.testcontainers.containers.wait.strategy.Wait; +import org.testcontainers.utility.DockerImageName; /** Integration test for testing {@link EntityTypeServiceClient} */ public class EntityTypeServiceTest { + private static final Logger LOG = LoggerFactory.getLogger(EntityTypeServiceTest.class); + private static final Slf4jLogConsumer logConsumer = new Slf4jLogConsumer(LOG); private static final String TENANT_ID = "__testTenant__" + EntityTypeServiceTest.class.getSimpleName(); private static EntityTypeServiceClient client; + private static final int CONTAINER_STARTUP_ATTEMPTS = 5; + private static GenericContainer mongo; + private static ManagedChannel channel; + @BeforeAll - public static void setUp() { - IntegrationTestServerUtil.startServices(new String[] {"entity-service"}); - Channel channel = - ClientInterceptors.intercept( - ManagedChannelBuilder.forAddress( - EntityServiceTestConfig.getClientConfig().getHost(), - EntityServiceTestConfig.getClientConfig().getPort()) - .usePlaintext() - .build()); + public static void setUp() throws Exception { + + mongo = + new GenericContainer<>(DockerImageName.parse("hypertrace/mongodb:main")) + .withExposedPorts(27017) + .withStartupAttempts(CONTAINER_STARTUP_ATTEMPTS) + .waitingFor(Wait.forListeningPort()) + .withLogConsumer(logConsumer); + mongo.start(); + + withEnvironmentVariable("MONGO_HOST", mongo.getHost()) + .and("MONGO_PORT", mongo.getMappedPort(27017).toString()) + .execute( + () -> { + ConfigFactory.invalidateCaches(); + IntegrationTestServerUtil.startServices(new String[] {"entity-service"}); + }); + EntityServiceClientConfig entityServiceTestConfig = EntityServiceTestConfig.getClientConfig(); + channel = + ManagedChannelBuilder.forAddress("localhost", entityServiceTestConfig.getPort()) + .usePlaintext() + .build(); client = new EntityTypeServiceClient(channel); } @AfterAll public static void teardown() { + channel.shutdown(); IntegrationTestServerUtil.shutdownServices(); + mongo.stop(); } @BeforeEach diff --git a/entity-service/src/integrationTest/java/org/hypertrace/entity/type/service/v2/EntityTypeServiceTest.java b/entity-service/src/integrationTest/java/org/hypertrace/entity/type/service/v2/EntityTypeServiceTest.java index 1f05bc14..3c9e5dfa 100644 --- a/entity-service/src/integrationTest/java/org/hypertrace/entity/type/service/v2/EntityTypeServiceTest.java +++ b/entity-service/src/integrationTest/java/org/hypertrace/entity/type/service/v2/EntityTypeServiceTest.java @@ -1,10 +1,13 @@ package org.hypertrace.entity.type.service.v2; -import io.grpc.Channel; -import io.grpc.ClientInterceptors; +import static com.github.stefanbirkner.systemlambda.SystemLambda.withEnvironmentVariable; + +import com.typesafe.config.ConfigFactory; +import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; import java.util.List; import org.hypertrace.core.serviceframework.IntegrationTestServerUtil; +import org.hypertrace.entity.service.client.config.EntityServiceClientConfig; import org.hypertrace.entity.service.client.config.EntityServiceTestConfig; import org.hypertrace.entity.type.client.EntityTypeServiceClient; import org.junit.jupiter.api.AfterAll; @@ -12,30 +15,57 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.containers.output.Slf4jLogConsumer; +import org.testcontainers.containers.wait.strategy.Wait; +import org.testcontainers.utility.DockerImageName; /** Integration test for testing {@link EntityTypeServiceImpl} */ public class EntityTypeServiceTest { + + private static final Logger LOG = LoggerFactory.getLogger(EntityTypeServiceTest.class); + private static final Slf4jLogConsumer logConsumer = new Slf4jLogConsumer(LOG); + private static final String TENANT_ID = "__testTenant__" + EntityTypeServiceTest.class.getSimpleName(); private static EntityTypeServiceClient client; + private static final int CONTAINER_STARTUP_ATTEMPTS = 5; + private static GenericContainer mongo; + private static ManagedChannel channel; @BeforeAll - public static void setUp() { - IntegrationTestServerUtil.startServices(new String[] {"entity-service"}); - Channel channel = - ClientInterceptors.intercept( - ManagedChannelBuilder.forAddress( - EntityServiceTestConfig.getClientConfig().getHost(), - EntityServiceTestConfig.getClientConfig().getPort()) - .usePlaintext() - .build()); + public static void setUp() throws Exception { + mongo = + new GenericContainer<>(DockerImageName.parse("hypertrace/mongodb:main")) + .withExposedPorts(27017) + .withStartupAttempts(CONTAINER_STARTUP_ATTEMPTS) + .waitingFor(Wait.forListeningPort()) + .withLogConsumer(logConsumer); + mongo.start(); + + withEnvironmentVariable("MONGO_HOST", mongo.getHost()) + .and("MONGO_PORT", mongo.getMappedPort(27017).toString()) + .execute( + () -> { + ConfigFactory.invalidateCaches(); + IntegrationTestServerUtil.startServices(new String[] {"entity-service"}); + }); + EntityServiceClientConfig entityServiceTestConfig = EntityServiceTestConfig.getClientConfig(); + channel = + ManagedChannelBuilder.forAddress("localhost", entityServiceTestConfig.getPort()) + .usePlaintext() + .build(); client = new EntityTypeServiceClient(channel); } @AfterAll public static void teardown() { + channel.shutdown(); IntegrationTestServerUtil.shutdownServices(); + mongo.stop(); } @BeforeEach diff --git a/entity-service/src/integrationTest/resources/configs/entity-service/application.conf b/entity-service/src/integrationTest/resources/configs/entity-service/application.conf index 0adf4aaa..36e4a978 100644 --- a/entity-service/src/integrationTest/resources/configs/entity-service/application.conf +++ b/entity-service/src/integrationTest/resources/configs/entity-service/application.conf @@ -7,7 +7,9 @@ entity.service.config = { dataStoreType = mongo mongo { host = localhost + host = ${?MONGO_HOST} port = 27017 + port = ${?MONGO_PORT} } } }