Skip to content

Commit 0e2bd47

Browse files
committed
container: add unit test for container start with checkpoint
add unit test for container start with checkpoint. Signed-off-by: ChengyuZhu6 <[email protected]>
1 parent 2c4729c commit 0e2bd47

File tree

1 file changed

+50
-0
lines changed

1 file changed

+50
-0
lines changed

cmd/nerdctl/container/container_start_linux_test.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,15 @@ import (
2020
"bytes"
2121
"errors"
2222
"io"
23+
"strconv"
2324
"strings"
2425
"testing"
26+
"time"
2527

2628
"gotest.tools/v3/assert"
2729

2830
"github.com/containerd/nerdctl/mod/tigron/expect"
31+
"github.com/containerd/nerdctl/mod/tigron/require"
2932
"github.com/containerd/nerdctl/mod/tigron/test"
3033
"github.com/containerd/nerdctl/mod/tigron/tig"
3134

@@ -77,3 +80,50 @@ func TestStartDetachKeys(t *testing.T) {
7780

7881
testCase.Run(t)
7982
}
83+
84+
func TestStartWithCheckpoint(t *testing.T) {
85+
86+
testCase := nerdtest.Setup()
87+
testCase.Require = require.Not(nerdtest.Rootless)
88+
89+
testCase.Setup = func(data test.Data, helpers test.Helpers) {
90+
// Use an in-memory tmpfs to model in-memory state without introducing extra processes
91+
// Single PID 1 shell: continuously increment a counter and write to /state/counter (tmpfs)
92+
helpers.Ensure("run", "-d", "--name", data.Identifier(), "--tmpfs", "/state", testutil.CommonImage,
93+
"sh", "-c", `i=0; while true; do i=$((i+1)); printf "%d\n" "$i" >/state/counter; sleep 0.2; done`)
94+
// Give some time for the counter to increase before checkpoint to validate continuity after restore
95+
time.Sleep(1 * time.Second)
96+
helpers.Ensure("checkpoint", "create", data.Identifier(), data.Identifier()+"-checkpoint")
97+
}
98+
99+
testCase.Cleanup = func(data test.Data, helpers test.Helpers) {
100+
helpers.Anyhow("rm", "-f", data.Identifier())
101+
}
102+
103+
testCase.Command = func(data test.Data, helpers test.Helpers) test.TestableCommand {
104+
return helpers.Command("start", "--checkpoint", data.Identifier()+"-checkpoint", data.Identifier())
105+
}
106+
107+
testCase.Expected = func(data test.Data, helpers test.Helpers) *test.Expected {
108+
return &test.Expected{
109+
ExitCode: 0,
110+
Output: expect.All(
111+
func(_ string, t tig.T) {
112+
// Validate in-memory state continuity via tmpfs: counter should not reset and must keep increasing
113+
// Short delay to allow the container to resume; if the counter had reset to 0, it could not reach >5 this fast
114+
time.Sleep(200 * time.Millisecond)
115+
c1Str := strings.TrimSpace(helpers.Capture("exec", data.Identifier(), "cat", "/state/counter"))
116+
var parseErrs []error
117+
c1, err1 := strconv.Atoi(c1Str)
118+
if err1 != nil {
119+
parseErrs = append(parseErrs, err1)
120+
}
121+
assert.Assert(t, len(parseErrs) == 0, "failed to parse counter values: %v", parseErrs)
122+
assert.Assert(t, c1 > 5, "tmpfs in-memory counter seems reset or too small: %d", c1)
123+
},
124+
),
125+
}
126+
}
127+
128+
testCase.Run(t)
129+
}

0 commit comments

Comments
 (0)