blob: 148b4ddc3bbbacea309074862ad025f1b5374ec4 [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))
Jeff Gaston294356f2017-09-27 17:05:30 -070064 ctx.RegisterModuleType("cc_object", android.ModuleFactoryAdaptor(objectFactory))
Colin Crossf18e1102017-11-16 14:33:08 -080065 ctx.RegisterModuleType("filegroup", android.ModuleFactoryAdaptor(genrule.FileGroupFactory))
Jiyong Park6a43f042017-10-12 23:05:00 +090066 ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
67 ctx.BottomUp("image", vendorMutator).Parallel()
68 ctx.BottomUp("link", linkageMutator).Parallel()
69 ctx.BottomUp("vndk", vndkMutator).Parallel()
70 })
71 ctx.Register()
72
Jeff Gaston294356f2017-09-27 17:05:30 -070073 // add some modules that are required by the compiler and/or linker
74 bp = bp + `
75 toolchain_library {
76 name: "libatomic",
77 vendor_available: true,
78 }
79
80 toolchain_library {
81 name: "libcompiler_rt-extras",
82 vendor_available: true,
83 }
84
85 toolchain_library {
86 name: "libgcc",
87 vendor_available: true,
88 }
89
90 cc_library {
91 name: "libc",
92 no_libgcc : true,
93 nocrt : true,
94 system_shared_libs: [],
95 }
96 llndk_library {
97 name: "libc",
98 symbol_file: "",
99 }
100 cc_library {
101 name: "libm",
102 no_libgcc : true,
103 nocrt : true,
104 system_shared_libs: [],
105 }
106 llndk_library {
107 name: "libm",
108 symbol_file: "",
109 }
110 cc_library {
111 name: "libdl",
112 no_libgcc : true,
113 nocrt : true,
114 system_shared_libs: [],
115 }
116 llndk_library {
117 name: "libdl",
118 symbol_file: "",
119 }
120
121 cc_object {
122 name: "crtbegin_so",
123 }
124
125 cc_object {
126 name: "crtend_so",
127 }
128
Colin Crossad59e752017-11-16 14:29:11 -0800129 cc_library {
130 name: "libprotobuf-cpp-lite",
131 }
132
Jeff Gaston294356f2017-09-27 17:05:30 -0700133`
134
Jiyong Park6a43f042017-10-12 23:05:00 +0900135 ctx.MockFileSystem(map[string][]byte{
136 "Android.bp": []byte(bp),
137 "foo.c": nil,
138 "bar.c": nil,
Colin Crossad59e752017-11-16 14:29:11 -0800139 "a.proto": nil,
Colin Crossf18e1102017-11-16 14:33:08 -0800140 "b.aidl": nil,
Jiyong Park6a43f042017-10-12 23:05:00 +0900141 })
142
Jeff Gastond3e141d2017-08-08 17:46:01 -0700143 _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
Jeff Gaston294356f2017-09-27 17:05:30 -0700144 failIfErrored(t, errs)
Jiyong Park6a43f042017-10-12 23:05:00 +0900145 _, errs = ctx.PrepareBuildActions(config)
Jeff Gaston294356f2017-09-27 17:05:30 -0700146 failIfErrored(t, errs)
Jiyong Park6a43f042017-10-12 23:05:00 +0900147
148 return ctx
149}
150
151func TestVendorSrc(t *testing.T) {
152 ctx := testCc(t, `
153 cc_library {
154 name: "libTest",
155 srcs: ["foo.c"],
156 no_libgcc : true,
157 nocrt : true,
158 system_shared_libs : [],
159 vendor_available: true,
160 target: {
161 vendor: {
162 srcs: ["bar.c"],
163 },
164 },
165 }
Jiyong Park6a43f042017-10-12 23:05:00 +0900166 `)
167
168 ld := ctx.ModuleForTests("libTest", "android_arm_armv7-a-neon_vendor_shared").Rule("ld")
169 var objs []string
170 for _, o := range ld.Inputs {
171 objs = append(objs, o.Base())
172 }
173 if len(objs) != 2 {
174 t.Errorf("inputs of libTest is expected to 2, but was %d.", len(objs))
175 }
176 if objs[0] != "foo.o" || objs[1] != "bar.o" {
177 t.Errorf("inputs of libTest must be []string{\"foo.o\", \"bar.o\"}, but was %#v.", objs)
178 }
179}
180
Colin Cross0af4b842015-04-30 16:36:18 -0700181var (
182 str11 = "01234567891"
183 str10 = str11[:10]
184 str9 = str11[:9]
185 str5 = str11[:5]
186 str4 = str11[:4]
187)
188
189var splitListForSizeTestCases = []struct {
190 in []string
191 out [][]string
192 size int
193}{
194 {
195 in: []string{str10},
196 out: [][]string{{str10}},
197 size: 10,
198 },
199 {
200 in: []string{str9},
201 out: [][]string{{str9}},
202 size: 10,
203 },
204 {
205 in: []string{str5},
206 out: [][]string{{str5}},
207 size: 10,
208 },
209 {
210 in: []string{str11},
211 out: nil,
212 size: 10,
213 },
214 {
215 in: []string{str10, str10},
216 out: [][]string{{str10}, {str10}},
217 size: 10,
218 },
219 {
220 in: []string{str9, str10},
221 out: [][]string{{str9}, {str10}},
222 size: 10,
223 },
224 {
225 in: []string{str10, str9},
226 out: [][]string{{str10}, {str9}},
227 size: 10,
228 },
229 {
230 in: []string{str5, str4},
231 out: [][]string{{str5, str4}},
232 size: 10,
233 },
234 {
235 in: []string{str5, str4, str5},
236 out: [][]string{{str5, str4}, {str5}},
237 size: 10,
238 },
239 {
240 in: []string{str5, str4, str5, str4},
241 out: [][]string{{str5, str4}, {str5, str4}},
242 size: 10,
243 },
244 {
245 in: []string{str5, str4, str5, str5},
246 out: [][]string{{str5, str4}, {str5}, {str5}},
247 size: 10,
248 },
249 {
250 in: []string{str5, str5, str5, str4},
251 out: [][]string{{str5}, {str5}, {str5, str4}},
252 size: 10,
253 },
254 {
255 in: []string{str9, str11},
256 out: nil,
257 size: 10,
258 },
259 {
260 in: []string{str11, str9},
261 out: nil,
262 size: 10,
263 },
264}
265
266func TestSplitListForSize(t *testing.T) {
267 for _, testCase := range splitListForSizeTestCases {
Colin Cross5b529592017-05-09 13:34:34 -0700268 out, _ := splitListForSize(android.PathsForTesting(testCase.in), testCase.size)
269
270 var outStrings [][]string
271
272 if len(out) > 0 {
273 outStrings = make([][]string, len(out))
274 for i, o := range out {
275 outStrings[i] = o.Strings()
276 }
277 }
278
279 if !reflect.DeepEqual(outStrings, testCase.out) {
Colin Cross0af4b842015-04-30 16:36:18 -0700280 t.Errorf("incorrect output:")
281 t.Errorf(" input: %#v", testCase.in)
282 t.Errorf(" size: %d", testCase.size)
283 t.Errorf(" expected: %#v", testCase.out)
Colin Cross5b529592017-05-09 13:34:34 -0700284 t.Errorf(" got: %#v", outStrings)
Colin Cross0af4b842015-04-30 16:36:18 -0700285 }
286 }
287}
Jeff Gaston294356f2017-09-27 17:05:30 -0700288
289var staticLinkDepOrderTestCases = []struct {
290 // This is a string representation of a map[moduleName][]moduleDependency .
291 // It models the dependencies declared in an Android.bp file.
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800292 inStatic string
293
294 // This is a string representation of a map[moduleName][]moduleDependency .
295 // It models the dependencies declared in an Android.bp file.
296 inShared string
Jeff Gaston294356f2017-09-27 17:05:30 -0700297
298 // allOrdered is a string representation of a map[moduleName][]moduleDependency .
299 // The keys of allOrdered specify which modules we would like to check.
300 // The values of allOrdered specify the expected result (of the transitive closure of all
301 // dependencies) for each module to test
302 allOrdered string
303
304 // outOrdered is a string representation of a map[moduleName][]moduleDependency .
305 // The keys of outOrdered specify which modules we would like to check.
306 // The values of outOrdered specify the expected result (of the ordered linker command line)
307 // for each module to test.
308 outOrdered string
309}{
310 // Simple tests
311 {
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800312 inStatic: "",
Jeff Gaston294356f2017-09-27 17:05:30 -0700313 outOrdered: "",
314 },
315 {
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800316 inStatic: "a:",
Jeff Gaston294356f2017-09-27 17:05:30 -0700317 outOrdered: "a:",
318 },
319 {
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800320 inStatic: "a:b; b:",
Jeff Gaston294356f2017-09-27 17:05:30 -0700321 outOrdered: "a:b; b:",
322 },
323 // Tests of reordering
324 {
325 // diamond example
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800326 inStatic: "a:d,b,c; b:d; c:d; d:",
Jeff Gaston294356f2017-09-27 17:05:30 -0700327 outOrdered: "a:b,c,d; b:d; c:d; d:",
328 },
329 {
330 // somewhat real example
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800331 inStatic: "bsdiff_unittest:b,c,d,e,f,g,h,i; e:b",
Jeff Gaston294356f2017-09-27 17:05:30 -0700332 outOrdered: "bsdiff_unittest:c,d,e,b,f,g,h,i; e:b",
333 },
334 {
335 // multiple reorderings
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800336 inStatic: "a:b,c,d,e; d:b; e:c",
Jeff Gaston294356f2017-09-27 17:05:30 -0700337 outOrdered: "a:d,b,e,c; d:b; e:c",
338 },
339 {
340 // should reorder without adding new transitive dependencies
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800341 inStatic: "bin:lib2,lib1; lib1:lib2,liboptional",
Jeff Gaston294356f2017-09-27 17:05:30 -0700342 allOrdered: "bin:lib1,lib2,liboptional; lib1:lib2,liboptional",
343 outOrdered: "bin:lib1,lib2; lib1:lib2,liboptional",
344 },
345 {
346 // multiple levels of dependencies
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800347 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 -0700348 allOrdered: "a:e,f,b,c,d,g,h; f:b,c,d; b:c,d; c:d",
349 outOrdered: "a:e,f,b,c,d,g,h; f:b,c,d; b:c,d; c:d",
350 },
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800351 // shared dependencies
352 {
353 // Note that this test doesn't recurse, to minimize the amount of logic it tests.
354 // So, we don't actually have to check that a shared dependency of c will change the order
355 // of a library that depends statically on b and on c. We only need to check that if c has
356 // a shared dependency on b, that that shows up in allOrdered.
357 inShared: "c:b",
358 allOrdered: "c:b",
359 outOrdered: "c:",
360 },
361 {
362 // This test doesn't actually include any shared dependencies but it's a reminder of what
363 // the second phase of the above test would look like
364 inStatic: "a:b,c; c:b",
365 allOrdered: "a:c,b; c:b",
366 outOrdered: "a:c,b; c:b",
367 },
Jeff Gaston294356f2017-09-27 17:05:30 -0700368 // tiebreakers for when two modules specifying different orderings and there is no dependency
369 // to dictate an order
370 {
371 // 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 -0800372 inStatic: "a1:b,c,d,e; a2:b,c,e,d; b:d,e; c:e,d",
Jeff Gaston294356f2017-09-27 17:05:30 -0700373 outOrdered: "a1:b,c,d,e; a2:b,c,e,d; b:d,e; c:e,d",
374 },
375 {
376 // 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 -0800377 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 -0700378 outOrdered: "a1:b1,c1,e,d; b1:d,e; c1:e,d; a2:b2,c2,d,e; b2:d,e; c2:d,e",
379 },
380 // Tests involving duplicate dependencies
381 {
382 // simple duplicate
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800383 inStatic: "a:b,c,c,b",
Jeff Gaston294356f2017-09-27 17:05:30 -0700384 outOrdered: "a:c,b",
385 },
386 {
387 // duplicates with reordering
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800388 inStatic: "a:b,c,d,c; c:b",
Jeff Gaston294356f2017-09-27 17:05:30 -0700389 outOrdered: "a:d,c,b",
390 },
391 // Tests to confirm the nonexistence of infinite loops.
392 // These cases should never happen, so as long as the test terminates and the
393 // result is deterministic then that should be fine.
394 {
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800395 inStatic: "a:a",
Jeff Gaston294356f2017-09-27 17:05:30 -0700396 outOrdered: "a:a",
397 },
398 {
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800399 inStatic: "a:b; b:c; c:a",
Jeff Gaston294356f2017-09-27 17:05:30 -0700400 allOrdered: "a:b,c; b:c,a; c:a,b",
401 outOrdered: "a:b; b:c; c:a",
402 },
403 {
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800404 inStatic: "a:b,c; b:c,a; c:a,b",
Jeff Gaston294356f2017-09-27 17:05:30 -0700405 allOrdered: "a:c,a,b; b:a,b,c; c:b,c,a",
406 outOrdered: "a:c,b; b:a,c; c:b,a",
407 },
408}
409
410// converts from a string like "a:b,c; d:e" to (["a","b"], {"a":["b","c"], "d":["e"]}, [{"a", "a.o"}, {"b", "b.o"}])
411func parseModuleDeps(text string) (modulesInOrder []android.Path, allDeps map[android.Path][]android.Path) {
412 // convert from "a:b,c; d:e" to "a:b,c;d:e"
413 strippedText := strings.Replace(text, " ", "", -1)
414 if len(strippedText) < 1 {
415 return []android.Path{}, make(map[android.Path][]android.Path, 0)
416 }
417 allDeps = make(map[android.Path][]android.Path, 0)
418
419 // convert from "a:b,c;d:e" to ["a:b,c", "d:e"]
420 moduleTexts := strings.Split(strippedText, ";")
421
422 outputForModuleName := func(moduleName string) android.Path {
423 return android.PathForTesting(moduleName)
424 }
425
426 for _, moduleText := range moduleTexts {
427 // convert from "a:b,c" to ["a", "b,c"]
428 components := strings.Split(moduleText, ":")
429 if len(components) != 2 {
430 panic(fmt.Sprintf("illegal module dep string %q from larger string %q; must contain one ':', not %v", moduleText, text, len(components)-1))
431 }
432 moduleName := components[0]
433 moduleOutput := outputForModuleName(moduleName)
434 modulesInOrder = append(modulesInOrder, moduleOutput)
435
436 depString := components[1]
437 // convert from "b,c" to ["b", "c"]
438 depNames := strings.Split(depString, ",")
439 if len(depString) < 1 {
440 depNames = []string{}
441 }
442 var deps []android.Path
443 for _, depName := range depNames {
444 deps = append(deps, outputForModuleName(depName))
445 }
446 allDeps[moduleOutput] = deps
447 }
448 return modulesInOrder, allDeps
449}
450
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800451func TestLinkReordering(t *testing.T) {
Jeff Gaston294356f2017-09-27 17:05:30 -0700452 for _, testCase := range staticLinkDepOrderTestCases {
453 errs := []string{}
454
455 // parse testcase
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800456 _, givenTransitiveDeps := parseModuleDeps(testCase.inStatic)
Jeff Gaston294356f2017-09-27 17:05:30 -0700457 expectedModuleNames, expectedTransitiveDeps := parseModuleDeps(testCase.outOrdered)
458 if testCase.allOrdered == "" {
459 // allow the test case to skip specifying allOrdered
460 testCase.allOrdered = testCase.outOrdered
461 }
462 _, expectedAllDeps := parseModuleDeps(testCase.allOrdered)
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800463 _, givenAllSharedDeps := parseModuleDeps(testCase.inShared)
Jeff Gaston294356f2017-09-27 17:05:30 -0700464
465 // For each module whose post-reordered dependencies were specified, validate that
466 // reordering the inputs produces the expected outputs.
467 for _, moduleName := range expectedModuleNames {
468 moduleDeps := givenTransitiveDeps[moduleName]
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800469 givenSharedDeps := givenAllSharedDeps[moduleName]
470 orderedAllDeps, orderedDeclaredDeps := orderDeps(moduleDeps, givenSharedDeps, givenTransitiveDeps)
Jeff Gaston294356f2017-09-27 17:05:30 -0700471
472 correctAllOrdered := expectedAllDeps[moduleName]
473 if !reflect.DeepEqual(orderedAllDeps, correctAllOrdered) {
474 errs = append(errs, fmt.Sprintf("orderDeps returned incorrect orderedAllDeps."+
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800475 "\nin static:%q"+
476 "\nin shared:%q"+
Jeff Gaston294356f2017-09-27 17:05:30 -0700477 "\nmodule: %v"+
478 "\nexpected: %s"+
479 "\nactual: %s",
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800480 testCase.inStatic, testCase.inShared, moduleName, correctAllOrdered, orderedAllDeps))
Jeff Gaston294356f2017-09-27 17:05:30 -0700481 }
482
483 correctOutputDeps := expectedTransitiveDeps[moduleName]
484 if !reflect.DeepEqual(correctOutputDeps, orderedDeclaredDeps) {
485 errs = append(errs, fmt.Sprintf("orderDeps returned incorrect orderedDeclaredDeps."+
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800486 "\nin static:%q"+
487 "\nin shared:%q"+
Jeff Gaston294356f2017-09-27 17:05:30 -0700488 "\nmodule: %v"+
489 "\nexpected: %s"+
490 "\nactual: %s",
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800491 testCase.inStatic, testCase.inShared, moduleName, correctOutputDeps, orderedDeclaredDeps))
Jeff Gaston294356f2017-09-27 17:05:30 -0700492 }
493 }
494
495 if len(errs) > 0 {
496 sort.Strings(errs)
497 for _, err := range errs {
498 t.Error(err)
499 }
500 }
501 }
502}
503func failIfErrored(t *testing.T, errs []error) {
504 if len(errs) > 0 {
505 for _, err := range errs {
506 t.Error(err)
507 }
508 t.FailNow()
509 }
510}
511
512func getOutputPaths(ctx *android.TestContext, variant string, moduleNames []string) (paths android.Paths) {
513 for _, moduleName := range moduleNames {
514 module := ctx.ModuleForTests(moduleName, variant).Module().(*Module)
515 output := module.outputFile.Path()
516 paths = append(paths, output)
517 }
518 return paths
519}
520
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800521func TestStaticLibDepReordering(t *testing.T) {
Jeff Gaston294356f2017-09-27 17:05:30 -0700522 ctx := testCc(t, `
523 cc_library {
524 name: "a",
525 static_libs: ["b", "c", "d"],
526 }
527 cc_library {
528 name: "b",
529 }
530 cc_library {
531 name: "c",
532 static_libs: ["b"],
533 }
534 cc_library {
535 name: "d",
536 }
537
538 `)
539
540 variant := "android_arm64_armv8-a_core_static"
541 moduleA := ctx.ModuleForTests("a", variant).Module().(*Module)
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800542 actual := moduleA.depsInLinkOrder
Jeff Gaston294356f2017-09-27 17:05:30 -0700543 expected := getOutputPaths(ctx, variant, []string{"c", "b", "d"})
544
545 if !reflect.DeepEqual(actual, expected) {
546 t.Errorf("staticDeps orderings were not propagated correctly"+
547 "\nactual: %v"+
548 "\nexpected: %v",
549 actual,
550 expected,
551 )
552 }
Jiyong Parkd08b6972017-09-26 10:50:54 +0900553}
Jeff Gaston294356f2017-09-27 17:05:30 -0700554
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800555func TestStaticLibDepReorderingWithShared(t *testing.T) {
556 ctx := testCc(t, `
557 cc_library {
558 name: "a",
559 static_libs: ["b", "c"],
560 }
561 cc_library {
562 name: "b",
563 }
564 cc_library {
565 name: "c",
566 shared_libs: ["b"],
567 }
568
569 `)
570
571 variant := "android_arm64_armv8-a_core_static"
572 moduleA := ctx.ModuleForTests("a", variant).Module().(*Module)
573 actual := moduleA.depsInLinkOrder
574 expected := getOutputPaths(ctx, variant, []string{"c", "b"})
575
576 if !reflect.DeepEqual(actual, expected) {
577 t.Errorf("staticDeps orderings did not account for shared libs"+
578 "\nactual: %v"+
579 "\nexpected: %v",
580 actual,
581 expected,
582 )
583 }
584}
585
Jiyong Parkd08b6972017-09-26 10:50:54 +0900586var compilerFlagsTestCases = []struct {
587 in string
588 out bool
589}{
590 {
591 in: "a",
592 out: false,
593 },
594 {
595 in: "-a",
596 out: true,
597 },
598 {
599 in: "-Ipath/to/something",
600 out: false,
601 },
602 {
603 in: "-isystempath/to/something",
604 out: false,
605 },
606 {
607 in: "--coverage",
608 out: false,
609 },
610 {
611 in: "-include a/b",
612 out: true,
613 },
614 {
615 in: "-include a/b c/d",
616 out: false,
617 },
618 {
619 in: "-DMACRO",
620 out: true,
621 },
622 {
623 in: "-DMAC RO",
624 out: false,
625 },
626 {
627 in: "-a -b",
628 out: false,
629 },
630 {
631 in: "-DMACRO=definition",
632 out: true,
633 },
634 {
635 in: "-DMACRO=defi nition",
636 out: true, // TODO(jiyong): this should be false
637 },
638 {
639 in: "-DMACRO(x)=x + 1",
640 out: true,
641 },
642 {
643 in: "-DMACRO=\"defi nition\"",
644 out: true,
645 },
646}
647
648type mockContext struct {
649 BaseModuleContext
650 result bool
651}
652
653func (ctx *mockContext) PropertyErrorf(property, format string, args ...interface{}) {
654 // CheckBadCompilerFlags calls this function when the flag should be rejected
655 ctx.result = false
656}
657
658func TestCompilerFlags(t *testing.T) {
659 for _, testCase := range compilerFlagsTestCases {
660 ctx := &mockContext{result: true}
661 CheckBadCompilerFlags(ctx, "", []string{testCase.in})
662 if ctx.result != testCase.out {
663 t.Errorf("incorrect output:")
664 t.Errorf(" input: %#v", testCase.in)
665 t.Errorf(" expected: %#v", testCase.out)
666 t.Errorf(" got: %#v", ctx.result)
667 }
668 }
Jeff Gaston294356f2017-09-27 17:05:30 -0700669}