mirror of
https://github.com/docker/compose.git
synced 2026-09-02 15:50:34 +00:00
test(e2e): start/stop scenarios observe container state, not CLI chatter
Migrate the state-friendly start/stop tests to the Scenario DSL: - TestStartStop: stop halts containers in place, start brings the same ones back (NotRecreated); the ls checks match the project name exactly in the JSON output, immune to the prefix collisions the other start-stop project names would cause under parallel runs. - TestStartStopWithDependencies: dependency start/stop propagation read from container state instead of 'Container X Started' messages. - TestUpNoDeps replaces the 'Up no-deps links' subtest as its own scenario: up --no-deps must not create the linked dependency. - TestStartSingleServiceAndDependency: create/start walk the dependency chain and nothing else — now asserting the unrelated services have no container at all, stronger than the legacy message matching. The one-off and multi-file tests stay legacy: the vocabulary has no one-off awareness yet and a scenario holds a single compose file. The links and start-stop-deps fixtures become unused and are removed. Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
This commit is contained in:
parent
5baeadf929
commit
695a2a759a
7 changed files with 121 additions and 143 deletions
|
|
@ -1,8 +0,0 @@
|
|||
services:
|
||||
foo:
|
||||
image: nginx:alpine
|
||||
links:
|
||||
- bar
|
||||
|
||||
bar:
|
||||
image: nginx:alpine
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
services:
|
||||
another_2:
|
||||
image: nginx:alpine
|
||||
another:
|
||||
image: nginx:alpine
|
||||
depends_on:
|
||||
- another_2
|
||||
dep_2:
|
||||
image: nginx:alpine
|
||||
dep_1:
|
||||
image: nginx:alpine
|
||||
depends_on:
|
||||
- dep_2
|
||||
desired:
|
||||
image: nginx:alpine
|
||||
depends_on:
|
||||
- dep_1
|
||||
|
|
@ -22,111 +22,62 @@ import (
|
|||
"testing"
|
||||
|
||||
"gotest.tools/v3/assert"
|
||||
is "gotest.tools/v3/assert/cmp"
|
||||
"gotest.tools/v3/icmd"
|
||||
)
|
||||
|
||||
func TestStartStop(t *testing.T) {
|
||||
c := NewParallelCLI(t)
|
||||
const projectName = "e2e-start-stop-no-dependencies"
|
||||
|
||||
getProjectRegx := func(status string) string {
|
||||
// match output with random spaces like:
|
||||
// e2e-start-stop running(3)
|
||||
return fmt.Sprintf("%s\\s+%s\\(%d\\)", projectName, status, 2)
|
||||
}
|
||||
|
||||
t.Run("Up a project", func(t *testing.T) {
|
||||
res := c.RunDockerComposeCmd(t, "-f", "./fixtures/start-stop/compose.yaml", "--project-name", projectName, "up",
|
||||
"-d")
|
||||
assert.Assert(t, strings.Contains(res.Combined(), "Container e2e-start-stop-no-dependencies-simple-1 Started"), res.Combined())
|
||||
|
||||
res = c.RunDockerComposeCmd(t, "ls", "--all")
|
||||
assert.Assert(t, is.Regexp(getProjectRegx("running"), res.Stdout()))
|
||||
|
||||
res = c.RunDockerComposeCmd(t, "--project-name", projectName, "ps")
|
||||
assertServiceStatus(t, projectName, "simple", "Up", res.Stdout())
|
||||
assertServiceStatus(t, projectName, "another", "Up", res.Stdout())
|
||||
})
|
||||
|
||||
t.Run("stop project", func(t *testing.T) {
|
||||
c.RunDockerComposeCmd(t, "-f", "./fixtures/start-stop/compose.yaml", "--project-name", projectName, "stop")
|
||||
|
||||
res := c.RunDockerComposeCmd(t, "ls")
|
||||
assert.Assert(t, !strings.Contains(res.Combined(), "e2e-start-stop-no-dependencies"), res.Combined())
|
||||
|
||||
res = c.RunDockerComposeCmd(t, "ls", "--all")
|
||||
assert.Assert(t, is.Regexp(getProjectRegx("exited"), res.Stdout()))
|
||||
|
||||
res = c.RunDockerComposeCmd(t, "--project-name", projectName, "ps")
|
||||
assert.Assert(t, !strings.Contains(res.Combined(), "e2e-start-stop-no-dependencies-words-1"), res.Combined())
|
||||
|
||||
res = c.RunDockerComposeCmd(t, "--project-name", projectName, "ps", "--all")
|
||||
assertServiceStatus(t, projectName, "simple", "Exited", res.Stdout())
|
||||
assertServiceStatus(t, projectName, "another", "Exited", res.Stdout())
|
||||
})
|
||||
|
||||
t.Run("start project", func(t *testing.T) {
|
||||
c.RunDockerComposeCmd(t, "-f", "./fixtures/start-stop/compose.yaml", "--project-name", projectName, "start")
|
||||
|
||||
res := c.RunDockerComposeCmd(t, "ls")
|
||||
assert.Assert(t, is.Regexp(getProjectRegx("running"), res.Stdout()))
|
||||
})
|
||||
|
||||
t.Run("down", func(t *testing.T) {
|
||||
_ = c.RunDockerComposeCmd(t, "--project-name", projectName, "down")
|
||||
})
|
||||
s := NewScenario(t, "stop must halt the project's containers in place, start must bring the same ones back")
|
||||
s.Step("up starts every service",
|
||||
ComposeCmd("up", "-d"),
|
||||
ServiceState("simple", "running"),
|
||||
ServiceState("another", "running")).
|
||||
Step("ls reports the project as running",
|
||||
ComposeCmd("ls", "--format", "json"),
|
||||
OutputContains(`"Name":"`+s.Project()+`"`)).
|
||||
Step("stop halts the containers without removing them",
|
||||
ComposeCmd("stop"),
|
||||
ServiceState("simple", "exited"),
|
||||
ServiceState("another", "exited")).
|
||||
Step("a stopped project is hidden from ls",
|
||||
ComposeCmd("ls", "--format", "json"),
|
||||
OutputNotContains(`"Name":"`+s.Project()+`"`)).
|
||||
Step("ls --all still lists the stopped project",
|
||||
ComposeCmd("ls", "--all", "--format", "json"),
|
||||
OutputContains(`"Name":"`+s.Project()+`"`)).
|
||||
Step("start brings the same containers back",
|
||||
ComposeCmd("start"),
|
||||
ServiceState("simple", "running"),
|
||||
ServiceState("another", "running"),
|
||||
NotRecreated("simple", "another"))
|
||||
}
|
||||
|
||||
func TestStartStopWithDependencies(t *testing.T) {
|
||||
c := NewParallelCLI(t)
|
||||
const projectName = "e2e-start-stop-with-dependencies"
|
||||
NewScenario(t, "stop must only halt the requested service, start must also start its dependencies").
|
||||
Step("up starts the service and its dependency",
|
||||
ComposeCmd("up", "-d"),
|
||||
ServiceState("foo", "running"),
|
||||
ServiceState("bar", "running")).
|
||||
Step("stop foo leaves the dependency running",
|
||||
ComposeCmd("stop", "foo"),
|
||||
ServiceState("foo", "exited"),
|
||||
ServiceState("bar", "running")).
|
||||
Step("stop halts the whole project",
|
||||
ComposeCmd("stop"),
|
||||
ServiceState("foo", "exited"),
|
||||
ServiceState("bar", "exited")).
|
||||
Step("start foo brings its dependency back too",
|
||||
ComposeCmd("start", "foo"),
|
||||
ServiceState("foo", "running"),
|
||||
ServiceState("bar", "running"),
|
||||
NotRecreated("foo", "bar"))
|
||||
}
|
||||
|
||||
defer c.RunDockerComposeCmd(t, "--project-name", projectName, "rm", "-fsv")
|
||||
|
||||
t.Run("Up", func(t *testing.T) {
|
||||
res := c.RunDockerComposeCmd(t, "-f", "./fixtures/dependencies/compose.yaml", "--project-name", projectName,
|
||||
"up", "-d")
|
||||
assert.Assert(t, strings.Contains(res.Combined(), "Container e2e-start-stop-with-dependencies-foo-1 Started"), res.Combined())
|
||||
assert.Assert(t, strings.Contains(res.Combined(), "Container e2e-start-stop-with-dependencies-bar-1 Started"), res.Combined())
|
||||
})
|
||||
|
||||
t.Run("stop foo", func(t *testing.T) {
|
||||
res := c.RunDockerComposeCmd(t, "--project-name", projectName, "stop", "foo")
|
||||
|
||||
assert.Assert(t, strings.Contains(res.Combined(), "Container e2e-start-stop-with-dependencies-foo-1 Stopped"), res.Combined())
|
||||
|
||||
res = c.RunDockerComposeCmd(t, "--project-name", projectName, "ps", "--status", "running")
|
||||
assert.Assert(t, strings.Contains(res.Combined(), "e2e-start-stop-with-dependencies-bar-1"), res.Combined())
|
||||
assert.Assert(t, !strings.Contains(res.Combined(), "e2e-start-stop-with-dependencies-foo-1"), res.Combined())
|
||||
})
|
||||
|
||||
t.Run("start foo", func(t *testing.T) {
|
||||
res := c.RunDockerComposeCmd(t, "--project-name", projectName, "stop")
|
||||
assert.Assert(t, strings.Contains(res.Combined(), "Container e2e-start-stop-with-dependencies-bar-1 Stopped"), res.Combined())
|
||||
|
||||
res = c.RunDockerComposeCmd(t, "--project-name", projectName, "start", "foo")
|
||||
out := res.Combined()
|
||||
assert.Assert(t, strings.Contains(out, "Container e2e-start-stop-with-dependencies-bar-1 Started"), out)
|
||||
assert.Assert(t, strings.Contains(out, "Container e2e-start-stop-with-dependencies-foo-1 Started"), out)
|
||||
|
||||
res = c.RunDockerComposeCmd(t, "--project-name", projectName, "ps", "--status", "running")
|
||||
out = res.Combined()
|
||||
assert.Assert(t, strings.Contains(out, "e2e-start-stop-with-dependencies-bar-1"), out)
|
||||
assert.Assert(t, strings.Contains(out, "e2e-start-stop-with-dependencies-foo-1"), out)
|
||||
})
|
||||
|
||||
t.Run("Up no-deps links", func(t *testing.T) {
|
||||
_ = c.RunDockerComposeCmd(t, "--project-name", projectName, "down")
|
||||
res := c.RunDockerComposeCmd(t, "-f", "./fixtures/links/compose.yaml", "--project-name", projectName, "up",
|
||||
"--no-deps", "-d", "foo")
|
||||
assert.Assert(t, strings.Contains(res.Combined(), "Container e2e-start-stop-with-dependencies-foo-1 Started"), res.Combined())
|
||||
assert.Assert(t, !strings.Contains(res.Combined(), "Container e2e-start-stop-with-dependencies-bar-1 Started"), res.Combined())
|
||||
})
|
||||
|
||||
t.Run("down", func(t *testing.T) {
|
||||
_ = c.RunDockerComposeCmd(t, "--project-name", projectName, "down")
|
||||
})
|
||||
func TestUpNoDeps(t *testing.T) {
|
||||
NewScenario(t, "up --no-deps must not create the service's dependencies").
|
||||
Step("up --no-deps starts only the requested service",
|
||||
ComposeCmd("up", "--no-deps", "-d", "foo"),
|
||||
ServiceState("foo", "running"),
|
||||
ServiceNotCreated("bar"))
|
||||
}
|
||||
|
||||
func TestStartStopWithOneOffs(t *testing.T) {
|
||||
|
|
@ -244,27 +195,21 @@ func TestStartStopMultipleServices(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestStartSingleServiceAndDependency(t *testing.T) {
|
||||
cli := NewParallelCLI(t, WithEnv(
|
||||
"COMPOSE_PROJECT_NAME=e2e-start-single-deps",
|
||||
"COMPOSE_FILE=./fixtures/start-stop/start-stop-deps.yaml"))
|
||||
t.Cleanup(func() {
|
||||
cli.RunDockerComposeCmd(t, "down", "--remove-orphans", "-v", "-t", "0")
|
||||
})
|
||||
|
||||
cli.RunDockerComposeCmd(t, "create", "desired")
|
||||
|
||||
res := cli.RunDockerComposeCmd(t, "start", "desired")
|
||||
desiredServices := []string{"desired", "dep_1", "dep_2"}
|
||||
for _, s := range desiredServices {
|
||||
startMsg := fmt.Sprintf("Container e2e-start-single-deps-%s-1 Started", s)
|
||||
assert.Assert(t, strings.Contains(res.Combined(), startMsg),
|
||||
fmt.Sprintf("Missing start message for service: %s\n%s", s, res.Combined()))
|
||||
}
|
||||
undesiredServices := []string{"another", "another_2"}
|
||||
for _, s := range undesiredServices {
|
||||
assert.Assert(t, !strings.Contains(res.Combined(), s),
|
||||
fmt.Sprintf("Shouldn't have message for service: %s\n%s", s, res.Combined()))
|
||||
}
|
||||
NewScenario(t, "start of a created service must start its dependency chain and nothing else").
|
||||
Step("create prepares the desired service and its dependencies only",
|
||||
ComposeCmd("create", "desired"),
|
||||
ServiceState("desired", "created"),
|
||||
ServiceState("dep_1", "created"),
|
||||
ServiceState("dep_2", "created"),
|
||||
ServiceNotCreated("another"),
|
||||
ServiceNotCreated("another_2")).
|
||||
Step("start brings up the desired service with its dependencies, nothing else",
|
||||
ComposeCmd("start", "desired"),
|
||||
ServiceState("desired", "running"),
|
||||
ServiceState("dep_1", "running"),
|
||||
ServiceState("dep_2", "running"),
|
||||
ServiceNotCreated("another"),
|
||||
ServiceNotCreated("another_2"))
|
||||
}
|
||||
|
||||
func TestStartStopMultipleFiles(t *testing.T) {
|
||||
|
|
|
|||
27
pkg/e2e/testdata/TestStartSingleServiceAndDependency/compose.yaml
vendored
Normal file
27
pkg/e2e/testdata/TestStartSingleServiceAndDependency/compose.yaml
vendored
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
services:
|
||||
desired:
|
||||
image: alpine
|
||||
init: true
|
||||
command: sleep infinity
|
||||
depends_on:
|
||||
- dep_1
|
||||
dep_1:
|
||||
image: alpine
|
||||
init: true
|
||||
command: sleep infinity
|
||||
depends_on:
|
||||
- dep_2
|
||||
dep_2:
|
||||
image: alpine
|
||||
init: true
|
||||
command: sleep infinity
|
||||
another:
|
||||
image: alpine
|
||||
init: true
|
||||
command: sleep infinity
|
||||
depends_on:
|
||||
- another_2
|
||||
another_2:
|
||||
image: alpine
|
||||
init: true
|
||||
command: sleep infinity
|
||||
9
pkg/e2e/testdata/TestStartStop/compose.yaml
vendored
Normal file
9
pkg/e2e/testdata/TestStartStop/compose.yaml
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
services:
|
||||
simple:
|
||||
image: alpine
|
||||
init: true
|
||||
command: sleep infinity
|
||||
another:
|
||||
image: alpine
|
||||
init: true
|
||||
command: sleep infinity
|
||||
11
pkg/e2e/testdata/TestStartStopWithDependencies/compose.yaml
vendored
Normal file
11
pkg/e2e/testdata/TestStartStopWithDependencies/compose.yaml
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
services:
|
||||
foo:
|
||||
image: alpine
|
||||
init: true
|
||||
command: sleep infinity
|
||||
depends_on:
|
||||
- bar
|
||||
bar:
|
||||
image: alpine
|
||||
init: true
|
||||
command: sleep infinity
|
||||
11
pkg/e2e/testdata/TestUpNoDeps/compose.yaml
vendored
Normal file
11
pkg/e2e/testdata/TestUpNoDeps/compose.yaml
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
services:
|
||||
foo:
|
||||
image: alpine
|
||||
init: true
|
||||
command: sleep infinity
|
||||
links:
|
||||
- bar
|
||||
bar:
|
||||
image: alpine
|
||||
init: true
|
||||
command: sleep infinity
|
||||
Loading…
Add table
Add a link
Reference in a new issue