55 "database/sql"
66 "os"
77 "path/filepath"
8+ "strings"
89 "sync/atomic"
910 "testing"
1011 "time"
@@ -54,7 +55,7 @@ func TestOpenCodeLateContainerAdmissionUsesJournalEvidence(t *testing.T) {
5455 require .Len (t , keys , 1 )
5556 assert .True (t , engine .opencodeCoverage .worker .unit (keys [0 ]).committedCheckpoint ().Initialized ,
5657 "runtime admission must use the row-zero origin, not the baseline sentinel" )
57- require .True (t , engine .wakeOpenCodePath (t .Context (), dbPath + "-wal" ))
58+ require .True (t , engine .wakeOpenCodePath (t .Context (), dbPath ))
5859 key , admitted := engine .opencodeCoverage .keyForPath (dbPath )
5960 require .True (t , admitted )
6061 assert .Equal (t , parser .AgentOpenCode , key .Agent )
@@ -66,6 +67,7 @@ func TestOpenCodeLateContainerAdmissionUsesJournalEvidence(t *testing.T) {
6667
6768func TestOpenCodeWakePathWakesEveryOverlappingUnit (t * testing.T ) {
6869 dbPath := filepath .Join (t .TempDir (), "opencode.db" )
70+ require .NoError (t , os .WriteFile (dbPath , nil , 0o644 ))
6971 first := openCodeCoverageKey {Agent : parser .AgentOpenCode , DBPath : dbPath }
7072 second := openCodeCoverageKey {Agent : parser .AgentKilo , DBPath : dbPath }
7173 var wakes atomic.Int32
@@ -90,6 +92,80 @@ func TestOpenCodeWakePathWakesEveryOverlappingUnit(t *testing.T) {
9092 c .stop ()
9193}
9294
95+ type coverageRelevanceProvider struct {
96+ parser.ProviderBase
97+ }
98+
99+ func (p * coverageRelevanceProvider ) Parse (
100+ context.Context , parser.ParseRequest ,
101+ ) (parser.ParseOutcome , error ) {
102+ return parser.ParseOutcome {}, nil
103+ }
104+
105+ func (p * coverageRelevanceProvider ) ChangedPathRelevance (
106+ _ context.Context , req parser.ChangedPathRequest ,
107+ ) (parser.ChangedPathRelevance , error ) {
108+ if strings .HasSuffix (req .Path , "-shm" ) {
109+ return parser .ChangedPathNonData , nil
110+ }
111+ if strings .HasSuffix (req .Path , "-wal" ) {
112+ return parser .ChangedPathNonData , nil
113+ }
114+ return parser .ChangedPathDataBearing , nil
115+ }
116+
117+ func TestOpenCodeWakePathHonorsSidecarRelevance (t * testing.T ) {
118+ dbPath := filepath .Join (t .TempDir (), "opencode.db" )
119+ require .NoError (t , os .WriteFile (dbPath , nil , 0o644 ))
120+ key := openCodeCoverageKey {Agent : parser .AgentOpenCode , DBPath : dbPath }
121+ var wakes atomic.Int32
122+ c := & openCodeCoverageCoordinator {
123+ units : map [openCodeCoverageKey ]struct {}{key : {}},
124+ providers : map [parser.AgentType ]parser.Provider {
125+ parser .AgentOpenCode : & coverageRelevanceProvider {
126+ ProviderBase : parser.ProviderBase {Caps : parser.Capabilities {
127+ Source : parser.SourceCapabilities {
128+ ChangedPathRelevance : parser .CapabilitySupported ,
129+ },
130+ }},
131+ },
132+ },
133+ }
134+ c .worker = newOpenCodeCoverageWorker (t .Context (), nil , nil )
135+ c .worker .drain = func (
136+ context.Context , string , parser.OpenCodeCoverageCheckpoint ,
137+ ) (parser.OpenCodeFeedResult , error ) {
138+ wakes .Add (1 )
139+ return parser.OpenCodeFeedResult {
140+ Next : parser.OpenCodeCoverageCheckpoint {Initialized : true },
141+ }, nil
142+ }
143+ c .worker .Register (key )
144+ e := & Engine {opencodeCoverage : c }
145+
146+ assert .Empty (t , e .wakeOpenCodePaths (t .Context (), []string {dbPath + "-shm" }))
147+ assert .Empty (t , e .wakeOpenCodePaths (t .Context (), []string {dbPath + "-wal" }))
148+ assert .Zero (t , wakes .Load (), "non-data sidecars must not wake coverage" )
149+ assert .Empty (t , e .wakeOpenCodePaths (t .Context (), []string {dbPath }))
150+ assert .Eventually (t , func () bool { return wakes .Load () == 1 }, time .Second , time .Millisecond )
151+ c .stop ()
152+ }
153+
154+ func TestOpenCodeWatcherDeletedUnitReturnsPathToNormalSync (t * testing.T ) {
155+ dbPath := filepath .Join (t .TempDir (), "opencode.db" )
156+ key := openCodeCoverageKey {Agent : parser .AgentOpenCode , DBPath : dbPath }
157+ c := & openCodeCoverageCoordinator {
158+ units : map [openCodeCoverageKey ]struct {}{key : {}},
159+ worker : newOpenCodeCoverageWorker (t .Context (), nil , nil ),
160+ }
161+ c .worker .Register (key )
162+ e := & Engine {opencodeCoverage : c }
163+
164+ assert .Equal (t , []string {dbPath }, e .wakeOpenCodePaths (t .Context (), []string {dbPath }))
165+ assert .Empty (t , c .keysForPath (dbPath ), "deleted units must be retired before normal processing" )
166+ c .stop ()
167+ }
168+
93169func TestOpenCodeDeletedUnitLeavesRootForAuthoritativeReconciliation (t * testing.T ) {
94170 root := t .TempDir ()
95171 key := openCodeCoverageKey {
@@ -110,6 +186,7 @@ func TestOpenCodeDeletedUnitLeavesRootForAuthoritativeReconciliation(t *testing.
110186
111187func TestSyncPathsDivertsAdmittedContainerToWake (t * testing.T ) {
112188 dbPath := filepath .Join (t .TempDir (), "opencode.db" )
189+ require .NoError (t , os .WriteFile (dbPath , nil , 0o644 ))
113190 key := openCodeCoverageKey {Agent : parser .AgentOpenCode , DBPath : dbPath }
114191 var wakes atomic.Int32
115192 c := & openCodeCoverageCoordinator {
0 commit comments