blob: ba3cecc8ed8f85b410748ccadcda934e30fd2e30 [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) {
Colin Cross323dc602020-09-18 14:25:31 -0700113 t.Parallel()
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700114 for _, testCase := range validateSafePathTestCases {
Colin Crossdc75ae72018-02-22 13:48:13 -0800115 t.Run(strings.Join(testCase.in, ","), func(t *testing.T) {
116 ctx := &configErrorWrapper{}
Colin Cross1ccfcc32018-02-22 13:54:26 -0800117 out, err := validateSafePath(testCase.in...)
118 if err != nil {
119 reportPathError(ctx, err)
120 }
Colin Crossdc75ae72018-02-22 13:48:13 -0800121 check(t, "validateSafePath", p(testCase.in), out, ctx.errors, testCase.out, testCase.err)
122 })
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700123 }
124}
125
126func TestValidatePath(t *testing.T) {
Colin Cross323dc602020-09-18 14:25:31 -0700127 t.Parallel()
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700128 for _, testCase := range validatePathTestCases {
Colin Crossdc75ae72018-02-22 13:48:13 -0800129 t.Run(strings.Join(testCase.in, ","), func(t *testing.T) {
130 ctx := &configErrorWrapper{}
Colin Cross1ccfcc32018-02-22 13:54:26 -0800131 out, err := validatePath(testCase.in...)
132 if err != nil {
133 reportPathError(ctx, err)
134 }
Colin Crossdc75ae72018-02-22 13:48:13 -0800135 check(t, "validatePath", p(testCase.in), out, ctx.errors, testCase.out, testCase.err)
136 })
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700137 }
138}
139
140func TestOptionalPath(t *testing.T) {
Colin Cross323dc602020-09-18 14:25:31 -0700141 t.Parallel()
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700142 var path OptionalPath
143 checkInvalidOptionalPath(t, path)
144
145 path = OptionalPathForPath(nil)
146 checkInvalidOptionalPath(t, path)
147}
148
149func checkInvalidOptionalPath(t *testing.T, path OptionalPath) {
Colin Crossdc75ae72018-02-22 13:48:13 -0800150 t.Helper()
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700151 if path.Valid() {
152 t.Errorf("Uninitialized OptionalPath should not be valid")
153 }
154 if path.String() != "" {
155 t.Errorf("Uninitialized OptionalPath String() should return \"\", not %q", path.String())
156 }
157 defer func() {
158 if r := recover(); r == nil {
159 t.Errorf("Expected a panic when calling Path() on an uninitialized OptionalPath")
160 }
161 }()
162 path.Path()
163}
164
165func check(t *testing.T, testType, testString string,
166 got interface{}, err []error,
167 expected interface{}, expectedErr []error) {
Colin Crossdc75ae72018-02-22 13:48:13 -0800168 t.Helper()
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700169
170 printedTestCase := false
171 e := func(s string, expected, got interface{}) {
Colin Crossdc75ae72018-02-22 13:48:13 -0800172 t.Helper()
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700173 if !printedTestCase {
174 t.Errorf("test case %s: %s", testType, testString)
175 printedTestCase = true
176 }
177 t.Errorf("incorrect %s", s)
178 t.Errorf(" expected: %s", p(expected))
179 t.Errorf(" got: %s", p(got))
180 }
181
182 if !reflect.DeepEqual(expectedErr, err) {
183 e("errors:", expectedErr, err)
184 }
185
186 if !reflect.DeepEqual(expected, got) {
187 e("output:", expected, got)
188 }
189}
190
191func p(in interface{}) string {
192 if v, ok := in.([]interface{}); ok {
193 s := make([]string, len(v))
194 for i := range v {
195 s[i] = fmt.Sprintf("%#v", v[i])
196 }
197 return "[" + strings.Join(s, ", ") + "]"
198 } else {
199 return fmt.Sprintf("%#v", in)
200 }
201}
Dan Willemsen00269f22017-07-06 16:59:48 -0700202
203type moduleInstallPathContextImpl struct {
Colin Cross0ea8ba82019-06-06 14:33:29 -0700204 baseModuleContext
Dan Willemsen00269f22017-07-06 16:59:48 -0700205
206 inData bool
Jaewoong Jung0949f312019-09-11 10:25:18 -0700207 inTestcases bool
Dan Willemsen00269f22017-07-06 16:59:48 -0700208 inSanitizerDir bool
Yifan Hong1b3348d2020-01-21 15:53:22 -0800209 inRamdisk bool
Jiyong Parkf9332f12018-02-01 00:54:12 +0900210 inRecovery bool
Colin Cross90ba5f42019-10-02 11:10:58 -0700211 inRoot bool
Colin Cross6e359402020-02-10 15:29:54 -0800212 forceOS *OsType
Jiyong Park87788b52020-09-01 12:37:45 +0900213 forceArch *ArchType
Dan Willemsen00269f22017-07-06 16:59:48 -0700214}
215
Colin Crossaabf6792017-11-29 00:27:14 -0800216func (m moduleInstallPathContextImpl) Config() Config {
Colin Cross0ea8ba82019-06-06 14:33:29 -0700217 return m.baseModuleContext.config
Dan Willemsen00269f22017-07-06 16:59:48 -0700218}
219
220func (moduleInstallPathContextImpl) AddNinjaFileDeps(deps ...string) {}
221
222func (m moduleInstallPathContextImpl) InstallInData() bool {
223 return m.inData
224}
225
Jaewoong Jung0949f312019-09-11 10:25:18 -0700226func (m moduleInstallPathContextImpl) InstallInTestcases() bool {
227 return m.inTestcases
228}
229
Dan Willemsen00269f22017-07-06 16:59:48 -0700230func (m moduleInstallPathContextImpl) InstallInSanitizerDir() bool {
231 return m.inSanitizerDir
232}
233
Yifan Hong1b3348d2020-01-21 15:53:22 -0800234func (m moduleInstallPathContextImpl) InstallInRamdisk() bool {
235 return m.inRamdisk
236}
237
Jiyong Parkf9332f12018-02-01 00:54:12 +0900238func (m moduleInstallPathContextImpl) InstallInRecovery() bool {
239 return m.inRecovery
240}
241
Colin Cross90ba5f42019-10-02 11:10:58 -0700242func (m moduleInstallPathContextImpl) InstallInRoot() bool {
243 return m.inRoot
244}
245
Colin Cross607d8582019-07-29 16:44:46 -0700246func (m moduleInstallPathContextImpl) InstallBypassMake() bool {
247 return false
248}
249
Jiyong Park87788b52020-09-01 12:37:45 +0900250func (m moduleInstallPathContextImpl) InstallForceOS() (*OsType, *ArchType) {
251 return m.forceOS, m.forceArch
Colin Cross6e359402020-02-10 15:29:54 -0800252}
253
Colin Cross98be1bb2019-12-13 20:41:13 -0800254func pathTestConfig(buildDir string) Config {
255 return TestConfig(buildDir, nil, "", nil)
256}
257
Dan Willemsen00269f22017-07-06 16:59:48 -0700258func TestPathForModuleInstall(t *testing.T) {
Colin Cross323dc602020-09-18 14:25:31 -0700259 t.Parallel()
Colin Cross98be1bb2019-12-13 20:41:13 -0800260 testConfig := pathTestConfig("")
Dan Willemsen00269f22017-07-06 16:59:48 -0700261
Jiyong Park87788b52020-09-01 12:37:45 +0900262 hostTarget := Target{Os: Linux, Arch: Arch{ArchType: X86}}
263 deviceTarget := Target{Os: Android, Arch: Arch{ArchType: Arm64}}
Dan Willemsen00269f22017-07-06 16:59:48 -0700264
265 testCases := []struct {
266 name string
267 ctx *moduleInstallPathContextImpl
268 in []string
269 out string
270 }{
271 {
272 name: "host binary",
273 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700274 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800275 os: hostTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700276 target: hostTarget,
277 },
278 },
279 in: []string{"bin", "my_test"},
280 out: "host/linux-x86/bin/my_test",
281 },
282
283 {
284 name: "system binary",
285 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700286 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800287 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700288 target: deviceTarget,
289 },
290 },
291 in: []string{"bin", "my_test"},
292 out: "target/product/test_device/system/bin/my_test",
293 },
294 {
295 name: "vendor binary",
296 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700297 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800298 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700299 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800300 earlyModuleContext: earlyModuleContext{
301 kind: socSpecificModule,
302 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700303 },
304 },
305 in: []string{"bin", "my_test"},
306 out: "target/product/test_device/vendor/bin/my_test",
307 },
Jiyong Park2db76922017-11-08 16:03:48 +0900308 {
309 name: "odm binary",
310 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700311 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800312 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900313 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800314 earlyModuleContext: earlyModuleContext{
315 kind: deviceSpecificModule,
316 },
Jiyong Park2db76922017-11-08 16:03:48 +0900317 },
318 },
319 in: []string{"bin", "my_test"},
320 out: "target/product/test_device/odm/bin/my_test",
321 },
322 {
Jaekyun Seok5cfbfbb2018-01-10 19:00:15 +0900323 name: "product binary",
Jiyong Park2db76922017-11-08 16:03:48 +0900324 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700325 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800326 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900327 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800328 earlyModuleContext: earlyModuleContext{
329 kind: productSpecificModule,
330 },
Jiyong Park2db76922017-11-08 16:03:48 +0900331 },
332 },
333 in: []string{"bin", "my_test"},
Jaekyun Seok5cfbfbb2018-01-10 19:00:15 +0900334 out: "target/product/test_device/product/bin/my_test",
Jiyong Park2db76922017-11-08 16:03:48 +0900335 },
Dario Frenifd05a742018-05-29 13:28:54 +0100336 {
Justin Yund5f6c822019-06-25 16:47:17 +0900337 name: "system_ext binary",
Dario Frenifd05a742018-05-29 13:28:54 +0100338 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700339 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800340 os: deviceTarget.Os,
Dario Frenifd05a742018-05-29 13:28:54 +0100341 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800342 earlyModuleContext: earlyModuleContext{
343 kind: systemExtSpecificModule,
344 },
Dario Frenifd05a742018-05-29 13:28:54 +0100345 },
346 },
347 in: []string{"bin", "my_test"},
Justin Yund5f6c822019-06-25 16:47:17 +0900348 out: "target/product/test_device/system_ext/bin/my_test",
Dario Frenifd05a742018-05-29 13:28:54 +0100349 },
Colin Cross90ba5f42019-10-02 11:10:58 -0700350 {
351 name: "root binary",
352 ctx: &moduleInstallPathContextImpl{
353 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800354 os: deviceTarget.Os,
Colin Cross90ba5f42019-10-02 11:10:58 -0700355 target: deviceTarget,
356 },
357 inRoot: true,
358 },
359 in: []string{"my_test"},
360 out: "target/product/test_device/root/my_test",
361 },
362 {
363 name: "recovery binary",
364 ctx: &moduleInstallPathContextImpl{
365 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800366 os: deviceTarget.Os,
Colin Cross90ba5f42019-10-02 11:10:58 -0700367 target: deviceTarget,
368 },
369 inRecovery: true,
370 },
371 in: []string{"bin/my_test"},
372 out: "target/product/test_device/recovery/root/system/bin/my_test",
373 },
374 {
375 name: "recovery root binary",
376 ctx: &moduleInstallPathContextImpl{
377 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800378 os: deviceTarget.Os,
Colin Cross90ba5f42019-10-02 11:10:58 -0700379 target: deviceTarget,
380 },
381 inRecovery: true,
382 inRoot: true,
383 },
384 in: []string{"my_test"},
385 out: "target/product/test_device/recovery/root/my_test",
386 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700387
388 {
389 name: "system native test binary",
390 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700391 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800392 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700393 target: deviceTarget,
394 },
395 inData: true,
396 },
397 in: []string{"nativetest", "my_test"},
398 out: "target/product/test_device/data/nativetest/my_test",
399 },
400 {
401 name: "vendor native test binary",
402 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700403 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800404 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700405 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800406 earlyModuleContext: earlyModuleContext{
407 kind: socSpecificModule,
408 },
Jiyong Park2db76922017-11-08 16:03:48 +0900409 },
410 inData: true,
411 },
412 in: []string{"nativetest", "my_test"},
413 out: "target/product/test_device/data/nativetest/my_test",
414 },
415 {
416 name: "odm native test binary",
417 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700418 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800419 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900420 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800421 earlyModuleContext: earlyModuleContext{
422 kind: deviceSpecificModule,
423 },
Jiyong Park2db76922017-11-08 16:03:48 +0900424 },
425 inData: true,
426 },
427 in: []string{"nativetest", "my_test"},
428 out: "target/product/test_device/data/nativetest/my_test",
429 },
430 {
Jaekyun Seok5cfbfbb2018-01-10 19:00:15 +0900431 name: "product native test binary",
Jiyong Park2db76922017-11-08 16:03:48 +0900432 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700433 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800434 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900435 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800436 earlyModuleContext: earlyModuleContext{
437 kind: productSpecificModule,
438 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700439 },
440 inData: true,
441 },
442 in: []string{"nativetest", "my_test"},
443 out: "target/product/test_device/data/nativetest/my_test",
444 },
445
446 {
Justin Yund5f6c822019-06-25 16:47:17 +0900447 name: "system_ext native test binary",
Dario Frenifd05a742018-05-29 13:28:54 +0100448 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700449 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800450 os: deviceTarget.Os,
Dario Frenifd05a742018-05-29 13:28:54 +0100451 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800452 earlyModuleContext: earlyModuleContext{
453 kind: systemExtSpecificModule,
454 },
Dario Frenifd05a742018-05-29 13:28:54 +0100455 },
456 inData: true,
457 },
458 in: []string{"nativetest", "my_test"},
459 out: "target/product/test_device/data/nativetest/my_test",
460 },
461
462 {
Dan Willemsen00269f22017-07-06 16:59:48 -0700463 name: "sanitized system binary",
464 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700465 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800466 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700467 target: deviceTarget,
468 },
469 inSanitizerDir: true,
470 },
471 in: []string{"bin", "my_test"},
472 out: "target/product/test_device/data/asan/system/bin/my_test",
473 },
474 {
475 name: "sanitized vendor binary",
476 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700477 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800478 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700479 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800480 earlyModuleContext: earlyModuleContext{
481 kind: socSpecificModule,
482 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700483 },
484 inSanitizerDir: true,
485 },
486 in: []string{"bin", "my_test"},
487 out: "target/product/test_device/data/asan/vendor/bin/my_test",
488 },
Jiyong Park2db76922017-11-08 16:03:48 +0900489 {
490 name: "sanitized odm binary",
491 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700492 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800493 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900494 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800495 earlyModuleContext: earlyModuleContext{
496 kind: deviceSpecificModule,
497 },
Jiyong Park2db76922017-11-08 16:03:48 +0900498 },
499 inSanitizerDir: true,
500 },
501 in: []string{"bin", "my_test"},
502 out: "target/product/test_device/data/asan/odm/bin/my_test",
503 },
504 {
Jaekyun Seok5cfbfbb2018-01-10 19:00:15 +0900505 name: "sanitized product binary",
Jiyong Park2db76922017-11-08 16:03:48 +0900506 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700507 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800508 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900509 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800510 earlyModuleContext: earlyModuleContext{
511 kind: productSpecificModule,
512 },
Jiyong Park2db76922017-11-08 16:03:48 +0900513 },
514 inSanitizerDir: true,
515 },
516 in: []string{"bin", "my_test"},
Jaekyun Seok5cfbfbb2018-01-10 19:00:15 +0900517 out: "target/product/test_device/data/asan/product/bin/my_test",
Jiyong Park2db76922017-11-08 16:03:48 +0900518 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700519
520 {
Justin Yund5f6c822019-06-25 16:47:17 +0900521 name: "sanitized system_ext binary",
Dario Frenifd05a742018-05-29 13:28:54 +0100522 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700523 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800524 os: deviceTarget.Os,
Dario Frenifd05a742018-05-29 13:28:54 +0100525 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800526 earlyModuleContext: earlyModuleContext{
527 kind: systemExtSpecificModule,
528 },
Dario Frenifd05a742018-05-29 13:28:54 +0100529 },
530 inSanitizerDir: true,
531 },
532 in: []string{"bin", "my_test"},
Justin Yund5f6c822019-06-25 16:47:17 +0900533 out: "target/product/test_device/data/asan/system_ext/bin/my_test",
Dario Frenifd05a742018-05-29 13:28:54 +0100534 },
535
536 {
Dan Willemsen00269f22017-07-06 16:59:48 -0700537 name: "sanitized system native test binary",
538 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700539 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800540 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700541 target: deviceTarget,
542 },
543 inData: true,
544 inSanitizerDir: true,
545 },
546 in: []string{"nativetest", "my_test"},
547 out: "target/product/test_device/data/asan/data/nativetest/my_test",
548 },
549 {
550 name: "sanitized vendor native test binary",
551 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700552 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800553 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700554 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800555 earlyModuleContext: earlyModuleContext{
556 kind: socSpecificModule,
557 },
Jiyong Park2db76922017-11-08 16:03:48 +0900558 },
559 inData: true,
560 inSanitizerDir: true,
561 },
562 in: []string{"nativetest", "my_test"},
563 out: "target/product/test_device/data/asan/data/nativetest/my_test",
564 },
565 {
566 name: "sanitized odm native test binary",
567 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700568 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800569 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900570 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800571 earlyModuleContext: earlyModuleContext{
572 kind: deviceSpecificModule,
573 },
Jiyong Park2db76922017-11-08 16:03:48 +0900574 },
575 inData: true,
576 inSanitizerDir: true,
577 },
578 in: []string{"nativetest", "my_test"},
579 out: "target/product/test_device/data/asan/data/nativetest/my_test",
580 },
581 {
Jaekyun Seok5cfbfbb2018-01-10 19:00:15 +0900582 name: "sanitized product native test binary",
Jiyong Park2db76922017-11-08 16:03:48 +0900583 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700584 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800585 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900586 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800587 earlyModuleContext: earlyModuleContext{
588 kind: productSpecificModule,
589 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700590 },
591 inData: true,
592 inSanitizerDir: true,
593 },
594 in: []string{"nativetest", "my_test"},
595 out: "target/product/test_device/data/asan/data/nativetest/my_test",
596 },
Dario Frenifd05a742018-05-29 13:28:54 +0100597 {
Justin Yund5f6c822019-06-25 16:47:17 +0900598 name: "sanitized system_ext native test binary",
Dario Frenifd05a742018-05-29 13:28:54 +0100599 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700600 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800601 os: deviceTarget.Os,
Dario Frenifd05a742018-05-29 13:28:54 +0100602 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800603 earlyModuleContext: earlyModuleContext{
604 kind: systemExtSpecificModule,
605 },
Dario Frenifd05a742018-05-29 13:28:54 +0100606 },
607 inData: true,
608 inSanitizerDir: true,
609 },
610 in: []string{"nativetest", "my_test"},
611 out: "target/product/test_device/data/asan/data/nativetest/my_test",
Colin Cross6e359402020-02-10 15:29:54 -0800612 }, {
613 name: "device testcases",
614 ctx: &moduleInstallPathContextImpl{
615 baseModuleContext: baseModuleContext{
616 os: deviceTarget.Os,
617 target: deviceTarget,
618 },
619 inTestcases: true,
620 },
621 in: []string{"my_test", "my_test_bin"},
622 out: "target/product/test_device/testcases/my_test/my_test_bin",
623 }, {
624 name: "host testcases",
625 ctx: &moduleInstallPathContextImpl{
626 baseModuleContext: baseModuleContext{
627 os: hostTarget.Os,
628 target: hostTarget,
629 },
630 inTestcases: true,
631 },
632 in: []string{"my_test", "my_test_bin"},
633 out: "host/linux-x86/testcases/my_test/my_test_bin",
634 }, {
635 name: "forced host testcases",
636 ctx: &moduleInstallPathContextImpl{
637 baseModuleContext: baseModuleContext{
638 os: deviceTarget.Os,
639 target: deviceTarget,
640 },
641 inTestcases: true,
642 forceOS: &Linux,
Jiyong Park87788b52020-09-01 12:37:45 +0900643 forceArch: &X86,
Colin Cross6e359402020-02-10 15:29:54 -0800644 },
645 in: []string{"my_test", "my_test_bin"},
646 out: "host/linux-x86/testcases/my_test/my_test_bin",
Dario Frenifd05a742018-05-29 13:28:54 +0100647 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700648 }
649
650 for _, tc := range testCases {
651 t.Run(tc.name, func(t *testing.T) {
Colin Cross0ea8ba82019-06-06 14:33:29 -0700652 tc.ctx.baseModuleContext.config = testConfig
Dan Willemsen00269f22017-07-06 16:59:48 -0700653 output := PathForModuleInstall(tc.ctx, tc.in...)
654 if output.basePath.path != tc.out {
655 t.Errorf("unexpected path:\n got: %q\nwant: %q\n",
656 output.basePath.path,
657 tc.out)
658 }
659 })
660 }
661}
Colin Cross5e6cfbe2017-11-03 15:20:35 -0700662
663func TestDirectorySortedPaths(t *testing.T) {
Colin Cross323dc602020-09-18 14:25:31 -0700664 t.Parallel()
Colin Cross98be1bb2019-12-13 20:41:13 -0800665 config := TestConfig("out", nil, "", map[string][]byte{
666 "Android.bp": nil,
667 "a.txt": nil,
668 "a/txt": nil,
669 "a/b/c": nil,
670 "a/b/d": nil,
671 "b": nil,
672 "b/b.txt": nil,
673 "a/a.txt": nil,
Colin Cross07e51612019-03-05 12:46:40 -0800674 })
675
Colin Cross98be1bb2019-12-13 20:41:13 -0800676 ctx := PathContextForTesting(config)
677
Colin Cross5e6cfbe2017-11-03 15:20:35 -0700678 makePaths := func() Paths {
679 return Paths{
Colin Cross07e51612019-03-05 12:46:40 -0800680 PathForSource(ctx, "a.txt"),
681 PathForSource(ctx, "a/txt"),
682 PathForSource(ctx, "a/b/c"),
683 PathForSource(ctx, "a/b/d"),
684 PathForSource(ctx, "b"),
685 PathForSource(ctx, "b/b.txt"),
686 PathForSource(ctx, "a/a.txt"),
Colin Cross5e6cfbe2017-11-03 15:20:35 -0700687 }
688 }
689
690 expected := []string{
691 "a.txt",
692 "a/a.txt",
693 "a/b/c",
694 "a/b/d",
695 "a/txt",
696 "b",
697 "b/b.txt",
698 }
699
700 paths := makePaths()
Colin Crossa140bb02018-04-17 10:52:26 -0700701 reversePaths := ReversePaths(paths)
Colin Cross5e6cfbe2017-11-03 15:20:35 -0700702
703 sortedPaths := PathsToDirectorySortedPaths(paths)
704 reverseSortedPaths := PathsToDirectorySortedPaths(reversePaths)
705
706 if !reflect.DeepEqual(Paths(sortedPaths).Strings(), expected) {
707 t.Fatalf("sorted paths:\n %#v\n != \n %#v", paths.Strings(), expected)
708 }
709
710 if !reflect.DeepEqual(Paths(reverseSortedPaths).Strings(), expected) {
711 t.Fatalf("sorted reversed paths:\n %#v\n !=\n %#v", reversePaths.Strings(), expected)
712 }
713
714 expectedA := []string{
715 "a/a.txt",
716 "a/b/c",
717 "a/b/d",
718 "a/txt",
719 }
720
721 inA := sortedPaths.PathsInDirectory("a")
722 if !reflect.DeepEqual(inA.Strings(), expectedA) {
723 t.Errorf("FilesInDirectory(a):\n %#v\n != \n %#v", inA.Strings(), expectedA)
724 }
725
726 expectedA_B := []string{
727 "a/b/c",
728 "a/b/d",
729 }
730
731 inA_B := sortedPaths.PathsInDirectory("a/b")
732 if !reflect.DeepEqual(inA_B.Strings(), expectedA_B) {
733 t.Errorf("FilesInDirectory(a/b):\n %#v\n != \n %#v", inA_B.Strings(), expectedA_B)
734 }
735
736 expectedB := []string{
737 "b/b.txt",
738 }
739
740 inB := sortedPaths.PathsInDirectory("b")
741 if !reflect.DeepEqual(inB.Strings(), expectedB) {
742 t.Errorf("FilesInDirectory(b):\n %#v\n != \n %#v", inA.Strings(), expectedA)
743 }
744}
Colin Cross43f08db2018-11-12 10:13:39 -0800745
746func TestMaybeRel(t *testing.T) {
Colin Cross323dc602020-09-18 14:25:31 -0700747 t.Parallel()
Colin Cross43f08db2018-11-12 10:13:39 -0800748 testCases := []struct {
749 name string
750 base string
751 target string
752 out string
753 isRel bool
754 }{
755 {
756 name: "normal",
757 base: "a/b/c",
758 target: "a/b/c/d",
759 out: "d",
760 isRel: true,
761 },
762 {
763 name: "parent",
764 base: "a/b/c/d",
765 target: "a/b/c",
766 isRel: false,
767 },
768 {
769 name: "not relative",
770 base: "a/b",
771 target: "c/d",
772 isRel: false,
773 },
774 {
775 name: "abs1",
776 base: "/a",
777 target: "a",
778 isRel: false,
779 },
780 {
781 name: "abs2",
782 base: "a",
783 target: "/a",
784 isRel: false,
785 },
786 }
787
788 for _, testCase := range testCases {
789 t.Run(testCase.name, func(t *testing.T) {
790 ctx := &configErrorWrapper{}
791 out, isRel := MaybeRel(ctx, testCase.base, testCase.target)
792 if len(ctx.errors) > 0 {
793 t.Errorf("MaybeRel(..., %s, %s) reported unexpected errors %v",
794 testCase.base, testCase.target, ctx.errors)
795 }
796 if isRel != testCase.isRel || out != testCase.out {
797 t.Errorf("MaybeRel(..., %s, %s) want %v, %v got %v, %v",
798 testCase.base, testCase.target, testCase.out, testCase.isRel, out, isRel)
799 }
800 })
801 }
802}
Colin Cross7b3dcc32019-01-24 13:14:39 -0800803
804func TestPathForSource(t *testing.T) {
Colin Cross323dc602020-09-18 14:25:31 -0700805 t.Parallel()
Colin Cross7b3dcc32019-01-24 13:14:39 -0800806 testCases := []struct {
807 name string
808 buildDir string
809 src string
810 err string
811 }{
812 {
813 name: "normal",
814 buildDir: "out",
815 src: "a/b/c",
816 },
817 {
818 name: "abs",
819 buildDir: "out",
820 src: "/a/b/c",
821 err: "is outside directory",
822 },
823 {
824 name: "in out dir",
825 buildDir: "out",
826 src: "out/a/b/c",
827 err: "is in output",
828 },
829 }
830
831 funcs := []struct {
832 name string
833 f func(ctx PathContext, pathComponents ...string) (SourcePath, error)
834 }{
835 {"pathForSource", pathForSource},
836 {"safePathForSource", safePathForSource},
837 }
838
839 for _, f := range funcs {
840 t.Run(f.name, func(t *testing.T) {
841 for _, test := range testCases {
842 t.Run(test.name, func(t *testing.T) {
Colin Cross98be1bb2019-12-13 20:41:13 -0800843 testConfig := pathTestConfig(test.buildDir)
Colin Cross7b3dcc32019-01-24 13:14:39 -0800844 ctx := &configErrorWrapper{config: testConfig}
845 _, err := f.f(ctx, test.src)
846 if len(ctx.errors) > 0 {
847 t.Fatalf("unexpected errors %v", ctx.errors)
848 }
849 if err != nil {
850 if test.err == "" {
851 t.Fatalf("unexpected error %q", err.Error())
852 } else if !strings.Contains(err.Error(), test.err) {
853 t.Fatalf("incorrect error, want substring %q got %q", test.err, err.Error())
854 }
855 } else {
856 if test.err != "" {
857 t.Fatalf("missing error %q", test.err)
858 }
859 }
860 })
861 }
862 })
863 }
864}
Colin Cross8854a5a2019-02-11 14:14:16 -0800865
Colin Cross8a497952019-03-05 22:25:09 -0800866type pathForModuleSrcTestModule struct {
Colin Cross937664a2019-03-06 10:17:32 -0800867 ModuleBase
868 props struct {
869 Srcs []string `android:"path"`
870 Exclude_srcs []string `android:"path"`
Colin Cross8a497952019-03-05 22:25:09 -0800871
872 Src *string `android:"path"`
Colin Crossba71a3f2019-03-18 12:12:48 -0700873
874 Module_handles_missing_deps bool
Colin Cross937664a2019-03-06 10:17:32 -0800875 }
876
Colin Cross8a497952019-03-05 22:25:09 -0800877 src string
878 rel string
879
880 srcs []string
Colin Cross937664a2019-03-06 10:17:32 -0800881 rels []string
Colin Cross8a497952019-03-05 22:25:09 -0800882
883 missingDeps []string
Colin Cross937664a2019-03-06 10:17:32 -0800884}
885
Colin Cross8a497952019-03-05 22:25:09 -0800886func pathForModuleSrcTestModuleFactory() Module {
887 module := &pathForModuleSrcTestModule{}
Colin Cross937664a2019-03-06 10:17:32 -0800888 module.AddProperties(&module.props)
889 InitAndroidModule(module)
890 return module
891}
892
Colin Cross8a497952019-03-05 22:25:09 -0800893func (p *pathForModuleSrcTestModule) GenerateAndroidBuildActions(ctx ModuleContext) {
Colin Crossba71a3f2019-03-18 12:12:48 -0700894 var srcs Paths
895 if p.props.Module_handles_missing_deps {
896 srcs, p.missingDeps = PathsAndMissingDepsForModuleSrcExcludes(ctx, p.props.Srcs, p.props.Exclude_srcs)
897 } else {
898 srcs = PathsForModuleSrcExcludes(ctx, p.props.Srcs, p.props.Exclude_srcs)
899 }
Colin Cross8a497952019-03-05 22:25:09 -0800900 p.srcs = srcs.Strings()
Colin Cross937664a2019-03-06 10:17:32 -0800901
Colin Cross8a497952019-03-05 22:25:09 -0800902 for _, src := range srcs {
Colin Cross937664a2019-03-06 10:17:32 -0800903 p.rels = append(p.rels, src.Rel())
904 }
Colin Cross8a497952019-03-05 22:25:09 -0800905
906 if p.props.Src != nil {
907 src := PathForModuleSrc(ctx, *p.props.Src)
908 if src != nil {
909 p.src = src.String()
910 p.rel = src.Rel()
911 }
912 }
913
Colin Crossba71a3f2019-03-18 12:12:48 -0700914 if !p.props.Module_handles_missing_deps {
915 p.missingDeps = ctx.GetMissingDependencies()
916 }
Colin Cross6c4f21f2019-06-06 15:41:36 -0700917
918 ctx.Build(pctx, BuildParams{
919 Rule: Touch,
920 Output: PathForModuleOut(ctx, "output"),
921 })
Colin Cross8a497952019-03-05 22:25:09 -0800922}
923
Colin Cross41955e82019-05-29 14:40:35 -0700924type pathForModuleSrcOutputFileProviderModule struct {
925 ModuleBase
926 props struct {
927 Outs []string
928 Tagged []string
929 }
930
931 outs Paths
932 tagged Paths
933}
934
935func pathForModuleSrcOutputFileProviderModuleFactory() Module {
936 module := &pathForModuleSrcOutputFileProviderModule{}
937 module.AddProperties(&module.props)
938 InitAndroidModule(module)
939 return module
940}
941
942func (p *pathForModuleSrcOutputFileProviderModule) GenerateAndroidBuildActions(ctx ModuleContext) {
943 for _, out := range p.props.Outs {
944 p.outs = append(p.outs, PathForModuleOut(ctx, out))
945 }
946
947 for _, tagged := range p.props.Tagged {
948 p.tagged = append(p.tagged, PathForModuleOut(ctx, tagged))
949 }
950}
951
952func (p *pathForModuleSrcOutputFileProviderModule) OutputFiles(tag string) (Paths, error) {
953 switch tag {
954 case "":
955 return p.outs, nil
956 case ".tagged":
957 return p.tagged, nil
958 default:
959 return nil, fmt.Errorf("unsupported tag %q", tag)
960 }
961}
962
Colin Cross8a497952019-03-05 22:25:09 -0800963type pathForModuleSrcTestCase struct {
964 name string
965 bp string
966 srcs []string
967 rels []string
968 src string
969 rel string
970}
971
972func testPathForModuleSrc(t *testing.T, buildDir string, tests []pathForModuleSrcTestCase) {
973 for _, test := range tests {
974 t.Run(test.name, func(t *testing.T) {
Colin Cross8a497952019-03-05 22:25:09 -0800975 ctx := NewTestContext()
976
Colin Cross4b49b762019-11-22 15:25:03 -0800977 ctx.RegisterModuleType("test", pathForModuleSrcTestModuleFactory)
978 ctx.RegisterModuleType("output_file_provider", pathForModuleSrcOutputFileProviderModuleFactory)
979 ctx.RegisterModuleType("filegroup", FileGroupFactory)
Colin Cross8a497952019-03-05 22:25:09 -0800980
981 fgBp := `
982 filegroup {
983 name: "a",
984 srcs: ["src/a"],
985 }
986 `
987
Colin Cross41955e82019-05-29 14:40:35 -0700988 ofpBp := `
989 output_file_provider {
990 name: "b",
991 outs: ["gen/b"],
992 tagged: ["gen/c"],
993 }
994 `
995
Colin Cross8a497952019-03-05 22:25:09 -0800996 mockFS := map[string][]byte{
997 "fg/Android.bp": []byte(fgBp),
998 "foo/Android.bp": []byte(test.bp),
Colin Cross41955e82019-05-29 14:40:35 -0700999 "ofp/Android.bp": []byte(ofpBp),
Colin Cross8a497952019-03-05 22:25:09 -08001000 "fg/src/a": nil,
1001 "foo/src/b": nil,
1002 "foo/src/c": nil,
1003 "foo/src/d": nil,
1004 "foo/src/e/e": nil,
1005 "foo/src_special/$": nil,
1006 }
1007
Colin Cross98be1bb2019-12-13 20:41:13 -08001008 config := TestConfig(buildDir, nil, "", mockFS)
Colin Cross8a497952019-03-05 22:25:09 -08001009
Colin Cross98be1bb2019-12-13 20:41:13 -08001010 ctx.Register(config)
Colin Cross41955e82019-05-29 14:40:35 -07001011 _, errs := ctx.ParseFileList(".", []string{"fg/Android.bp", "foo/Android.bp", "ofp/Android.bp"})
Colin Cross8a497952019-03-05 22:25:09 -08001012 FailIfErrored(t, errs)
1013 _, errs = ctx.PrepareBuildActions(config)
1014 FailIfErrored(t, errs)
1015
1016 m := ctx.ModuleForTests("foo", "").Module().(*pathForModuleSrcTestModule)
1017
1018 if g, w := m.srcs, test.srcs; !reflect.DeepEqual(g, w) {
1019 t.Errorf("want srcs %q, got %q", w, g)
1020 }
1021
1022 if g, w := m.rels, test.rels; !reflect.DeepEqual(g, w) {
1023 t.Errorf("want rels %q, got %q", w, g)
1024 }
1025
1026 if g, w := m.src, test.src; g != w {
1027 t.Errorf("want src %q, got %q", w, g)
1028 }
1029
1030 if g, w := m.rel, test.rel; g != w {
1031 t.Errorf("want rel %q, got %q", w, g)
1032 }
1033 })
1034 }
Colin Cross937664a2019-03-06 10:17:32 -08001035}
1036
Colin Cross8a497952019-03-05 22:25:09 -08001037func TestPathsForModuleSrc(t *testing.T) {
Colin Cross323dc602020-09-18 14:25:31 -07001038 t.Parallel()
Colin Cross8a497952019-03-05 22:25:09 -08001039 tests := []pathForModuleSrcTestCase{
Colin Cross937664a2019-03-06 10:17:32 -08001040 {
1041 name: "path",
1042 bp: `
1043 test {
1044 name: "foo",
1045 srcs: ["src/b"],
1046 }`,
1047 srcs: []string{"foo/src/b"},
1048 rels: []string{"src/b"},
1049 },
1050 {
1051 name: "glob",
1052 bp: `
1053 test {
1054 name: "foo",
1055 srcs: [
1056 "src/*",
1057 "src/e/*",
1058 ],
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: "recursive glob",
1065 bp: `
1066 test {
1067 name: "foo",
1068 srcs: ["src/**/*"],
1069 }`,
1070 srcs: []string{"foo/src/b", "foo/src/c", "foo/src/d", "foo/src/e/e"},
1071 rels: []string{"src/b", "src/c", "src/d", "src/e/e"},
1072 },
1073 {
1074 name: "filegroup",
1075 bp: `
1076 test {
1077 name: "foo",
1078 srcs: [":a"],
1079 }`,
1080 srcs: []string{"fg/src/a"},
1081 rels: []string{"src/a"},
1082 },
1083 {
Colin Cross41955e82019-05-29 14:40:35 -07001084 name: "output file provider",
1085 bp: `
1086 test {
1087 name: "foo",
1088 srcs: [":b"],
1089 }`,
1090 srcs: []string{buildDir + "/.intermediates/ofp/b/gen/b"},
1091 rels: []string{"gen/b"},
1092 },
1093 {
1094 name: "output file provider tagged",
1095 bp: `
1096 test {
1097 name: "foo",
1098 srcs: [":b{.tagged}"],
1099 }`,
1100 srcs: []string{buildDir + "/.intermediates/ofp/b/gen/c"},
1101 rels: []string{"gen/c"},
1102 },
1103 {
Jooyung Han7607dd32020-07-05 10:23:14 +09001104 name: "output file provider with exclude",
1105 bp: `
1106 test {
1107 name: "foo",
1108 srcs: [":b", ":c"],
1109 exclude_srcs: [":c"]
1110 }
1111 output_file_provider {
1112 name: "c",
1113 outs: ["gen/c"],
1114 }`,
1115 srcs: []string{buildDir + "/.intermediates/ofp/b/gen/b"},
1116 rels: []string{"gen/b"},
1117 },
1118 {
Colin Cross937664a2019-03-06 10:17:32 -08001119 name: "special characters glob",
1120 bp: `
1121 test {
1122 name: "foo",
1123 srcs: ["src_special/*"],
1124 }`,
1125 srcs: []string{"foo/src_special/$"},
1126 rels: []string{"src_special/$"},
1127 },
1128 }
1129
Colin Cross41955e82019-05-29 14:40:35 -07001130 testPathForModuleSrc(t, buildDir, tests)
1131}
1132
1133func TestPathForModuleSrc(t *testing.T) {
Colin Cross323dc602020-09-18 14:25:31 -07001134 t.Parallel()
Colin Cross8a497952019-03-05 22:25:09 -08001135 tests := []pathForModuleSrcTestCase{
1136 {
1137 name: "path",
1138 bp: `
1139 test {
1140 name: "foo",
1141 src: "src/b",
1142 }`,
1143 src: "foo/src/b",
1144 rel: "src/b",
1145 },
1146 {
1147 name: "glob",
1148 bp: `
1149 test {
1150 name: "foo",
1151 src: "src/e/*",
1152 }`,
1153 src: "foo/src/e/e",
1154 rel: "src/e/e",
1155 },
1156 {
1157 name: "filegroup",
1158 bp: `
1159 test {
1160 name: "foo",
1161 src: ":a",
1162 }`,
1163 src: "fg/src/a",
1164 rel: "src/a",
1165 },
1166 {
Colin Cross41955e82019-05-29 14:40:35 -07001167 name: "output file provider",
1168 bp: `
1169 test {
1170 name: "foo",
1171 src: ":b",
1172 }`,
1173 src: buildDir + "/.intermediates/ofp/b/gen/b",
1174 rel: "gen/b",
1175 },
1176 {
1177 name: "output file provider tagged",
1178 bp: `
1179 test {
1180 name: "foo",
1181 src: ":b{.tagged}",
1182 }`,
1183 src: buildDir + "/.intermediates/ofp/b/gen/c",
1184 rel: "gen/c",
1185 },
1186 {
Colin Cross8a497952019-03-05 22:25:09 -08001187 name: "special characters glob",
1188 bp: `
1189 test {
1190 name: "foo",
1191 src: "src_special/*",
1192 }`,
1193 src: "foo/src_special/$",
1194 rel: "src_special/$",
1195 },
1196 }
1197
Colin Cross8a497952019-03-05 22:25:09 -08001198 testPathForModuleSrc(t, buildDir, tests)
1199}
Colin Cross937664a2019-03-06 10:17:32 -08001200
Colin Cross8a497952019-03-05 22:25:09 -08001201func TestPathsForModuleSrc_AllowMissingDependencies(t *testing.T) {
Colin Cross323dc602020-09-18 14:25:31 -07001202 t.Parallel()
Colin Cross8a497952019-03-05 22:25:09 -08001203 bp := `
1204 test {
1205 name: "foo",
1206 srcs: [":a"],
1207 exclude_srcs: [":b"],
1208 src: ":c",
1209 }
Colin Crossba71a3f2019-03-18 12:12:48 -07001210
1211 test {
1212 name: "bar",
1213 srcs: [":d"],
1214 exclude_srcs: [":e"],
1215 module_handles_missing_deps: true,
1216 }
Colin Cross8a497952019-03-05 22:25:09 -08001217 `
1218
Colin Cross98be1bb2019-12-13 20:41:13 -08001219 config := TestConfig(buildDir, nil, bp, nil)
1220 config.TestProductVariables.Allow_missing_dependencies = proptools.BoolPtr(true)
Colin Cross8a497952019-03-05 22:25:09 -08001221
Colin Cross98be1bb2019-12-13 20:41:13 -08001222 ctx := NewTestContext()
1223 ctx.SetAllowMissingDependencies(true)
Colin Cross8a497952019-03-05 22:25:09 -08001224
Colin Cross98be1bb2019-12-13 20:41:13 -08001225 ctx.RegisterModuleType("test", pathForModuleSrcTestModuleFactory)
1226
1227 ctx.Register(config)
1228
Colin Cross8a497952019-03-05 22:25:09 -08001229 _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
1230 FailIfErrored(t, errs)
1231 _, errs = ctx.PrepareBuildActions(config)
1232 FailIfErrored(t, errs)
1233
1234 foo := ctx.ModuleForTests("foo", "").Module().(*pathForModuleSrcTestModule)
1235
1236 if g, w := foo.missingDeps, []string{"a", "b", "c"}; !reflect.DeepEqual(g, w) {
Colin Crossba71a3f2019-03-18 12:12:48 -07001237 t.Errorf("want foo missing deps %q, got %q", w, g)
Colin Cross8a497952019-03-05 22:25:09 -08001238 }
1239
1240 if g, w := foo.srcs, []string{}; !reflect.DeepEqual(g, w) {
Colin Crossba71a3f2019-03-18 12:12:48 -07001241 t.Errorf("want foo srcs %q, got %q", w, g)
Colin Cross8a497952019-03-05 22:25:09 -08001242 }
1243
1244 if g, w := foo.src, ""; g != w {
Colin Crossba71a3f2019-03-18 12:12:48 -07001245 t.Errorf("want foo src %q, got %q", w, g)
Colin Cross8a497952019-03-05 22:25:09 -08001246 }
1247
Colin Crossba71a3f2019-03-18 12:12:48 -07001248 bar := ctx.ModuleForTests("bar", "").Module().(*pathForModuleSrcTestModule)
1249
1250 if g, w := bar.missingDeps, []string{"d", "e"}; !reflect.DeepEqual(g, w) {
1251 t.Errorf("want bar missing deps %q, got %q", w, g)
1252 }
1253
1254 if g, w := bar.srcs, []string{}; !reflect.DeepEqual(g, w) {
1255 t.Errorf("want bar srcs %q, got %q", w, g)
1256 }
Colin Cross937664a2019-03-06 10:17:32 -08001257}
1258
Colin Cross8854a5a2019-02-11 14:14:16 -08001259func ExampleOutputPath_ReplaceExtension() {
1260 ctx := &configErrorWrapper{
Colin Cross98be1bb2019-12-13 20:41:13 -08001261 config: TestConfig("out", nil, "", nil),
Colin Cross8854a5a2019-02-11 14:14:16 -08001262 }
Colin Cross2cdd5df2019-02-25 10:25:24 -08001263 p := PathForOutput(ctx, "system/framework").Join(ctx, "boot.art")
Colin Cross8854a5a2019-02-11 14:14:16 -08001264 p2 := p.ReplaceExtension(ctx, "oat")
1265 fmt.Println(p, p2)
Colin Cross2cdd5df2019-02-25 10:25:24 -08001266 fmt.Println(p.Rel(), p2.Rel())
Colin Cross8854a5a2019-02-11 14:14:16 -08001267
1268 // Output:
1269 // out/system/framework/boot.art out/system/framework/boot.oat
Colin Cross2cdd5df2019-02-25 10:25:24 -08001270 // boot.art boot.oat
Colin Cross8854a5a2019-02-11 14:14:16 -08001271}
Colin Cross40e33732019-02-15 11:08:35 -08001272
Colin Cross41b46762020-10-09 19:26:32 -07001273func ExampleOutputPath_InSameDir() {
Colin Cross40e33732019-02-15 11:08:35 -08001274 ctx := &configErrorWrapper{
Colin Cross98be1bb2019-12-13 20:41:13 -08001275 config: TestConfig("out", nil, "", nil),
Colin Cross40e33732019-02-15 11:08:35 -08001276 }
Colin Cross2cdd5df2019-02-25 10:25:24 -08001277 p := PathForOutput(ctx, "system/framework").Join(ctx, "boot.art")
Colin Cross40e33732019-02-15 11:08:35 -08001278 p2 := p.InSameDir(ctx, "oat", "arm", "boot.vdex")
1279 fmt.Println(p, p2)
Colin Cross2cdd5df2019-02-25 10:25:24 -08001280 fmt.Println(p.Rel(), p2.Rel())
Colin Cross40e33732019-02-15 11:08:35 -08001281
1282 // Output:
1283 // out/system/framework/boot.art out/system/framework/oat/arm/boot.vdex
Colin Cross2cdd5df2019-02-25 10:25:24 -08001284 // boot.art oat/arm/boot.vdex
Colin Cross40e33732019-02-15 11:08:35 -08001285}
Colin Cross27027c72020-02-28 15:34:17 -08001286
1287func BenchmarkFirstUniquePaths(b *testing.B) {
1288 implementations := []struct {
1289 name string
1290 f func(Paths) Paths
1291 }{
1292 {
1293 name: "list",
1294 f: firstUniquePathsList,
1295 },
1296 {
1297 name: "map",
1298 f: firstUniquePathsMap,
1299 },
1300 }
1301 const maxSize = 1024
1302 uniquePaths := make(Paths, maxSize)
1303 for i := range uniquePaths {
1304 uniquePaths[i] = PathForTesting(strconv.Itoa(i))
1305 }
1306 samePath := make(Paths, maxSize)
1307 for i := range samePath {
1308 samePath[i] = uniquePaths[0]
1309 }
1310
1311 f := func(b *testing.B, imp func(Paths) Paths, paths Paths) {
1312 for i := 0; i < b.N; i++ {
1313 b.ReportAllocs()
1314 paths = append(Paths(nil), paths...)
1315 imp(paths)
1316 }
1317 }
1318
1319 for n := 1; n <= maxSize; n <<= 1 {
1320 b.Run(strconv.Itoa(n), func(b *testing.B) {
1321 for _, implementation := range implementations {
1322 b.Run(implementation.name, func(b *testing.B) {
1323 b.Run("same", func(b *testing.B) {
1324 f(b, implementation.f, samePath[:n])
1325 })
1326 b.Run("unique", func(b *testing.B) {
1327 f(b, implementation.f, uniquePaths[:n])
1328 })
1329 })
1330 }
1331 })
1332 }
1333}