283 lines
7.8 KiB
Go
283 lines
7.8 KiB
Go
package platform
|
|
|
|
import (
|
|
"fmt"
|
|
"testing"
|
|
)
|
|
|
|
func TestInferLiveBootKind(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
tests := []struct {
|
|
name string
|
|
fsType string
|
|
source string
|
|
deviceType string
|
|
transport string
|
|
want string
|
|
}{
|
|
{name: "ram tmpfs", fsType: "tmpfs", source: "/dev/shm/bee-live", want: "ram"},
|
|
{name: "usb disk", source: "/dev/sdb1", deviceType: "disk", transport: "usb", want: "usb"},
|
|
{name: "cdrom rom", source: "/dev/sr0", deviceType: "rom", want: "cdrom"},
|
|
{name: "disk sata", source: "/dev/nvme0n1p1", deviceType: "disk", transport: "nvme", want: "disk"},
|
|
{name: "unknown", source: "overlay", want: "unknown"},
|
|
}
|
|
for _, tc := range tests {
|
|
tc := tc
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
got := inferLiveBootKind(tc.fsType, tc.source, tc.deviceType, tc.transport)
|
|
if got != tc.want {
|
|
t.Fatalf("inferLiveBootKind(%q,%q,%q,%q)=%q want %q", tc.fsType, tc.source, tc.deviceType, tc.transport, got, tc.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestVerifyInstallToRAMStatus(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
dstDir := t.TempDir()
|
|
|
|
if err := verifyInstallToRAMStatus(LiveBootSource{InRAM: true, Kind: "ram", Source: "tmpfs"}, dstDir, false, nil); err != nil {
|
|
t.Fatalf("expected success for RAM-backed status, got %v", err)
|
|
}
|
|
|
|
err := verifyInstallToRAMStatus(LiveBootSource{InRAM: false, Kind: "usb", Device: "/dev/sdb1"}, dstDir, false, nil)
|
|
if err == nil {
|
|
t.Fatal("expected verification failure when media is still on USB")
|
|
}
|
|
if got := err.Error(); got != "install to RAM verification failed: live medium still mounted from USB (/dev/sdb1) and no squashfs found in "+dstDir {
|
|
t.Fatalf("error=%q", got)
|
|
}
|
|
}
|
|
|
|
func TestDescribeLiveBootSource(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
if got := describeLiveBootSource(LiveBootSource{InRAM: true, Kind: "ram"}); got != "RAM" {
|
|
t.Fatalf("got %q want RAM", got)
|
|
}
|
|
if got := describeLiveBootSource(LiveBootSource{Kind: "unknown", Source: "/run/live/medium"}); got != "/run/live/medium" {
|
|
t.Fatalf("got %q want /run/live/medium", got)
|
|
}
|
|
}
|
|
|
|
func TestEvaluateLiveMediaRAMState(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
t.Run("in_ram", func(t *testing.T) {
|
|
state := evaluateLiveMediaRAMState(
|
|
LiveBootSource{InRAM: true, Kind: "ram", Source: "tmpfs"},
|
|
false,
|
|
nil,
|
|
nil,
|
|
)
|
|
if state.State != "in_ram" || state.Status != "ok" || state.CanStartCopy {
|
|
t.Fatalf("state=%+v", state)
|
|
}
|
|
})
|
|
|
|
t.Run("partial_copy_after_cancel", func(t *testing.T) {
|
|
state := evaluateLiveMediaRAMState(
|
|
LiveBootSource{InRAM: false, Kind: "usb", Device: "/dev/sdb1"},
|
|
false,
|
|
[]string{"/run/live/medium/live/filesystem.squashfs", "/run/live/medium/live/firmware.squashfs"},
|
|
[]string{"/dev/shm/bee-live/filesystem.squashfs"},
|
|
)
|
|
if state.State != "partial" || state.Status != "partial" || !state.CanStartCopy {
|
|
t.Fatalf("state=%+v", state)
|
|
}
|
|
if state.CopyComplete {
|
|
t.Fatalf("CopyComplete=%v want false", state.CopyComplete)
|
|
}
|
|
})
|
|
|
|
t.Run("toram_failed", func(t *testing.T) {
|
|
state := evaluateLiveMediaRAMState(
|
|
LiveBootSource{InRAM: false, Kind: "usb", Device: "/dev/sdb1"},
|
|
true,
|
|
nil,
|
|
nil,
|
|
)
|
|
if state.State != "toram_failed" || state.Status != "failed" || !state.CanStartCopy {
|
|
t.Fatalf("state=%+v", state)
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestShouldLogCopyProgress(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
total := int64(250 * 1024 * 1024)
|
|
step := int64(100 * 1024 * 1024)
|
|
|
|
if shouldLogCopyProgress(step-1, total, 0) {
|
|
t.Fatal("progress logged too early")
|
|
}
|
|
if !shouldLogCopyProgress(step, total, 0) {
|
|
t.Fatal("expected log at first 100MB boundary")
|
|
}
|
|
if shouldLogCopyProgress(step+16*1024*1024, total, step) {
|
|
t.Fatal("progress logged again before next 100MB")
|
|
}
|
|
if !shouldLogCopyProgress(2*step, total, step) {
|
|
t.Fatal("expected log at second 100MB boundary")
|
|
}
|
|
if !shouldLogCopyProgress(total, total, 2*step) {
|
|
t.Fatal("expected final completion log")
|
|
}
|
|
}
|
|
|
|
func TestTryRemountLiveMedium(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
orig := runRemountMedium
|
|
t.Cleanup(func() {
|
|
runRemountMedium = orig
|
|
})
|
|
|
|
t.Run("success", func(t *testing.T) {
|
|
runRemountMedium = func() ([]byte, error) {
|
|
return []byte("[10:57:31] Mounted /dev/sr1 on /run/live/medium\n"), nil
|
|
}
|
|
var logs []string
|
|
if err := tryRemountLiveMedium(func(msg string) { logs = append(logs, msg) }); err != nil {
|
|
t.Fatalf("tryRemountLiveMedium() error = %v", err)
|
|
}
|
|
if len(logs) != 1 || logs[0] != "bee-remount-medium: [10:57:31] Mounted /dev/sr1 on /run/live/medium" {
|
|
t.Fatalf("logs=%v", logs)
|
|
}
|
|
})
|
|
|
|
t.Run("failure", func(t *testing.T) {
|
|
runRemountMedium = func() ([]byte, error) {
|
|
return []byte("must be run as root\n"), fmt.Errorf("exit status 1")
|
|
}
|
|
var logs []string
|
|
err := tryRemountLiveMedium(func(msg string) { logs = append(logs, msg) })
|
|
if err == nil {
|
|
t.Fatal("expected error")
|
|
}
|
|
if len(logs) != 1 || logs[0] != "bee-remount-medium: must be run as root" {
|
|
t.Fatalf("logs=%v", logs)
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestEnsureLiveMediumAvailableRemountsSource(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
origGlob := liveMediumSquashfsGlob
|
|
origRemount := runRemountMedium
|
|
t.Cleanup(func() {
|
|
liveMediumSquashfsGlob = origGlob
|
|
runRemountMedium = origRemount
|
|
})
|
|
|
|
callCount := 0
|
|
liveMediumSquashfsGlob = func() ([]string, error) {
|
|
callCount++
|
|
if callCount == 1 {
|
|
return nil, nil
|
|
}
|
|
return []string{"/run/live/medium/live/filesystem.squashfs"}, nil
|
|
}
|
|
runRemountMedium = func() ([]byte, error) {
|
|
return []byte("Mounted /dev/sr1 on /run/live/medium\n"), nil
|
|
}
|
|
|
|
var logs []string
|
|
files, ok := ensureLiveMediumAvailable(func(msg string) { logs = append(logs, msg) })
|
|
if !ok {
|
|
t.Fatal("expected live medium to become available after remount")
|
|
}
|
|
if callCount < 2 {
|
|
t.Fatalf("liveMediumSquashfsGlob called %d times, want at least 2", callCount)
|
|
}
|
|
if len(files) != 1 || files[0] != "/run/live/medium/live/filesystem.squashfs" {
|
|
t.Fatalf("files=%v", files)
|
|
}
|
|
found := false
|
|
for _, msg := range logs {
|
|
if msg == "Live medium restored after remount scan." {
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
if !found {
|
|
t.Fatalf("expected remount success log, logs=%v", logs)
|
|
}
|
|
}
|
|
|
|
func TestDetachInstallMedium(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
origUmount := umountLiveMedium
|
|
origEject := ejectDevice
|
|
t.Cleanup(func() {
|
|
umountLiveMedium = origUmount
|
|
ejectDevice = origEject
|
|
})
|
|
|
|
t.Run("success", func(t *testing.T) {
|
|
var umountCalled bool
|
|
var ejected string
|
|
umountLiveMedium = func() error {
|
|
umountCalled = true
|
|
return nil
|
|
}
|
|
ejectDevice = func(device string) error {
|
|
ejected = device
|
|
return nil
|
|
}
|
|
var logs []string
|
|
detachInstallMedium(LiveBootSource{Kind: "cdrom", Device: "/dev/sr1"}, func(msg string) { logs = append(logs, msg) })
|
|
if !umountCalled {
|
|
t.Fatal("expected umountLiveMedium to be called")
|
|
}
|
|
if ejected != "/dev/sr1" {
|
|
t.Fatalf("ejected=%q want /dev/sr1", ejected)
|
|
}
|
|
if len(logs) < 3 {
|
|
t.Fatalf("logs=%v", logs)
|
|
}
|
|
})
|
|
|
|
t.Run("no device", func(t *testing.T) {
|
|
umountLiveMedium = func() error { return nil }
|
|
ejectDevice = func(device string) error {
|
|
t.Fatalf("unexpected eject for %q", device)
|
|
return nil
|
|
}
|
|
var logs []string
|
|
detachInstallMedium(LiveBootSource{Kind: "ram", Source: "tmpfs"}, func(msg string) { logs = append(logs, msg) })
|
|
found := false
|
|
for _, msg := range logs {
|
|
if msg == "No block device identified for eject; skipping media eject." {
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
if !found {
|
|
t.Fatalf("logs=%v", logs)
|
|
}
|
|
})
|
|
|
|
t.Run("eject failure is warning only", func(t *testing.T) {
|
|
umountLiveMedium = func() error { return nil }
|
|
ejectDevice = func(device string) error { return fmt.Errorf("exit status 1") }
|
|
var logs []string
|
|
detachInstallMedium(LiveBootSource{Kind: "usb", Device: "/dev/sdb1"}, func(msg string) { logs = append(logs, msg) })
|
|
found := false
|
|
for _, msg := range logs {
|
|
if msg == "Warning: could not eject /dev/sdb1: exit status 1" {
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
if !found {
|
|
t.Fatalf("logs=%v", logs)
|
|
}
|
|
})
|
|
}
|