Files
ThothII/tools/tht/internal/compose/process_termination_test.go

82 lines
2.3 KiB
Go

package compose
import (
"errors"
"os"
"testing"
"time"
)
func TestTerminationKillsTheTreeEvenWhenTheDirectChildIsAlreadyReaped(t *testing.T) {
done := make(chan error, 1)
done <- nil
treeFailure := errors.New("tree termination failed")
treeCalls := 0
directCalls := 0
err := terminateProcessTree(done, func() error {
treeCalls++
return treeFailure
}, func() error {
directCalls++
return os.ErrProcessDone
}, time.Second)
if treeCalls != 1 {
t.Fatalf("tree termination calls = %d, want 1", treeCalls)
}
if directCalls != 1 {
t.Fatalf("direct termination calls = %d, want 1 fallback after tree failure", directCalls)
}
if !errors.Is(err, treeFailure) || !errors.Is(err, ErrProcessReap) {
t.Fatalf("terminateProcessTree() error = %v, want tree failure and ErrProcessReap", err)
}
if errors.Is(err, os.ErrProcessDone) {
t.Fatalf("terminateProcessTree() error = %v, must treat an already-reaped direct child as benign", err)
}
}
func TestTerminationWaitsForTheOriginalProcessAfterTreeTermination(t *testing.T) {
done := make(chan error, 1)
done <- nil
directCalls := 0
err := terminateProcessTree(done, func() error { return nil }, func() error {
directCalls++
return errors.New("direct fallback should not run after a successful tree termination")
}, time.Second)
if err != nil {
t.Fatalf("terminateProcessTree() error = %v, want nil", err)
}
if directCalls != 0 {
t.Fatalf("direct termination calls = %d, want 0", directCalls)
}
}
func TestTerminationJoinsTreeDirectAndReapFailures(t *testing.T) {
done := make(chan error)
treeFailure := errors.New("tree termination failed")
directFailure := errors.New("direct termination failed")
err := terminateProcessTree(done, func() error { return treeFailure }, func() error { return directFailure }, 0)
for _, want := range []error{treeFailure, directFailure, ErrProcessReap} {
if !errors.Is(err, want) {
t.Fatalf("terminateProcessTree() error = %v, want %v", err, want)
}
}
}
func TestTerminationReportsReapFailureWhenTheTreeTerminatesButTheProcessNeverReaps(t *testing.T) {
done := make(chan error)
err := terminateProcessTree(done, func() error { return nil }, func() error {
return errors.New("direct fallback should not run")
}, 0)
if !errors.Is(err, ErrProcessReap) {
t.Fatalf("terminateProcessTree() error = %v, want ErrProcessReap", err)
}
}