blob: 9b45d3f3a957118ea77dc54cd4f4706b4ebf828c [file] [log] [blame]
Dan Willemsen34cc69e2015-09-23 15:26:20 -07001// Copyright 2015 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 Cross635c3b02016-05-18 15:37:25 -070015package android
Dan Willemsen34cc69e2015-09-23 15:26:20 -070016
17import (
18 "errors"
19 "fmt"
20 "reflect"
Colin Cross27027c72020-02-28 15:34:17 -080021 "strconv"
Dan Willemsen34cc69e2015-09-23 15:26:20 -070022 "strings"
23 "testing"
Dan Willemsen00269f22017-07-06 16:59:48 -070024
Colin Cross8a497952019-03-05 22:25:09 -080025 "github.com/google/blueprint/proptools"
Dan Willemsen34cc69e2015-09-23 15:26:20 -070026)
27
28type strsTestCase struct {
29 in []string
30 out string
31 err []error
32}
33
34var commonValidatePathTestCases = []strsTestCase{
35 {
36 in: []string{""},
37 out: "",
38 },
39 {
40 in: []string{"a/b"},
41 out: "a/b",
42 },
43 {
44 in: []string{"a/b", "c"},
45 out: "a/b/c",
46 },
47 {
48 in: []string{"a/.."},
49 out: ".",
50 },
51 {
52 in: []string{"."},
53 out: ".",
54 },
55 {
56 in: []string{".."},
57 out: "",
58 err: []error{errors.New("Path is outside directory: ..")},
59 },
60 {
61 in: []string{"../a"},
62 out: "",
63 err: []error{errors.New("Path is outside directory: ../a")},
64 },
65 {
66 in: []string{"b/../../a"},
67 out: "",
68 err: []error{errors.New("Path is outside directory: ../a")},
69 },
70 {
71 in: []string{"/a"},
72 out: "",
73 err: []error{errors.New("Path is outside directory: /a")},
74 },
Dan Willemsen80a7c2a2015-12-21 14:57:11 -080075 {
76 in: []string{"a", "../b"},
77 out: "",
78 err: []error{errors.New("Path is outside directory: ../b")},
79 },
80 {
81 in: []string{"a", "b/../../c"},
82 out: "",
83 err: []error{errors.New("Path is outside directory: ../c")},
84 },
85 {
86 in: []string{"a", "./.."},
87 out: "",
88 err: []error{errors.New("Path is outside directory: ..")},
89 },
Dan Willemsen34cc69e2015-09-23 15:26:20 -070090}
91
92var validateSafePathTestCases = append(commonValidatePathTestCases, []strsTestCase{
93 {
94 in: []string{"$host/../$a"},
95 out: "$a",
96 },
97}...)
98
99var validatePathTestCases = append(commonValidatePathTestCases, []strsTestCase{
100 {
101 in: []string{"$host/../$a"},
102 out: "",
103 err: []error{errors.New("Path contains invalid character($): $host/../$a")},
104 },
105 {
106 in: []string{"$host/.."},
107 out: "",
108 err: []error{errors.New("Path contains invalid character($): $host/..")},
109 },
110}...)
111
112func TestValidateSafePath(t *testing.T) {
113 for _, testCase := range validateSafePathTestCases {
Colin Crossdc75ae72018-02-22 13:48:13 -0800114 t.Run(strings.Join(testCase.in, ","), func(t *testing.T) {
115 ctx := &configErrorWrapper{}
Colin Cross1ccfcc32018-02-22 13:54:26 -0800116 out, err := validateSafePath(testCase.in...)
117 if err != nil {
118 reportPathError(ctx, err)
119 }
Colin Crossdc75ae72018-02-22 13:48:13 -0800120 check(t, "validateSafePath", p(testCase.in), out, ctx.errors, testCase.out, testCase.err)
121 })
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700122 }
123}
124
125func TestValidatePath(t *testing.T) {
126 for _, testCase := range validatePathTestCases {
Colin Crossdc75ae72018-02-22 13:48:13 -0800127 t.Run(strings.Join(testCase.in, ","), func(t *testing.T) {
128 ctx := &configErrorWrapper{}
Colin Cross1ccfcc32018-02-22 13:54:26 -0800129 out, err := validatePath(testCase.in...)
130 if err != nil {
131 reportPathError(ctx, err)
132 }
Colin Crossdc75ae72018-02-22 13:48:13 -0800133 check(t, "validatePath", p(testCase.in), out, ctx.errors, testCase.out, testCase.err)
134 })
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700135 }
136}
137
138func TestOptionalPath(t *testing.T) {
139 var path OptionalPath
140 checkInvalidOptionalPath(t, path)
141
142 path = OptionalPathForPath(nil)
143 checkInvalidOptionalPath(t, path)
144}
145
146func checkInvalidOptionalPath(t *testing.T, path OptionalPath) {
Colin Crossdc75ae72018-02-22 13:48:13 -0800147 t.Helper()
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700148 if path.Valid() {
149 t.Errorf("Uninitialized OptionalPath should not be valid")
150 }
151 if path.String() != "" {
152 t.Errorf("Uninitialized OptionalPath String() should return \"\", not %q", path.String())
153 }
154 defer func() {
155 if r := recover(); r == nil {
156 t.Errorf("Expected a panic when calling Path() on an uninitialized OptionalPath")
157 }
158 }()
159 path.Path()
160}
161
162func check(t *testing.T, testType, testString string,
163 got interface{}, err []error,
164 expected interface{}, expectedErr []error) {
Colin Crossdc75ae72018-02-22 13:48:13 -0800165 t.Helper()
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700166
167 printedTestCase := false
168 e := func(s string, expected, got interface{}) {
Colin Crossdc75ae72018-02-22 13:48:13 -0800169 t.Helper()
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700170 if !printedTestCase {
171 t.Errorf("test case %s: %s", testType, testString)
172 printedTestCase = true
173 }
174 t.Errorf("incorrect %s", s)
175 t.Errorf(" expected: %s", p(expected))
176 t.Errorf(" got: %s", p(got))
177 }
178
179 if !reflect.DeepEqual(expectedErr, err) {
180 e("errors:", expectedErr, err)
181 }
182
183 if !reflect.DeepEqual(expected, got) {
184 e("output:", expected, got)
185 }
186}
187
188func p(in interface{}) string {
189 if v, ok := in.([]interface{}); ok {
190 s := make([]string, len(v))
191 for i := range v {
192 s[i] = fmt.Sprintf("%#v", v[i])
193 }
194 return "[" + strings.Join(s, ", ") + "]"
195 } else {
196 return fmt.Sprintf("%#v", in)
197 }
198}
Dan Willemsen00269f22017-07-06 16:59:48 -0700199
200type moduleInstallPathContextImpl struct {
Colin Cross0ea8ba82019-06-06 14:33:29 -0700201 baseModuleContext
Dan Willemsen00269f22017-07-06 16:59:48 -0700202
203 inData bool
Jaewoong Jung0949f312019-09-11 10:25:18 -0700204 inTestcases bool
Dan Willemsen00269f22017-07-06 16:59:48 -0700205 inSanitizerDir bool
Yifan Hong1b3348d2020-01-21 15:53:22 -0800206 inRamdisk bool
Jiyong Parkf9332f12018-02-01 00:54:12 +0900207 inRecovery bool
Colin Cross90ba5f42019-10-02 11:10:58 -0700208 inRoot bool
Colin Cross6e359402020-02-10 15:29:54 -0800209 forceOS *OsType
Dan Willemsen00269f22017-07-06 16:59:48 -0700210}
211
Colin Crossaabf6792017-11-29 00:27:14 -0800212func (m moduleInstallPathContextImpl) Config() Config {
Colin Cross0ea8ba82019-06-06 14:33:29 -0700213 return m.baseModuleContext.config
Dan Willemsen00269f22017-07-06 16:59:48 -0700214}
215
216func (moduleInstallPathContextImpl) AddNinjaFileDeps(deps ...string) {}
217
218func (m moduleInstallPathContextImpl) InstallInData() bool {
219 return m.inData
220}
221
Jaewoong Jung0949f312019-09-11 10:25:18 -0700222func (m moduleInstallPathContextImpl) InstallInTestcases() bool {
223 return m.inTestcases
224}
225
Dan Willemsen00269f22017-07-06 16:59:48 -0700226func (m moduleInstallPathContextImpl) InstallInSanitizerDir() bool {
227 return m.inSanitizerDir
228}
229
Yifan Hong1b3348d2020-01-21 15:53:22 -0800230func (m moduleInstallPathContextImpl) InstallInRamdisk() bool {
231 return m.inRamdisk
232}
233
Jiyong Parkf9332f12018-02-01 00:54:12 +0900234func (m moduleInstallPathContextImpl) InstallInRecovery() bool {
235 return m.inRecovery
236}
237
Colin Cross90ba5f42019-10-02 11:10:58 -0700238func (m moduleInstallPathContextImpl) InstallInRoot() bool {
239 return m.inRoot
240}
241
Colin Cross607d8582019-07-29 16:44:46 -0700242func (m moduleInstallPathContextImpl) InstallBypassMake() bool {
243 return false
244}
245
Colin Cross6e359402020-02-10 15:29:54 -0800246func (m moduleInstallPathContextImpl) InstallForceOS() *OsType {
247 return m.forceOS
248}
249
Colin Cross98be1bb2019-12-13 20:41:13 -0800250func pathTestConfig(buildDir string) Config {
251 return TestConfig(buildDir, nil, "", nil)
252}
253
Dan Willemsen00269f22017-07-06 16:59:48 -0700254func TestPathForModuleInstall(t *testing.T) {
Colin Cross98be1bb2019-12-13 20:41:13 -0800255 testConfig := pathTestConfig("")
Dan Willemsen00269f22017-07-06 16:59:48 -0700256
257 hostTarget := Target{Os: Linux}
258 deviceTarget := Target{Os: Android}
259
260 testCases := []struct {
261 name string
262 ctx *moduleInstallPathContextImpl
263 in []string
264 out string
265 }{
266 {
267 name: "host binary",
268 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700269 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800270 os: hostTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700271 target: hostTarget,
272 },
273 },
274 in: []string{"bin", "my_test"},
275 out: "host/linux-x86/bin/my_test",
276 },
277
278 {
279 name: "system binary",
280 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700281 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800282 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700283 target: deviceTarget,
284 },
285 },
286 in: []string{"bin", "my_test"},
287 out: "target/product/test_device/system/bin/my_test",
288 },
289 {
290 name: "vendor binary",
291 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700292 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800293 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700294 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800295 earlyModuleContext: earlyModuleContext{
296 kind: socSpecificModule,
297 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700298 },
299 },
300 in: []string{"bin", "my_test"},
301 out: "target/product/test_device/vendor/bin/my_test",
302 },
Jiyong Park2db76922017-11-08 16:03:48 +0900303 {
304 name: "odm binary",
305 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700306 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800307 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900308 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800309 earlyModuleContext: earlyModuleContext{
310 kind: deviceSpecificModule,
311 },
Jiyong Park2db76922017-11-08 16:03:48 +0900312 },
313 },
314 in: []string{"bin", "my_test"},
315 out: "target/product/test_device/odm/bin/my_test",
316 },
317 {
Jaekyun Seok5cfbfbb2018-01-10 19:00:15 +0900318 name: "product binary",
Jiyong Park2db76922017-11-08 16:03:48 +0900319 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700320 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800321 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900322 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800323 earlyModuleContext: earlyModuleContext{
324 kind: productSpecificModule,
325 },
Jiyong Park2db76922017-11-08 16:03:48 +0900326 },
327 },
328 in: []string{"bin", "my_test"},
Jaekyun Seok5cfbfbb2018-01-10 19:00:15 +0900329 out: "target/product/test_device/product/bin/my_test",
Jiyong Park2db76922017-11-08 16:03:48 +0900330 },
Dario Frenifd05a742018-05-29 13:28:54 +0100331 {
Justin Yund5f6c822019-06-25 16:47:17 +0900332 name: "system_ext binary",
Dario Frenifd05a742018-05-29 13:28:54 +0100333 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700334 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800335 os: deviceTarget.Os,
Dario Frenifd05a742018-05-29 13:28:54 +0100336 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800337 earlyModuleContext: earlyModuleContext{
338 kind: systemExtSpecificModule,
339 },
Dario Frenifd05a742018-05-29 13:28:54 +0100340 },
341 },
342 in: []string{"bin", "my_test"},
Justin Yund5f6c822019-06-25 16:47:17 +0900343 out: "target/product/test_device/system_ext/bin/my_test",
Dario Frenifd05a742018-05-29 13:28:54 +0100344 },
Colin Cross90ba5f42019-10-02 11:10:58 -0700345 {
346 name: "root binary",
347 ctx: &moduleInstallPathContextImpl{
348 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800349 os: deviceTarget.Os,
Colin Cross90ba5f42019-10-02 11:10:58 -0700350 target: deviceTarget,
351 },
352 inRoot: true,
353 },
354 in: []string{"my_test"},
355 out: "target/product/test_device/root/my_test",
356 },
357 {
358 name: "recovery binary",
359 ctx: &moduleInstallPathContextImpl{
360 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800361 os: deviceTarget.Os,
Colin Cross90ba5f42019-10-02 11:10:58 -0700362 target: deviceTarget,
363 },
364 inRecovery: true,
365 },
366 in: []string{"bin/my_test"},
367 out: "target/product/test_device/recovery/root/system/bin/my_test",
368 },
369 {
370 name: "recovery root binary",
371 ctx: &moduleInstallPathContextImpl{
372 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800373 os: deviceTarget.Os,
Colin Cross90ba5f42019-10-02 11:10:58 -0700374 target: deviceTarget,
375 },
376 inRecovery: true,
377 inRoot: true,
378 },
379 in: []string{"my_test"},
380 out: "target/product/test_device/recovery/root/my_test",
381 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700382
383 {
384 name: "system native test binary",
385 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700386 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800387 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700388 target: deviceTarget,
389 },
390 inData: true,
391 },
392 in: []string{"nativetest", "my_test"},
393 out: "target/product/test_device/data/nativetest/my_test",
394 },
395 {
396 name: "vendor native test binary",
397 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700398 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800399 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700400 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800401 earlyModuleContext: earlyModuleContext{
402 kind: socSpecificModule,
403 },
Jiyong Park2db76922017-11-08 16:03:48 +0900404 },
405 inData: true,
406 },
407 in: []string{"nativetest", "my_test"},
408 out: "target/product/test_device/data/nativetest/my_test",
409 },
410 {
411 name: "odm native test binary",
412 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700413 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800414 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900415 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800416 earlyModuleContext: earlyModuleContext{
417 kind: deviceSpecificModule,
418 },
Jiyong Park2db76922017-11-08 16:03:48 +0900419 },
420 inData: true,
421 },
422 in: []string{"nativetest", "my_test"},
423 out: "target/product/test_device/data/nativetest/my_test",
424 },
425 {
Jaekyun Seok5cfbfbb2018-01-10 19:00:15 +0900426 name: "product native test binary",
Jiyong Park2db76922017-11-08 16:03:48 +0900427 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700428 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800429 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900430 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800431 earlyModuleContext: earlyModuleContext{
432 kind: productSpecificModule,
433 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700434 },
435 inData: true,
436 },
437 in: []string{"nativetest", "my_test"},
438 out: "target/product/test_device/data/nativetest/my_test",
439 },
440
441 {
Justin Yund5f6c822019-06-25 16:47:17 +0900442 name: "system_ext native test binary",
Dario Frenifd05a742018-05-29 13:28:54 +0100443 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700444 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800445 os: deviceTarget.Os,
Dario Frenifd05a742018-05-29 13:28:54 +0100446 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800447 earlyModuleContext: earlyModuleContext{
448 kind: systemExtSpecificModule,
449 },
Dario Frenifd05a742018-05-29 13:28:54 +0100450 },
451 inData: true,
452 },
453 in: []string{"nativetest", "my_test"},
454 out: "target/product/test_device/data/nativetest/my_test",
455 },
456
457 {
Dan Willemsen00269f22017-07-06 16:59:48 -0700458 name: "sanitized system binary",
459 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700460 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800461 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700462 target: deviceTarget,
463 },
464 inSanitizerDir: true,
465 },
466 in: []string{"bin", "my_test"},
467 out: "target/product/test_device/data/asan/system/bin/my_test",
468 },
469 {
470 name: "sanitized vendor binary",
471 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700472 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800473 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700474 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800475 earlyModuleContext: earlyModuleContext{
476 kind: socSpecificModule,
477 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700478 },
479 inSanitizerDir: true,
480 },
481 in: []string{"bin", "my_test"},
482 out: "target/product/test_device/data/asan/vendor/bin/my_test",
483 },
Jiyong Park2db76922017-11-08 16:03:48 +0900484 {
485 name: "sanitized odm binary",
486 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700487 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800488 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900489 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800490 earlyModuleContext: earlyModuleContext{
491 kind: deviceSpecificModule,
492 },
Jiyong Park2db76922017-11-08 16:03:48 +0900493 },
494 inSanitizerDir: true,
495 },
496 in: []string{"bin", "my_test"},
497 out: "target/product/test_device/data/asan/odm/bin/my_test",
498 },
499 {
Jaekyun Seok5cfbfbb2018-01-10 19:00:15 +0900500 name: "sanitized product binary",
Jiyong Park2db76922017-11-08 16:03:48 +0900501 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700502 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800503 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900504 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800505 earlyModuleContext: earlyModuleContext{
506 kind: productSpecificModule,
507 },
Jiyong Park2db76922017-11-08 16:03:48 +0900508 },
509 inSanitizerDir: true,
510 },
511 in: []string{"bin", "my_test"},
Jaekyun Seok5cfbfbb2018-01-10 19:00:15 +0900512 out: "target/product/test_device/data/asan/product/bin/my_test",
Jiyong Park2db76922017-11-08 16:03:48 +0900513 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700514
515 {
Justin Yund5f6c822019-06-25 16:47:17 +0900516 name: "sanitized system_ext binary",
Dario Frenifd05a742018-05-29 13:28:54 +0100517 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700518 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800519 os: deviceTarget.Os,
Dario Frenifd05a742018-05-29 13:28:54 +0100520 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800521 earlyModuleContext: earlyModuleContext{
522 kind: systemExtSpecificModule,
523 },
Dario Frenifd05a742018-05-29 13:28:54 +0100524 },
525 inSanitizerDir: true,
526 },
527 in: []string{"bin", "my_test"},
Justin Yund5f6c822019-06-25 16:47:17 +0900528 out: "target/product/test_device/data/asan/system_ext/bin/my_test",
Dario Frenifd05a742018-05-29 13:28:54 +0100529 },
530
531 {
Dan Willemsen00269f22017-07-06 16:59:48 -0700532 name: "sanitized system native test binary",
533 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700534 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800535 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700536 target: deviceTarget,
537 },
538 inData: true,
539 inSanitizerDir: true,
540 },
541 in: []string{"nativetest", "my_test"},
542 out: "target/product/test_device/data/asan/data/nativetest/my_test",
543 },
544 {
545 name: "sanitized vendor native test binary",
546 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700547 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800548 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700549 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800550 earlyModuleContext: earlyModuleContext{
551 kind: socSpecificModule,
552 },
Jiyong Park2db76922017-11-08 16:03:48 +0900553 },
554 inData: true,
555 inSanitizerDir: true,
556 },
557 in: []string{"nativetest", "my_test"},
558 out: "target/product/test_device/data/asan/data/nativetest/my_test",
559 },
560 {
561 name: "sanitized odm native test binary",
562 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700563 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800564 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900565 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800566 earlyModuleContext: earlyModuleContext{
567 kind: deviceSpecificModule,
568 },
Jiyong Park2db76922017-11-08 16:03:48 +0900569 },
570 inData: true,
571 inSanitizerDir: true,
572 },
573 in: []string{"nativetest", "my_test"},
574 out: "target/product/test_device/data/asan/data/nativetest/my_test",
575 },
576 {
Jaekyun Seok5cfbfbb2018-01-10 19:00:15 +0900577 name: "sanitized product native test binary",
Jiyong Park2db76922017-11-08 16:03:48 +0900578 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700579 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800580 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900581 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800582 earlyModuleContext: earlyModuleContext{
583 kind: productSpecificModule,
584 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700585 },
586 inData: true,
587 inSanitizerDir: true,
588 },
589 in: []string{"nativetest", "my_test"},
590 out: "target/product/test_device/data/asan/data/nativetest/my_test",
591 },
Dario Frenifd05a742018-05-29 13:28:54 +0100592 {
Justin Yund5f6c822019-06-25 16:47:17 +0900593 name: "sanitized system_ext native test binary",
Dario Frenifd05a742018-05-29 13:28:54 +0100594 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700595 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800596 os: deviceTarget.Os,
Dario Frenifd05a742018-05-29 13:28:54 +0100597 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800598 earlyModuleContext: earlyModuleContext{
599 kind: systemExtSpecificModule,
600 },
Dario Frenifd05a742018-05-29 13:28:54 +0100601 },
602 inData: true,
603 inSanitizerDir: true,
604 },
605 in: []string{"nativetest", "my_test"},
606 out: "target/product/test_device/data/asan/data/nativetest/my_test",
Colin Cross6e359402020-02-10 15:29:54 -0800607 }, {
608 name: "device testcases",
609 ctx: &moduleInstallPathContextImpl{
610 baseModuleContext: baseModuleContext{
611 os: deviceTarget.Os,
612 target: deviceTarget,
613 },
614 inTestcases: true,
615 },
616 in: []string{"my_test", "my_test_bin"},
617 out: "target/product/test_device/testcases/my_test/my_test_bin",
618 }, {
619 name: "host testcases",
620 ctx: &moduleInstallPathContextImpl{
621 baseModuleContext: baseModuleContext{
622 os: hostTarget.Os,
623 target: hostTarget,
624 },
625 inTestcases: true,
626 },
627 in: []string{"my_test", "my_test_bin"},
628 out: "host/linux-x86/testcases/my_test/my_test_bin",
629 }, {
630 name: "forced host testcases",
631 ctx: &moduleInstallPathContextImpl{
632 baseModuleContext: baseModuleContext{
633 os: deviceTarget.Os,
634 target: deviceTarget,
635 },
636 inTestcases: true,
637 forceOS: &Linux,
638 },
639 in: []string{"my_test", "my_test_bin"},
640 out: "host/linux-x86/testcases/my_test/my_test_bin",
Dario Frenifd05a742018-05-29 13:28:54 +0100641 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700642 }
643
644 for _, tc := range testCases {
645 t.Run(tc.name, func(t *testing.T) {
Colin Cross0ea8ba82019-06-06 14:33:29 -0700646 tc.ctx.baseModuleContext.config = testConfig
Dan Willemsen00269f22017-07-06 16:59:48 -0700647 output := PathForModuleInstall(tc.ctx, tc.in...)
648 if output.basePath.path != tc.out {
649 t.Errorf("unexpected path:\n got: %q\nwant: %q\n",
650 output.basePath.path,
651 tc.out)
652 }
653 })
654 }
655}
Colin Cross5e6cfbe2017-11-03 15:20:35 -0700656
657func TestDirectorySortedPaths(t *testing.T) {
Colin Cross98be1bb2019-12-13 20:41:13 -0800658 config := TestConfig("out", nil, "", map[string][]byte{
659 "Android.bp": nil,
660 "a.txt": nil,
661 "a/txt": nil,
662 "a/b/c": nil,
663 "a/b/d": nil,
664 "b": nil,
665 "b/b.txt": nil,
666 "a/a.txt": nil,
Colin Cross07e51612019-03-05 12:46:40 -0800667 })
668
Colin Cross98be1bb2019-12-13 20:41:13 -0800669 ctx := PathContextForTesting(config)
670
Colin Cross5e6cfbe2017-11-03 15:20:35 -0700671 makePaths := func() Paths {
672 return Paths{
Colin Cross07e51612019-03-05 12:46:40 -0800673 PathForSource(ctx, "a.txt"),
674 PathForSource(ctx, "a/txt"),
675 PathForSource(ctx, "a/b/c"),
676 PathForSource(ctx, "a/b/d"),
677 PathForSource(ctx, "b"),
678 PathForSource(ctx, "b/b.txt"),
679 PathForSource(ctx, "a/a.txt"),
Colin Cross5e6cfbe2017-11-03 15:20:35 -0700680 }
681 }
682
683 expected := []string{
684 "a.txt",
685 "a/a.txt",
686 "a/b/c",
687 "a/b/d",
688 "a/txt",
689 "b",
690 "b/b.txt",
691 }
692
693 paths := makePaths()
Colin Crossa140bb02018-04-17 10:52:26 -0700694 reversePaths := ReversePaths(paths)
Colin Cross5e6cfbe2017-11-03 15:20:35 -0700695
696 sortedPaths := PathsToDirectorySortedPaths(paths)
697 reverseSortedPaths := PathsToDirectorySortedPaths(reversePaths)
698
699 if !reflect.DeepEqual(Paths(sortedPaths).Strings(), expected) {
700 t.Fatalf("sorted paths:\n %#v\n != \n %#v", paths.Strings(), expected)
701 }
702
703 if !reflect.DeepEqual(Paths(reverseSortedPaths).Strings(), expected) {
704 t.Fatalf("sorted reversed paths:\n %#v\n !=\n %#v", reversePaths.Strings(), expected)
705 }
706
707 expectedA := []string{
708 "a/a.txt",
709 "a/b/c",
710 "a/b/d",
711 "a/txt",
712 }
713
714 inA := sortedPaths.PathsInDirectory("a")
715 if !reflect.DeepEqual(inA.Strings(), expectedA) {
716 t.Errorf("FilesInDirectory(a):\n %#v\n != \n %#v", inA.Strings(), expectedA)
717 }
718
719 expectedA_B := []string{
720 "a/b/c",
721 "a/b/d",
722 }
723
724 inA_B := sortedPaths.PathsInDirectory("a/b")
725 if !reflect.DeepEqual(inA_B.Strings(), expectedA_B) {
726 t.Errorf("FilesInDirectory(a/b):\n %#v\n != \n %#v", inA_B.Strings(), expectedA_B)
727 }
728
729 expectedB := []string{
730 "b/b.txt",
731 }
732
733 inB := sortedPaths.PathsInDirectory("b")
734 if !reflect.DeepEqual(inB.Strings(), expectedB) {
735 t.Errorf("FilesInDirectory(b):\n %#v\n != \n %#v", inA.Strings(), expectedA)
736 }
737}
Colin Cross43f08db2018-11-12 10:13:39 -0800738
739func TestMaybeRel(t *testing.T) {
740 testCases := []struct {
741 name string
742 base string
743 target string
744 out string
745 isRel bool
746 }{
747 {
748 name: "normal",
749 base: "a/b/c",
750 target: "a/b/c/d",
751 out: "d",
752 isRel: true,
753 },
754 {
755 name: "parent",
756 base: "a/b/c/d",
757 target: "a/b/c",
758 isRel: false,
759 },
760 {
761 name: "not relative",
762 base: "a/b",
763 target: "c/d",
764 isRel: false,
765 },
766 {
767 name: "abs1",
768 base: "/a",
769 target: "a",
770 isRel: false,
771 },
772 {
773 name: "abs2",
774 base: "a",
775 target: "/a",
776 isRel: false,
777 },
778 }
779
780 for _, testCase := range testCases {
781 t.Run(testCase.name, func(t *testing.T) {
782 ctx := &configErrorWrapper{}
783 out, isRel := MaybeRel(ctx, testCase.base, testCase.target)
784 if len(ctx.errors) > 0 {
785 t.Errorf("MaybeRel(..., %s, %s) reported unexpected errors %v",
786 testCase.base, testCase.target, ctx.errors)
787 }
788 if isRel != testCase.isRel || out != testCase.out {
789 t.Errorf("MaybeRel(..., %s, %s) want %v, %v got %v, %v",
790 testCase.base, testCase.target, testCase.out, testCase.isRel, out, isRel)
791 }
792 })
793 }
794}
Colin Cross7b3dcc32019-01-24 13:14:39 -0800795
796func TestPathForSource(t *testing.T) {
797 testCases := []struct {
798 name string
799 buildDir string
800 src string
801 err string
802 }{
803 {
804 name: "normal",
805 buildDir: "out",
806 src: "a/b/c",
807 },
808 {
809 name: "abs",
810 buildDir: "out",
811 src: "/a/b/c",
812 err: "is outside directory",
813 },
814 {
815 name: "in out dir",
816 buildDir: "out",
817 src: "out/a/b/c",
818 err: "is in output",
819 },
820 }
821
822 funcs := []struct {
823 name string
824 f func(ctx PathContext, pathComponents ...string) (SourcePath, error)
825 }{
826 {"pathForSource", pathForSource},
827 {"safePathForSource", safePathForSource},
828 }
829
830 for _, f := range funcs {
831 t.Run(f.name, func(t *testing.T) {
832 for _, test := range testCases {
833 t.Run(test.name, func(t *testing.T) {
Colin Cross98be1bb2019-12-13 20:41:13 -0800834 testConfig := pathTestConfig(test.buildDir)
Colin Cross7b3dcc32019-01-24 13:14:39 -0800835 ctx := &configErrorWrapper{config: testConfig}
836 _, err := f.f(ctx, test.src)
837 if len(ctx.errors) > 0 {
838 t.Fatalf("unexpected errors %v", ctx.errors)
839 }
840 if err != nil {
841 if test.err == "" {
842 t.Fatalf("unexpected error %q", err.Error())
843 } else if !strings.Contains(err.Error(), test.err) {
844 t.Fatalf("incorrect error, want substring %q got %q", test.err, err.Error())
845 }
846 } else {
847 if test.err != "" {
848 t.Fatalf("missing error %q", test.err)
849 }
850 }
851 })
852 }
853 })
854 }
855}
Colin Cross8854a5a2019-02-11 14:14:16 -0800856
Colin Cross8a497952019-03-05 22:25:09 -0800857type pathForModuleSrcTestModule struct {
Colin Cross937664a2019-03-06 10:17:32 -0800858 ModuleBase
859 props struct {
860 Srcs []string `android:"path"`
861 Exclude_srcs []string `android:"path"`
Colin Cross8a497952019-03-05 22:25:09 -0800862
863 Src *string `android:"path"`
Colin Crossba71a3f2019-03-18 12:12:48 -0700864
865 Module_handles_missing_deps bool
Colin Cross937664a2019-03-06 10:17:32 -0800866 }
867
Colin Cross8a497952019-03-05 22:25:09 -0800868 src string
869 rel string
870
871 srcs []string
Colin Cross937664a2019-03-06 10:17:32 -0800872 rels []string
Colin Cross8a497952019-03-05 22:25:09 -0800873
874 missingDeps []string
Colin Cross937664a2019-03-06 10:17:32 -0800875}
876
Colin Cross8a497952019-03-05 22:25:09 -0800877func pathForModuleSrcTestModuleFactory() Module {
878 module := &pathForModuleSrcTestModule{}
Colin Cross937664a2019-03-06 10:17:32 -0800879 module.AddProperties(&module.props)
880 InitAndroidModule(module)
881 return module
882}
883
Colin Cross8a497952019-03-05 22:25:09 -0800884func (p *pathForModuleSrcTestModule) GenerateAndroidBuildActions(ctx ModuleContext) {
Colin Crossba71a3f2019-03-18 12:12:48 -0700885 var srcs Paths
886 if p.props.Module_handles_missing_deps {
887 srcs, p.missingDeps = PathsAndMissingDepsForModuleSrcExcludes(ctx, p.props.Srcs, p.props.Exclude_srcs)
888 } else {
889 srcs = PathsForModuleSrcExcludes(ctx, p.props.Srcs, p.props.Exclude_srcs)
890 }
Colin Cross8a497952019-03-05 22:25:09 -0800891 p.srcs = srcs.Strings()
Colin Cross937664a2019-03-06 10:17:32 -0800892
Colin Cross8a497952019-03-05 22:25:09 -0800893 for _, src := range srcs {
Colin Cross937664a2019-03-06 10:17:32 -0800894 p.rels = append(p.rels, src.Rel())
895 }
Colin Cross8a497952019-03-05 22:25:09 -0800896
897 if p.props.Src != nil {
898 src := PathForModuleSrc(ctx, *p.props.Src)
899 if src != nil {
900 p.src = src.String()
901 p.rel = src.Rel()
902 }
903 }
904
Colin Crossba71a3f2019-03-18 12:12:48 -0700905 if !p.props.Module_handles_missing_deps {
906 p.missingDeps = ctx.GetMissingDependencies()
907 }
Colin Cross6c4f21f2019-06-06 15:41:36 -0700908
909 ctx.Build(pctx, BuildParams{
910 Rule: Touch,
911 Output: PathForModuleOut(ctx, "output"),
912 })
Colin Cross8a497952019-03-05 22:25:09 -0800913}
914
Colin Cross41955e82019-05-29 14:40:35 -0700915type pathForModuleSrcOutputFileProviderModule struct {
916 ModuleBase
917 props struct {
918 Outs []string
919 Tagged []string
920 }
921
922 outs Paths
923 tagged Paths
924}
925
926func pathForModuleSrcOutputFileProviderModuleFactory() Module {
927 module := &pathForModuleSrcOutputFileProviderModule{}
928 module.AddProperties(&module.props)
929 InitAndroidModule(module)
930 return module
931}
932
933func (p *pathForModuleSrcOutputFileProviderModule) GenerateAndroidBuildActions(ctx ModuleContext) {
934 for _, out := range p.props.Outs {
935 p.outs = append(p.outs, PathForModuleOut(ctx, out))
936 }
937
938 for _, tagged := range p.props.Tagged {
939 p.tagged = append(p.tagged, PathForModuleOut(ctx, tagged))
940 }
941}
942
943func (p *pathForModuleSrcOutputFileProviderModule) OutputFiles(tag string) (Paths, error) {
944 switch tag {
945 case "":
946 return p.outs, nil
947 case ".tagged":
948 return p.tagged, nil
949 default:
950 return nil, fmt.Errorf("unsupported tag %q", tag)
951 }
952}
953
Colin Cross8a497952019-03-05 22:25:09 -0800954type pathForModuleSrcTestCase struct {
955 name string
956 bp string
957 srcs []string
958 rels []string
959 src string
960 rel string
961}
962
963func testPathForModuleSrc(t *testing.T, buildDir string, tests []pathForModuleSrcTestCase) {
964 for _, test := range tests {
965 t.Run(test.name, func(t *testing.T) {
Colin Cross8a497952019-03-05 22:25:09 -0800966 ctx := NewTestContext()
967
Colin Cross4b49b762019-11-22 15:25:03 -0800968 ctx.RegisterModuleType("test", pathForModuleSrcTestModuleFactory)
969 ctx.RegisterModuleType("output_file_provider", pathForModuleSrcOutputFileProviderModuleFactory)
970 ctx.RegisterModuleType("filegroup", FileGroupFactory)
Colin Cross8a497952019-03-05 22:25:09 -0800971
972 fgBp := `
973 filegroup {
974 name: "a",
975 srcs: ["src/a"],
976 }
977 `
978
Colin Cross41955e82019-05-29 14:40:35 -0700979 ofpBp := `
980 output_file_provider {
981 name: "b",
982 outs: ["gen/b"],
983 tagged: ["gen/c"],
984 }
985 `
986
Colin Cross8a497952019-03-05 22:25:09 -0800987 mockFS := map[string][]byte{
988 "fg/Android.bp": []byte(fgBp),
989 "foo/Android.bp": []byte(test.bp),
Colin Cross41955e82019-05-29 14:40:35 -0700990 "ofp/Android.bp": []byte(ofpBp),
Colin Cross8a497952019-03-05 22:25:09 -0800991 "fg/src/a": nil,
992 "foo/src/b": nil,
993 "foo/src/c": nil,
994 "foo/src/d": nil,
995 "foo/src/e/e": nil,
996 "foo/src_special/$": nil,
997 }
998
Colin Cross98be1bb2019-12-13 20:41:13 -0800999 config := TestConfig(buildDir, nil, "", mockFS)
Colin Cross8a497952019-03-05 22:25:09 -08001000
Colin Cross98be1bb2019-12-13 20:41:13 -08001001 ctx.Register(config)
Colin Cross41955e82019-05-29 14:40:35 -07001002 _, errs := ctx.ParseFileList(".", []string{"fg/Android.bp", "foo/Android.bp", "ofp/Android.bp"})
Colin Cross8a497952019-03-05 22:25:09 -08001003 FailIfErrored(t, errs)
1004 _, errs = ctx.PrepareBuildActions(config)
1005 FailIfErrored(t, errs)
1006
1007 m := ctx.ModuleForTests("foo", "").Module().(*pathForModuleSrcTestModule)
1008
1009 if g, w := m.srcs, test.srcs; !reflect.DeepEqual(g, w) {
1010 t.Errorf("want srcs %q, got %q", w, g)
1011 }
1012
1013 if g, w := m.rels, test.rels; !reflect.DeepEqual(g, w) {
1014 t.Errorf("want rels %q, got %q", w, g)
1015 }
1016
1017 if g, w := m.src, test.src; g != w {
1018 t.Errorf("want src %q, got %q", w, g)
1019 }
1020
1021 if g, w := m.rel, test.rel; g != w {
1022 t.Errorf("want rel %q, got %q", w, g)
1023 }
1024 })
1025 }
Colin Cross937664a2019-03-06 10:17:32 -08001026}
1027
Colin Cross8a497952019-03-05 22:25:09 -08001028func TestPathsForModuleSrc(t *testing.T) {
1029 tests := []pathForModuleSrcTestCase{
Colin Cross937664a2019-03-06 10:17:32 -08001030 {
1031 name: "path",
1032 bp: `
1033 test {
1034 name: "foo",
1035 srcs: ["src/b"],
1036 }`,
1037 srcs: []string{"foo/src/b"},
1038 rels: []string{"src/b"},
1039 },
1040 {
1041 name: "glob",
1042 bp: `
1043 test {
1044 name: "foo",
1045 srcs: [
1046 "src/*",
1047 "src/e/*",
1048 ],
1049 }`,
1050 srcs: []string{"foo/src/b", "foo/src/c", "foo/src/d", "foo/src/e/e"},
1051 rels: []string{"src/b", "src/c", "src/d", "src/e/e"},
1052 },
1053 {
1054 name: "recursive glob",
1055 bp: `
1056 test {
1057 name: "foo",
1058 srcs: ["src/**/*"],
1059 }`,
1060 srcs: []string{"foo/src/b", "foo/src/c", "foo/src/d", "foo/src/e/e"},
1061 rels: []string{"src/b", "src/c", "src/d", "src/e/e"},
1062 },
1063 {
1064 name: "filegroup",
1065 bp: `
1066 test {
1067 name: "foo",
1068 srcs: [":a"],
1069 }`,
1070 srcs: []string{"fg/src/a"},
1071 rels: []string{"src/a"},
1072 },
1073 {
Colin Cross41955e82019-05-29 14:40:35 -07001074 name: "output file provider",
1075 bp: `
1076 test {
1077 name: "foo",
1078 srcs: [":b"],
1079 }`,
1080 srcs: []string{buildDir + "/.intermediates/ofp/b/gen/b"},
1081 rels: []string{"gen/b"},
1082 },
1083 {
1084 name: "output file provider tagged",
1085 bp: `
1086 test {
1087 name: "foo",
1088 srcs: [":b{.tagged}"],
1089 }`,
1090 srcs: []string{buildDir + "/.intermediates/ofp/b/gen/c"},
1091 rels: []string{"gen/c"},
1092 },
1093 {
Colin Cross937664a2019-03-06 10:17:32 -08001094 name: "special characters glob",
1095 bp: `
1096 test {
1097 name: "foo",
1098 srcs: ["src_special/*"],
1099 }`,
1100 srcs: []string{"foo/src_special/$"},
1101 rels: []string{"src_special/$"},
1102 },
1103 }
1104
Colin Cross41955e82019-05-29 14:40:35 -07001105 testPathForModuleSrc(t, buildDir, tests)
1106}
1107
1108func TestPathForModuleSrc(t *testing.T) {
Colin Cross8a497952019-03-05 22:25:09 -08001109 tests := []pathForModuleSrcTestCase{
1110 {
1111 name: "path",
1112 bp: `
1113 test {
1114 name: "foo",
1115 src: "src/b",
1116 }`,
1117 src: "foo/src/b",
1118 rel: "src/b",
1119 },
1120 {
1121 name: "glob",
1122 bp: `
1123 test {
1124 name: "foo",
1125 src: "src/e/*",
1126 }`,
1127 src: "foo/src/e/e",
1128 rel: "src/e/e",
1129 },
1130 {
1131 name: "filegroup",
1132 bp: `
1133 test {
1134 name: "foo",
1135 src: ":a",
1136 }`,
1137 src: "fg/src/a",
1138 rel: "src/a",
1139 },
1140 {
Colin Cross41955e82019-05-29 14:40:35 -07001141 name: "output file provider",
1142 bp: `
1143 test {
1144 name: "foo",
1145 src: ":b",
1146 }`,
1147 src: buildDir + "/.intermediates/ofp/b/gen/b",
1148 rel: "gen/b",
1149 },
1150 {
1151 name: "output file provider tagged",
1152 bp: `
1153 test {
1154 name: "foo",
1155 src: ":b{.tagged}",
1156 }`,
1157 src: buildDir + "/.intermediates/ofp/b/gen/c",
1158 rel: "gen/c",
1159 },
1160 {
Colin Cross8a497952019-03-05 22:25:09 -08001161 name: "special characters glob",
1162 bp: `
1163 test {
1164 name: "foo",
1165 src: "src_special/*",
1166 }`,
1167 src: "foo/src_special/$",
1168 rel: "src_special/$",
1169 },
1170 }
1171
Colin Cross8a497952019-03-05 22:25:09 -08001172 testPathForModuleSrc(t, buildDir, tests)
1173}
Colin Cross937664a2019-03-06 10:17:32 -08001174
Colin Cross8a497952019-03-05 22:25:09 -08001175func TestPathsForModuleSrc_AllowMissingDependencies(t *testing.T) {
Colin Cross8a497952019-03-05 22:25:09 -08001176 bp := `
1177 test {
1178 name: "foo",
1179 srcs: [":a"],
1180 exclude_srcs: [":b"],
1181 src: ":c",
1182 }
Colin Crossba71a3f2019-03-18 12:12:48 -07001183
1184 test {
1185 name: "bar",
1186 srcs: [":d"],
1187 exclude_srcs: [":e"],
1188 module_handles_missing_deps: true,
1189 }
Colin Cross8a497952019-03-05 22:25:09 -08001190 `
1191
Colin Cross98be1bb2019-12-13 20:41:13 -08001192 config := TestConfig(buildDir, nil, bp, nil)
1193 config.TestProductVariables.Allow_missing_dependencies = proptools.BoolPtr(true)
Colin Cross8a497952019-03-05 22:25:09 -08001194
Colin Cross98be1bb2019-12-13 20:41:13 -08001195 ctx := NewTestContext()
1196 ctx.SetAllowMissingDependencies(true)
Colin Cross8a497952019-03-05 22:25:09 -08001197
Colin Cross98be1bb2019-12-13 20:41:13 -08001198 ctx.RegisterModuleType("test", pathForModuleSrcTestModuleFactory)
1199
1200 ctx.Register(config)
1201
Colin Cross8a497952019-03-05 22:25:09 -08001202 _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
1203 FailIfErrored(t, errs)
1204 _, errs = ctx.PrepareBuildActions(config)
1205 FailIfErrored(t, errs)
1206
1207 foo := ctx.ModuleForTests("foo", "").Module().(*pathForModuleSrcTestModule)
1208
1209 if g, w := foo.missingDeps, []string{"a", "b", "c"}; !reflect.DeepEqual(g, w) {
Colin Crossba71a3f2019-03-18 12:12:48 -07001210 t.Errorf("want foo missing deps %q, got %q", w, g)
Colin Cross8a497952019-03-05 22:25:09 -08001211 }
1212
1213 if g, w := foo.srcs, []string{}; !reflect.DeepEqual(g, w) {
Colin Crossba71a3f2019-03-18 12:12:48 -07001214 t.Errorf("want foo srcs %q, got %q", w, g)
Colin Cross8a497952019-03-05 22:25:09 -08001215 }
1216
1217 if g, w := foo.src, ""; g != w {
Colin Crossba71a3f2019-03-18 12:12:48 -07001218 t.Errorf("want foo src %q, got %q", w, g)
Colin Cross8a497952019-03-05 22:25:09 -08001219 }
1220
Colin Crossba71a3f2019-03-18 12:12:48 -07001221 bar := ctx.ModuleForTests("bar", "").Module().(*pathForModuleSrcTestModule)
1222
1223 if g, w := bar.missingDeps, []string{"d", "e"}; !reflect.DeepEqual(g, w) {
1224 t.Errorf("want bar missing deps %q, got %q", w, g)
1225 }
1226
1227 if g, w := bar.srcs, []string{}; !reflect.DeepEqual(g, w) {
1228 t.Errorf("want bar srcs %q, got %q", w, g)
1229 }
Colin Cross937664a2019-03-06 10:17:32 -08001230}
1231
Colin Cross8854a5a2019-02-11 14:14:16 -08001232func ExampleOutputPath_ReplaceExtension() {
1233 ctx := &configErrorWrapper{
Colin Cross98be1bb2019-12-13 20:41:13 -08001234 config: TestConfig("out", nil, "", nil),
Colin Cross8854a5a2019-02-11 14:14:16 -08001235 }
Colin Cross2cdd5df2019-02-25 10:25:24 -08001236 p := PathForOutput(ctx, "system/framework").Join(ctx, "boot.art")
Colin Cross8854a5a2019-02-11 14:14:16 -08001237 p2 := p.ReplaceExtension(ctx, "oat")
1238 fmt.Println(p, p2)
Colin Cross2cdd5df2019-02-25 10:25:24 -08001239 fmt.Println(p.Rel(), p2.Rel())
Colin Cross8854a5a2019-02-11 14:14:16 -08001240
1241 // Output:
1242 // out/system/framework/boot.art out/system/framework/boot.oat
Colin Cross2cdd5df2019-02-25 10:25:24 -08001243 // boot.art boot.oat
Colin Cross8854a5a2019-02-11 14:14:16 -08001244}
Colin Cross40e33732019-02-15 11:08:35 -08001245
1246func ExampleOutputPath_FileInSameDir() {
1247 ctx := &configErrorWrapper{
Colin Cross98be1bb2019-12-13 20:41:13 -08001248 config: TestConfig("out", nil, "", nil),
Colin Cross40e33732019-02-15 11:08:35 -08001249 }
Colin Cross2cdd5df2019-02-25 10:25:24 -08001250 p := PathForOutput(ctx, "system/framework").Join(ctx, "boot.art")
Colin Cross40e33732019-02-15 11:08:35 -08001251 p2 := p.InSameDir(ctx, "oat", "arm", "boot.vdex")
1252 fmt.Println(p, p2)
Colin Cross2cdd5df2019-02-25 10:25:24 -08001253 fmt.Println(p.Rel(), p2.Rel())
Colin Cross40e33732019-02-15 11:08:35 -08001254
1255 // Output:
1256 // out/system/framework/boot.art out/system/framework/oat/arm/boot.vdex
Colin Cross2cdd5df2019-02-25 10:25:24 -08001257 // boot.art oat/arm/boot.vdex
Colin Cross40e33732019-02-15 11:08:35 -08001258}
Colin Cross27027c72020-02-28 15:34:17 -08001259
1260func BenchmarkFirstUniquePaths(b *testing.B) {
1261 implementations := []struct {
1262 name string
1263 f func(Paths) Paths
1264 }{
1265 {
1266 name: "list",
1267 f: firstUniquePathsList,
1268 },
1269 {
1270 name: "map",
1271 f: firstUniquePathsMap,
1272 },
1273 }
1274 const maxSize = 1024
1275 uniquePaths := make(Paths, maxSize)
1276 for i := range uniquePaths {
1277 uniquePaths[i] = PathForTesting(strconv.Itoa(i))
1278 }
1279 samePath := make(Paths, maxSize)
1280 for i := range samePath {
1281 samePath[i] = uniquePaths[0]
1282 }
1283
1284 f := func(b *testing.B, imp func(Paths) Paths, paths Paths) {
1285 for i := 0; i < b.N; i++ {
1286 b.ReportAllocs()
1287 paths = append(Paths(nil), paths...)
1288 imp(paths)
1289 }
1290 }
1291
1292 for n := 1; n <= maxSize; n <<= 1 {
1293 b.Run(strconv.Itoa(n), func(b *testing.B) {
1294 for _, implementation := range implementations {
1295 b.Run(implementation.name, func(b *testing.B) {
1296 b.Run("same", func(b *testing.B) {
1297 f(b, implementation.f, samePath[:n])
1298 })
1299 b.Run("unique", func(b *testing.B) {
1300 f(b, implementation.f, uniquePaths[:n])
1301 })
1302 })
1303 }
1304 })
1305 }
1306}