Skip to content

Commit

Permalink
Support mongodb/mongodb-community-server and mongodb/mongodb-enterpri…
Browse files Browse the repository at this point in the history
…se-server (#8386)
  • Loading branch information
eddumelendez committed Feb 27, 2024
1 parent 7bedef7 commit fdcc31c
Show file tree
Hide file tree
Showing 4 changed files with 146 additions and 89 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
/**
* Testcontainers implementation for MongoDB.
* <p>
* Supported image: {@code mongo}
* Supported images: {@code mongo}, {@code mongodb/mongodb-community-server}, {@code mongodb/mongodb-enterprise-server}
* <p>
* Exposed ports: 27017
*/
Expand All @@ -22,6 +22,14 @@ public class MongoDBContainer extends GenericContainer<MongoDBContainer> {

private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("mongo");

private static final DockerImageName COMMUNITY_SERVER_IMAGE = DockerImageName.parse(
"mongodb/mongodb-community-server"
);

private static final DockerImageName ENTERPRISE_SERVER_IMAGE = DockerImageName.parse(
"mongodb/mongodb-enterprise-server"
);

private static final String DEFAULT_TAG = "4.0.10";

private static final int CONTAINER_EXIT_CODE_OK = 0;
Expand All @@ -48,7 +56,7 @@ public MongoDBContainer(@NonNull final String dockerImageName) {

public MongoDBContainer(final DockerImageName dockerImageName) {
super(dockerImageName);
dockerImageName.assertCompatibleWith(DEFAULT_IMAGE_NAME);
dockerImageName.assertCompatibleWith(DEFAULT_IMAGE_NAME, COMMUNITY_SERVER_IMAGE, ENTERPRISE_SERVER_IMAGE);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package org.testcontainers.containers;

import com.mongodb.ReadConcern;
import com.mongodb.ReadPreference;
import com.mongodb.TransactionOptions;
import com.mongodb.WriteConcern;
import com.mongodb.client.ClientSession;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.TransactionBody;
import org.bson.Document;

import static org.assertj.core.api.Assertions.assertThat;

public class AbstractMongo {

protected void executeTx(MongoDBContainer mongoDBContainer) {
final MongoClient mongoSyncClientBase = MongoClients.create(mongoDBContainer.getConnectionString());
final MongoClient mongoSyncClient = MongoClients.create(mongoDBContainer.getReplicaSetUrl());
mongoSyncClient
.getDatabase("mydb1")
.getCollection("foo")
.withWriteConcern(WriteConcern.MAJORITY)
.insertOne(new Document("abc", 0));
mongoSyncClient
.getDatabase("mydb2")
.getCollection("bar")
.withWriteConcern(WriteConcern.MAJORITY)
.insertOne(new Document("xyz", 0));
mongoSyncClientBase
.getDatabase("mydb3")
.getCollection("baz")
.withWriteConcern(WriteConcern.MAJORITY)
.insertOne(new Document("def", 0));

final ClientSession clientSession = mongoSyncClient.startSession();
final TransactionOptions txnOptions = TransactionOptions
.builder()
.readPreference(ReadPreference.primary())
.readConcern(ReadConcern.LOCAL)
.writeConcern(WriteConcern.MAJORITY)
.build();

final String trxResult = "Inserted into collections in different databases";

TransactionBody<String> txnBody = () -> {
final MongoCollection<Document> coll1 = mongoSyncClient.getDatabase("mydb1").getCollection("foo");
final MongoCollection<Document> coll2 = mongoSyncClient.getDatabase("mydb2").getCollection("bar");

coll1.insertOne(clientSession, new Document("abc", 1));
coll2.insertOne(clientSession, new Document("xyz", 999));
return trxResult;
};

try {
final String trxResultActual = clientSession.withTransaction(txnBody, txnOptions);
assertThat(trxResultActual).isEqualTo(trxResult);
} catch (RuntimeException re) {
throw new IllegalStateException(re.getMessage(), re);
} finally {
clientSession.close();
mongoSyncClient.close();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package org.testcontainers.containers;

import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import org.bson.Document;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

import static org.assertj.core.api.Assertions.assertThat;

@RunWith(Parameterized.class)
public class CompatibleImageTest extends AbstractMongo {

private final String image;

public CompatibleImageTest(String image) {
this.image = image;
}

@Parameterized.Parameters(name = "{0}")
public static String[] image() {
return new String[] {
"mongo:7",
"mongodb/mongodb-community-server:7.0.2-ubi8",
"mongodb/mongodb-enterprise-server:7.0.0-ubi8",
};
}

@Test
public void shouldExecuteTransactions() {
try (
// creatingMongoDBContainer {
final MongoDBContainer mongoDBContainer = new MongoDBContainer("mongo:4.0.10")
// }
) {
// startingMongoDBContainer {
mongoDBContainer.start();
// }
executeTx(mongoDBContainer);
}
}

@Test
public void shouldSupportSharding() {
try (final MongoDBContainer mongoDBContainer = new MongoDBContainer(this.image).withSharding()) {
mongoDBContainer.start();
final MongoClient mongoClient = MongoClients.create(mongoDBContainer.getReplicaSetUrl());

mongoClient.getDatabase("mydb1").getCollection("foo").insertOne(new Document("abc", 0));

Document shards = mongoClient.getDatabase("config").getCollection("shards").find().first();
assertThat(shards).isNotNull();
assertThat(shards).isNotEmpty();
assertThat(isReplicaSet(mongoClient)).isFalse();
}
}

private boolean isReplicaSet(MongoClient mongoClient) {
return runIsMaster(mongoClient).get("setName") != null;
}

private Document runIsMaster(MongoClient mongoClient) {
return mongoClient.getDatabase("admin").runCommand(new Document("ismaster", 1));
}
}
Original file line number Diff line number Diff line change
@@ -1,21 +1,10 @@
package org.testcontainers.containers;

import com.mongodb.ReadConcern;
import com.mongodb.ReadPreference;
import com.mongodb.TransactionOptions;
import com.mongodb.WriteConcern;
import com.mongodb.client.ClientSession;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.TransactionBody;
import org.bson.Document;
import org.junit.Test;
import org.testcontainers.utility.DockerImageName;

import static org.assertj.core.api.Assertions.assertThat;

public class MongoDBContainerTest {
public class MongoDBContainerTest extends AbstractMongo {

/**
* Taken from <a href="https://docs.mongodb.com/manual/core/transactions/">https://docs.mongodb.com</a>
Expand All @@ -24,7 +13,7 @@ public class MongoDBContainerTest {
public void shouldExecuteTransactions() {
try (
// creatingMongoDBContainer {
final MongoDBContainer mongoDBContainer = new MongoDBContainer(DockerImageName.parse("mongo:4.0.10"))
final MongoDBContainer mongoDBContainer = new MongoDBContainer("mongo:4.0.10")
// }
) {
// startingMongoDBContainer {
Expand All @@ -34,91 +23,19 @@ public void shouldExecuteTransactions() {
}
}

private void executeTx(MongoDBContainer mongoDBContainer) {
final MongoClient mongoSyncClientBase = MongoClients.create(mongoDBContainer.getConnectionString());
final MongoClient mongoSyncClient = MongoClients.create(mongoDBContainer.getReplicaSetUrl());
mongoSyncClient
.getDatabase("mydb1")
.getCollection("foo")
.withWriteConcern(WriteConcern.MAJORITY)
.insertOne(new Document("abc", 0));
mongoSyncClient
.getDatabase("mydb2")
.getCollection("bar")
.withWriteConcern(WriteConcern.MAJORITY)
.insertOne(new Document("xyz", 0));
mongoSyncClientBase
.getDatabase("mydb3")
.getCollection("baz")
.withWriteConcern(WriteConcern.MAJORITY)
.insertOne(new Document("def", 0));

final ClientSession clientSession = mongoSyncClient.startSession();
final TransactionOptions txnOptions = TransactionOptions
.builder()
.readPreference(ReadPreference.primary())
.readConcern(ReadConcern.LOCAL)
.writeConcern(WriteConcern.MAJORITY)
.build();

final String trxResult = "Inserted into collections in different databases";

TransactionBody<String> txnBody = () -> {
final MongoCollection<Document> coll1 = mongoSyncClient.getDatabase("mydb1").getCollection("foo");
final MongoCollection<Document> coll2 = mongoSyncClient.getDatabase("mydb2").getCollection("bar");

coll1.insertOne(clientSession, new Document("abc", 1));
coll2.insertOne(clientSession, new Document("xyz", 999));
return trxResult;
};

try {
final String trxResultActual = clientSession.withTransaction(txnBody, txnOptions);
assertThat(trxResultActual).isEqualTo(trxResult);
} catch (RuntimeException re) {
throw new IllegalStateException(re.getMessage(), re);
} finally {
clientSession.close();
mongoSyncClient.close();
}
}

@Test
public void supportsMongoDB_4_4() {
try (final MongoDBContainer mongoDBContainer = new MongoDBContainer(DockerImageName.parse("mongo:4.4"))) {
try (final MongoDBContainer mongoDBContainer = new MongoDBContainer("mongo:4.4")) {
mongoDBContainer.start();
}
}

@Test
public void shouldTestDatabaseName() {
try (final MongoDBContainer mongoDBContainer = new MongoDBContainer(DockerImageName.parse("mongo:4.0.10"))) {
try (final MongoDBContainer mongoDBContainer = new MongoDBContainer("mongo:4.0.10")) {
mongoDBContainer.start();
final String databaseName = "my-db";
assertThat(mongoDBContainer.getReplicaSetUrl(databaseName)).endsWith(databaseName);
}
}

@Test
public void shouldSupportSharding() {
try (final MongoDBContainer mongoDBContainer = new MongoDBContainer("mongo:6").withSharding()) {
mongoDBContainer.start();
final MongoClient mongoClient = MongoClients.create(mongoDBContainer.getReplicaSetUrl());

mongoClient.getDatabase("mydb1").getCollection("foo").insertOne(new Document("abc", 0));

Document shards = mongoClient.getDatabase("config").getCollection("shards").find().first();
assertThat(shards).isNotNull();
assertThat(shards).isNotEmpty();
assertThat(isReplicaSet(mongoClient)).isFalse();
}
}

private boolean isReplicaSet(MongoClient mongoClient) {
return runIsMaster(mongoClient).get("setName") != null;
}

private Document runIsMaster(MongoClient mongoClient) {
return mongoClient.getDatabase("admin").runCommand(new Document("ismaster", 1));
}
}

0 comments on commit fdcc31c

Please sign in to comment.