Add exiter to test os.Exit case (#729)

authored-by: jingdi.zhu <jingdi.zhu@bytedance.com>
This commit is contained in:
xiantang
2025-01-19 22:55:20 +08:00
committed by GitHub
parent 0811477d4f
commit ad8fbb7a1c
3 changed files with 109 additions and 4 deletions
+12 -3
View File
@@ -17,7 +17,9 @@ import (
// Engine ...
type Engine struct {
config *Config
config *Config
exiter exiter
proxy *Proxy
logger *logger
watcher filenotify.FileWatcher
@@ -50,6 +52,7 @@ func NewEngineWithConfig(cfg *Config, debugMode bool) (*Engine, error) {
}
e := Engine{
config: cfg,
exiter: defaultExiter{},
proxy: NewProxy(&cfg.Proxy),
logger: logger,
watcher: watcher,
@@ -655,8 +658,14 @@ func (e *Engine) stopBin() {
close(exitCode)
}
})
if ret := <-exitCode; ret != 0 {
os.Exit(ret)
select {
case ret := <-exitCode:
if ret != 0 {
e.exiter.Exit(ret) // Use exiter instead of direct os.Exit, it's for tests purpose.
}
case <-time.After(5 * time.Second):
e.mainDebug("timed out waiting for process exit")
}
}
+84 -1
View File
@@ -1044,7 +1044,7 @@ include_file = ["main.sh"]
t.Logf("start change main.sh")
go func() {
err := os.WriteFile("main.sh", []byte("#!/bin/sh\nprintf modified > output"), 0o755)
err = os.WriteFile("main.sh", []byte("#!/bin/sh\nprintf modified > output"), 0o755)
if err != nil {
log.Fatalf("Error updating file: %s.", err)
}
@@ -1058,3 +1058,86 @@ include_file = ["main.sh"]
}
assert.Equal(t, []byte("modified"), bytes)
}
type testExiter struct {
t *testing.T
called bool
expectCode int
}
func (te *testExiter) Exit(code int) {
te.called = true
if code != te.expectCode {
te.t.Fatalf("expected exit code %d, got %d", te.expectCode, code)
}
}
func TestEngineExit(t *testing.T) {
tests := []struct {
name string
setup func(*Engine, chan<- int)
expectCode int
wantCalled bool
}{
{
name: "normal exit - no error",
setup: func(_ *Engine, exitCode chan<- int) {
go func() {
exitCode <- 0
}()
},
expectCode: 0,
wantCalled: false,
},
{
name: "error exit - non-zero code",
setup: func(_ *Engine, exitCode chan<- int) {
go func() {
exitCode <- 1
}()
},
expectCode: 1,
wantCalled: true,
},
{
name: "process timeout",
setup: func(_ *Engine, _ chan<- int) {
},
expectCode: 0,
wantCalled: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
e, err := NewEngine("", true)
if err != nil {
t.Fatal(err)
}
exiter := &testExiter{
t: t,
expectCode: tt.expectCode,
}
e.exiter = exiter
exitCode := make(chan int)
if tt.setup != nil {
tt.setup(e, exitCode)
}
select {
case ret := <-exitCode:
if ret != 0 {
e.exiter.Exit(ret)
}
case <-time.After(1 * time.Millisecond):
// timeout case
}
if tt.wantCalled != exiter.called {
t.Errorf("Exit() called = %v, want %v", exiter.called, tt.wantCalled)
}
})
}
}
+13
View File
@@ -0,0 +1,13 @@
package runner
import "os"
type exiter interface {
Exit(code int)
}
type defaultExiter struct{}
func (d defaultExiter) Exit(code int) {
os.Exit(code)
}