From 4a1e0f96edbab3078ccbb5e7ed88cf852b9d3d22 Mon Sep 17 00:00:00 2001 From: Chris Koch Date: Mon, 15 Jan 2024 03:10:20 +0000 Subject: [PATCH 1/4] Rename helloworld -> catfile test cmd Signed-off-by: Chris Koch --- tests/cmds/catfile/.gitignore | 1 + tests/cmds/{helloworld => catfile}/main_linux.go | 3 +-- tests/cmds/helloworld/.gitignore | 1 - tests/startexample/vm_test.go | 4 ++-- 4 files changed, 4 insertions(+), 5 deletions(-) create mode 100644 tests/cmds/catfile/.gitignore rename tests/cmds/{helloworld => catfile}/main_linux.go (87%) delete mode 100644 tests/cmds/helloworld/.gitignore diff --git a/tests/cmds/catfile/.gitignore b/tests/cmds/catfile/.gitignore new file mode 100644 index 0000000..cab0757 --- /dev/null +++ b/tests/cmds/catfile/.gitignore @@ -0,0 +1 @@ +catfile diff --git a/tests/cmds/helloworld/main_linux.go b/tests/cmds/catfile/main_linux.go similarity index 87% rename from tests/cmds/helloworld/main_linux.go rename to tests/cmds/catfile/main_linux.go index 88062f7..240e869 100644 --- a/tests/cmds/helloworld/main_linux.go +++ b/tests/cmds/catfile/main_linux.go @@ -1,5 +1,4 @@ -// Command httpdownload configures networking with DHCP and downloads one web -// page. +// Command catfile reads a file. package main import ( diff --git a/tests/cmds/helloworld/.gitignore b/tests/cmds/helloworld/.gitignore deleted file mode 100644 index 31e0fce..0000000 --- a/tests/cmds/helloworld/.gitignore +++ /dev/null @@ -1 +0,0 @@ -helloworld diff --git a/tests/startexample/vm_test.go b/tests/startexample/vm_test.go index 77f1f25..411084f 100644 --- a/tests/startexample/vm_test.go +++ b/tests/startexample/vm_test.go @@ -21,10 +21,10 @@ func TestStart(t *testing.T) { Commands: uroot.BusyBoxCmds( "github.com/u-root/u-root/cmds/core/init", "github.com/u-root/u-root/cmds/core/elvish", - "github.com/hugelgupf/vmtest/tests/cmds/helloworld", + "github.com/hugelgupf/vmtest/tests/cmds/catfile", ), InitCmd: "init", - UinitCmd: "helloworld", + UinitCmd: "catfile", UinitArgs: []string{"-file", "/testdata/hello"}, TempDir: t.TempDir(), } From 0c5bec4bd1da2d1456b17c1b218c7098c77c26e6 Mon Sep 17 00:00:00 2001 From: Chris Koch Date: Mon, 15 Jan 2024 03:12:16 +0000 Subject: [PATCH 2/4] Rename qemutest1 -> helloworld test cmd Signed-off-by: Chris Koch --- qemu/qemu_test.go | 6 ++--- tests/cmds/helloworld/.gitignore | 1 + .../{qemutest1 => helloworld}/main_linux.go | 4 +-- tests/cmds/qemutest1/.gitignore | 1 - uqemu/uqemu_test.go | 26 +++++++++---------- 5 files changed, 19 insertions(+), 19 deletions(-) create mode 100644 tests/cmds/helloworld/.gitignore rename tests/cmds/{qemutest1 => helloworld}/main_linux.go (69%) delete mode 100644 tests/cmds/qemutest1/.gitignore diff --git a/qemu/qemu_test.go b/qemu/qemu_test.go index 648b25f..b8a5d80 100644 --- a/qemu/qemu_test.go +++ b/qemu/qemu_test.go @@ -276,13 +276,13 @@ func TestStartVM(t *testing.T) { uopts := uroot.Opts{ Env: env, InitCmd: "init", - UinitCmd: "qemutest1", + UinitCmd: "helloworld", OutputFile: initrdWriter, TempDir: tmp, } uopts.AddBusyBoxCommands( "github.com/u-root/u-root/cmds/core/init", - "github.com/hugelgupf/vmtest/tests/cmds/qemutest1", + "github.com/hugelgupf/vmtest/tests/cmds/helloworld", ) if err := uroot.CreateInitramfs(logger, uopts); err != nil { t.Fatalf("error creating initramfs: %v", err) @@ -298,7 +298,7 @@ func TestStartVM(t *testing.T) { } t.Logf("cmdline: %#v", vm.CmdlineQuoted()) - if _, err := vm.Console.ExpectString("I AM HERE"); err != nil { + if _, err := vm.Console.ExpectString("Hello world"); err != nil { t.Errorf("Error expecting I AM HERE: %v", err) } diff --git a/tests/cmds/helloworld/.gitignore b/tests/cmds/helloworld/.gitignore new file mode 100644 index 0000000..31e0fce --- /dev/null +++ b/tests/cmds/helloworld/.gitignore @@ -0,0 +1 @@ +helloworld diff --git a/tests/cmds/qemutest1/main_linux.go b/tests/cmds/helloworld/main_linux.go similarity index 69% rename from tests/cmds/qemutest1/main_linux.go rename to tests/cmds/helloworld/main_linux.go index 62efbc3..24d374e 100644 --- a/tests/cmds/qemutest1/main_linux.go +++ b/tests/cmds/helloworld/main_linux.go @@ -1,4 +1,4 @@ -// Package qemutest1 is just a test program for qemu/ tests. +// Package helloworld prints hello world and shuts down. package main import ( @@ -9,7 +9,7 @@ import ( ) func main() { - fmt.Println("I AM HERE") + fmt.Println("Hello world") if err := unix.Reboot(unix.LINUX_REBOOT_CMD_POWER_OFF); err != nil { log.Fatalf("Failed to shut down: %v", err) diff --git a/tests/cmds/qemutest1/.gitignore b/tests/cmds/qemutest1/.gitignore deleted file mode 100644 index 58c1d9f..0000000 --- a/tests/cmds/qemutest1/.gitignore +++ /dev/null @@ -1 +0,0 @@ -qemutest1 diff --git a/uqemu/uqemu_test.go b/uqemu/uqemu_test.go index d15c51f..ef4bfbc 100644 --- a/uqemu/uqemu_test.go +++ b/uqemu/uqemu_test.go @@ -73,11 +73,11 @@ func TestStartVM(t *testing.T) { initramfs := uroot.Opts{ InitCmd: "init", - UinitCmd: "qemutest1", + UinitCmd: "helloworld", TempDir: tmp, Commands: uroot.BusyBoxCmds( "github.com/u-root/u-root/cmds/core/init", - "github.com/hugelgupf/vmtest/tests/cmds/qemutest1", + "github.com/hugelgupf/vmtest/tests/cmds/helloworld", ), } vm, err := qemu.Start(qemu.ArchUseEnvv, WithUrootInitramfs(logger, initramfs, initrdPath), qemu.WithSerialOutput(w)) @@ -86,8 +86,8 @@ func TestStartVM(t *testing.T) { } t.Logf("cmdline: %#v", vm.CmdlineQuoted()) - if _, err := vm.Console.ExpectString("I AM HERE"); err != nil { - t.Errorf("Error expecting I AM HERE: %v", err) + if _, err := vm.Console.ExpectString("Hello world"); err != nil { + t.Errorf("Error expecting Hello world: %v", err) } if err := vm.Wait(); err != nil { @@ -104,16 +104,16 @@ func TestTask(t *testing.T) { r, w := io.Pipe() var taskGotCanceled bool - var taskSawIAmHere bool + var taskSawHelloWorld bool var vmExitErr error initramfs := uroot.Opts{ InitCmd: "init", - UinitCmd: "qemutest1", + UinitCmd: "helloworld", TempDir: tmp, Commands: uroot.BusyBoxCmds( "github.com/u-root/u-root/cmds/core/init", - "github.com/hugelgupf/vmtest/tests/cmds/qemutest1", + "github.com/hugelgupf/vmtest/tests/cmds/helloworld", ), } vm, err := qemu.Start( @@ -125,8 +125,8 @@ func TestTask(t *testing.T) { s := bufio.NewScanner(r) for s.Scan() { line := string(replaceCtl(s.Bytes())) - if strings.Contains(line, "I AM HERE") { - taskSawIAmHere = true + if strings.Contains(line, "Hello world") { + taskSawHelloWorld = true } t.Logf("vm: %s", line) } @@ -159,8 +159,8 @@ func TestTask(t *testing.T) { } t.Logf("cmdline: %#v", vm.CmdlineQuoted()) - if _, err := vm.Console.ExpectString("I AM HERE"); err != nil { - t.Errorf("Error expecting I AM HERE: %v", err) + if _, err := vm.Console.ExpectString("Hello world"); err != nil { + t.Errorf("Error expecting Hello world: %v", err) } werr := vm.Wait() @@ -174,8 +174,8 @@ func TestTask(t *testing.T) { if !taskGotCanceled { t.Error("Error: Task did not get canceled") } - if !taskSawIAmHere { - t.Error("Error: Serial console task didn't see I AM HERE") + if !taskSawHelloWorld { + t.Error("Error: Serial console task didn't see Hello world") } } From d015c07039d6a4899623371bf8af249fd5c7c252 Mon Sep 17 00:00:00 2001 From: Chris Koch Date: Mon, 15 Jan 2024 03:13:07 +0000 Subject: [PATCH 3/4] helloworld: add repeat flag Signed-off-by: Chris Koch --- tests/cmds/helloworld/main_linux.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tests/cmds/helloworld/main_linux.go b/tests/cmds/helloworld/main_linux.go index 24d374e..ad1ba57 100644 --- a/tests/cmds/helloworld/main_linux.go +++ b/tests/cmds/helloworld/main_linux.go @@ -2,14 +2,21 @@ package main import ( + "flag" "fmt" "log" "golang.org/x/sys/unix" ) +var n = flag.Int("n", 1, "How many times to repeat Hello world") + func main() { - fmt.Println("Hello world") + flag.Parse() + + for i := 0; i < n; i++ { + fmt.Println("Hello world") + } if err := unix.Reboot(unix.LINUX_REBOOT_CMD_POWER_OFF); err != nil { log.Fatalf("Failed to shut down: %v", err) From 7bc2091daa557a46a206e3c8d7897e79708c5685 Mon Sep 17 00:00:00 2001 From: Chris Koch Date: Mon, 15 Jan 2024 03:24:51 +0000 Subject: [PATCH 4/4] Make sure lots of guest output does not cause hangs Signed-off-by: Chris Koch --- qemu/qemu.go | 8 ++++++++ tests/cmds/helloworld/main_linux.go | 4 ++-- uqemu/uqemu_test.go | 30 +++++++++++++++++++++++++++++ 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/qemu/qemu.go b/qemu/qemu.go index 6f29a55..d11c802 100644 --- a/qemu/qemu.go +++ b/qemu/qemu.go @@ -528,6 +528,14 @@ func (v *VM) Waited() bool { func (v *VM) Wait() error { v.waitCalled.Store(true) + // If there is a lot of output after the last user's Expect call (or + // there are no Expect calls at all), the pty buffer may fill up and + // the guest is blocked from writing anything and from continuing + // execution. + // + // Therefore, drain! EOF should happen when the guest exits. + _, _ = v.Console.ExpectEOF() + <-v.wait v.waitMu.Lock() diff --git a/tests/cmds/helloworld/main_linux.go b/tests/cmds/helloworld/main_linux.go index ad1ba57..f619025 100644 --- a/tests/cmds/helloworld/main_linux.go +++ b/tests/cmds/helloworld/main_linux.go @@ -14,8 +14,8 @@ var n = flag.Int("n", 1, "How many times to repeat Hello world") func main() { flag.Parse() - for i := 0; i < n; i++ { - fmt.Println("Hello world") + for i := 0; i < *n; i++ { + fmt.Println("Hello world", i) } if err := unix.Reboot(unix.LINUX_REBOOT_CMD_POWER_OFF); err != nil { diff --git a/uqemu/uqemu_test.go b/uqemu/uqemu_test.go index ef4bfbc..0005709 100644 --- a/uqemu/uqemu_test.go +++ b/uqemu/uqemu_test.go @@ -450,3 +450,33 @@ func TestInvalidInitramfs(t *testing.T) { }) } } + +func TestOutputFillsConsoleBuffers(t *testing.T) { + // 4000 repeats of Hello world fill the buffer of the pty used by the + // Expect library. Make sure this does not cause hangs. + initramfs := uroot.Opts{ + InitCmd: "init", + UinitCmd: "helloworld", + UinitArgs: []string{"-n", "4000"}, + TempDir: t.TempDir(), + Commands: uroot.BusyBoxCmds( + "github.com/u-root/u-root/cmds/core/init", + "github.com/hugelgupf/vmtest/tests/cmds/helloworld", + ), + } + vm, err := qemu.Start( + qemu.ArchUseEnvv, + WithUrootInitramfsT(t, initramfs), + qemu.LogSerialByLine(qemu.PrintLineWithPrefix("vm", t.Logf)), + ) + if err != nil { + t.Fatalf("Failed to start VM: %v", err) + } + t.Logf("cmdline: %#v", vm.CmdlineQuoted()) + + // No calls to Expect means nothing is draining the Console pty buffer. + + if err := vm.Wait(); err != nil { + t.Fatalf("Error waiting for VM to exit: %v", err) + } +}