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