Skip to content

[Bug]: listChildContainers should be case insensitive - causes waitUntilServiceStarted to fail #6943

@mccants-heb

Description

@mccants-heb

Module

Core

Testcontainers version

1.18.0

Using the latest Testcontainers version?

Yes

Host OS

Mac OS

Host Arch

ARM

Docker version

rush@RUSHs-MacBook-Pro dcs % docker compose version
Docker Compose version v2.17.2
rush@RUSHs-MacBook-Pro dcs % docker version
Client:
 Cloud integration: v1.0.31
 Version:           20.10.24
 API version:       1.41
 Go version:        go1.19.7
 Git commit:        297e128
 Built:             Tue Apr  4 18:21:21 2023
 OS/Arch:           darwin/arm64
 Context:           default
 Experimental:      true

Server: Docker Desktop 4.18.0 (104112)
 Engine:
  Version:          20.10.24
  API version:      1.41 (minimum version 1.12)
  Go version:       go1.19.7
  Git commit:       5d6db84
  Built:            Tue Apr  4 18:17:07 2023
  OS/Arch:          linux/arm64
  Experimental:     false
 containerd:
  Version:          1.6.18
  GitCommit:        2456e983eb9e37e47538f59ea18f2043c9a73640
 runc:
  Version:          1.1.4
  GitCommit:        v1.1.4-0-g5fd4c4d
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0

What happened?

Running with DockerComposeContainer, I cannot properly wait for Services.

Example code that is failing:

@Container
private static DockerComposeContainer postGres = new DockerComposeContainer("OrderGroupProcessApiFunctionalTest_", new File("docker-compose.test.yml"))
    .withLocalCompose(false)
    .withServices("dcs-db")
    .waitingFor("dcs-db", Wait.defaultWaitStrategy());

Here is the error message:

Services named [flyway_1, dcs-db_1] do not exist, but wait conditions have been defined for them. This might mean that you misspelled the service name when defining the wait condition.
java.lang.IllegalStateException: Services named [dcs-db_1] do not exist, but wait conditions have been defined for them. This might mean that you misspelled the service name when defining the wait condition.
	at org.testcontainers.containers.DockerComposeContainer.waitUntilServiceStarted(DockerComposeContainer.java:280)
	at org.testcontainers.containers.DockerComposeContainer.start(DockerComposeContainer.java:191)
	at org.testcontainers.junit.jupiter.TestcontainersExtension$StoreAdapter.start(TestcontainersExtension.java:274)
	at org.testcontainers.junit.jupiter.TestcontainersExtension$StoreAdapter.access$200(TestcontainersExtension.java:261)
	at org.testcontainers.junit.jupiter.TestcontainersExtension.lambda$null$3(TestcontainersExtension.java:76)
	at org.junit.jupiter.engine.execution.ExtensionValuesStore.lambda$getOrComputeIfAbsent$4(ExtensionValuesStore.java:86)
	at org.junit.jupiter.engine.execution.ExtensionValuesStore$MemoizingSupplier.computeValue(ExtensionValuesStore.java:223)
	at org.junit.jupiter.engine.execution.ExtensionValuesStore$MemoizingSupplier.get(ExtensionValuesStore.java:211)
	at org.junit.jupiter.engine.execution.ExtensionValuesStore$StoredValue.evaluate(ExtensionValuesStore.java:191)
	at org.junit.jupiter.engine.execution.ExtensionValuesStore$StoredValue.access$100(ExtensionValuesStore.java:171)
	at org.junit.jupiter.engine.execution.ExtensionValuesStore.getOrComputeIfAbsent(ExtensionValuesStore.java:89)
	at org.junit.jupiter.engine.execution.NamespaceAwareStore.getOrComputeIfAbsent(NamespaceAwareStore.java:53)
	at org.testcontainers.junit.jupiter.TestcontainersExtension.lambda$startContainers$4(TestcontainersExtension.java:76)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
	at org.testcontainers.junit.jupiter.TestcontainersExtension.startContainers(TestcontainersExtension.java:76)
	at org.testcontainers.junit.jupiter.TestcontainersExtension.beforeAll(TestcontainersExtension.java:56)
	at ... 

This is caused because DockerComposeContainer.waitUntilServiceStarted() calls listChildContainers and it returns no child containers, even though it should. The reason it doesn't is because it fails to properly compare names on this line:

.filter(container -> Arrays.stream(container.getNames()).anyMatch(name -> name.startsWith("/" + project)))

In my case, the project name is OrderGroupProcessApiFunctionalTest_b8kvyt, but the name of the matching container is /ordergroupprocessapifunctionaltest_b8kvyt_flyway_1. The filter states filters out this container, because the filter statement is case sensitive.

This results in DockerComposeContainer.waitUntilServiceStarted() putting something in missingServiceInstances and throw an IllegalStateException resulting in the error message above.

Worse, this leaves orphaned Docker instances after the test completes.

Relevant log output

No response

Additional Information

Work around: lower case the project name when creating DockerComposeContainer.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions