blob: b451f17c6ec250468ec1cb9f1ed23f3e25c0896d [file] [log] [blame]
Colin Cross74d1ec02015-04-28 13:30:13 -07001package cc
2
3import (
Colin Cross5b529592017-05-09 13:34:34 -07004 "android/soong/android"
Jeff Gaston294356f2017-09-27 17:05:30 -07005 "fmt"
Jiyong Park6a43f042017-10-12 23:05:00 +09006 "io/ioutil"
7 "os"
Colin Cross74d1ec02015-04-28 13:30:13 -07008 "reflect"
Jeff Gaston294356f2017-09-27 17:05:30 -07009 "sort"
10 "strings"
Colin Cross74d1ec02015-04-28 13:30:13 -070011 "testing"
12)
13
Jiyong Park6a43f042017-10-12 23:05:00 +090014var buildDir string
15
16func setUp() {
17 var err error
18 buildDir, err = ioutil.TempDir("", "soong_cc_test")
19 if err != nil {
20 panic(err)
21 }
22}
23
24func tearDown() {
25 os.RemoveAll(buildDir)
26}
27
28func TestMain(m *testing.M) {
29 run := func() int {
30 setUp()
31 defer tearDown()
32
33 return m.Run()
34 }
35
36 os.Exit(run())
37}
38
39func testCc(t *testing.T, bp string) *android.TestContext {
40 config := android.TestArchConfig(buildDir, nil)
Nan Zhang0007d812017-11-07 10:57:05 -080041 config.ProductVariables.DeviceVndkVersion = StringPtr("current")
Jiyong Park6a43f042017-10-12 23:05:00 +090042
43 ctx := android.NewTestArchContext()
Steven Morelandf9e62162017-11-02 17:00:50 -070044 ctx.RegisterModuleType("cc_library", android.ModuleFactoryAdaptor(LibraryFactory))
Jiyong Park6a43f042017-10-12 23:05:00 +090045 ctx.RegisterModuleType("toolchain_library", android.ModuleFactoryAdaptor(toolchainLibraryFactory))
46 ctx.RegisterModuleType("llndk_library", android.ModuleFactoryAdaptor(llndkLibraryFactory))
Jeff Gaston294356f2017-09-27 17:05:30 -070047 ctx.RegisterModuleType("cc_object", android.ModuleFactoryAdaptor(objectFactory))
Jiyong Park6a43f042017-10-12 23:05:00 +090048 ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
49 ctx.BottomUp("image", vendorMutator).Parallel()
50 ctx.BottomUp("link", linkageMutator).Parallel()
51 ctx.BottomUp("vndk", vndkMutator).Parallel()
52 })
53 ctx.Register()
54
Jeff Gaston294356f2017-09-27 17:05:30 -070055 // add some modules that are required by the compiler and/or linker
56 bp = bp + `
57 toolchain_library {
58 name: "libatomic",
59 vendor_available: true,
60 }
61
62 toolchain_library {
63 name: "libcompiler_rt-extras",
64 vendor_available: true,
65 }
66
67 toolchain_library {
68 name: "libgcc",
69 vendor_available: true,
70 }
71
72 cc_library {
73 name: "libc",
74 no_libgcc : true,
75 nocrt : true,
76 system_shared_libs: [],
77 }
78 llndk_library {
79 name: "libc",
80 symbol_file: "",
81 }
82 cc_library {
83 name: "libm",
84 no_libgcc : true,
85 nocrt : true,
86 system_shared_libs: [],
87 }
88 llndk_library {
89 name: "libm",
90 symbol_file: "",
91 }
92 cc_library {
93 name: "libdl",
94 no_libgcc : true,
95 nocrt : true,
96 system_shared_libs: [],
97 }
98 llndk_library {
99 name: "libdl",
100 symbol_file: "",
101 }
102
103 cc_object {
104 name: "crtbegin_so",
105 }
106
107 cc_object {
108 name: "crtend_so",
109 }
110
Colin Crossad59e752017-11-16 14:29:11 -0800111 cc_library {
112 name: "libprotobuf-cpp-lite",
113 }
114
Jeff Gaston294356f2017-09-27 17:05:30 -0700115`
116
Jiyong Park6a43f042017-10-12 23:05:00 +0900117 ctx.MockFileSystem(map[string][]byte{
118 "Android.bp": []byte(bp),
119 "foo.c": nil,
120 "bar.c": nil,
Colin Crossad59e752017-11-16 14:29:11 -0800121 "a.proto": nil,
Jiyong Park6a43f042017-10-12 23:05:00 +0900122 })
123
Jeff Gastond3e141d2017-08-08 17:46:01 -0700124 _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
Jeff Gaston294356f2017-09-27 17:05:30 -0700125 failIfErrored(t, errs)
Jiyong Park6a43f042017-10-12 23:05:00 +0900126 _, errs = ctx.PrepareBuildActions(config)
Jeff Gaston294356f2017-09-27 17:05:30 -0700127 failIfErrored(t, errs)
Jiyong Park6a43f042017-10-12 23:05:00 +0900128
129 return ctx
130}
131
132func TestVendorSrc(t *testing.T) {
133 ctx := testCc(t, `
134 cc_library {
135 name: "libTest",
136 srcs: ["foo.c"],
137 no_libgcc : true,
138 nocrt : true,
139 system_shared_libs : [],
140 vendor_available: true,
141 target: {
142 vendor: {
143 srcs: ["bar.c"],
144 },
145 },
146 }
Jiyong Park6a43f042017-10-12 23:05:00 +0900147 `)
148
149 ld := ctx.ModuleForTests("libTest", "android_arm_armv7-a-neon_vendor_shared").Rule("ld")
150 var objs []string
151 for _, o := range ld.Inputs {
152 objs = append(objs, o.Base())
153 }
154 if len(objs) != 2 {
155 t.Errorf("inputs of libTest is expected to 2, but was %d.", len(objs))
156 }
157 if objs[0] != "foo.o" || objs[1] != "bar.o" {
158 t.Errorf("inputs of libTest must be []string{\"foo.o\", \"bar.o\"}, but was %#v.", objs)
159 }
160}
161
Colin Cross0af4b842015-04-30 16:36:18 -0700162var (
163 str11 = "01234567891"
164 str10 = str11[:10]
165 str9 = str11[:9]
166 str5 = str11[:5]
167 str4 = str11[:4]
168)
169
170var splitListForSizeTestCases = []struct {
171 in []string
172 out [][]string
173 size int
174}{
175 {
176 in: []string{str10},
177 out: [][]string{{str10}},
178 size: 10,
179 },
180 {
181 in: []string{str9},
182 out: [][]string{{str9}},
183 size: 10,
184 },
185 {
186 in: []string{str5},
187 out: [][]string{{str5}},
188 size: 10,
189 },
190 {
191 in: []string{str11},
192 out: nil,
193 size: 10,
194 },
195 {
196 in: []string{str10, str10},
197 out: [][]string{{str10}, {str10}},
198 size: 10,
199 },
200 {
201 in: []string{str9, str10},
202 out: [][]string{{str9}, {str10}},
203 size: 10,
204 },
205 {
206 in: []string{str10, str9},
207 out: [][]string{{str10}, {str9}},
208 size: 10,
209 },
210 {
211 in: []string{str5, str4},
212 out: [][]string{{str5, str4}},
213 size: 10,
214 },
215 {
216 in: []string{str5, str4, str5},
217 out: [][]string{{str5, str4}, {str5}},
218 size: 10,
219 },
220 {
221 in: []string{str5, str4, str5, str4},
222 out: [][]string{{str5, str4}, {str5, str4}},
223 size: 10,
224 },
225 {
226 in: []string{str5, str4, str5, str5},
227 out: [][]string{{str5, str4}, {str5}, {str5}},
228 size: 10,
229 },
230 {
231 in: []string{str5, str5, str5, str4},
232 out: [][]string{{str5}, {str5}, {str5, str4}},
233 size: 10,
234 },
235 {
236 in: []string{str9, str11},
237 out: nil,
238 size: 10,
239 },
240 {
241 in: []string{str11, str9},
242 out: nil,
243 size: 10,
244 },
245}
246
247func TestSplitListForSize(t *testing.T) {
248 for _, testCase := range splitListForSizeTestCases {
Colin Cross5b529592017-05-09 13:34:34 -0700249 out, _ := splitListForSize(android.PathsForTesting(testCase.in), testCase.size)
250
251 var outStrings [][]string
252
253 if len(out) > 0 {
254 outStrings = make([][]string, len(out))
255 for i, o := range out {
256 outStrings[i] = o.Strings()
257 }
258 }
259
260 if !reflect.DeepEqual(outStrings, testCase.out) {
Colin Cross0af4b842015-04-30 16:36:18 -0700261 t.Errorf("incorrect output:")
262 t.Errorf(" input: %#v", testCase.in)
263 t.Errorf(" size: %d", testCase.size)
264 t.Errorf(" expected: %#v", testCase.out)
Colin Cross5b529592017-05-09 13:34:34 -0700265 t.Errorf(" got: %#v", outStrings)
Colin Cross0af4b842015-04-30 16:36:18 -0700266 }
267 }
268}
Jeff Gaston294356f2017-09-27 17:05:30 -0700269
270var staticLinkDepOrderTestCases = []struct {
271 // This is a string representation of a map[moduleName][]moduleDependency .
272 // It models the dependencies declared in an Android.bp file.
273 in string
274
275 // allOrdered is a string representation of a map[moduleName][]moduleDependency .
276 // The keys of allOrdered specify which modules we would like to check.
277 // The values of allOrdered specify the expected result (of the transitive closure of all
278 // dependencies) for each module to test
279 allOrdered string
280
281 // outOrdered is a string representation of a map[moduleName][]moduleDependency .
282 // The keys of outOrdered specify which modules we would like to check.
283 // The values of outOrdered specify the expected result (of the ordered linker command line)
284 // for each module to test.
285 outOrdered string
286}{
287 // Simple tests
288 {
289 in: "",
290 outOrdered: "",
291 },
292 {
293 in: "a:",
294 outOrdered: "a:",
295 },
296 {
297 in: "a:b; b:",
298 outOrdered: "a:b; b:",
299 },
300 // Tests of reordering
301 {
302 // diamond example
303 in: "a:d,b,c; b:d; c:d; d:",
304 outOrdered: "a:b,c,d; b:d; c:d; d:",
305 },
306 {
307 // somewhat real example
308 in: "bsdiff_unittest:b,c,d,e,f,g,h,i; e:b",
309 outOrdered: "bsdiff_unittest:c,d,e,b,f,g,h,i; e:b",
310 },
311 {
312 // multiple reorderings
313 in: "a:b,c,d,e; d:b; e:c",
314 outOrdered: "a:d,b,e,c; d:b; e:c",
315 },
316 {
317 // should reorder without adding new transitive dependencies
318 in: "bin:lib2,lib1; lib1:lib2,liboptional",
319 allOrdered: "bin:lib1,lib2,liboptional; lib1:lib2,liboptional",
320 outOrdered: "bin:lib1,lib2; lib1:lib2,liboptional",
321 },
322 {
323 // multiple levels of dependencies
324 in: "a:b,c,d,e,f,g,h; f:b,c,d; b:c,d; c:d",
325 allOrdered: "a:e,f,b,c,d,g,h; f:b,c,d; b:c,d; c:d",
326 outOrdered: "a:e,f,b,c,d,g,h; f:b,c,d; b:c,d; c:d",
327 },
328 // tiebreakers for when two modules specifying different orderings and there is no dependency
329 // to dictate an order
330 {
331 // if the tie is between two modules at the end of a's deps, then a's order wins
332 in: "a1:b,c,d,e; a2:b,c,e,d; b:d,e; c:e,d",
333 outOrdered: "a1:b,c,d,e; a2:b,c,e,d; b:d,e; c:e,d",
334 },
335 {
336 // if the tie is between two modules at the start of a's deps, then c's order is used
337 in: "a1:d,e,b1,c1; b1:d,e; c1:e,d; a2:d,e,b2,c2; b2:d,e; c2:d,e",
338 outOrdered: "a1:b1,c1,e,d; b1:d,e; c1:e,d; a2:b2,c2,d,e; b2:d,e; c2:d,e",
339 },
340 // Tests involving duplicate dependencies
341 {
342 // simple duplicate
343 in: "a:b,c,c,b",
344 outOrdered: "a:c,b",
345 },
346 {
347 // duplicates with reordering
348 in: "a:b,c,d,c; c:b",
349 outOrdered: "a:d,c,b",
350 },
351 // Tests to confirm the nonexistence of infinite loops.
352 // These cases should never happen, so as long as the test terminates and the
353 // result is deterministic then that should be fine.
354 {
355 in: "a:a",
356 outOrdered: "a:a",
357 },
358 {
359 in: "a:b; b:c; c:a",
360 allOrdered: "a:b,c; b:c,a; c:a,b",
361 outOrdered: "a:b; b:c; c:a",
362 },
363 {
364 in: "a:b,c; b:c,a; c:a,b",
365 allOrdered: "a:c,a,b; b:a,b,c; c:b,c,a",
366 outOrdered: "a:c,b; b:a,c; c:b,a",
367 },
368}
369
370// converts from a string like "a:b,c; d:e" to (["a","b"], {"a":["b","c"], "d":["e"]}, [{"a", "a.o"}, {"b", "b.o"}])
371func parseModuleDeps(text string) (modulesInOrder []android.Path, allDeps map[android.Path][]android.Path) {
372 // convert from "a:b,c; d:e" to "a:b,c;d:e"
373 strippedText := strings.Replace(text, " ", "", -1)
374 if len(strippedText) < 1 {
375 return []android.Path{}, make(map[android.Path][]android.Path, 0)
376 }
377 allDeps = make(map[android.Path][]android.Path, 0)
378
379 // convert from "a:b,c;d:e" to ["a:b,c", "d:e"]
380 moduleTexts := strings.Split(strippedText, ";")
381
382 outputForModuleName := func(moduleName string) android.Path {
383 return android.PathForTesting(moduleName)
384 }
385
386 for _, moduleText := range moduleTexts {
387 // convert from "a:b,c" to ["a", "b,c"]
388 components := strings.Split(moduleText, ":")
389 if len(components) != 2 {
390 panic(fmt.Sprintf("illegal module dep string %q from larger string %q; must contain one ':', not %v", moduleText, text, len(components)-1))
391 }
392 moduleName := components[0]
393 moduleOutput := outputForModuleName(moduleName)
394 modulesInOrder = append(modulesInOrder, moduleOutput)
395
396 depString := components[1]
397 // convert from "b,c" to ["b", "c"]
398 depNames := strings.Split(depString, ",")
399 if len(depString) < 1 {
400 depNames = []string{}
401 }
402 var deps []android.Path
403 for _, depName := range depNames {
404 deps = append(deps, outputForModuleName(depName))
405 }
406 allDeps[moduleOutput] = deps
407 }
408 return modulesInOrder, allDeps
409}
410
411func TestStaticLinkDependencyOrdering(t *testing.T) {
412 for _, testCase := range staticLinkDepOrderTestCases {
413 errs := []string{}
414
415 // parse testcase
416 _, givenTransitiveDeps := parseModuleDeps(testCase.in)
417 expectedModuleNames, expectedTransitiveDeps := parseModuleDeps(testCase.outOrdered)
418 if testCase.allOrdered == "" {
419 // allow the test case to skip specifying allOrdered
420 testCase.allOrdered = testCase.outOrdered
421 }
422 _, expectedAllDeps := parseModuleDeps(testCase.allOrdered)
423
424 // For each module whose post-reordered dependencies were specified, validate that
425 // reordering the inputs produces the expected outputs.
426 for _, moduleName := range expectedModuleNames {
427 moduleDeps := givenTransitiveDeps[moduleName]
428 orderedAllDeps, orderedDeclaredDeps := orderDeps(moduleDeps, givenTransitiveDeps)
429
430 correctAllOrdered := expectedAllDeps[moduleName]
431 if !reflect.DeepEqual(orderedAllDeps, correctAllOrdered) {
432 errs = append(errs, fmt.Sprintf("orderDeps returned incorrect orderedAllDeps."+
433 "\nInput: %q"+
434 "\nmodule: %v"+
435 "\nexpected: %s"+
436 "\nactual: %s",
437 testCase.in, moduleName, correctAllOrdered, orderedAllDeps))
438 }
439
440 correctOutputDeps := expectedTransitiveDeps[moduleName]
441 if !reflect.DeepEqual(correctOutputDeps, orderedDeclaredDeps) {
442 errs = append(errs, fmt.Sprintf("orderDeps returned incorrect orderedDeclaredDeps."+
443 "\nInput: %q"+
444 "\nmodule: %v"+
445 "\nexpected: %s"+
446 "\nactual: %s",
447 testCase.in, moduleName, correctOutputDeps, orderedDeclaredDeps))
448 }
449 }
450
451 if len(errs) > 0 {
452 sort.Strings(errs)
453 for _, err := range errs {
454 t.Error(err)
455 }
456 }
457 }
458}
459func failIfErrored(t *testing.T, errs []error) {
460 if len(errs) > 0 {
461 for _, err := range errs {
462 t.Error(err)
463 }
464 t.FailNow()
465 }
466}
467
468func getOutputPaths(ctx *android.TestContext, variant string, moduleNames []string) (paths android.Paths) {
469 for _, moduleName := range moduleNames {
470 module := ctx.ModuleForTests(moduleName, variant).Module().(*Module)
471 output := module.outputFile.Path()
472 paths = append(paths, output)
473 }
474 return paths
475}
476
477func TestLibDeps(t *testing.T) {
478 ctx := testCc(t, `
479 cc_library {
480 name: "a",
481 static_libs: ["b", "c", "d"],
482 }
483 cc_library {
484 name: "b",
485 }
486 cc_library {
487 name: "c",
488 static_libs: ["b"],
489 }
490 cc_library {
491 name: "d",
492 }
493
494 `)
495
496 variant := "android_arm64_armv8-a_core_static"
497 moduleA := ctx.ModuleForTests("a", variant).Module().(*Module)
498 actual := moduleA.staticDepsInLinkOrder
499 expected := getOutputPaths(ctx, variant, []string{"c", "b", "d"})
500
501 if !reflect.DeepEqual(actual, expected) {
502 t.Errorf("staticDeps orderings were not propagated correctly"+
503 "\nactual: %v"+
504 "\nexpected: %v",
505 actual,
506 expected,
507 )
508 }
Jiyong Parkd08b6972017-09-26 10:50:54 +0900509}
Jeff Gaston294356f2017-09-27 17:05:30 -0700510
Jiyong Parkd08b6972017-09-26 10:50:54 +0900511var compilerFlagsTestCases = []struct {
512 in string
513 out bool
514}{
515 {
516 in: "a",
517 out: false,
518 },
519 {
520 in: "-a",
521 out: true,
522 },
523 {
524 in: "-Ipath/to/something",
525 out: false,
526 },
527 {
528 in: "-isystempath/to/something",
529 out: false,
530 },
531 {
532 in: "--coverage",
533 out: false,
534 },
535 {
536 in: "-include a/b",
537 out: true,
538 },
539 {
540 in: "-include a/b c/d",
541 out: false,
542 },
543 {
544 in: "-DMACRO",
545 out: true,
546 },
547 {
548 in: "-DMAC RO",
549 out: false,
550 },
551 {
552 in: "-a -b",
553 out: false,
554 },
555 {
556 in: "-DMACRO=definition",
557 out: true,
558 },
559 {
560 in: "-DMACRO=defi nition",
561 out: true, // TODO(jiyong): this should be false
562 },
563 {
564 in: "-DMACRO(x)=x + 1",
565 out: true,
566 },
567 {
568 in: "-DMACRO=\"defi nition\"",
569 out: true,
570 },
571}
572
573type mockContext struct {
574 BaseModuleContext
575 result bool
576}
577
578func (ctx *mockContext) PropertyErrorf(property, format string, args ...interface{}) {
579 // CheckBadCompilerFlags calls this function when the flag should be rejected
580 ctx.result = false
581}
582
583func TestCompilerFlags(t *testing.T) {
584 for _, testCase := range compilerFlagsTestCases {
585 ctx := &mockContext{result: true}
586 CheckBadCompilerFlags(ctx, "", []string{testCase.in})
587 if ctx.result != testCase.out {
588 t.Errorf("incorrect output:")
589 t.Errorf(" input: %#v", testCase.in)
590 t.Errorf(" expected: %#v", testCase.out)
591 t.Errorf(" got: %#v", ctx.result)
592 }
593 }
Jeff Gaston294356f2017-09-27 17:05:30 -0700594}