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  }