...

Source file src/cuelang.org/go/cue/attribute_test.go

Documentation: cuelang.org/go/cue

     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  	"cuelang.org/go/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  	c1: {} @step(1)
    36  	if true {
    37  		c2: { @step(2a) } @step(2b)
    38  		@step(2c)
    39  	}
    40  	c3: {} @step(3)
    41  	if false {
    42  		c4: { @step(4a) } @step(4b)
    43  		@step(4c)
    44  	}
    45  	`
    46  
    47  	testCases := []struct {
    48  		flags AttrKind
    49  		path  string
    50  		out   string
    51  	}{{
    52  		flags: FieldAttr,
    53  		path:  "a.a",
    54  		out:   "[@foo(a,b,c=1)]",
    55  	}, {
    56  		flags: FieldAttr,
    57  		path:  "a.b",
    58  		out:   "[@bar(a,b,c,d=1) @foo(a,,d=1)]",
    59  	}, {
    60  		flags: DeclAttr,
    61  		path:  "b",
    62  		out:   "[@embed(foo)]",
    63  	}, {
    64  		flags: FieldAttr,
    65  		path:  "b",
    66  		out:   "[@field(foo)]",
    67  	}, {
    68  		flags: ValueAttr,
    69  		path:  "b",
    70  		out:   "[@field(foo) @embed(foo)]",
    71  	}, {
    72  		flags: ValueAttr,
    73  		path:  "c1",
    74  		out:   "[@step(1)]",
    75  	}, {
    76  		flags: DeclAttr,
    77  		path:  "c2",
    78  		out:   "[@step(2a)]",
    79  	}, {
    80  		flags: FieldAttr,
    81  		path:  "c2",
    82  		out:   "[@step(2b)]",
    83  	}, {
    84  		flags: DeclAttr,
    85  		path:  "",
    86  		out:   "[@step(2c)]",
    87  	}, {
    88  		flags: ValueAttr | FieldAttr,
    89  		path:  "c3",
    90  		out:   "[@step(3)]",
    91  	}, {
    92  		flags: ValueAttr | FieldAttr,
    93  		path:  "c4",
    94  		out:   "[]",
    95  	}}
    96  	for _, tc := range testCases {
    97  		t.Run(tc.path, func(t *testing.T) {
    98  			v := getInstance(t, config).Value().LookupPath(ParsePath(tc.path))
    99  			a := v.Attributes(tc.flags)
   100  			got := fmt.Sprint(a)
   101  			if got != tc.out {
   102  				t.Errorf("got %v; want %v", got, tc.out)
   103  			}
   104  
   105  		})
   106  	}
   107  }
   108  
   109  func TestAttributeErr(t *testing.T) {
   110  	const config = `
   111  	a: {
   112  		a: 0 @foo(a,b,c=1)
   113  		b: 1 @bar(a,b,c,d=1) @foo(a,,d=1)
   114  	}
   115  	`
   116  	testCases := []struct {
   117  		path string
   118  		attr string
   119  		err  error
   120  	}{{
   121  		path: "a",
   122  		attr: "foo",
   123  		err:  nil,
   124  	}, {
   125  		path: "a",
   126  		attr: "bar",
   127  		err:  errors.New(`attribute "bar" does not exist`),
   128  	}, {
   129  		path: "xx",
   130  		attr: "bar",
   131  		err:  errors.New(`attribute "bar" does not exist`),
   132  	}, {
   133  		path: "e",
   134  		attr: "bar",
   135  		err:  errors.New(`attribute "bar" does not exist`),
   136  	}}
   137  	for _, tc := range testCases {
   138  		t.Run(tc.path+"-"+tc.attr, func(t *testing.T) {
   139  			v := getInstance(t, config).Value().Lookup("a", tc.path)
   140  			a := v.Attribute(tc.attr)
   141  			err := a.Err()
   142  			if !cmpError(err, tc.err) {
   143  				t.Errorf("got %v; want %v", err, tc.err)
   144  			}
   145  		})
   146  	}
   147  }
   148  
   149  func TestAttributeName(t *testing.T) {
   150  	const config = `
   151  	a: 0 @foo(a,b,c=1) @bar()
   152  	`
   153  	v := getInstance(t, config).Value().Lookup("a")
   154  	a := v.Attribute("foo")
   155  	if got, want := a.Name(), "foo"; got != want {
   156  		t.Errorf("got %v; want %v", got, want)
   157  	}
   158  }
   159  
   160  func TestAttributeString(t *testing.T) {
   161  	const config = `
   162  	a: {
   163  		a: 0 @foo(a,b,c=1)
   164  		b: 1 @bar(a,b,c,d=1) @foo(a,,d=1,e="x y","f g")
   165  	}
   166  	`
   167  	testCases := []struct {
   168  		path string
   169  		attr string
   170  		pos  int
   171  		str  string
   172  		err  error
   173  	}{{
   174  		path: "a",
   175  		attr: "foo",
   176  		pos:  0,
   177  		str:  "a",
   178  	}, {
   179  		path: "a",
   180  		attr: "foo",
   181  		pos:  2,
   182  		str:  "c=1",
   183  	}, {
   184  		path: "b",
   185  		attr: "bar",
   186  		pos:  3,
   187  		str:  "d=1",
   188  	}, {
   189  		path: "b",
   190  		attr: "foo",
   191  		pos:  3,
   192  		str:  `e="x y"`,
   193  	}, {
   194  		path: "b",
   195  		attr: "foo",
   196  		pos:  4,
   197  		str:  `f g`,
   198  	}, {
   199  		path: "e",
   200  		attr: "bar",
   201  		err:  errors.New(`attribute "bar" does not exist`),
   202  	}, {
   203  		path: "b",
   204  		attr: "foo",
   205  		pos:  5,
   206  		err:  errors.New("field does not exist"),
   207  	}}
   208  	for _, tc := range testCases {
   209  		t.Run(fmt.Sprintf("%s.%s:%d", tc.path, tc.attr, tc.pos), func(t *testing.T) {
   210  			v := getInstance(t, config).Value().Lookup("a", tc.path)
   211  			a := v.Attribute(tc.attr)
   212  			got, err := a.String(tc.pos)
   213  			if !cmpError(err, tc.err) {
   214  				t.Errorf("err: got %v; want %v", err, tc.err)
   215  			}
   216  			if got != tc.str {
   217  				t.Errorf("str: got %v; want %v", got, tc.str)
   218  			}
   219  		})
   220  	}
   221  }
   222  
   223  func TestAttributeArg(t *testing.T) {
   224  	const config = `
   225  	a: 1 @foo(a,,d=1,e="x y","f g", with spaces ,  s=  spaces in value  )
   226  	`
   227  	testCases := []struct {
   228  		pos int
   229  		key string
   230  		val string
   231  		raw string
   232  	}{{
   233  		pos: 0,
   234  		key: "a",
   235  		val: "",
   236  		raw: "a",
   237  	}, {
   238  		pos: 1,
   239  		key: "",
   240  		val: "",
   241  		raw: "",
   242  	}, {
   243  		pos: 2,
   244  		key: "d",
   245  		val: "1",
   246  		raw: "d=1",
   247  	}, {
   248  		pos: 3,
   249  		key: "e",
   250  		val: "x y",
   251  		raw: `e="x y"`,
   252  	}, {
   253  		pos: 4,
   254  		key: "f g",
   255  		val: "",
   256  		raw: `"f g"`,
   257  	}, {
   258  		pos: 5,
   259  		key: "with spaces",
   260  		val: "",
   261  		raw: " with spaces ",
   262  	}, {
   263  		pos: 6,
   264  		key: "s",
   265  		val: "spaces in value",
   266  		raw: "  s=  spaces in value  ",
   267  	}}
   268  	for _, tc := range testCases {
   269  		t.Run(fmt.Sprintf("%d", tc.pos), func(t *testing.T) {
   270  			v := getInstance(t, config).Value().Lookup("a")
   271  			a := v.Attribute("foo")
   272  			key, val := a.Arg(tc.pos)
   273  			raw := a.RawArg(tc.pos)
   274  			if got, want := key, tc.key; got != want {
   275  				t.Errorf("unexpected key; got %q want %q", got, want)
   276  			}
   277  			if got, want := val, tc.val; got != want {
   278  				t.Errorf("unexpected value; got %q want %q", got, want)
   279  			}
   280  			if got, want := raw, tc.raw; got != want {
   281  				t.Errorf("unexpected raw value; got %q want %q", got, want)
   282  			}
   283  		})
   284  	}
   285  }
   286  
   287  func TestAttributeInt(t *testing.T) {
   288  	const config = `
   289  	a: {
   290  		a: 0 @foo(1,3,c=1)
   291  		b: 1 @bar(a,-4,c,d=1) @foo(a,,d=1)
   292  	}
   293  	`
   294  	testCases := []struct {
   295  		path string
   296  		attr string
   297  		pos  int
   298  		val  int64
   299  		err  error
   300  	}{{
   301  		path: "a",
   302  		attr: "foo",
   303  		pos:  0,
   304  		val:  1,
   305  	}, {
   306  		path: "b",
   307  		attr: "bar",
   308  		pos:  1,
   309  		val:  -4,
   310  	}, {
   311  		path: "e",
   312  		attr: "bar",
   313  		err:  errors.New(`attribute "bar" does not exist`),
   314  	}, {
   315  		path: "b",
   316  		attr: "foo",
   317  		pos:  4,
   318  		err:  errors.New("field does not exist"),
   319  	}, {
   320  		path: "a",
   321  		attr: "foo",
   322  		pos:  2,
   323  		err:  errors.New(`strconv.ParseInt: parsing "c=1": invalid syntax`),
   324  	}}
   325  	for _, tc := range testCases {
   326  		t.Run(fmt.Sprintf("%s.%s:%d", tc.path, tc.attr, tc.pos), func(t *testing.T) {
   327  			v := getInstance(t, config).Value().Lookup("a", tc.path)
   328  			a := v.Attribute(tc.attr)
   329  			got, err := a.Int(tc.pos)
   330  			if !cmpError(err, tc.err) {
   331  				t.Errorf("err: got %v; want %v", err, tc.err)
   332  			}
   333  			if got != tc.val {
   334  				t.Errorf("val: got %v; want %v", got, tc.val)
   335  			}
   336  		})
   337  	}
   338  }
   339  
   340  func TestAttributeFlag(t *testing.T) {
   341  	const config = `
   342  	a: {
   343  		a: 0 @foo(a,b,c=1)
   344  		b: 1 @bar(a,b,c,d=1) @foo(a,,d=1)
   345  	}
   346  	`
   347  	testCases := []struct {
   348  		path string
   349  		attr string
   350  		pos  int
   351  		flag string
   352  		val  bool
   353  		err  error
   354  	}{{
   355  		path: "a",
   356  		attr: "foo",
   357  		pos:  0,
   358  		flag: "a",
   359  		val:  true,
   360  	}, {
   361  		path: "b",
   362  		attr: "bar",
   363  		pos:  1,
   364  		flag: "a",
   365  		val:  false,
   366  	}, {
   367  		path: "b",
   368  		attr: "bar",
   369  		pos:  0,
   370  		flag: "c",
   371  		val:  true,
   372  	}, {
   373  		path: "e",
   374  		attr: "bar",
   375  		err:  errors.New(`attribute "bar" does not exist`),
   376  	}, {
   377  		path: "b",
   378  		attr: "foo",
   379  		pos:  4,
   380  		err:  errors.New("field does not exist"),
   381  	}}
   382  	for _, tc := range testCases {
   383  		t.Run(fmt.Sprintf("%s.%s:%d", tc.path, tc.attr, tc.pos), func(t *testing.T) {
   384  			v := getInstance(t, config).Value().Lookup("a", tc.path)
   385  			a := v.Attribute(tc.attr)
   386  			got, err := a.Flag(tc.pos, tc.flag)
   387  			if !cmpError(err, tc.err) {
   388  				t.Errorf("err: got %v; want %v", err, tc.err)
   389  			}
   390  			if got != tc.val {
   391  				t.Errorf("val: got %v; want %v", got, tc.val)
   392  			}
   393  		})
   394  	}
   395  }
   396  
   397  func TestAttributeLookup(t *testing.T) {
   398  	const config = `
   399  	a: {
   400  		a: 0 @foo(a,b,c=1)
   401  		b: 1 @bar(a,b,e =-5,d=1) @foo(a,,d=1)
   402  	}
   403  	`
   404  	testCases := []struct {
   405  		path string
   406  		attr string
   407  		pos  int
   408  		key  string
   409  		val  string
   410  		err  error
   411  	}{{
   412  		path: "a",
   413  		attr: "foo",
   414  		pos:  0,
   415  		key:  "c",
   416  		val:  "1",
   417  	}, {
   418  		path: "b",
   419  		attr: "bar",
   420  		pos:  1,
   421  		key:  "a",
   422  		val:  "",
   423  	}, {
   424  		path: "b",
   425  		attr: "bar",
   426  		pos:  0,
   427  		key:  "e",
   428  		val:  "-5",
   429  	}, {
   430  		path: "b",
   431  		attr: "bar",
   432  		pos:  0,
   433  		key:  "d",
   434  		val:  "1",
   435  	}, {
   436  		path: "b",
   437  		attr: "foo",
   438  		pos:  2,
   439  		key:  "d",
   440  		val:  "1",
   441  	}, {
   442  		path: "b",
   443  		attr: "foo",
   444  		pos:  2,
   445  		key:  "f",
   446  		val:  "",
   447  	}, {
   448  		path: "e",
   449  		attr: "bar",
   450  		err:  errors.New(`attribute "bar" does not exist`),
   451  	}, {
   452  		path: "b",
   453  		attr: "foo",
   454  		pos:  4,
   455  		err:  errors.New("field does not exist"),
   456  	}}
   457  	for _, tc := range testCases {
   458  		t.Run(fmt.Sprintf("%s.%s:%d", tc.path, tc.attr, tc.pos), func(t *testing.T) {
   459  			v := getInstance(t, config).Value().Lookup("a", tc.path)
   460  			a := v.Attribute(tc.attr)
   461  			got, _, err := a.Lookup(tc.pos, tc.key)
   462  			if !cmpError(err, tc.err) {
   463  				t.Errorf("err: got %v; want %v", err, tc.err)
   464  			}
   465  			if got != tc.val {
   466  				t.Errorf("val: got %v; want %v", got, tc.val)
   467  			}
   468  		})
   469  	}
   470  }
   471  

View as plain text