1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package modfile
16
17 import (
18 "strings"
19 "testing"
20
21 "github.com/go-quicktest/qt"
22 "github.com/google/go-cmp/cmp/cmpopts"
23
24 "cuelang.org/go/cue/errors"
25 "cuelang.org/go/internal/cuetest"
26 "cuelang.org/go/mod/module"
27 )
28
29 var parseTests = []struct {
30 testName string
31 parse func(modfile []byte, filename string) (*File, error)
32 data string
33 wantError string
34 want *File
35 wantVersions []module.Version
36 wantDefaults map[string]string
37 }{{
38 testName: "NoDeps",
39 parse: Parse,
40 data: `
41 module: "foo.com/bar@v0"
42 `,
43 want: &File{
44 Module: "foo.com/bar@v0",
45 },
46 wantDefaults: map[string]string{
47 "foo.com/bar": "v0",
48 },
49 }, {
50 testName: "WithDeps",
51 parse: Parse,
52 data: `
53 language: version: "v0.4.3"
54 module: "foo.com/bar@v0"
55 deps: "example.com@v1": {
56 default: true
57 v: "v1.2.3"
58 }
59 deps: "other.com/something@v0": v: "v0.2.3"
60 `,
61 want: &File{
62 Language: &Language{
63 Version: "v0.4.3",
64 },
65 Module: "foo.com/bar@v0",
66 Deps: map[string]*Dep{
67 "example.com@v1": {
68 Default: true,
69 Version: "v1.2.3",
70 },
71 "other.com/something@v0": {
72 Version: "v0.2.3",
73 },
74 },
75 },
76 wantVersions: parseVersions("example.com@v1.2.3", "other.com/something@v0.2.3"),
77 wantDefaults: map[string]string{
78 "foo.com/bar": "v0",
79 "example.com": "v1",
80 },
81 }, {
82 testName: "AmbiguousDefaults",
83 parse: Parse,
84 data: `
85 module: "foo.com/bar@v0"
86 deps: "example.com@v1": {
87 default: true
88 v: "v1.2.3"
89 }
90 deps: "example.com@v2": {
91 default: true
92 v: "v2.0.0"
93 }
94 `,
95 wantError: `multiple default major versions found for example.com`,
96 }, {
97 testName: "AmbiguousDefaultsWithMainModule",
98 parse: Parse,
99 data: `
100 module: "foo.com/bar@v0"
101 deps: "foo.com/bar@v1": {
102 default: true
103 v: "v1.2.3"
104 }
105 `,
106 wantError: `multiple default major versions found for foo.com/bar`,
107 }, {
108 testName: "MisspelledLanguageVersionField",
109 parse: Parse,
110 data: `
111 langugage: version: "v0.4.3"
112 module: "foo.com/bar@v0"
113 `,
114 wantError: `langugage: field not allowed:
115 cuelang.org/go/mod/modfile/schema.cue:28:8
116 cuelang.org/go/mod/modfile/schema.cue:30:2
117 module.cue:2:1`,
118 }, {
119 testName: "InvalidLanguageVersion",
120 parse: Parse,
121 data: `
122 language: version: "vblah"
123 module: "foo.com/bar@v0"`,
124 wantError: `language version "vblah" in module.cue is not well formed`,
125 }, {
126 testName: "EmptyLanguageVersion",
127 parse: Parse,
128 data: `
129 language: {}
130 module: "foo.com/bar@v0"`,
131 wantError: `language version "" in module.cue is not well formed`,
132 }, {
133 testName: "NonCanonicalLanguageVersion",
134 parse: Parse,
135 data: `
136 module: "foo.com/bar@v0"
137 language: version: "v0.8"
138 `,
139 wantError: `language version v0.8 in module.cue is not canonical`,
140 }, {
141 testName: "InvalidDepVersion",
142 parse: Parse,
143 data: `
144 module: "foo.com/bar@v1"
145 deps: "example.com@v1": v: "1.2.3"
146 `,
147 wantError: `invalid module.cue file module.cue: cannot make version from module "example.com@v1", version "1.2.3": version "1.2.3" \(of module "example.com@v1"\) is not well formed`,
148 }, {
149 testName: "NonCanonicalVersion",
150 parse: Parse,
151 data: `
152 module: "foo.com/bar@v1"
153 deps: "example.com@v1": v: "v1.2"
154 `,
155 wantError: `invalid module.cue file module.cue: cannot make version from module "example.com@v1", version "v1.2": version "v1.2" \(of module "example.com@v1"\) is not canonical`,
156 }, {
157 testName: "NonCanonicalModule",
158 parse: Parse,
159 data: `
160 module: "foo.com/bar"
161 `,
162 wantError: `module path "foo.com/bar" in module.cue does not contain major version`,
163 }, {
164 testName: "NonCanonicalDep",
165 parse: Parse,
166 data: `
167 module: "foo.com/bar@v1"
168 deps: "example.com": v: "v1.2.3"
169 `,
170 wantError: `invalid module.cue file module.cue: no major version in "example.com"`,
171 }, {
172 testName: "MismatchedMajorVersion",
173 parse: Parse,
174 data: `
175 module: "foo.com/bar@v1"
176 deps: "example.com@v1": v: "v0.1.2"
177 `,
178 wantError: `invalid module.cue file module.cue: cannot make version from module "example.com@v1", version "v0.1.2": mismatched major version suffix in "example.com@v1" \(version v0.1.2\)`,
179 }, {
180 testName: "NonStrictNoMajorVersions",
181 parse: ParseNonStrict,
182 data: `
183 module: "foo.com/bar"
184 deps: "example.com": v: "v1.2.3"
185 `,
186 want: &File{
187 Module: "foo.com/bar@v0",
188 Deps: map[string]*Dep{
189 "example.com": {
190 Version: "v1.2.3",
191 },
192 },
193 },
194 wantVersions: parseVersions("example.com@v1.2.3"),
195 wantDefaults: map[string]string{
196 "foo.com/bar": "v0",
197 },
198 }, {
199 testName: "LegacyWithExtraFields",
200 parse: ParseLegacy,
201 data: `
202 module: "foo.com/bar"
203 something: 4
204 cue: lang: "xxx"
205 `,
206 want: &File{
207 Module: "foo.com/bar",
208 },
209 }}
210
211 func TestParse(t *testing.T) {
212 for _, test := range parseTests {
213 t.Run(test.testName, func(t *testing.T) {
214 f, err := test.parse([]byte(test.data), "module.cue")
215 if test.wantError != "" {
216 gotErr := strings.TrimSuffix(errors.Details(err, nil), "\n")
217 qt.Assert(t, qt.Matches(gotErr, test.wantError))
218 return
219 }
220 qt.Assert(t, qt.IsNil(err), qt.Commentf("details: %v", strings.TrimSuffix(errors.Details(err, nil), "\n")))
221 qt.Assert(t, qt.CmpEquals(f, test.want, cmpopts.IgnoreUnexported(File{})))
222 qt.Assert(t, qt.DeepEquals(f.DepVersions(), test.wantVersions))
223 qt.Assert(t, qt.DeepEquals(f.DefaultMajorVersions(), test.wantDefaults))
224 })
225 }
226 }
227
228 func TestFormat(t *testing.T) {
229 type formatTest struct {
230 name string
231 file *File
232 wantError string
233 want string
234 }
235 tests := []formatTest{{
236 name: "WithLanguage",
237 file: &File{
238 Language: &Language{
239 Version: "v0.4.3",
240 },
241 Module: "foo.com/bar@v0",
242 Deps: map[string]*Dep{
243 "example.com@v1": {
244 Version: "v1.2.3",
245 },
246 "other.com/something@v0": {
247 Version: "v0.2.3",
248 },
249 },
250 },
251 want: `module: "foo.com/bar@v0"
252 language: {
253 version: "v0.4.3"
254 }
255 deps: {
256 "example.com@v1": {
257 v: "v1.2.3"
258 }
259 "other.com/something@v0": {
260 v: "v0.2.3"
261 }
262 }
263 `}, {
264 name: "WithoutLanguage",
265 file: &File{
266 Module: "foo.com/bar@v0",
267 Language: &Language{
268 Version: "v0.4.3",
269 },
270 },
271 want: `module: "foo.com/bar@v0"
272 language: {
273 version: "v0.4.3"
274 }
275 `}, {
276 name: "WithInvalidModuleVersion",
277 file: &File{
278 Module: "foo.com/bar@v0",
279 Language: &Language{
280 Version: "badversion--",
281 },
282 },
283 wantError: `cannot round-trip module file: language version "badversion--" in - is not well formed`,
284 }, {
285 name: "WithNonNilEmptyDeps",
286 file: &File{
287 Module: "foo.com/bar@v0",
288 Deps: map[string]*Dep{},
289 },
290 want: `module: "foo.com/bar@v0"
291 `,
292 }}
293 cuetest.Run(t, tests, func(t *cuetest.T, test *formatTest) {
294 data, err := test.file.Format()
295 if test.wantError != "" {
296 qt.Assert(t, qt.ErrorMatches(err, test.wantError))
297 return
298 }
299 qt.Assert(t, qt.IsNil(err))
300 t.Equal(string(data), test.want)
301
302
303 f, err := Parse(data, "")
304 qt.Assert(t, qt.IsNil(err))
305 qt.Assert(t, qt.CmpEquals(f, test.file, cmpopts.IgnoreUnexported(File{}), cmpopts.EquateEmpty()))
306 })
307 }
308
309 func parseVersions(vs ...string) []module.Version {
310 vvs := make([]module.Version, 0, len(vs))
311 for _, v := range vs {
312 vvs = append(vvs, module.MustParseVersion(v))
313 }
314 return vvs
315 }
316
View as plain text