fix: support parallel execution of reusable containers #593
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
What does this PR do?
It adds a sync.Mutex lock/unlock when a reusable container is created, including a test that demonstrates the bug
In the original bug report (#592), a repro snippet was added, although I preferred a different test that leverages our
testcontainers.ParallelContainers
API, adding code coverage to the library.Why is it important?
Thanks to @mhatch-nxcr, who reported this bug in #592, we demonstrated that the implementation of the reusable containers was not complete in terms of a parallel execution of tests creating containers with the library. The bug report found a race condition while checking the Docker client to find containers with the same name when called from a goroutine (i.e. running multiple Test functions including
t.Parallel()
or ourParallelContainers
function).Internally, when we are checking if we need to reuse a container by its name, the library calls the Docker client with a
findContainerByName
function of the DockerProvider. At the moment thisfindContainerByName
function was called by any goroutine, no container was already created with the reusable container name, and in consequence the Docker client responded with a list of zero containers, which was expected. Therefore we had to look up the stack call to identify what code was calling that method, until we found that we needed synchronization at the moment the first container was created. That's why we are adding thelock/unlock
only for thereq.Reuse
if/else branch.Before the changes
After the changes
How to test this
Run the first commit of this PR with and without the second commit.
Another way to test this fix is using what @mhatch-nxcr proposed in the original bug report: because the two tests uses
t.Parallel()
, they will be run in different goroutines, being affected by the bug. Please run all tests in thereusable
package, not only one of them.Related issues