| // Copyright 2015 Google Inc. All rights reserved | |
| // | |
| // 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 kati | |
| import ( | |
| "reflect" | |
| "testing" | |
| ) | |
| func TestParseExpr(t *testing.T) { | |
| for _, tc := range []struct { | |
| in string | |
| val Value | |
| isErr bool | |
| }{ | |
| { | |
| in: "foo", | |
| val: literal("foo"), | |
| }, | |
| { | |
| in: "(foo)", | |
| val: literal("(foo)"), | |
| }, | |
| { | |
| in: "{foo}", | |
| val: literal("{foo}"), | |
| }, | |
| { | |
| in: "$$", | |
| val: literal("$"), | |
| }, | |
| { | |
| in: "foo$$bar", | |
| val: literal("foo$bar"), | |
| }, | |
| { | |
| in: "$foo", | |
| val: expr{&varref{varname: literal("f")}, literal("oo")}, | |
| }, | |
| { | |
| in: "$(foo)", | |
| val: &varref{varname: literal("foo"), paren: '('}, | |
| }, | |
| { | |
| in: "$(foo:.c=.o)", | |
| val: varsubst{ | |
| varname: literal("foo"), | |
| pat: literal(".c"), | |
| subst: literal(".o"), | |
| paren: '(', | |
| }, | |
| }, | |
| { | |
| in: "$(subst $(space),$(,),$(foo))/bar", | |
| val: expr{ | |
| &funcSubst{ | |
| fclosure: fclosure{ | |
| args: []Value{ | |
| literal("(subst"), | |
| &varref{ | |
| varname: literal("space"), | |
| paren: '(', | |
| }, | |
| &varref{ | |
| varname: literal(","), | |
| paren: '(', | |
| }, | |
| &varref{ | |
| varname: literal("foo"), | |
| paren: '(', | |
| }, | |
| }, | |
| }, | |
| }, | |
| literal("/bar"), | |
| }, | |
| }, | |
| { | |
| in: "$(subst $(space),$,,$(foo))", | |
| val: &funcSubst{ | |
| fclosure: fclosure{ | |
| args: []Value{ | |
| literal("(subst"), | |
| &varref{ | |
| varname: literal("space"), | |
| paren: '(', | |
| }, | |
| &varref{ | |
| varname: literal(""), | |
| }, | |
| expr{ | |
| literal(","), | |
| &varref{ | |
| varname: literal("foo"), | |
| paren: '(', | |
| }, | |
| }, | |
| }, | |
| }, | |
| }, | |
| }, | |
| { | |
| in: `$(shell echo '()')`, | |
| val: &funcShell{ | |
| fclosure: fclosure{ | |
| args: []Value{ | |
| literal("(shell"), | |
| literal("echo '()'"), | |
| }, | |
| }, | |
| }, | |
| }, | |
| { | |
| in: `${shell echo '()'}`, | |
| val: &funcShell{ | |
| fclosure: fclosure{ | |
| args: []Value{ | |
| literal("{shell"), | |
| literal("echo '()'"), | |
| }, | |
| }, | |
| }, | |
| }, | |
| { | |
| in: `$(shell echo ')')`, | |
| val: expr{ | |
| &funcShell{ | |
| fclosure: fclosure{ | |
| args: []Value{ | |
| literal("(shell"), | |
| literal("echo '"), | |
| }, | |
| }, | |
| }, | |
| literal("')"), | |
| }, | |
| }, | |
| { | |
| in: `${shell echo ')'}`, | |
| val: &funcShell{ | |
| fclosure: fclosure{ | |
| args: []Value{ | |
| literal("{shell"), | |
| literal("echo ')'"), | |
| }, | |
| }, | |
| }, | |
| }, | |
| { | |
| in: `${shell echo '}'}`, | |
| val: expr{ | |
| &funcShell{ | |
| fclosure: fclosure{ | |
| args: []Value{ | |
| literal("{shell"), | |
| literal("echo '"), | |
| }, | |
| }, | |
| }, | |
| literal("'}"), | |
| }, | |
| }, | |
| { | |
| in: `$(shell make --version | ruby -n0e 'puts $$_[/Make (\d)/,1]')`, | |
| val: &funcShell{ | |
| fclosure: fclosure{ | |
| args: []Value{ | |
| literal("(shell"), | |
| literal(`make --version | ruby -n0e 'puts $_[/Make (\d)/,1]'`), | |
| }, | |
| }, | |
| }, | |
| }, | |
| { | |
| in: `$(and ${TRUE}, $(X) )`, | |
| val: &funcAnd{ | |
| fclosure: fclosure{ | |
| args: []Value{ | |
| literal("(and"), | |
| &varref{ | |
| varname: literal("TRUE"), | |
| paren: '{', | |
| }, | |
| &varref{ | |
| varname: literal("X"), | |
| paren: '(', | |
| }, | |
| }, | |
| }, | |
| }, | |
| }, | |
| { | |
| in: `$(call func, \ | |
| foo)`, | |
| val: &funcCall{ | |
| fclosure: fclosure{ | |
| args: []Value{ | |
| literal("(call"), | |
| literal("func"), | |
| literal(" foo"), | |
| }, | |
| }, | |
| }, | |
| }, | |
| { | |
| in: `$(call func, \)`, | |
| val: &funcCall{ | |
| fclosure: fclosure{ | |
| args: []Value{ | |
| literal("(call"), | |
| literal("func"), | |
| literal(` \`), | |
| }, | |
| }, | |
| }, | |
| }, | |
| { | |
| in: `$(eval ## comment)`, | |
| val: &funcNop{ | |
| expr: `$(eval ## comment)`, | |
| }, | |
| }, | |
| { | |
| in: `$(eval foo = bar)`, | |
| val: &funcEvalAssign{ | |
| lhs: "foo", | |
| op: "=", | |
| rhs: literal("bar"), | |
| }, | |
| }, | |
| { | |
| in: `$(eval foo :=)`, | |
| val: &funcEvalAssign{ | |
| lhs: "foo", | |
| op: ":=", | |
| rhs: literal(""), | |
| }, | |
| }, | |
| { | |
| in: `$(eval foo := $(bar))`, | |
| val: &funcEvalAssign{ | |
| lhs: "foo", | |
| op: ":=", | |
| rhs: &varref{ | |
| varname: literal("bar"), | |
| paren: '(', | |
| }, | |
| }, | |
| }, | |
| { | |
| in: `$(eval foo := $$(bar))`, | |
| val: &funcEvalAssign{ | |
| lhs: "foo", | |
| op: ":=", | |
| rhs: literal("$(bar)"), | |
| }, | |
| }, | |
| { | |
| in: `$(strip $1)`, | |
| val: &funcStrip{ | |
| fclosure: fclosure{ | |
| args: []Value{ | |
| literal("(strip"), | |
| paramref(1), | |
| }, | |
| }, | |
| }, | |
| }, | |
| { | |
| in: `$(strip $(1))`, | |
| val: &funcStrip{ | |
| fclosure: fclosure{ | |
| args: []Value{ | |
| literal("(strip"), | |
| paramref(1), | |
| }, | |
| }, | |
| }, | |
| }, | |
| } { | |
| val, _, err := parseExpr([]byte(tc.in), nil, parseOp{alloc: true}) | |
| if tc.isErr { | |
| if err == nil { | |
| t.Errorf(`parseExpr(%q)=_, _, nil; want error`, tc.in) | |
| } | |
| continue | |
| } | |
| if err != nil { | |
| t.Errorf(`parseExpr(%q)=_, _, %v; want nil error`, tc.in, err) | |
| continue | |
| } | |
| if got, want := val, tc.val; !reflect.DeepEqual(got, want) { | |
| t.Errorf("parseExpr(%[1]q)=%[2]q %#[2]v, _, _;\n want %[3]q %#[3]v, _, _", tc.in, got, want) | |
| } | |
| } | |
| } |