blob: cfb18804dbe1b0113a8d1ed59ff36ddba0d24f23 [file] [log] [blame]
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package virtual_device
import (
"testing"
"go.fuchsia.dev/fuchsia/tools/build"
fvdpb "go.fuchsia.dev/fuchsia/tools/virtual_device/proto"
)
func TestValidate(t *testing.T) {
// An ImageManifest shared by all test cases. This is not modified during testing.
testImageManifest := build.ImageManifest{
{Name: "qemu-kernel", Path: "/kernel", Type: "kernel"},
{Name: "storage-full", Path: "/fvm", Type: "blk"},
{Name: "zircon-a", Path: "/ramdisk", Type: "zbi"},
// Images for testing error cases.
{Name: "no-path"},
{Name: "duplicate", Path: "/duplicate"},
{Name: "duplicate", Path: "/duplicate"},
}
// Test cases.
//
// setupFVD is used to initialize the FVD to pass to Validate. It is called with a
// known-good FVD as input, during test setup.
tests := []struct {
name string
setupFVD func(*fvdpb.VirtualDevice)
wantErr bool
}{{
name: "ok",
setupFVD: func(fvd *fvdpb.VirtualDevice) { return },
}, {
name: "missing kernel",
setupFVD: func(fvd *fvdpb.VirtualDevice) { fvd.Kernel = "" },
wantErr: true,
}, {
name: "missing drive name",
setupFVD: func(fvd *fvdpb.VirtualDevice) { fvd.Drive.Image = "" },
wantErr: true,
}, {
name: "missing MAC",
setupFVD: func(fvd *fvdpb.VirtualDevice) { fvd.Hw.Mac = "" },
wantErr: true,
}, {
name: "missing initial ramdisk",
setupFVD: func(fvd *fvdpb.VirtualDevice) { fvd.Initrd = "" },
wantErr: true,
}, {
name: "invalid ram",
setupFVD: func(fvd *fvdpb.VirtualDevice) { fvd.Hw.Ram = "-1G" },
wantErr: true,
}, {
name: "invalid arch",
setupFVD: func(fvd *fvdpb.VirtualDevice) { fvd.Hw.Arch = "MIPS" },
wantErr: true,
}, {
name: "invalid mac",
setupFVD: func(fvd *fvdpb.VirtualDevice) { fvd.Hw.Mac = "0::12345" },
wantErr: true,
}, {
name: "image is missing path",
setupFVD: func(fvd *fvdpb.VirtualDevice) { fvd.Kernel = "no-path" },
wantErr: true,
}, {
name: "image has non-unique name",
setupFVD: func(fvd *fvdpb.VirtualDevice) { fvd.Kernel = "duplicate" },
wantErr: true,
}}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
inputFVD := Default()
tt.setupFVD(inputFVD)
if err := Validate(inputFVD, testImageManifest); err != nil != tt.wantErr {
if tt.wantErr {
t.Fatalf("wanted an error but got nil")
}
t.Fatalf("got error %v", err)
}
})
}
// Nil cases.
if err := Validate(nil, testImageManifest); err == nil {
t.Fatalf("Validate(nil, /*images*/) wanted an error but got nil")
}
if err := Validate(Default(), nil); err == nil {
t.Fatalf("Validate(Default(), nil) wanted an error but got nil")
}
}
func TestIsValidRAM(t *testing.T) {
tests := []struct {
ram string
want bool
}{
{"", false},
{"0", false},
{"1", false},
{"1Z", false},
{"b", false},
{"-22G", false},
{"0b", true},
{"0B", true},
{"1k", true},
{"1K", true},
{"16m", true},
{"16M", true},
{"256g", true},
{"256G", true},
}
for _, tt := range tests {
t.Run(tt.ram, func(t *testing.T) {
if isValidRAM(tt.ram) != tt.want {
t.Fatalf("isValidRAM(%q) got %v but wanted %v", tt.ram, !tt.want, tt.want)
}
})
}
}
func TestIsValidArch(t *testing.T) {
tests := []struct {
arch string
want bool
}{
{"", false},
{"MIPS", false},
{"x64", true},
{"arm64", true},
}
for _, tt := range tests {
t.Run(tt.arch, func(t *testing.T) {
if isValidArch(tt.arch) != tt.want {
t.Fatalf("isValidArch(%q) got %v but wanted %v", tt.arch, !tt.want, tt.want)
}
})
}
}
func TestIsValidMAC(t *testing.T) {
tests := []struct {
mac string
want bool
}{
{"00", false},
{"00:11", false},
{"00:11:22", false},
{"00:11:22:33", false},
{"00:11:22:33:44", false},
{"00:11:22:33:44:55:", false},
{":00:11:22:33:44:55:", false},
{"00:11:22:33:44:55:66", false},
{"00:11:22:33:44:55:66", false},
{"00:11:22:33:44:55", true},
{"7d:af:25:e3:dd:0b", true},
}
for _, tt := range tests {
t.Run(tt.mac, func(t *testing.T) {
if isValidMAC(tt.mac) != tt.want {
t.Fatalf("isValidMAC(%q) got %v but wanted %v", tt.mac, !tt.want, tt.want)
}
})
}
}
func TestParseRAMBytes(t *testing.T) {
tests := []struct {
ram string
wantBytes float64 // float64 simplfies using math.Pow without casting to int.
wantErr bool
}{
{"5b", 5, false},
{"5B", 5, false},
{"5k", 1024 * 5, false},
{"5K", 1024 * 5, false},
{"5m", 1024 * 1024 * 5, false},
{"5M", 1024 * 1024 * 5, false},
{"5g", 1024 * 1024 * 1024 * 5, false},
{"5G", 1024 * 1024 * 1024 * 5, false},
{"", -1, true},
{"-5G", -1, true},
{"5z", -1, true},
}
for _, tt := range tests {
t.Run(tt.ram, func(t *testing.T) {
gotBytes, err := parseRAMBytes(tt.ram)
if err != nil != tt.wantErr {
if tt.wantErr {
t.Fatalf("parseRAMBytes(%q) wanted an error but got nil", tt.ram)
}
t.Fatalf("parseRAMBytes(%q) got error %v", tt.ram, err)
}
wantBytes := int(tt.wantBytes)
if gotBytes != wantBytes {
t.Fatalf("parseRAMBytes(%q) got %d but wanted %d", tt.ram, gotBytes, wantBytes)
}
})
}
}