1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package trim
16
17 import (
18 "testing"
19
20 "cuelang.org/go/cue"
21 "cuelang.org/go/cue/ast"
22 "cuelang.org/go/cue/cuecontext"
23 "cuelang.org/go/cue/errors"
24 "cuelang.org/go/cue/format"
25 "cuelang.org/go/cue/parser"
26 "cuelang.org/go/internal/cuetxtar"
27 "golang.org/x/tools/txtar"
28 )
29
30 func TestFiles(t *testing.T) {
31 testCases := []struct {
32 name string
33 in string
34 out string
35 }{{
36 name: "optional does not remove required",
37 in: `
38 a: ["aFoo"]: 3
39 a: aFoo: _
40
41 a: {
42 {["aFoo"]: 3}
43 aFoo: _
44 }
45
46 ["aFoo"]: 3
47 aFoo: _
48 `,
49 out: `a: ["aFoo"]: 3
50 a: aFoo: _
51
52 a: {
53 {["aFoo"]: 3}
54 aFoo: _
55 }
56
57 ["aFoo"]: 3
58 aFoo: _
59 `,
60 }, {
61
62 name: "defaults can remove non-defaults",
63 in: `
64 foo: [string]: a: *1 | int
65 foo: b: a: 1
66 `,
67 out: `foo: [string]: a: *1 | int
68 foo: b: {}
69 `,
70 }, {
71 name: "remove top-level struct",
72 in: `
73 a: b: 3
74 for k, v in a {
75 c: "\(k)": v
76 }
77 c: b: 3
78
79 z: {
80
81 a: b: 3
82 for k, v in a {
83 c: "\(k)": v
84 }
85 c: b: 3
86 }
87 `,
88 out: `a: b: 3
89 for k, v in a {
90 c: "\(k)": v
91 }
92
93 z: {
94
95 a: b: 3
96 for k, v in a {
97 c: "\(k)": v
98 }
99 }
100 `,
101 }, {
102 name: "do not remove field",
103 in: `
104 {[_]: x: "hello"}
105 a: x: "hello"
106 `,
107 out: `
108 {[_]: x: "hello"}
109 a: {}
110 `,
111 }, {
112 name: "issue303",
113 in: `
114 foo: c: true
115 foo: #M
116 #M: c?: bool
117 `,
118 out: `foo: c: true
119 foo: #M
120 #M: c?: bool
121 `,
122 }, {
123 name: "remove due to simplification",
124 in: `
125 foo: [string]: {
126 t: [string]: {
127 x: >=0 & <=5
128 }
129 }
130
131 foo: multipath: {
132 t: [string]: {
133 // Combined with the other constraints, we know the value must be 5 and
134 // thus the entry below can be eliminated.
135 x: >=5 & <=8 & int
136 }
137
138 t: u: { x: 5 }
139 }
140
141 group: {
142 for k, v in foo {
143 comp: "\(k)": v
144 }
145 }
146
147 `,
148 out: `foo: [string]: {
149 t: [string]: {
150 x: >=0 & <=5
151 }
152 }
153
154 foo: multipath: {
155 t: [string]: {
156
157 x: >=5 & <=8 & int
158 }
159
160 t: u: {}
161 }
162
163 group: {
164 for k, v in foo {
165 comp: "\(k)": v
166 }
167 }
168 `,
169 }, {
170 name: "list removal",
171 in: `
172 service: [string]: {
173 ports: [{a: 1}, {a: 1}, ...{ extra: 3 }]
174 }
175 service: a: {
176 ports: [{a: 1}, {a: 1, extra: 3}, {}, { extra: 3 }]
177 }
178 `,
179 out: `service: [string]: {
180 ports: [{a: 1}, {a: 1}, ...{extra: 3}]
181 }
182 service: a: {
183 ports: [{}, {extra: 3}, {}, {}]
184 }
185 `,
186 }, {
187 name: "list removal",
188 in: `
189 service: [string]: {
190 ports: [{a: 1}, {a: 1}, ...{ extra: 3 }]
191 }
192 service: a: {
193 ports: [{a: 1}, {a: 1,}]
194 }
195 `,
196 out: `service: [string]: {
197 ports: [{a: 1}, {a: 1}, ...{extra: 3}]
198 }
199 service: a: {
200 }
201 `,
202 }, {
203 name: "do not overmark comprehension",
204 in: `
205 foo: multipath: {
206 t: [string]: { x: 5 }
207
208 // Don't remove u!
209 t: u: { x: 5 }
210 }
211
212 group: {
213 for k, v in foo {
214 comp: "\(k)": v
215 }
216 }
217
218 `,
219 out: `foo: multipath: {
220 t: [string]: {x: 5}
221
222 t: u: {}
223 }
224
225 group: {
226 for k, v in foo {
227 comp: "\(k)": v
228 }
229 }
230 `,
231 }, {
232 name: "remove implied interpolations",
233 in: `
234 foo: [string]: {
235 a: string
236 b: "--\(a)--"
237 }
238 foo: entry: {
239 a: "insert"
240 b: "--insert--"
241 }
242 `,
243 out: `foo: [string]: {
244 a: string
245 b: "--\(a)--"
246 }
247 foo: entry: {
248 a: "insert"
249 }
250 `,
251 }}
252 for _, tc := range testCases {
253 t.Run(tc.name, func(t *testing.T) {
254 f, err := parser.ParseFile("test", tc.in)
255 if err != nil {
256 t.Fatal(err)
257 }
258 r := cuecontext.New()
259 v := r.BuildFile(f)
260 if err := v.Err(); err != nil {
261 t.Fatal(err)
262 }
263 err = Files([]*ast.File{f}, v, &Config{Trace: false})
264 if err != nil {
265 t.Fatal(err)
266 }
267
268 out := formatNode(t, f)
269 if got := string(out); got != tc.out {
270 t.Errorf("\ngot:\n%s\nwant:\n%s", got, tc.out)
271 }
272 })
273 }
274 }
275
276 const trace = false
277
278 func TestData(t *testing.T) {
279 test := cuetxtar.TxTarTest{
280 Root: "./testdata",
281 Name: "trim",
282 }
283
284 test.Run(t, func(t *cuetxtar.Test) {
285
286 a := t.Instance()
287 val := cuecontext.New().BuildInstance(a)
288
289
290
291 files := a.Files
292
293 err := Files(files, val, &Config{Trace: trace})
294 if err != nil {
295 t.WriteErrors(errors.Promote(err, ""))
296 }
297
298 for _, f := range files {
299 t.WriteFile(f)
300 }
301 })
302 }
303
304 func formatNode(t *testing.T, n ast.Node) []byte {
305 t.Helper()
306
307 b, err := format.Node(n)
308 if err != nil {
309 t.Fatal(err)
310 }
311 return b
312 }
313
314
315 func TestX(t *testing.T) {
316 in := `
317 -- in.cue --
318 `
319
320 t.Skip()
321
322 a := txtar.Parse([]byte(in))
323 instances := cuetxtar.Load(a, t.TempDir())
324
325 inst := cue.Build(instances)[0]
326 if inst.Err != nil {
327 t.Fatal(inst.Err)
328 }
329
330 files := instances[0].Files
331
332 Debug = true
333
334 err := Files(files, inst, &Config{
335 Trace: true,
336 })
337 if err != nil {
338 t.Fatal(err)
339 }
340
341 for _, f := range files {
342 b := formatNode(t, f)
343 t.Error(string(b))
344 }
345 }
346
View as plain text