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  }