github.com/galaxyobe/gen@v0.0.0-20220910125335-392fa8f0990f/third_party/gengo/parser/parse_test.go (about) 1 /* 2 Copyright 2015 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package parser_test 18 19 import ( 20 "bytes" 21 "path" 22 "path/filepath" 23 "reflect" 24 "testing" 25 "text/template" 26 27 "github.com/davecgh/go-spew/spew" 28 "github.com/google/go-cmp/cmp" 29 "github.com/google/go-cmp/cmp/cmpopts" 30 31 "k8s.io/gengo/args" 32 "k8s.io/gengo/namer" 33 "k8s.io/gengo/parser" 34 "k8s.io/gengo/types" 35 ) 36 37 func TestRecursive(t *testing.T) { 38 dir := "k8s.io/gengo/testdata/a" 39 d := args.Default() 40 d.InputDirs = []string{dir + "/..."} 41 b, err := d.NewBuilder() 42 if err != nil { 43 t.Fatalf("Fail making builder: %v", err) 44 } 45 findTypes, err := b.FindTypes() 46 if err != nil { 47 t.Fatalf("Fail finding types: %v", err) 48 } 49 foundB := false 50 foundC := false 51 for _, p := range b.FindPackages() { 52 t.Logf("Package: %v", p) 53 if p == "k8s.io/gengo/testdata/a/b" { 54 foundB = true 55 } 56 if p == "k8s.io/gengo/testdata/a/c" { 57 foundC = true 58 } 59 } 60 if !foundB { 61 t.Errorf("Expected to find packages a and b") 62 } 63 if foundC { 64 t.Error("Did not expect to find package c") 65 } 66 if name := findTypes[dir].Types["AA"].Methods["AFunc"].Name.Name; name != "func (*k8s.io/gengo/testdata/a.AA).AFunc(i *int, j int) (*k8s.io/gengo/testdata/a.A, k8s.io/gengo/testdata/a/b.ITest, error)" { 67 t.Errorf("Parse method type error, got name: %s", name) 68 } 69 // only has three package: package "a", package "b", and package "" for all 70 if len(findTypes) != 3 { 71 t.Error("Parse type error, and take type path as package") 72 } 73 } 74 75 func TestRecursiveWithTestGoFiles(t *testing.T) { 76 d := args.Default() 77 d.IncludeTestFiles = true 78 d.InputDirs = []string{"k8s.io/gengo/testdata/a/..."} 79 b, err := d.NewBuilder() 80 if err != nil { 81 t.Fatalf("Fail making builder: %v", err) 82 } 83 _, err = b.FindTypes() 84 if err != nil { 85 t.Fatalf("Fail finding types: %v", err) 86 } 87 foundB := false 88 foundC := false 89 for _, p := range b.FindPackages() { 90 t.Logf("Package: %v", p) 91 if p == "k8s.io/gengo/testdata/a/b" { 92 foundB = true 93 } 94 if p == "k8s.io/gengo/testdata/a/c" { 95 foundC = true 96 } 97 } 98 if !foundC || !foundB { 99 t.Errorf("Expected to find packages a, b and c") 100 } 101 } 102 103 type file struct { 104 path string 105 contents string 106 } 107 108 // Pass files in topological order - deps first! 109 func construct(t *testing.T, files []file, testNamer namer.Namer) (*parser.Builder, types.Universe, []*types.Type) { 110 b := parser.New() 111 for _, f := range files { 112 if err := b.AddFileForTest(path.Dir(f.path), filepath.FromSlash(f.path), []byte(f.contents)); err != nil { 113 t.Fatal(err) 114 } 115 } 116 u, err := b.FindTypes() 117 if err != nil { 118 t.Fatal(err) 119 } 120 orderer := namer.Orderer{Namer: testNamer} 121 o := orderer.OrderUniverse(u) 122 return b, u, o 123 } 124 125 func TestBuilder(t *testing.T) { 126 var testFiles = []file{ 127 { 128 path: "base/common/proto/common.go", contents: ` 129 package common 130 131 type Object struct { 132 ID int64 133 } 134 `, 135 }, { 136 path: "base/foo/proto/foo.go", contents: ` 137 package foo 138 139 import ( 140 "base/common/proto" 141 ) 142 143 type Blah struct { 144 common.Object 145 Count int64 146 Frobbers map[string]*Frobber 147 Baz []Object 148 Nickname *string 149 NumberIsAFavorite map[int]bool 150 } 151 152 type Frobber struct { 153 Name string 154 Amount int64 155 } 156 157 type Object struct { 158 common.Object 159 } 160 161 func AFunc(obj1 common.Object, obj2 Object) Frobber { 162 } 163 164 var AVar Frobber 165 166 var ( 167 AnotherVar = Frobber{} 168 ) 169 170 type Enumeration string 171 const ( 172 EnumSymbol Enumeration = "enumSymbolValue" 173 ) 174 175 type Degrees int 176 const ( 177 FirstDegree Degrees = iota 178 SecondDegree 179 ThirdDegree 180 ) 181 182 const ConstNineNine = 99 183 const ConstHundred = ConstNineNine + 1 184 185 const ConstExpr = 1 - 0.707i * 9.3 186 const ConstFloat = float64(7.8) 187 const ConstString = "constant string" 188 `, 189 }, 190 } 191 192 var tmplText = ` 193 package o 194 {{define "Struct"}}type {{Name .}} interface { {{range $m := .Members}}{{$n := Name $m.Type}} 195 {{if $m.Embedded}}{{$n}}{{else}}{{$m.Name}}() {{$n}}{{if $m.Type.Elem}}{{else}} 196 Set{{$m.Name}}({{$n}}){{end}}{{end}}{{end}} 197 } 198 199 {{end}} 200 {{define "Func"}}{{$s := .Underlying.Signature}}var {{Name .}} func({{range $index,$elem := $s.Parameters}}{{if $index}}, {{end}}{{Raw $elem}}{{end}}) {{if $s.Results|len |gt 1}}({{end}}{{range $index,$elem := $s.Results}}{{if $index}}, {{end}}{{Raw .}}{{end}}{{if $s.Results|len |gt 1}}){{end}} = {{Raw .}} 201 202 {{end}} 203 {{define "Var"}}{{$t := .Underlying}}var {{Name .}} {{Raw $t}} = {{Raw .}} 204 205 {{end}} 206 {{define "Const"}}{{$t := .Underlying}}const {{Name .}} {{Raw $t}} = {{Raw .}}({{ .ConstValue }}) 207 208 {{end}} 209 {{range $t := .}}{{if eq $t.Kind "Struct"}}{{template "Struct" $t}}{{end}}{{end}} 210 {{range $t := .}}{{if eq $t.Kind "DeclarationOf"}}{{if eq $t.Underlying.Kind "Func"}}{{template "Func" $t}}{{end}}{{end}}{{end}} 211 {{range $t := .}}{{if eq $t.Kind "DeclarationOf"}}{{if eq $t.Underlying.Kind "Struct"}}{{template "Var" $t}}{{end}}{{end}}{{end}} 212 {{range $t := .}}{{if eq $t.Kind "DeclarationOf"}}{{if eq $t.Underlying.Kind "Alias"}}{{template "Const" $t}}{{end}}{{end}}{{end}}` 213 214 var expect = ` 215 package o 216 217 218 219 220 type CommonObject interface { 221 ID() Int64 222 SetID(Int64) 223 } 224 225 type FooBlah interface { 226 CommonObject 227 Count() Int64 228 SetCount(Int64) 229 Frobbers() MapStringToPointerFooFrobber 230 Baz() SliceFooObject 231 Nickname() PointerString 232 NumberIsAFavorite() MapIntToBool 233 } 234 235 type FooFrobber interface { 236 Name() String 237 SetName(String) 238 Amount() Int64 239 SetAmount(Int64) 240 } 241 242 type FooObject interface { 243 CommonObject 244 } 245 246 247 var FooAFunc func(proto.Object, proto.Object) proto.Frobber = proto.AFunc 248 249 250 var FooAVar proto.Frobber = proto.AVar 251 252 var FooAnotherVar proto.Frobber = proto.AnotherVar 253 254 255 const FooEnumSymbol proto.Enumeration = proto.EnumSymbol(enumSymbolValue) 256 257 const FooFirstDegree proto.Degrees = proto.FirstDegree(0) 258 259 const FooSecondDegree proto.Degrees = proto.SecondDegree(1) 260 261 const FooThirdDegree proto.Degrees = proto.ThirdDegree(2) 262 263 ` 264 testNamer := namer.NewPublicNamer(1, "proto") 265 rawNamer := namer.NewRawNamer("o", nil) 266 _, u, o := construct(t, testFiles, testNamer) 267 t.Logf("\n%v\n\n", o) 268 args := map[string]interface{}{ 269 "Name": testNamer.Name, 270 "Raw": rawNamer.Name, 271 } 272 tmpl := template.Must( 273 template.New(""). 274 Funcs(args). 275 Parse(tmplText), 276 ) 277 buf := &bytes.Buffer{} 278 tmpl.Execute(buf, o) 279 if e, a := expect, buf.String(); e != a { 280 cmp.Diff(e, a) 281 t.Errorf("Wanted, got:\n%v\n-----\n%v\nDiff:\n%s", e, a, cmp.Diff(e, a)) 282 } 283 if p := u.Package("base/foo/proto"); !p.HasImport("base/common/proto") { 284 t.Errorf("Unexpected lack of import line: %#v", p.Imports) 285 } 286 287 strPtr := func(s string) *string { return &s } 288 289 expectedConst := map[string]*types.Type{ 290 "EnumSymbol": &types.Type{ 291 Name: types.Name{Package: "base/foo/proto", Name: "EnumSymbol"}, 292 Kind: types.DeclarationOf, 293 ConstValue: strPtr("enumSymbolValue"), 294 }, 295 "FirstDegree": &types.Type{ 296 Name: types.Name{Package: "base/foo/proto", Name: "FirstDegree"}, 297 Kind: types.DeclarationOf, 298 ConstValue: strPtr("0"), 299 }, 300 "SecondDegree": &types.Type{ 301 Name: types.Name{Package: "base/foo/proto", Name: "SecondDegree"}, 302 Kind: types.DeclarationOf, 303 ConstValue: strPtr("1"), 304 }, 305 "ThirdDegree": &types.Type{ 306 Name: types.Name{Package: "base/foo/proto", Name: "ThirdDegree"}, 307 Kind: types.DeclarationOf, 308 ConstValue: strPtr("2"), 309 }, 310 "ConstNineNine": &types.Type{ 311 Name: types.Name{Package: "base/foo/proto", Name: "ConstNineNine"}, 312 Kind: types.DeclarationOf, 313 ConstValue: strPtr("99"), 314 }, 315 "ConstHundred": &types.Type{ 316 Name: types.Name{Package: "base/foo/proto", Name: "ConstHundred"}, 317 Kind: types.DeclarationOf, 318 ConstValue: strPtr("100"), 319 }, 320 "ConstFloat": &types.Type{ 321 Name: types.Name{Package: "base/foo/proto", Name: "ConstFloat"}, 322 Kind: types.DeclarationOf, 323 ConstValue: strPtr("7.8"), 324 }, 325 "ConstExpr": &types.Type{ 326 Name: types.Name{Package: "base/foo/proto", Name: "ConstExpr"}, 327 Kind: types.DeclarationOf, 328 ConstValue: strPtr("(1 + -6.5751i)"), 329 }, 330 "ConstString": &types.Type{ 331 Name: types.Name{Package: "base/foo/proto", Name: "ConstString"}, 332 Kind: types.DeclarationOf, 333 ConstValue: strPtr("constant string"), 334 }, 335 } 336 337 if diff := cmp.Diff( 338 u.Package("base/foo/proto").Constants, expectedConst, 339 cmpopts.IgnoreFields(types.Type{}, "Underlying"), 340 cmpopts.IgnoreFields(types.Type{}, "CommentLines"), 341 cmpopts.IgnoreFields(types.Type{}, "SecondClosestCommentLines"), 342 ); diff != "" { 343 t.Errorf("Constant mismatch: %s", diff) 344 } 345 346 if len(u.Package("base/foo/proto").Constants) != len(expectedConst) { 347 t.Errorf("Wanted %d constants, got: %s", 348 len(expectedConst), spew.Sdump(u.Package("base/foo/proto").Constants)) 349 } 350 } 351 352 func TestStructParse(t *testing.T) { 353 var structTest = file{ 354 path: "base/foo/proto/foo.go", 355 contents: ` 356 package foo 357 358 // Blah is a test. 359 // A test, I tell you. 360 type Blah struct { 361 // A is the first field. 362 A int64 ` + "`" + `json:"a"` + "`" + ` 363 364 // B is the second field. 365 // Multiline comments work. 366 B string ` + "`" + `json:"b"` + "`" + ` 367 } 368 `, 369 } 370 371 _, u, o := construct(t, []file{structTest}, namer.NewPublicNamer(0)) 372 t.Logf("%#v", o) 373 blahT := u.Type(types.Name{Package: "base/foo/proto", Name: "Blah"}) 374 if blahT == nil { 375 t.Fatal("type not found") 376 } 377 if e, a := types.Struct, blahT.Kind; e != a { 378 t.Errorf("struct kind wrong, wanted %v, got %v", e, a) 379 } 380 if e, a := []string{"Blah is a test.", "A test, I tell you."}, blahT.CommentLines; !reflect.DeepEqual(e, a) { 381 t.Errorf("struct comment wrong, wanted %q, got %q", e, a) 382 } 383 m := types.Member{ 384 Name: "B", 385 Embedded: false, 386 CommentLines: []string{"B is the second field.", "Multiline comments work."}, 387 Tags: `json:"b"`, 388 Type: types.String, 389 } 390 if e, a := m, blahT.Members[1]; !reflect.DeepEqual(e, a) { 391 t.Errorf("wanted, got:\n%#v\n%#v", e, a) 392 } 393 } 394 395 func TestParseSecondClosestCommentLines(t *testing.T) { 396 const fileName = "base/foo/proto/foo.go" 397 testCases := []struct { 398 testFile file 399 expected []string 400 }{ 401 { 402 testFile: file{ 403 path: fileName, contents: ` 404 package foo 405 // Blah's SecondClosestCommentLines. 406 // Another line. 407 408 // Blah is a test. 409 // A test, I tell you. 410 type Blah struct { 411 a int 412 } 413 `}, 414 expected: []string{"Blah's SecondClosestCommentLines.", "Another line."}, 415 }, 416 { 417 testFile: file{ 418 path: fileName, contents: ` 419 package foo 420 // Blah's SecondClosestCommentLines. 421 // Another line. 422 423 type Blah struct { 424 a int 425 } 426 `}, 427 expected: []string{"Blah's SecondClosestCommentLines.", "Another line."}, 428 }, 429 } 430 for _, test := range testCases { 431 _, u, o := construct(t, []file{test.testFile}, namer.NewPublicNamer(0)) 432 t.Logf("%#v", o) 433 blahT := u.Type(types.Name{Package: "base/foo/proto", Name: "Blah"}) 434 if e, a := test.expected, blahT.SecondClosestCommentLines; !reflect.DeepEqual(e, a) { 435 t.Errorf("struct second closest comment wrong, wanted %q, got %q", e, a) 436 } 437 } 438 } 439 440 func TestParseMethodParameterAndResultNames(t *testing.T) { 441 const fileName = "base/foo/proto/foo.go" 442 testCases := []struct { 443 testFile file 444 expectedParamNames map[string][]string 445 expectedResultNames map[string][]string 446 }{ 447 { 448 testFile: file{ 449 path: fileName, contents: ` 450 package foo 451 452 type bar struct{} 453 454 func (b *bar) SingleParam(param1 int) {} 455 func (b *bar) MultipleParams(param1, param2 int) {} 456 func (b *bar) SingleParamSingleResult(param1 int) (out1 bool) {} 457 func (b *bar) MultipleParamsMultipleResults(param1 bool, param2 int) (out1 bool, out2 string) {} 458 func (b *bar) NoParamsMultipleResults() (out1 bool, out2 string) {} 459 func (b *bar) NoParamsSingleResults() (out1 bool) {} 460 func (b *bar) NoParamsNoResults() {} 461 func (b *bar) UnnamedSingleParamNoResults(int) {} 462 func (b *bar) UnnamedMultipleParamsNoResult(int, bool) {} 463 func (b *bar) NoParamsSingleUnnamedResults() int {} 464 func (b *bar) NoParamsMultipleUnnamedResults() (int, string) {} 465 `}, 466 expectedParamNames: map[string][]string{ 467 "SingleParam": {"param1"}, 468 "MultipleParams": {"param1", "param2"}, 469 "SingleParamSingleResult": {"param1"}, 470 "MultipleParamsMultipleResults": {"param1", "param2"}, 471 "NoParamsMultipleResults": nil, 472 "NoParamsSingleResults": nil, 473 "NoParamsNoResults": nil, 474 "UnnamedSingleParamNoResults": {""}, 475 "UnnamedMultipleParamsNoResult": {"", ""}, 476 "NoParamsSingleUnnamedResults": nil, 477 "NoParamsMultipleUnnamedResults": nil, 478 }, 479 expectedResultNames: map[string][]string{ 480 "SingleParam": nil, 481 "MultipleParams": nil, 482 "SingleParamSingleResult": {"out1"}, 483 "MultipleParamsMultipleResults": {"out1", "out2"}, 484 "NoParamsMultipleResults": {"out1", "out2"}, 485 "NoParamsSingleResults": {"out1"}, 486 "NoParamsNoResults": nil, 487 "UnnamedSingleParamNoResults": nil, 488 "UnnamedMultipleParamsNoResult": nil, 489 "NoParamsSingleUnnamedResults": {""}, 490 "NoParamsMultipleUnnamedResults": {"", ""}, 491 }, 492 }, 493 } 494 for _, test := range testCases { 495 _, u, o := construct(t, []file{test.testFile}, namer.NewPublicNamer(0)) 496 t.Logf("%#v", o) 497 blahT := u.Type(types.Name{Package: "base/foo/proto", Name: "bar"}) 498 499 for methodName, methodType := range blahT.Methods { 500 expectedParamNames := test.expectedParamNames[methodName] 501 actualParamNames := methodType.Signature.ParameterNames 502 if !reflect.DeepEqual(expectedParamNames, actualParamNames) { 503 t.Errorf("%s param names parsed incorrectly wrong, wanted %v, got %v", methodName, expectedParamNames, 504 actualParamNames) 505 } 506 507 expectedResultNames := test.expectedResultNames[methodName] 508 actualResultNames := methodType.Signature.ResultNames 509 if !reflect.DeepEqual(expectedResultNames, actualResultNames) { 510 t.Errorf("%s result names parsed incorrectly wrong, wanted %v, got %v", methodName, expectedResultNames, 511 actualResultNames) 512 } 513 } 514 515 } 516 } 517 518 func TestParseMethodCommentLines(t *testing.T) { 519 const fileName = "base/foo/proto/foo.go" 520 testCases := []struct { 521 testFile file 522 expected []string 523 }{ 524 { 525 testFile: file{ 526 path: fileName, contents: ` 527 package foo 528 529 type Blah struct { 530 a int 531 } 532 533 // BlahFunc's CommentLines. 534 // Another line. 535 func (b *Blah) BlahFunc() {} 536 `}, 537 expected: []string{"BlahFunc's CommentLines.", "Another line."}, 538 }, 539 { 540 testFile: file{ 541 path: fileName, contents: ` 542 package foo 543 544 type Blah interface { 545 // BlahFunc's CommentLines. 546 // Another line. 547 BlahFunc() 548 } 549 `}, 550 expected: []string{"BlahFunc's CommentLines.", "Another line."}, 551 }, 552 } 553 for _, test := range testCases { 554 _, u, o := construct(t, []file{test.testFile}, namer.NewPublicNamer(0)) 555 t.Logf("%#v", o) 556 blahT := u.Type(types.Name{Package: "base/foo/proto", Name: "Blah"}) 557 blahM := blahT.Methods["BlahFunc"] 558 if e, a := test.expected, blahM.CommentLines; !reflect.DeepEqual(e, a) { 559 t.Errorf("method comment wrong, wanted %q, got %q", e, a) 560 } 561 } 562 563 signatureTestCases := []struct { 564 testFile file 565 expected []string 566 }{ 567 { 568 testFile: file{ 569 path: fileName, contents: ` 570 package foo 571 572 type Blah struct { 573 a int 574 } 575 576 // Method1 CommentLines. 577 func (b *Blah) Method1(sameArg int) {} 578 579 // Method2 CommentLines. 580 func (b *Blah) Method2(sameArg int) {} 581 `}, 582 }, 583 { 584 testFile: file{ 585 path: fileName, contents: ` 586 package foo 587 588 type Blah interface { 589 // Method1 CommentLines. 590 Method1(sameArg int) error 591 592 // Method2 CommentLines. 593 Method2(sameArg int) error 594 } 595 `}, 596 }, 597 } 598 for _, test := range signatureTestCases { 599 _, u, o := construct(t, []file{test.testFile}, namer.NewPublicNamer(0)) 600 t.Logf("%#v", o) 601 blahT := u.Type(types.Name{Package: "base/foo/proto", Name: "Blah"}) 602 blahM1 := blahT.Methods["Method1"] 603 blahM2 := blahT.Methods["Method2"] 604 c1 := blahM1.CommentLines 605 c2 := blahM2.CommentLines 606 if reflect.DeepEqual(c1, c2) { 607 t.Errorf("same signature method comment got equal, %v == %v", c1, c2) 608 } 609 } 610 } 611 612 func TestParseConstantCommentLines(t *testing.T) { 613 testFile := file{ 614 path: "base/foo/proto/foo.go", 615 contents: ` 616 package foo 617 618 // FooString is a string of foo. 619 type FooString string 620 621 // FooStringOne is one foo. 622 const FooStringOne FooString = "One" 623 624 // An important integer. 625 // This one is nine. 626 const OtherInt = 9 627 `, 628 } 629 630 expectComment := func(obj *types.Type, lines []string) { 631 t.Helper() 632 if !reflect.DeepEqual(obj.CommentLines, lines) { 633 t.Errorf("wrong const comment for %q: wanted %q, got %q", 634 obj.Name, 635 lines, obj.CommentLines, 636 ) 637 } 638 } 639 640 _, u, _ := construct(t, []file{testFile}, namer.NewPublicNamer(0)) 641 642 expectComment( 643 u.Constant(types.Name{Package: "base/foo/proto", Name: "FooStringOne"}), 644 []string{"FooStringOne is one foo."}, 645 ) 646 647 expectComment( 648 u.Constant(types.Name{Package: "base/foo/proto", Name: "OtherInt"}), 649 []string{"An important integer.", "This one is nine."}, 650 ) 651 } 652 653 func TestTypeKindParse(t *testing.T) { 654 var testFiles = []file{ 655 {path: "a/foo.go", contents: "package a\ntype Test string\n"}, 656 {path: "b/foo.go", contents: "package b\ntype Test map[int]string\n"}, 657 {path: "c/foo.go", contents: "package c\ntype Test []string\n"}, 658 {path: "d/foo.go", contents: "package d\ntype Test struct{a int; b struct{a int}; c map[int]string; d *string}\n"}, 659 {path: "e/foo.go", contents: "package e\ntype Test *string\n"}, 660 {path: "f/foo.go", contents: ` 661 package f 662 import ( 663 "a" 664 "b" 665 ) 666 type Test []a.Test 667 type Test2 *a.Test 668 type Test3 map[a.Test]b.Test 669 type Test4 struct { 670 a struct {a a.Test; b b.Test} 671 b map[a.Test]b.Test 672 c *a.Test 673 d []a.Test 674 e []string 675 } 676 `}, 677 {path: "g/foo.go", contents: ` 678 package g 679 type Test func(a, b string) (c, d string) 680 func (t Test) Method(a, b string) (c, d string) { return t(a, b) } 681 type Interface interface{Method(a, b string) (c, d string)} 682 `}, 683 {path: "h/foo.go", contents: ` 684 package h 685 import "a" 686 type Test [1]a.Test 687 `}, 688 } 689 690 // Check that the right types are found, and the namers give the expected names. 691 692 assertions := []struct { 693 Package, Name string 694 k types.Kind 695 names []string 696 }{ 697 { 698 Package: "a", Name: "Test", k: types.Alias, 699 names: []string{"Test", "ATest", "test", "aTest", "a.Test"}, 700 }, 701 { 702 Package: "b", Name: "Test", k: types.Map, 703 names: []string{"Test", "BTest", "test", "bTest", "b.Test"}, 704 }, 705 { 706 Package: "c", Name: "Test", k: types.Slice, 707 names: []string{"Test", "CTest", "test", "cTest", "c.Test"}, 708 }, 709 { 710 Package: "d", Name: "Test", k: types.Struct, 711 names: []string{"Test", "DTest", "test", "dTest", "d.Test"}, 712 }, 713 { 714 Package: "e", Name: "Test", k: types.Pointer, 715 names: []string{"Test", "ETest", "test", "eTest", "e.Test"}, 716 }, 717 { 718 Package: "f", Name: "Test", k: types.Slice, 719 names: []string{"Test", "FTest", "test", "fTest", "f.Test"}, 720 }, 721 { 722 Package: "g", Name: "Test", k: types.Func, 723 names: []string{"Test", "GTest", "test", "gTest", "g.Test"}, 724 }, 725 { 726 Package: "g", Name: "Interface", k: types.Interface, 727 names: []string{"Interface", "GInterface", "interface", "gInterface", "g.Interface"}, 728 }, 729 { 730 Package: "h", Name: "Test", k: types.Array, 731 names: []string{"Test", "HTest", "test", "hTest", "h.Test"}, 732 }, 733 { 734 Package: "", Name: "string", k: types.Builtin, 735 names: []string{"String", "String", "string", "string", "string"}, 736 }, 737 { 738 Package: "", Name: "int", k: types.Builtin, 739 names: []string{"Int", "Int", "int", "int", "int"}, 740 }, 741 { 742 Package: "", Name: "struct{a int}", k: types.Struct, 743 names: []string{"StructInt", "StructInt", "structInt", "structInt", "struct{a int}"}, 744 }, 745 { 746 Package: "", Name: "struct{a a.Test; b b.Test}", k: types.Struct, 747 names: []string{"StructTestTest", "StructATestBTest", "structTestTest", "structATestBTest", "struct{a a.Test; b b.Test}"}, 748 }, 749 { 750 Package: "", Name: "map[int]string", k: types.Map, 751 names: []string{"MapIntToString", "MapIntToString", "mapIntToString", "mapIntToString", "map[int]string"}, 752 }, 753 { 754 Package: "", Name: "map[a.Test]b.Test", k: types.Map, 755 names: []string{"MapTestToTest", "MapATestToBTest", "mapTestToTest", "mapATestToBTest", "map[a.Test]b.Test"}, 756 }, 757 { 758 Package: "", Name: "[]string", k: types.Slice, 759 names: []string{"SliceString", "SliceString", "sliceString", "sliceString", "[]string"}, 760 }, 761 { 762 Package: "", Name: "[]a.Test", k: types.Slice, 763 names: []string{"SliceTest", "SliceATest", "sliceTest", "sliceATest", "[]a.Test"}, 764 }, 765 { 766 Package: "", Name: "*string", k: types.Pointer, 767 names: []string{"PointerString", "PointerString", "pointerString", "pointerString", "*string"}, 768 }, 769 { 770 Package: "", Name: "*a.Test", k: types.Pointer, 771 names: []string{"PointerTest", "PointerATest", "pointerTest", "pointerATest", "*a.Test"}, 772 }, 773 } 774 775 namers := []namer.Namer{ 776 namer.NewPublicNamer(0), 777 namer.NewPublicNamer(1), 778 namer.NewPrivateNamer(0), 779 namer.NewPrivateNamer(1), 780 namer.NewRawNamer("", nil), 781 } 782 783 for nameIndex, namer := range namers { 784 _, u, _ := construct(t, testFiles, namer) 785 t.Logf("Found types:\n") 786 for pkgName, pkg := range u { 787 for typeName, cur := range pkg.Types { 788 t.Logf("%q-%q: %s %s", pkgName, typeName, cur.Name, cur.Kind) 789 } 790 } 791 t.Logf("\n\n") 792 793 for _, item := range assertions { 794 n := types.Name{Package: item.Package, Name: item.Name} 795 thisType := u.Type(n) 796 if thisType == nil { 797 t.Errorf("type %s not found", n) 798 continue 799 } 800 underlyingType := thisType 801 if item.k != types.Alias && thisType.Kind == types.Alias { 802 underlyingType = thisType.Underlying 803 if underlyingType == nil { 804 t.Errorf("underlying type %s not found", n) 805 continue 806 } 807 } 808 if e, a := item.k, underlyingType.Kind; e != a { 809 t.Errorf("%v-%s: type kind wrong, wanted %v, got %v (%#v)", nameIndex, n, e, a, underlyingType) 810 } 811 if e, a := item.names[nameIndex], namer.Name(thisType); e != a { 812 t.Errorf("%v-%s: Expected %q, got %q", nameIndex, n, e, a) 813 } 814 } 815 816 // Also do some one-off checks 817 gtest := u.Type(types.Name{Package: "g", Name: "Test"}) 818 if e, a := 1, len(gtest.Methods); e != a { 819 t.Errorf("expected %v but found %v methods: %#v", e, a, gtest) 820 } 821 iface := u.Type(types.Name{Package: "g", Name: "Interface"}) 822 if e, a := 1, len(iface.Methods); e != a { 823 t.Errorf("expected %v but found %v methods: %#v", e, a, iface) 824 } 825 } 826 }