From a74358073424c31c712783923a436c127fc310e2 Mon Sep 17 00:00:00 2001 From: Nia Waldvogel Date: Fri, 14 Jan 2022 11:34:56 -0500 Subject: [PATCH] main (test): reorganize runTestWithConfig This change updates the test runner to use exec.CommandContext for timeout handling. The timeout has been raised to 1 minute to handle slow machines and (hopefully) Windows. The test run also now acquires the semaphore to reserve CPU time for the test and (hopefully?????) reduce the number of timeouts in Windows CI. --- main_test.go | 39 ++++++++++++--------------------------- 1 file changed, 12 insertions(+), 27 deletions(-) diff --git a/main_test.go b/main_test.go index 9660d33e..d83448bf 100644 --- a/main_test.go +++ b/main_test.go @@ -6,6 +6,7 @@ package main import ( "bufio" "bytes" + "context" "errors" "flag" "fmt" @@ -366,13 +367,20 @@ func runTestWithConfig(name string, t *testing.T, options compileopts.Options, c return } + // Reserve CPU time for the test to run. + // This attempts to ensure that the test is not CPU-starved. + options.Semaphore <- struct{}{} + defer func() { <-options.Semaphore }() + // Create the test command, taking care of emulators etc. + ctx, cancel := context.WithTimeout(context.Background(), time.Minute) + defer cancel() var cmd *exec.Cmd if len(spec.Emulator) == 0 { - cmd = exec.Command(binary) + cmd = exec.CommandContext(ctx, binary) } else { args := append(spec.Emulator[1:], binary) - cmd = exec.Command(spec.Emulator[0], args...) + cmd = exec.CommandContext(ctx, spec.Emulator[0], args...) } if len(spec.Emulator) != 0 && spec.Emulator[0] == "wasmtime" { // Allow reading from the current directory. @@ -389,8 +397,6 @@ func runTestWithConfig(name string, t *testing.T, options compileopts.Options, c } // Run the test. - runComplete := make(chan struct{}) - ranTooLong := false stdout := &bytes.Buffer{} if len(spec.Emulator) != 0 && spec.Emulator[0] == "simavr" { cmd.Stdout = os.Stderr @@ -403,32 +409,11 @@ func runTestWithConfig(name string, t *testing.T, options compileopts.Options, c if err != nil { t.Fatal("failed to start:", err) } - go func() { - // Terminate the process if it runs too long. - maxDuration := 10 * time.Second - if runtime.GOOS == "windows" { - // For some reason, tests on Windows can take around - // 30s to complete. TODO: investigate why and fix this. - maxDuration = 40 * time.Second - } - timer := time.NewTimer(maxDuration) - select { - case <-runComplete: - timer.Stop() - case <-timer.C: - ranTooLong = true - if runtime.GOOS == "windows" { - cmd.Process.Signal(os.Kill) // Windows doesn't support SIGINT. - } else { - cmd.Process.Signal(os.Interrupt) - } - } - }() err = cmd.Wait() - close(runComplete) - if ranTooLong { + if cerr := ctx.Err(); cerr == context.DeadlineExceeded { stdout.WriteString("--- test ran too long, terminating...\n") + err = cerr } // putchar() prints CRLF, convert it to LF.