@@ -41,6 +41,7 @@ func newBatchTestService() *Service {
4141 Service : service.Service {
4242 Logger : slog .New (slog .NewTextHandler (& bytes.Buffer {}, nil )),
4343 },
44+ handlers : cloneDispatchTable (jsonrpcHandlers ),
4445 }
4546}
4647
@@ -128,7 +129,7 @@ func TestJSONRPCBatchRejectsMoreThanMaximumBeforeDispatch(t *testing.T) {
128129 s := newBatchTestService ()
129130 var calls atomic.Int32
130131 const method = "test_batch_cap"
131- withTestRPCHandler (t , method , func (_ * Service , _ * http.Request , _ RPCRequest ) (any , error ) {
132+ withTestRPCHandler (t , s , method , func (_ * Service , _ * http.Request , _ RPCRequest ) (any , error ) {
132133 calls .Add (1 )
133134 return true , nil
134135 })
@@ -312,7 +313,7 @@ func TestJSONRPCBatchReplacesResponsesAtCumulativeResponseBudget(t *testing.T) {
312313 var calls atomic.Int32
313314 const method = "test_large_batch_result"
314315 largeResult := strings .Repeat ("x" , testLargeResultSize )
315- withTestRPCHandler (t , method , func (_ * Service , _ * http.Request , _ RPCRequest ) (any , error ) {
316+ withTestRPCHandler (t , s , method , func (_ * Service , _ * http.Request , _ RPCRequest ) (any , error ) {
316317 calls .Add (1 )
317318 return largeResult , nil
318319 })
@@ -351,7 +352,7 @@ func TestJSONRPCBatchStopsBetweenEntriesWhenContextIsCanceled(t *testing.T) {
351352 s .Logger = slog .New (slog .NewJSONHandler (& logs , & slog.HandlerOptions {Level : slog .LevelDebug }))
352353 ctx , cancel := context .WithCancel (context .Background ())
353354 const method = "test_cancel_batch"
354- withTestRPCHandler (t , method , func (_ * Service , _ * http.Request , _ RPCRequest ) (any , error ) {
355+ withTestRPCHandler (t , s , method , func (_ * Service , _ * http.Request , _ RPCRequest ) (any , error ) {
355356 calls .Add (1 )
356357 cancel ()
357358 return true , nil
@@ -387,7 +388,7 @@ func TestJSONRPCBatchStopsSilentlyWhenRepositoryCallIsCanceled(t *testing.T) {
387388 s .Logger = slog .New (slog .NewJSONHandler (& logs , & slog.HandlerOptions {Level : slog .LevelDebug }))
388389 ctx , cancel := context .WithCancel (context .Background ())
389390 const method = "test_repository_cancel_batch"
390- withTestRPCHandler (t , method , func (s * Service , _ * http.Request , _ RPCRequest ) (any , error ) {
391+ withTestRPCHandler (t , s , method , func (s * Service , _ * http.Request , _ RPCRequest ) (any , error ) {
391392 calls .Add (1 )
392393 cancel ()
393394 return nil , s .repositoryError (ctx , "Unable to retrieve test data from repository" ,
@@ -419,7 +420,7 @@ func TestJSONRPCBatchReturnsErrorsForIDDRequestsAfterDeadline(t *testing.T) {
419420 s := newBatchTestService ()
420421 var calls atomic.Int32
421422 const method = "test_deadline_batch"
422- withTestRPCHandler (t , method , func (_ * Service , _ * http.Request , _ RPCRequest ) (any , error ) {
423+ withTestRPCHandler (t , s , method , func (_ * Service , _ * http.Request , _ RPCRequest ) (any , error ) {
423424 calls .Add (1 )
424425 return true , nil
425426 })
@@ -462,7 +463,7 @@ func TestJSONRPCSingleRequestReturnsTimeoutWhenItsContextExpires(t *testing.T) {
462463 var logs bytes.Buffer
463464 s .Logger = slog .New (slog .NewJSONHandler (& logs , & slog.HandlerOptions {Level : slog .LevelDebug }))
464465 const method = "test_single_request_timeout"
465- withTestRPCHandler (t , method , func (s * Service , r * http.Request , _ RPCRequest ) (any , error ) {
466+ withTestRPCHandler (t , s , method , func (s * Service , r * http.Request , _ RPCRequest ) (any , error ) {
466467 <- r .Context ().Done ()
467468 return nil , s .repositoryError (r .Context (), "Unable to retrieve test data from repository" ,
468469 fmt .Errorf ("repository query failed: %w" , r .Context ().Err ()))
@@ -482,7 +483,7 @@ func TestJSONRPCUpstreamDeadlineRemainsInternalError(t *testing.T) {
482483 var logs bytes.Buffer
483484 s .Logger = slog .New (slog .NewJSONHandler (& logs , & slog.HandlerOptions {Level : slog .LevelDebug }))
484485 const method = "test_upstream_deadline"
485- withTestRPCHandler (t , method , func (s * Service , r * http.Request , _ RPCRequest ) (any , error ) {
486+ withTestRPCHandler (t , s , method , func (s * Service , r * http.Request , _ RPCRequest ) (any , error ) {
486487 return nil , s .repositoryError (r .Context (), "Unable to retrieve test data from repository" ,
487488 fmt .Errorf ("upstream deadline: %w" , context .DeadlineExceeded ))
488489 })
@@ -500,10 +501,10 @@ func TestJSONRPCBatchRecoversPanicPerEntry(t *testing.T) {
500501 s .Logger = slog .New (slog .NewJSONHandler (& logs , & slog.HandlerOptions {Level : slog .LevelDebug }))
501502 panicMethod := strings .Repeat ("p" , MAX_LOGGED_METHOD_LEN + 32 )
502503 const okMethod = "test_after_panic_batch"
503- withTestRPCHandler (t , panicMethod , func (_ * Service , _ * http.Request , _ RPCRequest ) (any , error ) {
504+ withTestRPCHandler (t , s , panicMethod , func (_ * Service , _ * http.Request , _ RPCRequest ) (any , error ) {
504505 panic ("test panic" )
505506 })
506- withTestRPCHandler (t , okMethod , func (_ * Service , _ * http.Request , _ RPCRequest ) (any , error ) {
507+ withTestRPCHandler (t , s , okMethod , func (_ * Service , _ * http.Request , _ RPCRequest ) (any , error ) {
507508 return "ok" , nil
508509 })
509510
@@ -530,7 +531,7 @@ func TestJSONRPCBatchRecoversPanicPerEntry(t *testing.T) {
530531func TestJSONRPCDoesNotRecoverAbortHandler (t * testing.T ) {
531532 s := newBatchTestService ()
532533 const method = "test_abort_handler"
533- withTestRPCHandler (t , method , func (_ * Service , _ * http.Request , _ RPCRequest ) (any , error ) {
534+ withTestRPCHandler (t , s , method , func (_ * Service , _ * http.Request , _ RPCRequest ) (any , error ) {
534535 panic (http .ErrAbortHandler )
535536 })
536537
@@ -549,7 +550,7 @@ func TestJSONRPCBatchUsesOneAdmissionPermit(t *testing.T) {
549550 }
550551 var nestedAcquisitions atomic.Int32
551552 const method = "test_batch_admission"
552- withTestRPCHandler (t , method , func (s * Service , _ * http.Request , _ RPCRequest ) (any , error ) {
553+ withTestRPCHandler (t , s , method , func (s * Service , _ * http.Request , _ RPCRequest ) (any , error ) {
553554 if s .admission .TryAcquire () {
554555 nestedAcquisitions .Add (1 )
555556 s .admission .Release ()
@@ -631,15 +632,31 @@ func TestJSONRPCBatchMethodLoggingIsTruncated(t *testing.T) {
631632 require .True (t , found )
632633}
633634
634- func withTestRPCHandler (t * testing.T , method string , handler rpcHandler ) {
635+ func withTestRPCHandler (t * testing.T , service * Service , method string , handler rpcHandler ) {
635636 t .Helper ()
636- previous , existed := jsonrpcHandlers [method ]
637- jsonrpcHandlers [method ] = handler
637+ previous , existed := service . handlers [method ]
638+ service . handlers [method ] = handler
638639 t .Cleanup (func () {
639640 if existed {
640- jsonrpcHandlers [method ] = previous
641+ service . handlers [method ] = previous
641642 } else {
642- delete (jsonrpcHandlers , method )
643+ delete (service . handlers , method )
643644 }
644645 })
645646}
647+
648+ func TestRPCHandlerOverridesAreServiceLocal (t * testing.T ) {
649+ first := newBatchTestService ()
650+ second := newBatchTestService ()
651+ const method = "test_service_local_handler"
652+ withTestRPCHandler (t , first , method , func (_ * Service , _ * http.Request , _ RPCRequest ) (any , error ) {
653+ return true , nil
654+ })
655+
656+ _ , firstHasHandler := first .handlers [method ]
657+ _ , secondHasHandler := second .handlers [method ]
658+ _ , globalHasHandler := jsonrpcHandlers [method ]
659+ require .True (t , firstHasHandler )
660+ require .False (t , secondHasHandler )
661+ require .False (t , globalHasHandler )
662+ }
0 commit comments