44package harvest
55
66import (
7+ "context"
78 "errors"
89 "os"
910 "path/filepath"
@@ -21,50 +22,58 @@ import (
2122)
2223
2324// successfulExtractRoutes simulates a successful route extraction
24- func successfulExtractRoutes (app.PID ) (* RouteHarvesterResult , error ) {
25+ func successfulExtractRoutes (context. Context , app.PID ) (* RouteHarvesterResult , error ) {
2526 return & RouteHarvesterResult {
2627 Routes : []string {"/api/users" , "/api/orders" },
2728 Kind : CompleteRoutes ,
2829 }, nil
2930}
3031
3132// errorExtractRoutes simulates an error during route extraction
32- func errorExtractRoutes (app.PID ) (* RouteHarvesterResult , error ) {
33+ func errorExtractRoutes (context. Context , app.PID ) (* RouteHarvesterResult , error ) {
3334 return nil , errors .New ("failed to connect to Java process" )
3435}
3536
3637// timeoutExtractRoutes simulates a slow operation that will timeout
37- func timeoutExtractRoutes (app.PID ) (* RouteHarvesterResult , error ) {
38- // Sleep longer than any reasonable timeout
39- time .Sleep (5 * time .Second )
40- return & RouteHarvesterResult {
41- Routes : []string {"/api/delayed" },
42- Kind : CompleteRoutes ,
43- }, nil
38+ func timeoutExtractRoutes (ctx context.Context , _ app.PID ) (* RouteHarvesterResult , error ) {
39+ <- ctx .Done ()
40+ return nil , ctx .Err ()
4441}
4542
4643// panicExtractRoutes simulates a panic during route extraction
47- func panicExtractRoutes (app.PID ) (* RouteHarvesterResult , error ) {
44+ func panicExtractRoutes (context. Context , app.PID ) (* RouteHarvesterResult , error ) {
4845 panic ("unexpected error in java route extraction" )
4946}
5047
5148// slowButSuccessfulExtractRoutes simulates a slow but successful operation
52- func slowButSuccessfulExtractRoutes (app.PID ) (* RouteHarvesterResult , error ) {
53- time .Sleep (50 * time .Millisecond ) // Slow but within timeout
49+ func slowButSuccessfulExtractRoutes (ctx context.Context , _ app.PID ) (* RouteHarvesterResult , error ) {
50+ select {
51+ case <- ctx .Done ():
52+ return nil , ctx .Err ()
53+ case <- time .After (50 * time .Millisecond ): // Slow but within timeout
54+ }
5455 return & RouteHarvesterResult {
5556 Routes : []string {"/api/slow" },
5657 Kind : PartialRoutes ,
5758 }, nil
5859}
5960
6061// emptyResultExtractRoutes simulates successful extraction with no routes
61- func emptyResultExtractRoutes (app.PID ) (* RouteHarvesterResult , error ) {
62+ func emptyResultExtractRoutes (context. Context , app.PID ) (* RouteHarvesterResult , error ) {
6263 return & RouteHarvesterResult {
6364 Routes : []string {},
6465 Kind : CompleteRoutes ,
6566 }, nil
6667}
6768
69+ func successfulNodeExtractRoutes (pid app.PID ) (* RouteHarvesterResult , error ) {
70+ return successfulExtractRoutes (context .Background (), pid )
71+ }
72+
73+ func errorNodeExtractRoutes (pid app.PID ) (* RouteHarvesterResult , error ) {
74+ return errorExtractRoutes (context .Background (), pid )
75+ }
76+
6877func createTestFileInfo (language svc.InstrumentableType ) * exec.FileInfo {
6978 return exec .New (exec.Init {
7079 Pid : 12345 ,
@@ -172,7 +181,7 @@ func TestHarvestRoutes_EmptyResult(t *testing.T) {
172181func TestHarvestRoutes_NonJavaLanguage (t * testing.T ) {
173182 harvester := NewRouteHarvester (& services.RouteHarvestingConfig {}, []services.RouteHarvesterLanguage {}, 1 * time .Second )
174183 // javaExtractRoutes should not be called for non-Java languages
175- harvester .javaExtractRoutes = func (_ app.PID ) (* RouteHarvesterResult , error ) {
184+ harvester .javaExtractRoutes = func (_ context. Context , _ app.PID ) (* RouteHarvesterResult , error ) {
176185 t .Fatal ("javaExtractRoutes should not be called for non-Java languages" )
177186 return nil , nil
178187 }
@@ -187,7 +196,14 @@ func TestHarvestRoutes_NonJavaLanguage(t *testing.T) {
187196
188197func TestHarvestRoutes_MultipleTimeouts (t * testing.T ) {
189198 harvester := NewRouteHarvester (& services.RouteHarvestingConfig {}, []services.RouteHarvesterLanguage {}, 50 * time .Millisecond )
190- harvester .javaExtractRoutes = timeoutExtractRoutes
199+
200+ exited := make (chan struct {}, 3 )
201+ harvester .javaExtractRoutes = func (ctx context.Context , pid app.PID ) (* RouteHarvesterResult , error ) {
202+ defer func () {
203+ exited <- struct {}{}
204+ }()
205+ return timeoutExtractRoutes (ctx , pid )
206+ }
191207
192208 fileInfo := createTestFileInfo (svc .InstrumentableJava )
193209
@@ -202,11 +218,15 @@ func TestHarvestRoutes_MultipleTimeouts(t *testing.T) {
202218 require .ErrorAs (t , err , & harvestErr , "iteration %d should return HarvestError" , i )
203219 assert .Equal (t , "route harvesting timed out" , harvestErr .Message , "iteration %d should have timeout message" , i )
204220 }
221+
222+ require .Eventually (t , func () bool {
223+ return len (exited ) == 3
224+ }, time .Second , time .Millisecond )
205225}
206226
207227func TestHarvestNodejsRoutes_Successful (t * testing.T ) {
208228 harvester := NewRouteHarvester (& services.RouteHarvestingConfig {}, []services.RouteHarvesterLanguage {}, 1 * time .Second )
209- harvester .nodeExtractRoutes = successfulExtractRoutes
229+ harvester .nodeExtractRoutes = successfulNodeExtractRoutes
210230
211231 fileInfo := createTestFileInfo (svc .InstrumentableNodejs )
212232
@@ -220,7 +240,7 @@ func TestHarvestNodejsRoutes_Successful(t *testing.T) {
220240
221241func TestHarvestNodejsRoutes_Error (t * testing.T ) {
222242 harvester := NewRouteHarvester (& services.RouteHarvestingConfig {}, []services.RouteHarvesterLanguage {}, 1 * time .Second )
223- harvester .nodeExtractRoutes = errorExtractRoutes
243+ harvester .nodeExtractRoutes = errorNodeExtractRoutes
224244
225245 fileInfo := createTestFileInfo (svc .InstrumentableNodejs )
226246
0 commit comments