cuelang.org/go@v0.10.1/internal/mod/modload/tidy_test.go (about) 1 package modload 2 3 import ( 4 "archive/zip" 5 "bytes" 6 "context" 7 "fmt" 8 "io" 9 "io/fs" 10 "path/filepath" 11 "strings" 12 "testing" 13 14 "cuelabs.dev/go/oci/ociregistry/ociclient" 15 "github.com/go-quicktest/qt" 16 "github.com/google/go-cmp/cmp" 17 "golang.org/x/tools/txtar" 18 19 "cuelang.org/go/internal/registrytest" 20 "cuelang.org/go/mod/modfile" 21 "cuelang.org/go/mod/modregistry" 22 "cuelang.org/go/mod/module" 23 ) 24 25 func TestTidy(t *testing.T) { 26 files, err := filepath.Glob("testdata/tidy/*.txtar") 27 qt.Assert(t, qt.IsNil(err)) 28 for _, f := range files { 29 t.Run(f, func(t *testing.T) { 30 ar, err := txtar.ParseFile(f) 31 qt.Assert(t, qt.IsNil(err)) 32 tfs, err := txtar.FS(ar) 33 qt.Assert(t, qt.IsNil(err)) 34 reg := newRegistry(t, tfs) 35 36 want, err := fs.ReadFile(tfs, "want") 37 qt.Assert(t, qt.IsNil(err)) 38 39 err = CheckTidy(context.Background(), tfs, ".", reg) 40 wantCheckTidyError := stringFromFile(tfs, "tidy-check-error") 41 if wantCheckTidyError == "" { 42 qt.Check(t, qt.IsNil(err)) 43 } else { 44 qt.Check(t, qt.ErrorMatches(err, wantCheckTidyError)) 45 } 46 47 var out strings.Builder 48 var tidyFile []byte 49 mf, err := Tidy(context.Background(), tfs, ".", reg) 50 if err != nil { 51 fmt.Fprintf(&out, "error: %v\n", err) 52 } else { 53 tidyFile, err = mf.Format() 54 qt.Assert(t, qt.IsNil(err)) 55 out.Write(tidyFile) 56 } 57 if diff := cmp.Diff(string(want), out.String()); diff != "" { 58 t.Log("actual result:\n", out.String()) 59 t.Fatalf("unexpected results (-want +got):\n%s", diff) 60 } 61 62 // Ensure that CheckTidy does not error after a successful Tidy. 63 // We make a new txtar FS given that an FS is read-only. 64 if len(tidyFile) > 0 { 65 for i := range ar.Files { 66 file := &ar.Files[i] 67 if file.Name == "cue.mod/module.cue" { 68 file.Data = []byte(out.String()) 69 } 70 } 71 tfs, err := txtar.FS(ar) 72 qt.Assert(t, qt.IsNil(err)) 73 err = CheckTidy(context.Background(), tfs, ".", reg) 74 qt.Check(t, qt.IsNil(err), qt.Commentf("CheckTidy after a successful Tidy should not fail")) 75 } 76 }) 77 } 78 } 79 80 func stringFromFile(fsys fs.FS, file string) string { 81 data, _ := fs.ReadFile(fsys, file) 82 return strings.TrimSpace(string(data)) 83 } 84 85 func newRegistry(t *testing.T, fsys fs.FS) Registry { 86 fsys, err := fs.Sub(fsys, "_registry") 87 qt.Assert(t, qt.IsNil(err)) 88 regSrv, err := registrytest.New(fsys, "") 89 qt.Assert(t, qt.IsNil(err)) 90 t.Cleanup(regSrv.Close) 91 regOCI, err := ociclient.New(regSrv.Host(), &ociclient.Options{ 92 Insecure: true, 93 }) 94 qt.Assert(t, qt.IsNil(err)) 95 return ®istryImpl{modregistry.NewClient(regOCI)} 96 } 97 98 type registryImpl struct { 99 reg *modregistry.Client 100 } 101 102 func (r *registryImpl) Requirements(ctx context.Context, mv module.Version) ([]module.Version, error) { 103 m, err := r.reg.GetModule(ctx, mv) 104 if err != nil { 105 return nil, err 106 } 107 data, err := m.ModuleFile(ctx) 108 if err != nil { 109 return nil, fmt.Errorf("cannot get module file from %v: %v", m, err) 110 } 111 mf, err := modfile.Parse(data, mv.String()) 112 if err != nil { 113 return nil, fmt.Errorf("cannot parse module file from %v: %v", m, err) 114 } 115 return mf.DepVersions(), nil 116 } 117 118 // getModContents downloads the module with the given version 119 // and returns the directory where it's stored. 120 func (c *registryImpl) Fetch(ctx context.Context, mv module.Version) (module.SourceLoc, error) { 121 m, err := c.reg.GetModule(ctx, mv) 122 if err != nil { 123 return module.SourceLoc{}, err 124 } 125 r, err := m.GetZip(ctx) 126 if err != nil { 127 return module.SourceLoc{}, err 128 } 129 defer r.Close() 130 zipData, err := io.ReadAll(r) 131 if err != nil { 132 return module.SourceLoc{}, err 133 } 134 zipr, err := zip.NewReader(bytes.NewReader(zipData), int64(len(zipData))) 135 if err != nil { 136 return module.SourceLoc{}, err 137 } 138 return module.SourceLoc{ 139 FS: zipr, 140 Dir: ".", 141 }, nil 142 } 143 144 func (r *registryImpl) ModuleVersions(ctx context.Context, mpath string) ([]string, error) { 145 versions, err := r.reg.ModuleVersions(ctx, mpath) 146 if err != nil { 147 return nil, fmt.Errorf("cannot obtain versions for module %q: %v", mpath, err) 148 } 149 return versions, nil 150 }