tortoise/main_test.go

154 lines
3.5 KiB
Go

package tortoise_test
import (
"sync"
"testing"
"time"
"git.iamthefij.com/iamthefij/tortoise"
)
func TestShellRunnerNoCallback(t *testing.T) {
t.Parallel()
cases := []struct {
command string
output string
ReturnCode int
}{
{"echo hello world", "hello world\n", 0},
{"echo hello world && exit 1", "hello world\n", 1},
}
for _, c := range cases {
c := c
t.Run(c.command, func(t *testing.T) {
t.Parallel()
runner := tortoise.NewShellRunner()
runner.Start()
// Test command without callback
if err := runner.AddCommand(c.command, nil); err != nil {
t.Fatalf("unexpected error adding command: %v", err)
}
runner.Stop()
result := runner.GetResults()
if result == nil || result.Output != c.output || result.ReturnCode != c.ReturnCode {
t.Fatalf("expected output '%s' and return code %d, got '%s' and %d", c.output, c.ReturnCode, result.Output, result.ReturnCode)
}
})
}
}
func TestShellRunnerCallback(t *testing.T) {
t.Parallel()
runner := tortoise.NewShellRunner()
runner.Start()
// Test command with callback
outputString := ""
callbackWait := sync.WaitGroup{}
callbackWait.Add(1)
if err := runner.AddCommand("echo callback a", func(result *tortoise.CommandResult) {
if result.Output != "callback a\n" {
t.Fatalf("expected 'callback a', got '%s'", result.Output)
}
outputString = outputString + "a"
callbackWait.Done()
}); err != nil {
t.Fatalf("unexpected error adding command: %v", err)
}
callbackWait.Add(1)
if err := runner.AddCommand("echo callback b", func(result *tortoise.CommandResult) {
if result.Output != "callback b\n" {
t.Fatalf("expected 'callback b', got '%s'", result.Output)
}
outputString = outputString + "b"
callbackWait.Done()
}); err != nil {
t.Fatalf("unexpected error adding command: %v", err)
}
// Timeout waiting for callbacks
done := make(chan struct{})
go func() {
callbackWait.Wait()
close(done)
}()
select {
case <-done:
case <-time.After(2 * time.Second):
t.Fatal("callbacks timed out")
}
if outputString != "ab" {
t.Fatal("callbacks was not reached in order:", outputString)
}
runner.Stop()
// Make sure stop and kill both exit gracefully after the runner is stopped
runner.Stop()
runner.Kill()
}
func TestShellRunnerKillWithTimeout(t *testing.T) {
t.Parallel()
runner := tortoise.NewShellRunner()
runner.Start()
// Test command with callback
callbackReached := false
if err := runner.AddCommand("sleep 10 && echo callback test", func(result *tortoise.CommandResult) {
callbackReached = true
if result.Output != "callback test\n" {
t.Fatalf("expected 'callback test', got '%s'", result.Output)
}
}); err != nil {
t.Fatalf("unexpected error adding command: %v", err)
}
// Wait one second to make sure the command starts running
time.Sleep(1 * time.Second)
if err := runner.KillWithTimeout(1 * time.Second); err == nil {
t.Fatal("expected error when killing commands, but got none")
}
if callbackReached {
t.Fatal("callback was reached before kill")
}
}
func TestStopPreventsNewCommands(t *testing.T) {
runner := tortoise.NewShellRunner()
runner.Start()
runner.Stop()
err := runner.AddCommand("echo should not run", nil)
if err == nil {
t.Fatal("expected error when adding command after stop, but got none")
}
}
func TestAddingPriorToStart(t *testing.T) {
runner := tortoise.NewShellRunner()
err := runner.AddCommand("echo should not run", nil)
if err == nil {
t.Fatal("Should have failed to add prior to starting runner")
}
}