diff options
| author | 2023-04-28 01:36:44 +0800 | |
|---|---|---|
| committer | 2023-04-28 01:36:44 +0800 | |
| commit | dd84b9d64fb98746a230cd24233ff50a562c39c9 (patch) | |
| tree | b583261ef00b3afe72ec4d6dacb31e57779a6faf /cli/internal/process/child_nix_test.go | |
| parent | 0b46fcd72ac34382387b2bcf9095233efbcc52f4 (diff) | |
| download | HydroRoll-dd84b9d64fb98746a230cd24233ff50a562c39c9.tar.gz HydroRoll-dd84b9d64fb98746a230cd24233ff50a562c39c9.zip | |
Diffstat (limited to 'cli/internal/process/child_nix_test.go')
| -rw-r--r-- | cli/internal/process/child_nix_test.go | 190 |
1 files changed, 190 insertions, 0 deletions
diff --git a/cli/internal/process/child_nix_test.go b/cli/internal/process/child_nix_test.go new file mode 100644 index 0000000..7311d18 --- /dev/null +++ b/cli/internal/process/child_nix_test.go @@ -0,0 +1,190 @@ +//go:build !windows +// +build !windows + +package process + +/** + * Code in this file is based on the source code at + * https://github.com/hashicorp/consul-template/tree/3ea7d99ad8eff17897e0d63dac86d74770170bb8/child/child_test.go + * + * Tests in this file use signals or pgid features not available on windows + */ + +import ( + "os/exec" + "syscall" + "testing" + "time" + + "github.com/hashicorp/go-gatedio" +) + +func TestSignal(t *testing.T) { + + c := testChild(t) + cmd := exec.Command("sh", "-c", "trap 'echo one; exit' USR1; while true; do sleep 0.2; done") + c.cmd = cmd + + out := gatedio.NewByteBuffer() + c.cmd.Stdout = out + + if err := c.Start(); err != nil { + t.Fatal(err) + } + defer c.Stop() + + // For some reason bash doesn't start immediately + time.Sleep(fileWaitSleepDelay) + + if err := c.Signal(syscall.SIGUSR1); err != nil { + t.Fatal(err) + } + + // Give time for the file to flush + time.Sleep(fileWaitSleepDelay) + + expected := "one\n" + if out.String() != expected { + t.Errorf("expected %q to be %q", out.String(), expected) + } +} + +func TestStop_childAlreadyDead(t *testing.T) { + c := testChild(t) + c.cmd = exec.Command("sh", "-c", "exit 1") + c.splay = 100 * time.Second + c.killSignal = syscall.SIGTERM + + if err := c.Start(); err != nil { + t.Fatal(err) + } + + // For some reason bash doesn't start immediately + time.Sleep(fileWaitSleepDelay) + + killStartTime := time.Now() + c.Stop() + killEndTime := time.Now() + + if killEndTime.Sub(killStartTime) > fileWaitSleepDelay { + t.Error("expected not to wait for splay") + } +} + +func TestSignal_noProcess(t *testing.T) { + + c := testChild(t) + if err := c.Signal(syscall.SIGUSR1); err != nil { + // Just assert there is no error + t.Fatal(err) + } +} + +func TestKill_signal(t *testing.T) { + + c := testChild(t) + cmd := exec.Command("sh", "-c", "trap 'echo one; exit' USR1; while true; do sleep 0.2; done") + c.killSignal = syscall.SIGUSR1 + + out := gatedio.NewByteBuffer() + cmd.Stdout = out + c.cmd = cmd + + if err := c.Start(); err != nil { + t.Fatal(err) + } + defer c.Stop() + + // For some reason bash doesn't start immediately + time.Sleep(fileWaitSleepDelay) + + c.Kill() + + // Give time for the file to flush + time.Sleep(fileWaitSleepDelay) + + expected := "one\n" + if out.String() != expected { + t.Errorf("expected %q to be %q", out.String(), expected) + } +} + +func TestKill_noProcess(t *testing.T) { + c := testChild(t) + c.killSignal = syscall.SIGUSR1 + c.Kill() +} + +func TestStop_noWaitForSplay(t *testing.T) { + c := testChild(t) + c.cmd = exec.Command("sh", "-c", "trap 'echo one; exit' USR1; while true; do sleep 0.2; done") + c.splay = 100 * time.Second + c.killSignal = syscall.SIGUSR1 + + out := gatedio.NewByteBuffer() + c.cmd.Stdout = out + + if err := c.Start(); err != nil { + t.Fatal(err) + } + + // For some reason bash doesn't start immediately + time.Sleep(fileWaitSleepDelay) + + killStartTime := time.Now() + c.StopImmediately() + killEndTime := time.Now() + + expected := "one\n" + if out.String() != expected { + t.Errorf("expected %q to be %q", out.String(), expected) + } + + if killEndTime.Sub(killStartTime) > fileWaitSleepDelay { + t.Error("expected not to wait for splay") + } +} + +func TestSetpgid(t *testing.T) { + t.Run("true", func(t *testing.T) { + c := testChild(t) + c.cmd = exec.Command("sh", "-c", "while true; do sleep 0.2; done") + // default, but to be explicit for the test + c.setpgid = true + + if err := c.Start(); err != nil { + t.Fatal(err) + } + defer c.Stop() + + // when setpgid is true, the pid and gpid should be the same + gpid, err := syscall.Getpgid(c.Pid()) + if err != nil { + t.Fatal("Getpgid error:", err) + } + + if c.Pid() != gpid { + t.Fatal("pid and gpid should match") + } + }) + t.Run("false", func(t *testing.T) { + c := testChild(t) + c.cmd = exec.Command("sh", "-c", "while true; do sleep 0.2; done") + c.setpgid = false + + if err := c.Start(); err != nil { + t.Fatal(err) + } + defer c.Stop() + + // when setpgid is true, the pid and gpid should be the same + gpid, err := syscall.Getpgid(c.Pid()) + if err != nil { + t.Fatal("Getpgid error:", err) + } + + if c.Pid() == gpid { + t.Fatal("pid and gpid should NOT match") + } + }) +} |
