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 gccgoimporter 6 7 import ( 8 "go/types" 9 "internal/testenv" 10 "io/ioutil" 11 "os" 12 "os/exec" 13 "path/filepath" 14 "runtime" 15 "testing" 16 ) 17 18 type importerTest struct { 19 pkgpath, name, want, wantval string 20 wantinits []string 21 } 22 23 func runImporterTest(t *testing.T, imp Importer, initmap map[*types.Package]InitData, test *importerTest) { 24 pkg, err := imp(make(map[string]*types.Package), test.pkgpath) 25 if err != nil { 26 t.Error(err) 27 return 28 } 29 30 if test.name != "" { 31 obj := pkg.Scope().Lookup(test.name) 32 if obj == nil { 33 t.Errorf("%s: object not found", test.name) 34 return 35 } 36 37 got := types.ObjectString(obj, types.RelativeTo(pkg)) 38 if got != test.want { 39 t.Errorf("%s: got %q; want %q", test.name, got, test.want) 40 } 41 42 if test.wantval != "" { 43 gotval := obj.(*types.Const).Val().String() 44 if gotval != test.wantval { 45 t.Errorf("%s: got val %q; want val %q", test.name, gotval, test.wantval) 46 } 47 } 48 } 49 50 if len(test.wantinits) > 0 { 51 initdata := initmap[pkg] 52 found := false 53 // Check that the package's own init function has the package's priority 54 for _, pkginit := range initdata.Inits { 55 if pkginit.InitFunc == test.wantinits[0] { 56 if initdata.Priority != pkginit.Priority { 57 t.Errorf("%s: got self priority %d; want %d", test.pkgpath, pkginit.Priority, initdata.Priority) 58 } 59 found = true 60 break 61 } 62 } 63 64 if !found { 65 t.Errorf("%s: could not find expected function %q", test.pkgpath, test.wantinits[0]) 66 } 67 68 // Each init function in the list other than the first one is a 69 // dependency of the function immediately before it. Check that 70 // the init functions appear in descending priority order. 71 priority := initdata.Priority 72 for _, wantdepinit := range test.wantinits[1:] { 73 found = false 74 for _, pkginit := range initdata.Inits { 75 if pkginit.InitFunc == wantdepinit { 76 if priority <= pkginit.Priority { 77 t.Errorf("%s: got dep priority %d; want less than %d", test.pkgpath, pkginit.Priority, priority) 78 } 79 found = true 80 priority = pkginit.Priority 81 break 82 } 83 } 84 85 if !found { 86 t.Errorf("%s: could not find expected function %q", test.pkgpath, wantdepinit) 87 } 88 } 89 } 90 } 91 92 var importerTests = [...]importerTest{ 93 {pkgpath: "pointer", name: "Int8Ptr", want: "type Int8Ptr *int8"}, 94 {pkgpath: "complexnums", name: "NN", want: "const NN untyped complex", wantval: "(-1/1 + -1/1i)"}, 95 {pkgpath: "complexnums", name: "NP", want: "const NP untyped complex", wantval: "(-1/1 + 1/1i)"}, 96 {pkgpath: "complexnums", name: "PN", want: "const PN untyped complex", wantval: "(1/1 + -1/1i)"}, 97 {pkgpath: "complexnums", name: "PP", want: "const PP untyped complex", wantval: "(1/1 + 1/1i)"}, 98 // TODO: enable this entry once bug has been tracked down 99 //{pkgpath: "imports", wantinits: []string{"imports..import", "fmt..import", "math..import"}}, 100 } 101 102 func TestGoxImporter(t *testing.T) { 103 testenv.MustHaveGoBuild(t) 104 105 initmap := make(map[*types.Package]InitData) 106 imp := GetImporter([]string{"testdata"}, initmap) 107 108 for _, test := range importerTests { 109 runImporterTest(t, imp, initmap, &test) 110 } 111 } 112 113 func TestObjImporter(t *testing.T) { 114 testenv.MustHaveGoBuild(t) 115 116 // This test relies on gccgo being around, which it most likely will be if we 117 // were compiled with gccgo. 118 if runtime.Compiler != "gccgo" { 119 t.Skip("This test needs gccgo") 120 return 121 } 122 123 tmpdir, err := ioutil.TempDir("", "") 124 if err != nil { 125 t.Fatal(err) 126 } 127 initmap := make(map[*types.Package]InitData) 128 imp := GetImporter([]string{tmpdir}, initmap) 129 130 artmpdir, err := ioutil.TempDir("", "") 131 if err != nil { 132 t.Fatal(err) 133 } 134 arinitmap := make(map[*types.Package]InitData) 135 arimp := GetImporter([]string{artmpdir}, arinitmap) 136 137 for _, test := range importerTests { 138 gofile := filepath.Join("testdata", test.pkgpath+".go") 139 ofile := filepath.Join(tmpdir, test.pkgpath+".o") 140 afile := filepath.Join(artmpdir, "lib"+test.pkgpath+".a") 141 142 cmd := exec.Command("gccgo", "-fgo-pkgpath="+test.pkgpath, "-c", "-o", ofile, gofile) 143 out, err := cmd.CombinedOutput() 144 if err != nil { 145 t.Logf("%s", out) 146 t.Fatalf("gccgo %s failed: %s", gofile, err) 147 } 148 149 runImporterTest(t, imp, initmap, &test) 150 151 cmd = exec.Command("ar", "cr", afile, ofile) 152 out, err = cmd.CombinedOutput() 153 if err != nil { 154 t.Logf("%s", out) 155 t.Fatalf("ar cr %s %s failed: %s", afile, ofile, err) 156 } 157 158 runImporterTest(t, arimp, arinitmap, &test) 159 160 if err = os.Remove(ofile); err != nil { 161 t.Fatal(err) 162 } 163 if err = os.Remove(afile); err != nil { 164 t.Fatal(err) 165 } 166 } 167 168 if err = os.Remove(tmpdir); err != nil { 169 t.Fatal(err) 170 } 171 } 172