blob: 91accb6df9b4aaa1660ecf42258974073536707c [file] [log] [blame]
// Copyright 2021 CUE Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package cue
import (
"fmt"
"testing"
"cuelang.org/go/cue/errors"
)
func TestAttributes(t *testing.T) {
const config = `
a: {
a: 0 @foo(a,b,c=1)
b: 1 @bar(a,b,c,d=1) @foo(a,,d=1)
}
b: {
@embed(foo)
3
} @field(foo)
`
testCases := []struct {
flags AttrKind
path string
out string
}{{
flags: FieldAttr,
path: "a.a",
out: "[@foo(a,b,c=1)]",
}, {
flags: FieldAttr,
path: "a.b",
out: "[@bar(a,b,c,d=1) @foo(a,,d=1)]",
}, {
flags: DeclAttr,
path: "b",
out: "[@embed(foo)]",
}, {
flags: FieldAttr,
path: "b",
out: "[@field(foo)]",
}, {
flags: ValueAttr,
path: "b",
out: "[@field(foo) @embed(foo)]",
}}
for _, tc := range testCases {
t.Run("", func(t *testing.T) {
v := getInstance(t, config).Value().LookupPath(ParsePath(tc.path))
a := v.Attributes(tc.flags)
got := fmt.Sprint(a)
if got != tc.out {
t.Errorf("got %v; want %v", got, tc.out)
}
})
}
}
func TestAttributeErr(t *testing.T) {
const config = `
a: {
a: 0 @foo(a,b,c=1)
b: 1 @bar(a,b,c,d=1) @foo(a,,d=1)
}
`
testCases := []struct {
path string
attr string
err error
}{{
path: "a",
attr: "foo",
err: nil,
}, {
path: "a",
attr: "bar",
err: errors.New(`attribute "bar" does not exist`),
}, {
path: "xx",
attr: "bar",
err: errors.New(`attribute "bar" does not exist`),
}, {
path: "e",
attr: "bar",
err: errors.New(`attribute "bar" does not exist`),
}}
for _, tc := range testCases {
t.Run(tc.path+"-"+tc.attr, func(t *testing.T) {
v := getInstance(t, config).Value().Lookup("a", tc.path)
a := v.Attribute(tc.attr)
err := a.Err()
if !cmpError(err, tc.err) {
t.Errorf("got %v; want %v", err, tc.err)
}
})
}
}
func TestAttributeString(t *testing.T) {
const config = `
a: {
a: 0 @foo(a,b,c=1)
b: 1 @bar(a,b,c,d=1) @foo(a,,d=1)
}
`
testCases := []struct {
path string
attr string
pos int
str string
err error
}{{
path: "a",
attr: "foo",
pos: 0,
str: "a",
}, {
path: "a",
attr: "foo",
pos: 2,
str: "c=1",
}, {
path: "b",
attr: "bar",
pos: 3,
str: "d=1",
}, {
path: "e",
attr: "bar",
err: errors.New(`attribute "bar" does not exist`),
}, {
path: "b",
attr: "foo",
pos: 4,
err: errors.New("field does not exist"),
}}
for _, tc := range testCases {
t.Run(fmt.Sprintf("%s.%s:%d", tc.path, tc.attr, tc.pos), func(t *testing.T) {
v := getInstance(t, config).Value().Lookup("a", tc.path)
a := v.Attribute(tc.attr)
got, err := a.String(tc.pos)
if !cmpError(err, tc.err) {
t.Errorf("err: got %v; want %v", err, tc.err)
}
if got != tc.str {
t.Errorf("str: got %v; want %v", got, tc.str)
}
})
}
}
func TestAttributeInt(t *testing.T) {
const config = `
a: {
a: 0 @foo(1,3,c=1)
b: 1 @bar(a,-4,c,d=1) @foo(a,,d=1)
}
`
testCases := []struct {
path string
attr string
pos int
val int64
err error
}{{
path: "a",
attr: "foo",
pos: 0,
val: 1,
}, {
path: "b",
attr: "bar",
pos: 1,
val: -4,
}, {
path: "e",
attr: "bar",
err: errors.New(`attribute "bar" does not exist`),
}, {
path: "b",
attr: "foo",
pos: 4,
err: errors.New("field does not exist"),
}, {
path: "a",
attr: "foo",
pos: 2,
err: errors.New(`strconv.ParseInt: parsing "c=1": invalid syntax`),
}}
for _, tc := range testCases {
t.Run(fmt.Sprintf("%s.%s:%d", tc.path, tc.attr, tc.pos), func(t *testing.T) {
v := getInstance(t, config).Value().Lookup("a", tc.path)
a := v.Attribute(tc.attr)
got, err := a.Int(tc.pos)
if !cmpError(err, tc.err) {
t.Errorf("err: got %v; want %v", err, tc.err)
}
if got != tc.val {
t.Errorf("val: got %v; want %v", got, tc.val)
}
})
}
}
func TestAttributeFlag(t *testing.T) {
const config = `
a: {
a: 0 @foo(a,b,c=1)
b: 1 @bar(a,b,c,d=1) @foo(a,,d=1)
}
`
testCases := []struct {
path string
attr string
pos int
flag string
val bool
err error
}{{
path: "a",
attr: "foo",
pos: 0,
flag: "a",
val: true,
}, {
path: "b",
attr: "bar",
pos: 1,
flag: "a",
val: false,
}, {
path: "b",
attr: "bar",
pos: 0,
flag: "c",
val: true,
}, {
path: "e",
attr: "bar",
err: errors.New(`attribute "bar" does not exist`),
}, {
path: "b",
attr: "foo",
pos: 4,
err: errors.New("field does not exist"),
}}
for _, tc := range testCases {
t.Run(fmt.Sprintf("%s.%s:%d", tc.path, tc.attr, tc.pos), func(t *testing.T) {
v := getInstance(t, config).Value().Lookup("a", tc.path)
a := v.Attribute(tc.attr)
got, err := a.Flag(tc.pos, tc.flag)
if !cmpError(err, tc.err) {
t.Errorf("err: got %v; want %v", err, tc.err)
}
if got != tc.val {
t.Errorf("val: got %v; want %v", got, tc.val)
}
})
}
}
func TestAttributeLookup(t *testing.T) {
const config = `
a: {
a: 0 @foo(a,b,c=1)
b: 1 @bar(a,b,e =-5,d=1) @foo(a,,d=1)
}
`
testCases := []struct {
path string
attr string
pos int
key string
val string
err error
}{{
path: "a",
attr: "foo",
pos: 0,
key: "c",
val: "1",
}, {
path: "b",
attr: "bar",
pos: 1,
key: "a",
val: "",
}, {
path: "b",
attr: "bar",
pos: 0,
key: "e",
val: "-5",
}, {
path: "b",
attr: "bar",
pos: 0,
key: "d",
val: "1",
}, {
path: "b",
attr: "foo",
pos: 2,
key: "d",
val: "1",
}, {
path: "b",
attr: "foo",
pos: 2,
key: "f",
val: "",
}, {
path: "e",
attr: "bar",
err: errors.New(`attribute "bar" does not exist`),
}, {
path: "b",
attr: "foo",
pos: 4,
err: errors.New("field does not exist"),
}}
for _, tc := range testCases {
t.Run(fmt.Sprintf("%s.%s:%d", tc.path, tc.attr, tc.pos), func(t *testing.T) {
v := getInstance(t, config).Value().Lookup("a", tc.path)
a := v.Attribute(tc.attr)
got, _, err := a.Lookup(tc.pos, tc.key)
if !cmpError(err, tc.err) {
t.Errorf("err: got %v; want %v", err, tc.err)
}
if got != tc.val {
t.Errorf("val: got %v; want %v", got, tc.val)
}
})
}
}