@@ -37,6 +37,7 @@ import (
37
37
"internal/testenv"
38
38
"os"
39
39
"path/filepath"
40
+ "reflect"
40
41
"regexp"
41
42
"strconv"
42
43
"strings"
@@ -50,12 +51,14 @@ var (
50
51
verifyErrors = flag .Bool ("verify" , false , "verify errors (rather than list them) in TestManual" )
51
52
)
52
53
53
- func parseFiles (t * testing.T , filenames []string , mode syntax.Mode ) ([]* syntax.File , []error ) {
54
+ func parseFiles (t * testing.T , filenames []string , srcs [][] byte , mode syntax.Mode ) ([]* syntax.File , []error ) {
54
55
var files []* syntax.File
55
56
var errlist []error
56
57
errh := func (err error ) { errlist = append (errlist , err ) }
57
- for _ , filename := range filenames {
58
- file , err := syntax .ParseFile (filename , errh , nil , mode )
58
+ for i , filename := range filenames {
59
+ base := syntax .NewFileBase (filename )
60
+ r := bytes .NewReader (srcs [i ])
61
+ file , err := syntax .Parse (base , r , errh , nil , mode )
59
62
if file == nil {
60
63
t .Fatalf ("%s: %s" , filename , err )
61
64
}
@@ -83,30 +86,10 @@ func absDiff(x, y uint) uint {
83
86
return x - y
84
87
}
85
88
86
- // Note: parseFlags is identical to the version in go/types which is
87
- // why it has a src argument even though here it is always nil.
88
-
89
- // parseFlags parses flags from the first line of the given source
90
- // (from src if present, or by reading from the file) if the line
91
- // starts with "//" (line comment) followed by "-" (possibly with
92
- // spaces between). Otherwise the line is ignored.
93
- func parseFlags (filename string , src []byte , flags * flag.FlagSet ) error {
94
- // If there is no src, read from the file.
95
- const maxLen = 256
96
- if len (src ) == 0 {
97
- f , err := os .Open (filename )
98
- if err != nil {
99
- return err
100
- }
101
-
102
- var buf [maxLen ]byte
103
- n , err := f .Read (buf [:])
104
- if err != nil {
105
- return err
106
- }
107
- src = buf [:n ]
108
- }
109
-
89
+ // parseFlags parses flags from the first line of the given source if the line
90
+ // starts with "//" (line comment) followed by "-" (possibly with spaces
91
+ // between). Otherwise the line is ignored.
92
+ func parseFlags (src []byte , flags * flag.FlagSet ) error {
110
93
// we must have a line comment that starts with a "-"
111
94
const prefix = "//"
112
95
if ! bytes .HasPrefix (src , []byte (prefix )) {
@@ -117,14 +100,24 @@ func parseFlags(filename string, src []byte, flags *flag.FlagSet) error {
117
100
return nil // comment doesn't start with a "-"
118
101
}
119
102
end := bytes .Index (src , []byte ("\n " ))
103
+ const maxLen = 256
120
104
if end < 0 || end > maxLen {
121
105
return fmt .Errorf ("flags comment line too long" )
122
106
}
123
107
124
108
return flags .Parse (strings .Fields (string (src [:end ])))
125
109
}
126
110
127
- func testFiles (t * testing.T , filenames []string , colDelta uint , manual bool ) {
111
+ // testFiles type-checks the package consisting of the given files, and
112
+ // compares the resulting errors with the ERROR annotations in the source.
113
+ //
114
+ // The srcs slice contains the file content for the files named in the
115
+ // filenames slice. The colDelta parameter specifies the tolerance for position
116
+ // mismatch when comparing errors. The manual parameter specifies whether this
117
+ // is a 'manual' test.
118
+ //
119
+ // If provided, opts may be used to mutate the Config before type-checking.
120
+ func testFiles (t * testing.T , filenames []string , srcs [][]byte , colDelta uint , manual bool , opts ... func (* Config )) {
128
121
if len (filenames ) == 0 {
129
122
t .Fatal ("no source files" )
130
123
}
@@ -133,11 +126,11 @@ func testFiles(t *testing.T, filenames []string, colDelta uint, manual bool) {
133
126
flags := flag .NewFlagSet ("" , flag .PanicOnError )
134
127
flags .StringVar (& conf .GoVersion , "lang" , "" , "" )
135
128
flags .BoolVar (& conf .FakeImportC , "fakeImportC" , false , "" )
136
- if err := parseFlags (filenames [0 ], nil , flags ); err != nil {
129
+ if err := parseFlags (srcs [0 ], flags ); err != nil {
137
130
t .Fatal (err )
138
131
}
139
132
140
- files , errlist := parseFiles (t , filenames , 0 )
133
+ files , errlist := parseFiles (t , filenames , srcs , 0 )
141
134
142
135
pkgName := "<no package>"
143
136
if len (files ) > 0 {
@@ -165,6 +158,11 @@ func testFiles(t *testing.T, filenames []string, colDelta uint, manual bool) {
165
158
}
166
159
errlist = append (errlist , err )
167
160
}
161
+
162
+ for _ , opt := range opts {
163
+ opt (& conf )
164
+ }
165
+
168
166
conf .Check (pkgName , files , nil )
169
167
170
168
if listErrors {
@@ -173,16 +171,10 @@ func testFiles(t *testing.T, filenames []string, colDelta uint, manual bool) {
173
171
174
172
// collect expected errors
175
173
errmap := make (map [string ]map [uint ][]syntax.Error )
176
- for _ , filename := range filenames {
177
- f , err := os .Open (filename )
178
- if err != nil {
179
- t .Error (err )
180
- continue
181
- }
182
- if m := syntax .CommentMap (f , regexp .MustCompile ("^ ERRORx? " )); len (m ) > 0 {
174
+ for i , filename := range filenames {
175
+ if m := syntax .CommentMap (bytes .NewReader (srcs [i ]), regexp .MustCompile ("^ ERRORx? " )); len (m ) > 0 {
183
176
errmap [filename ] = m
184
177
}
185
- f .Close ()
186
178
}
187
179
188
180
// match against found errors
@@ -280,6 +272,13 @@ func testFiles(t *testing.T, filenames []string, colDelta uint, manual bool) {
280
272
}
281
273
}
282
274
275
+ // boolFieldAddr(conf, name) returns the address of the boolean field conf.<name>.
276
+ // For accessing unexported fields.
277
+ func boolFieldAddr (conf * Config , name string ) * bool {
278
+ v := reflect .Indirect (reflect .ValueOf (conf ))
279
+ return (* bool )(v .FieldByName (name ).Addr ().UnsafePointer ())
280
+ }
281
+
283
282
// TestManual is for manual testing of a package - either provided
284
283
// as a list of filenames belonging to the package, or a directory
285
284
// name containing the package files - after the test arguments
@@ -314,7 +313,7 @@ func TestManual(t *testing.T) {
314
313
}
315
314
testDir (t , filenames [0 ], 0 , true )
316
315
} else {
317
- testFiles (t , filenames , 0 , true )
316
+ testPkg (t , filenames , 0 , true )
318
317
}
319
318
}
320
319
@@ -351,7 +350,7 @@ func testDirFiles(t *testing.T, dir string, colDelta uint, manual bool) {
351
350
testDir (t , path , colDelta , manual )
352
351
} else {
353
352
t .Run (filepath .Base (path ), func (t * testing.T ) {
354
- testFiles (t , []string {path }, colDelta , manual )
353
+ testPkg (t , []string {path }, colDelta , manual )
355
354
})
356
355
}
357
356
}
@@ -370,6 +369,18 @@ func testDir(t *testing.T, dir string, colDelta uint, manual bool) {
370
369
}
371
370
372
371
t .Run (filepath .Base (dir ), func (t * testing.T ) {
373
- testFiles (t , filenames , colDelta , manual )
372
+ testPkg (t , filenames , colDelta , manual )
374
373
})
375
374
}
375
+
376
+ func testPkg (t * testing.T , filenames []string , colDelta uint , manual bool ) {
377
+ srcs := make ([][]byte , len (filenames ))
378
+ for i , filename := range filenames {
379
+ src , err := os .ReadFile (filename )
380
+ if err != nil {
381
+ t .Fatalf ("could not read %s: %v" , filename , err )
382
+ }
383
+ srcs [i ] = src
384
+ }
385
+ testFiles (t , filenames , srcs , colDelta , manual )
386
+ }
0 commit comments