mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-10-22 04:18:53 +00:00
Add a heuristic to ensure the amount of memory allocated to the hypervisor is bigger than the size of the image. This catches simple configuration issues where `default_memory=` is set to a smaller value than the size of either the `image=` or `initrd=` files. If the configured image type is `initrd`, fail but only warn in the logs for `image` as although it seems a highly unlikely scenario, it is permitted. Update tests to ensure that created resources have `>0` bytes. Fixes #636. Signed-off-by: James O. D. Hunt <james.o.hunt@intel.com>
399 lines
8.1 KiB
Go
399 lines
8.1 KiB
Go
// Copyright (c) 2017 Intel Corporation
|
|
//
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
//
|
|
|
|
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"io/ioutil"
|
|
"os"
|
|
"path"
|
|
"path/filepath"
|
|
"syscall"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
func TestFileExists(t *testing.T) {
|
|
dir, err := ioutil.TempDir(testDir, "")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer os.RemoveAll(dir)
|
|
|
|
file := filepath.Join(dir, "foo")
|
|
|
|
assert.False(t, fileExists(file),
|
|
fmt.Sprintf("File %q should not exist", file))
|
|
|
|
err = createEmptyFile(file)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
assert.True(t, fileExists(file),
|
|
fmt.Sprintf("File %q should exist", file))
|
|
}
|
|
|
|
func TestIsEphemeralStorage(t *testing.T) {
|
|
sampleEphePath := "/var/lib/kubelet/pods/366c3a75-4869-11e8-b479-507b9ddd5ce4/volumes/kubernetes.io~empty-dir/cache-volume"
|
|
isEphe := IsEphemeralStorage(sampleEphePath)
|
|
if !isEphe {
|
|
t.Fatalf("Unable to correctly determine volume type")
|
|
}
|
|
|
|
sampleEphePath = "/var/lib/kubelet/pods/366c3a75-4869-11e8-b479-507b9ddd5ce4/volumes/cache-volume"
|
|
isEphe = IsEphemeralStorage(sampleEphePath)
|
|
if isEphe {
|
|
t.Fatalf("Unable to correctly determine volume type")
|
|
}
|
|
}
|
|
|
|
func TestGetFileContents(t *testing.T) {
|
|
type testData struct {
|
|
contents string
|
|
}
|
|
|
|
data := []testData{
|
|
{""},
|
|
{" "},
|
|
{"\n"},
|
|
{"\n\n"},
|
|
{"\n\n\n"},
|
|
{"foo"},
|
|
{"foo\nbar"},
|
|
{"processor : 0\nvendor_id : GenuineIntel\n"},
|
|
}
|
|
|
|
dir, err := ioutil.TempDir(testDir, "")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer os.RemoveAll(dir)
|
|
|
|
file := filepath.Join(dir, "foo")
|
|
|
|
// file doesn't exist
|
|
_, err = getFileContents(file)
|
|
assert.Error(t, err)
|
|
|
|
for _, d := range data {
|
|
// create the file
|
|
err = ioutil.WriteFile(file, []byte(d.contents), testFileMode)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer os.Remove(file)
|
|
|
|
contents, err := getFileContents(file)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, contents, d.contents)
|
|
}
|
|
}
|
|
|
|
func TestGetKernelVersion(t *testing.T) {
|
|
type testData struct {
|
|
contents string
|
|
expectedVersion string
|
|
expectError bool
|
|
}
|
|
|
|
const validVersion = "1.2.3-4.5.x86_64"
|
|
validContents := fmt.Sprintf("Linux version %s blah blah blah ...", validVersion)
|
|
|
|
data := []testData{
|
|
{"", "", true},
|
|
{"invalid contents", "", true},
|
|
{"a b c", "c", false},
|
|
{validContents, validVersion, false},
|
|
}
|
|
|
|
tmpdir, err := ioutil.TempDir("", "")
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
defer os.RemoveAll(tmpdir)
|
|
|
|
subDir := filepath.Join(tmpdir, "subdir")
|
|
err = os.MkdirAll(subDir, testDirMode)
|
|
assert.NoError(t, err)
|
|
|
|
_, err = getKernelVersion()
|
|
assert.Error(t, err)
|
|
|
|
file := filepath.Join(tmpdir, "proc-version")
|
|
|
|
// override
|
|
procVersion = file
|
|
|
|
_, err = getKernelVersion()
|
|
// ENOENT
|
|
assert.Error(t, err)
|
|
assert.True(t, os.IsNotExist(err))
|
|
|
|
for _, d := range data {
|
|
err := createFile(file, d.contents)
|
|
assert.NoError(t, err)
|
|
|
|
version, err := getKernelVersion()
|
|
if d.expectError {
|
|
assert.Error(t, err, fmt.Sprintf("%+v", d))
|
|
continue
|
|
} else {
|
|
assert.NoError(t, err, fmt.Sprintf("%+v", d))
|
|
assert.Equal(t, d.expectedVersion, version)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestGetDistroDetails(t *testing.T) {
|
|
type testData struct {
|
|
clrContents string
|
|
nonClrContents string
|
|
expectedName string
|
|
expectedVersion string
|
|
expectError bool
|
|
}
|
|
|
|
tmpdir, err := ioutil.TempDir("", "")
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
defer os.RemoveAll(tmpdir)
|
|
|
|
testOSRelease := filepath.Join(tmpdir, "os-release")
|
|
testOSReleaseClr := filepath.Join(tmpdir, "os-release-clr")
|
|
|
|
const clrExpectedName = "clr"
|
|
const clrExpectedVersion = "1.2.3-4"
|
|
clrContents := fmt.Sprintf(`
|
|
HELLO=world
|
|
NAME="%s"
|
|
FOO=bar
|
|
VERSION_ID="%s"
|
|
`, clrExpectedName, clrExpectedVersion)
|
|
|
|
const nonClrExpectedName = "not-clr"
|
|
const nonClrExpectedVersion = "999"
|
|
nonClrContents := fmt.Sprintf(`
|
|
HELLO=world
|
|
NAME="%s"
|
|
FOO=bar
|
|
VERSION_ID="%s"
|
|
`, nonClrExpectedName, nonClrExpectedVersion)
|
|
|
|
subDir := filepath.Join(tmpdir, "subdir")
|
|
err = os.MkdirAll(subDir, testDirMode)
|
|
assert.NoError(t, err)
|
|
|
|
// override
|
|
osRelease = subDir
|
|
|
|
_, _, err = getDistroDetails()
|
|
assert.Error(t, err)
|
|
|
|
// override
|
|
osRelease = testOSRelease
|
|
osReleaseClr = testOSReleaseClr
|
|
|
|
_, _, err = getDistroDetails()
|
|
// ENOENT
|
|
assert.Error(t, err)
|
|
|
|
data := []testData{
|
|
{"", "", "", "", true},
|
|
{"invalid", "", "", "", true},
|
|
{clrContents, "", clrExpectedName, clrExpectedVersion, false},
|
|
{"", nonClrContents, nonClrExpectedName, nonClrExpectedVersion, false},
|
|
{clrContents, nonClrContents, nonClrExpectedName, nonClrExpectedVersion, false},
|
|
}
|
|
|
|
for _, d := range data {
|
|
err := createFile(osRelease, d.nonClrContents)
|
|
assert.NoError(t, err)
|
|
|
|
err = createFile(osReleaseClr, d.clrContents)
|
|
assert.NoError(t, err)
|
|
|
|
name, version, err := getDistroDetails()
|
|
if d.expectError {
|
|
assert.Error(t, err, fmt.Sprintf("%+v", d))
|
|
continue
|
|
} else {
|
|
assert.NoError(t, err, fmt.Sprintf("%+v", d))
|
|
assert.Equal(t, d.expectedName, name)
|
|
assert.Equal(t, d.expectedVersion, version)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestUtilsResolvePathEmptyPath(t *testing.T) {
|
|
_, err := resolvePath("")
|
|
assert.Error(t, err)
|
|
}
|
|
|
|
func TestUtilsResolvePathValidPath(t *testing.T) {
|
|
dir, err := ioutil.TempDir("", "")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer os.RemoveAll(dir)
|
|
|
|
target := path.Join(dir, "target")
|
|
linkDir := path.Join(dir, "a/b/c")
|
|
linkFile := path.Join(linkDir, "link")
|
|
|
|
err = createEmptyFile(target)
|
|
assert.NoError(t, err)
|
|
|
|
absolute, err := filepath.Abs(target)
|
|
assert.NoError(t, err)
|
|
|
|
resolvedTarget, err := filepath.EvalSymlinks(absolute)
|
|
assert.NoError(t, err)
|
|
|
|
err = os.MkdirAll(linkDir, testDirMode)
|
|
assert.NoError(t, err)
|
|
|
|
err = syscall.Symlink(target, linkFile)
|
|
assert.NoError(t, err)
|
|
|
|
resolvedLink, err := resolvePath(linkFile)
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, resolvedTarget, resolvedLink)
|
|
}
|
|
|
|
func TestUtilsResolvePathENOENT(t *testing.T) {
|
|
dir, err := ioutil.TempDir("", "")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
target := path.Join(dir, "target")
|
|
linkDir := path.Join(dir, "a/b/c")
|
|
linkFile := path.Join(linkDir, "link")
|
|
|
|
err = createEmptyFile(target)
|
|
assert.NoError(t, err)
|
|
|
|
err = os.MkdirAll(linkDir, testDirMode)
|
|
assert.NoError(t, err)
|
|
|
|
err = syscall.Symlink(target, linkFile)
|
|
assert.NoError(t, err)
|
|
|
|
cwd, err := os.Getwd()
|
|
assert.NoError(t, err)
|
|
defer os.Chdir(cwd)
|
|
|
|
err = os.Chdir(dir)
|
|
assert.NoError(t, err)
|
|
|
|
err = os.RemoveAll(dir)
|
|
assert.NoError(t, err)
|
|
|
|
_, err = resolvePath(filepath.Base(linkFile))
|
|
assert.Error(t, err)
|
|
}
|
|
|
|
func TestUtilsRunCommand(t *testing.T) {
|
|
output, err := runCommand([]string{"true"})
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, "", output)
|
|
}
|
|
|
|
func TestUtilsRunCommandCaptureStdout(t *testing.T) {
|
|
output, err := runCommand([]string{"echo", "hello"})
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, "hello", output)
|
|
}
|
|
|
|
func TestUtilsRunCommandIgnoreStderr(t *testing.T) {
|
|
args := []string{"/bin/sh", "-c", "echo foo >&2;exit 0"}
|
|
|
|
output, err := runCommand(args)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, "", output)
|
|
}
|
|
|
|
func TestUtilsRunCommandInvalidCmds(t *testing.T) {
|
|
invalidCommands := [][]string{
|
|
{""},
|
|
{"", ""},
|
|
{" "},
|
|
{" ", " "},
|
|
{" ", ""},
|
|
{"\\"},
|
|
{"/"},
|
|
{"/.."},
|
|
{"../"},
|
|
{"/tmp"},
|
|
{"\t"},
|
|
{"\n"},
|
|
{"false"},
|
|
}
|
|
|
|
for _, args := range invalidCommands {
|
|
output, err := runCommand(args)
|
|
assert.Error(t, err)
|
|
assert.Equal(t, "", output)
|
|
}
|
|
}
|
|
|
|
func TestWriteFileErrWriteFail(t *testing.T) {
|
|
assert := assert.New(t)
|
|
|
|
err := writeFile("", "", 0000)
|
|
assert.Error(err)
|
|
}
|
|
|
|
func TestWriteFileErrNoPath(t *testing.T) {
|
|
assert := assert.New(t)
|
|
|
|
dir, err := ioutil.TempDir(testDir, "")
|
|
assert.NoError(err)
|
|
defer os.RemoveAll(dir)
|
|
|
|
// attempt to write a file over an existing directory
|
|
err = writeFile(dir, "", 0000)
|
|
assert.Error(err)
|
|
}
|
|
|
|
func TestFileSize(t *testing.T) {
|
|
assert := assert.New(t)
|
|
|
|
dir, err := ioutil.TempDir(testDir, "")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer os.RemoveAll(dir)
|
|
|
|
file := filepath.Join(dir, "foo")
|
|
|
|
// ENOENT
|
|
_, err = fileSize(file)
|
|
assert.Error(err)
|
|
|
|
err = createEmptyFile(file)
|
|
assert.NoError(err)
|
|
|
|
// zero size
|
|
size, err := fileSize(file)
|
|
assert.NoError(err)
|
|
assert.Equal(size, int64(0))
|
|
|
|
msg := "hello"
|
|
msgLen := len(msg)
|
|
|
|
err = writeFile(file, msg, testFileMode)
|
|
assert.NoError(err)
|
|
|
|
size, err = fileSize(file)
|
|
assert.NoError(err)
|
|
assert.Equal(size, int64(msgLen))
|
|
}
|