cuelang.org/go@v0.10.1/internal/buildattr/buildattr_test.go (about) 1 package buildattr 2 3 import ( 4 "testing" 5 6 "cuelang.org/go/cue/errors" 7 "cuelang.org/go/cue/format" 8 "cuelang.org/go/cue/parser" 9 10 "github.com/go-quicktest/qt" 11 ) 12 13 var shouldBuildFileTests = []struct { 14 testName string 15 syntax string 16 tags map[string]bool 17 wantOK bool 18 wantAttr string 19 wantError string 20 wantTagCalls map[string]bool 21 }{{ 22 testName: "EmptyFile", 23 syntax: "", 24 wantOK: true, 25 }, { 26 testName: "PackageWithIf", 27 syntax: ` 28 @if(foo) 29 30 package something 31 `, 32 wantOK: false, 33 wantTagCalls: map[string]bool{"foo": true}, 34 wantAttr: "@if(foo)", 35 }, { 36 testName: "PackageWithComments", 37 syntax: ` 38 39 // Some comment 40 41 @if(foo) 42 43 // Other comment 44 45 package something 46 `, 47 wantOK: false, 48 wantTagCalls: map[string]bool{"foo": true}, 49 wantAttr: "@if(foo)", 50 }, { 51 testName: "PackageWithIfSuccess", 52 syntax: ` 53 @if(foo) 54 55 package something 56 `, 57 tags: map[string]bool{"foo": true}, 58 wantOK: true, 59 wantTagCalls: map[string]bool{"foo": true}, 60 wantAttr: "@if(foo)", 61 }, { 62 testName: "PackageWithIfAfterPackageClause", 63 syntax: ` 64 package something 65 66 @if(foo) 67 `, 68 wantOK: true, 69 }, { 70 testName: "InvalidExpr", 71 syntax: ` 72 @if(foo + bar) 73 74 package something 75 `, 76 wantOK: false, 77 wantAttr: "@if(foo + bar)", 78 wantError: `invalid operator \+ in build attribute 79 `, 80 }, { 81 testName: "MultipleIfAttributes", 82 syntax: ` 83 84 @if(foo) 85 @if(bar) 86 87 package something 88 `, 89 wantOK: false, 90 wantAttr: "@if(foo)", 91 wantError: `previous declaration here: 92 testfile.cue:3:1 93 multiple @if attributes: 94 testfile.cue:4:1 95 `, 96 }, { 97 testName: "MultipleIfAttributesWithOneAfterPackage", 98 syntax: ` 99 100 @if(foo) 101 102 package something 103 104 @if(bar) 105 `, 106 wantOK: false, 107 wantAttr: "@if(foo)", 108 wantTagCalls: map[string]bool{"foo": true}, 109 }, { 110 testName: "And#0", 111 syntax: ` 112 @if(foo && bar) 113 114 package something 115 `, 116 wantOK: false, 117 wantAttr: "@if(foo && bar)", 118 wantTagCalls: map[string]bool{ 119 "foo": true, 120 "bar": true, 121 }, 122 }, { 123 testName: "And#1", 124 syntax: ` 125 @if(foo && bar) 126 127 package something 128 `, 129 tags: map[string]bool{"foo": true}, 130 wantOK: false, 131 wantAttr: "@if(foo && bar)", 132 wantTagCalls: map[string]bool{ 133 "foo": true, 134 "bar": true, 135 }, 136 }, { 137 testName: "And#2", 138 syntax: ` 139 @if(foo && bar) 140 141 package something 142 `, 143 tags: map[string]bool{"bar": true}, 144 wantOK: false, 145 wantAttr: "@if(foo && bar)", 146 wantTagCalls: map[string]bool{ 147 "foo": true, 148 "bar": true, 149 }, 150 }, { 151 testName: "And#3", 152 syntax: ` 153 @if(foo && bar) 154 155 package something 156 `, 157 tags: map[string]bool{"foo": true, "bar": true}, 158 wantOK: true, 159 wantAttr: "@if(foo && bar)", 160 wantTagCalls: map[string]bool{ 161 "foo": true, 162 "bar": true, 163 }, 164 }, { 165 testName: "Or#0", 166 syntax: ` 167 @if(foo || bar) 168 169 package something 170 `, 171 wantOK: false, 172 wantAttr: "@if(foo || bar)", 173 wantTagCalls: map[string]bool{ 174 "foo": true, 175 "bar": true, 176 }, 177 }, { 178 testName: "Or#1", 179 syntax: ` 180 @if(foo || bar) 181 182 package something 183 `, 184 tags: map[string]bool{"foo": true}, 185 wantOK: true, 186 wantAttr: "@if(foo || bar)", 187 wantTagCalls: map[string]bool{ 188 "foo": true, 189 "bar": true, 190 }, 191 }, { 192 testName: "Or#2", 193 syntax: ` 194 @if(foo || bar) 195 196 package something 197 `, 198 tags: map[string]bool{"bar": true}, 199 wantOK: true, 200 wantAttr: "@if(foo || bar)", 201 wantTagCalls: map[string]bool{ 202 "foo": true, 203 "bar": true, 204 }, 205 }, { 206 testName: "Or#3", 207 syntax: ` 208 @if(foo || bar) 209 210 package something 211 `, 212 tags: map[string]bool{"foo": true, "bar": true}, 213 wantOK: true, 214 wantAttr: "@if(foo || bar)", 215 wantTagCalls: map[string]bool{ 216 "foo": true, 217 "bar": true, 218 }, 219 }, { 220 testName: "Not#0", 221 syntax: ` 222 @if(!foo) 223 224 package something 225 `, 226 wantOK: true, 227 wantAttr: "@if(!foo)", 228 wantTagCalls: map[string]bool{ 229 "foo": true, 230 }, 231 }, { 232 testName: "Not#1", 233 syntax: ` 234 @if(!foo) 235 236 package something 237 `, 238 tags: map[string]bool{"foo": true}, 239 wantOK: false, 240 wantAttr: "@if(!foo)", 241 wantTagCalls: map[string]bool{ 242 "foo": true, 243 }, 244 }, { 245 testName: "ComplexExpr", 246 syntax: ` 247 @if(foo || (!bar && baz)) 248 249 package something 250 `, 251 tags: map[string]bool{ 252 "baz": true, 253 }, 254 wantOK: true, 255 wantTagCalls: map[string]bool{ 256 "foo": true, 257 "bar": true, 258 "baz": true, 259 }, 260 wantAttr: "@if(foo || (!bar && baz))", 261 }, { 262 testName: "IgnoreOnly", 263 syntax: ` 264 @ignore() 265 266 package something 267 `, 268 wantOK: false, 269 wantAttr: "@ignore()", 270 }, { 271 testName: "IgnoreWithBuildAttrs", 272 syntax: ` 273 @ignore() 274 @if(blah) 275 276 package something 277 `, 278 wantOK: false, 279 wantAttr: "@ignore()", 280 }, { 281 // It's arguable whether multiple @if attributes 282 // should be an error when there's an @ignore 283 // attribute, but it's easily worked around by 284 // putting the @ignore attribute first, which should 285 // be fairly intuitive. 286 testName: "IgnoreWithMultipleEarlierIfs", 287 syntax: ` 288 @if(foo) 289 @if(bar) 290 @ignore() 291 292 package something 293 `, 294 wantOK: false, 295 wantError: `previous declaration here: 296 testfile.cue:2:1 297 multiple @if attributes: 298 testfile.cue:3:1 299 `, 300 wantAttr: "@if(foo)", 301 }, { 302 testName: "IgnoreWithMultipleLaterIfs", 303 syntax: ` 304 @ignore() 305 @if(foo) 306 @if(bar) 307 308 package something 309 `, 310 wantOK: false, 311 wantAttr: "@ignore()", 312 }, { 313 testName: "IgnoreWithoutPackageClause", 314 syntax: ` 315 @ignore() 316 a: 5 317 `, 318 wantOK: false, 319 wantAttr: "@ignore()", 320 }, { 321 testName: "IfAfterDeclaration", 322 syntax: ` 323 a: 1 324 @if(foo) 325 `, 326 wantOK: true, 327 }} 328 329 func TestShouldBuildFile(t *testing.T) { 330 for _, test := range shouldBuildFileTests { 331 t.Run(test.testName, func(t *testing.T) { 332 f, err := parser.ParseFile("testfile.cue", test.syntax) 333 qt.Assert(t, qt.IsNil(err)) 334 tagsUsed := make(map[string]bool) 335 ok, attr, err := ShouldBuildFile(f, func(tag string) bool { 336 tagsUsed[tag] = true 337 return test.tags[tag] 338 }) 339 qt.Check(t, qt.Equals(ok, test.wantOK)) 340 if test.wantAttr == "" { 341 qt.Assert(t, qt.IsNil(attr)) 342 } else { 343 qt.Assert(t, qt.Not(qt.IsNil(attr))) 344 attrStr, err := format.Node(attr) 345 qt.Assert(t, qt.IsNil(err)) 346 qt.Assert(t, qt.Equals(string(attrStr), test.wantAttr)) 347 } 348 if test.wantError != "" { 349 qt.Assert(t, qt.Not(qt.IsNil(err))) 350 qt.Assert(t, qt.Matches(errors.Details(err, nil), test.wantError)) 351 qt.Assert(t, qt.Equals(ok, false)) 352 return 353 } 354 qt.Assert(t, qt.IsNil(err)) 355 if len(tagsUsed) == 0 { 356 tagsUsed = nil 357 } 358 qt.Check(t, qt.DeepEquals(tagsUsed, test.wantTagCalls)) 359 }) 360 } 361 }