cuelang.org/go@v0.10.1/internal/mod/modpkgload/pkgload_test.go (about) 1 package modpkgload 2 3 import ( 4 "context" 5 "errors" 6 "fmt" 7 "io/fs" 8 "path" 9 "path/filepath" 10 "strings" 11 "testing" 12 13 "github.com/go-quicktest/qt" 14 "github.com/google/go-cmp/cmp" 15 "golang.org/x/tools/txtar" 16 17 "cuelang.org/go/internal/mod/modimports" 18 "cuelang.org/go/internal/mod/modrequirements" 19 "cuelang.org/go/mod/modfile" 20 "cuelang.org/go/mod/module" 21 ) 22 23 func TestLoadPackages(t *testing.T) { 24 files, err := filepath.Glob("testdata/*.txtar") 25 qt.Assert(t, qt.IsNil(err)) 26 for _, f := range files { 27 ar, err := txtar.ParseFile(f) 28 qt.Assert(t, qt.IsNil(err)) 29 tfs, err := txtar.FS(ar) 30 qt.Assert(t, qt.IsNil(err)) 31 reg := testRegistry{tfs} 32 testDirs, _ := fs.Glob(tfs, "test[0-9]*") 33 for _, testDir := range testDirs { 34 testName := strings.TrimSuffix(filepath.Base(f), ".txtar") 35 t.Run(testName, func(t *testing.T) { 36 t.Logf("test file: %v", f) 37 readTestFile := func(name string) string { 38 data, err := fs.ReadFile(tfs, path.Join(testDir, name)) 39 qt.Assert(t, qt.IsNil(err)) 40 return string(data) 41 } 42 43 initialRequirementsStr := strings.Fields(readTestFile("initial-requirements")) 44 mainModulePath, moduleVersions := initialRequirementsStr[0], mapSlice(initialRequirementsStr[1:], module.MustParseVersion) 45 defaultMajorVersions := make(map[string]string) 46 for _, f := range strings.Fields(readTestFile("default-major-versions")) { 47 p, v, ok := strings.Cut(f, "@") 48 qt.Assert(t, qt.IsTrue(ok)) 49 defaultMajorVersions[p] = v 50 } 51 initialRequirements := modrequirements.NewRequirements(mainModulePath, reg, moduleVersions, defaultMajorVersions) 52 53 rootPackages := strings.Fields(readTestFile("root-packages")) 54 want := readTestFile("want") 55 56 var out strings.Builder 57 printf := func(f string, a ...any) { 58 fmt.Fprintf(&out, f, a...) 59 } 60 pkgs := LoadPackages( 61 context.Background(), 62 mainModulePath, 63 module.SourceLoc{FS: tfs, Dir: "."}, 64 initialRequirements, 65 reg, 66 rootPackages, 67 func(pkgPath string, mod module.Version, fsys fs.FS, mf modimports.ModuleFile) bool { 68 return true 69 }, 70 ) 71 for _, pkg := range pkgs.All() { 72 printf("%s\n", pkg.ImportPath()) 73 printf("\tflags: %v\n", pkg.Flags()) 74 if pkg.Error() != nil { 75 printf("\terror: %v\n", pkg.Error()) 76 printf("\tmissing: %v\n", errors.As(pkg.Error(), new(*ImportMissingError))) 77 } else { 78 printf("\tmod: %v\n", pkg.Mod()) 79 for _, loc := range pkg.Locations() { 80 printf("\tlocation: %v\n", loc.Dir) 81 } 82 if imps := pkg.Imports(); len(imps) > 0 { 83 printf("\timports:\n") 84 for _, imp := range imps { 85 printf("\t\t%v\n", imp.ImportPath()) 86 } 87 } 88 } 89 } 90 if diff := cmp.Diff(string(want), out.String()); diff != "" { 91 t.Logf("actual result:\n%s", out.String()) 92 t.Fatalf("unexpected results (-want +got):\n%s", diff) 93 } 94 }) 95 } 96 } 97 } 98 99 type testRegistry struct { 100 fs fs.FS 101 } 102 103 func (r testRegistry) Fetch(ctx context.Context, m module.Version) (module.SourceLoc, error) { 104 mpath := r.modpath(m) 105 info, err := fs.Stat(r.fs, mpath) 106 if err != nil || !info.IsDir() { 107 return module.SourceLoc{}, fmt.Errorf("module %v not found at %v", m, mpath) 108 } 109 return module.SourceLoc{ 110 FS: r.fs, 111 Dir: mpath, 112 }, nil 113 } 114 115 func (r testRegistry) Requirements(ctx context.Context, m module.Version) ([]module.Version, error) { 116 mpath := path.Join(r.modpath(m), "cue.mod/module.cue") 117 data, err := fs.ReadFile(r.fs, mpath) 118 if err != nil { 119 return nil, err 120 } 121 mf, err := modfile.Parse(data, mpath) 122 if err != nil { 123 return nil, fmt.Errorf("cannot parse module file from %v: %v", m, err) 124 } 125 return mf.DepVersions(), nil 126 } 127 128 func (r testRegistry) modpath(m module.Version) string { 129 mpath, _, _ := module.SplitPathVersion(m.Path()) 130 return path.Join("_registry", strings.ReplaceAll(mpath, "/", "_")+"_"+m.Version()) 131 } 132 133 func mapSlice[From, To any](ss []From, f func(From) To) []To { 134 ts := make([]To, len(ss)) 135 for i := range ss { 136 ts[i] = f(ss[i]) 137 } 138 return ts 139 }