...

Source file src/go/build/read_test.go

Documentation: go/build

		 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  		var in, testOut string
	 123  		j := strings.Index(tt.in, "ℙ")
	 124  		if j < 0 {
	 125  			in = tt.in
	 126  			testOut = tt.in
	 127  		} else {
	 128  			in = tt.in[:j] + tt.in[j+len("ℙ"):]
	 129  			testOut = tt.in[:j]
	 130  		}
	 131  		d := strings.Index(tt.in, "𝔻")
	 132  		if d >= 0 {
	 133  			in = in[:d] + in[d+len("𝔻"):]
	 134  			testOut = testOut[d+len("𝔻"):]
	 135  		}
	 136  		r := strings.NewReader(in)
	 137  		buf, err := read(r)
	 138  		if err != nil {
	 139  			if tt.err == "" {
	 140  				t.Errorf("#%d: err=%q, expected success (%q)", i, err, string(buf))
	 141  			} else if !strings.Contains(err.Error(), tt.err) {
	 142  				t.Errorf("#%d: err=%q, expected %q", i, err, tt.err)
	 143  			}
	 144  			continue
	 145  		}
	 146  		if tt.err != "" {
	 147  			t.Errorf("#%d: success, expected %q", i, tt.err)
	 148  			continue
	 149  		}
	 150  
	 151  		out := string(buf)
	 152  		if out != testOut {
	 153  			t.Errorf("#%d: wrong output:\nhave %q\nwant %q\n", i, out, testOut)
	 154  		}
	 155  	}
	 156  }
	 157  
	 158  func TestReadGoInfo(t *testing.T) {
	 159  	testRead(t, readGoInfoTests, func(r io.Reader) ([]byte, error) {
	 160  		var info fileInfo
	 161  		err := readGoInfo(r, &info)
	 162  		return info.header, err
	 163  	})
	 164  }
	 165  
	 166  func TestReadComments(t *testing.T) {
	 167  	testRead(t, readCommentsTests, readComments)
	 168  }
	 169  
	 170  var readFailuresTests = []readTest{
	 171  	{
	 172  		`package`,
	 173  		"syntax error",
	 174  	},
	 175  	{
	 176  		"package p\n\x00\nimport `math`\n",
	 177  		"unexpected NUL in input",
	 178  	},
	 179  	{
	 180  		`package p; import`,
	 181  		"syntax error",
	 182  	},
	 183  	{
	 184  		`package p; import "`,
	 185  		"syntax error",
	 186  	},
	 187  	{
	 188  		"package p; import ` \n\n",
	 189  		"syntax error",
	 190  	},
	 191  	{
	 192  		`package p; import "x`,
	 193  		"syntax error",
	 194  	},
	 195  	{
	 196  		`package p; import _`,
	 197  		"syntax error",
	 198  	},
	 199  	{
	 200  		`package p; import _ "`,
	 201  		"syntax error",
	 202  	},
	 203  	{
	 204  		`package p; import _ "x`,
	 205  		"syntax error",
	 206  	},
	 207  	{
	 208  		`package p; import .`,
	 209  		"syntax error",
	 210  	},
	 211  	{
	 212  		`package p; import . "`,
	 213  		"syntax error",
	 214  	},
	 215  	{
	 216  		`package p; import . "x`,
	 217  		"syntax error",
	 218  	},
	 219  	{
	 220  		`package p; import (`,
	 221  		"syntax error",
	 222  	},
	 223  	{
	 224  		`package p; import ("`,
	 225  		"syntax error",
	 226  	},
	 227  	{
	 228  		`package p; import ("x`,
	 229  		"syntax error",
	 230  	},
	 231  	{
	 232  		`package p; import ("x"`,
	 233  		"syntax error",
	 234  	},
	 235  }
	 236  
	 237  func TestReadFailuresIgnored(t *testing.T) {
	 238  	// Syntax errors should not be reported (false arg to readImports).
	 239  	// Instead, entire file should be the output and no error.
	 240  	// Convert tests not to return syntax errors.
	 241  	tests := make([]readTest, len(readFailuresTests))
	 242  	copy(tests, readFailuresTests)
	 243  	for i := range tests {
	 244  		tt := &tests[i]
	 245  		if !strings.Contains(tt.err, "NUL") {
	 246  			tt.err = ""
	 247  		}
	 248  	}
	 249  	testRead(t, tests, func(r io.Reader) ([]byte, error) {
	 250  		var info fileInfo
	 251  		err := readGoInfo(r, &info)
	 252  		return info.header, err
	 253  	})
	 254  }
	 255  
	 256  var readEmbedTests = []struct {
	 257  	in, out string
	 258  }{
	 259  	{
	 260  		"package p\n",
	 261  		"",
	 262  	},
	 263  	{
	 264  		"package p\nimport \"embed\"\nvar i int\n//go:embed x y z\nvar files embed.FS",
	 265  		`test:4:12:x
	 266  		 test:4:14:y
	 267  		 test:4:16:z`,
	 268  	},
	 269  	{
	 270  		"package p\nimport \"embed\"\nvar i int\n//go:embed x \"\\x79\" `z`\nvar files embed.FS",
	 271  		`test:4:12:x
	 272  		 test:4:14:y
	 273  		 test:4:21:z`,
	 274  	},
	 275  	{
	 276  		"package p\nimport \"embed\"\nvar i int\n//go:embed x y\n//go:embed z\nvar files embed.FS",
	 277  		`test:4:12:x
	 278  		 test:4:14:y
	 279  		 test:5:12:z`,
	 280  	},
	 281  	{
	 282  		"package p\nimport \"embed\"\nvar i int\n\t //go:embed x y\n\t //go:embed z\n\t var files embed.FS",
	 283  		`test:4:14:x
	 284  		 test:4:16:y
	 285  		 test:5:14:z`,
	 286  	},
	 287  	{
	 288  		"package p\nimport \"embed\"\n//go:embed x y z\nvar files embed.FS",
	 289  		`test:3:12:x
	 290  		 test:3:14:y
	 291  		 test:3:16:z`,
	 292  	},
	 293  	{
	 294  		"\ufeffpackage p\nimport \"embed\"\n//go:embed x y z\nvar files embed.FS",
	 295  		`test:3:12:x
	 296  		 test:3:14:y
	 297  		 test:3:16:z`,
	 298  	},
	 299  	{
	 300  		"package p\nimport \"embed\"\nvar s = \"/*\"\n//go:embed x\nvar files embed.FS",
	 301  		`test:4:12:x`,
	 302  	},
	 303  	{
	 304  		`package p
	 305  		 import "embed"
	 306  		 var s = "\"\\\\"
	 307  		 //go:embed x
	 308  		 var files embed.FS`,
	 309  		`test:4:15:x`,
	 310  	},
	 311  	{
	 312  		"package p\nimport \"embed\"\nvar s = `/*`\n//go:embed x\nvar files embed.FS",
	 313  		`test:4:12:x`,
	 314  	},
	 315  	{
	 316  		"package p\nimport \"embed\"\nvar s = z/ *y\n//go:embed pointer\nvar pointer embed.FS",
	 317  		"test:4:12:pointer",
	 318  	},
	 319  	{
	 320  		"package p\n//go:embed x y z\n", // no import, no scan
	 321  		"",
	 322  	},
	 323  	{
	 324  		"package p\n//go:embed x y z\nvar files embed.FS", // no import, no scan
	 325  		"",
	 326  	},
	 327  	{
	 328  		"\ufeffpackage p\n//go:embed x y z\nvar files embed.FS", // no import, no scan
	 329  		"",
	 330  	},
	 331  }
	 332  
	 333  func TestReadEmbed(t *testing.T) {
	 334  	fset := token.NewFileSet()
	 335  	for i, tt := range readEmbedTests {
	 336  		info := fileInfo{
	 337  			name: "test",
	 338  			fset: fset,
	 339  		}
	 340  		err := readGoInfo(strings.NewReader(tt.in), &info)
	 341  		if err != nil {
	 342  			t.Errorf("#%d: %v", i, err)
	 343  			continue
	 344  		}
	 345  		b := &strings.Builder{}
	 346  		sep := ""
	 347  		for _, emb := range info.embeds {
	 348  			fmt.Fprintf(b, "%s%v:%s", sep, emb.pos, emb.pattern)
	 349  			sep = "\n"
	 350  		}
	 351  		got := b.String()
	 352  		want := strings.Join(strings.Fields(tt.out), "\n")
	 353  		if got != want {
	 354  			t.Errorf("#%d: embeds:\n%s\nwant:\n%s", i, got, want)
	 355  		}
	 356  	}
	 357  }
	 358  

View as plain text