package cmdext import ( "errors" "fmt" "testing" "time" ) func TestStdout(t *testing.T) { res1, err := Runner("printf").Arg("hello").Run() if err != nil { t.Errorf("%v", err) } if res1.CommandTimedOut { t.Errorf("Timeout") } if res1.ExitCode != 0 { t.Errorf("res1.ExitCode == %v", res1.ExitCode) } if res1.StdErr != "" { t.Errorf("res1.StdErr == '%v'", res1.StdErr) } if res1.StdOut != "hello" { t.Errorf("res1.StdOut == '%v'", res1.StdOut) } if res1.StdCombined != "hello\n" { t.Errorf("res1.StdCombined == '%v'", res1.StdCombined) } } func TestStderr(t *testing.T) { res1, err := Runner("python3").Arg("-c").Arg("import sys; print(\"error\", file=sys.stderr, end='')").Run() if err != nil { t.Errorf("%v", err) } if res1.CommandTimedOut { t.Errorf("Timeout") } if res1.ExitCode != 0 { t.Errorf("res1.ExitCode == %v", res1.ExitCode) } if res1.StdErr != "error" { t.Errorf("res1.StdErr == '%v'", res1.StdErr) } if res1.StdOut != "" { t.Errorf("res1.StdOut == '%v'", res1.StdOut) } if res1.StdCombined != "error\n" { t.Errorf("res1.StdCombined == '%v'", res1.StdCombined) } } func TestStdcombined(t *testing.T) { res1, err := Runner("python3"). Arg("-c"). Arg("import sys; import time; print(\"1\", file=sys.stderr, flush=True); time.sleep(0.1); print(\"2\", file=sys.stdout, flush=True); time.sleep(0.1); print(\"3\", file=sys.stderr, flush=True)"). Run() if err != nil { t.Errorf("%v", err) } if res1.CommandTimedOut { t.Errorf("Timeout") } if res1.ExitCode != 0 { t.Errorf("res1.ExitCode == %v", res1.ExitCode) } if res1.StdErr != "1\n3\n" { t.Errorf("res1.StdErr == '%v'", res1.StdErr) } if res1.StdOut != "2\n" { t.Errorf("res1.StdOut == '%v'", res1.StdOut) } if res1.StdCombined != "1\n2\n3\n" { t.Errorf("res1.StdCombined == '%v'", res1.StdCombined) } } func TestPartialRead(t *testing.T) { res1, err := Runner("python3"). Arg("-c"). Arg("import sys; import time; print(\"first message\", flush=True); time.sleep(5); print(\"cant see me\", flush=True);"). Timeout(100 * time.Millisecond). Run() if err != nil { t.Errorf("%v", err) } if !res1.CommandTimedOut { t.Errorf("!CommandTimedOut") } if res1.StdErr != "" { t.Errorf("res1.StdErr == '%v'", res1.StdErr) } if res1.StdOut != "first message\n" { t.Errorf("res1.StdOut == '%v'", res1.StdOut) } if res1.StdCombined != "first message\n" { t.Errorf("res1.StdCombined == '%v'", res1.StdCombined) } } func TestPartialReadStderr(t *testing.T) { res1, err := Runner("python3"). Arg("-c"). Arg("import sys; import time; print(\"first message\", file=sys.stderr, flush=True); time.sleep(5); print(\"cant see me\", file=sys.stderr, flush=True);"). Timeout(100 * time.Millisecond). Run() if err != nil { t.Errorf("%v", err) } if !res1.CommandTimedOut { t.Errorf("!CommandTimedOut") } if res1.StdErr != "first message\n" { t.Errorf("res1.StdErr == '%v'", res1.StdErr) } if res1.StdOut != "" { t.Errorf("res1.StdOut == '%v'", res1.StdOut) } if res1.StdCombined != "first message\n" { t.Errorf("res1.StdCombined == '%v'", res1.StdCombined) } } func TestReadUnflushedStdout(t *testing.T) { res1, err := Runner("python3").Arg("-c").Arg("import sys; print(\"message101\", file=sys.stdout, end='')").Run() if err != nil { t.Errorf("%v", err) } if res1.CommandTimedOut { t.Errorf("Timeout") } if res1.ExitCode != 0 { t.Errorf("res1.ExitCode == %v", res1.ExitCode) } if res1.StdErr != "" { t.Errorf("res1.StdErr == '%v'", res1.StdErr) } if res1.StdOut != "message101" { t.Errorf("res1.StdOut == '%v'", res1.StdOut) } if res1.StdCombined != "message101\n" { t.Errorf("res1.StdCombined == '%v'", res1.StdCombined) } } func TestReadUnflushedStderr(t *testing.T) { res1, err := Runner("python3").Arg("-c").Arg("import sys; print(\"message101\", file=sys.stderr, end='')").Run() if err != nil { t.Errorf("%v", err) } if res1.CommandTimedOut { t.Errorf("Timeout") } if res1.ExitCode != 0 { t.Errorf("res1.ExitCode == %v", res1.ExitCode) } if res1.StdErr != "message101" { t.Errorf("res1.StdErr == '%v'", res1.StdErr) } if res1.StdOut != "" { t.Errorf("res1.StdOut == '%v'", res1.StdOut) } if res1.StdCombined != "message101\n" { t.Errorf("res1.StdCombined == '%v'", res1.StdCombined) } } func TestPartialReadUnflushed(t *testing.T) { t.SkipNow() res1, err := Runner("python3"). Arg("-c"). Arg("import sys; import time; print(\"first message\", end=''); time.sleep(5); print(\"cant see me\", end='');"). Timeout(100 * time.Millisecond). Run() if err != nil { t.Errorf("%v", err) } if !res1.CommandTimedOut { t.Errorf("!CommandTimedOut") } if res1.StdErr != "" { t.Errorf("res1.StdErr == '%v'", res1.StdErr) } if res1.StdOut != "first message" { t.Errorf("res1.StdOut == '%v'", res1.StdOut) } if res1.StdCombined != "first message" { t.Errorf("res1.StdCombined == '%v'", res1.StdCombined) } } func TestPartialReadUnflushedStderr(t *testing.T) { t.SkipNow() res1, err := Runner("python3"). Arg("-c"). Arg("import sys; import time; print(\"first message\", file=sys.stderr, end=''); time.sleep(5); print(\"cant see me\", file=sys.stderr, end='');"). Timeout(100 * time.Millisecond). Run() if err != nil { t.Errorf("%v", err) } if !res1.CommandTimedOut { t.Errorf("!CommandTimedOut") } if res1.StdErr != "first message" { t.Errorf("res1.StdErr == '%v'", res1.StdErr) } if res1.StdOut != "" { t.Errorf("res1.StdOut == '%v'", res1.StdOut) } if res1.StdCombined != "first message" { t.Errorf("res1.StdCombined == '%v'", res1.StdCombined) } } func TestListener(t *testing.T) { res1, err := Runner("python3"). Arg("-c"). Arg("import sys;" + "import time;" + "print(\"message 1\", flush=True);" + "time.sleep(1);" + "print(\"message 2\", flush=True);" + "time.sleep(1);" + "print(\"message 3\", flush=True);" + "time.sleep(1);" + "print(\"message 4\", file=sys.stderr, flush=True);" + "time.sleep(1);" + "print(\"message 5\", flush=True);" + "time.sleep(1);" + "print(\"final\");"). ListenStdout(func(s string) { fmt.Printf("@@STDOUT <<- %v (%v)\n", s, time.Now().Format(time.RFC3339Nano)) }). ListenStderr(func(s string) { fmt.Printf("@@STDERR <<- %v (%v)\n", s, time.Now().Format(time.RFC3339Nano)) }). Timeout(10 * time.Second). Run() if err != nil { panic(err) } if res1.CommandTimedOut { t.Errorf("Timeout") } if res1.ExitCode != 0 { t.Errorf("res1.ExitCode == %v", res1.ExitCode) } } func TestLongStdout(t *testing.T) { res1, err := Runner("python3"). Arg("-c"). Arg("import sys; import time; print(\"X\" * 125001 + \"\\n\"); print(\"Y\" * 125001 + \"\\n\"); print(\"Z\" * 125001 + \"\\n\");"). Timeout(5000 * time.Millisecond). Run() if err != nil { t.Errorf("%v", err) } if res1.CommandTimedOut { t.Errorf("Timeout") } if res1.ExitCode != 0 { t.Errorf("res1.ExitCode == %v", res1.ExitCode) } if res1.StdErr != "" { t.Errorf("res1.StdErr == '%v'", res1.StdErr) } if len(res1.StdOut) != 375009 { t.Errorf("len(res1.StdOut) == '%v'", len(res1.StdOut)) } } func TestFailOnTimeout(t *testing.T) { _, err := Runner("sleep").Arg("2").Timeout(200 * time.Millisecond).FailOnTimeout().Run() if !errors.Is(err, ErrTimeout) { t.Errorf("wrong err := %v", err) } } func TestFailOnStderr(t *testing.T) { res1, err := Runner("python3").Arg("-c").Arg("import sys; print(\"error\", file=sys.stderr, end='')").FailOnStderr().Run() if err == nil { t.Errorf("no err") } if res1.CommandTimedOut { t.Errorf("Timeout") } if res1.ExitCode != -1 { t.Errorf("res1.ExitCode == %v", res1.ExitCode) } if res1.StdErr != "error" { t.Errorf("res1.StdErr == '%v'", res1.StdErr) } if res1.StdOut != "" { t.Errorf("res1.StdOut == '%v'", res1.StdOut) } if res1.StdCombined != "error\n" { t.Errorf("res1.StdCombined == '%v'", res1.StdCombined) } } func TestFailOnExitcode(t *testing.T) { _, err := Runner("false").Timeout(200 * time.Millisecond).FailOnExitCode().Run() if !errors.Is(err, ErrExitCode) { t.Errorf("wrong err := %v", err) } } func TestEnsureExitcode1(t *testing.T) { _, err := Runner("false").Timeout(200 * time.Millisecond).EnsureExitcode(1).Run() if err != nil { t.Errorf("wrong err := %v", err) } } func TestEnsureExitcode2(t *testing.T) { _, err := Runner("false").Timeout(200*time.Millisecond).EnsureExitcode(0, 2, 3).Run() if err != ErrExitCode { t.Errorf("wrong err := %v", err) } }