deps_test.go 16 KB

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