blob: 15e45d0c49b30b4db6d399d85ad51d68b9628615 [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 }
175 if len(objs) != 2 {
176 t.Errorf("inputs of libTest is expected to 2, but was %d.", len(objs))
177 }
178 if objs[0] != "foo.o" || objs[1] != "bar.o" {
179 t.Errorf("inputs of libTest must be []string{\"foo.o\", \"bar.o\"}, but was %#v.", objs)
180 }
181}
182
Colin Cross0af4b842015-04-30 16:36:18 -0700183var (
184 str11 = "01234567891"
185 str10 = str11[:10]
186 str9 = str11[:9]
187 str5 = str11[:5]
188 str4 = str11[:4]
189)
190
191var splitListForSizeTestCases = []struct {
192 in []string
193 out [][]string
194 size int
195}{
196 {
197 in: []string{str10},
198 out: [][]string{{str10}},
199 size: 10,
200 },
201 {
202 in: []string{str9},
203 out: [][]string{{str9}},
204 size: 10,
205 },
206 {
207 in: []string{str5},
208 out: [][]string{{str5}},
209 size: 10,
210 },
211 {
212 in: []string{str11},
213 out: nil,
214 size: 10,
215 },
216 {
217 in: []string{str10, str10},
218 out: [][]string{{str10}, {str10}},
219 size: 10,
220 },
221 {
222 in: []string{str9, str10},
223 out: [][]string{{str9}, {str10}},
224 size: 10,
225 },
226 {
227 in: []string{str10, str9},
228 out: [][]string{{str10}, {str9}},
229 size: 10,
230 },
231 {
232 in: []string{str5, str4},
233 out: [][]string{{str5, str4}},
234 size: 10,
235 },
236 {
237 in: []string{str5, str4, str5},
238 out: [][]string{{str5, str4}, {str5}},
239 size: 10,
240 },
241 {
242 in: []string{str5, str4, str5, str4},
243 out: [][]string{{str5, str4}, {str5, str4}},
244 size: 10,
245 },
246 {
247 in: []string{str5, str4, str5, str5},
248 out: [][]string{{str5, str4}, {str5}, {str5}},
249 size: 10,
250 },
251 {
252 in: []string{str5, str5, str5, str4},
253 out: [][]string{{str5}, {str5}, {str5, str4}},
254 size: 10,
255 },
256 {
257 in: []string{str9, str11},
258 out: nil,
259 size: 10,
260 },
261 {
262 in: []string{str11, str9},
263 out: nil,
264 size: 10,
265 },
266}
267
268func TestSplitListForSize(t *testing.T) {
269 for _, testCase := range splitListForSizeTestCases {
Colin Cross5b529592017-05-09 13:34:34 -0700270 out, _ := splitListForSize(android.PathsForTesting(testCase.in), testCase.size)
271
272 var outStrings [][]string
273
274 if len(out) > 0 {
275 outStrings = make([][]string, len(out))
276 for i, o := range out {
277 outStrings[i] = o.Strings()
278 }
279 }
280
281 if !reflect.DeepEqual(outStrings, testCase.out) {
Colin Cross0af4b842015-04-30 16:36:18 -0700282 t.Errorf("incorrect output:")
283 t.Errorf(" input: %#v", testCase.in)
284 t.Errorf(" size: %d", testCase.size)
285 t.Errorf(" expected: %#v", testCase.out)
Colin Cross5b529592017-05-09 13:34:34 -0700286 t.Errorf(" got: %#v", outStrings)
Colin Cross0af4b842015-04-30 16:36:18 -0700287 }
288 }
289}
Jeff Gaston294356f2017-09-27 17:05:30 -0700290
291var staticLinkDepOrderTestCases = []struct {
292 // This is a string representation of a map[moduleName][]moduleDependency .
293 // It models the dependencies declared in an Android.bp file.
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800294 inStatic string
295
296 // This is a string representation of a map[moduleName][]moduleDependency .
297 // It models the dependencies declared in an Android.bp file.
298 inShared string
Jeff Gaston294356f2017-09-27 17:05:30 -0700299
300 // allOrdered is a string representation of a map[moduleName][]moduleDependency .
301 // The keys of allOrdered specify which modules we would like to check.
302 // The values of allOrdered specify the expected result (of the transitive closure of all
303 // dependencies) for each module to test
304 allOrdered string
305
306 // outOrdered is a string representation of a map[moduleName][]moduleDependency .
307 // The keys of outOrdered specify which modules we would like to check.
308 // The values of outOrdered specify the expected result (of the ordered linker command line)
309 // for each module to test.
310 outOrdered string
311}{
312 // Simple tests
313 {
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800314 inStatic: "",
Jeff Gaston294356f2017-09-27 17:05:30 -0700315 outOrdered: "",
316 },
317 {
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800318 inStatic: "a:",
Jeff Gaston294356f2017-09-27 17:05:30 -0700319 outOrdered: "a:",
320 },
321 {
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800322 inStatic: "a:b; b:",
Jeff Gaston294356f2017-09-27 17:05:30 -0700323 outOrdered: "a:b; b:",
324 },
325 // Tests of reordering
326 {
327 // diamond example
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800328 inStatic: "a:d,b,c; b:d; c:d; d:",
Jeff Gaston294356f2017-09-27 17:05:30 -0700329 outOrdered: "a:b,c,d; b:d; c:d; d:",
330 },
331 {
332 // somewhat real example
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800333 inStatic: "bsdiff_unittest:b,c,d,e,f,g,h,i; e:b",
Jeff Gaston294356f2017-09-27 17:05:30 -0700334 outOrdered: "bsdiff_unittest:c,d,e,b,f,g,h,i; e:b",
335 },
336 {
337 // multiple reorderings
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800338 inStatic: "a:b,c,d,e; d:b; e:c",
Jeff Gaston294356f2017-09-27 17:05:30 -0700339 outOrdered: "a:d,b,e,c; d:b; e:c",
340 },
341 {
342 // should reorder without adding new transitive dependencies
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800343 inStatic: "bin:lib2,lib1; lib1:lib2,liboptional",
Jeff Gaston294356f2017-09-27 17:05:30 -0700344 allOrdered: "bin:lib1,lib2,liboptional; lib1:lib2,liboptional",
345 outOrdered: "bin:lib1,lib2; lib1:lib2,liboptional",
346 },
347 {
348 // multiple levels of dependencies
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800349 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 -0700350 allOrdered: "a:e,f,b,c,d,g,h; f:b,c,d; b:c,d; c:d",
351 outOrdered: "a:e,f,b,c,d,g,h; f:b,c,d; b:c,d; c:d",
352 },
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800353 // shared dependencies
354 {
355 // Note that this test doesn't recurse, to minimize the amount of logic it tests.
356 // So, we don't actually have to check that a shared dependency of c will change the order
357 // of a library that depends statically on b and on c. We only need to check that if c has
358 // a shared dependency on b, that that shows up in allOrdered.
359 inShared: "c:b",
360 allOrdered: "c:b",
361 outOrdered: "c:",
362 },
363 {
364 // This test doesn't actually include any shared dependencies but it's a reminder of what
365 // the second phase of the above test would look like
366 inStatic: "a:b,c; c:b",
367 allOrdered: "a:c,b; c:b",
368 outOrdered: "a:c,b; c:b",
369 },
Jeff Gaston294356f2017-09-27 17:05:30 -0700370 // tiebreakers for when two modules specifying different orderings and there is no dependency
371 // to dictate an order
372 {
373 // 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 -0800374 inStatic: "a1:b,c,d,e; a2:b,c,e,d; b:d,e; c:e,d",
Jeff Gaston294356f2017-09-27 17:05:30 -0700375 outOrdered: "a1:b,c,d,e; a2:b,c,e,d; b:d,e; c:e,d",
376 },
377 {
378 // 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 -0800379 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 -0700380 outOrdered: "a1:b1,c1,e,d; b1:d,e; c1:e,d; a2:b2,c2,d,e; b2:d,e; c2:d,e",
381 },
382 // Tests involving duplicate dependencies
383 {
384 // simple duplicate
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800385 inStatic: "a:b,c,c,b",
Jeff Gaston294356f2017-09-27 17:05:30 -0700386 outOrdered: "a:c,b",
387 },
388 {
389 // duplicates with reordering
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800390 inStatic: "a:b,c,d,c; c:b",
Jeff Gaston294356f2017-09-27 17:05:30 -0700391 outOrdered: "a:d,c,b",
392 },
393 // Tests to confirm the nonexistence of infinite loops.
394 // These cases should never happen, so as long as the test terminates and the
395 // result is deterministic then that should be fine.
396 {
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800397 inStatic: "a:a",
Jeff Gaston294356f2017-09-27 17:05:30 -0700398 outOrdered: "a:a",
399 },
400 {
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800401 inStatic: "a:b; b:c; c:a",
Jeff Gaston294356f2017-09-27 17:05:30 -0700402 allOrdered: "a:b,c; b:c,a; c:a,b",
403 outOrdered: "a:b; b:c; c:a",
404 },
405 {
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800406 inStatic: "a:b,c; b:c,a; c:a,b",
Jeff Gaston294356f2017-09-27 17:05:30 -0700407 allOrdered: "a:c,a,b; b:a,b,c; c:b,c,a",
408 outOrdered: "a:c,b; b:a,c; c:b,a",
409 },
410}
411
412// converts from a string like "a:b,c; d:e" to (["a","b"], {"a":["b","c"], "d":["e"]}, [{"a", "a.o"}, {"b", "b.o"}])
413func parseModuleDeps(text string) (modulesInOrder []android.Path, allDeps map[android.Path][]android.Path) {
414 // convert from "a:b,c; d:e" to "a:b,c;d:e"
415 strippedText := strings.Replace(text, " ", "", -1)
416 if len(strippedText) < 1 {
417 return []android.Path{}, make(map[android.Path][]android.Path, 0)
418 }
419 allDeps = make(map[android.Path][]android.Path, 0)
420
421 // convert from "a:b,c;d:e" to ["a:b,c", "d:e"]
422 moduleTexts := strings.Split(strippedText, ";")
423
424 outputForModuleName := func(moduleName string) android.Path {
425 return android.PathForTesting(moduleName)
426 }
427
428 for _, moduleText := range moduleTexts {
429 // convert from "a:b,c" to ["a", "b,c"]
430 components := strings.Split(moduleText, ":")
431 if len(components) != 2 {
432 panic(fmt.Sprintf("illegal module dep string %q from larger string %q; must contain one ':', not %v", moduleText, text, len(components)-1))
433 }
434 moduleName := components[0]
435 moduleOutput := outputForModuleName(moduleName)
436 modulesInOrder = append(modulesInOrder, moduleOutput)
437
438 depString := components[1]
439 // convert from "b,c" to ["b", "c"]
440 depNames := strings.Split(depString, ",")
441 if len(depString) < 1 {
442 depNames = []string{}
443 }
444 var deps []android.Path
445 for _, depName := range depNames {
446 deps = append(deps, outputForModuleName(depName))
447 }
448 allDeps[moduleOutput] = deps
449 }
450 return modulesInOrder, allDeps
451}
452
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800453func TestLinkReordering(t *testing.T) {
Jeff Gaston294356f2017-09-27 17:05:30 -0700454 for _, testCase := range staticLinkDepOrderTestCases {
455 errs := []string{}
456
457 // parse testcase
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800458 _, givenTransitiveDeps := parseModuleDeps(testCase.inStatic)
Jeff Gaston294356f2017-09-27 17:05:30 -0700459 expectedModuleNames, expectedTransitiveDeps := parseModuleDeps(testCase.outOrdered)
460 if testCase.allOrdered == "" {
461 // allow the test case to skip specifying allOrdered
462 testCase.allOrdered = testCase.outOrdered
463 }
464 _, expectedAllDeps := parseModuleDeps(testCase.allOrdered)
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800465 _, givenAllSharedDeps := parseModuleDeps(testCase.inShared)
Jeff Gaston294356f2017-09-27 17:05:30 -0700466
467 // For each module whose post-reordered dependencies were specified, validate that
468 // reordering the inputs produces the expected outputs.
469 for _, moduleName := range expectedModuleNames {
470 moduleDeps := givenTransitiveDeps[moduleName]
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800471 givenSharedDeps := givenAllSharedDeps[moduleName]
472 orderedAllDeps, orderedDeclaredDeps := orderDeps(moduleDeps, givenSharedDeps, givenTransitiveDeps)
Jeff Gaston294356f2017-09-27 17:05:30 -0700473
474 correctAllOrdered := expectedAllDeps[moduleName]
475 if !reflect.DeepEqual(orderedAllDeps, correctAllOrdered) {
476 errs = append(errs, fmt.Sprintf("orderDeps returned incorrect orderedAllDeps."+
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800477 "\nin static:%q"+
478 "\nin shared:%q"+
Jeff Gaston294356f2017-09-27 17:05:30 -0700479 "\nmodule: %v"+
480 "\nexpected: %s"+
481 "\nactual: %s",
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800482 testCase.inStatic, testCase.inShared, moduleName, correctAllOrdered, orderedAllDeps))
Jeff Gaston294356f2017-09-27 17:05:30 -0700483 }
484
485 correctOutputDeps := expectedTransitiveDeps[moduleName]
486 if !reflect.DeepEqual(correctOutputDeps, orderedDeclaredDeps) {
487 errs = append(errs, fmt.Sprintf("orderDeps returned incorrect orderedDeclaredDeps."+
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800488 "\nin static:%q"+
489 "\nin shared:%q"+
Jeff Gaston294356f2017-09-27 17:05:30 -0700490 "\nmodule: %v"+
491 "\nexpected: %s"+
492 "\nactual: %s",
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800493 testCase.inStatic, testCase.inShared, moduleName, correctOutputDeps, orderedDeclaredDeps))
Jeff Gaston294356f2017-09-27 17:05:30 -0700494 }
495 }
496
497 if len(errs) > 0 {
498 sort.Strings(errs)
499 for _, err := range errs {
500 t.Error(err)
501 }
502 }
503 }
504}
505func failIfErrored(t *testing.T, errs []error) {
506 if len(errs) > 0 {
507 for _, err := range errs {
508 t.Error(err)
509 }
510 t.FailNow()
511 }
512}
513
514func getOutputPaths(ctx *android.TestContext, variant string, moduleNames []string) (paths android.Paths) {
515 for _, moduleName := range moduleNames {
516 module := ctx.ModuleForTests(moduleName, variant).Module().(*Module)
517 output := module.outputFile.Path()
518 paths = append(paths, output)
519 }
520 return paths
521}
522
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800523func TestStaticLibDepReordering(t *testing.T) {
Jeff Gaston294356f2017-09-27 17:05:30 -0700524 ctx := testCc(t, `
525 cc_library {
526 name: "a",
527 static_libs: ["b", "c", "d"],
528 }
529 cc_library {
530 name: "b",
531 }
532 cc_library {
533 name: "c",
534 static_libs: ["b"],
535 }
536 cc_library {
537 name: "d",
538 }
539
540 `)
541
542 variant := "android_arm64_armv8-a_core_static"
543 moduleA := ctx.ModuleForTests("a", variant).Module().(*Module)
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800544 actual := moduleA.depsInLinkOrder
Jeff Gaston294356f2017-09-27 17:05:30 -0700545 expected := getOutputPaths(ctx, variant, []string{"c", "b", "d"})
546
547 if !reflect.DeepEqual(actual, expected) {
548 t.Errorf("staticDeps orderings were not propagated correctly"+
549 "\nactual: %v"+
550 "\nexpected: %v",
551 actual,
552 expected,
553 )
554 }
Jiyong Parkd08b6972017-09-26 10:50:54 +0900555}
Jeff Gaston294356f2017-09-27 17:05:30 -0700556
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800557func TestStaticLibDepReorderingWithShared(t *testing.T) {
558 ctx := testCc(t, `
559 cc_library {
560 name: "a",
561 static_libs: ["b", "c"],
562 }
563 cc_library {
564 name: "b",
565 }
566 cc_library {
567 name: "c",
568 shared_libs: ["b"],
569 }
570
571 `)
572
573 variant := "android_arm64_armv8-a_core_static"
574 moduleA := ctx.ModuleForTests("a", variant).Module().(*Module)
575 actual := moduleA.depsInLinkOrder
576 expected := getOutputPaths(ctx, variant, []string{"c", "b"})
577
578 if !reflect.DeepEqual(actual, expected) {
579 t.Errorf("staticDeps orderings did not account for shared libs"+
580 "\nactual: %v"+
581 "\nexpected: %v",
582 actual,
583 expected,
584 )
585 }
586}
587
Jiyong Parka46a4d52017-12-14 19:54:34 +0900588func TestLlndkHeaders(t *testing.T) {
589 ctx := testCc(t, `
590 llndk_headers {
591 name: "libllndk_headers",
592 export_include_dirs: ["my_include"],
593 }
594 llndk_library {
595 name: "libllndk",
596 export_llndk_headers: ["libllndk_headers"],
597 }
598 cc_library {
599 name: "libvendor",
600 shared_libs: ["libllndk"],
601 vendor: true,
602 srcs: ["foo.c"],
603 no_libgcc : true,
604 nocrt : true,
605 }
606 `)
607
608 // _static variant is used since _shared reuses *.o from the static variant
609 cc := ctx.ModuleForTests("libvendor", "android_arm_armv7-a-neon_vendor_static").Rule("cc")
610 cflags := cc.Args["cFlags"]
611 if !strings.Contains(cflags, "-Imy_include") {
612 t.Errorf("cflags for libvendor must contain -Imy_include, but was %#v.", cflags)
613 }
614}
615
Jiyong Parkd08b6972017-09-26 10:50:54 +0900616var compilerFlagsTestCases = []struct {
617 in string
618 out bool
619}{
620 {
621 in: "a",
622 out: false,
623 },
624 {
625 in: "-a",
626 out: true,
627 },
628 {
629 in: "-Ipath/to/something",
630 out: false,
631 },
632 {
633 in: "-isystempath/to/something",
634 out: false,
635 },
636 {
637 in: "--coverage",
638 out: false,
639 },
640 {
641 in: "-include a/b",
642 out: true,
643 },
644 {
645 in: "-include a/b c/d",
646 out: false,
647 },
648 {
649 in: "-DMACRO",
650 out: true,
651 },
652 {
653 in: "-DMAC RO",
654 out: false,
655 },
656 {
657 in: "-a -b",
658 out: false,
659 },
660 {
661 in: "-DMACRO=definition",
662 out: true,
663 },
664 {
665 in: "-DMACRO=defi nition",
666 out: true, // TODO(jiyong): this should be false
667 },
668 {
669 in: "-DMACRO(x)=x + 1",
670 out: true,
671 },
672 {
673 in: "-DMACRO=\"defi nition\"",
674 out: true,
675 },
676}
677
678type mockContext struct {
679 BaseModuleContext
680 result bool
681}
682
683func (ctx *mockContext) PropertyErrorf(property, format string, args ...interface{}) {
684 // CheckBadCompilerFlags calls this function when the flag should be rejected
685 ctx.result = false
686}
687
688func TestCompilerFlags(t *testing.T) {
689 for _, testCase := range compilerFlagsTestCases {
690 ctx := &mockContext{result: true}
691 CheckBadCompilerFlags(ctx, "", []string{testCase.in})
692 if ctx.result != testCase.out {
693 t.Errorf("incorrect output:")
694 t.Errorf(" input: %#v", testCase.in)
695 t.Errorf(" expected: %#v", testCase.out)
696 t.Errorf(" got: %#v", ctx.result)
697 }
698 }
Jeff Gaston294356f2017-09-27 17:05:30 -0700699}