X Tutup
Skip to content

Commit 651aaff

Browse files
committed
Update integration test to support windows
Signed-off-by: Kenfe-Mickael Laventure <mickael.laventure@gmail.com>
1 parent 79d04de commit 651aaff

14 files changed

+555
-214
lines changed

benchmark_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ func BenchmarkContainerCreate(b *testing.B) {
2020
b.Error(err)
2121
return
2222
}
23-
spec, err := GenerateSpec(WithImageConfig(ctx, image), WithProcessArgs("true"))
23+
spec, err := GenerateSpec(WithImageConfig(ctx, image), withTrue())
2424
if err != nil {
2525
b.Error(err)
2626
return
@@ -63,7 +63,7 @@ func BenchmarkContainerStart(b *testing.B) {
6363
b.Error(err)
6464
return
6565
}
66-
spec, err := GenerateSpec(WithImageConfig(ctx, image), WithProcessArgs("true"))
66+
spec, err := GenerateSpec(WithImageConfig(ctx, image), withTrue())
6767
if err != nil {
6868
b.Error(err)
6969
return

checkpoint_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// +build !windows
2+
13
package containerd
24

35
import (

client_test.go

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"fmt"
88
"os"
99
"os/exec"
10+
"runtime"
1011
"syscall"
1112
"testing"
1213
"time"
@@ -17,19 +18,14 @@ import (
1718
"github.com/containerd/containerd/testutil"
1819
)
1920

20-
const (
21-
defaultRoot = "/var/lib/containerd-test"
22-
testImage = "docker.io/library/alpine:latest"
23-
)
24-
2521
var (
2622
address string
2723
noDaemon bool
2824
supportsCriu bool
2925
)
3026

3127
func init() {
32-
flag.StringVar(&address, "address", "/run/containerd-test/containerd.sock", "The address to the containerd socket for use in the tests")
28+
flag.StringVar(&address, "address", defaultAddress, "The address to the containerd socket for use in the tests")
3329
flag.BoolVar(&noDaemon, "no-daemon", false, "Do not start a dedicated daemon for the tests")
3430
flag.Parse()
3531
}
@@ -57,11 +53,15 @@ func TestMain(m *testing.M) {
5753
defer cancel()
5854

5955
if !noDaemon {
56+
os.RemoveAll(defaultRoot)
57+
6058
// setup a new containerd daemon if !testing.Short
6159
cmd = exec.Command("containerd",
6260
"--root", defaultRoot,
6361
"--address", address,
62+
"--log-level", "debug",
6463
)
64+
cmd.Stdout = buf
6565
cmd.Stderr = buf
6666
if err := cmd.Start(); err != nil {
6767
cmd.Wait()
@@ -94,14 +94,22 @@ func TestMain(m *testing.M) {
9494
}).Info("running tests against containerd")
9595

9696
// pull a seed image
97-
if _, err = client.Pull(ctx, testImage, WithPullUnpack); err != nil {
98-
cmd.Process.Signal(syscall.SIGTERM)
99-
cmd.Wait()
100-
fmt.Fprintf(os.Stderr, "%s: %s", err, buf.String())
97+
if runtime.GOOS != "windows" { // TODO: remove once pull is supported on windows
98+
if _, err = client.Pull(ctx, testImage, WithPullUnpack); err != nil {
99+
cmd.Process.Signal(syscall.SIGTERM)
100+
cmd.Wait()
101+
fmt.Fprintf(os.Stderr, "%s: %s", err, buf.String())
102+
os.Exit(1)
103+
}
104+
}
105+
106+
if err := platformTestSetup(client); err != nil {
107+
fmt.Fprintln(os.Stderr, "platform test setup failed", err)
101108
os.Exit(1)
102109
}
110+
103111
if err := client.Close(); err != nil {
104-
fmt.Fprintln(os.Stderr, err)
112+
fmt.Fprintln(os.Stderr, "failed to close client", err)
105113
}
106114

107115
// run the test
@@ -110,13 +118,15 @@ func TestMain(m *testing.M) {
110118
if !noDaemon {
111119
// tear down the daemon and resources created
112120
if err := cmd.Process.Signal(syscall.SIGTERM); err != nil {
113-
fmt.Fprintln(os.Stderr, err)
121+
if err := cmd.Process.Kill(); err != nil {
122+
fmt.Fprintln(os.Stderr, "failed to signal containerd", err)
123+
}
114124
}
115125
if err := cmd.Wait(); err != nil {
116-
fmt.Fprintln(os.Stderr, err)
126+
fmt.Fprintln(os.Stderr, "failed to wait for containerd", err)
117127
}
118128
if err := os.RemoveAll(defaultRoot); err != nil {
119-
fmt.Fprintln(os.Stderr, err)
129+
fmt.Fprintln(os.Stderr, "failed to remove test root dir", err)
120130
os.Exit(1)
121131
}
122132
// only print containerd logs if the test failed
@@ -171,6 +181,11 @@ func TestNewClient(t *testing.T) {
171181
}
172182

173183
func TestImagePull(t *testing.T) {
184+
if runtime.GOOS == "windows" {
185+
// TODO: remove once Windows has a snapshotter
186+
t.Skip("Windows does not have a snapshotter yet")
187+
}
188+
174189
client, err := newClient(t, address)
175190
if err != nil {
176191
t.Fatal(err)

client_unix_test.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// +build !windows
2+
3+
package containerd
4+
5+
const (
6+
defaultRoot = "/var/lib/containerd-test"
7+
defaultAddress = "/run/containerd-test/containerd.sock"
8+
testImage = "docker.io/library/alpine:latest"
9+
)
10+
11+
func platformTestSetup(client *Client) error {
12+
return nil
13+
}

client_windows_test.go

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
package containerd
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"os"
7+
"path/filepath"
8+
9+
"github.com/pkg/errors"
10+
)
11+
12+
const (
13+
defaultAddress = `\\.\pipe\containerd-containerd-test`
14+
testImage = "docker.io/library/go:nanoserver"
15+
)
16+
17+
var (
18+
dockerLayerFolders []string
19+
20+
defaultRoot = filepath.Join(os.Getenv("programfiles"), "containerd", "root-test")
21+
)
22+
23+
func platformTestSetup(client *Client) error {
24+
var (
25+
roots []string
26+
layerChains = make(map[string]string)
27+
)
28+
// Since we can't pull images yet, we'll piggyback on the default
29+
// docker's images
30+
wfPath := `C:\ProgramData\docker\windowsfilter`
31+
wf, err := os.Open(wfPath)
32+
if err != nil {
33+
return errors.Wrapf(err, "failed to access docker layers @ %s", wfPath)
34+
}
35+
defer wf.Close()
36+
entries, err := wf.Readdirnames(0)
37+
if err != nil {
38+
return errors.Wrapf(err, "failed to read %s entries", wfPath)
39+
}
40+
41+
for _, fn := range entries {
42+
layerChainPath := filepath.Join(wfPath, fn, "layerchain.json")
43+
lfi, err := os.Stat(layerChainPath)
44+
switch {
45+
case err == nil && lfi.Mode().IsRegular():
46+
f, err := os.OpenFile(layerChainPath, os.O_RDONLY, 0660)
47+
if err != nil {
48+
fmt.Fprintln(os.Stderr,
49+
errors.Wrapf(err, "failed to open %s", layerChainPath))
50+
continue
51+
}
52+
defer f.Close()
53+
l := make([]string, 0)
54+
if err := json.NewDecoder(f).Decode(&l); err != nil {
55+
fmt.Fprintln(os.Stderr,
56+
errors.Wrapf(err, "failed to decode %s", layerChainPath))
57+
continue
58+
}
59+
switch {
60+
case len(l) == 1:
61+
layerChains[l[0]] = filepath.Join(wfPath, fn)
62+
case len(l) > 1:
63+
fmt.Fprintf(os.Stderr, "Too many entries in %s: %d", layerChainPath, len(l))
64+
case len(l) == 0:
65+
roots = append(roots, filepath.Join(wfPath, fn))
66+
}
67+
case os.IsNotExist(err):
68+
// keep on going
69+
default:
70+
return errors.Wrapf(err, "error trying to access %s", layerChainPath)
71+
}
72+
}
73+
74+
// They'll be 2 roots, just take the first one
75+
l := roots[0]
76+
dockerLayerFolders = append(dockerLayerFolders, l)
77+
for {
78+
l = layerChains[l]
79+
if l == "" {
80+
break
81+
}
82+
83+
dockerLayerFolders = append([]string{l}, dockerLayerFolders...)
84+
}
85+
86+
return nil
87+
}

container_linux_test.go

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
// +build linux
2+
3+
package containerd
4+
5+
import (
6+
"syscall"
7+
"testing"
8+
9+
"github.com/containerd/cgroups"
10+
specs "github.com/opencontainers/runtime-spec/specs-go"
11+
)
12+
13+
func TestContainerUpdate(t *testing.T) {
14+
client, err := newClient(t, address)
15+
if err != nil {
16+
t.Fatal(err)
17+
}
18+
defer client.Close()
19+
20+
var (
21+
ctx, cancel = testContext()
22+
id = t.Name()
23+
)
24+
defer cancel()
25+
26+
image, err := client.GetImage(ctx, testImage)
27+
if err != nil {
28+
t.Error(err)
29+
return
30+
}
31+
spec, err := generateSpec(WithImageConfig(ctx, image), withProcessArgs("sleep", "30"))
32+
if err != nil {
33+
t.Error(err)
34+
return
35+
}
36+
limit := int64(32 * 1024 * 1024)
37+
spec.Linux.Resources.Memory = &specs.LinuxMemory{
38+
Limit: &limit,
39+
}
40+
container, err := client.NewContainer(ctx, id, WithSpec(spec), WithNewRootFS(id, image))
41+
if err != nil {
42+
t.Error(err)
43+
return
44+
}
45+
defer container.Delete(ctx, WithRootFSDeletion)
46+
47+
task, err := container.NewTask(ctx, empty())
48+
if err != nil {
49+
t.Error(err)
50+
return
51+
}
52+
defer task.Delete(ctx)
53+
54+
statusC := make(chan uint32, 1)
55+
go func() {
56+
status, err := task.Wait(ctx)
57+
if err != nil {
58+
t.Error(err)
59+
}
60+
statusC <- status
61+
}()
62+
63+
// check that the task has a limit of 32mb
64+
cgroup, err := cgroups.Load(cgroups.V1, cgroups.PidPath(int(task.Pid())))
65+
if err != nil {
66+
t.Error(err)
67+
return
68+
}
69+
stat, err := cgroup.Stat(cgroups.IgnoreNotExist)
70+
if err != nil {
71+
t.Error(err)
72+
return
73+
}
74+
if int64(stat.Memory.Usage.Limit) != limit {
75+
t.Errorf("expected memory limit to be set to %d but received %d", limit, stat.Memory.Usage.Limit)
76+
return
77+
}
78+
limit = 64 * 1024 * 1024
79+
if err := task.Update(ctx, WithResources(&specs.LinuxResources{
80+
Memory: &specs.LinuxMemory{
81+
Limit: &limit,
82+
},
83+
})); err != nil {
84+
t.Error(err)
85+
}
86+
// check that the task has a limit of 64mb
87+
if stat, err = cgroup.Stat(cgroups.IgnoreNotExist); err != nil {
88+
t.Error(err)
89+
return
90+
}
91+
if int64(stat.Memory.Usage.Limit) != limit {
92+
t.Errorf("expected memory limit to be set to %d but received %d", limit, stat.Memory.Usage.Limit)
93+
}
94+
if err := task.Kill(ctx, syscall.SIGKILL); err != nil {
95+
t.Error(err)
96+
return
97+
}
98+
99+
<-statusC
100+
}

0 commit comments

Comments
 (0)
X Tutup