1// Copyright 2019 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
15package ast_test
16
17import (
18	"strings"
19	"testing"
20
21	"github.com/stretchr/testify/assert"
22
23	"cuelang.org/go/cue/ast"
24	"cuelang.org/go/cue/errors"
25	"cuelang.org/go/cue/format"
26	"cuelang.org/go/cue/token"
27)
28
29func TestLabelName(t *testing.T) {
30	testCases := []struct {
31		in      ast.Label
32		out     string
33		isIdent bool
34		err     bool
35		expr    bool
36	}{{
37		in:      ast.NewString("foo-bar"),
38		out:     "foo-bar",
39		isIdent: false,
40	}, {
41		in:      ast.NewString("8ball"),
42		out:     "8ball",
43		isIdent: false,
44	}, {
45		in:      ast.NewString("foo bar"),
46		out:     "foo bar",
47		isIdent: false,
48	}, {
49		in:      &ast.Ident{Name: "`foo`"},
50		out:     "foo",
51		isIdent: true,
52	}, {
53		in:      &ast.Ident{Name: ""},
54		out:     "",
55		isIdent: false,
56		err:     true,
57	}, {
58		in:      &ast.Ident{Name: "#"},
59		out:     "#",
60		isIdent: true,
61	}, {
62		in:      &ast.Ident{Name: "#0"},
63		out:     "",
64		isIdent: false,
65		err:     true,
66	}, {
67		in:      &ast.Ident{Name: "_#"},
68		out:     "_#",
69		isIdent: true,
70		err:     false,
71	}, {
72		in:      &ast.Ident{Name: "_"},
73		out:     "_",
74		isIdent: true,
75	}, {
76		in:      &ast.Ident{Name: "8ball"},
77		out:     "",
78		isIdent: false,
79		err:     true,
80	}, {
81		in:      &ast.Ident{Name: "_hidden"},
82		out:     "_hidden",
83		isIdent: true,
84	}, {
85		in:      &ast.Ident{Name: "#A"},
86		out:     "#A",
87		isIdent: true,
88	}, {
89		in:      &ast.Ident{Name: "#Def"},
90		out:     "#Def",
91		isIdent: true,
92	}, {
93		in:      &ast.Ident{Name: "_#Def"},
94		out:     "_#Def",
95		isIdent: true,
96	}, {
97		in:      &ast.Ident{Name: "#_Def"},
98		out:     "#_Def",
99		isIdent: true,
100	}, {
101		in:      &ast.Ident{Name: "`foo-bar`"},
102		out:     "foo-bar",
103		isIdent: true,
104	}, {
105		in:      &ast.Ident{Name: "`foo-bar\x00`"},
106		out:     "",
107		isIdent: false,
108		err:     true,
109	}, {
110		in:      &ast.Ident{Name: "`foo-bar\x00`"},
111		out:     "",
112		isIdent: false,
113		err:     true,
114	}, {
115		in:      ast.NewBool(true),
116		out:     "true",
117		isIdent: true,
118	}, {
119		in:      &ast.BasicLit{Kind: token.STRING, Value: `"foo`},
120		out:     "",
121		isIdent: false,
122		err:     true,
123	}, {
124		in:      &ast.Interpolation{Elts: []ast.Expr{ast.NewString("foo")}},
125		out:     "",
126		isIdent: false,
127		err:     true,
128		expr:    true,
129	}}
130	for _, tc := range testCases {
131		b, _ := format.Node(tc.in)
132		t.Run(string(b), func(t *testing.T) {
133			if id, ok := tc.in.(*ast.Ident); ok && !strings.HasPrefix(id.Name, "`") {
134				assert.Equal(t, tc.isIdent, ast.IsValidIdent(id.Name))
135			}
136
137			str, isIdent, err := ast.LabelName(tc.in)
138			assert.Equal(t, tc.out, str, "value")
139			assert.Equal(t, tc.isIdent, isIdent, "isIdent")
140			assert.Equal(t, tc.err, err != nil, "err")
141			assert.Equal(t, tc.expr, errors.Is(err, ast.ErrIsExpression), "expr")
142		})
143	}
144}
145