308 lines
5.4 KiB
Go
308 lines
5.4 KiB
Go
// 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)
|
|
}
|
|
}
|
|
}
|