1package hcl
2
3import (
4	"testing"
5)
6
7type asTraversalSupported struct {
8	staticExpr
9	RootName string
10}
11
12type asTraversalSupportedAttr struct {
13	staticExpr
14	RootName string
15	AttrName string
16}
17
18type asTraversalNotSupported struct {
19	staticExpr
20}
21
22type asTraversalDeclined struct {
23	staticExpr
24}
25
26type asTraversalWrappedDelegated struct {
27	original Expression
28	staticExpr
29}
30
31func (e asTraversalSupported) AsTraversal() Traversal {
32	return Traversal{
33		TraverseRoot{
34			Name: e.RootName,
35		},
36	}
37}
38
39func (e asTraversalSupportedAttr) AsTraversal() Traversal {
40	return Traversal{
41		TraverseRoot{
42			Name: e.RootName,
43		},
44		TraverseAttr{
45			Name: e.AttrName,
46		},
47	}
48}
49
50func (e asTraversalDeclined) AsTraversal() Traversal {
51	return nil
52}
53
54func (e asTraversalWrappedDelegated) UnwrapExpression() Expression {
55	return e.original
56}
57
58func TestAbsTraversalForExpr(t *testing.T) {
59	tests := []struct {
60		Expr         Expression
61		WantRootName string
62	}{
63		{
64			asTraversalSupported{RootName: "foo"},
65			"foo",
66		},
67		{
68			asTraversalNotSupported{},
69			"",
70		},
71		{
72			asTraversalDeclined{},
73			"",
74		},
75		{
76			asTraversalWrappedDelegated{
77				original: asTraversalSupported{RootName: "foo"},
78			},
79			"foo",
80		},
81		{
82			asTraversalWrappedDelegated{
83				original: asTraversalWrappedDelegated{
84					original: asTraversalSupported{RootName: "foo"},
85				},
86			},
87			"foo",
88		},
89	}
90
91	for _, test := range tests {
92		t.Run("", func(t *testing.T) {
93			got, diags := AbsTraversalForExpr(test.Expr)
94			switch {
95			case got != nil:
96				if test.WantRootName == "" {
97					t.Fatalf("traversal was returned; want error")
98				}
99				if len(got) != 1 {
100					t.Fatalf("wrong traversal length %d; want 1", len(got))
101				}
102				gotRoot, ok := got[0].(TraverseRoot)
103				if !ok {
104					t.Fatalf("first traversal step is %T; want hcl.TraverseRoot", got[0])
105				}
106				if gotRoot.Name != test.WantRootName {
107					t.Errorf("wrong root name %q; want %q", gotRoot.Name, test.WantRootName)
108				}
109			default:
110				if !diags.HasErrors() {
111					t.Errorf("returned nil traversal without error diagnostics")
112				}
113				if test.WantRootName != "" {
114					t.Errorf("traversal was not returned; want TraverseRoot(%q)", test.WantRootName)
115				}
116			}
117		})
118	}
119}
120
121func TestRelTraversalForExpr(t *testing.T) {
122	tests := []struct {
123		Expr          Expression
124		WantFirstName string
125	}{
126		{
127			asTraversalSupported{RootName: "foo"},
128			"foo",
129		},
130		{
131			asTraversalNotSupported{},
132			"",
133		},
134		{
135			asTraversalDeclined{},
136			"",
137		},
138	}
139
140	for _, test := range tests {
141		t.Run("", func(t *testing.T) {
142			got, diags := RelTraversalForExpr(test.Expr)
143			switch {
144			case got != nil:
145				if test.WantFirstName == "" {
146					t.Fatalf("traversal was returned; want error")
147				}
148				if len(got) != 1 {
149					t.Fatalf("wrong traversal length %d; want 1", len(got))
150				}
151				gotRoot, ok := got[0].(TraverseAttr)
152				if !ok {
153					t.Fatalf("first traversal step is %T; want hcl.TraverseAttr", got[0])
154				}
155				if gotRoot.Name != test.WantFirstName {
156					t.Errorf("wrong root name %q; want %q", gotRoot.Name, test.WantFirstName)
157				}
158			default:
159				if !diags.HasErrors() {
160					t.Errorf("returned nil traversal without error diagnostics")
161				}
162				if test.WantFirstName != "" {
163					t.Errorf("traversal was not returned; want TraverseAttr(%q)", test.WantFirstName)
164				}
165			}
166		})
167	}
168}
169
170func TestExprAsKeyword(t *testing.T) {
171	tests := []struct {
172		Expr Expression
173		Want string
174	}{
175		{
176			asTraversalSupported{RootName: "foo"},
177			"foo",
178		},
179		{
180			asTraversalSupportedAttr{
181				RootName: "foo",
182				AttrName: "bar",
183			},
184			"",
185		},
186		{
187			asTraversalNotSupported{},
188			"",
189		},
190		{
191			asTraversalDeclined{},
192			"",
193		},
194		{
195			asTraversalWrappedDelegated{
196				original: asTraversalSupported{RootName: "foo"},
197			},
198			"foo",
199		},
200		{
201			asTraversalWrappedDelegated{
202				original: asTraversalWrappedDelegated{
203					original: asTraversalSupported{RootName: "foo"},
204				},
205			},
206			"foo",
207		},
208	}
209
210	for _, test := range tests {
211		t.Run("", func(t *testing.T) {
212			got := ExprAsKeyword(test.Expr)
213			if got != test.Want {
214				t.Errorf("wrong result %q; want %q\ninput: %T", got, test.Want, test.Expr)
215			}
216		})
217	}
218}
219