返回 DeepSeek-Reasonix
ownership_completion_test.go
根目录 / internal / jobs / ownership_completion_test.go
1 package jobs
2
3 import (
4 "context"
5 "encoding/json"
6 "io"
7 "os"
8 "path/filepath"
9 "strings"
10 "sync"
11 "testing"
12 )
13
14 func TestRuntimeStateAdoptionAndCompletionShareOwnership(t *testing.T) {
15 for _, phase := range []string{"before-completion", "during-notice", "after-done"} {
16 t.Run(phase, func(t *testing.T) {
17 sink := &blockingFinishedSink{entered: make(chan struct{}), released: make(chan struct{})}
18 m := NewManager(sink)
19 defer m.Close()
20 runRelease := make(chan struct{})
21 releaseRun := sync.OnceFunc(func() { close(runRelease) })
22 releaseNotice := sync.OnceFunc(func() { close(sink.released) })
23 defer releaseRun()
24 defer releaseNotice()
25 job := m.StartForSession("", "bash", "adoption", func(context.Context, io.Writer) (string, error) {
26 <-runRelease
27 return "complete", nil
28 })
29 path := filepath.Join(t.TempDir(), "adopted.jsonl")
30 if phase == "before-completion" {
31 m.SetActiveSessionPath("adopted", path)
32 }
33 releaseRun()
34 <-sink.entered
35 select {
36 case <-job.done:
37 t.Fatal("done closed before completion notice finished")
38 default:
39 }
40 if phase == "during-notice" {
41 m.SetActiveSessionPath("adopted", path)
42 }
43 releaseNotice()
44 <-job.done
45 if phase == "after-done" {
46 m.SetActiveSessionPath("adopted", path)
47 }
48 if got := m.DrainCompletedNoteForSession("other"); got != "" {
49 t.Fatalf("completion leaked: %s", got)
50 }
51 if got := m.DrainCompletedNoteForSession("adopted"); strings.Count(got, job.ID) != 1 {
52 t.Fatalf("completion not owned exactly once: %q", got)
53 }
54 if got := m.DrainCompletedNoteForSession("adopted"); got != "" {
55 t.Fatalf("completion replayed: %q", got)
56 }
57 job.mu.Lock()
58 metaPath := job.artifactMetaPath
59 job.mu.Unlock()
60 if metaPath != "" {
61 data, err := os.ReadFile(metaPath)
62 if err != nil {
63 t.Fatal(err)
64 }
65 var meta artifactMeta
66 if err := json.Unmarshal(data, &meta); err != nil {
67 t.Fatal(err)
68 }
69 if meta.SessionID != "adopted" {
70 t.Fatalf("artifact kept old owner: %q", meta.SessionID)
71 }
72 }
73 })
74 }
75 }
76
76 lines GO