1// Copyright 2014 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
15package blueprint
16
17import (
18	"reflect"
19	"testing"
20)
21
22var ninjaParseTestCases = []struct {
23	input string
24	vars  []string
25	strs  []string
26	err   string
27}{
28	{
29		input: "abc def $ghi jkl",
30		vars:  []string{"ghi"},
31		strs:  []string{"abc def ", " jkl"},
32	},
33	{
34		input: "abc def $ghi$jkl",
35		vars:  []string{"ghi", "jkl"},
36		strs:  []string{"abc def ", "", ""},
37	},
38	{
39		input: "foo $012_-345xyz_! bar",
40		vars:  []string{"012_-345xyz_"},
41		strs:  []string{"foo ", "! bar"},
42	},
43	{
44		input: "foo ${012_-345xyz_} bar",
45		vars:  []string{"012_-345xyz_"},
46		strs:  []string{"foo ", " bar"},
47	},
48	{
49		input: "foo ${012_-345xyz_} bar",
50		vars:  []string{"012_-345xyz_"},
51		strs:  []string{"foo ", " bar"},
52	},
53	{
54		input: "foo $$ bar",
55		vars:  nil,
56		strs:  []string{"foo $$ bar"},
57	},
58	{
59		input: "$foo${bar}",
60		vars:  []string{"foo", "bar"},
61		strs:  []string{"", "", ""},
62	},
63	{
64		input: "$foo$$",
65		vars:  []string{"foo"},
66		strs:  []string{"", "$$"},
67	},
68	{
69		input: "foo bar",
70		vars:  nil,
71		strs:  []string{"foo bar"},
72	},
73	{
74		input: "foo $ bar",
75		err:   "invalid character after '$' at byte offset 5",
76	},
77	{
78		input: "foo $",
79		err:   "unexpected end of string after '$'",
80	},
81	{
82		input: "foo ${} bar",
83		err:   "empty variable name at byte offset 6",
84	},
85	{
86		input: "foo ${abc!} bar",
87		err:   "invalid character in variable name at byte offset 9",
88	},
89	{
90		input: "foo ${abc",
91		err:   "unexpected end of string in variable name",
92	},
93}
94
95func TestParseNinjaString(t *testing.T) {
96	for _, testCase := range ninjaParseTestCases {
97		scope := newLocalScope(nil, "namespace")
98		expectedVars := []Variable{}
99		for _, varName := range testCase.vars {
100			v, err := scope.LookupVariable(varName)
101			if err != nil {
102				v, err = scope.AddLocalVariable(varName, "")
103				if err != nil {
104					t.Fatalf("error creating scope: %s", err)
105				}
106			}
107			expectedVars = append(expectedVars, v)
108		}
109
110		output, err := parseNinjaString(scope, testCase.input)
111		if err == nil {
112			if !reflect.DeepEqual(output.variables, expectedVars) {
113				t.Errorf("incorrect variable list:")
114				t.Errorf("     input: %q", testCase.input)
115				t.Errorf("  expected: %#v", expectedVars)
116				t.Errorf("       got: %#v", output.variables)
117			}
118			if !reflect.DeepEqual(output.strings, testCase.strs) {
119				t.Errorf("incorrect string list:")
120				t.Errorf("     input: %q", testCase.input)
121				t.Errorf("  expected: %#v", testCase.strs)
122				t.Errorf("       got: %#v", output.strings)
123			}
124		}
125		var errStr string
126		if err != nil {
127			errStr = err.Error()
128		}
129		if err != nil && err.Error() != testCase.err {
130			t.Errorf("unexpected error:")
131			t.Errorf("     input: %q", testCase.input)
132			t.Errorf("  expected: %q", testCase.err)
133			t.Errorf("       got: %q", errStr)
134		}
135	}
136}
137
138func TestParseNinjaStringWithImportedVar(t *testing.T) {
139	ImpVar := &staticVariable{name_: "ImpVar"}
140	impScope := newScope(nil)
141	impScope.AddVariable(ImpVar)
142	scope := newScope(nil)
143	scope.AddImport("impPkg", impScope)
144
145	input := "abc def ${impPkg.ImpVar} ghi"
146	output, err := parseNinjaString(scope, input)
147	if err != nil {
148		t.Fatalf("unexpected error: %s", err)
149	}
150
151	expect := []Variable{ImpVar}
152	if !reflect.DeepEqual(output.variables, expect) {
153		t.Errorf("incorrect output:")
154		t.Errorf("     input: %q", input)
155		t.Errorf("  expected: %#v", expect)
156		t.Errorf("       got: %#v", output)
157	}
158}
159