github.com/gopherjs/gopherjs@v1.19.0-beta1.0.20240506212314-27071a8796e4/build/context_test.go (about) 1 package build 2 3 import ( 4 "fmt" 5 "go/build" 6 "net/http" 7 "path/filepath" 8 "strings" 9 "testing" 10 11 "github.com/google/go-cmp/cmp" 12 "github.com/google/go-cmp/cmp/cmpopts" 13 "github.com/gopherjs/gopherjs/compiler/gopherjspkg" 14 "golang.org/x/tools/go/buildutil" 15 ) 16 17 func init() { 18 gopherjspkg.RegisterFS(http.Dir("..")) 19 } 20 21 func TestSimpleCtx(t *testing.T) { 22 e := DefaultEnv() 23 24 gopherjsRoot := filepath.Join(e.GOROOT, "src", "github.com", "gopherjs", "gopherjs") 25 fs := &withPrefix{gopherjspkg.FS, gopherjsRoot} 26 ec := embeddedCtx(fs, e) 27 ec.bctx.JoinPath = filepath.Join // Avoid diffs in the test on Windows. 28 29 gc := goCtx(e) 30 31 t.Run("exists", func(t *testing.T) { 32 tests := []struct { 33 buildCtx XContext 34 wantPkg *PackageData 35 }{ 36 { 37 buildCtx: ec, 38 wantPkg: &PackageData{ 39 Package: expectedPackage(&ec.bctx, "github.com/gopherjs/gopherjs/js", "wasm"), 40 IsVirtual: true, 41 }, 42 }, { 43 buildCtx: gc, 44 wantPkg: &PackageData{ 45 Package: expectedPackage(&gc.bctx, "fmt", "wasm"), 46 IsVirtual: false, 47 }, 48 }, 49 } 50 51 for _, test := range tests { 52 t.Run(fmt.Sprintf("%T", test.buildCtx), func(t *testing.T) { 53 importPath := test.wantPkg.ImportPath 54 got, err := test.buildCtx.Import(importPath, "", build.FindOnly) 55 if err != nil { 56 t.Fatalf("ec.Import(%q) returned error: %s. Want: no error.", importPath, err) 57 } 58 if diff := cmp.Diff(test.wantPkg, got, cmpopts.IgnoreUnexported(*got)); diff != "" { 59 t.Errorf("ec.Import(%q) returned diff (-want,+got):\n%s", importPath, diff) 60 } 61 }) 62 } 63 }) 64 65 t.Run("not found", func(t *testing.T) { 66 tests := []struct { 67 buildCtx XContext 68 importPath string 69 }{ 70 { 71 buildCtx: ec, 72 importPath: "package/not/found", 73 }, { 74 // Outside of the main module. 75 buildCtx: gc, 76 importPath: "package/not/found", 77 }, { 78 // In the main module. 79 buildCtx: gc, 80 importPath: "github.com/gopherjs/gopherjs/not/found", 81 }, 82 } 83 84 for _, test := range tests { 85 t.Run(fmt.Sprintf("%T", test.buildCtx), func(t *testing.T) { 86 _, err := ec.Import(test.importPath, "", build.FindOnly) 87 want := "cannot find package" 88 if err == nil || !strings.Contains(err.Error(), want) { 89 t.Errorf("ec.Import(%q) returned error: %s. Want error containing %q.", test.importPath, err, want) 90 } 91 }) 92 } 93 }) 94 } 95 96 func TestChainedCtx(t *testing.T) { 97 // Construct a chained context of two fake contexts so that we could verify 98 // fallback behavior. 99 cc := chainedCtx{ 100 primary: simpleCtx{ 101 bctx: *buildutil.FakeContext(map[string]map[string]string{ 102 "primaryonly": {"po.go": "package primaryonly"}, 103 "both": {"both.go": "package both"}, 104 }), 105 isVirtual: false, 106 }, 107 secondary: simpleCtx{ 108 bctx: *buildutil.FakeContext(map[string]map[string]string{ 109 "both": {"both_secondary.go": "package both"}, 110 "secondaryonly": {"so.go": "package secondaryonly"}, 111 }), 112 isVirtual: true, 113 }, 114 } 115 116 tests := []struct { 117 importPath string 118 wantFromPrimary bool 119 }{ 120 { 121 importPath: "primaryonly", 122 wantFromPrimary: true, 123 }, { 124 importPath: "both", 125 wantFromPrimary: true, 126 }, { 127 importPath: "secondaryonly", 128 wantFromPrimary: false, 129 }, 130 } 131 132 for _, test := range tests { 133 t.Run(test.importPath, func(t *testing.T) { 134 pkg, err := cc.Import(test.importPath, "", 0) 135 if err != nil { 136 t.Errorf("cc.Import() returned error: %v. Want: no error.", err) 137 } 138 gotFromPrimary := !pkg.IsVirtual 139 if gotFromPrimary != test.wantFromPrimary { 140 t.Errorf("Got package imported from primary: %t. Want: %t.", gotFromPrimary, test.wantFromPrimary) 141 } 142 }) 143 } 144 } 145 146 func TestIsStd(t *testing.T) { 147 realGOROOT := goCtx(DefaultEnv()) 148 overlayGOROOT := overlayCtx(DefaultEnv()) 149 gopherjsPackages := gopherjsCtx(DefaultEnv()) 150 tests := []struct { 151 descr string 152 importPath string 153 context *simpleCtx 154 want bool 155 }{ 156 { 157 descr: "real goroot, standard package", 158 importPath: "fmt", 159 context: realGOROOT, 160 want: true, 161 }, 162 { 163 descr: "real goroot, non-standard package", 164 importPath: "github.com/gopherjs/gopherjs/build", 165 context: realGOROOT, 166 want: false, 167 }, 168 { 169 descr: "real goroot, non-exiting package", 170 importPath: "does/not/exist", 171 context: realGOROOT, 172 want: false, 173 }, 174 { 175 descr: "overlay goroot, standard package", 176 importPath: "fmt", 177 context: overlayGOROOT, 178 want: true, 179 }, 180 { 181 descr: "embedded gopherjs packages, gopherjs/js package", 182 importPath: "github.com/gopherjs/gopherjs/js", 183 context: gopherjsPackages, 184 // When user's source tree doesn't contain gopherjs package (e.g. it uses 185 // syscall/js API only), we pretend that gopherjs/js package is included 186 // in the standard library. 187 want: true, 188 }, 189 } 190 191 for _, test := range tests { 192 t.Run(test.descr, func(t *testing.T) { 193 got := test.context.isStd(test.importPath, "") 194 if got != test.want { 195 t.Errorf("Got: simpleCtx.isStd(%q) = %v. Want: %v", test.importPath, got, test.want) 196 } 197 }) 198 } 199 } 200 201 func expectedPackage(bctx *build.Context, importPath string, goarch string) *build.Package { 202 targetRoot := filepath.Clean(filepath.Join(bctx.GOROOT, "pkg", bctx.GOOS+"_"+goarch)) 203 return &build.Package{ 204 Dir: filepath.Join(bctx.GOROOT, "src", importPath), 205 ImportPath: importPath, 206 Root: bctx.GOROOT, 207 SrcRoot: filepath.Join(bctx.GOROOT, "src"), 208 PkgRoot: filepath.Join(bctx.GOROOT, "pkg"), 209 PkgTargetRoot: targetRoot, 210 BinDir: filepath.Join(bctx.GOROOT, "bin"), 211 Goroot: true, 212 PkgObj: filepath.Join(targetRoot, importPath+".a"), 213 } 214 }