From e7d457e5a1b5ce03bb308a4217f543633138145f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20B=C3=B6hm?= Date: Sun, 29 Oct 2023 19:30:48 +0100 Subject: [PATCH] Allow running multiple test binaries at once in parallel --- cmd/pidonetest/flags.go | 33 ++++++++++++++++---------------- cmd/pidonetest/main.go | 42 ++++++++++++++++++++++++++++------------- 2 files changed, 46 insertions(+), 29 deletions(-) diff --git a/cmd/pidonetest/flags.go b/cmd/pidonetest/flags.go index c205657..6bed13e 100644 --- a/cmd/pidonetest/flags.go +++ b/cmd/pidonetest/flags.go @@ -8,7 +8,7 @@ import ( "github.com/aibor/pidonetest/internal" ) -func parseArgs(args []string, testBinaryPath *string, qemuCmd *internal.QEMUCommand, standalone *bool) error { +func parseArgs(args []string, testBinaries *[]string, qemuCmd *internal.QEMUCommand, standalone *bool) error { fsName := fmt.Sprintf("%s [flags...] [testbinary] [testflags...]", args[0]) fs := flag.NewFlagSet(fsName, flag.ContinueOnError) @@ -25,29 +25,30 @@ func parseArgs(args []string, testBinaryPath *string, qemuCmd *internal.QEMUComm return err } - posArgs := fs.Args() - if len(posArgs) < 1 { - fmt.Fprintln(fs.Output(), "no testbinary given") - fs.Usage() - return fmt.Errorf("no testbinary given") - } - - *testBinaryPath = posArgs[0] - // Catch coverage related paths and adjust them. - for i := 1; i < len(posArgs); i++ { - arg := posArgs[i] - splits := strings.Split(arg, "=") + for _, posArg := range fs.Args() { + splits := strings.Split(posArg, "=") switch splits[0] { case "-test.coverprofile": qemuCmd.SerialFiles = append(qemuCmd.SerialFiles, splits[1]) splits[1] = "/dev/ttyS1" - arg = strings.Join(splits, "=") + posArg = strings.Join(splits, "=") case "-test.gocoverdir": splits[1] = "/tmp" - arg = strings.Join(splits, "=") + posArg = strings.Join(splits, "=") } - qemuCmd.InitArgs = append(qemuCmd.InitArgs, arg) + + if strings.HasPrefix(posArg, "-") { + qemuCmd.InitArgs = append(qemuCmd.InitArgs, posArg) + } else { + *testBinaries = append(*testBinaries, posArg) + } + } + + if len(*testBinaries) < 1 { + fmt.Fprintln(fs.Output(), "no testbinary given") + fs.Usage() + return fmt.Errorf("no testbinary given") } return nil diff --git a/cmd/pidonetest/main.go b/cmd/pidonetest/main.go index f592043..0bf018a 100644 --- a/cmd/pidonetest/main.go +++ b/cmd/pidonetest/main.go @@ -10,6 +10,7 @@ import ( "os/signal" "path/filepath" "runtime" + "slices" "syscall" "github.com/aibor/initramfs" @@ -19,9 +20,9 @@ import ( func run() (int, error) { var ( - testBinaryPath string - err error - standalone bool + binaries []string + err error + standalone bool ) qemuCmd, err := internal.NewQEMUCommand(runtime.GOARCH) @@ -32,15 +33,17 @@ func run() (int, error) { qemuCmd.Kernel = os.Getenv("PIDEONETEST_KERNEL") // ParseArgs already prints errors, so we just exit. - if err := parseArgs(os.Args, &testBinaryPath, qemuCmd, &standalone); err != nil { + if err := parseArgs(os.Args, &binaries, qemuCmd, &standalone); err != nil { if err == flag.ErrHelp { return 0, nil } return 1, nil } - if _, err := os.Stat(testBinaryPath); errors.Is(err, os.ErrNotExist) { - return 1, fmt.Errorf("testbinary file %s doesn't exist.", testBinaryPath) + for _, file := range binaries { + if _, err := os.Stat(file); errors.Is(err, os.ErrNotExist) { + return 1, fmt.Errorf("file %s doesn't exist.", file) + } } if qemuCmd.Kernel == "" { @@ -52,7 +55,8 @@ func run() (int, error) { var archive *internal.Initramfs if standalone { - archive = internal.NewInitramfs(testBinaryPath) + archive = internal.NewInitramfs(binaries[0]) + binaries = slices.Delete(binaries, 0, 1) } else { var self string self, err = os.Executable() @@ -60,10 +64,12 @@ func run() (int, error) { return 1, fmt.Errorf("get own path: %v", err) } archive = internal.NewInitramfs(self) - if err := archive.AddFile("test", testBinaryPath); err != nil { - return 1, fmt.Errorf("add test binary: %v", err) - } } + + if err := archive.AddFiles(binaries...); err != nil { + return 1, fmt.Errorf("add binares: %v", err) + } + qemuCmd.Initrd, err = archive.Write() if err != nil { return 1, fmt.Errorf("write initramfs: %v", err) @@ -107,13 +113,23 @@ func runInit() (int, error) { return 126, err } + files, err := os.ReadDir(initramfs.FilesDir) + if err != nil { + return 125, err + } + + paths := make([]string, len(files)) + for idx, f := range files { + paths[idx] = filepath.Join(initramfs.FilesDir, f.Name()) + } + rc := 0 - path := filepath.Join(initramfs.FilesDir, "test") - err = sysinit.Exec(path, os.Args[1:], os.Stdout, os.Stderr) + err = sysinit.ExecParallel(paths, os.Args[1:], os.Stdout, os.Stderr) if err != nil { if !errors.Is(err, &exec.ExitError{}) { - return 125, err + return 124, err } + err = nil rc = 1 } sysinit.PrintRC(rc)