Files
2026-06-09 22:43:29 +08:00

55 lines
1.3 KiB
Go

package proc
import (
"fmt"
"os/exec"
"runtime"
"testing"
"time"
)
// sleeperCmd 返回一个会阻塞约 d 秒的跨平台命令。
func sleeperCmd(d int) *exec.Cmd {
if runtime.GOOS == "windows" {
return exec.Command("cmd", "/c", fmt.Sprintf("timeout /t %d /nobreak >nul", d))
}
return exec.Command("sh", "-c", fmt.Sprintf("sleep %d", d))
}
// TestGroup_TerminateKillsStartedProcess 验证完整生命周期:Prepare → Start →
// Adopt → TerminateGroup 能在 grace 内终止一个本应长跑的进程。
func TestGroup_TerminateKillsStartedProcess(t *testing.T) {
g := NewGroup()
cmd := sleeperCmd(30)
g.Prepare(cmd)
if err := cmd.Start(); err != nil {
t.Fatalf("start: %v", err)
}
if err := g.Adopt(cmd); err != nil {
t.Fatalf("adopt: %v", err)
}
defer g.Close()
done := make(chan struct{})
go func() {
_ = cmd.Wait()
close(done)
}()
g.TerminateGroup(done, 2*time.Second)
select {
case <-done:
// 进程已终止,符合预期。
case <-time.After(10 * time.Second):
t.Fatal("process not terminated within 10s after TerminateGroup")
}
}
// TestNewGroup_NotNil 守护 build tag 选择逻辑:任意平台都应返回非 nil Group。
func TestNewGroup_NotNil(t *testing.T) {
if NewGroup() == nil {
t.Fatal("NewGroup returned nil")
}
}