Files
kata-containers/qemu/qemu_test.go
Sergio Lopez 88a25a2d68 Refactor code to support multiple virtio transports at runtime
Currently, virtio transports for each device are determined with
architecture dependent build time conditionals. This isn't the ideal
solution, as virtio transports aren't exactly tied to the host's
architecture.

For example, aarch64 VMs do support both PCI and MMIO devices, and
after the recent introduction of the microvm machine type, that's also
the case for x86_64.

This patch extends each device that supports multiple transports with
a VirtioTransport field, so users of the library can manually specify
a transport for each device. To avoid breaking the compatibility, if
VirtioTransport is empty a behavior equivalent to the legacy one is
achieved by checking runtime.GOARCH and Config.Machine.Type.

Keeping support for isVirtioPCI/isVirtioCCW in qmp.go is a bit
tricky. Eventually, the hot-plug API should be extended so callers
must manually specify the transport for the device.

Signed-off-by: Sergio Lopez <slp@redhat.com>
2020-02-07 18:17:12 +01:00

1117 lines
24 KiB
Go

/*
// Copyright contributors to the Virtual Machine Manager for Go project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
*/
package qemu
import (
"fmt"
"io/ioutil"
"os"
"strings"
"testing"
)
const agentUUID = "4cb19522-1e18-439a-883a-f9b2a3a95f5e"
const volumeUUID = "67d86208-b46c-4465-9018-e14187d4010"
var (
deviceNetworkPCIString = "-netdev tap,id=tap0,vhost=on,ifname=ceth0,downscript=no,script=no -device driver=virtio-net-pci,netdev=tap0,mac=01:02:de:ad:be:ef,bus=/pci-bus/pcie.0,addr=ff,disable-modern=true,romfile=efi-virtio.rom"
deviceNetworkPCIStringMq = "-netdev tap,id=tap0,vhost=on,fds=3:4 -device driver=virtio-net-pci,netdev=tap0,mac=01:02:de:ad:be:ef,bus=/pci-bus/pcie.0,addr=ff,disable-modern=true,mq=on,vectors=6,romfile=efi-virtio.rom"
)
const DevNo = "fe.1.1234"
func testAppend(structure interface{}, expected string, t *testing.T) {
var config Config
testConfigAppend(&config, structure, expected, t)
}
func testConfigAppend(config *Config, structure interface{}, expected string, t *testing.T) {
switch s := structure.(type) {
case Machine:
config.Machine = s
config.appendMachine()
case Device:
config.Devices = []Device{s}
config.appendDevices()
case Knobs:
config.Knobs = s
config.appendKnobs()
case Kernel:
config.Kernel = s
config.appendKernel()
case Memory:
config.Memory = s
config.appendMemory()
case SMP:
config.SMP = s
if err := config.appendCPUs(); err != nil {
t.Fatalf("Unexpected error: %v", err)
}
case QMPSocket:
config.QMPSockets = []QMPSocket{s}
config.appendQMPSockets()
case []QMPSocket:
config.QMPSockets = s
config.appendQMPSockets()
case RTC:
config.RTC = s
config.appendRTC()
case IOThread:
config.IOThreads = []IOThread{s}
config.appendIOThreads()
case Incoming:
config.Incoming = s
config.appendIncoming()
}
result := strings.Join(config.qemuParams, " ")
if result != expected {
t.Fatalf("Failed to append parameters [%s] != [%s]", result, expected)
}
}
func TestAppendMachine(t *testing.T) {
machineString := "-machine pc-lite,accel=kvm,kernel_irqchip,nvdimm"
machine := Machine{
Type: "pc-lite",
Acceleration: "kvm,kernel_irqchip,nvdimm",
}
testAppend(machine, machineString, t)
machineString = "-machine pc-lite,accel=kvm,kernel_irqchip,nvdimm,gic-version=host,usb=off"
machine = Machine{
Type: "pc-lite",
Acceleration: "kvm,kernel_irqchip,nvdimm",
Options: "gic-version=host,usb=off",
}
testAppend(machine, machineString, t)
}
func TestAppendEmptyMachine(t *testing.T) {
machine := Machine{}
testAppend(machine, "", t)
}
var deviceNVDIMMString = "-device nvdimm,id=nv0,memdev=mem0 -object memory-backend-file,id=mem0,mem-path=/root,size=65536"
func TestAppendDeviceNVDIMM(t *testing.T) {
object := Object{
Driver: NVDIMM,
Type: MemoryBackendFile,
DeviceID: "nv0",
ID: "mem0",
MemPath: "/root",
Size: 1 << 16,
}
testAppend(object, deviceNVDIMMString, t)
}
func TestAppendDeviceFS(t *testing.T) {
fsdev := FSDevice{
Driver: Virtio9P,
FSDriver: Local,
ID: "workload9p",
Path: "/var/lib/docker/devicemapper/mnt/e31ebda2",
MountTag: "rootfs",
SecurityModel: None,
DisableModern: true,
ROMFile: "efi-virtio.rom",
}
if fsdev.Transport.isVirtioCCW(nil) {
fsdev.DevNo = DevNo
}
testAppend(fsdev, deviceFSString, t)
}
func TestAppendDeviceNetwork(t *testing.T) {
netdev := NetDevice{
Driver: VirtioNet,
Type: TAP,
ID: "tap0",
IFName: "ceth0",
Script: "no",
DownScript: "no",
VHost: true,
MACAddress: "01:02:de:ad:be:ef",
DisableModern: true,
ROMFile: "efi-virtio.rom",
}
if netdev.Transport.isVirtioCCW(nil) {
netdev.DevNo = DevNo
}
testAppend(netdev, deviceNetworkString, t)
}
func TestAppendDeviceNetworkMq(t *testing.T) {
foo, _ := ioutil.TempFile(os.TempDir(), "govmm-qemu-test")
bar, _ := ioutil.TempFile(os.TempDir(), "govmm-qemu-test")
defer func() {
_ = foo.Close()
_ = bar.Close()
_ = os.Remove(foo.Name())
_ = os.Remove(bar.Name())
}()
netdev := NetDevice{
Driver: VirtioNet,
Type: TAP,
ID: "tap0",
IFName: "ceth0",
Script: "no",
DownScript: "no",
FDs: []*os.File{foo, bar},
VHost: true,
MACAddress: "01:02:de:ad:be:ef",
DisableModern: true,
ROMFile: "efi-virtio.rom",
}
if netdev.Transport.isVirtioCCW(nil) {
netdev.DevNo = DevNo
}
testAppend(netdev, deviceNetworkStringMq, t)
}
func TestAppendDeviceNetworkPCI(t *testing.T) {
netdev := NetDevice{
Driver: VirtioNet,
Type: TAP,
ID: "tap0",
IFName: "ceth0",
Bus: "/pci-bus/pcie.0",
Addr: "255",
Script: "no",
DownScript: "no",
VHost: true,
MACAddress: "01:02:de:ad:be:ef",
DisableModern: true,
ROMFile: romfile,
}
if !netdev.Transport.isVirtioPCI(nil) {
t.Skip("Test valid only for PCI devices")
}
testAppend(netdev, deviceNetworkPCIString, t)
}
func TestAppendDeviceNetworkPCIMq(t *testing.T) {
foo, _ := ioutil.TempFile(os.TempDir(), "govmm-qemu-test")
bar, _ := ioutil.TempFile(os.TempDir(), "govmm-qemu-test")
defer func() {
_ = foo.Close()
_ = bar.Close()
_ = os.Remove(foo.Name())
_ = os.Remove(bar.Name())
}()
netdev := NetDevice{
Driver: VirtioNet,
Type: TAP,
ID: "tap0",
IFName: "ceth0",
Bus: "/pci-bus/pcie.0",
Addr: "255",
Script: "no",
DownScript: "no",
FDs: []*os.File{foo, bar},
VHost: true,
MACAddress: "01:02:de:ad:be:ef",
DisableModern: true,
ROMFile: romfile,
}
if !netdev.Transport.isVirtioPCI(nil) {
t.Skip("Test valid only for PCI devices")
}
testAppend(netdev, deviceNetworkPCIStringMq, t)
}
func TestAppendDeviceSerial(t *testing.T) {
sdev := SerialDevice{
Driver: VirtioSerial,
ID: "serial0",
DisableModern: true,
ROMFile: romfile,
}
if sdev.Transport.isVirtioCCW(nil) {
sdev.DevNo = DevNo
}
testAppend(sdev, deviceSerialString, t)
}
var deviceSerialPortString = "-device virtserialport,chardev=char0,id=channel0,name=channel.0 -chardev socket,id=char0,path=/tmp/char.sock,server,nowait"
func TestAppendDeviceSerialPort(t *testing.T) {
chardev := CharDevice{
Driver: VirtioSerialPort,
Backend: Socket,
ID: "char0",
DeviceID: "channel0",
Path: "/tmp/char.sock",
Name: "channel.0",
}
if chardev.Transport.isVirtioCCW(nil) {
chardev.DevNo = DevNo
}
testAppend(chardev, deviceSerialPortString, t)
}
func TestAppendDeviceBlock(t *testing.T) {
blkdev := BlockDevice{
Driver: VirtioBlock,
ID: "hd0",
File: "/var/lib/vm.img",
AIO: Threads,
Format: QCOW2,
Interface: NoInterface,
SCSI: false,
WCE: false,
DisableModern: true,
ROMFile: romfile,
}
if blkdev.Transport.isVirtioCCW(nil) {
blkdev.DevNo = DevNo
}
testAppend(blkdev, deviceBlockString, t)
}
func TestAppendDeviceVFIO(t *testing.T) {
vfioDevice := VFIODevice{
BDF: "02:10.0",
ROMFile: romfile,
VendorID: "0x1234",
DeviceID: "0x5678",
}
if vfioDevice.Transport.isVirtioCCW(nil) {
vfioDevice.DevNo = DevNo
}
testAppend(vfioDevice, deviceVFIOString, t)
}
func TestAppendVSOCK(t *testing.T) {
vsockDevice := VSOCKDevice{
ID: "vhost-vsock-pci0",
ContextID: 4,
VHostFD: nil,
DisableModern: true,
ROMFile: romfile,
}
if vsockDevice.Transport.isVirtioCCW(nil) {
vsockDevice.DevNo = DevNo
}
testAppend(vsockDevice, deviceVSOCKString, t)
}
func TestVSOCKValid(t *testing.T) {
vsockDevice := VSOCKDevice{
ID: "vhost-vsock-pci0",
ContextID: MinimalGuestCID - 1,
VHostFD: nil,
DisableModern: true,
}
if vsockDevice.Valid() {
t.Fatalf("VSOCK Context ID is not valid")
}
vsockDevice.ContextID = MaxGuestCID + 1
if vsockDevice.Valid() {
t.Fatalf("VSOCK Context ID is not valid")
}
vsockDevice.ID = ""
if vsockDevice.Valid() {
t.Fatalf("VSOCK ID is not valid")
}
}
func TestAppendVirtioRng(t *testing.T) {
var objectString = "-object rng-random,id=rng0"
var deviceString = "-device " + string(VirtioRng)
rngDevice := RngDevice{
ID: "rng0",
ROMFile: romfile,
}
deviceString += "-" + string(rngDevice.Transport.getName(nil)) + ",rng=rng0"
if romfile != "" {
deviceString = deviceString + ",romfile=efi-virtio.rom"
}
if rngDevice.Transport.isVirtioCCW(nil) {
rngDevice.DevNo = DevNo
deviceString += ",devno=" + rngDevice.DevNo
}
testAppend(rngDevice, objectString+" "+deviceString, t)
rngDevice.Filename = "/dev/urandom"
objectString += ",filename=" + rngDevice.Filename
testAppend(rngDevice, objectString+" "+deviceString, t)
rngDevice.MaxBytes = 20
deviceString += fmt.Sprintf(",max-bytes=%d", rngDevice.MaxBytes)
testAppend(rngDevice, objectString+" "+deviceString, t)
rngDevice.Period = 500
deviceString += fmt.Sprintf(",period=%d", rngDevice.Period)
testAppend(rngDevice, objectString+" "+deviceString, t)
}
func TestVirtioRngValid(t *testing.T) {
rng := RngDevice{
ID: "",
}
if rng.Valid() {
t.Fatalf("rng should be not valid when ID is empty")
}
rng.ID = "rng0"
if !rng.Valid() {
t.Fatalf("rng should be valid")
}
}
func TestVirtioBalloonValid(t *testing.T) {
balloon := BalloonDevice{
ID: "",
}
if balloon.Valid() {
t.Fatalf("balloon should be not valid when ID is empty")
}
balloon.ID = "balloon0"
if !balloon.Valid() {
t.Fatalf("balloon should be valid")
}
}
func TestAppendDeviceSCSIController(t *testing.T) {
scsiCon := SCSIController{
ID: "foo",
ROMFile: romfile,
}
if scsiCon.Transport.isVirtioCCW(nil) {
scsiCon.DevNo = DevNo
}
testAppend(scsiCon, deviceSCSIControllerStr, t)
scsiCon.Bus = "pci.0"
scsiCon.Addr = "00:04.0"
scsiCon.DisableModern = true
scsiCon.IOThread = "iothread1"
testAppend(scsiCon, deviceSCSIControllerBusAddrStr, t)
}
func TestAppendPCIBridgeDevice(t *testing.T) {
bridge := BridgeDevice{
Type: PCIBridge,
ID: "mybridge",
Bus: "/pci-bus/pcie.0",
Addr: "255",
Chassis: 5,
SHPC: true,
ROMFile: romfile,
}
testAppend(bridge, devicePCIBridgeString, t)
}
func TestAppendPCIEBridgeDevice(t *testing.T) {
bridge := BridgeDevice{
Type: PCIEBridge,
ID: "mybridge",
Bus: "/pci-bus/pcie.0",
Addr: "255",
ROMFile: "efi-virtio.rom",
}
testAppend(bridge, devicePCIEBridgeString, t)
}
func TestAppendEmptyDevice(t *testing.T) {
device := SerialDevice{}
testAppend(device, "", t)
}
func TestAppendKnobsAllTrue(t *testing.T) {
var knobsString = "-no-user-config -nodefaults -nographic -daemonize -realtime mlock=on -S"
knobs := Knobs{
NoUserConfig: true,
NoDefaults: true,
NoGraphic: true,
Daemonize: true,
MemPrealloc: true,
FileBackedMem: true,
MemShared: true,
Realtime: true,
Mlock: true,
Stopped: true,
}
testAppend(knobs, knobsString, t)
}
func TestAppendKnobsAllFalse(t *testing.T) {
var knobsString = "-realtime mlock=off"
knobs := Knobs{
NoUserConfig: false,
NoDefaults: false,
NoGraphic: false,
MemPrealloc: false,
FileBackedMem: false,
MemShared: false,
Realtime: false,
Mlock: false,
Stopped: false,
}
testAppend(knobs, knobsString, t)
}
func TestAppendMemoryHugePages(t *testing.T) {
if !isDimmSupported(nil) {
t.Skip("Dimm not supported")
}
conf := &Config{
Memory: Memory{
Size: "1G",
Slots: 8,
MaxMem: "3G",
Path: "foobar",
},
}
memString := "-m 1G,slots=8,maxmem=3G"
testConfigAppend(conf, conf.Memory, memString, t)
knobs := Knobs{
HugePages: true,
MemPrealloc: true,
FileBackedMem: true,
MemShared: true,
}
knobsString := "-object memory-backend-file,id=dimm1,size=1G,mem-path=/dev/hugepages,share=on,prealloc=on -numa node,memdev=dimm1"
mlockFalseString := "-realtime mlock=off"
testConfigAppend(conf, knobs, memString+" "+knobsString+" "+mlockFalseString, t)
}
func TestAppendMemoryMemPrealloc(t *testing.T) {
if !isDimmSupported(nil) {
t.Skip("Dimm not supported")
}
conf := &Config{
Memory: Memory{
Size: "1G",
Slots: 8,
MaxMem: "3G",
Path: "foobar",
},
}
memString := "-m 1G,slots=8,maxmem=3G"
testConfigAppend(conf, conf.Memory, memString, t)
knobs := Knobs{
MemPrealloc: true,
MemShared: true,
}
knobsString := "-object memory-backend-ram,id=dimm1,size=1G,share=on,prealloc=on -numa node,memdev=dimm1"
mlockFalseString := "-realtime mlock=off"
testConfigAppend(conf, knobs, memString+" "+knobsString+" "+mlockFalseString, t)
}
func TestAppendMemoryMemShared(t *testing.T) {
if !isDimmSupported(nil) {
t.Skip("Dimm not supported")
}
conf := &Config{
Memory: Memory{
Size: "1G",
Slots: 8,
MaxMem: "3G",
Path: "foobar",
},
}
memString := "-m 1G,slots=8,maxmem=3G"
testConfigAppend(conf, conf.Memory, memString, t)
knobs := Knobs{
FileBackedMem: true,
MemShared: true,
}
knobsString := "-object memory-backend-file,id=dimm1,size=1G,mem-path=foobar,share=on -numa node,memdev=dimm1"
mlockFalseString := "-realtime mlock=off"
testConfigAppend(conf, knobs, memString+" "+knobsString+" "+mlockFalseString, t)
}
func TestAppendMemoryFileBackedMem(t *testing.T) {
if !isDimmSupported(nil) {
t.Skip("Dimm not supported")
}
conf := &Config{
Memory: Memory{
Size: "1G",
Slots: 8,
MaxMem: "3G",
Path: "foobar",
},
}
memString := "-m 1G,slots=8,maxmem=3G"
testConfigAppend(conf, conf.Memory, memString, t)
knobs := Knobs{
FileBackedMem: true,
MemShared: false,
}
knobsString := "-object memory-backend-file,id=dimm1,size=1G,mem-path=foobar -numa node,memdev=dimm1"
mlockFalseString := "-realtime mlock=off"
testConfigAppend(conf, knobs, memString+" "+knobsString+" "+mlockFalseString, t)
}
func TestAppendMemoryFileBackedMemPrealloc(t *testing.T) {
if !isDimmSupported(nil) {
t.Skip("Dimm not supported")
}
conf := &Config{
Memory: Memory{
Size: "1G",
Slots: 8,
MaxMem: "3G",
Path: "foobar",
},
}
memString := "-m 1G,slots=8,maxmem=3G"
testConfigAppend(conf, conf.Memory, memString, t)
knobs := Knobs{
FileBackedMem: true,
MemShared: true,
MemPrealloc: true,
}
knobsString := "-object memory-backend-file,id=dimm1,size=1G,mem-path=foobar,share=on,prealloc=on -numa node,memdev=dimm1"
mlockFalseString := "-realtime mlock=off"
testConfigAppend(conf, knobs, memString+" "+knobsString+" "+mlockFalseString, t)
}
var kernelString = "-kernel /opt/vmlinux.container -initrd /opt/initrd.container -append root=/dev/pmem0p1 rootflags=dax,data=ordered,errors=remount-ro rw rootfstype=ext4 tsc=reliable"
func TestAppendKernel(t *testing.T) {
kernel := Kernel{
Path: "/opt/vmlinux.container",
InitrdPath: "/opt/initrd.container",
Params: "root=/dev/pmem0p1 rootflags=dax,data=ordered,errors=remount-ro rw rootfstype=ext4 tsc=reliable",
}
testAppend(kernel, kernelString, t)
}
var memoryString = "-m 2G,slots=2,maxmem=3G"
func TestAppendMemory(t *testing.T) {
memory := Memory{
Size: "2G",
Slots: 2,
MaxMem: "3G",
Path: "",
}
testAppend(memory, memoryString, t)
}
var cpusString = "-smp 2,cores=1,threads=2,sockets=2,maxcpus=6"
func TestAppendCPUs(t *testing.T) {
smp := SMP{
CPUs: 2,
Sockets: 2,
Cores: 1,
Threads: 2,
MaxCPUs: 6,
}
testAppend(smp, cpusString, t)
}
func TestFailToAppendCPUs(t *testing.T) {
config := Config{
SMP: SMP{
CPUs: 2,
Sockets: 2,
Cores: 1,
Threads: 2,
MaxCPUs: 1,
},
}
if err := config.appendCPUs(); err == nil {
t.Fatalf("Expected appendCPUs to fail")
}
}
var qmpSingleSocketServerString = "-qmp unix:cc-qmp,server,nowait"
var qmpSingleSocketString = "-qmp unix:cc-qmp"
func TestAppendSingleQMPSocketServer(t *testing.T) {
qmp := QMPSocket{
Type: "unix",
Name: "cc-qmp",
Server: true,
NoWait: true,
}
testAppend(qmp, qmpSingleSocketServerString, t)
}
func TestAppendSingleQMPSocket(t *testing.T) {
qmp := QMPSocket{
Type: Unix,
Name: "cc-qmp",
Server: false,
}
testAppend(qmp, qmpSingleSocketString, t)
}
var qmpSocketServerString = "-qmp unix:cc-qmp-1,server,nowait -qmp unix:cc-qmp-2,server,nowait"
func TestAppendQMPSocketServer(t *testing.T) {
qmp := []QMPSocket{
{
Type: "unix",
Name: "cc-qmp-1",
Server: true,
NoWait: true,
},
{
Type: "unix",
Name: "cc-qmp-2",
Server: true,
NoWait: true,
},
}
testAppend(qmp, qmpSocketServerString, t)
}
var pidfile = "/run/vc/vm/iamsandboxid/pidfile"
var logfile = "/run/vc/vm/iamsandboxid/logfile"
var qemuString = "-name cc-qemu -cpu host -uuid " + agentUUID + " -pidfile " + pidfile + " -D " + logfile
func TestAppendStrings(t *testing.T) {
config := Config{
Path: "qemu",
Name: "cc-qemu",
UUID: agentUUID,
CPUModel: "host",
PidFile: pidfile,
LogFile: logfile,
}
config.appendName()
config.appendCPUModel()
config.appendUUID()
config.appendPidFile()
config.appendLogFile()
result := strings.Join(config.qemuParams, " ")
if result != qemuString {
t.Fatalf("Failed to append parameters [%s] != [%s]", result, qemuString)
}
}
var rtcString = "-rtc base=utc,driftfix=slew,clock=host"
func TestAppendRTC(t *testing.T) {
rtc := RTC{
Base: UTC,
Clock: Host,
DriftFix: Slew,
}
testAppend(rtc, rtcString, t)
}
var ioThreadString = "-object iothread,id=iothread1"
func TestAppendIOThread(t *testing.T) {
ioThread := IOThread{
ID: "iothread1",
}
testAppend(ioThread, ioThreadString, t)
}
var incomingStringFD = "-S -incoming fd:3"
func TestAppendIncomingFD(t *testing.T) {
source := Incoming{
MigrationType: MigrationFD,
FD: os.Stdout,
}
testAppend(source, incomingStringFD, t)
}
var incomingStringExec = "-S -incoming exec:test migration cmd"
func TestAppendIncomingExec(t *testing.T) {
source := Incoming{
MigrationType: MigrationExec,
Exec: "test migration cmd",
}
testAppend(source, incomingStringExec, t)
}
var incomingStringDefer = "-S -incoming defer"
func TestAppendIncomingDefer(t *testing.T) {
source := Incoming{
MigrationType: MigrationDefer,
}
testAppend(source, incomingStringDefer, t)
}
func TestBadName(t *testing.T) {
c := &Config{}
c.appendName()
if len(c.qemuParams) != 0 {
t.Errorf("Expected empty qemuParams, found %s", c.qemuParams)
}
}
func TestBadMachine(t *testing.T) {
c := &Config{}
c.appendMachine()
if len(c.qemuParams) != 0 {
t.Errorf("Expected empty qemuParams, found %s", c.qemuParams)
}
}
func TestBadCPUModel(t *testing.T) {
c := &Config{}
c.appendCPUModel()
if len(c.qemuParams) != 0 {
t.Errorf("Expected empty qemuParams, found %s", c.qemuParams)
}
}
func TestBadQMPSockets(t *testing.T) {
c := &Config{}
c.appendQMPSockets()
if len(c.qemuParams) != 0 {
t.Errorf("Expected empty qemuParams, found %s", c.qemuParams)
}
c = &Config{
QMPSockets: []QMPSocket{{}},
}
c.appendQMPSockets()
if len(c.qemuParams) != 0 {
t.Errorf("Expected empty qemuParams, found %s", c.qemuParams)
}
c = &Config{
QMPSockets: []QMPSocket{{Name: "test"}},
}
c.appendQMPSockets()
if len(c.qemuParams) != 0 {
t.Errorf("Expected empty qemuParams, found %s", c.qemuParams)
}
c = &Config{
QMPSockets: []QMPSocket{
{
Name: "test",
Type: QMPSocketType("ip"),
},
},
}
c.appendQMPSockets()
if len(c.qemuParams) != 0 {
t.Errorf("Expected empty qemuParams, found %s", c.qemuParams)
}
}
func TestBadDevices(t *testing.T) {
c := &Config{}
c.appendDevices()
if len(c.qemuParams) != 0 {
t.Errorf("Expected empty qemuParams, found %s", c.qemuParams)
}
c = &Config{
Devices: []Device{
FSDevice{},
FSDevice{
ID: "id0",
MountTag: "tag",
},
CharDevice{},
CharDevice{
ID: "id1",
},
NetDevice{},
NetDevice{
ID: "id1",
IFName: "if",
Type: IPVTAP,
},
SerialDevice{},
SerialDevice{
ID: "id0",
},
BlockDevice{},
BlockDevice{
Driver: "drv",
ID: "id1",
},
VhostUserDevice{},
VhostUserDevice{
CharDevID: "devid",
},
VhostUserDevice{
CharDevID: "devid",
SocketPath: "/var/run/sock",
},
VhostUserDevice{
CharDevID: "devid",
SocketPath: "/var/run/sock",
VhostUserType: VhostUserNet,
},
VhostUserDevice{
CharDevID: "devid",
SocketPath: "/var/run/sock",
VhostUserType: VhostUserSCSI,
},
},
}
c.appendDevices()
if len(c.qemuParams) != 0 {
t.Errorf("Expected empty qemuParams, found %s", c.qemuParams)
}
}
func TestBadRTC(t *testing.T) {
c := &Config{}
c.appendRTC()
if len(c.qemuParams) != 0 {
t.Errorf("Expected empty qemuParams, found %s", c.qemuParams)
}
c = &Config{
RTC: RTC{
Clock: RTCClock("invalid"),
},
}
c.appendRTC()
if len(c.qemuParams) != 0 {
t.Errorf("Expected empty qemuParams, found %s", c.qemuParams)
}
c = &Config{
RTC: RTC{
Clock: Host,
DriftFix: RTCDriftFix("invalid"),
},
}
c.appendRTC()
if len(c.qemuParams) != 0 {
t.Errorf("Expected empty qemuParams, found %s", c.qemuParams)
}
}
func TestBadGlobalParam(t *testing.T) {
c := &Config{}
c.appendGlobalParam()
if len(c.qemuParams) != 0 {
t.Errorf("Expected empty qemuParams, found %s", c.qemuParams)
}
}
func TestBadVGA(t *testing.T) {
c := &Config{}
c.appendVGA()
if len(c.qemuParams) != 0 {
t.Errorf("Expected empty qemuParams, found %s", c.qemuParams)
}
}
func TestBadKernel(t *testing.T) {
c := &Config{}
c.appendKernel()
if len(c.qemuParams) != 0 {
t.Errorf("Expected empty qemuParams, found %s", c.qemuParams)
}
}
func TestBadMemoryKnobs(t *testing.T) {
c := &Config{}
c.appendMemoryKnobs()
if len(c.qemuParams) != 0 {
t.Errorf("Expected empty qemuParams, found %s", c.qemuParams)
}
c = &Config{
Knobs: Knobs{
HugePages: true,
},
}
c.appendMemoryKnobs()
if len(c.qemuParams) != 0 {
t.Errorf("Expected empty qemuParams, found %s", c.qemuParams)
}
c = &Config{
Knobs: Knobs{
MemShared: true,
},
}
c.appendMemoryKnobs()
if len(c.qemuParams) != 0 {
t.Errorf("Expected empty qemuParams, found %s", c.qemuParams)
}
c = &Config{
Knobs: Knobs{
MemPrealloc: true,
},
}
c.appendMemoryKnobs()
if len(c.qemuParams) != 0 {
t.Errorf("Expected empty qemuParams, found %s", c.qemuParams)
}
}
func TestBadKnobs(t *testing.T) {
c := &Config{
Knobs: Knobs{
Mlock: true,
},
}
c.appendKnobs()
if len(c.qemuParams) != 0 {
t.Errorf("Expected empty qemuParams, found %s", c.qemuParams)
}
}
func TestBadBios(t *testing.T) {
c := &Config{}
c.appendBios()
if len(c.qemuParams) != 0 {
t.Errorf("Expected empty qemuParams, found %s", c.qemuParams)
}
}
func TestBadIOThreads(t *testing.T) {
c := &Config{}
c.appendIOThreads()
if len(c.qemuParams) != 0 {
t.Errorf("Expected empty qemuParams, found %s", c.qemuParams)
}
c = &Config{
IOThreads: []IOThread{{ID: ""}},
}
c.appendIOThreads()
if len(c.qemuParams) != 0 {
t.Errorf("Expected empty qemuParams, found %s", c.qemuParams)
}
}
func TestBadIncoming(t *testing.T) {
c := &Config{}
c.appendIncoming()
if len(c.qemuParams) != 0 {
t.Errorf("Expected empty qemuParams, found %s", c.qemuParams)
}
}
func TestBadCPUs(t *testing.T) {
c := &Config{}
if err := c.appendCPUs(); err != nil {
t.Fatalf("No error expected got %v", err)
}
if len(c.qemuParams) != 0 {
t.Errorf("Expected empty qemuParams, found %s", c.qemuParams)
}
c = &Config{
SMP: SMP{
MaxCPUs: 1,
CPUs: 2,
},
}
if c.appendCPUs() == nil {
t.Errorf("Error expected")
}
}