blob: 4d8c4fb207b79a94d6dc4690f2fd11a10e3e6278 [file] [log] [blame]
Colin Crossd00350c2017-11-17 10:55:38 -08001// Copyright 2017 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
Colin Cross74d1ec02015-04-28 13:30:13 -070015package cc
16
17import (
Colin Cross5b529592017-05-09 13:34:34 -070018 "android/soong/android"
Colin Crossf18e1102017-11-16 14:33:08 -080019 "android/soong/genrule"
20
Jeff Gaston294356f2017-09-27 17:05:30 -070021 "fmt"
Jiyong Park6a43f042017-10-12 23:05:00 +090022 "io/ioutil"
23 "os"
Colin Cross74d1ec02015-04-28 13:30:13 -070024 "reflect"
Jeff Gaston294356f2017-09-27 17:05:30 -070025 "sort"
26 "strings"
Colin Cross74d1ec02015-04-28 13:30:13 -070027 "testing"
28)
29
Jiyong Park6a43f042017-10-12 23:05:00 +090030var buildDir string
31
32func setUp() {
33 var err error
34 buildDir, err = ioutil.TempDir("", "soong_cc_test")
35 if err != nil {
36 panic(err)
37 }
38}
39
40func tearDown() {
41 os.RemoveAll(buildDir)
42}
43
44func TestMain(m *testing.M) {
45 run := func() int {
46 setUp()
47 defer tearDown()
48
49 return m.Run()
50 }
51
52 os.Exit(run())
53}
54
55func testCc(t *testing.T, bp string) *android.TestContext {
56 config := android.TestArchConfig(buildDir, nil)
Nan Zhang0007d812017-11-07 10:57:05 -080057 config.ProductVariables.DeviceVndkVersion = StringPtr("current")
Jiyong Park6a43f042017-10-12 23:05:00 +090058
59 ctx := android.NewTestArchContext()
Steven Morelandf9e62162017-11-02 17:00:50 -070060 ctx.RegisterModuleType("cc_library", android.ModuleFactoryAdaptor(LibraryFactory))
Colin Crossf18e1102017-11-16 14:33:08 -080061 ctx.RegisterModuleType("cc_library_shared", android.ModuleFactoryAdaptor(LibrarySharedFactory))
Jiyong Park6a43f042017-10-12 23:05:00 +090062 ctx.RegisterModuleType("toolchain_library", android.ModuleFactoryAdaptor(toolchainLibraryFactory))
63 ctx.RegisterModuleType("llndk_library", android.ModuleFactoryAdaptor(llndkLibraryFactory))
Jiyong Parka46a4d52017-12-14 19:54:34 +090064 ctx.RegisterModuleType("llndk_headers", android.ModuleFactoryAdaptor(llndkHeadersFactory))
Jeff Gaston294356f2017-09-27 17:05:30 -070065 ctx.RegisterModuleType("cc_object", android.ModuleFactoryAdaptor(objectFactory))
Colin Crossf18e1102017-11-16 14:33:08 -080066 ctx.RegisterModuleType("filegroup", android.ModuleFactoryAdaptor(genrule.FileGroupFactory))
Jiyong Park6a43f042017-10-12 23:05:00 +090067 ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
68 ctx.BottomUp("image", vendorMutator).Parallel()
69 ctx.BottomUp("link", linkageMutator).Parallel()
70 ctx.BottomUp("vndk", vndkMutator).Parallel()
71 })
72 ctx.Register()
73
Jeff Gaston294356f2017-09-27 17:05:30 -070074 // add some modules that are required by the compiler and/or linker
75 bp = bp + `
76 toolchain_library {
77 name: "libatomic",
78 vendor_available: true,
79 }
80
81 toolchain_library {
82 name: "libcompiler_rt-extras",
83 vendor_available: true,
84 }
85
86 toolchain_library {
87 name: "libgcc",
88 vendor_available: true,
89 }
90
91 cc_library {
92 name: "libc",
93 no_libgcc : true,
94 nocrt : true,
95 system_shared_libs: [],
96 }
97 llndk_library {
98 name: "libc",
99 symbol_file: "",
100 }
101 cc_library {
102 name: "libm",
103 no_libgcc : true,
104 nocrt : true,
105 system_shared_libs: [],
106 }
107 llndk_library {
108 name: "libm",
109 symbol_file: "",
110 }
111 cc_library {
112 name: "libdl",
113 no_libgcc : true,
114 nocrt : true,
115 system_shared_libs: [],
116 }
117 llndk_library {
118 name: "libdl",
119 symbol_file: "",
120 }
121
122 cc_object {
123 name: "crtbegin_so",
124 }
125
126 cc_object {
127 name: "crtend_so",
128 }
129
Colin Crossad59e752017-11-16 14:29:11 -0800130 cc_library {
131 name: "libprotobuf-cpp-lite",
132 }
133
Jeff Gaston294356f2017-09-27 17:05:30 -0700134`
135
Jiyong Park6a43f042017-10-12 23:05:00 +0900136 ctx.MockFileSystem(map[string][]byte{
137 "Android.bp": []byte(bp),
138 "foo.c": nil,
139 "bar.c": nil,
Colin Crossad59e752017-11-16 14:29:11 -0800140 "a.proto": nil,
Colin Crossf18e1102017-11-16 14:33:08 -0800141 "b.aidl": nil,
Jiyong Parka46a4d52017-12-14 19:54:34 +0900142 "my_include": nil,
Jiyong Park6a43f042017-10-12 23:05:00 +0900143 })
144
Jeff Gastond3e141d2017-08-08 17:46:01 -0700145 _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
Jeff Gaston294356f2017-09-27 17:05:30 -0700146 failIfErrored(t, errs)
Jiyong Park6a43f042017-10-12 23:05:00 +0900147 _, errs = ctx.PrepareBuildActions(config)
Jeff Gaston294356f2017-09-27 17:05:30 -0700148 failIfErrored(t, errs)
Jiyong Park6a43f042017-10-12 23:05:00 +0900149
150 return ctx
151}
152
153func TestVendorSrc(t *testing.T) {
154 ctx := testCc(t, `
155 cc_library {
156 name: "libTest",
157 srcs: ["foo.c"],
158 no_libgcc : true,
159 nocrt : true,
160 system_shared_libs : [],
161 vendor_available: true,
162 target: {
163 vendor: {
164 srcs: ["bar.c"],
165 },
166 },
167 }
Jiyong Park6a43f042017-10-12 23:05:00 +0900168 `)
169
170 ld := ctx.ModuleForTests("libTest", "android_arm_armv7-a-neon_vendor_shared").Rule("ld")
171 var objs []string
172 for _, o := range ld.Inputs {
173 objs = append(objs, o.Base())
174 }
Colin Cross95d33fe2018-01-03 13:40:46 -0800175 if len(objs) != 2 || objs[0] != "foo.o" || objs[1] != "bar.o" {
Jiyong Park6a43f042017-10-12 23:05:00 +0900176 t.Errorf("inputs of libTest must be []string{\"foo.o\", \"bar.o\"}, but was %#v.", objs)
177 }
178}
179
Colin Cross0af4b842015-04-30 16:36:18 -0700180var (
181 str11 = "01234567891"
182 str10 = str11[:10]
183 str9 = str11[:9]
184 str5 = str11[:5]
185 str4 = str11[:4]
186)
187
188var splitListForSizeTestCases = []struct {
189 in []string
190 out [][]string
191 size int
192}{
193 {
194 in: []string{str10},
195 out: [][]string{{str10}},
196 size: 10,
197 },
198 {
199 in: []string{str9},
200 out: [][]string{{str9}},
201 size: 10,
202 },
203 {
204 in: []string{str5},
205 out: [][]string{{str5}},
206 size: 10,
207 },
208 {
209 in: []string{str11},
210 out: nil,
211 size: 10,
212 },
213 {
214 in: []string{str10, str10},
215 out: [][]string{{str10}, {str10}},
216 size: 10,
217 },
218 {
219 in: []string{str9, str10},
220 out: [][]string{{str9}, {str10}},
221 size: 10,
222 },
223 {
224 in: []string{str10, str9},
225 out: [][]string{{str10}, {str9}},
226 size: 10,
227 },
228 {
229 in: []string{str5, str4},
230 out: [][]string{{str5, str4}},
231 size: 10,
232 },
233 {
234 in: []string{str5, str4, str5},
235 out: [][]string{{str5, str4}, {str5}},
236 size: 10,
237 },
238 {
239 in: []string{str5, str4, str5, str4},
240 out: [][]string{{str5, str4}, {str5, str4}},
241 size: 10,
242 },
243 {
244 in: []string{str5, str4, str5, str5},
245 out: [][]string{{str5, str4}, {str5}, {str5}},
246 size: 10,
247 },
248 {
249 in: []string{str5, str5, str5, str4},
250 out: [][]string{{str5}, {str5}, {str5, str4}},
251 size: 10,
252 },
253 {
254 in: []string{str9, str11},
255 out: nil,
256 size: 10,
257 },
258 {
259 in: []string{str11, str9},
260 out: nil,
261 size: 10,
262 },
263}
264
265func TestSplitListForSize(t *testing.T) {
266 for _, testCase := range splitListForSizeTestCases {
Colin Cross5b529592017-05-09 13:34:34 -0700267 out, _ := splitListForSize(android.PathsForTesting(testCase.in), testCase.size)
268
269 var outStrings [][]string
270
271 if len(out) > 0 {
272 outStrings = make([][]string, len(out))
273 for i, o := range out {
274 outStrings[i] = o.Strings()
275 }
276 }
277
278 if !reflect.DeepEqual(outStrings, testCase.out) {
Colin Cross0af4b842015-04-30 16:36:18 -0700279 t.Errorf("incorrect output:")
280 t.Errorf(" input: %#v", testCase.in)
281 t.Errorf(" size: %d", testCase.size)
282 t.Errorf(" expected: %#v", testCase.out)
Colin Cross5b529592017-05-09 13:34:34 -0700283 t.Errorf(" got: %#v", outStrings)
Colin Cross0af4b842015-04-30 16:36:18 -0700284 }
285 }
286}
Jeff Gaston294356f2017-09-27 17:05:30 -0700287
288var staticLinkDepOrderTestCases = []struct {
289 // This is a string representation of a map[moduleName][]moduleDependency .
290 // It models the dependencies declared in an Android.bp file.
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800291 inStatic string
292
293 // This is a string representation of a map[moduleName][]moduleDependency .
294 // It models the dependencies declared in an Android.bp file.
295 inShared string
Jeff Gaston294356f2017-09-27 17:05:30 -0700296
297 // allOrdered is a string representation of a map[moduleName][]moduleDependency .
298 // The keys of allOrdered specify which modules we would like to check.
299 // The values of allOrdered specify the expected result (of the transitive closure of all
300 // dependencies) for each module to test
301 allOrdered string
302
303 // outOrdered is a string representation of a map[moduleName][]moduleDependency .
304 // The keys of outOrdered specify which modules we would like to check.
305 // The values of outOrdered specify the expected result (of the ordered linker command line)
306 // for each module to test.
307 outOrdered string
308}{
309 // Simple tests
310 {
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800311 inStatic: "",
Jeff Gaston294356f2017-09-27 17:05:30 -0700312 outOrdered: "",
313 },
314 {
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800315 inStatic: "a:",
Jeff Gaston294356f2017-09-27 17:05:30 -0700316 outOrdered: "a:",
317 },
318 {
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800319 inStatic: "a:b; b:",
Jeff Gaston294356f2017-09-27 17:05:30 -0700320 outOrdered: "a:b; b:",
321 },
322 // Tests of reordering
323 {
324 // diamond example
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800325 inStatic: "a:d,b,c; b:d; c:d; d:",
Jeff Gaston294356f2017-09-27 17:05:30 -0700326 outOrdered: "a:b,c,d; b:d; c:d; d:",
327 },
328 {
329 // somewhat real example
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800330 inStatic: "bsdiff_unittest:b,c,d,e,f,g,h,i; e:b",
Jeff Gaston294356f2017-09-27 17:05:30 -0700331 outOrdered: "bsdiff_unittest:c,d,e,b,f,g,h,i; e:b",
332 },
333 {
334 // multiple reorderings
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800335 inStatic: "a:b,c,d,e; d:b; e:c",
Jeff Gaston294356f2017-09-27 17:05:30 -0700336 outOrdered: "a:d,b,e,c; d:b; e:c",
337 },
338 {
339 // should reorder without adding new transitive dependencies
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800340 inStatic: "bin:lib2,lib1; lib1:lib2,liboptional",
Jeff Gaston294356f2017-09-27 17:05:30 -0700341 allOrdered: "bin:lib1,lib2,liboptional; lib1:lib2,liboptional",
342 outOrdered: "bin:lib1,lib2; lib1:lib2,liboptional",
343 },
344 {
345 // multiple levels of dependencies
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800346 inStatic: "a:b,c,d,e,f,g,h; f:b,c,d; b:c,d; c:d",
Jeff Gaston294356f2017-09-27 17:05:30 -0700347 allOrdered: "a:e,f,b,c,d,g,h; f:b,c,d; b:c,d; c:d",
348 outOrdered: "a:e,f,b,c,d,g,h; f:b,c,d; b:c,d; c:d",
349 },
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800350 // shared dependencies
351 {
352 // Note that this test doesn't recurse, to minimize the amount of logic it tests.
353 // So, we don't actually have to check that a shared dependency of c will change the order
354 // of a library that depends statically on b and on c. We only need to check that if c has
355 // a shared dependency on b, that that shows up in allOrdered.
356 inShared: "c:b",
357 allOrdered: "c:b",
358 outOrdered: "c:",
359 },
360 {
361 // This test doesn't actually include any shared dependencies but it's a reminder of what
362 // the second phase of the above test would look like
363 inStatic: "a:b,c; c:b",
364 allOrdered: "a:c,b; c:b",
365 outOrdered: "a:c,b; c:b",
366 },
Jeff Gaston294356f2017-09-27 17:05:30 -0700367 // tiebreakers for when two modules specifying different orderings and there is no dependency
368 // to dictate an order
369 {
370 // if the tie is between two modules at the end of a's deps, then a's order wins
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800371 inStatic: "a1:b,c,d,e; a2:b,c,e,d; b:d,e; c:e,d",
Jeff Gaston294356f2017-09-27 17:05:30 -0700372 outOrdered: "a1:b,c,d,e; a2:b,c,e,d; b:d,e; c:e,d",
373 },
374 {
375 // if the tie is between two modules at the start of a's deps, then c's order is used
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800376 inStatic: "a1:d,e,b1,c1; b1:d,e; c1:e,d; a2:d,e,b2,c2; b2:d,e; c2:d,e",
Jeff Gaston294356f2017-09-27 17:05:30 -0700377 outOrdered: "a1:b1,c1,e,d; b1:d,e; c1:e,d; a2:b2,c2,d,e; b2:d,e; c2:d,e",
378 },
379 // Tests involving duplicate dependencies
380 {
381 // simple duplicate
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800382 inStatic: "a:b,c,c,b",
Jeff Gaston294356f2017-09-27 17:05:30 -0700383 outOrdered: "a:c,b",
384 },
385 {
386 // duplicates with reordering
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800387 inStatic: "a:b,c,d,c; c:b",
Jeff Gaston294356f2017-09-27 17:05:30 -0700388 outOrdered: "a:d,c,b",
389 },
390 // Tests to confirm the nonexistence of infinite loops.
391 // These cases should never happen, so as long as the test terminates and the
392 // result is deterministic then that should be fine.
393 {
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800394 inStatic: "a:a",
Jeff Gaston294356f2017-09-27 17:05:30 -0700395 outOrdered: "a:a",
396 },
397 {
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800398 inStatic: "a:b; b:c; c:a",
Jeff Gaston294356f2017-09-27 17:05:30 -0700399 allOrdered: "a:b,c; b:c,a; c:a,b",
400 outOrdered: "a:b; b:c; c:a",
401 },
402 {
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800403 inStatic: "a:b,c; b:c,a; c:a,b",
Jeff Gaston294356f2017-09-27 17:05:30 -0700404 allOrdered: "a:c,a,b; b:a,b,c; c:b,c,a",
405 outOrdered: "a:c,b; b:a,c; c:b,a",
406 },
407}
408
409// converts from a string like "a:b,c; d:e" to (["a","b"], {"a":["b","c"], "d":["e"]}, [{"a", "a.o"}, {"b", "b.o"}])
410func parseModuleDeps(text string) (modulesInOrder []android.Path, allDeps map[android.Path][]android.Path) {
411 // convert from "a:b,c; d:e" to "a:b,c;d:e"
412 strippedText := strings.Replace(text, " ", "", -1)
413 if len(strippedText) < 1 {
414 return []android.Path{}, make(map[android.Path][]android.Path, 0)
415 }
416 allDeps = make(map[android.Path][]android.Path, 0)
417
418 // convert from "a:b,c;d:e" to ["a:b,c", "d:e"]
419 moduleTexts := strings.Split(strippedText, ";")
420
421 outputForModuleName := func(moduleName string) android.Path {
422 return android.PathForTesting(moduleName)
423 }
424
425 for _, moduleText := range moduleTexts {
426 // convert from "a:b,c" to ["a", "b,c"]
427 components := strings.Split(moduleText, ":")
428 if len(components) != 2 {
429 panic(fmt.Sprintf("illegal module dep string %q from larger string %q; must contain one ':', not %v", moduleText, text, len(components)-1))
430 }
431 moduleName := components[0]
432 moduleOutput := outputForModuleName(moduleName)
433 modulesInOrder = append(modulesInOrder, moduleOutput)
434
435 depString := components[1]
436 // convert from "b,c" to ["b", "c"]
437 depNames := strings.Split(depString, ",")
438 if len(depString) < 1 {
439 depNames = []string{}
440 }
441 var deps []android.Path
442 for _, depName := range depNames {
443 deps = append(deps, outputForModuleName(depName))
444 }
445 allDeps[moduleOutput] = deps
446 }
447 return modulesInOrder, allDeps
448}
449
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800450func TestLinkReordering(t *testing.T) {
Jeff Gaston294356f2017-09-27 17:05:30 -0700451 for _, testCase := range staticLinkDepOrderTestCases {
452 errs := []string{}
453
454 // parse testcase
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800455 _, givenTransitiveDeps := parseModuleDeps(testCase.inStatic)
Jeff Gaston294356f2017-09-27 17:05:30 -0700456 expectedModuleNames, expectedTransitiveDeps := parseModuleDeps(testCase.outOrdered)
457 if testCase.allOrdered == "" {
458 // allow the test case to skip specifying allOrdered
459 testCase.allOrdered = testCase.outOrdered
460 }
461 _, expectedAllDeps := parseModuleDeps(testCase.allOrdered)
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800462 _, givenAllSharedDeps := parseModuleDeps(testCase.inShared)
Jeff Gaston294356f2017-09-27 17:05:30 -0700463
464 // For each module whose post-reordered dependencies were specified, validate that
465 // reordering the inputs produces the expected outputs.
466 for _, moduleName := range expectedModuleNames {
467 moduleDeps := givenTransitiveDeps[moduleName]
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800468 givenSharedDeps := givenAllSharedDeps[moduleName]
469 orderedAllDeps, orderedDeclaredDeps := orderDeps(moduleDeps, givenSharedDeps, givenTransitiveDeps)
Jeff Gaston294356f2017-09-27 17:05:30 -0700470
471 correctAllOrdered := expectedAllDeps[moduleName]
472 if !reflect.DeepEqual(orderedAllDeps, correctAllOrdered) {
473 errs = append(errs, fmt.Sprintf("orderDeps returned incorrect orderedAllDeps."+
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800474 "\nin static:%q"+
475 "\nin shared:%q"+
Jeff Gaston294356f2017-09-27 17:05:30 -0700476 "\nmodule: %v"+
477 "\nexpected: %s"+
478 "\nactual: %s",
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800479 testCase.inStatic, testCase.inShared, moduleName, correctAllOrdered, orderedAllDeps))
Jeff Gaston294356f2017-09-27 17:05:30 -0700480 }
481
482 correctOutputDeps := expectedTransitiveDeps[moduleName]
483 if !reflect.DeepEqual(correctOutputDeps, orderedDeclaredDeps) {
484 errs = append(errs, fmt.Sprintf("orderDeps returned incorrect orderedDeclaredDeps."+
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800485 "\nin static:%q"+
486 "\nin shared:%q"+
Jeff Gaston294356f2017-09-27 17:05:30 -0700487 "\nmodule: %v"+
488 "\nexpected: %s"+
489 "\nactual: %s",
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800490 testCase.inStatic, testCase.inShared, moduleName, correctOutputDeps, orderedDeclaredDeps))
Jeff Gaston294356f2017-09-27 17:05:30 -0700491 }
492 }
493
494 if len(errs) > 0 {
495 sort.Strings(errs)
496 for _, err := range errs {
497 t.Error(err)
498 }
499 }
500 }
501}
502func failIfErrored(t *testing.T, errs []error) {
503 if len(errs) > 0 {
504 for _, err := range errs {
505 t.Error(err)
506 }
507 t.FailNow()
508 }
509}
510
511func getOutputPaths(ctx *android.TestContext, variant string, moduleNames []string) (paths android.Paths) {
512 for _, moduleName := range moduleNames {
513 module := ctx.ModuleForTests(moduleName, variant).Module().(*Module)
514 output := module.outputFile.Path()
515 paths = append(paths, output)
516 }
517 return paths
518}
519
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800520func TestStaticLibDepReordering(t *testing.T) {
Jeff Gaston294356f2017-09-27 17:05:30 -0700521 ctx := testCc(t, `
522 cc_library {
523 name: "a",
524 static_libs: ["b", "c", "d"],
525 }
526 cc_library {
527 name: "b",
528 }
529 cc_library {
530 name: "c",
531 static_libs: ["b"],
532 }
533 cc_library {
534 name: "d",
535 }
536
537 `)
538
539 variant := "android_arm64_armv8-a_core_static"
540 moduleA := ctx.ModuleForTests("a", variant).Module().(*Module)
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800541 actual := moduleA.depsInLinkOrder
Jeff Gaston294356f2017-09-27 17:05:30 -0700542 expected := getOutputPaths(ctx, variant, []string{"c", "b", "d"})
543
544 if !reflect.DeepEqual(actual, expected) {
545 t.Errorf("staticDeps orderings were not propagated correctly"+
546 "\nactual: %v"+
547 "\nexpected: %v",
548 actual,
549 expected,
550 )
551 }
Jiyong Parkd08b6972017-09-26 10:50:54 +0900552}
Jeff Gaston294356f2017-09-27 17:05:30 -0700553
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800554func TestStaticLibDepReorderingWithShared(t *testing.T) {
555 ctx := testCc(t, `
556 cc_library {
557 name: "a",
558 static_libs: ["b", "c"],
559 }
560 cc_library {
561 name: "b",
562 }
563 cc_library {
564 name: "c",
565 shared_libs: ["b"],
566 }
567
568 `)
569
570 variant := "android_arm64_armv8-a_core_static"
571 moduleA := ctx.ModuleForTests("a", variant).Module().(*Module)
572 actual := moduleA.depsInLinkOrder
573 expected := getOutputPaths(ctx, variant, []string{"c", "b"})
574
575 if !reflect.DeepEqual(actual, expected) {
576 t.Errorf("staticDeps orderings did not account for shared libs"+
577 "\nactual: %v"+
578 "\nexpected: %v",
579 actual,
580 expected,
581 )
582 }
583}
584
Jiyong Parka46a4d52017-12-14 19:54:34 +0900585func TestLlndkHeaders(t *testing.T) {
586 ctx := testCc(t, `
587 llndk_headers {
588 name: "libllndk_headers",
589 export_include_dirs: ["my_include"],
590 }
591 llndk_library {
592 name: "libllndk",
593 export_llndk_headers: ["libllndk_headers"],
594 }
595 cc_library {
596 name: "libvendor",
597 shared_libs: ["libllndk"],
598 vendor: true,
599 srcs: ["foo.c"],
600 no_libgcc : true,
601 nocrt : true,
602 }
603 `)
604
605 // _static variant is used since _shared reuses *.o from the static variant
606 cc := ctx.ModuleForTests("libvendor", "android_arm_armv7-a-neon_vendor_static").Rule("cc")
607 cflags := cc.Args["cFlags"]
608 if !strings.Contains(cflags, "-Imy_include") {
609 t.Errorf("cflags for libvendor must contain -Imy_include, but was %#v.", cflags)
610 }
611}
612
Jiyong Parkd08b6972017-09-26 10:50:54 +0900613var compilerFlagsTestCases = []struct {
614 in string
615 out bool
616}{
617 {
618 in: "a",
619 out: false,
620 },
621 {
622 in: "-a",
623 out: true,
624 },
625 {
626 in: "-Ipath/to/something",
627 out: false,
628 },
629 {
630 in: "-isystempath/to/something",
631 out: false,
632 },
633 {
634 in: "--coverage",
635 out: false,
636 },
637 {
638 in: "-include a/b",
639 out: true,
640 },
641 {
642 in: "-include a/b c/d",
643 out: false,
644 },
645 {
646 in: "-DMACRO",
647 out: true,
648 },
649 {
650 in: "-DMAC RO",
651 out: false,
652 },
653 {
654 in: "-a -b",
655 out: false,
656 },
657 {
658 in: "-DMACRO=definition",
659 out: true,
660 },
661 {
662 in: "-DMACRO=defi nition",
663 out: true, // TODO(jiyong): this should be false
664 },
665 {
666 in: "-DMACRO(x)=x + 1",
667 out: true,
668 },
669 {
670 in: "-DMACRO=\"defi nition\"",
671 out: true,
672 },
673}
674
675type mockContext struct {
676 BaseModuleContext
677 result bool
678}
679
680func (ctx *mockContext) PropertyErrorf(property, format string, args ...interface{}) {
681 // CheckBadCompilerFlags calls this function when the flag should be rejected
682 ctx.result = false
683}
684
685func TestCompilerFlags(t *testing.T) {
686 for _, testCase := range compilerFlagsTestCases {
687 ctx := &mockContext{result: true}
688 CheckBadCompilerFlags(ctx, "", []string{testCase.in})
689 if ctx.result != testCase.out {
690 t.Errorf("incorrect output:")
691 t.Errorf(" input: %#v", testCase.in)
692 t.Errorf(" expected: %#v", testCase.out)
693 t.Errorf(" got: %#v", ctx.result)
694 }
695 }
Jeff Gaston294356f2017-09-27 17:05:30 -0700696}