package testcontainers import ( "fmt" "os" "path/filepath" "testing" "github.com/stretchr/testify/assert" ) const ( dockerSock = "unix:///var/run/docker.sock" tcpDockerHost1234 = "tcp://127.0.0.1:1234" tcpDockerHost33293 = "tcp://127.0.0.1:33293" tcpDockerHost4711 = "tcp://127.0.0.1:4711" ) // unset environment variables to avoid side effects // execute this function before each test func resetTestEnv(t *testing.T) { t.Setenv("TESTCONTAINERS_RYUK_DISABLED", "") t.Setenv("TESTCONTAINERS_RYUK_CONTAINER_PRIVILEGED", "") } func TestReadConfig(t *testing.T) { resetTestEnv(t) t.Run("Config is read just once", func(t *testing.T) { t.Setenv("HOME", "") t.Setenv("TESTCONTAINERS_RYUK_DISABLED", "true") config := ReadConfig() expected := TestcontainersConfig{ RyukDisabled: true, Host: dockerSock, } assert.Equal(t, expected, config) t.Setenv("TESTCONTAINERS_RYUK_DISABLED", "false") config = ReadConfig() assert.Equal(t, expected, config) }) } func TestReadTCConfig(t *testing.T) { resetTestEnv(t) t.Run("HOME is not set", func(t *testing.T) { t.Setenv("HOME", "") config := readConfig() expected := TestcontainersConfig{} expected.Host = dockerSock assert.Equal(t, expected, config) }) t.Run("HOME is not set - TESTCONTAINERS_ env is set", func(t *testing.T) { t.Setenv("HOME", "") t.Setenv("TESTCONTAINERS_RYUK_DISABLED", "true") t.Setenv("TESTCONTAINERS_RYUK_CONTAINER_PRIVILEGED", "true") config := readConfig() expected := TestcontainersConfig{} expected.RyukDisabled = true expected.RyukPrivileged = true expected.Host = dockerSock assert.Equal(t, expected, config) }) t.Run("HOME does not contain TC props file", func(t *testing.T) { tmpDir := t.TempDir() t.Setenv("HOME", tmpDir) config := readConfig() expected := TestcontainersConfig{} expected.Host = dockerSock assert.Equal(t, expected, config) }) t.Run("HOME does not contain TC props file - DOCKER_HOST env is set", func(t *testing.T) { tmpDir := t.TempDir() t.Setenv("HOME", tmpDir) t.Setenv("DOCKER_HOST", tcpDockerHost33293) config := readConfig() expected := TestcontainersConfig{} expected.Host = tcpDockerHost33293 assert.Equal(t, expected, config) }) t.Run("HOME does not contain TC props file - TESTCONTAINERS_ env is set", func(t *testing.T) { tmpDir := t.TempDir() t.Setenv("HOME", tmpDir) t.Setenv("TESTCONTAINERS_RYUK_DISABLED", "true") t.Setenv("TESTCONTAINERS_RYUK_CONTAINER_PRIVILEGED", "true") config := readConfig() expected := TestcontainersConfig{} expected.RyukDisabled = true expected.RyukPrivileged = true expected.Host = dockerSock assert.Equal(t, expected, config) }) t.Run("HOME contains TC properties file", func(t *testing.T) { tests := []struct { name string content string env map[string]string expected TestcontainersConfig }{ { "Single Docker host with spaces", "docker.host = " + tcpDockerHost33293, map[string]string{}, TestcontainersConfig{ Host: tcpDockerHost33293, TLSVerify: 0, CertPath: "", }, }, { "Multiple docker host entries, last one wins", `docker.host = ` + tcpDockerHost33293 + ` docker.host = ` + tcpDockerHost4711 + ` `, map[string]string{}, TestcontainersConfig{ Host: tcpDockerHost4711, TLSVerify: 0, CertPath: "", }, }, { "Multiple docker host entries, last one wins, with TLS", `docker.host = ` + tcpDockerHost33293 + ` docker.host = ` + tcpDockerHost4711 + ` docker.host = ` + tcpDockerHost1234 + ` docker.tls.verify = 1 `, map[string]string{}, TestcontainersConfig{ Host: tcpDockerHost1234, TLSVerify: 1, CertPath: "", }, }, { "Empty file", "", map[string]string{}, TestcontainersConfig{ Host: dockerSock, TLSVerify: 0, CertPath: "", }, }, { "Non-valid properties are ignored", `foo = bar docker.host = ` + tcpDockerHost1234 + ` `, map[string]string{}, TestcontainersConfig{ Host: tcpDockerHost1234, TLSVerify: 0, CertPath: "", }, }, { "Single Docker host without spaces", "docker.host=" + tcpDockerHost33293, map[string]string{}, TestcontainersConfig{ Host: tcpDockerHost33293, TLSVerify: 0, CertPath: "", }, }, { "Comments are ignored", `#docker.host=` + tcpDockerHost33293, map[string]string{}, TestcontainersConfig{ Host: dockerSock, TLSVerify: 0, CertPath: "", }, }, { "Multiple docker host entries, last one wins, with TLS and cert path", `#docker.host = ` + tcpDockerHost33293 + ` docker.host = ` + tcpDockerHost4711 + ` docker.host = ` + tcpDockerHost1234 + ` docker.cert.path=/tmp/certs`, map[string]string{}, TestcontainersConfig{ Host: tcpDockerHost1234, TLSVerify: 0, CertPath: "/tmp/certs", }, }, { "With Ryuk disabled using properties", `ryuk.disabled=true`, map[string]string{}, TestcontainersConfig{ Host: dockerSock, TLSVerify: 0, CertPath: "", RyukDisabled: true, }, }, { "With Ryuk container privileged using properties", `ryuk.container.privileged=true`, map[string]string{}, TestcontainersConfig{ Host: dockerSock, TLSVerify: 0, CertPath: "", RyukPrivileged: true, }, }, { "With Ryuk disabled using an env var", ``, map[string]string{ "TESTCONTAINERS_RYUK_DISABLED": "true", }, TestcontainersConfig{ Host: dockerSock, TLSVerify: 0, CertPath: "", RyukDisabled: true, }, }, { "With Ryuk container privileged using an env var", ``, map[string]string{ "TESTCONTAINERS_RYUK_CONTAINER_PRIVILEGED": "true", }, TestcontainersConfig{ Host: dockerSock, TLSVerify: 0, CertPath: "", RyukPrivileged: true, }, }, { "With Ryuk disabled using an env var and properties. Env var wins (0)", `ryuk.disabled=true`, map[string]string{ "TESTCONTAINERS_RYUK_DISABLED": "true", }, TestcontainersConfig{ Host: dockerSock, TLSVerify: 0, CertPath: "", RyukDisabled: true, }, }, { "With Ryuk disabled using an env var and properties. Env var wins (1)", `ryuk.disabled=false`, map[string]string{ "TESTCONTAINERS_RYUK_DISABLED": "true", }, TestcontainersConfig{ Host: dockerSock, TLSVerify: 0, CertPath: "", RyukDisabled: true, }, }, { "With Ryuk disabled using an env var and properties. Env var wins (2)", `ryuk.disabled=true`, map[string]string{ "TESTCONTAINERS_RYUK_DISABLED": "false", }, TestcontainersConfig{ Host: dockerSock, TLSVerify: 0, CertPath: "", RyukDisabled: false, }, }, { "With Ryuk disabled using an env var and properties. Env var wins (3)", `ryuk.disabled=false`, map[string]string{ "TESTCONTAINERS_RYUK_DISABLED": "false", }, TestcontainersConfig{ Host: dockerSock, TLSVerify: 0, CertPath: "", RyukDisabled: false, }, }, { "With Ryuk container privileged using an env var and properties. Env var wins (0)", `ryuk.container.privileged=true`, map[string]string{ "TESTCONTAINERS_RYUK_CONTAINER_PRIVILEGED": "true", }, TestcontainersConfig{ Host: dockerSock, TLSVerify: 0, CertPath: "", RyukPrivileged: true, }, }, { "With Ryuk container privileged using an env var and properties. Env var wins (1)", `ryuk.container.privileged=false`, map[string]string{ "TESTCONTAINERS_RYUK_CONTAINER_PRIVILEGED": "true", }, TestcontainersConfig{ Host: dockerSock, TLSVerify: 0, CertPath: "", RyukPrivileged: true, }, }, { "With Ryuk container privileged using an env var and properties. Env var wins (2)", `ryuk.container.privileged=true`, map[string]string{ "TESTCONTAINERS_RYUK_CONTAINER_PRIVILEGED": "false", }, TestcontainersConfig{ Host: dockerSock, TLSVerify: 0, CertPath: "", RyukPrivileged: false, }, }, { "With Ryuk container privileged using an env var and properties. Env var wins (3)", `ryuk.container.privileged=false`, map[string]string{ "TESTCONTAINERS_RYUK_CONTAINER_PRIVILEGED": "false", }, TestcontainersConfig{ Host: dockerSock, TLSVerify: 0, CertPath: "", RyukPrivileged: false, }, }, { "With TLS verify using properties when value is wrong", `ryuk.container.privileged=false docker.tls.verify = ERROR`, map[string]string{ "TESTCONTAINERS_RYUK_DISABLED": "true", "TESTCONTAINERS_RYUK_CONTAINER_PRIVILEGED": "true", }, TestcontainersConfig{ Host: dockerSock, TLSVerify: 0, CertPath: "", RyukDisabled: true, RyukPrivileged: true, }, }, { "With Ryuk disabled using an env var and properties. Env var does not win because it's not a boolean value", `ryuk.disabled=false`, map[string]string{ "TESTCONTAINERS_RYUK_DISABLED": "foo", }, TestcontainersConfig{ Host: dockerSock, TLSVerify: 0, CertPath: "", RyukDisabled: false, }, }, { "With Ryuk container privileged using an env var and properties. Env var does not win because it's not a boolean value", `ryuk.container.privileged=false`, map[string]string{ "TESTCONTAINERS_RYUK_CONTAINER_PRIVILEGED": "foo", }, TestcontainersConfig{ Host: dockerSock, TLSVerify: 0, CertPath: "", RyukPrivileged: false, }, }, } for _, tt := range tests { t.Run(fmt.Sprintf(tt.name), func(t *testing.T) { tmpDir := t.TempDir() t.Setenv("HOME", tmpDir) for k, v := range tt.env { t.Setenv(k, v) } if err := os.WriteFile(filepath.Join(tmpDir, ".testcontainers.properties"), []byte(tt.content), 0o600); err != nil { t.Errorf("Failed to create the file: %v", err) return } config := readConfig() assert.Equal(t, tt.expected, config, "Configuration doesn't not match") }) } }) }