@@ -5,21 +5,27 @@ import (
5
5
"context"
6
6
"encoding/json"
7
7
"fmt"
8
+ "io"
8
9
"net"
9
10
"os"
10
11
"path/filepath"
12
+ "slices"
13
+ "sort"
14
+ "strings"
11
15
"testing"
12
16
"time"
13
17
14
18
"github.com/sourcegraph/jsonrpc2"
15
19
16
- "github.com/styrainc/regal/internal/lsp/cache"
17
20
"github.com/styrainc/regal/internal/lsp/types"
18
21
)
19
22
20
23
const mainRegoFileName = "/main.rego"
21
24
22
- const defaultTimeout = 3 * time .Second
25
+ // defaultTimeout is set based on the investigation done as part of
26
+ // https://github.com/StyraInc/regal/issues/931. 20 seconds is 10x the
27
+ // maximum time observed for an operation to complete.
28
+ const defaultTimeout = 20 * time .Second
23
29
24
30
const defaultBufferedChannelSize = 5
25
31
@@ -87,7 +93,7 @@ allow = true
87
93
defer cancel ()
88
94
89
95
ls := NewLanguageServer (& LanguageServerOptions {
90
- ErrorLog : os . Stderr ,
96
+ ErrorLog : newTestLogger ( t ) ,
91
97
})
92
98
go ls .StartDiagnosticsWorker (ctx )
93
99
go ls .StartConfigWorker (ctx )
@@ -331,7 +337,7 @@ ignore:
331
337
defer cancel ()
332
338
333
339
ls := NewLanguageServer (& LanguageServerOptions {
334
- ErrorLog : os . Stderr ,
340
+ ErrorLog : newTestLogger ( t ) ,
335
341
})
336
342
go ls .StartDiagnosticsWorker (ctx )
337
343
go ls .StartConfigWorker (ctx )
@@ -340,30 +346,29 @@ ignore:
340
346
adminsFileMessages := make (chan types.FileDiagnostics , defaultBufferedChannelSize )
341
347
ignoredFileMessages := make (chan types.FileDiagnostics , defaultBufferedChannelSize )
342
348
clientHandler := func (_ context.Context , _ * jsonrpc2.Conn , req * jsonrpc2.Request ) (result any , err error ) {
343
- if req .Method == "textDocument/publishDiagnostics" {
344
- var requestData types.FileDiagnostics
345
-
346
- err = json .Unmarshal (* req .Params , & requestData )
347
- if err != nil {
348
- t .Fatalf ("failed to unmarshal diagnostics: %s" , err )
349
- }
349
+ if req .Method != "textDocument/publishDiagnostics" {
350
+ t .Log ("unexpected request method:" , req .Method )
350
351
351
- if requestData .URI == authzRegoURI {
352
- authzFileMessages <- requestData
353
- }
352
+ return struct {}{}, nil
353
+ }
354
354
355
- if requestData .URI == adminsRegoURI {
356
- adminsFileMessages <- requestData
357
- }
355
+ var requestData types.FileDiagnostics
358
356
359
- if requestData .URI == ignoredRegoURI {
360
- ignoredFileMessages <- requestData
361
- }
362
-
363
- return struct {}{}, nil
357
+ err = json .Unmarshal (* req .Params , & requestData )
358
+ if err != nil {
359
+ t .Fatalf ("failed to unmarshal diagnostics: %s" , err )
364
360
}
365
361
366
- t .Fatalf ("unexpected request: %v" , req )
362
+ switch requestData .URI {
363
+ case authzRegoURI :
364
+ authzFileMessages <- requestData
365
+ case adminsRegoURI :
366
+ adminsFileMessages <- requestData
367
+ case ignoredRegoURI :
368
+ ignoredFileMessages <- requestData
369
+ default :
370
+ t .Logf ("unexpected diagnostics for file: %s" , requestData .URI )
371
+ }
367
372
368
373
return struct {}{}, nil
369
374
}
@@ -464,7 +469,7 @@ allow if input.user in admins.users
464
469
case diags := <- authzFileMessages :
465
470
success = testRequestDataCodes (t , diags , authzRegoURI , []string {})
466
471
case <- timeout .C :
467
- t .Fatalf ("timed out waiting for file diagnostics to be sent" )
472
+ t .Fatalf ("timed out waiting for authz.rego diagnostics to be sent" )
468
473
}
469
474
470
475
if success {
@@ -483,7 +488,7 @@ allow if input.user in admins.users
483
488
case requestData := <- adminsFileMessages :
484
489
success = testRequestDataCodes (t , requestData , adminsRegoURI , []string {"use-assignment-operator" })
485
490
case <- timeout .C :
486
- t .Fatalf ("timed out waiting for file diagnostics to be sent" )
491
+ t .Fatalf ("timed out waiting for admins.rego diagnostics to be sent" )
487
492
}
488
493
489
494
if success {
@@ -496,9 +501,9 @@ allow if input.user in admins.users
496
501
func TestProcessBuiltinUpdateExitsOnMissingFile (t * testing.T ) {
497
502
t .Parallel ()
498
503
499
- ls := LanguageServer {
500
- cache : cache . NewCache ( ),
501
- }
504
+ ls := NewLanguageServer ( & LanguageServerOptions {
505
+ ErrorLog : newTestLogger ( t ),
506
+ })
502
507
503
508
err := ls .processHoverContentUpdate (context .Background (), "file://missing.rego" , "foo" )
504
509
if err != nil {
@@ -571,7 +576,7 @@ allow := true
571
576
defer cancel ()
572
577
573
578
ls := NewLanguageServer (& LanguageServerOptions {
574
- ErrorLog : os . Stderr ,
579
+ ErrorLog : newTestLogger ( t ) ,
575
580
})
576
581
go ls .StartDiagnosticsWorker (ctx )
577
582
go ls .StartConfigWorker (ctx )
@@ -683,31 +688,20 @@ func testRequestDataCodes(t *testing.T, requestData types.FileDiagnostics, fileU
683
688
return false
684
689
}
685
690
686
- if len ( requestData . Items ) != len ( codes ) {
687
- t . Log ( "expected" , len ( codes ), "diagnostics, got" , len (requestData .Items ))
688
-
689
- return false
691
+ // Extract the codes from requestData.Items
692
+ requestCodes := make ([] string , len (requestData .Items ))
693
+ for i , item := range requestData . Items {
694
+ requestCodes [ i ] = item . Code
690
695
}
691
696
692
- for _ , v := range codes {
693
- found := false
694
- foundItems := make ([]string , 0 , len (requestData .Items ))
695
-
696
- for _ , i := range requestData .Items {
697
- foundItems = append (foundItems , i .Code )
697
+ // Sort both slices
698
+ sort .Strings (requestCodes )
699
+ sort .Strings (codes )
698
700
699
- if i . Code == v {
700
- found = true
701
+ if ! slices . Equal ( requestCodes , codes ) {
702
+ t . Logf ( "expected items: %v, got: %v" , codes , requestCodes )
701
703
702
- break
703
- }
704
- }
705
-
706
- if ! found {
707
- t .Log ("expected diagnostic" , v , "not found in" , foundItems )
708
-
709
- return false
710
- }
704
+ return false
711
705
}
712
706
713
707
return true
@@ -740,3 +734,20 @@ func createConnections(
740
734
741
735
return connServer , connClient , cleanup
742
736
}
737
+
738
+ // NewTestLogger returns an io.Writer that logs to the given testing.T.
739
+ func newTestLogger (t * testing.T ) io.Writer {
740
+ t .Helper ()
741
+
742
+ return & testLogger {t : t }
743
+ }
744
+
745
+ type testLogger struct {
746
+ t * testing.T
747
+ }
748
+
749
+ func (tl * testLogger ) Write (p []byte ) (n int , err error ) {
750
+ tl .t .Log (strings .TrimSpace (string (p )))
751
+
752
+ return len (p ), nil
753
+ }
0 commit comments