Skip to content

Commit

Permalink
tests: Add lots of new unit tests
Browse files Browse the repository at this point in the history
Add new tests for agent, gRPC and mount functions.

Fixes: kata-containers#561.

Signed-off-by: James O. D. Hunt <[email protected]>
  • Loading branch information
jodh-intel committed Jul 18, 2019
1 parent d4a22d1 commit 4354b24
Show file tree
Hide file tree
Showing 3 changed files with 1,053 additions and 9 deletions.
258 changes: 254 additions & 4 deletions agent_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
package main

import (
"errors"
"fmt"
"io/ioutil"
"os"
Expand All @@ -18,6 +19,8 @@ import (
"testing"

"github.com/opencontainers/runc/libcontainer"
"github.com/opencontainers/runc/libcontainer/configs"
"github.com/opencontainers/runc/libcontainer/specconv"
specs "github.com/opencontainers/runtime-spec/specs-go"
"github.com/stretchr/testify/assert"
"golang.org/x/net/context"
Expand All @@ -27,6 +30,7 @@ const (
testExecID = "testExecID"
testContainerID = "testContainerID"
testFileMode = os.FileMode(0640)
testDirMode = os.FileMode(0750)
)

func createFileWithPerms(file, contents string, perms os.FileMode) error {
Expand All @@ -51,6 +55,12 @@ func skipUnlessRoot(t *testing.T) {
}
}

func skipIfRoot(t *testing.T) {
if os.Getuid() == 0 {
t.Skip("Test disabled as requires non-root user")
}
}

func TestClosePostStartFDsAllNil(t *testing.T) {
p := &process{}

Expand Down Expand Up @@ -216,25 +226,107 @@ func TestSetSandboxStorage(t *testing.T) {
assert.Equal(t, 2, refCount, "Invalid refcount, got %d expected 2", refCount)
}

func bindMount(src, dest string) error {
return mount(src, dest, "bind", syscall.MS_BIND, "")
}

func TestRemoveSandboxStorage(t *testing.T) {
skipUnlessRoot(t)

s := &sandbox{
containers: make(map[string]*container),
}

tmpDir, err := ioutil.TempDir("", "")
assert.NoError(t, err)
defer os.RemoveAll(tmpDir)

src, err := ioutil.TempDir(tmpDir, "src")
assert.NoError(t, err)

dest, err := ioutil.TempDir(tmpDir, "dest")
assert.NoError(t, err)

emptyDir, err := ioutil.TempDir(tmpDir, "empty")
assert.NoError(t, err)

err = s.removeSandboxStorage(emptyDir)
assert.Error(t, err, "expect failure as directory is not a mountpoint")

err = s.removeSandboxStorage("")
assert.Error(t, err)

invalidDir := filepath.Join(emptyDir, "invalid")

err = s.removeSandboxStorage(invalidDir)
assert.Error(t, err)

// Now, create a double mount as this guarantees the directory cannot
// be deleted after the first unmount
for range []int{0, 1} {
err = bindMount(src, dest)
assert.NoError(t, err)
}

err = s.removeSandboxStorage(dest)
assert.Error(t, err, "expect fail as deletion cannot happen due to the second mount")

// This time it should work as the previous two calls have undone the double mount.
err = s.removeSandboxStorage(dest)
assert.NoError(t, err)

s.storages = make(map[string]*sandboxStorage)
err := s.removeSandboxStorage("/tmp/testEphePath/")
err = s.removeSandboxStorage("/tmp/testEphePath/")

assert.Error(t, err, "Should fail because sandbox storage doesn't exist")
}

func TestUnsetAndRemoveSandboxStorage(t *testing.T) {
skipUnlessRoot(t)

s := &sandbox{
containers: make(map[string]*container),
storages: make(map[string]*sandboxStorage),
}

s.storages = make(map[string]*sandboxStorage)
err := s.unsetAndRemoveSandboxStorage("/tmp/testEphePath/")
path := "/tmp/testEphePath"
err := s.unsetAndRemoveSandboxStorage(path)

assert.Error(t, err, "Should fail because sandbox storage doesn't exist")

tmpDir, err := ioutil.TempDir("", "")
assert.NoError(t, err)
defer os.RemoveAll(tmpDir)

src, err := ioutil.TempDir(tmpDir, "src")
assert.NoError(t, err)

dest, err := ioutil.TempDir(tmpDir, "dest")
assert.NoError(t, err)

err = bindMount(src, dest)
assert.NoError(t, err)

newPath := s.setSandboxStorage(dest)
assert.True(t, newPath)

err = s.unsetAndRemoveSandboxStorage(dest)
assert.NoError(t, err)

// Create another directory
dir, err := ioutil.TempDir(tmpDir, "dir")
assert.NoError(t, err)

// Register it
newPath = s.setSandboxStorage(dir)
assert.True(t, newPath)

// Now, delete the directory to ensure the following call fails
err = os.RemoveAll(dir)
assert.NoError(t, err)

err = s.unsetAndRemoveSandboxStorage(dir)
assert.Error(t, err, "should fail as path has been deleted")
}

func TestUnSetSandboxStorage(t *testing.T) {
Expand Down Expand Up @@ -342,7 +434,7 @@ func TestDeleteContainer(t *testing.T) {

func TestGetProcessFromSandbox(t *testing.T) {
s := &sandbox{
running: true,
running: false,
containers: make(map[string]*container),
}

Expand All @@ -358,6 +450,17 @@ func TestGetProcessFromSandbox(t *testing.T) {
c.processes[testExecID] = p
s.containers[testContainerID] = c

_, _, err := s.getProcess(testContainerID, testExecID)
assert.Error(t, err, "sandbox not running")

s.running = true

_, _, err = s.getProcess("invalidCID", testExecID)
assert.Error(t, err, "invalid container ID")

_, _, err = s.getProcess(testContainerID, "invalidExecID")
assert.Error(t, err, "invalid exec ID")

proc, _, err := s.getProcess(testContainerID, testExecID)
assert.Nil(t, err, "%v", err)

Expand Down Expand Up @@ -427,6 +530,38 @@ func TestMountToRootfs(t *testing.T) {
}
}

func TestMountToRootfsFailed(t *testing.T) {
assert := assert.New(t)

if os.Geteuid() == 0 {
t.Skip("need non-root")
}

tmpDir, err := ioutil.TempDir("", "")
assert.NoError(err)
defer os.RemoveAll(tmpDir)

existingDir := filepath.Join(tmpDir, "exists")
err = os.Mkdir(existingDir, 0750)
assert.NoError(err)

dir := filepath.Join(tmpDir, "dir")

mounts := []initMount{
{"", "", "", []string{}},
{"", "", existingDir, []string{}},
{"", "", dir, []string{}},
}

for i, m := range mounts {
msg := fmt.Sprintf("test[%d]: %+v\n", i, m)

err := mountToRootfs(m)
assert.Error(err, msg)
}

}

func TestGetCgroupMountsFailed(t *testing.T) {
cgprocDir, err := ioutil.TempDir("", "proc-cgroup")
assert.Nil(t, err, "%v", err)
Expand Down Expand Up @@ -489,6 +624,9 @@ func TestAddGuestHooks(t *testing.T) {
s.scanGuestHooks(hookPath)
assert.False(s.guestHooksPresent)

// No test to perform but this does check the function doesn't panic.
s.addGuestHooks(nil)

spec := &specs.Spec{}
s.addGuestHooks(spec)
assert.True(len(spec.Hooks.Poststop) == 0)
Expand All @@ -506,6 +644,118 @@ func TestAddGuestHooks(t *testing.T) {
assert.True(strings.Contains(spec.Hooks.Poststop[0].Path, "executable"))
}

type myPostStopHook struct {
}

const hookErrorMsg = "hook always fails"

func (h *myPostStopHook) Run(_ *specs.State) error {
return errors.New(hookErrorMsg)
}

func TestContainerRemoveContainer(t *testing.T) {
skipUnlessRoot(t)

assert := assert.New(t)

cid := "foo"

dir, err := ioutil.TempDir("", "")
assert.NoError(err)
defer os.RemoveAll(dir)

containerPath := filepath.Join(dir, "container")

invalidMountDir := filepath.Join(dir, "bad-mount-dir")

containerFactory, err := libcontainer.New(containerPath)
assert.NoError(err)

spec := &specs.Spec{
Root: &specs.Root{
Path: containerPath,
Readonly: false,
},
}

hooks := &configs.Hooks{
Poststop: []configs.Hook{
&myPostStopHook{},
},
}

mounts := []string{invalidMountDir}

type testData struct {
withBadMount bool
withBadHook bool
expectError bool
}

data := []testData{
{false, false, false},
{true, false, true},
{false, true, true},
{true, true, true},
}

for i, d := range data {
msg := fmt.Sprintf("test[%d]: %+v\n", i, d)

config, err := specconv.CreateLibcontainerConfig(&specconv.CreateOpts{
CgroupName: cid,
NoNewKeyring: true,
Spec: spec,
NoPivotRoot: true,
})
assert.NoError(err, msg)

if d.withBadHook {
config.Hooks = hooks
}

libContainerContainer, err := containerFactory.Create(cid, config)
assert.NoError(err, msg)

c := container{
ctx: context.Background(),
id: cid,
processes: make(map[string]*process),
container: libContainerContainer,
}

if d.withBadMount {
c.mounts = mounts
}

err = c.removeContainer()
if d.expectError {
assert.Error(err, msg)

if d.withBadHook {
assert.Equal(err.Error(), hookErrorMsg, msg)
}

continue
}

assert.NoError(err, msg)
}
}

func TestGetGRPCContext(t *testing.T) {
assert := assert.New(t)

grpcContext = nil
ctx := getGRPCContext()
assert.NotNil(ctx)

grpcContext = context.Background()
ctx = getGRPCContext()
assert.NotNil(ctx)
assert.Equal(ctx, grpcContext)
}

func TestGetMemory(t *testing.T) {
assert := assert.New(t)

Expand Down
Loading

0 comments on commit 4354b24

Please sign in to comment.