@@ -97,12 +97,14 @@ var update = flag.Bool("update", false, "if set, update test data during marker
97
97
//
98
98
// # Special files
99
99
//
100
- // There are three types of file within the test archive that are given special
100
+ // There are several types of file within the test archive that are given special
101
101
// treatment by the test runner:
102
102
// - "flags": this file is treated as a whitespace-separated list of flags
103
103
// that configure the MarkerTest instance. Supported flags:
104
104
// -min_go=go1.18 sets the minimum Go version for the test;
105
105
// -cgo requires that CGO_ENABLED is set and the cgo tool is available
106
+ // -write_sumfile=a,b,c instructs the test runner to generate go.sum files
107
+ // in these directories before running the test.
106
108
// TODO(rfindley): support flag values containing whitespace.
107
109
// - "settings.json": this file is parsed as JSON, and used as the
108
110
// session configuration (see gopls/doc/settings.md)
@@ -115,6 +117,9 @@ var update = flag.Bool("update", false, "if set, update test data during marker
115
117
// Foo were of type *Golden, the test runner would convert the identifier a
116
118
// in the call @foo(a, "b", 3) into a *Golden by collecting golden file
117
119
// data starting with "@a/".
120
+ // - proxy files: any file starting with proxy/ is treated as a Go proxy
121
+ // file. If present, these files are written to a separate temporary
122
+ // directory and GOPROXY is set to file://<proxy directory>.
118
123
//
119
124
// # Marker types
120
125
//
@@ -136,10 +141,8 @@ var update = flag.Bool("update", false, "if set, update test data during marker
136
141
// a 1:1 correspondence between observed diagnostics and diag annotations.
137
142
// The diagnostics source and kind fields are ignored, to reduce fuss.
138
143
//
139
- // The marker must accurately represent the diagnostic's range.
140
- // Use grouping parens in the location regular expression to indicate
141
- // a portion in context.
142
- // TODO(adonovan): make this less strict, like the old framework.
144
+ // The specified location must match the start position of the diagnostic,
145
+ // but end positions are ignored.
143
146
//
144
147
// TODO(adonovan): in the older marker framework, the annotation asserted
145
148
// two additional fields (source="compiler", kind="error"). Restore them?
@@ -357,10 +360,17 @@ func RunMarkerTests(t *testing.T, dir string) {
357
360
}
358
361
config .Settings ["diagnosticsDelay" ] = "10ms"
359
362
}
360
- run := & markerTestRun {
361
- test : test ,
362
- env : newEnv (t , cache , test .files , config ),
363
363
364
+ var writeGoSum []string
365
+ if test .writeGoSum != "" {
366
+ for _ , d := range strings .Split (test .writeGoSum , "," ) {
367
+ writeGoSum = append (writeGoSum , strings .TrimSpace (d ))
368
+ }
369
+ }
370
+
371
+ run := & markerTestRun {
372
+ test : test ,
373
+ env : newEnv (t , cache , test .files , test .proxyFiles , writeGoSum , config ),
364
374
locations : make (map [expect.Identifier ]protocol.Location ),
365
375
diags : make (map [protocol.Location ][]protocol.Diagnostic ),
366
376
}
@@ -397,8 +407,11 @@ func RunMarkerTests(t *testing.T, dir string) {
397
407
uri := run .env .Sandbox .Workdir .URI (path )
398
408
for _ , diag := range params .Diagnostics {
399
409
loc := protocol.Location {
400
- URI : uri ,
401
- Range : diag .Range ,
410
+ URI : uri ,
411
+ Range : protocol.Range {
412
+ Start : diag .Range .Start ,
413
+ End : diag .Range .Start , // ignore end positions
414
+ },
402
415
}
403
416
run .diags [loc ] = append (run .diags [loc ], diag )
404
417
}
@@ -546,21 +559,23 @@ var markerFuncs = map[string]markerFunc{
546
559
// See the documentation for RunMarkerTests for more information on the archive
547
560
// format.
548
561
type markerTest struct {
549
- name string // relative path to the txtar file in the testdata dir
550
- fset * token.FileSet // fileset used for parsing notes
551
- content []byte // raw test content
552
- archive * txtar.Archive // original test archive
553
- settings map [string ]interface {} // gopls settings
554
- env map [string ]string // editor environment
555
- files map [string ][]byte // data files from the archive (excluding special files)
556
- notes []* expect.Note // extracted notes from data files
557
- golden map [string ]* Golden // extracted golden content, by identifier name
562
+ name string // relative path to the txtar file in the testdata dir
563
+ fset * token.FileSet // fileset used for parsing notes
564
+ content []byte // raw test content
565
+ archive * txtar.Archive // original test archive
566
+ settings map [string ]interface {} // gopls settings
567
+ env map [string ]string // editor environment
568
+ proxyFiles map [string ][]byte // proxy content
569
+ files map [string ][]byte // data files from the archive (excluding special files)
570
+ notes []* expect.Note // extracted notes from data files
571
+ golden map [string ]* Golden // extracted golden content, by identifier name
558
572
559
573
// flags holds flags extracted from the special "flags" archive file.
560
574
flags []string
561
575
// Parsed flags values.
562
576
minGoVersion string
563
577
cgo bool
578
+ writeGoSum string // comma separated dirs to write go sum for
564
579
}
565
580
566
581
// flagSet returns the flagset used for parsing the special "flags" file in the
@@ -569,6 +584,7 @@ func (t *markerTest) flagSet() *flag.FlagSet {
569
584
flags := flag .NewFlagSet (t .name , flag .ContinueOnError )
570
585
flags .StringVar (& t .minGoVersion , "min_go" , "" , "if set, the minimum go1.X version required for this test" )
571
586
flags .BoolVar (& t .cgo , "cgo" , false , "if set, requires cgo (both the cgo tool and CGO_ENABLED=1)" )
587
+ flags .StringVar (& t .writeGoSum , "write_sumfile" , "" , "if set, write the sumfile for these directories" )
572
588
return flags
573
589
}
574
590
@@ -711,6 +727,13 @@ func loadMarkerTest(name string, content []byte) (*markerTest, error) {
711
727
}
712
728
test .golden [id ].data [name ] = file .Data
713
729
730
+ case strings .HasPrefix (file .Name , "proxy/" ):
731
+ name := file .Name [len ("proxy/" ):]
732
+ if test .proxyFiles == nil {
733
+ test .proxyFiles = make (map [string ][]byte )
734
+ }
735
+ test .proxyFiles [name ] = file .Data
736
+
714
737
default : // ordinary file content
715
738
notes , err := expect .Parse (test .fset , file .Name , file .Data )
716
739
if err != nil {
@@ -773,6 +796,8 @@ func formatTest(test *markerTest) ([]byte, error) {
773
796
default :
774
797
if _ , ok := test .files [file .Name ]; ok { // ordinary file
775
798
arch .Files = append (arch .Files , file )
799
+ } else if strings .HasPrefix (file .Name , "proxy/" ) { // proxy file
800
+ arch .Files = append (arch .Files , file )
776
801
} else if data , ok := updatedGolden [file .Name ]; ok { // golden file
777
802
arch .Files = append (arch .Files , txtar.File {Name : file .Name , Data : data })
778
803
delete (updatedGolden , file .Name )
@@ -798,16 +823,22 @@ func formatTest(test *markerTest) ([]byte, error) {
798
823
//
799
824
// TODO(rfindley): simplify and refactor the construction of testing
800
825
// environments across regtests, marker tests, and benchmarks.
801
- func newEnv (t * testing.T , cache * cache.Cache , files map [string ][]byte , config fake.EditorConfig ) * Env {
826
+ func newEnv (t * testing.T , cache * cache.Cache , files , proxyFiles map [string ][]byte , writeGoSum [] string , config fake.EditorConfig ) * Env {
802
827
sandbox , err := fake .NewSandbox (& fake.SandboxConfig {
803
- RootDir : t .TempDir (),
804
- GOPROXY : "https://proxy.golang.org" ,
805
- Files : files ,
828
+ RootDir : t .TempDir (),
829
+ Files : files ,
830
+ ProxyFiles : proxyFiles ,
806
831
})
807
832
if err != nil {
808
833
t .Fatal (err )
809
834
}
810
835
836
+ for _ , dir := range writeGoSum {
837
+ if err := sandbox .RunGoCommand (context .Background (), dir , "list" , []string {"-mod=mod" , "..." }, []string {"GOWORK=off" }, true ); err != nil {
838
+ t .Fatal (err )
839
+ }
840
+ }
841
+
811
842
// Put a debug instance in the context to prevent logging to stderr.
812
843
// See associated TODO in runner.go: we should revisit this pattern.
813
844
ctx := context .Background ()
@@ -851,7 +882,7 @@ type markerTestRun struct {
851
882
// Collected information.
852
883
// Each @diag/@suggestedfix marker eliminates an entry from diags.
853
884
locations map [expect.Identifier ]protocol.Location
854
- diags map [protocol.Location ][]protocol.Diagnostic
885
+ diags map [protocol.Location ][]protocol.Diagnostic // diagnostics by position; location end == start
855
886
}
856
887
857
888
// sprintf returns a formatted string after applying pre-processing to
@@ -1324,7 +1355,14 @@ func diagMarker(mark marker, loc protocol.Location, re *regexp.Regexp) {
1324
1355
}
1325
1356
}
1326
1357
1358
+ // removeDiagnostic looks for a diagnostic matching loc at the given position.
1359
+ //
1360
+ // If found, it returns (diag, true), and eliminates the matched diagnostic
1361
+ // from the unmatched set.
1362
+ //
1363
+ // If not found, it returns (protocol.Diagnostic{}, false).
1327
1364
func removeDiagnostic (mark marker , loc protocol.Location , re * regexp.Regexp ) (protocol.Diagnostic , bool ) {
1365
+ loc .Range .End = loc .Range .Start // diagnostics ignore end position.
1328
1366
diags := mark .run .diags [loc ]
1329
1367
for i , diag := range diags {
1330
1368
if re .MatchString (diag .Message ) {
@@ -1444,6 +1482,7 @@ func codeActionErrMarker(mark marker, actionKind string, start, end protocol.Loc
1444
1482
// the expectation of a diagnostic, but then it applies the first code
1445
1483
// action of the specified kind suggested by the matched diagnostic.
1446
1484
func suggestedfixMarker (mark marker , loc protocol.Location , re * regexp.Regexp , actionKind string , golden * Golden ) {
1485
+ loc .Range .End = loc .Range .Start // diagnostics ignore end position.
1447
1486
// Find and remove the matching diagnostic.
1448
1487
diag , ok := removeDiagnostic (mark , loc , re )
1449
1488
if ! ok {
0 commit comments