Files
kata-containers/src/runtime/virtcontainers/device/manager/manager_test.go
zhanghj efa19c41eb device: use const strings for block-driver option instead of hard coding
Currently, the block driver option is specifed by hard coding, maybe it
is better to use const string variables instead of hard coded strings.
Another modification is to remove duplicate consts for virtio driver in
manager.go.

Fixes: #3321

Signed-off-by: Jason Zhang <zhanghj.lc@inspur.com>
2022-03-14 09:20:43 +08:00

266 lines
7.2 KiB
Go

// Copyright (c) 2017 Intel Corporation
// Copyright (c) 2018 Huawei Corporation
//
// SPDX-License-Identifier: Apache-2.0
//
package manager
import (
"context"
"os"
"path/filepath"
"strconv"
"testing"
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/device/api"
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/device/config"
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/device/drivers"
"github.com/stretchr/testify/assert"
)
const fileMode0640 = os.FileMode(0640)
// dirMode is the permission bits used for creating a directory
const dirMode = os.FileMode(0750) | os.ModeDir
func TestNewDevice(t *testing.T) {
dm := &deviceManager{
blockDriver: config.VirtioBlock,
devices: make(map[string]api.Device),
}
savedSysDevPrefix := config.SysDevPrefix
major := int64(252)
minor := int64(3)
tmpDir, err := os.MkdirTemp("", "")
assert.Nil(t, err)
config.SysDevPrefix = tmpDir
defer func() {
os.RemoveAll(tmpDir)
config.SysDevPrefix = savedSysDevPrefix
}()
path := "/dev/vfio/2"
deviceInfo := config.DeviceInfo{
ContainerPath: "",
Major: major,
Minor: minor,
UID: 2,
GID: 2,
DevType: "c",
}
_, err = dm.NewDevice(deviceInfo)
assert.NotNil(t, err)
format := strconv.FormatInt(major, 10) + ":" + strconv.FormatInt(minor, 10)
ueventPathPrefix := filepath.Join(config.SysDevPrefix, "char", format)
ueventPath := filepath.Join(ueventPathPrefix, "uevent")
// Return true for non-existent /sys/dev path.
deviceInfo.ContainerPath = path
_, err = dm.NewDevice(deviceInfo)
assert.Nil(t, err)
err = os.MkdirAll(ueventPathPrefix, dirMode)
assert.Nil(t, err)
// Should return error for bad data in uevent file
content := []byte("nonkeyvaluedata")
err = os.WriteFile(ueventPath, content, fileMode0640)
assert.Nil(t, err)
_, err = dm.NewDevice(deviceInfo)
assert.NotNil(t, err)
content = []byte("MAJOR=252\nMINOR=3\nDEVNAME=vfio/2")
err = os.WriteFile(ueventPath, content, fileMode0640)
assert.Nil(t, err)
device, err := dm.NewDevice(deviceInfo)
assert.Nil(t, err)
vfioDev, ok := device.(*drivers.VFIODevice)
assert.True(t, ok)
assert.Equal(t, vfioDev.DeviceInfo.HostPath, path)
assert.Equal(t, vfioDev.DeviceInfo.ContainerPath, path)
assert.Equal(t, vfioDev.DeviceInfo.DevType, "c")
assert.Equal(t, vfioDev.DeviceInfo.Major, major)
assert.Equal(t, vfioDev.DeviceInfo.Minor, minor)
assert.Equal(t, vfioDev.DeviceInfo.UID, uint32(2))
assert.Equal(t, vfioDev.DeviceInfo.GID, uint32(2))
}
func TestAttachVFIODevice(t *testing.T) {
dm := &deviceManager{
blockDriver: config.VirtioBlock,
devices: make(map[string]api.Device),
}
tmpDir, err := os.MkdirTemp("", "")
assert.Nil(t, err)
defer os.RemoveAll(tmpDir)
testFDIOGroup := "2"
testDeviceBDFPath := "0000:00:1c.0"
devicesDir := filepath.Join(tmpDir, testFDIOGroup, "devices")
err = os.MkdirAll(devicesDir, dirMode)
assert.Nil(t, err)
deviceBDFDir := filepath.Join(devicesDir, testDeviceBDFPath)
err = os.MkdirAll(deviceBDFDir, dirMode)
assert.Nil(t, err)
deviceClassFile := filepath.Join(deviceBDFDir, "class")
_, err = os.Create(deviceClassFile)
assert.Nil(t, err)
deviceConfigFile := filepath.Join(deviceBDFDir, "config")
_, err = os.Create(deviceConfigFile)
assert.Nil(t, err)
savedIOMMUPath := config.SysIOMMUPath
config.SysIOMMUPath = tmpDir
savedSysBusPciDevicesPath := config.SysBusPciDevicesPath
config.SysBusPciDevicesPath = devicesDir
defer func() {
config.SysIOMMUPath = savedIOMMUPath
config.SysBusPciDevicesPath = savedSysBusPciDevicesPath
}()
path := filepath.Join(vfioPath, testFDIOGroup)
deviceInfo := config.DeviceInfo{
HostPath: path,
ContainerPath: path,
DevType: "c",
}
device, err := dm.NewDevice(deviceInfo)
assert.Nil(t, err)
_, ok := device.(*drivers.VFIODevice)
assert.True(t, ok)
devReceiver := &api.MockDeviceReceiver{}
err = device.Attach(context.Background(), devReceiver)
assert.Nil(t, err)
err = device.Detach(context.Background(), devReceiver)
assert.Nil(t, err)
}
func TestAttachGenericDevice(t *testing.T) {
dm := &deviceManager{
blockDriver: config.VirtioBlock,
devices: make(map[string]api.Device),
}
path := "/dev/tty2"
deviceInfo := config.DeviceInfo{
HostPath: path,
ContainerPath: path,
DevType: "c",
}
device, err := dm.NewDevice(deviceInfo)
assert.Nil(t, err)
_, ok := device.(*drivers.GenericDevice)
assert.True(t, ok)
devReceiver := &api.MockDeviceReceiver{}
err = device.Attach(context.Background(), devReceiver)
assert.Nil(t, err)
err = device.Detach(context.Background(), devReceiver)
assert.Nil(t, err)
}
func TestAttachBlockDevice(t *testing.T) {
dm := &deviceManager{
blockDriver: config.VirtioBlock,
devices: make(map[string]api.Device),
}
path := "/dev/hda"
deviceInfo := config.DeviceInfo{
HostPath: path,
ContainerPath: path,
DevType: "b",
}
devReceiver := &api.MockDeviceReceiver{}
device, err := dm.NewDevice(deviceInfo)
assert.Nil(t, err)
_, ok := device.(*drivers.BlockDevice)
assert.True(t, ok)
err = device.Attach(context.Background(), devReceiver)
assert.Nil(t, err)
err = device.Detach(context.Background(), devReceiver)
assert.Nil(t, err)
// test virtio SCSI driver
dm.blockDriver = config.VirtioSCSI
device, err = dm.NewDevice(deviceInfo)
assert.Nil(t, err)
err = device.Attach(context.Background(), devReceiver)
assert.Nil(t, err)
err = device.Detach(context.Background(), devReceiver)
assert.Nil(t, err)
}
func TestAttachDetachDevice(t *testing.T) {
dm := NewDeviceManager(config.VirtioSCSI, false, "", nil)
path := "/dev/hda"
deviceInfo := config.DeviceInfo{
HostPath: path,
ContainerPath: path,
DevType: "b",
}
devReceiver := &api.MockDeviceReceiver{}
device, err := dm.NewDevice(deviceInfo)
assert.Nil(t, err)
// attach non-exist device
err = dm.AttachDevice(context.Background(), "non-exist", devReceiver)
assert.NotNil(t, err)
// attach device
err = dm.AttachDevice(context.Background(), device.DeviceID(), devReceiver)
assert.Nil(t, err)
assert.Equal(t, device.GetAttachCount(), uint(1), "attach device count should be 1")
// attach device again(twice)
err = dm.AttachDevice(context.Background(), device.DeviceID(), devReceiver)
assert.Nil(t, err)
assert.Equal(t, device.GetAttachCount(), uint(2), "attach device count should be 2")
attached := dm.IsDeviceAttached(device.DeviceID())
assert.True(t, attached)
// detach device
err = dm.DetachDevice(context.Background(), device.DeviceID(), devReceiver)
assert.Nil(t, err)
assert.Equal(t, device.GetAttachCount(), uint(1), "attach device count should be 1")
// detach device again(twice)
err = dm.DetachDevice(context.Background(), device.DeviceID(), devReceiver)
assert.Nil(t, err)
assert.Equal(t, device.GetAttachCount(), uint(0), "attach device count should be 0")
// detach device again should report error
err = dm.DetachDevice(context.Background(), device.DeviceID(), devReceiver)
assert.NotNil(t, err)
assert.Equal(t, err, ErrDeviceNotAttached, "")
assert.Equal(t, device.GetAttachCount(), uint(0), "attach device count should be 0")
attached = dm.IsDeviceAttached(device.DeviceID())
assert.False(t, attached)
err = dm.RemoveDevice(device.DeviceID())
assert.Nil(t, err)
}