github.com/solo-io/cue@v0.4.7/cue/attribute_test.go (about) 1 // Copyright 2021 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 cue 16 17 import ( 18 "fmt" 19 "testing" 20 21 "github.com/solo-io/cue/cue/errors" 22 ) 23 24 func TestAttributes(t *testing.T) { 25 const config = ` 26 a: { 27 a: 0 @foo(a,b,c=1) 28 b: 1 @bar(a,b,c,d=1) @foo(a,,d=1) 29 } 30 b: { 31 @embed(foo) 32 3 33 } @field(foo) 34 35 ` 36 37 testCases := []struct { 38 flags AttrKind 39 path string 40 out string 41 }{{ 42 flags: FieldAttr, 43 path: "a.a", 44 out: "[@foo(a,b,c=1)]", 45 }, { 46 flags: FieldAttr, 47 path: "a.b", 48 out: "[@bar(a,b,c,d=1) @foo(a,,d=1)]", 49 }, { 50 flags: DeclAttr, 51 path: "b", 52 out: "[@embed(foo)]", 53 }, { 54 flags: FieldAttr, 55 path: "b", 56 out: "[@field(foo)]", 57 }, { 58 flags: ValueAttr, 59 path: "b", 60 out: "[@field(foo) @embed(foo)]", 61 }} 62 for _, tc := range testCases { 63 t.Run("", func(t *testing.T) { 64 v := getInstance(t, config).Value().LookupPath(ParsePath(tc.path)) 65 a := v.Attributes(tc.flags) 66 got := fmt.Sprint(a) 67 if got != tc.out { 68 t.Errorf("got %v; want %v", got, tc.out) 69 } 70 71 }) 72 } 73 } 74 75 func TestAttributeErr(t *testing.T) { 76 const config = ` 77 a: { 78 a: 0 @foo(a,b,c=1) 79 b: 1 @bar(a,b,c,d=1) @foo(a,,d=1) 80 } 81 ` 82 testCases := []struct { 83 path string 84 attr string 85 err error 86 }{{ 87 path: "a", 88 attr: "foo", 89 err: nil, 90 }, { 91 path: "a", 92 attr: "bar", 93 err: errors.New(`attribute "bar" does not exist`), 94 }, { 95 path: "xx", 96 attr: "bar", 97 err: errors.New(`attribute "bar" does not exist`), 98 }, { 99 path: "e", 100 attr: "bar", 101 err: errors.New(`attribute "bar" does not exist`), 102 }} 103 for _, tc := range testCases { 104 t.Run(tc.path+"-"+tc.attr, func(t *testing.T) { 105 v := getInstance(t, config).Value().Lookup("a", tc.path) 106 a := v.Attribute(tc.attr) 107 err := a.Err() 108 if !cmpError(err, tc.err) { 109 t.Errorf("got %v; want %v", err, tc.err) 110 } 111 }) 112 } 113 } 114 115 func TestAttributeString(t *testing.T) { 116 const config = ` 117 a: { 118 a: 0 @foo(a,b,c=1) 119 b: 1 @bar(a,b,c,d=1) @foo(a,,d=1) 120 } 121 ` 122 testCases := []struct { 123 path string 124 attr string 125 pos int 126 str string 127 err error 128 }{{ 129 path: "a", 130 attr: "foo", 131 pos: 0, 132 str: "a", 133 }, { 134 path: "a", 135 attr: "foo", 136 pos: 2, 137 str: "c=1", 138 }, { 139 path: "b", 140 attr: "bar", 141 pos: 3, 142 str: "d=1", 143 }, { 144 path: "e", 145 attr: "bar", 146 err: errors.New(`attribute "bar" does not exist`), 147 }, { 148 path: "b", 149 attr: "foo", 150 pos: 4, 151 err: errors.New("field does not exist"), 152 }} 153 for _, tc := range testCases { 154 t.Run(fmt.Sprintf("%s.%s:%d", tc.path, tc.attr, tc.pos), func(t *testing.T) { 155 v := getInstance(t, config).Value().Lookup("a", tc.path) 156 a := v.Attribute(tc.attr) 157 got, err := a.String(tc.pos) 158 if !cmpError(err, tc.err) { 159 t.Errorf("err: got %v; want %v", err, tc.err) 160 } 161 if got != tc.str { 162 t.Errorf("str: got %v; want %v", got, tc.str) 163 } 164 }) 165 } 166 } 167 168 func TestAttributeInt(t *testing.T) { 169 const config = ` 170 a: { 171 a: 0 @foo(1,3,c=1) 172 b: 1 @bar(a,-4,c,d=1) @foo(a,,d=1) 173 } 174 ` 175 testCases := []struct { 176 path string 177 attr string 178 pos int 179 val int64 180 err error 181 }{{ 182 path: "a", 183 attr: "foo", 184 pos: 0, 185 val: 1, 186 }, { 187 path: "b", 188 attr: "bar", 189 pos: 1, 190 val: -4, 191 }, { 192 path: "e", 193 attr: "bar", 194 err: errors.New(`attribute "bar" does not exist`), 195 }, { 196 path: "b", 197 attr: "foo", 198 pos: 4, 199 err: errors.New("field does not exist"), 200 }, { 201 path: "a", 202 attr: "foo", 203 pos: 2, 204 err: errors.New(`strconv.ParseInt: parsing "c=1": invalid syntax`), 205 }} 206 for _, tc := range testCases { 207 t.Run(fmt.Sprintf("%s.%s:%d", tc.path, tc.attr, tc.pos), func(t *testing.T) { 208 v := getInstance(t, config).Value().Lookup("a", tc.path) 209 a := v.Attribute(tc.attr) 210 got, err := a.Int(tc.pos) 211 if !cmpError(err, tc.err) { 212 t.Errorf("err: got %v; want %v", err, tc.err) 213 } 214 if got != tc.val { 215 t.Errorf("val: got %v; want %v", got, tc.val) 216 } 217 }) 218 } 219 } 220 221 func TestAttributeFlag(t *testing.T) { 222 const config = ` 223 a: { 224 a: 0 @foo(a,b,c=1) 225 b: 1 @bar(a,b,c,d=1) @foo(a,,d=1) 226 } 227 ` 228 testCases := []struct { 229 path string 230 attr string 231 pos int 232 flag string 233 val bool 234 err error 235 }{{ 236 path: "a", 237 attr: "foo", 238 pos: 0, 239 flag: "a", 240 val: true, 241 }, { 242 path: "b", 243 attr: "bar", 244 pos: 1, 245 flag: "a", 246 val: false, 247 }, { 248 path: "b", 249 attr: "bar", 250 pos: 0, 251 flag: "c", 252 val: true, 253 }, { 254 path: "e", 255 attr: "bar", 256 err: errors.New(`attribute "bar" does not exist`), 257 }, { 258 path: "b", 259 attr: "foo", 260 pos: 4, 261 err: errors.New("field does not exist"), 262 }} 263 for _, tc := range testCases { 264 t.Run(fmt.Sprintf("%s.%s:%d", tc.path, tc.attr, tc.pos), func(t *testing.T) { 265 v := getInstance(t, config).Value().Lookup("a", tc.path) 266 a := v.Attribute(tc.attr) 267 got, err := a.Flag(tc.pos, tc.flag) 268 if !cmpError(err, tc.err) { 269 t.Errorf("err: got %v; want %v", err, tc.err) 270 } 271 if got != tc.val { 272 t.Errorf("val: got %v; want %v", got, tc.val) 273 } 274 }) 275 } 276 } 277 278 func TestAttributeLookup(t *testing.T) { 279 const config = ` 280 a: { 281 a: 0 @foo(a,b,c=1) 282 b: 1 @bar(a,b,e =-5,d=1) @foo(a,,d=1) 283 } 284 ` 285 testCases := []struct { 286 path string 287 attr string 288 pos int 289 key string 290 val string 291 err error 292 }{{ 293 path: "a", 294 attr: "foo", 295 pos: 0, 296 key: "c", 297 val: "1", 298 }, { 299 path: "b", 300 attr: "bar", 301 pos: 1, 302 key: "a", 303 val: "", 304 }, { 305 path: "b", 306 attr: "bar", 307 pos: 0, 308 key: "e", 309 val: "-5", 310 }, { 311 path: "b", 312 attr: "bar", 313 pos: 0, 314 key: "d", 315 val: "1", 316 }, { 317 path: "b", 318 attr: "foo", 319 pos: 2, 320 key: "d", 321 val: "1", 322 }, { 323 path: "b", 324 attr: "foo", 325 pos: 2, 326 key: "f", 327 val: "", 328 }, { 329 path: "e", 330 attr: "bar", 331 err: errors.New(`attribute "bar" does not exist`), 332 }, { 333 path: "b", 334 attr: "foo", 335 pos: 4, 336 err: errors.New("field does not exist"), 337 }} 338 for _, tc := range testCases { 339 t.Run(fmt.Sprintf("%s.%s:%d", tc.path, tc.attr, tc.pos), func(t *testing.T) { 340 v := getInstance(t, config).Value().Lookup("a", tc.path) 341 a := v.Attribute(tc.attr) 342 got, _, err := a.Lookup(tc.pos, tc.key) 343 if !cmpError(err, tc.err) { 344 t.Errorf("err: got %v; want %v", err, tc.err) 345 } 346 if got != tc.val { 347 t.Errorf("val: got %v; want %v", got, tc.val) 348 } 349 }) 350 } 351 }