Skip to content

Commit b7ca531

Browse files
committed
fix: Address review comments
1 parent 488b5fa commit b7ca531

File tree

3 files changed

+63
-38
lines changed

3 files changed

+63
-38
lines changed

modules/mongodb/src/main/java/org/testcontainers/mongodb/MongoDBContainer.java

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,16 @@
66
import lombok.extern.slf4j.Slf4j;
77
import org.testcontainers.containers.GenericContainer;
88
import org.testcontainers.containers.wait.strategy.Wait;
9+
import org.testcontainers.images.builder.Transferable;
910
import org.testcontainers.utility.DockerImageName;
1011
import org.testcontainers.utility.MountableFile;
1112

1213
import java.io.IOException;
14+
import java.net.URL;
15+
import java.nio.file.Files;
16+
import java.nio.file.Path;
17+
import java.nio.file.Paths;
18+
import java.util.Enumeration;
1319

1420
/**
1521
* Testcontainers implementation for MongoDB.
@@ -82,13 +88,56 @@ protected void containerIsStarted(InspectContainerResponse containerInfo, boolea
8288
}
8389
}
8490

91+
/**
92+
* Configures the container.
93+
* <p>
94+
* This method handles the transfer of the initialization script to the container.
95+
* Unlike standard file copying mechanisms, this implementation explicitly reads the script content as bytes
96+
* and uses {@link org.testcontainers.images.builder.Transferable} to copy it.
97+
* <p>
98+
* This approach is necessary to strictly support filenames containing special characters
99+
* (e.g., "#", spaces, etc.) on the classpath. Standard resource loading methods may misinterpret
100+
* these characters (e.g., treating "#" as a URL fragment), causing resolution failures.
101+
* By manually resolving the file path and transferring the raw bytes, we ensure the script
102+
* is correctly deployed regardless of its filename complexity.
103+
*/
85104
@Override
86105
protected void configure() {
87106
super.configure();
88107
boolean isClusterMode = this.shardingEnabled || this.rsEnabled;
89108
if (this.initScriptPath != null) {
90-
String destination = isClusterMode ? SCRIPT_DESTINATION_MANUAL : SCRIPT_DESTINATION_DEFAULT;
91-
withCopyFileToContainer(MountableFile.forClasspathResource(this.initScriptPath), destination);
109+
try {
110+
Path scriptPath = Paths.get(this.initScriptPath);
111+
String fileName = scriptPath.getFileName().toString();
112+
Path parentDir = scriptPath.getParent();
113+
String resourceDir = (parentDir == null) ? "" : parentDir.toString();
114+
115+
Enumeration<URL> resources = this.getClass().getClassLoader().getResources(resourceDir);
116+
byte[] fileContent = null;
117+
118+
while (resources.hasMoreElements()) {
119+
URL dirUrl = resources.nextElement();
120+
121+
if ("file".equals(dirUrl.getProtocol())) {
122+
Path dirPath = Paths.get(dirUrl.toURI());
123+
Path candidatePath = dirPath.resolve(fileName);
124+
125+
if (Files.exists(candidatePath) && !Files.isDirectory(candidatePath)) {
126+
fileContent = Files.readAllBytes(candidatePath);
127+
break;
128+
}
129+
}
130+
}
131+
132+
if (fileContent == null) {
133+
throw new RuntimeException("Could not find init script on classpath: " + this.initScriptPath);
134+
}
135+
136+
String destination = isClusterMode ? SCRIPT_DESTINATION_MANUAL : SCRIPT_DESTINATION_DEFAULT;
137+
withCopyToContainer(Transferable.of(fileContent, 0777), destination);
138+
} catch (Exception e) {
139+
throw new RuntimeException("Failed to read or transfer init script: " + this.initScriptPath, e);
140+
}
92141
}
93142

94143
if (this.initScriptPath != null && !isClusterMode) {

modules/mongodb/src/test/java/org/testcontainers/mongodb/MongoDBContainerTest.java

Lines changed: 9 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,7 @@ void shouldExecuteInitScript() {
5757
void shouldExecuteInitScriptWithEdgeCases() {
5858
try (
5959
MongoDBContainer mongoDB = new MongoDBContainer("mongo:4.0.10")
60-
.withInitScript("initEdgeCase.js")
61-
.withEnv("LANG", "C.UTF-8")
62-
.withEnv("LC_ALL", "C.UTF-8")
60+
.withInitScript("initEdgeCase!@#%^& *'().js")
6361
.withStartupTimeout(Duration.ofSeconds(30))
6462
) {
6563
mongoDB.start();
@@ -70,31 +68,27 @@ void shouldExecuteInitScriptWithEdgeCases() {
7068
)
7169
) {
7270
String expectedComplexName = "test_col_\"_with_specials_!@#%^&*()";
73-
String expectedJapaneseName = "日本語 コレクション テスト";
71+
String expectedCollectionWithSpecialChars = "col with spaces & symbols !@#";
7472

7573
com.mongodb.client.MongoDatabase database = client.getDatabase("test");
7674

77-
assertThat(database.listCollectionNames()).contains(expectedComplexName, expectedJapaneseName);
75+
assertThat(database.listCollectionNames())
76+
.contains(expectedComplexName, expectedCollectionWithSpecialChars);
7877

7978
com.mongodb.client.MongoCollection<org.bson.Document> collection = database.getCollection(
8079
expectedComplexName
8180
);
8281

8382
org.bson.Document doc = collection.find(new org.bson.Document("_id", 1)).first();
8483

85-
assertThat(doc).as("Document with _id=1 should exist").isNotNull();
84+
assertThat(doc).isNotNull();
8685

87-
assertThat(doc.getString("key_with_quotes"))
88-
.as("Double quotes should be preserved correctly")
89-
.isEqualTo("This is a \"double quoted\" string");
86+
assertThat(doc.getString("key_with_quotes")).isEqualTo("This is a \"double quoted\" string");
9087

91-
assertThat(doc.getString("key_with_json_chars"))
92-
.as("JSON special chars should be treated as plain text")
93-
.isEqualTo("{ } [ ] : ,");
88+
assertThat(doc.getString("key_with_json_chars")).isEqualTo("{ } [ ] : ,");
9489

9590
assertThat(doc.getString("description"))
96-
.as("Japanese text should be preserved correctly")
97-
.isEqualTo("特殊記号を含むコレクションへの挿入テスト");
91+
.isEqualTo("Insertion test for collection with special symbols");
9892
}
9993
}
10094
}
@@ -107,14 +101,6 @@ void shouldExecuteInitScriptWithReplicaSet() {
107101
}
108102
}
109103

110-
@Test
111-
void shouldExecuteInitScriptWithReplicaSetConfiguredFirst() {
112-
try (MongoDBContainer mongo = new MongoDBContainer("mongo:7.0.0").withReplicaSet().withInitScript("init.js")) {
113-
mongo.start();
114-
assertInitScriptExecuted(mongo);
115-
}
116-
}
117-
118104
@Test
119105
void shouldExecuteInitScriptWithSharding() {
120106
try (MongoDBContainer mongo = new MongoDBContainer("mongo:7.0.0").withInitScript("init.js").withSharding()) {
@@ -123,19 +109,9 @@ void shouldExecuteInitScriptWithSharding() {
123109
}
124110
}
125111

126-
@Test
127-
void shouldExecuteInitScriptWithShardingConfiguredFirst() {
128-
try (MongoDBContainer mongo = new MongoDBContainer("mongo:7.0.0").withSharding().withInitScript("init.js")) {
129-
mongo.start();
130-
assertInitScriptExecuted(mongo);
131-
}
132-
}
133-
134112
private void assertInitScriptExecuted(MongoDBContainer mongo) {
135113
try (com.mongodb.client.MongoClient client = com.mongodb.client.MongoClients.create(mongo.getReplicaSetUrl())) {
136-
assertThat(client.getDatabase("test").listCollectionNames())
137-
.as("Check if init.js created the collection")
138-
.contains("test_collection");
114+
assertThat(client.getDatabase("test").listCollectionNames()).contains("test_collection");
139115
}
140116
}
141117
}

modules/mongodb/src/test/resources/initEdgeCase.js renamed to modules/mongodb/src/test/resources/initEdgeCase!@#%^& *'().js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@ var complexCollectionName = 'test_col_"_with_specials_!@#%^&*()';
22

33
db.createCollection(complexCollectionName);
44

5-
var japaneseCollectionName = "日本語 コレクション テスト";
5+
var collectionWithSpecialChars = "col with spaces & symbols !@#";
66

7-
db.createCollection(japaneseCollectionName);
7+
db.createCollection(collectionWithSpecialChars);
88

99
db.getCollection(complexCollectionName).insertOne({
1010
"_id": 1,
1111
"key_with_quotes": "This is a \"double quoted\" string",
1212
"key_with_json_chars": "{ } [ ] : ,",
13-
"description": "特殊記号を含むコレクションへの挿入テスト"
13+
"description": "Insertion test for collection with special symbols"
1414
});
1515

1616
print("Initialization completed: " + complexCollectionName);

0 commit comments

Comments
 (0)