• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// 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
15package kati
16
17import (
18	"reflect"
19	"testing"
20)
21
22func TestRuleParser(t *testing.T) {
23	for _, tc := range []struct {
24		in     string
25		tsv    *assignAST
26		rhs    expr
27		want   rule
28		assign *assignAST
29		err    string
30	}{
31		{
32			in: "foo: bar",
33			want: rule{
34				outputs: []string{"foo"},
35				inputs:  []string{"bar"},
36			},
37		},
38		{
39			in: "foo: bar baz",
40			want: rule{
41				outputs: []string{"foo"},
42				inputs:  []string{"bar", "baz"},
43			},
44		},
45		{
46			in: "foo:: bar",
47			want: rule{
48				outputs:       []string{"foo"},
49				inputs:        []string{"bar"},
50				isDoubleColon: true,
51			},
52		},
53		{
54			in:  "foo",
55			err: "*** missing separator.",
56		},
57		{
58			in: "%.o: %.c",
59			want: rule{
60				outputs:        []string{},
61				outputPatterns: []pattern{pattern{suffix: ".o"}},
62				inputs:         []string{"%.c"},
63			},
64		},
65		{
66			in:  "foo %.o: %.c",
67			err: "*** mixed implicit and normal rules: deprecated syntax",
68		},
69		{
70			in: "foo.o: %.o: %.c %.h",
71			want: rule{
72				outputs:        []string{"foo.o"},
73				outputPatterns: []pattern{pattern{suffix: ".o"}},
74				inputs:         []string{"%.c", "%.h"},
75			},
76		},
77		{
78			in:  "%.x: %.y: %.z",
79			err: "*** mixed implicit and normal rules: deprecated syntax",
80		},
81		{
82			in:  "foo.o: : %.c",
83			err: "*** missing target pattern.",
84		},
85		{
86			in:  "foo.o: %.o %.o: %.c",
87			err: "*** multiple target patterns.",
88		},
89		{
90			in:  "foo.o: foo.o: %.c",
91			err: "*** target pattern contains no '%'.",
92		},
93		{
94			in: "foo: bar | baz",
95			want: rule{
96				outputs:         []string{"foo"},
97				inputs:          []string{"bar"},
98				orderOnlyInputs: []string{"baz"},
99			},
100		},
101		{
102			in:  "foo: CFLAGS =",
103			rhs: expr{literal("-g")},
104			want: rule{
105				outputs: []string{"foo"},
106			},
107			assign: &assignAST{
108				lhs: literal("CFLAGS"),
109				rhs: literal("-g"),
110				op:  "=",
111			},
112		},
113		{
114			in: "foo:",
115			tsv: &assignAST{
116				lhs: literal("CFLAGS"),
117				rhs: literal("-g"),
118				op:  "=",
119			},
120			want: rule{
121				outputs: []string{"foo"},
122			},
123			assign: &assignAST{
124				lhs: literal("CFLAGS"),
125				rhs: literal("-g"),
126				op:  "=",
127			},
128		},
129		{
130			in:  "foo: CFLAGS=",
131			rhs: expr{literal("-g")},
132			want: rule{
133				outputs: []string{"foo"},
134			},
135			assign: &assignAST{
136				lhs: literal("CFLAGS"),
137				rhs: literal("-g"),
138				op:  "=",
139			},
140		},
141		{
142			in:  "foo: CFLAGS :=",
143			rhs: expr{literal("-g")},
144			want: rule{
145				outputs: []string{"foo"},
146			},
147			assign: &assignAST{
148				lhs: literal("CFLAGS"),
149				rhs: literal("-g"),
150				op:  ":=",
151			},
152		},
153		{
154			in:  "%.o: CFLAGS :=",
155			rhs: expr{literal("-g")},
156			want: rule{
157				outputs:        []string{},
158				outputPatterns: []pattern{pattern{suffix: ".o"}},
159			},
160			assign: &assignAST{
161				lhs: literal("CFLAGS"),
162				rhs: literal("-g"),
163				op:  ":=",
164			},
165		},
166		{
167			in: "%.o:",
168			tsv: &assignAST{
169				lhs: literal("CFLAGS"),
170				rhs: literal("-g"),
171				op:  ":=",
172			},
173			want: rule{
174				outputs:        []string{},
175				outputPatterns: []pattern{pattern{suffix: ".o"}},
176			},
177			assign: &assignAST{
178				lhs: literal("CFLAGS"),
179				rhs: literal("-g"),
180				op:  ":=",
181			},
182		},
183		/* TODO
184		{
185			in:  "foo.o: %.c: %.c",
186			err: "*** target 'foo.o' doesn't match the target pattern",
187		},
188		*/
189	} {
190		got := &rule{}
191		assign, err := got.parse([]byte(tc.in), tc.tsv, tc.rhs)
192		if tc.err != "" {
193			if err == nil {
194				t.Errorf(`r.parse(%q, %v)=_, <nil>, want _, %q`, tc.in, tc.rhs, tc.err)
195				continue
196			}
197			if got, want := err.Error(), tc.err; got != want {
198				t.Errorf(`r.parse(%q, %v)=_, %s, want %s`, tc.in, tc.rhs, got, want)
199			}
200			continue
201		}
202		if err != nil {
203			t.Errorf(`r.parse(%q, %v)=_, %v; want nil error`, tc.in, tc.rhs, err)
204			continue
205		}
206		if !reflect.DeepEqual(*got, tc.want) {
207			t.Errorf(`r.parse(%q, %v); r=%#v, want %#v`, tc.in, tc.rhs, *got, tc.want)
208		}
209		if tc.assign != nil {
210			if assign == nil {
211				t.Errorf(`r.parse(%q, %v)=<nil>; want=%#v`, tc.in, tc.rhs, tc.assign)
212				continue
213			}
214			if got, want := assign, tc.assign; !reflect.DeepEqual(got, want) {
215				t.Errorf(`r.parse(%q, %v)=%#v; want=%#v`, tc.in, tc.rhs, got, want)
216			}
217			continue
218		}
219		if assign != nil {
220			t.Errorf(`r.parse(%q, %v)=%v; want=<nil>`, tc.in, tc.rhs, assign)
221		}
222	}
223}
224