github.com/gnolang/gno@v0.0.0-20240520182011-228e9d0192ce/gnovm/pkg/gnomod/pkg_test.go (about) 1 package gnomod 2 3 import ( 4 "os" 5 "path/filepath" 6 "testing" 7 8 "github.com/gnolang/gno/tm2/pkg/testutils" 9 "github.com/stretchr/testify/assert" 10 "github.com/stretchr/testify/require" 11 ) 12 13 func TestListAndNonDraftPkgs(t *testing.T) { 14 for _, tc := range []struct { 15 desc string 16 in []struct{ name, modfile string } 17 18 outListPkgs []string 19 outNonDraftPkgs []string 20 }{ 21 { 22 desc: "no packages", 23 }, 24 { 25 desc: "no package depends on another package", 26 in: []struct{ name, modfile string }{ 27 { 28 "foo", 29 `module foo`, 30 }, 31 { 32 "bar", 33 `module bar`, 34 }, 35 { 36 "baz", 37 `module baz`, 38 }, 39 }, 40 outListPkgs: []string{"foo", "bar", "baz"}, 41 outNonDraftPkgs: []string{"foo", "bar", "baz"}, 42 }, 43 { 44 desc: "no package depends on draft package", 45 in: []struct{ name, modfile string }{ 46 { 47 "foo", 48 `module foo`, 49 }, 50 { 51 "bar", 52 `module bar 53 54 require foo v0.0.0`, 55 }, 56 { 57 "baz", 58 `module baz`, 59 }, 60 { 61 "qux", 62 `// Draft 63 64 module qux`, 65 }, 66 }, 67 outListPkgs: []string{"foo", "bar", "baz", "qux"}, 68 outNonDraftPkgs: []string{"foo", "bar", "baz"}, 69 }, 70 { 71 desc: "package directly depends on draft package", 72 in: []struct{ name, modfile string }{ 73 { 74 "foo", 75 `// Draft 76 77 module foo`, 78 }, 79 { 80 "bar", 81 `module bar 82 require foo v0.0.0`, 83 }, 84 { 85 "baz", 86 `module baz`, 87 }, 88 }, 89 outListPkgs: []string{"foo", "bar", "baz"}, 90 outNonDraftPkgs: []string{"baz"}, 91 }, 92 { 93 desc: "package indirectly depends on draft package", 94 in: []struct{ name, modfile string }{ 95 { 96 "foo", 97 `// Draft 98 99 module foo`, 100 }, 101 { 102 "bar", 103 `module bar 104 105 require foo v0.0.0`, 106 }, 107 { 108 "baz", 109 `module baz 110 111 require bar v0.0.0`, 112 }, 113 { 114 "qux", 115 `module qux`, 116 }, 117 }, 118 outListPkgs: []string{"foo", "bar", "baz", "qux"}, 119 outNonDraftPkgs: []string{"qux"}, 120 }, 121 { 122 desc: "package indirectly depends on draft package (multiple levels - 1)", 123 in: []struct{ name, modfile string }{ 124 { 125 "foo", 126 `// Draft 127 128 module foo`, 129 }, 130 { 131 "bar", 132 `module bar 133 134 require foo v0.0.0`, 135 }, 136 { 137 "baz", 138 `module baz 139 140 require bar v0.0.0`, 141 }, 142 { 143 "qux", 144 `module qux 145 146 require baz v0.0.0`, 147 }, 148 }, 149 outListPkgs: []string{"foo", "bar", "baz", "qux"}, 150 outNonDraftPkgs: []string{}, 151 }, 152 { 153 desc: "package indirectly depends on draft package (multiple levels - 2)", 154 in: []struct{ name, modfile string }{ 155 { 156 "foo", 157 `// Draft 158 159 module foo`, 160 }, 161 { 162 "bar", 163 `module bar 164 165 require qux v0.0.0`, 166 }, 167 { 168 "baz", 169 `module baz 170 171 require foo v0.0.0`, 172 }, 173 { 174 "qux", 175 `module qux 176 177 require baz v0.0.0`, 178 }, 179 }, 180 outListPkgs: []string{"foo", "bar", "baz", "qux"}, 181 outNonDraftPkgs: []string{}, 182 }, 183 } { 184 t.Run(tc.desc, func(t *testing.T) { 185 // Create test dir 186 dirPath, cleanUpFn := testutils.NewTestCaseDir(t) 187 require.NotNil(t, dirPath) 188 defer cleanUpFn() 189 190 // Create packages 191 for _, p := range tc.in { 192 createGnoModPkg(t, dirPath, p.name, p.modfile) 193 } 194 195 // List packages 196 pkgs, err := ListPkgs(dirPath) 197 require.NoError(t, err) 198 assert.Equal(t, len(tc.outListPkgs), len(pkgs)) 199 for _, p := range pkgs { 200 assert.Contains(t, tc.outListPkgs, p.Name) 201 } 202 203 // Sort packages 204 sorted, err := pkgs.Sort() 205 require.NoError(t, err) 206 207 // Non draft packages 208 nonDraft := sorted.GetNonDraftPkgs() 209 assert.Equal(t, len(tc.outNonDraftPkgs), len(nonDraft)) 210 for _, p := range nonDraft { 211 assert.Contains(t, tc.outNonDraftPkgs, p.Name) 212 } 213 }) 214 } 215 } 216 217 func createGnoModPkg(t *testing.T, dirPath, pkgName, modData string) { 218 t.Helper() 219 220 // Create package dir 221 pkgDirPath := filepath.Join(dirPath, pkgName) 222 err := os.MkdirAll(pkgDirPath, 0o755) 223 require.NoError(t, err) 224 225 // Create gno.mod 226 err = os.WriteFile(filepath.Join(pkgDirPath, "gno.mod"), []byte(modData), 0o644) 227 } 228 229 func TestSortPkgs(t *testing.T) { 230 for _, tc := range []struct { 231 desc string 232 in PkgList 233 expected []string 234 shouldErr bool 235 }{ 236 { 237 desc: "empty_input", 238 in: []Pkg{}, 239 expected: make([]string, 0), 240 }, { 241 desc: "no_dependencies", 242 in: []Pkg{ 243 {Name: "pkg1", Dir: "/path/to/pkg1", Requires: []string{}}, 244 {Name: "pkg2", Dir: "/path/to/pkg2", Requires: []string{}}, 245 {Name: "pkg3", Dir: "/path/to/pkg3", Requires: []string{}}, 246 }, 247 expected: []string{"pkg1", "pkg2", "pkg3"}, 248 }, { 249 desc: "circular_dependencies", 250 in: []Pkg{ 251 {Name: "pkg1", Dir: "/path/to/pkg1", Requires: []string{"pkg2"}}, 252 {Name: "pkg2", Dir: "/path/to/pkg2", Requires: []string{"pkg1"}}, 253 }, 254 shouldErr: true, 255 }, { 256 desc: "missing_dependencies", 257 in: []Pkg{ 258 {Name: "pkg1", Dir: "/path/to/pkg1", Requires: []string{"pkg2"}}, 259 }, 260 shouldErr: true, 261 }, { 262 desc: "valid_dependencies", 263 in: []Pkg{ 264 {Name: "pkg1", Dir: "/path/to/pkg1", Requires: []string{"pkg2"}}, 265 {Name: "pkg2", Dir: "/path/to/pkg2", Requires: []string{"pkg3"}}, 266 {Name: "pkg3", Dir: "/path/to/pkg3", Requires: []string{}}, 267 }, 268 expected: []string{"pkg3", "pkg2", "pkg1"}, 269 }, 270 } { 271 t.Run(tc.desc, func(t *testing.T) { 272 sorted, err := tc.in.Sort() 273 if tc.shouldErr { 274 assert.Error(t, err) 275 } else { 276 require.NoError(t, err) 277 for i := range tc.expected { 278 assert.Equal(t, tc.expected[i], sorted[i].Name) 279 } 280 } 281 }) 282 } 283 }