blob: ac2f6996a1a4c9b20b8fce3c62cdc3e6b24ae2af [file] [log] [blame]
Dan Willemsen43398532018-02-21 02:10:29 -08001// Copyright 2018 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
Dan Willemsenc89b6f12019-08-29 14:47:40 -070015package makedeps
Dan Willemsen43398532018-02-21 02:10:29 -080016
17import (
18 "bytes"
19 "io"
20 "io/ioutil"
21 "os"
22 "testing"
23)
24
25func TestParse(t *testing.T) {
26 testCases := []struct {
27 name string
28 input string
29 output Deps
30 err error
31 }{
32 // These come from the ninja test suite
33 {
34 name: "Basic",
35 input: "build/ninja.o: ninja.cc ninja.h eval_env.h manifest_parser.h",
36 output: Deps{
37 Output: "build/ninja.o",
38 Inputs: []string{
39 "ninja.cc",
40 "ninja.h",
41 "eval_env.h",
42 "manifest_parser.h",
43 },
44 },
45 },
46 {
47 name: "EarlyNewlineAndWhitespace",
48 input: ` \
49 out: in`,
50 output: Deps{
51 Output: "out",
52 Inputs: []string{"in"},
53 },
54 },
55 {
56 name: "Continuation",
57 input: `foo.o: \
58 bar.h baz.h
59`,
60 output: Deps{
61 Output: "foo.o",
62 Inputs: []string{"bar.h", "baz.h"},
63 },
64 },
65 {
66 name: "CarriageReturnContinuation",
67 input: "foo.o: \\\r\n bar.h baz.h\r\n",
68 output: Deps{
69 Output: "foo.o",
70 Inputs: []string{"bar.h", "baz.h"},
71 },
72 },
73 {
74 name: "BackSlashes",
75 input: `Project\Dir\Build\Release8\Foo\Foo.res : \
76 Dir\Library\Foo.rc \
77 Dir\Library\Version\Bar.h \
78 Dir\Library\Foo.ico \
79 Project\Thing\Bar.tlb \
80`,
81 output: Deps{
82 Output: `Project\Dir\Build\Release8\Foo\Foo.res`,
83 Inputs: []string{
84 `Dir\Library\Foo.rc`,
85 `Dir\Library\Version\Bar.h`,
86 `Dir\Library\Foo.ico`,
87 `Project\Thing\Bar.tlb`,
88 },
89 },
90 },
91 {
92 name: "Spaces",
93 input: `a\ bc\ def: a\ b c d`,
94 output: Deps{
95 Output: `a bc def`,
96 Inputs: []string{"a b", "c", "d"},
97 },
98 },
99 {
100 name: "Escapes",
101 input: `\!\@\#$$\%\^\&\\:`,
102 output: Deps{
103 Output: `\!\@#$\%\^\&\`,
104 },
105 },
106 {
107 name: "SpecialChars",
108 // Ninja includes a number of '=', but our parser can't handle that,
109 // since it sees the equals and switches over to assuming it's an
110 // assignment.
111 //
112 // We don't have any files in our tree that contain an '=' character,
113 // and Kati can't handle parsing this either, so for now I'm just
114 // going to remove all the '=' characters below.
115 //
116 // It looks like make will only do this for the first
117 // dependency, but not later dependencies.
118 input: `C\:/Program\ Files\ (x86)/Microsoft\ crtdefs.h: \
119 en@quot.header~ t+t-x!1 \
120 openldap/slapd.d/cnconfig/cnschema/cn{0}core.ldif \
121 Fu` + "\303\244ball",
122 output: Deps{
123 Output: "C:/Program Files (x86)/Microsoft crtdefs.h",
124 Inputs: []string{
125 "en@quot.header~",
126 "t+t-x!1",
127 "openldap/slapd.d/cnconfig/cnschema/cn{0}core.ldif",
128 "Fu\303\244ball",
129 },
130 },
131 },
132 // Ninja's UnifyMultipleOutputs and RejectMultipleDifferentOutputs tests have been omitted,
133 // since we don't want the same behavior.
134
135 // Our own tests
136 {
137 name: "Multiple outputs",
138 input: `a b: c
139a: d
140b: e`,
141 output: Deps{
142 Output: "b",
143 Inputs: []string{
144 "c",
145 "d",
146 "e",
147 },
148 },
149 },
Colin Cross5274d582019-10-04 12:34:19 -0700150 {
151 // TODO(b/141372861): remove this
152 // AIDL produces a dep file with no output file for a parcelable (b/
153 name: "AIDL parcelable",
154 input: ` : \
155 frameworks/base/tests/net/integration/src/com/android/server/net/integrationtests/HttpResponse.aidl
156`,
157 output: Deps{
158 Output: "",
159 Inputs: []string{
160 "frameworks/base/tests/net/integration/src/com/android/server/net/integrationtests/HttpResponse.aidl",
161 },
162 },
163 },
Dan Willemsen43398532018-02-21 02:10:29 -0800164 }
165
166 for _, tc := range testCases {
167 t.Run(tc.name, func(t *testing.T) {
168 out, err := Parse("test.d", bytes.NewBufferString(tc.input))
169 if err != tc.err {
170 t.Fatalf("Unexpected error: %v (expected %v)", err, tc.err)
171 }
172
173 if out.Output != tc.output.Output {
174 t.Errorf("output file doesn't match:\n"+
175 " str: %#v\n"+
176 "want: %#v\n"+
177 " got: %#v", tc.input, tc.output.Output, out.Output)
178 }
179
180 matches := true
181 if len(out.Inputs) != len(tc.output.Inputs) {
182 matches = false
183 } else {
184 for i := range out.Inputs {
185 if out.Inputs[i] != tc.output.Inputs[i] {
186 matches = false
187 }
188 }
189 }
190 if !matches {
191 t.Errorf("input files don't match:\n"+
192 " str: %#v\n"+
193 "want: %#v\n"+
194 " got: %#v", tc.input, tc.output.Inputs, out.Inputs)
195 }
196 })
197 }
198}
199
200func BenchmarkParsing(b *testing.B) {
201 // Write it out to a file to most closely match ninja's perftest
202 tmpfile, err := ioutil.TempFile("", "depfile")
203 if err != nil {
204 b.Fatal("Failed to create temp file:", err)
205 }
206 defer os.Remove(tmpfile.Name())
207 _, err = io.WriteString(tmpfile, `out/soong/.intermediates/external/ninja/ninja/linux_glibc_x86_64/obj/external/ninja/src/ninja.o: \
208 external/ninja/src/ninja.cc external/libcxx/include/errno.h \
209 external/libcxx/include/__config \
210 prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8/sysroot/usr/include/features.h \
211 prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8/sysroot/usr/include/x86_64-linux-gnu/bits/predefs.h \
212 prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8/sysroot/usr/include/x86_64-linux-gnu/sys/cdefs.h \
213 prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8/sysroot/usr/include/x86_64-linux-gnu/bits/wordsize.h \
214 prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8/sysroot/usr/include/x86_64-linux-gnu/gnu/stubs.h \
215 prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8/sysroot/usr/include/x86_64-linux-gnu/gnu/stubs-64.h \
216 prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8/sysroot/usr/include/errno.h \
217 prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8/sysroot/usr/include/x86_64-linux-gnu/bits/errno.h \
218 prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8/sysroot/usr/include/linux/errno.h \
219 prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8/sysroot/usr/include/x86_64-linux-gnu/asm/errno.h \
220 prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8/sysroot/usr/include/asm-generic/errno.h \
221 prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8/sysroot/usr/include/asm-generic/errno-base.h \
222 external/libcxx/include/limits.h \
223 prebuilts/clang/host/linux-x86/clang-4639204/lib64/clang/6.0.1/include/limits.h \
224 prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8/sysroot/usr/include/limits.h \
225 prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8/sysroot/usr/include/x86_64-linux-gnu/bits/posix1_lim.h \
226 prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8/sysroot/usr/include/x86_64-linux-gnu/bits/local_lim.h \
227 prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8/sysroot/usr/include/linux/limits.h \
228 prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8/sysroot/usr/include/x86_64-linux-gnu/bits/posix2_lim.h \
229 prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8/sysroot/usr/include/x86_64-linux-gnu/bits/xopen_lim.h \
230 prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8/sysroot/usr/include/x86_64-linux-gnu/bits/stdio_lim.h \
231 external/libcxx/include/stdio.h \
232 prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8/sysroot/usr/include/stdio.h \
233 external/libcxx/include/stddef.h \
234 prebuilts/clang/host/linux-x86/clang-4639204/lib64/clang/6.0.1/include/stddef.h \
235 prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8/sysroot/usr/include/x86_64-linux-gnu/bits/types.h \
236 prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8/sysroot/usr/include/x86_64-linux-gnu/bits/typesizes.h \
237 prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8/sysroot/usr/include/libio.h \
238 prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8/sysroot/usr/include/_G_config.h \
239 external/libcxx/include/wchar.h \
240 prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8/sysroot/usr/include/wchar.h \
241 prebuilts/clang/host/linux-x86/clang-4639204/lib64/clang/6.0.1/include/stdarg.h \
242 prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8/sysroot/usr/include/x86_64-linux-gnu/bits/sys_errlist.h \
243 external/libcxx/include/stdlib.h \
244 prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8/sysroot/usr/include/stdlib.h \
245 prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8/sysroot/usr/include/x86_64-linux-gnu/bits/waitflags.h \
246 prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8/sysroot/usr/include/x86_64-linux-gnu/bits/waitstatus.h \
247 prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8/sysroot/usr/include/endian.h \
248 prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8/sysroot/usr/include/x86_64-linux-gnu/bits/endian.h \
249 prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8/sysroot/usr/include/x86_64-linux-gnu/bits/byteswap.h \
250 prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8/sysroot/usr/include/xlocale.h \
251 prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8/sysroot/usr/include/x86_64-linux-gnu/sys/types.h \
252 prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8/sysroot/usr/include/time.h \
253 prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8/sysroot/usr/include/x86_64-linux-gnu/sys/select.h \
254 prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8/sysroot/usr/include/x86_64-linux-gnu/bits/select.h \
255 prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8/sysroot/usr/include/x86_64-linux-gnu/bits/sigset.h \
256 prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8/sysroot/usr/include/x86_64-linux-gnu/bits/time.h \
257 prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8/sysroot/usr/include/x86_64-linux-gnu/bits/select2.h \
258 prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8/sysroot/usr/include/x86_64-linux-gnu/sys/sysmacros.h \
259 prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8/sysroot/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h \
260 prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8/sysroot/usr/include/alloca.h \
261 external/libcxx/include/string.h \
262 prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8/sysroot/usr/include/string.h \
263 prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8/sysroot/usr/include/getopt.h \
264 prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8/sysroot/usr/include/unistd.h \
265 prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8/sysroot/usr/include/x86_64-linux-gnu/bits/posix_opt.h \
266 prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8/sysroot/usr/include/x86_64-linux-gnu/bits/environments.h \
267 prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8/sysroot/usr/include/x86_64-linux-gnu/bits/confname.h \
268 external/ninja/src/browse.h external/ninja/src/build.h \
269 external/libcxx/include/cstdio external/libcxx/include/map \
270 external/libcxx/include/__tree external/libcxx/include/iterator \
271 external/libcxx/include/iosfwd \
272 prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8/sysroot/usr/include/x86_64-linux-gnu/bits/wchar.h \
273 external/libcxx/include/__functional_base \
274 external/libcxx/include/type_traits external/libcxx/include/cstddef \
275 prebuilts/clang/host/linux-x86/clang-4639204/lib64/clang/6.0.1/include/__stddef_max_align_t.h \
276 external/libcxx/include/__nullptr external/libcxx/include/typeinfo \
277 external/libcxx/include/exception external/libcxx/include/cstdlib \
278 external/libcxx/include/cstdint external/libcxx/include/stdint.h \
279 prebuilts/clang/host/linux-x86/clang-4639204/lib64/clang/6.0.1/include/stdint.h \
280 prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8/sysroot/usr/include/stdint.h \
281 external/libcxx/include/new external/libcxx/include/utility \
282 external/libcxx/include/__tuple \
283 external/libcxx/include/initializer_list \
284 external/libcxx/include/cstring external/libcxx/include/__debug \
285 external/libcxx/include/memory external/libcxx/include/limits \
286 external/libcxx/include/__undef_macros external/libcxx/include/tuple \
287 external/libcxx/include/stdexcept external/libcxx/include/cassert \
288 prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8/sysroot/usr/include/assert.h \
289 external/libcxx/include/atomic external/libcxx/include/algorithm \
290 external/libcxx/include/functional external/libcxx/include/queue \
291 external/libcxx/include/deque external/libcxx/include/__split_buffer \
292 external/libcxx/include/vector external/libcxx/include/__bit_reference \
293 external/libcxx/include/climits external/libcxx/include/set \
294 external/libcxx/include/string external/libcxx/include/string_view \
295 external/libcxx/include/__string external/libcxx/include/cwchar \
296 external/libcxx/include/cwctype external/libcxx/include/cctype \
297 external/libcxx/include/ctype.h \
298 prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8/sysroot/usr/include/ctype.h \
299 external/libcxx/include/wctype.h \
300 prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8/sysroot/usr/include/wctype.h \
301 external/ninja/src/graph.h external/ninja/src/eval_env.h \
302 external/ninja/src/string_piece.h external/ninja/src/timestamp.h \
303 external/ninja/src/util.h external/ninja/src/exit_status.h \
304 external/ninja/src/line_printer.h external/ninja/src/metrics.h \
305 external/ninja/src/build_log.h external/ninja/src/hash_map.h \
306 external/libcxx/include/unordered_map \
307 external/libcxx/include/__hash_table external/libcxx/include/cmath \
308 external/libcxx/include/math.h \
309 prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8/sysroot/usr/include/math.h \
310 prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8/sysroot/usr/include/x86_64-linux-gnu/bits/huge_val.h \
311 prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8/sysroot/usr/include/x86_64-linux-gnu/bits/huge_valf.h \
312 prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8/sysroot/usr/include/x86_64-linux-gnu/bits/huge_vall.h \
313 prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8/sysroot/usr/include/x86_64-linux-gnu/bits/inf.h \
314 prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8/sysroot/usr/include/x86_64-linux-gnu/bits/nan.h \
315 prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8/sysroot/usr/include/x86_64-linux-gnu/bits/mathdef.h \
316 prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8/sysroot/usr/include/x86_64-linux-gnu/bits/mathcalls.h \
317 external/ninja/src/deps_log.h external/ninja/src/clean.h \
318 external/ninja/src/debug_flags.h external/ninja/src/disk_interface.h \
319 external/ninja/src/graphviz.h external/ninja/src/manifest_parser.h \
320 external/ninja/src/lexer.h external/ninja/src/state.h \
321 external/ninja/src/version.h`)
322 tmpfile.Close()
323 if err != nil {
324 b.Fatal("Failed to write dep file:", err)
325 }
326 b.ResetTimer()
327
328 for n := 0; n < b.N; n++ {
329 depfile, err := ioutil.ReadFile(tmpfile.Name())
330 if err != nil {
331 b.Fatal("Failed to read dep file:", err)
332 }
333
334 _, err = Parse(tmpfile.Name(), bytes.NewBuffer(depfile))
335 if err != nil {
336 b.Fatal("Failed to parse:", err)
337 }
338 }
339}
340
341func TestDepPrint(t *testing.T) {
Dan Willemsen43398532018-02-21 02:10:29 -0800342 testCases := []struct {
343 name string
344 input Deps
345 output string
346 }{
347 {
348 name: "Empty",
349 input: Deps{
350 Output: "a",
351 },
352 output: "a:",
353 },
354 {
355 name: "Basic",
356 input: Deps{
357 Output: "a",
358 Inputs: []string{"b", "c"},
359 },
360 output: "a: b c",
361 },
362 {
363 name: "Escapes",
364 input: Deps{
365 Output: `\!\@#$\%\^\&\`,
366 },
367 output: `\\!\\@\#$$\\%\\^\\&\\:`,
368 },
369 {
370 name: "Spaces",
371 input: Deps{
372 Output: "a b",
373 Inputs: []string{"c d", "e f "},
374 },
375 output: `a\ b: c\ d e\ f\ `,
376 },
377 {
378 name: "SpecialChars",
379 input: Deps{
380 Output: "C:/Program Files (x86)/Microsoft crtdefs.h",
381 Inputs: []string{
382 "en@quot.header~",
383 "t+t-x!1",
384 "openldap/slapd.d/cnconfig/cnschema/cn{0}core.ldif",
385 "Fu\303\244ball",
386 },
387 },
388 output: `C\:/Program\ Files\ (x86)/Microsoft\ crtdefs.h: en@quot.header~ t+t-x!1 openldap/slapd.d/cnconfig/cnschema/cn{0}core.ldif Fu` + "\303\244ball",
389 },
390 }
391
392 for _, tc := range testCases {
393 t.Run(tc.name, func(t *testing.T) {
394 out := tc.input.Print()
395 outStr := string(out)
396 want := tc.output + "\n"
397
398 if outStr != want {
399 t.Errorf("output doesn't match:\nwant:%q\n got:%q", want, outStr)
400 }
401 })
402 }
403}