package container // import "github.com/docker/docker/integration/container" import ( "context" "strconv" "testing" "time" containertypes "github.com/docker/docker/api/types/container" "github.com/docker/docker/integration/internal/container" "gotest.tools/v3/assert" "gotest.tools/v3/poll" "gotest.tools/v3/skip" ) // TestStopContainerWithTimeout checks that ContainerStop with // a timeout works as documented, i.e. in case of negative timeout // waiting is not limited (issue #35311). func TestStopContainerWithTimeout(t *testing.T) { skip.If(t, testEnv.OSType == "windows") defer setupTest(t)() client := testEnv.APIClient() ctx := context.Background() testCmd := container.WithCmd("sh", "-c", "sleep 2 && exit 42") testData := []struct { doc string timeout int expectedExitCode int }{ // In case container is forcefully killed, 137 is returned, // otherwise the exit code from the above script { "zero timeout: expect forceful container kill", 1, 0x40010004, }, { "too small timeout: expect forceful container kill", 2, 0x40010004, }, { "big enough timeout: expect graceful container stop", 120, 42, }, { "unlimited timeout: expect graceful container stop", -1, 42, }, } for _, d := range testData { d := d t.Run(strconv.Itoa(d.timeout), func(t *testing.T) { t.Parallel() id := container.Run(ctx, t, client, testCmd) err := client.ContainerStop(ctx, id, containertypes.StopOptions{Timeout: &d.timeout}) assert.NilError(t, err) poll.WaitOn(t, container.IsStopped(ctx, client, id), poll.WithDelay(100*time.Millisecond)) inspect, err := client.ContainerInspect(ctx, id) assert.NilError(t, err) assert.Equal(t, inspect.State.ExitCode, d.expectedExitCode) }) } }