testcontainers-go
testcontainers-go copied to clipboard
[Bug]: WithAfterReadyCommand incorrect iterator scope
Testcontainers version
0.32.0
Using the latest Testcontainers version?
Yes
Host OS
MacOS
Host arch
ARM64
Go version
1.22.4
Docker version
Server: Docker Desktop 4.22.1 (118664)
Engine:
Version: 24.0.5
API version: 1.43 (minimum version 1.12)
Go version: go1.20.6
Git commit: a61e2b4
Built: Fri Jul 21 20:35:38 2023
OS/Arch: linux/arm64
Experimental: false
containerd:
Version: 1.6.21
GitCommit: 3dce8eb055cbb6872793272b4f20ed16117344f8
runc:
Version: 1.1.7
GitCommit: v1.1.7-0-g860f061
docker-init:
Version: 0.19.0
GitCommit: de40ad0
Docker info
Server:
Containers: 10
Running: 9
Paused: 0
Stopped: 1
Images: 24
Server Version: 24.0.5
Storage Driver: overlay2
Backing Filesystem: extfs
Supports d_type: true
Using metacopy: false
Native Overlay Diff: true
userxattr: false
Logging Driver: json-file
Cgroup Driver: cgroupfs
Cgroup Version: 2
Plugins:
Volume: local
Network: bridge host ipvlan macvlan null overlay
Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
Swarm: inactive
Runtimes: io.containerd.runc.v2 runc
Default Runtime: runc
Init Binary: docker-init
containerd version: 3dce8eb055cbb6872793272b4f20ed16117344f8
runc version: v1.1.7-0-g860f061
init version: de40ad0
Security Options:
seccomp
Profile: unconfined
cgroupns
Kernel Version: 5.15.49-linuxkit-pr
Operating System: Docker Desktop
OSType: linux
Architecture: aarch64
CPUs: 5
Total Memory: 7.667GiB
Name: docker-desktop
ID: 8e7dabbb-25ee-4f34-9fe5-2df589d4f8b3
Docker Root Dir: /var/lib/docker
Debug Mode: false
HTTP Proxy: http.docker.internal:3128
HTTPS Proxy: http.docker.internal:3128
No Proxy: hubproxy.docker.internal
Experimental: false
Insecure Registries:
hubproxy.docker.internal:5555
127.0.0.0/8
Live Restore Enabled: false
What happened?
The for loop for generating the functions associated with WithAfterReadyCommand is referencing the wrong scope.
Consider this test:
func TestWithAfterReadyCommand(t *testing.T) {
req := testcontainers.GenericContainerRequest{
ContainerRequest: testcontainers.ContainerRequest{
Image: "alpine",
Entrypoint: []string{"tail", "-f", "/dev/null"},
},
Started: true,
}
testExec := []testcontainers.Executable{
testcontainers.NewRawCommand([]string{"touch", "/tmp/.testcontainers-1"}),
testcontainers.NewRawCommand([]string{"touch", "/tmp/.testcontainers-2"}),
testcontainers.NewRawCommand([]string{"touch", "/tmp/.testcontainers-3"}),
}
err := testcontainers.WithAfterReadyCommand(testExec...)(&req)
require.NoError(t, err)
c, err := testcontainers.GenericContainer(context.Background(), req)
require.NoError(t, err)
defer func() {
err = c.Terminate(context.Background())
require.NoError(t, err)
}()
for i := 1; i <= 3; i++ {
_, reader, err := c.Exec(context.Background(), []string{"ls", fmt.Sprintf("/tmp/.testcontainers-%d", i)}, exec.Multiplexed())
require.NoError(t, err)
content, err := io.ReadAll(reader)
require.NoError(t, err)
assert.Equal(t, fmt.Sprintf("/tmp/.testcontainers-%d\n", i), string(content))
}
}
This will fail with go 1.21. However, if you update to go 1.22 or use the env var GOEXPERIMENT=loopvar the test will pass.
Simple fix is to update the scope for exec at https://github.com/testcontainers/testcontainers-go/blob/70b90cce99b42b5c5e64646e9fd30471c85e0d9d/options.go#L275
exec := exec
execFn := func(ctx context.Context, c Container) error {
_, _, err := c.Exec(ctx, exec.AsCommand(), exec.Options()...)
return err
}
Relevant log output
No response
Additional information
No response