blob: ad51a896aa9f427556ced9e5fbec43e3061d9732 [file] [log] [blame]
Shinichiro Hamajib69bf8a2015-06-10 14:52:06 +09001// Copyright 2015 Google Inc. All rights reserved
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
Fumitoshi Ukai744bb2b2015-06-25 00:10:52 +090015package kati
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +090016
17import (
18 "reflect"
19 "testing"
20)
21
22func TestParseExpr(t *testing.T) {
23 for _, tc := range []struct {
24 in string
25 val Value
26 isErr bool
27 }{
28 {
29 in: "foo",
30 val: literal("foo"),
31 },
32 {
33 in: "(foo)",
34 val: literal("(foo)"),
35 },
36 {
37 in: "{foo}",
38 val: literal("{foo}"),
39 },
40 {
41 in: "$$",
42 val: literal("$"),
43 },
44 {
45 in: "foo$$bar",
46 val: literal("foo$bar"),
47 },
48 {
49 in: "$foo",
Fumitoshi Ukai55c8fa92015-06-25 15:56:10 +090050 val: expr{&varref{varname: literal("f")}, literal("oo")},
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +090051 },
52 {
53 in: "$(foo)",
Fumitoshi Ukaibbb0db52015-06-30 16:51:27 +090054 val: &varref{varname: literal("foo"), paren: '('},
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +090055 },
56 {
57 in: "$(foo:.c=.o)",
58 val: varsubst{
59 varname: literal("foo"),
60 pat: literal(".c"),
61 subst: literal(".o"),
Fumitoshi Ukaibbb0db52015-06-30 16:51:27 +090062 paren: '(',
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +090063 },
64 },
65 {
66 in: "$(subst $(space),$(,),$(foo))/bar",
Fumitoshi Ukai55c8fa92015-06-25 15:56:10 +090067 val: expr{
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +090068 &funcSubst{
69 fclosure: fclosure{
70 args: []Value{
Fumitoshi Ukaib2670d92015-04-16 10:28:27 +090071 literal("(subst"),
Fumitoshi Ukaib8acae92015-06-18 15:36:57 +090072 &varref{
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +090073 varname: literal("space"),
Fumitoshi Ukaibbb0db52015-06-30 16:51:27 +090074 paren: '(',
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +090075 },
Fumitoshi Ukaib8acae92015-06-18 15:36:57 +090076 &varref{
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +090077 varname: literal(","),
Fumitoshi Ukaibbb0db52015-06-30 16:51:27 +090078 paren: '(',
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +090079 },
Fumitoshi Ukaib8acae92015-06-18 15:36:57 +090080 &varref{
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +090081 varname: literal("foo"),
Fumitoshi Ukaibbb0db52015-06-30 16:51:27 +090082 paren: '(',
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +090083 },
84 },
85 },
86 },
87 literal("/bar"),
88 },
89 },
90 {
91 in: "$(subst $(space),$,,$(foo))",
92 val: &funcSubst{
93 fclosure: fclosure{
94 args: []Value{
Fumitoshi Ukaib2670d92015-04-16 10:28:27 +090095 literal("(subst"),
Fumitoshi Ukaib8acae92015-06-18 15:36:57 +090096 &varref{
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +090097 varname: literal("space"),
Fumitoshi Ukaibbb0db52015-06-30 16:51:27 +090098 paren: '(',
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +090099 },
Fumitoshi Ukaib8acae92015-06-18 15:36:57 +0900100 &varref{
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900101 varname: literal(""),
102 },
Fumitoshi Ukai55c8fa92015-06-25 15:56:10 +0900103 expr{
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900104 literal(","),
Fumitoshi Ukaib8acae92015-06-18 15:36:57 +0900105 &varref{
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900106 varname: literal("foo"),
Fumitoshi Ukaibbb0db52015-06-30 16:51:27 +0900107 paren: '(',
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900108 },
109 },
110 },
111 },
112 },
113 },
114 {
115 in: `$(shell echo '()')`,
116 val: &funcShell{
117 fclosure: fclosure{
118 args: []Value{
Fumitoshi Ukaib2670d92015-04-16 10:28:27 +0900119 literal("(shell"),
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900120 literal("echo '()'"),
121 },
122 },
123 },
124 },
125 {
Fumitoshi Ukaiebf945c2015-04-10 17:30:04 +0900126 in: `${shell echo '()'}`,
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900127 val: &funcShell{
128 fclosure: fclosure{
129 args: []Value{
Fumitoshi Ukaib2670d92015-04-16 10:28:27 +0900130 literal("{shell"),
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900131 literal("echo '()'"),
132 },
133 },
134 },
135 },
136 {
137 in: `$(shell echo ')')`,
Fumitoshi Ukai55c8fa92015-06-25 15:56:10 +0900138 val: expr{
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900139 &funcShell{
140 fclosure: fclosure{
141 args: []Value{
Fumitoshi Ukaib2670d92015-04-16 10:28:27 +0900142 literal("(shell"),
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900143 literal("echo '"),
144 },
145 },
146 },
147 literal("')"),
148 },
149 },
150 {
151 in: `${shell echo ')'}`,
152 val: &funcShell{
153 fclosure: fclosure{
154 args: []Value{
Fumitoshi Ukaib2670d92015-04-16 10:28:27 +0900155 literal("{shell"),
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900156 literal("echo ')'"),
157 },
158 },
159 },
160 },
161 {
162 in: `${shell echo '}'}`,
Fumitoshi Ukai55c8fa92015-06-25 15:56:10 +0900163 val: expr{
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900164 &funcShell{
165 fclosure: fclosure{
166 args: []Value{
Fumitoshi Ukaib2670d92015-04-16 10:28:27 +0900167 literal("{shell"),
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900168 literal("echo '"),
169 },
170 },
171 },
172 literal("'}"),
173 },
174 },
175 {
176 in: `$(shell make --version | ruby -n0e 'puts $$_[/Make (\d)/,1]')`,
177 val: &funcShell{
178 fclosure: fclosure{
179 args: []Value{
Fumitoshi Ukaib2670d92015-04-16 10:28:27 +0900180 literal("(shell"),
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900181 literal(`make --version | ruby -n0e 'puts $_[/Make (\d)/,1]'`),
182 },
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900183 },
184 },
185 },
Fumitoshi Ukaiee5c6fc2015-04-16 13:13:10 +0900186 {
187 in: `$(and ${TRUE}, $(X) )`,
188 val: &funcAnd{
189 fclosure: fclosure{
190 args: []Value{
191 literal("(and"),
Fumitoshi Ukaib8acae92015-06-18 15:36:57 +0900192 &varref{
Fumitoshi Ukaiee5c6fc2015-04-16 13:13:10 +0900193 varname: literal("TRUE"),
Fumitoshi Ukaibbb0db52015-06-30 16:51:27 +0900194 paren: '{',
Fumitoshi Ukaiee5c6fc2015-04-16 13:13:10 +0900195 },
Fumitoshi Ukaib8acae92015-06-18 15:36:57 +0900196 &varref{
Fumitoshi Ukaiee5c6fc2015-04-16 13:13:10 +0900197 varname: literal("X"),
Fumitoshi Ukaibbb0db52015-06-30 16:51:27 +0900198 paren: '(',
Fumitoshi Ukaiee5c6fc2015-04-16 13:13:10 +0900199 },
200 },
201 },
202 },
203 },
204 {
205 in: `$(call func, \
206 foo)`,
207 val: &funcCall{
208 fclosure: fclosure{
209 args: []Value{
210 literal("(call"),
211 literal("func"),
212 literal(" foo"),
213 },
214 },
215 },
216 },
217 {
218 in: `$(call func, \)`,
219 val: &funcCall{
220 fclosure: fclosure{
221 args: []Value{
222 literal("(call"),
223 literal("func"),
224 literal(` \`),
225 },
226 },
227 },
228 },
Fumitoshi Ukaida7f2552015-04-16 13:33:37 +0900229 {
230 in: `$(eval ## comment)`,
231 val: &funcNop{
232 expr: `$(eval ## comment)`,
233 },
234 },
Fumitoshi Ukai150c8612015-04-16 15:35:44 +0900235 {
236 in: `$(eval foo = bar)`,
237 val: &funcEvalAssign{
238 lhs: "foo",
239 op: "=",
240 rhs: literal("bar"),
241 },
242 },
243 {
244 in: `$(eval foo :=)`,
245 val: &funcEvalAssign{
246 lhs: "foo",
247 op: ":=",
248 rhs: literal(""),
249 },
250 },
Fumitoshi Ukaid8cec172015-04-28 00:08:09 +0900251 {
252 in: `$(eval foo := $(bar))`,
253 val: &funcEvalAssign{
254 lhs: "foo",
255 op: ":=",
Fumitoshi Ukaib8acae92015-06-18 15:36:57 +0900256 rhs: &varref{
Fumitoshi Ukaibbb0db52015-06-30 16:51:27 +0900257 varname: literal("bar"),
258 paren: '(',
Fumitoshi Ukaid8cec172015-04-28 00:08:09 +0900259 },
260 },
261 },
262 {
263 in: `$(eval foo := $$(bar))`,
264 val: &funcEvalAssign{
265 lhs: "foo",
266 op: ":=",
267 rhs: literal("$(bar)"),
268 },
269 },
270 {
271 in: `$(strip $1)`,
272 val: &funcStrip{
273 fclosure: fclosure{
274 args: []Value{
275 literal("(strip"),
276 paramref(1),
Fumitoshi Ukaif0a2ba72015-04-19 00:02:32 +0900277 },
278 },
279 },
Fumitoshi Ukaid8cec172015-04-28 00:08:09 +0900280 },
281 {
282 in: `$(strip $(1))`,
283 val: &funcStrip{
284 fclosure: fclosure{
285 args: []Value{
286 literal("(strip"),
287 paramref(1),
Fumitoshi Ukaif0a2ba72015-04-19 00:02:32 +0900288 },
289 },
290 },
Fumitoshi Ukaid8cec172015-04-28 00:08:09 +0900291 },
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900292 } {
Fumitoshi Ukaie9aa3802015-07-03 11:33:23 +0900293 val, _, err := parseExpr([]byte(tc.in), nil, parseOp{alloc: true})
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900294 if tc.isErr {
295 if err == nil {
296 t.Errorf(`parseExpr(%q)=_, _, nil; want error`, tc.in)
297 }
298 continue
299 }
300 if err != nil {
301 t.Errorf(`parseExpr(%q)=_, _, %v; want nil error`, tc.in, err)
302 continue
303 }
304 if got, want := val, tc.val; !reflect.DeepEqual(got, want) {
305 t.Errorf("parseExpr(%[1]q)=%[2]q %#[2]v, _, _;\n want %[3]q %#[3]v, _, _", tc.in, got, want)
306 }
307 }
308}