...

Source file src/go/doc/example_test.go

Documentation: go/doc

		 1  // Copyright 2013 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 doc_test
		 6  
		 7  import (
		 8  	"bytes"
		 9  	"fmt"
		10  	"go/ast"
		11  	"go/doc"
		12  	"go/format"
		13  	"go/parser"
		14  	"go/token"
		15  	"reflect"
		16  	"strings"
		17  	"testing"
		18  )
		19  
		20  const exampleTestFile = `
		21  package foo_test
		22  
		23  import (
		24  	"flag"
		25  	"fmt"
		26  	"log"
		27  	"sort"
		28  	"os/exec"
		29  )
		30  
		31  func ExampleHello() {
		32  	fmt.Println("Hello, world!")
		33  	// Output: Hello, world!
		34  }
		35  
		36  func ExampleImport() {
		37  	out, err := exec.Command("date").Output()
		38  	if err != nil {
		39  		log.Fatal(err)
		40  	}
		41  	fmt.Printf("The date is %s\n", out)
		42  }
		43  
		44  func ExampleKeyValue() {
		45  	v := struct {
		46  		a string
		47  		b int
		48  	}{
		49  		a: "A",
		50  		b: 1,
		51  	}
		52  	fmt.Print(v)
		53  	// Output: a: "A", b: 1
		54  }
		55  
		56  func ExampleKeyValueImport() {
		57  	f := flag.Flag{
		58  		Name: "play",
		59  	}
		60  	fmt.Print(f)
		61  	// Output: Name: "play"
		62  }
		63  
		64  var keyValueTopDecl = struct {
		65  	a string
		66  	b int
		67  }{
		68  	a: "B",
		69  	b: 2,
		70  }
		71  
		72  func ExampleKeyValueTopDecl() {
		73  	fmt.Print(keyValueTopDecl)
		74  	// Output: a: "B", b: 2
		75  }
		76  
		77  // Person represents a person by name and age.
		78  type Person struct {
		79  		Name string
		80  		Age	int
		81  }
		82  
		83  // String returns a string representation of the Person.
		84  func (p Person) String() string {
		85  		return fmt.Sprintf("%s: %d", p.Name, p.Age)
		86  }
		87  
		88  // ByAge implements sort.Interface for []Person based on
		89  // the Age field.
		90  type ByAge []Person
		91  
		92  // Len returns the number of elements in ByAge.
		93  func (a (ByAge)) Len() int { return len(a) }
		94  
		95  // Swap swaps the elements in ByAge.
		96  func (a ByAge) Swap(i, j int)			{ a[i], a[j] = a[j], a[i] }
		97  func (a ByAge) Less(i, j int) bool { return a[i].Age < a[j].Age }
		98  
		99  // people is the array of Person
	 100  var people = []Person{
	 101  	{"Bob", 31},
	 102  	{"John", 42},
	 103  	{"Michael", 17},
	 104  	{"Jenny", 26},
	 105  }
	 106  
	 107  func ExampleSort() {
	 108  		fmt.Println(people)
	 109  		sort.Sort(ByAge(people))
	 110  		fmt.Println(people)
	 111  		// Output:
	 112  		// [Bob: 31 John: 42 Michael: 17 Jenny: 26]
	 113  		// [Michael: 17 Jenny: 26 Bob: 31 John: 42]
	 114  }
	 115  `
	 116  
	 117  var exampleTestCases = []struct {
	 118  	Name, Play, Output string
	 119  }{
	 120  	{
	 121  		Name:	 "Hello",
	 122  		Play:	 exampleHelloPlay,
	 123  		Output: "Hello, world!\n",
	 124  	},
	 125  	{
	 126  		Name: "Import",
	 127  		Play: exampleImportPlay,
	 128  	},
	 129  	{
	 130  		Name:	 "KeyValue",
	 131  		Play:	 exampleKeyValuePlay,
	 132  		Output: "a: \"A\", b: 1\n",
	 133  	},
	 134  	{
	 135  		Name:	 "KeyValueImport",
	 136  		Play:	 exampleKeyValueImportPlay,
	 137  		Output: "Name: \"play\"\n",
	 138  	},
	 139  	{
	 140  		Name:	 "KeyValueTopDecl",
	 141  		Play:	 exampleKeyValueTopDeclPlay,
	 142  		Output: "a: \"B\", b: 2\n",
	 143  	},
	 144  	{
	 145  		Name:	 "Sort",
	 146  		Play:	 exampleSortPlay,
	 147  		Output: "[Bob: 31 John: 42 Michael: 17 Jenny: 26]\n[Michael: 17 Jenny: 26 Bob: 31 John: 42]\n",
	 148  	},
	 149  }
	 150  
	 151  const exampleHelloPlay = `package main
	 152  
	 153  import (
	 154  	"fmt"
	 155  )
	 156  
	 157  func main() {
	 158  	fmt.Println("Hello, world!")
	 159  }
	 160  `
	 161  const exampleImportPlay = `package main
	 162  
	 163  import (
	 164  	"fmt"
	 165  	"log"
	 166  	"os/exec"
	 167  )
	 168  
	 169  func main() {
	 170  	out, err := exec.Command("date").Output()
	 171  	if err != nil {
	 172  		log.Fatal(err)
	 173  	}
	 174  	fmt.Printf("The date is %s\n", out)
	 175  }
	 176  `
	 177  
	 178  const exampleKeyValuePlay = `package main
	 179  
	 180  import (
	 181  	"fmt"
	 182  )
	 183  
	 184  func main() {
	 185  	v := struct {
	 186  		a string
	 187  		b int
	 188  	}{
	 189  		a: "A",
	 190  		b: 1,
	 191  	}
	 192  	fmt.Print(v)
	 193  }
	 194  `
	 195  
	 196  const exampleKeyValueImportPlay = `package main
	 197  
	 198  import (
	 199  	"flag"
	 200  	"fmt"
	 201  )
	 202  
	 203  func main() {
	 204  	f := flag.Flag{
	 205  		Name: "play",
	 206  	}
	 207  	fmt.Print(f)
	 208  }
	 209  `
	 210  
	 211  const exampleKeyValueTopDeclPlay = `package main
	 212  
	 213  import (
	 214  	"fmt"
	 215  )
	 216  
	 217  var keyValueTopDecl = struct {
	 218  	a string
	 219  	b int
	 220  }{
	 221  	a: "B",
	 222  	b: 2,
	 223  }
	 224  
	 225  func main() {
	 226  	fmt.Print(keyValueTopDecl)
	 227  }
	 228  `
	 229  
	 230  const exampleSortPlay = `package main
	 231  
	 232  import (
	 233  	"fmt"
	 234  	"sort"
	 235  )
	 236  
	 237  // Person represents a person by name and age.
	 238  type Person struct {
	 239  	Name string
	 240  	Age	int
	 241  }
	 242  
	 243  // String returns a string representation of the Person.
	 244  func (p Person) String() string {
	 245  	return fmt.Sprintf("%s: %d", p.Name, p.Age)
	 246  }
	 247  
	 248  // ByAge implements sort.Interface for []Person based on
	 249  // the Age field.
	 250  type ByAge []Person
	 251  
	 252  // Len returns the number of elements in ByAge.
	 253  func (a ByAge) Len() int { return len(a) }
	 254  
	 255  // Swap swaps the elements in ByAge.
	 256  func (a ByAge) Swap(i, j int)			{ a[i], a[j] = a[j], a[i] }
	 257  func (a ByAge) Less(i, j int) bool { return a[i].Age < a[j].Age }
	 258  
	 259  // people is the array of Person
	 260  var people = []Person{
	 261  	{"Bob", 31},
	 262  	{"John", 42},
	 263  	{"Michael", 17},
	 264  	{"Jenny", 26},
	 265  }
	 266  
	 267  func main() {
	 268  	fmt.Println(people)
	 269  	sort.Sort(ByAge(people))
	 270  	fmt.Println(people)
	 271  }
	 272  `
	 273  
	 274  func TestExamples(t *testing.T) {
	 275  	fset := token.NewFileSet()
	 276  	file, err := parser.ParseFile(fset, "test.go", strings.NewReader(exampleTestFile), parser.ParseComments)
	 277  	if err != nil {
	 278  		t.Fatal(err)
	 279  	}
	 280  	for i, e := range doc.Examples(file) {
	 281  		c := exampleTestCases[i]
	 282  		if e.Name != c.Name {
	 283  			t.Errorf("got Name == %q, want %q", e.Name, c.Name)
	 284  		}
	 285  		if w := c.Play; w != "" {
	 286  			g := formatFile(t, fset, e.Play)
	 287  			if g != w {
	 288  				t.Errorf("%s: got Play == %q, want %q", c.Name, g, w)
	 289  			}
	 290  		}
	 291  		if g, w := e.Output, c.Output; g != w {
	 292  			t.Errorf("%s: got Output == %q, want %q", c.Name, g, w)
	 293  		}
	 294  	}
	 295  }
	 296  
	 297  const exampleWholeFile = `package foo_test
	 298  
	 299  type X int
	 300  
	 301  func (X) Foo() {
	 302  }
	 303  
	 304  func (X) TestBlah() {
	 305  }
	 306  
	 307  func (X) BenchmarkFoo() {
	 308  }
	 309  
	 310  func Example() {
	 311  	fmt.Println("Hello, world!")
	 312  	// Output: Hello, world!
	 313  }
	 314  `
	 315  
	 316  const exampleWholeFileOutput = `package main
	 317  
	 318  type X int
	 319  
	 320  func (X) Foo() {
	 321  }
	 322  
	 323  func (X) TestBlah() {
	 324  }
	 325  
	 326  func (X) BenchmarkFoo() {
	 327  }
	 328  
	 329  func main() {
	 330  	fmt.Println("Hello, world!")
	 331  }
	 332  `
	 333  
	 334  const exampleWholeFileFunction = `package foo_test
	 335  
	 336  func Foo(x int) {
	 337  }
	 338  
	 339  func Example() {
	 340  	fmt.Println("Hello, world!")
	 341  	// Output: Hello, world!
	 342  }
	 343  `
	 344  
	 345  const exampleWholeFileFunctionOutput = `package main
	 346  
	 347  func Foo(x int) {
	 348  }
	 349  
	 350  func main() {
	 351  	fmt.Println("Hello, world!")
	 352  }
	 353  `
	 354  
	 355  const exampleWholeFileExternalFunction = `package foo_test
	 356  
	 357  func foo(int)
	 358  
	 359  func Example() {
	 360  	foo(42)
	 361  	// Output:
	 362  }
	 363  `
	 364  
	 365  const exampleWholeFileExternalFunctionOutput = `package main
	 366  
	 367  func foo(int)
	 368  
	 369  func main() {
	 370  	foo(42)
	 371  }
	 372  `
	 373  
	 374  var exampleWholeFileTestCases = []struct {
	 375  	Title, Source, Play, Output string
	 376  }{
	 377  	{
	 378  		"Methods",
	 379  		exampleWholeFile,
	 380  		exampleWholeFileOutput,
	 381  		"Hello, world!\n",
	 382  	},
	 383  	{
	 384  		"Function",
	 385  		exampleWholeFileFunction,
	 386  		exampleWholeFileFunctionOutput,
	 387  		"Hello, world!\n",
	 388  	},
	 389  	{
	 390  		"ExternalFunction",
	 391  		exampleWholeFileExternalFunction,
	 392  		exampleWholeFileExternalFunctionOutput,
	 393  		"",
	 394  	},
	 395  }
	 396  
	 397  func TestExamplesWholeFile(t *testing.T) {
	 398  	for _, c := range exampleWholeFileTestCases {
	 399  		fset := token.NewFileSet()
	 400  		file, err := parser.ParseFile(fset, "test.go", strings.NewReader(c.Source), parser.ParseComments)
	 401  		if err != nil {
	 402  			t.Fatal(err)
	 403  		}
	 404  		es := doc.Examples(file)
	 405  		if len(es) != 1 {
	 406  			t.Fatalf("%s: wrong number of examples; got %d want 1", c.Title, len(es))
	 407  		}
	 408  		e := es[0]
	 409  		if e.Name != "" {
	 410  			t.Errorf("%s: got Name == %q, want %q", c.Title, e.Name, "")
	 411  		}
	 412  		if g, w := formatFile(t, fset, e.Play), c.Play; g != w {
	 413  			t.Errorf("%s: got Play == %q, want %q", c.Title, g, w)
	 414  		}
	 415  		if g, w := e.Output, c.Output; g != w {
	 416  			t.Errorf("%s: got Output == %q, want %q", c.Title, g, w)
	 417  		}
	 418  	}
	 419  }
	 420  
	 421  const exampleInspectSignature = `package foo_test
	 422  
	 423  import (
	 424  	"bytes"
	 425  	"io"
	 426  )
	 427  
	 428  func getReader() io.Reader { return nil }
	 429  
	 430  func do(b bytes.Reader) {}
	 431  
	 432  func Example() {
	 433  	getReader()
	 434  	do()
	 435  	// Output:
	 436  }
	 437  
	 438  func ExampleIgnored() {
	 439  }
	 440  `
	 441  
	 442  const exampleInspectSignatureOutput = `package main
	 443  
	 444  import (
	 445  	"bytes"
	 446  	"io"
	 447  )
	 448  
	 449  func getReader() io.Reader { return nil }
	 450  
	 451  func do(b bytes.Reader) {}
	 452  
	 453  func main() {
	 454  	getReader()
	 455  	do()
	 456  }
	 457  `
	 458  
	 459  func TestExampleInspectSignature(t *testing.T) {
	 460  	// Verify that "bytes" and "io" are imported. See issue #28492.
	 461  	fset := token.NewFileSet()
	 462  	file, err := parser.ParseFile(fset, "test.go", strings.NewReader(exampleInspectSignature), parser.ParseComments)
	 463  	if err != nil {
	 464  		t.Fatal(err)
	 465  	}
	 466  	es := doc.Examples(file)
	 467  	if len(es) != 2 {
	 468  		t.Fatalf("wrong number of examples; got %d want 2", len(es))
	 469  	}
	 470  	// We are interested in the first example only.
	 471  	e := es[0]
	 472  	if e.Name != "" {
	 473  		t.Errorf("got Name == %q, want %q", e.Name, "")
	 474  	}
	 475  	if g, w := formatFile(t, fset, e.Play), exampleInspectSignatureOutput; g != w {
	 476  		t.Errorf("got Play == %q, want %q", g, w)
	 477  	}
	 478  	if g, w := e.Output, ""; g != w {
	 479  		t.Errorf("got Output == %q, want %q", g, w)
	 480  	}
	 481  }
	 482  
	 483  const exampleEmpty = `
	 484  package p
	 485  func Example() {}
	 486  func Example_a()
	 487  `
	 488  
	 489  const exampleEmptyOutput = `package main
	 490  
	 491  func main() {}
	 492  func main()
	 493  `
	 494  
	 495  func TestExampleEmpty(t *testing.T) {
	 496  	fset := token.NewFileSet()
	 497  	file, err := parser.ParseFile(fset, "test.go", strings.NewReader(exampleEmpty), parser.ParseComments)
	 498  	if err != nil {
	 499  		t.Fatal(err)
	 500  	}
	 501  
	 502  	es := doc.Examples(file)
	 503  	if len(es) != 1 {
	 504  		t.Fatalf("wrong number of examples; got %d want 1", len(es))
	 505  	}
	 506  	e := es[0]
	 507  	if e.Name != "" {
	 508  		t.Errorf("got Name == %q, want %q", e.Name, "")
	 509  	}
	 510  	if g, w := formatFile(t, fset, e.Play), exampleEmptyOutput; g != w {
	 511  		t.Errorf("got Play == %q, want %q", g, w)
	 512  	}
	 513  	if g, w := e.Output, ""; g != w {
	 514  		t.Errorf("got Output == %q, want %q", g, w)
	 515  	}
	 516  }
	 517  
	 518  func formatFile(t *testing.T, fset *token.FileSet, n *ast.File) string {
	 519  	if n == nil {
	 520  		return "<nil>"
	 521  	}
	 522  	var buf bytes.Buffer
	 523  	if err := format.Node(&buf, fset, n); err != nil {
	 524  		t.Fatal(err)
	 525  	}
	 526  	return buf.String()
	 527  }
	 528  
	 529  // This example illustrates how to use NewFromFiles
	 530  // to compute package documentation with examples.
	 531  func ExampleNewFromFiles() {
	 532  	// src and test are two source files that make up
	 533  	// a package whose documentation will be computed.
	 534  	const src = `
	 535  // This is the package comment.
	 536  package p
	 537  
	 538  import "fmt"
	 539  
	 540  // This comment is associated with the Greet function.
	 541  func Greet(who string) {
	 542  	fmt.Printf("Hello, %s!\n", who)
	 543  }
	 544  `
	 545  	const test = `
	 546  package p_test
	 547  
	 548  // This comment is associated with the ExampleGreet_world example.
	 549  func ExampleGreet_world() {
	 550  	Greet("world")
	 551  }
	 552  `
	 553  
	 554  	// Create the AST by parsing src and test.
	 555  	fset := token.NewFileSet()
	 556  	files := []*ast.File{
	 557  		mustParse(fset, "src.go", src),
	 558  		mustParse(fset, "src_test.go", test),
	 559  	}
	 560  
	 561  	// Compute package documentation with examples.
	 562  	p, err := doc.NewFromFiles(fset, files, "example.com/p")
	 563  	if err != nil {
	 564  		panic(err)
	 565  	}
	 566  
	 567  	fmt.Printf("package %s - %s", p.Name, p.Doc)
	 568  	fmt.Printf("func %s - %s", p.Funcs[0].Name, p.Funcs[0].Doc)
	 569  	fmt.Printf(" ⤷ example with suffix %q - %s", p.Funcs[0].Examples[0].Suffix, p.Funcs[0].Examples[0].Doc)
	 570  
	 571  	// Output:
	 572  	// package p - This is the package comment.
	 573  	// func Greet - This comment is associated with the Greet function.
	 574  	//	⤷ example with suffix "world" - This comment is associated with the ExampleGreet_world example.
	 575  }
	 576  
	 577  func TestClassifyExamples(t *testing.T) {
	 578  	const src = `
	 579  package p
	 580  
	 581  const Const1 = 0
	 582  var	 Var1	 = 0
	 583  
	 584  type (
	 585  	Type1		 int
	 586  	Type1_Foo int
	 587  	Type1_foo int
	 588  	type2		 int
	 589  
	 590  	Embed struct { Type1 }
	 591  	Uembed struct { type2 }
	 592  )
	 593  
	 594  func Func1()		 {}
	 595  func Func1_Foo() {}
	 596  func Func1_foo() {}
	 597  func func2()		 {}
	 598  
	 599  func (Type1) Func1() {}
	 600  func (Type1) Func1_Foo() {}
	 601  func (Type1) Func1_foo() {}
	 602  func (Type1) func2() {}
	 603  
	 604  func (type2) Func1() {}
	 605  
	 606  type (
	 607  	Conflict					int
	 608  	Conflict_Conflict int
	 609  	Conflict_conflict int
	 610  )
	 611  
	 612  func (Conflict) Conflict() {}
	 613  `
	 614  	const test = `
	 615  package p_test
	 616  
	 617  func ExampleConst1() {} // invalid - no support for consts and vars
	 618  func ExampleVar1()	 {} // invalid - no support for consts and vars
	 619  
	 620  func Example()							 {}
	 621  func Example_()							{} // invalid - suffix must start with a lower-case letter
	 622  func Example_suffix()				{}
	 623  func Example_suffix_xX_X_x() {}
	 624  func Example_世界()					 {} // invalid - suffix must start with a lower-case letter
	 625  func Example_123()					 {} // invalid - suffix must start with a lower-case letter
	 626  func Example_BadSuffix()		 {} // invalid - suffix must start with a lower-case letter
	 627  
	 628  func ExampleType1()							 {}
	 629  func ExampleType1_()							{} // invalid - suffix must start with a lower-case letter
	 630  func ExampleType1_suffix()				{}
	 631  func ExampleType1_BadSuffix()		 {} // invalid - suffix must start with a lower-case letter
	 632  func ExampleType1_Foo()					 {}
	 633  func ExampleType1_Foo_suffix()		{}
	 634  func ExampleType1_Foo_BadSuffix() {} // invalid - suffix must start with a lower-case letter
	 635  func ExampleType1_foo()					 {}
	 636  func ExampleType1_foo_suffix()		{}
	 637  func ExampleType1_foo_Suffix()		{} // matches Type1, instead of Type1_foo
	 638  func Exampletype2()							 {} // invalid - cannot match unexported
	 639  
	 640  func ExampleFunc1()							 {}
	 641  func ExampleFunc1_()							{} // invalid - suffix must start with a lower-case letter
	 642  func ExampleFunc1_suffix()				{}
	 643  func ExampleFunc1_BadSuffix()		 {} // invalid - suffix must start with a lower-case letter
	 644  func ExampleFunc1_Foo()					 {}
	 645  func ExampleFunc1_Foo_suffix()		{}
	 646  func ExampleFunc1_Foo_BadSuffix() {} // invalid - suffix must start with a lower-case letter
	 647  func ExampleFunc1_foo()					 {}
	 648  func ExampleFunc1_foo_suffix()		{}
	 649  func ExampleFunc1_foo_Suffix()		{} // matches Func1, instead of Func1_foo
	 650  func Examplefunc1()							 {} // invalid - cannot match unexported
	 651  
	 652  func ExampleType1_Func1()							 {}
	 653  func ExampleType1_Func1_()							{} // invalid - suffix must start with a lower-case letter
	 654  func ExampleType1_Func1_suffix()				{}
	 655  func ExampleType1_Func1_BadSuffix()		 {} // invalid - suffix must start with a lower-case letter
	 656  func ExampleType1_Func1_Foo()					 {}
	 657  func ExampleType1_Func1_Foo_suffix()		{}
	 658  func ExampleType1_Func1_Foo_BadSuffix() {} // invalid - suffix must start with a lower-case letter
	 659  func ExampleType1_Func1_foo()					 {}
	 660  func ExampleType1_Func1_foo_suffix()		{}
	 661  func ExampleType1_Func1_foo_Suffix()		{} // matches Type1.Func1, instead of Type1.Func1_foo
	 662  func ExampleType1_func2()							 {} // matches Type1, instead of Type1.func2
	 663  
	 664  func ExampleEmbed_Func1()				 {} // invalid - no support for forwarded methods from embedding exported type
	 665  func ExampleUembed_Func1()				{} // methods from embedding unexported types are OK
	 666  func ExampleUembed_Func1_suffix() {}
	 667  
	 668  func ExampleConflict_Conflict()				{} // ambiguous with either Conflict or Conflict_Conflict type
	 669  func ExampleConflict_conflict()				{} // ambiguous with either Conflict or Conflict_conflict type
	 670  func ExampleConflict_Conflict_suffix() {} // ambiguous with either Conflict or Conflict_Conflict type
	 671  func ExampleConflict_conflict_suffix() {} // ambiguous with either Conflict or Conflict_conflict type
	 672  `
	 673  
	 674  	// Parse literal source code as a *doc.Package.
	 675  	fset := token.NewFileSet()
	 676  	files := []*ast.File{
	 677  		mustParse(fset, "src.go", src),
	 678  		mustParse(fset, "src_test.go", test),
	 679  	}
	 680  	p, err := doc.NewFromFiles(fset, files, "example.com/p")
	 681  	if err != nil {
	 682  		t.Fatalf("doc.NewFromFiles: %v", err)
	 683  	}
	 684  
	 685  	// Collect the association of examples to top-level identifiers.
	 686  	got := map[string][]string{}
	 687  	got[""] = exampleNames(p.Examples)
	 688  	for _, f := range p.Funcs {
	 689  		got[f.Name] = exampleNames(f.Examples)
	 690  	}
	 691  	for _, t := range p.Types {
	 692  		got[t.Name] = exampleNames(t.Examples)
	 693  		for _, f := range t.Funcs {
	 694  			got[f.Name] = exampleNames(f.Examples)
	 695  		}
	 696  		for _, m := range t.Methods {
	 697  			got[t.Name+"."+m.Name] = exampleNames(m.Examples)
	 698  		}
	 699  	}
	 700  
	 701  	want := map[string][]string{
	 702  		"": {"", "suffix", "suffix_xX_X_x"}, // Package-level examples.
	 703  
	 704  		"Type1":		 {"", "foo_Suffix", "func2", "suffix"},
	 705  		"Type1_Foo": {"", "suffix"},
	 706  		"Type1_foo": {"", "suffix"},
	 707  
	 708  		"Func1":		 {"", "foo_Suffix", "suffix"},
	 709  		"Func1_Foo": {"", "suffix"},
	 710  		"Func1_foo": {"", "suffix"},
	 711  
	 712  		"Type1.Func1":		 {"", "foo_Suffix", "suffix"},
	 713  		"Type1.Func1_Foo": {"", "suffix"},
	 714  		"Type1.Func1_foo": {"", "suffix"},
	 715  
	 716  		"Uembed.Func1": {"", "suffix"},
	 717  
	 718  		// These are implementation dependent due to the ambiguous parsing.
	 719  		"Conflict_Conflict": {"", "suffix"},
	 720  		"Conflict_conflict": {"", "suffix"},
	 721  	}
	 722  
	 723  	for id := range got {
	 724  		if !reflect.DeepEqual(got[id], want[id]) {
	 725  			t.Errorf("classification mismatch for %q:\ngot	%q\nwant %q", id, got[id], want[id])
	 726  		}
	 727  	}
	 728  }
	 729  
	 730  func exampleNames(exs []*doc.Example) (out []string) {
	 731  	for _, ex := range exs {
	 732  		out = append(out, ex.Suffix)
	 733  	}
	 734  	return out
	 735  }
	 736  
	 737  func mustParse(fset *token.FileSet, filename, src string) *ast.File {
	 738  	f, err := parser.ParseFile(fset, filename, src, parser.ParseComments)
	 739  	if err != nil {
	 740  		panic(err)
	 741  	}
	 742  	return f
	 743  }
	 744  

View as plain text