Files
kata-containers/src/runtime/virtcontainers/nydusd_test.go
luodaowen.backend 2d9f89aec7 feature(nydusd): add nydusd support to introduse lazyload ability
Pulling image is the most time-consuming step in the container lifecycle. This PR
introduse nydus to kata container, it can lazily pull image when container start. So it
can speed up kata container create and start.

Fixes #2724

Signed-off-by: luodaowen.backend <luodaowen.backend@bytedance.com>
2022-02-11 21:41:17 +08:00

242 lines
5.7 KiB
Go

// Copyright (c) 2017 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
//
package virtcontainers
import (
"context"
"encoding/base64"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"strings"
"testing"
"github.com/stretchr/testify/assert"
)
func TestNydusdStart(t *testing.T) {
assert := assert.New(t)
// nolint: govet
type fields struct {
pid int
path string
sockPath string
apiSockPath string
sourcePath string
debug bool
extraArgs []string
startFn func(cmd *exec.Cmd) error
setupShareDirFn func() error
}
sourcePath, err := ioutil.TempDir("", "")
assert.NoError(err)
defer os.RemoveAll(sourcePath)
socketDir, err := ioutil.TempDir("", "")
assert.NoError(err)
defer os.RemoveAll(socketDir)
sockPath := filepath.Join(socketDir, "vhost-user.sock")
apiSockPath := filepath.Join(socketDir, "api.sock")
validConfig := fields{
path: "/usr/bin/nydusd",
sockPath: sockPath,
apiSockPath: apiSockPath,
sourcePath: sourcePath,
startFn: func(cmd *exec.Cmd) error {
cmd.Process = &os.Process{}
return nil
},
setupShareDirFn: func() error { return nil },
}
SourcePathNoExist := validConfig
SourcePathNoExist.sourcePath = "/tmp/path/to/nydusd/sourcepath"
// nolint: govet
tests := []struct {
name string
fields fields
wantErr bool
}{
{"empty config", fields{}, true},
{"directory source path not exist", SourcePathNoExist, true},
{"valid config", validConfig, false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
nd := &nydusd{
path: tt.fields.path,
sockPath: tt.fields.sockPath,
apiSockPath: tt.fields.apiSockPath,
sourcePath: tt.fields.sourcePath,
extraArgs: tt.fields.extraArgs,
debug: tt.fields.debug,
pid: tt.fields.pid,
startFn: tt.fields.startFn,
setupShareDirFn: tt.fields.setupShareDirFn,
}
ctx := context.Background()
_, err := nd.Start(ctx, nil)
if (err != nil) != tt.wantErr {
t.Errorf("nydusd.Start() error = %v, wantErr %v", err, tt.wantErr)
return
}
})
}
}
func TestNydusdArgs(t *testing.T) {
assert := assert.New(t)
nd := &nydusd{
path: "/usr/bin/nydusd",
sockPath: "/var/lib/vhost-user.sock",
apiSockPath: "/var/lib/api.sock",
debug: true,
}
expected := "--log-level debug --apisock /var/lib/api.sock --sock /var/lib/vhost-user.sock"
args, err := nd.args()
assert.NoError(err)
assert.Equal(expected, strings.Join(args, " "))
nd.debug = false
expected = "--log-level info --apisock /var/lib/api.sock --sock /var/lib/vhost-user.sock"
args, err = nd.args()
assert.NoError(err)
assert.Equal(expected, strings.Join(args, " "))
}
func TestNydusdValid(t *testing.T) {
assert := assert.New(t)
sourcePath, err := ioutil.TempDir("", "")
assert.NoError(err)
defer os.RemoveAll(sourcePath)
socketDir, err := ioutil.TempDir("", "")
assert.NoError(err)
defer os.RemoveAll(socketDir)
sockPath := filepath.Join(socketDir, "vhost-user.sock")
apiSockPath := filepath.Join(socketDir, "api.sock")
newNydsudFunc := func() *nydusd {
return &nydusd{
path: "/usr/bin/nydusd",
sourcePath: sourcePath,
sockPath: sockPath,
apiSockPath: apiSockPath,
}
}
nd := newNydsudFunc()
err = nd.valid()
assert.NoError(err)
nd = newNydsudFunc()
nd.path = ""
err = nd.valid()
assert.Equal(errNydusdDaemonPathInvalid, err)
nd = newNydsudFunc()
nd.sockPath = ""
err = nd.valid()
assert.Equal(errNydusdSockPathInvalid, err)
nd = newNydsudFunc()
nd.apiSockPath = ""
err = nd.valid()
assert.Equal(errNydusdAPISockPathInvalid, err)
nd = newNydsudFunc()
nd.sourcePath = ""
err = nd.valid()
assert.Equal(errNydusdSourcePathInvalid, err)
}
func TestParseExtraOption(t *testing.T) {
tests := []struct {
name string
option string
wantErr bool
}{
{
name: "valid option",
option: "extraoption=" + base64.StdEncoding.EncodeToString([]byte("{\"source\":\"/path/to/bootstrap\",\"config\":\"config content\",\"snapshotdir\":\"/path/to/snapshotdir\"}")),
wantErr: false,
},
{
name: "no extra option",
option: base64.StdEncoding.EncodeToString([]byte("{\"source\":/path/to/bootstrap,\"config\":config content,\"snapshotdir\":/path/to/snapshotdir}")),
wantErr: true,
},
{
name: "no source",
option: "extraoption=" + base64.StdEncoding.EncodeToString([]byte("{\"config\":config content,\"snapshotdir\":/path/to/snapshotdir}")),
wantErr: true,
},
{
name: "no config",
option: "extraoption=" + base64.StdEncoding.EncodeToString([]byte("{\"source\":/path/to/bootstrap,\"snapshotdir\":/path/to/snapshotdir}")),
wantErr: true,
},
{
name: "no snapshotdir",
option: "extraoption=" + base64.StdEncoding.EncodeToString([]byte("{\"source\":/path/to/bootstrap,\"config\":config content}")),
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
_, err := parseExtraOption([]string{tt.option})
if (err != nil) != tt.wantErr {
t.Errorf("parseExtraOption error = %v, wantErr %v", err, tt.wantErr)
return
}
})
}
}
func TestCheckRafsMountPointValid(t *testing.T) {
tests := []struct {
mountPoint string
valid bool
}{
{
mountPoint: "/rafs/xxxxaaa/lowerdir",
valid: true,
},
{
mountPoint: "/",
valid: false,
},
{
mountPoint: "/rafs",
valid: false,
},
{
mountPoint: "/xxxx",
valid: false,
},
{
mountPoint: "/rafs/aaaaa/xxxx",
valid: false,
},
{
mountPoint: "/rafs//lowerdir",
valid: false,
},
}
for _, tt := range tests {
res := checkRafsMountPointValid(tt.mountPoint)
if res != tt.valid {
t.Errorf("test %v get %v, but want %v", tt, res, tt.valid)
}
}
}