JOJ3/internal/executor/local/executor_test.go
张泊明518370910136 79a64efbfd
Some checks failed
build / build (push) Successful in 1m22s
build / trigger-build-image (push) Has been skipped
build / build (pull_request) Failing after 44s
build / trigger-build-image (pull_request) Has been skipped
test: cover stage and executor reliability regressions
2026-08-02 01:51:04 -07:00

53 lines
1.3 KiB
Go

package local
import (
"context"
"errors"
"os"
"path/filepath"
"testing"
"time"
"github.com/joint-online-judge/JOJ3/internal/stage"
)
func TestRunRejectsEmptyArgs(t *testing.T) {
_, err := (&Local{}).Run(context.Background(), []stage.Cmd{{}})
if err == nil || err.Error() != "command args must not be empty" {
t.Fatalf("Run() error = %v", err)
}
}
func TestRunCancellationKillsProcessGroup(t *testing.T) {
dir := t.TempDir()
ready := filepath.Join(dir, "ready")
marker := filepath.Join(dir, "marker")
ctx, cancel := context.WithCancel(context.Background())
done := make(chan error, 1)
go func() {
_, err := (&Local{}).Run(ctx, []stage.Cmd{{
Args: []string{"/bin/sh", "-c", "touch \"$1\"; (sleep 0.3; touch \"$2\") & wait", "sh", ready, marker},
}})
done <- err
}()
deadline := time.Now().Add(2 * time.Second)
for {
if _, err := os.Stat(ready); err == nil {
break
}
if time.Now().After(deadline) {
t.Fatal("command did not start")
}
time.Sleep(10 * time.Millisecond)
}
cancel()
if err := <-done; !errors.Is(err, context.Canceled) {
t.Fatalf("Run() error = %v, want context canceled", err)
}
time.Sleep(500 * time.Millisecond)
if _, err := os.Stat(marker); !errors.Is(err, os.ErrNotExist) {
t.Fatalf("child process survived cancellation: %v", err)
}
}