From ba3edc5638f656b73592a44151fd9341a5935031 Mon Sep 17 00:00:00 2001 From: Florian Klink Date: Sat, 23 Sep 2023 17:34:01 +0300 Subject: feat(tvix/tests): add basic plumbing for integration tests This adds a basic skeleton to test various tvix components in combination. As a first start, we test the virtiofs integration, by seeding the tvix- store with some data, booting a VM, and listing the contents from there. Change-Id: Ice6516d0eb508d19ea8fabefee860a0950046171 Reviewed-on: https://cl.tvl.fyi/c/depot/+/9449 Autosubmit: flokli Tested-by: BuildkiteCI Reviewed-by: Connor Brewster --- tvix/tests/tvix-init.go | 85 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 tvix/tests/tvix-init.go (limited to 'tvix/tests/tvix-init.go') diff --git a/tvix/tests/tvix-init.go b/tvix/tests/tvix-init.go new file mode 100644 index 0000000000..a81001159a --- /dev/null +++ b/tvix/tests/tvix-init.go @@ -0,0 +1,85 @@ +package main + +import ( + "log" + "os" + "os/exec" + "strings" + "syscall" +) + +// run the given command, connecting std{in,err,out} with the OS one. +func run(args ...string) error { + cmd := exec.Command(args[0], args[1:]...) + cmd.Stdin = os.Stdin + cmd.Stderr = os.Stderr + cmd.Stdout = os.Stdout + + return cmd.Run() +} + +// parse the cmdline, return a map[string]string. +func parseCmdline(cmdline string) map[string]string { + line := strings.TrimSuffix(cmdline, "\n") + fields := strings.Fields(line) + out := make(map[string]string, 0) + + for _, arg := range fields { + kv := strings.SplitN(arg, "=", 2) + switch len(kv) { + case 1: + out[kv[0]] = "" + case 2: + out[kv[0]] = kv[1] + } + } + + return out +} + +func main() { + log.Println("Running tvix-init…") + + log.Println("Creating /nix/store") + os.MkdirAll("/nix/store", os.ModePerm) + + cmdline, err := os.ReadFile("/proc/cmdline") + if err != nil { + log.Printf("Failed to read cmdline: %s\n", err) + } + cmdlineFields := parseCmdline(string(cmdline)) + + log.Println("Mounting…") + if err := run("mount", "-t", "virtiofs", "tvix", "/nix/store", "-o", "ro"); err != nil { + log.Printf("Failed to run mount: %v\n", err) + } + + // If tvix.find is set, invoke find /nix/store + if _, ok := cmdlineFields["tvix.find"]; ok { + log.Println("Listing…") + if err := run("find", "/nix/store"); err != nil { + log.Printf("Failed to run find command: %s\n", err) + } + } + + // If tvix.shell is set, invoke the elvish shell + if v, ok := cmdlineFields["tvix.shell"]; ok { + log.Printf("Invoking shell%s\n…", v) + if err := run("elvish"); err != nil { + log.Printf("Failed to run shell: %s\n", err) + } + } + + // If tvix.exec is set, invoke the binary specified + if v, ok := cmdlineFields["tvix.exec"]; ok { + log.Printf("Invoking %s\n…", v) + if err := syscall.Exec(v, []string{v}, []string{}); err != nil { + log.Printf("Failed to exec: %s\n", err) + } + } + + log.Println("Powering off") + if err := run("poweroff"); err != nil { + log.Printf("Failed to run command: %v\n", err) + } +} -- cgit 1.4.1