Skip to content

Commit

Permalink
Add exiter to test os.Exit case (#729)
Browse files Browse the repository at this point in the history
authored-by: jingdi.zhu <[email protected]>
  • Loading branch information
xiantang authored Jan 19, 2025
1 parent 0811477 commit ad8fbb7
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 4 deletions.
15 changes: 12 additions & 3 deletions runner/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ import (

// Engine ...
type Engine struct {
config *Config
config *Config

exiter exiter
proxy *Proxy
logger *logger
watcher filenotify.FileWatcher
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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")
}
}

Expand Down
85 changes: 84 additions & 1 deletion runner/engine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand All @@ -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 changes: 13 additions & 0 deletions runner/exiter.go
Original file line number Diff line number Diff line change
@@ -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)
}

0 comments on commit ad8fbb7

Please sign in to comment.