github.com/AndrienkoAleksandr/go@v0.0.19/src/go/build/read_test.go (about) 1 // Copyright 2012 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package build 6 7 import ( 8 "fmt" 9 "go/token" 10 "io" 11 "strings" 12 "testing" 13 ) 14 15 const quote = "`" 16 17 type readTest struct { 18 // Test input contains ℙ where readGoInfo should stop. 19 in string 20 err string 21 } 22 23 var readGoInfoTests = []readTest{ 24 { 25 `package p`, 26 "", 27 }, 28 { 29 `package p; import "x"`, 30 "", 31 }, 32 { 33 `package p; import . "x"`, 34 "", 35 }, 36 { 37 `package p; import "x";ℙvar x = 1`, 38 "", 39 }, 40 { 41 `package p 42 43 // comment 44 45 import "x" 46 import _ "x" 47 import a "x" 48 49 /* comment */ 50 51 import ( 52 "x" /* comment */ 53 _ "x" 54 a "x" // comment 55 ` + quote + `x` + quote + ` 56 _ /*comment*/ ` + quote + `x` + quote + ` 57 a ` + quote + `x` + quote + ` 58 ) 59 import ( 60 ) 61 import () 62 import()import()import() 63 import();import();import() 64 65 ℙvar x = 1 66 `, 67 "", 68 }, 69 { 70 "\ufeff𝔻" + `package p; import "x";ℙvar x = 1`, 71 "", 72 }, 73 } 74 75 var readCommentsTests = []readTest{ 76 { 77 `ℙpackage p`, 78 "", 79 }, 80 { 81 `ℙpackage p; import "x"`, 82 "", 83 }, 84 { 85 `ℙpackage p; import . "x"`, 86 "", 87 }, 88 { 89 "\ufeff𝔻" + `ℙpackage p; import . "x"`, 90 "", 91 }, 92 { 93 `// foo 94 95 /* bar */ 96 97 /* quux */ // baz 98 99 /*/ zot */ 100 101 // asdf 102 ℙHello, world`, 103 "", 104 }, 105 { 106 "\ufeff𝔻" + `// foo 107 108 /* bar */ 109 110 /* quux */ // baz 111 112 /*/ zot */ 113 114 // asdf 115 ℙHello, world`, 116 "", 117 }, 118 } 119 120 func testRead(t *testing.T, tests []readTest, read func(io.Reader) ([]byte, error)) { 121 for i, tt := range tests { 122 beforeP, afterP, _ := strings.Cut(tt.in, "ℙ") 123 in := beforeP + afterP 124 testOut := beforeP 125 126 if beforeD, afterD, ok := strings.Cut(beforeP, "𝔻"); ok { 127 in = beforeD + afterD + afterP 128 testOut = afterD 129 } 130 131 r := strings.NewReader(in) 132 buf, err := read(r) 133 if err != nil { 134 if tt.err == "" { 135 t.Errorf("#%d: err=%q, expected success (%q)", i, err, string(buf)) 136 } else if !strings.Contains(err.Error(), tt.err) { 137 t.Errorf("#%d: err=%q, expected %q", i, err, tt.err) 138 } 139 continue 140 } 141 if tt.err != "" { 142 t.Errorf("#%d: success, expected %q", i, tt.err) 143 continue 144 } 145 146 out := string(buf) 147 if out != testOut { 148 t.Errorf("#%d: wrong output:\nhave %q\nwant %q\n", i, out, testOut) 149 } 150 } 151 } 152 153 func TestReadGoInfo(t *testing.T) { 154 testRead(t, readGoInfoTests, func(r io.Reader) ([]byte, error) { 155 var info fileInfo 156 err := readGoInfo(r, &info) 157 return info.header, err 158 }) 159 } 160 161 func TestReadComments(t *testing.T) { 162 testRead(t, readCommentsTests, readComments) 163 } 164 165 var readFailuresTests = []readTest{ 166 { 167 `package`, 168 "syntax error", 169 }, 170 { 171 "package p\n\x00\nimport `math`\n", 172 "unexpected NUL in input", 173 }, 174 { 175 `package p; import`, 176 "syntax error", 177 }, 178 { 179 `package p; import "`, 180 "syntax error", 181 }, 182 { 183 "package p; import ` \n\n", 184 "syntax error", 185 }, 186 { 187 `package p; import "x`, 188 "syntax error", 189 }, 190 { 191 `package p; import _`, 192 "syntax error", 193 }, 194 { 195 `package p; import _ "`, 196 "syntax error", 197 }, 198 { 199 `package p; import _ "x`, 200 "syntax error", 201 }, 202 { 203 `package p; import .`, 204 "syntax error", 205 }, 206 { 207 `package p; import . "`, 208 "syntax error", 209 }, 210 { 211 `package p; import . "x`, 212 "syntax error", 213 }, 214 { 215 `package p; import (`, 216 "syntax error", 217 }, 218 { 219 `package p; import ("`, 220 "syntax error", 221 }, 222 { 223 `package p; import ("x`, 224 "syntax error", 225 }, 226 { 227 `package p; import ("x"`, 228 "syntax error", 229 }, 230 } 231 232 func TestReadFailuresIgnored(t *testing.T) { 233 // Syntax errors should not be reported (false arg to readImports). 234 // Instead, entire file should be the output and no error. 235 // Convert tests not to return syntax errors. 236 tests := make([]readTest, len(readFailuresTests)) 237 copy(tests, readFailuresTests) 238 for i := range tests { 239 tt := &tests[i] 240 if !strings.Contains(tt.err, "NUL") { 241 tt.err = "" 242 } 243 } 244 testRead(t, tests, func(r io.Reader) ([]byte, error) { 245 var info fileInfo 246 err := readGoInfo(r, &info) 247 return info.header, err 248 }) 249 } 250 251 var readEmbedTests = []struct { 252 in, out string 253 }{ 254 { 255 "package p\n", 256 "", 257 }, 258 { 259 "package p\nimport \"embed\"\nvar i int\n//go:embed x y z\nvar files embed.FS", 260 `test:4:12:x 261 test:4:14:y 262 test:4:16:z`, 263 }, 264 { 265 "package p\nimport \"embed\"\nvar i int\n//go:embed x \"\\x79\" `z`\nvar files embed.FS", 266 `test:4:12:x 267 test:4:14:y 268 test:4:21:z`, 269 }, 270 { 271 "package p\nimport \"embed\"\nvar i int\n//go:embed x y\n//go:embed z\nvar files embed.FS", 272 `test:4:12:x 273 test:4:14:y 274 test:5:12:z`, 275 }, 276 { 277 "package p\nimport \"embed\"\nvar i int\n\t //go:embed x y\n\t //go:embed z\n\t var files embed.FS", 278 `test:4:14:x 279 test:4:16:y 280 test:5:14:z`, 281 }, 282 { 283 "package p\nimport \"embed\"\n//go:embed x y z\nvar files embed.FS", 284 `test:3:12:x 285 test:3:14:y 286 test:3:16:z`, 287 }, 288 { 289 "\ufeffpackage p\nimport \"embed\"\n//go:embed x y z\nvar files embed.FS", 290 `test:3:12:x 291 test:3:14:y 292 test:3:16:z`, 293 }, 294 { 295 "package p\nimport \"embed\"\nvar s = \"/*\"\n//go:embed x\nvar files embed.FS", 296 `test:4:12:x`, 297 }, 298 { 299 `package p 300 import "embed" 301 var s = "\"\\\\" 302 //go:embed x 303 var files embed.FS`, 304 `test:4:15:x`, 305 }, 306 { 307 "package p\nimport \"embed\"\nvar s = `/*`\n//go:embed x\nvar files embed.FS", 308 `test:4:12:x`, 309 }, 310 { 311 "package p\nimport \"embed\"\nvar s = z/ *y\n//go:embed pointer\nvar pointer embed.FS", 312 "test:4:12:pointer", 313 }, 314 { 315 "package p\n//go:embed x y z\n", // no import, no scan 316 "", 317 }, 318 { 319 "package p\n//go:embed x y z\nvar files embed.FS", // no import, no scan 320 "", 321 }, 322 { 323 "\ufeffpackage p\n//go:embed x y z\nvar files embed.FS", // no import, no scan 324 "", 325 }, 326 } 327 328 func TestReadEmbed(t *testing.T) { 329 fset := token.NewFileSet() 330 for i, tt := range readEmbedTests { 331 info := fileInfo{ 332 name: "test", 333 fset: fset, 334 } 335 err := readGoInfo(strings.NewReader(tt.in), &info) 336 if err != nil { 337 t.Errorf("#%d: %v", i, err) 338 continue 339 } 340 b := &strings.Builder{} 341 sep := "" 342 for _, emb := range info.embeds { 343 fmt.Fprintf(b, "%s%v:%s", sep, emb.pos, emb.pattern) 344 sep = "\n" 345 } 346 got := b.String() 347 want := strings.Join(strings.Fields(tt.out), "\n") 348 if got != want { 349 t.Errorf("#%d: embeds:\n%s\nwant:\n%s", i, got, want) 350 } 351 } 352 }