You've already forked agentic-coding-workflow
55 lines
1.3 KiB
Go
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")
|
|
}
|
|
}
|