Files
kata-containers/src/runtime/virtcontainers/nydusd_test.go
liubin 2ae807fd29 nydus: wait nydusd API server ready before mounting share fs
If the API server is not ready, the mount call will fail, so before
mounting share fs, we should wait the nydusd is started and
the API server is ready.

Fixes: #4710

Signed-off-by: liubin <liubin0329@gmail.com>
Signed-off-by: Bin Liu <bin@hyper.sh>
2022-08-08 16:18:38 +08:00

236 lines
5.5 KiB
Go

// Copyright (c) 2017 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
//
package virtcontainers
import (
"context"
"encoding/base64"
"os"
"os/exec"
"path/filepath"
"strings"
"testing"
"github.com/stretchr/testify/assert"
)
func TestNydusdStart(t *testing.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
waitFn func() error
setupShareDirFn func() error
}
sourcePath := t.TempDir()
socketDir := t.TempDir()
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
},
waitFn: func() error {
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,
waitFn: tt.fields.waitFn,
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 := t.TempDir()
socketDir := t.TempDir()
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)
}
}
}