test: supplement test cases for kata-check and kata-env in Arm64

There were missing test cases in Arm64 for platform-dependent
kata-check and kata-env, leading to 'make test' failure under
kata-containers/runtime

Fixes: #403

Signed-off-by: Penny Zheng <penny.zheng@arm.com>
This commit is contained in:
Penny Zheng 2018-06-15 06:19:07 +00:00
parent fca7eb822d
commit f2096f1f4e
11 changed files with 426 additions and 64 deletions

View File

@ -455,3 +455,7 @@ func TestKvmIsUsable(t *testing.T) {
err = kvmIsUsable()
assert.Error(err)
}
func TestGetCPUDetails(t *testing.T) {
genericTestGetCPUDetails(t)
}

View File

@ -53,6 +53,12 @@ func archHostCanCreateVMContainer() error {
// hostIsVMContainerCapable checks to see if the host is theoretically capable
// of creating a VM container.
func hostIsVMContainerCapable(details vmContainerCapableDetails) error {
_, err := getCPUInfo(details.cpuInfoFile)
if err != nil {
return err
}
count, err := checkKernelModules(details.requiredKernelModules, archKernelParamHandler)
if err != nil {
return err

View File

@ -0,0 +1,201 @@
// Copyright (c) 2018 ARM Limited
//
// SPDX-License-Identifier: Apache-2.0
//
package main
import (
"bytes"
"fmt"
"io/ioutil"
"os"
"path"
"path/filepath"
"testing"
"github.com/stretchr/testify/assert"
"github.com/urfave/cli"
)
func setupCheckHostIsVMContainerCapable(assert *assert.Assertions, cpuInfoFile string, moduleData []testModuleData) {
//For now, Arm64 only deal with module check
createModules(assert, cpuInfoFile, moduleData)
err := makeCPUInfoFile(cpuInfoFile, "", "")
assert.NoError(err)
}
func TestCCCheckCLIFunction(t *testing.T) {
assert := assert.New(t)
dir, err := ioutil.TempDir("", "")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(dir)
savedSysModuleDir := sysModuleDir
savedProcCPUInfo := procCPUInfo
cpuInfoFile := filepath.Join(dir, "cpuinfo")
// XXX: override
sysModuleDir = filepath.Join(dir, "sys/module")
procCPUInfo = cpuInfoFile
defer func() {
sysModuleDir = savedSysModuleDir
procCPUInfo = savedProcCPUInfo
}()
err = os.MkdirAll(sysModuleDir, testDirMode)
if err != nil {
t.Fatal(err)
}
moduleData := []testModuleData{
{filepath.Join(sysModuleDir, "kvm"), true, ""},
{filepath.Join(sysModuleDir, "vhost"), true, ""},
{filepath.Join(sysModuleDir, "vhost_net"), true, ""},
}
devNull, err := os.OpenFile(os.DevNull, os.O_WRONLY, 0666)
assert.NoError(err)
defer devNull.Close()
savedLogOutput := kataLog.Logger.Out
// discard normal output
kataLog.Logger.Out = devNull
defer func() {
kataLog.Logger.Out = savedLogOutput
}()
setupCheckHostIsVMContainerCapable(assert, cpuInfoFile, moduleData)
app := cli.NewApp()
ctx := cli.NewContext(app, nil, nil)
app.Name = "foo"
// create buffer to save logger output
buf := &bytes.Buffer{}
// capture output this time
kataLog.Logger.Out = buf
fn, ok := kataCheckCLICommand.Action.(func(context *cli.Context) error)
assert.True(ok)
err = fn(ctx)
assert.NoError(err)
output := buf.String()
for _, m := range moduleData {
name := path.Base(m.path)
assert.True(findAnchoredString(output, name))
}
}
func TestKvmIsUsable(t *testing.T) {
assert := assert.New(t)
dir, err := ioutil.TempDir("", "")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(dir)
savedKvmDevice := kvmDevice
fakeKVMDevice := filepath.Join(dir, "kvm")
kvmDevice = fakeKVMDevice
defer func() {
kvmDevice = savedKvmDevice
}()
err = kvmIsUsable()
assert.Error(err)
err = createEmptyFile(fakeKVMDevice)
assert.NoError(err)
err = kvmIsUsable()
assert.Error(err)
}
func TestGetCPUDetails(t *testing.T) {
type testData struct {
contents string
expectedVendor string
expectedModel string
expectedNormalizeVendor string
expectedNormalizeModel string
expectError bool
}
const validVendorName = "0x41"
const validNormalizeVendorName = "ARM Limited"
validVendor := fmt.Sprintf(`%s : %s`, archCPUVendorField, validVendorName)
const validModelName = "8"
const validNormalizeModelName = "v8"
validModel := fmt.Sprintf(`%s : %s`, archCPUModelField, validModelName)
validContents := fmt.Sprintf(`
a : b
%s
foo : bar
%s
`, validVendor, validModel)
data := []testData{
{"", "", "", "", "", true},
{"invalid", "", "", "", "", true},
{archCPUVendorField, "", "", "", "", true},
{validVendor, "", "", "", "", true},
{validModel, "", "", "", "", true},
{validContents, validVendorName, validModelName, validNormalizeVendorName, validNormalizeModelName, false},
}
tmpdir, err := ioutil.TempDir("", "")
if err != nil {
panic(err)
}
defer os.RemoveAll(tmpdir)
savedProcCPUInfo := procCPUInfo
testProcCPUInfo := filepath.Join(tmpdir, "cpuinfo")
// override
procCPUInfo = testProcCPUInfo
defer func() {
procCPUInfo = savedProcCPUInfo
}()
_, _, err = getCPUDetails()
// ENOENT
assert.Error(t, err)
assert.True(t, os.IsNotExist(err))
for _, d := range data {
err := createFile(procCPUInfo, d.contents)
assert.NoError(t, err)
vendor, model, err := getCPUDetails()
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.expectedNormalizeVendor, vendor)
assert.Equal(t, d.expectedNormalizeModel, model)
}
}
}

View File

@ -0,0 +1,27 @@
// Copyright (c) 2018 ARM Limited
//
// SPDX-License-Identifier: Apache-2.0
//
package main
const testCPUInfoTemplate = `
processor : 0
BogoMIPS : 500.00
Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 cpuid
CPU implementer : 0x41
CPU architecture: 8
CPU variant : 0x1
CPU part : 0xd07
CPU revision : 2
processor : 1
BogoMIPS : 500.00
Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 cpuid
CPU implementer : 0x41
CPU architecture: 8
CPU variant : 0x1
CPU part : 0xd07
CPU revision : 2
`

View File

@ -207,3 +207,7 @@ func TestKvmIsUsable(t *testing.T) {
err = kvmIsUsable()
assert.Error(err)
}
func TestGetCPUDetails(t *testing.T) {
genericTestGetCPUDetails(t)
}

View File

@ -137,6 +137,75 @@ func makeCPUInfoFile(path, vendorID, flags string) error {
return ioutil.WriteFile(path, contents.Bytes(), testFileMode)
}
func genericTestGetCPUDetails(t *testing.T) {
type testData struct {
contents string
expectedVendor string
expectedModel string
expectError bool
}
const validVendorName = "a vendor"
validVendor := fmt.Sprintf(`%s : %s`, archCPUVendorField, validVendorName)
const validModelName = "some CPU model"
validModel := fmt.Sprintf(`%s : %s`, archCPUModelField, validModelName)
validContents := fmt.Sprintf(`
a : b
%s
foo : bar
%s
`, validVendor, validModel)
data := []testData{
{"", "", "", true},
{"invalid", "", "", true},
{archCPUVendorField, "", "", true},
{validVendor, "", "", true},
{validModel, "", "", true},
{validContents, validVendorName, validModelName, false},
}
tmpdir, err := ioutil.TempDir("", "")
if err != nil {
panic(err)
}
defer os.RemoveAll(tmpdir)
savedProcCPUInfo := procCPUInfo
testProcCPUInfo := filepath.Join(tmpdir, "cpuinfo")
// override
procCPUInfo = testProcCPUInfo
defer func() {
procCPUInfo = savedProcCPUInfo
}()
_, _, err = getCPUDetails()
// ENOENT
assert.Error(t, err)
assert.True(t, os.IsNotExist(err))
for _, d := range data {
err := createFile(procCPUInfo, d.contents)
assert.NoError(t, err)
vendor, model, err := getCPUDetails()
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.expectedVendor, vendor)
assert.Equal(t, d.expectedModel, model)
}
}
}
func TestCheckGetCPUInfo(t *testing.T) {
assert := assert.New(t)

View File

@ -0,0 +1,10 @@
// Copyright (c) 2018 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
//
package main
func getExpectedHostDetails(tmpdir string) (HostInfo, error) {
return genericGetExpectedHostDetails(tmpdir)
}

View File

@ -0,0 +1,94 @@
// Copyright (c) 2018 ARM Limited
//
// SPDX-License-Identifier: Apache-2.0
//
package main
import (
"fmt"
"path/filepath"
goruntime "runtime"
)
func getExpectedHostDetails(tmpdir string) (HostInfo, error) {
type filesToCreate struct {
file string
contents string
}
const expectedKernelVersion = "99.1"
const expectedArch = goruntime.GOARCH
expectedDistro := DistroInfo{
Name: "Foo",
Version: "42",
}
expectedCPU := CPUInfo{
Vendor: "0x41",
Model: "8",
}
expectedNormalizeCPU := CPUInfo{
Vendor: "ARM Limited",
Model: "v8",
}
expectedHostDetails := HostInfo{
Kernel: expectedKernelVersion,
Architecture: expectedArch,
Distro: expectedDistro,
CPU: expectedNormalizeCPU,
VMContainerCapable: true,
}
testProcCPUInfo := filepath.Join(tmpdir, "cpuinfo")
testOSRelease := filepath.Join(tmpdir, "os-release")
// XXX: This file is *NOT* created by this function on purpose
// (to ensure the only file checked by the tests is
// testOSRelease). osReleaseClr handling is tested in
// utils_test.go.
testOSReleaseClr := filepath.Join(tmpdir, "os-release-clr")
testProcVersion := filepath.Join(tmpdir, "proc-version")
// override
procVersion = testProcVersion
osRelease = testOSRelease
osReleaseClr = testOSReleaseClr
procCPUInfo = testProcCPUInfo
procVersionContents := fmt.Sprintf("Linux version %s a b c",
expectedKernelVersion)
osReleaseContents := fmt.Sprintf(`
NAME="%s"
VERSION_ID="%s"
`, expectedDistro.Name, expectedDistro.Version)
procCPUInfoContents := fmt.Sprintf(`
%s : %s
%s : %s
`,
archCPUVendorField,
expectedCPU.Vendor,
archCPUModelField,
expectedCPU.Model)
data := []filesToCreate{
{procVersion, procVersionContents},
{osRelease, osReleaseContents},
{procCPUInfo, procCPUInfoContents},
}
for _, d := range data {
err := createFile(d.file, d.contents)
if err != nil {
return HostInfo{}, err
}
}
return expectedHostDetails, nil
}

View File

@ -0,0 +1,10 @@
// Copyright (c) 2018 IBM
//
// SPDX-License-Identifier: Apache-2.0
//
package main
func getExpectedHostDetails(tmpdir string) (HostInfo, error) {
return genericGetExpectedHostDetails(tmpdir)
}

View File

@ -152,7 +152,7 @@ func getExpectedAgentDetails(config oci.RuntimeConfig) (AgentInfo, error) {
}, nil
}
func getExpectedHostDetails(tmpdir string) (HostInfo, error) {
func genericGetExpectedHostDetails(tmpdir string) (HostInfo, error) {
type filesToCreate struct {
file string
contents string

View File

@ -216,69 +216,6 @@ VERSION_ID="%s"
}
}
func TestGetCPUDetails(t *testing.T) {
type testData struct {
contents string
expectedVendor string
expectedModel string
expectError bool
}
const validVendorName = "a vendor"
validVendor := fmt.Sprintf(`%s : %s`, archCPUVendorField, validVendorName)
const validModelName = "some CPU model"
validModel := fmt.Sprintf(`%s : %s`, archCPUModelField, validModelName)
validContents := fmt.Sprintf(`
a : b
%s
foo : bar
%s
`, validVendor, validModel)
data := []testData{
{"", "", "", true},
{"invalid", "", "", true},
{archCPUVendorField, "", "", true},
{validVendor, "", "", true},
{validModel, "", "", true},
{validContents, validVendorName, validModelName, false},
}
tmpdir, err := ioutil.TempDir("", "")
if err != nil {
panic(err)
}
defer os.RemoveAll(tmpdir)
testProcCPUInfo := filepath.Join(tmpdir, "cpuinfo")
// override
procCPUInfo = testProcCPUInfo
_, _, err = getCPUDetails()
// ENOENT
assert.Error(t, err)
assert.True(t, os.IsNotExist(err))
for _, d := range data {
err := createFile(procCPUInfo, d.contents)
assert.NoError(t, err)
vendor, model, err := getCPUDetails()
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.expectedVendor, vendor)
assert.Equal(t, d.expectedModel, model)
}
}
}
func TestUtilsResolvePathEmptyPath(t *testing.T) {
_, err := resolvePath("")
assert.Error(t, err)