blob: cb5495efeb644dfb91e0ba90eae20df740952b08 [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
Jiyong Park87788b52020-09-01 12:37:45 +0900210 forceArch *ArchType
Dan Willemsen00269f22017-07-06 16:59:48 -0700211}
212
Colin Crossaabf6792017-11-29 00:27:14 -0800213func (m moduleInstallPathContextImpl) Config() Config {
Colin Cross0ea8ba82019-06-06 14:33:29 -0700214 return m.baseModuleContext.config
Dan Willemsen00269f22017-07-06 16:59:48 -0700215}
216
217func (moduleInstallPathContextImpl) AddNinjaFileDeps(deps ...string) {}
218
219func (m moduleInstallPathContextImpl) InstallInData() bool {
220 return m.inData
221}
222
Jaewoong Jung0949f312019-09-11 10:25:18 -0700223func (m moduleInstallPathContextImpl) InstallInTestcases() bool {
224 return m.inTestcases
225}
226
Dan Willemsen00269f22017-07-06 16:59:48 -0700227func (m moduleInstallPathContextImpl) InstallInSanitizerDir() bool {
228 return m.inSanitizerDir
229}
230
Yifan Hong1b3348d2020-01-21 15:53:22 -0800231func (m moduleInstallPathContextImpl) InstallInRamdisk() bool {
232 return m.inRamdisk
233}
234
Jiyong Parkf9332f12018-02-01 00:54:12 +0900235func (m moduleInstallPathContextImpl) InstallInRecovery() bool {
236 return m.inRecovery
237}
238
Colin Cross90ba5f42019-10-02 11:10:58 -0700239func (m moduleInstallPathContextImpl) InstallInRoot() bool {
240 return m.inRoot
241}
242
Colin Cross607d8582019-07-29 16:44:46 -0700243func (m moduleInstallPathContextImpl) InstallBypassMake() bool {
244 return false
245}
246
Jiyong Park87788b52020-09-01 12:37:45 +0900247func (m moduleInstallPathContextImpl) InstallForceOS() (*OsType, *ArchType) {
248 return m.forceOS, m.forceArch
Colin Cross6e359402020-02-10 15:29:54 -0800249}
250
Colin Cross98be1bb2019-12-13 20:41:13 -0800251func pathTestConfig(buildDir string) Config {
252 return TestConfig(buildDir, nil, "", nil)
253}
254
Dan Willemsen00269f22017-07-06 16:59:48 -0700255func TestPathForModuleInstall(t *testing.T) {
Colin Cross98be1bb2019-12-13 20:41:13 -0800256 testConfig := pathTestConfig("")
Dan Willemsen00269f22017-07-06 16:59:48 -0700257
Jiyong Park87788b52020-09-01 12:37:45 +0900258 hostTarget := Target{Os: Linux, Arch: Arch{ArchType: X86}}
259 deviceTarget := Target{Os: Android, Arch: Arch{ArchType: Arm64}}
Dan Willemsen00269f22017-07-06 16:59:48 -0700260
261 testCases := []struct {
Jiyong Park957bcd92020-10-20 18:23:33 +0900262 name string
263 ctx *moduleInstallPathContextImpl
264 in []string
265 out string
266 partitionDir string
Dan Willemsen00269f22017-07-06 16:59:48 -0700267 }{
268 {
269 name: "host binary",
270 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700271 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800272 os: hostTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700273 target: hostTarget,
274 },
275 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900276 in: []string{"bin", "my_test"},
277 out: "host/linux-x86/bin/my_test",
278 partitionDir: "host/linux-x86",
Dan Willemsen00269f22017-07-06 16:59:48 -0700279 },
280
281 {
282 name: "system binary",
283 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700284 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800285 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700286 target: deviceTarget,
287 },
288 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900289 in: []string{"bin", "my_test"},
290 out: "target/product/test_device/system/bin/my_test",
291 partitionDir: "target/product/test_device/system",
Dan Willemsen00269f22017-07-06 16:59:48 -0700292 },
293 {
294 name: "vendor binary",
295 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700296 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800297 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700298 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800299 earlyModuleContext: earlyModuleContext{
300 kind: socSpecificModule,
301 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700302 },
303 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900304 in: []string{"bin", "my_test"},
305 out: "target/product/test_device/vendor/bin/my_test",
306 partitionDir: "target/product/test_device/vendor",
Dan Willemsen00269f22017-07-06 16:59:48 -0700307 },
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 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900319 in: []string{"bin", "my_test"},
320 out: "target/product/test_device/odm/bin/my_test",
321 partitionDir: "target/product/test_device/odm",
Jiyong Park2db76922017-11-08 16:03:48 +0900322 },
323 {
Jaekyun Seok5cfbfbb2018-01-10 19:00:15 +0900324 name: "product binary",
Jiyong Park2db76922017-11-08 16:03:48 +0900325 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700326 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800327 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900328 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800329 earlyModuleContext: earlyModuleContext{
330 kind: productSpecificModule,
331 },
Jiyong Park2db76922017-11-08 16:03:48 +0900332 },
333 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900334 in: []string{"bin", "my_test"},
335 out: "target/product/test_device/product/bin/my_test",
336 partitionDir: "target/product/test_device/product",
Jiyong Park2db76922017-11-08 16:03:48 +0900337 },
Dario Frenifd05a742018-05-29 13:28:54 +0100338 {
Justin Yund5f6c822019-06-25 16:47:17 +0900339 name: "system_ext binary",
Dario Frenifd05a742018-05-29 13:28:54 +0100340 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700341 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800342 os: deviceTarget.Os,
Dario Frenifd05a742018-05-29 13:28:54 +0100343 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800344 earlyModuleContext: earlyModuleContext{
345 kind: systemExtSpecificModule,
346 },
Dario Frenifd05a742018-05-29 13:28:54 +0100347 },
348 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900349 in: []string{"bin", "my_test"},
350 out: "target/product/test_device/system_ext/bin/my_test",
351 partitionDir: "target/product/test_device/system_ext",
Dario Frenifd05a742018-05-29 13:28:54 +0100352 },
Colin Cross90ba5f42019-10-02 11:10:58 -0700353 {
354 name: "root binary",
355 ctx: &moduleInstallPathContextImpl{
356 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800357 os: deviceTarget.Os,
Colin Cross90ba5f42019-10-02 11:10:58 -0700358 target: deviceTarget,
359 },
360 inRoot: true,
361 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900362 in: []string{"my_test"},
363 out: "target/product/test_device/root/my_test",
364 partitionDir: "target/product/test_device/root",
Colin Cross90ba5f42019-10-02 11:10:58 -0700365 },
366 {
367 name: "recovery binary",
368 ctx: &moduleInstallPathContextImpl{
369 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800370 os: deviceTarget.Os,
Colin Cross90ba5f42019-10-02 11:10:58 -0700371 target: deviceTarget,
372 },
373 inRecovery: true,
374 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900375 in: []string{"bin/my_test"},
376 out: "target/product/test_device/recovery/root/system/bin/my_test",
377 partitionDir: "target/product/test_device/recovery/root/system",
Colin Cross90ba5f42019-10-02 11:10:58 -0700378 },
379 {
380 name: "recovery root binary",
381 ctx: &moduleInstallPathContextImpl{
382 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800383 os: deviceTarget.Os,
Colin Cross90ba5f42019-10-02 11:10:58 -0700384 target: deviceTarget,
385 },
386 inRecovery: true,
387 inRoot: true,
388 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900389 in: []string{"my_test"},
390 out: "target/product/test_device/recovery/root/my_test",
391 partitionDir: "target/product/test_device/recovery/root",
Colin Cross90ba5f42019-10-02 11:10:58 -0700392 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700393
394 {
395 name: "system native test binary",
396 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700397 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800398 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700399 target: deviceTarget,
400 },
401 inData: true,
402 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900403 in: []string{"nativetest", "my_test"},
404 out: "target/product/test_device/data/nativetest/my_test",
405 partitionDir: "target/product/test_device/data",
Dan Willemsen00269f22017-07-06 16:59:48 -0700406 },
407 {
408 name: "vendor native test binary",
409 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700410 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800411 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700412 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800413 earlyModuleContext: earlyModuleContext{
414 kind: socSpecificModule,
415 },
Jiyong Park2db76922017-11-08 16:03:48 +0900416 },
417 inData: true,
418 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900419 in: []string{"nativetest", "my_test"},
420 out: "target/product/test_device/data/nativetest/my_test",
421 partitionDir: "target/product/test_device/data",
Jiyong Park2db76922017-11-08 16:03:48 +0900422 },
423 {
424 name: "odm native test binary",
425 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700426 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800427 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900428 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800429 earlyModuleContext: earlyModuleContext{
430 kind: deviceSpecificModule,
431 },
Jiyong Park2db76922017-11-08 16:03:48 +0900432 },
433 inData: true,
434 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900435 in: []string{"nativetest", "my_test"},
436 out: "target/product/test_device/data/nativetest/my_test",
437 partitionDir: "target/product/test_device/data",
Jiyong Park2db76922017-11-08 16:03:48 +0900438 },
439 {
Jaekyun Seok5cfbfbb2018-01-10 19:00:15 +0900440 name: "product native test binary",
Jiyong Park2db76922017-11-08 16:03:48 +0900441 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700442 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800443 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900444 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800445 earlyModuleContext: earlyModuleContext{
446 kind: productSpecificModule,
447 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700448 },
449 inData: true,
450 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900451 in: []string{"nativetest", "my_test"},
452 out: "target/product/test_device/data/nativetest/my_test",
453 partitionDir: "target/product/test_device/data",
Dan Willemsen00269f22017-07-06 16:59:48 -0700454 },
455
456 {
Justin Yund5f6c822019-06-25 16:47:17 +0900457 name: "system_ext native test binary",
Dario Frenifd05a742018-05-29 13:28:54 +0100458 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700459 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800460 os: deviceTarget.Os,
Dario Frenifd05a742018-05-29 13:28:54 +0100461 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800462 earlyModuleContext: earlyModuleContext{
463 kind: systemExtSpecificModule,
464 },
Dario Frenifd05a742018-05-29 13:28:54 +0100465 },
466 inData: true,
467 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900468 in: []string{"nativetest", "my_test"},
469 out: "target/product/test_device/data/nativetest/my_test",
470 partitionDir: "target/product/test_device/data",
Dario Frenifd05a742018-05-29 13:28:54 +0100471 },
472
473 {
Dan Willemsen00269f22017-07-06 16:59:48 -0700474 name: "sanitized system binary",
475 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700476 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800477 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700478 target: deviceTarget,
479 },
480 inSanitizerDir: true,
481 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900482 in: []string{"bin", "my_test"},
483 out: "target/product/test_device/data/asan/system/bin/my_test",
484 partitionDir: "target/product/test_device/data/asan/system",
Dan Willemsen00269f22017-07-06 16:59:48 -0700485 },
486 {
487 name: "sanitized vendor binary",
488 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700489 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800490 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700491 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800492 earlyModuleContext: earlyModuleContext{
493 kind: socSpecificModule,
494 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700495 },
496 inSanitizerDir: true,
497 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900498 in: []string{"bin", "my_test"},
499 out: "target/product/test_device/data/asan/vendor/bin/my_test",
500 partitionDir: "target/product/test_device/data/asan/vendor",
Dan Willemsen00269f22017-07-06 16:59:48 -0700501 },
Jiyong Park2db76922017-11-08 16:03:48 +0900502 {
503 name: "sanitized odm binary",
504 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700505 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800506 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900507 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800508 earlyModuleContext: earlyModuleContext{
509 kind: deviceSpecificModule,
510 },
Jiyong Park2db76922017-11-08 16:03:48 +0900511 },
512 inSanitizerDir: true,
513 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900514 in: []string{"bin", "my_test"},
515 out: "target/product/test_device/data/asan/odm/bin/my_test",
516 partitionDir: "target/product/test_device/data/asan/odm",
Jiyong Park2db76922017-11-08 16:03:48 +0900517 },
518 {
Jaekyun Seok5cfbfbb2018-01-10 19:00:15 +0900519 name: "sanitized product binary",
Jiyong Park2db76922017-11-08 16:03:48 +0900520 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700521 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800522 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900523 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800524 earlyModuleContext: earlyModuleContext{
525 kind: productSpecificModule,
526 },
Jiyong Park2db76922017-11-08 16:03:48 +0900527 },
528 inSanitizerDir: true,
529 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900530 in: []string{"bin", "my_test"},
531 out: "target/product/test_device/data/asan/product/bin/my_test",
532 partitionDir: "target/product/test_device/data/asan/product",
Jiyong Park2db76922017-11-08 16:03:48 +0900533 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700534
535 {
Justin Yund5f6c822019-06-25 16:47:17 +0900536 name: "sanitized system_ext binary",
Dario Frenifd05a742018-05-29 13:28:54 +0100537 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700538 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800539 os: deviceTarget.Os,
Dario Frenifd05a742018-05-29 13:28:54 +0100540 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800541 earlyModuleContext: earlyModuleContext{
542 kind: systemExtSpecificModule,
543 },
Dario Frenifd05a742018-05-29 13:28:54 +0100544 },
545 inSanitizerDir: true,
546 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900547 in: []string{"bin", "my_test"},
548 out: "target/product/test_device/data/asan/system_ext/bin/my_test",
549 partitionDir: "target/product/test_device/data/asan/system_ext",
Dario Frenifd05a742018-05-29 13:28:54 +0100550 },
551
552 {
Dan Willemsen00269f22017-07-06 16:59:48 -0700553 name: "sanitized system native test binary",
554 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700555 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800556 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700557 target: deviceTarget,
558 },
559 inData: true,
560 inSanitizerDir: true,
561 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900562 in: []string{"nativetest", "my_test"},
563 out: "target/product/test_device/data/asan/data/nativetest/my_test",
564 partitionDir: "target/product/test_device/data/asan/data",
Dan Willemsen00269f22017-07-06 16:59:48 -0700565 },
566 {
567 name: "sanitized vendor native test binary",
568 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700569 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800570 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700571 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800572 earlyModuleContext: earlyModuleContext{
573 kind: socSpecificModule,
574 },
Jiyong Park2db76922017-11-08 16:03:48 +0900575 },
576 inData: true,
577 inSanitizerDir: true,
578 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900579 in: []string{"nativetest", "my_test"},
580 out: "target/product/test_device/data/asan/data/nativetest/my_test",
581 partitionDir: "target/product/test_device/data/asan/data",
Jiyong Park2db76922017-11-08 16:03:48 +0900582 },
583 {
584 name: "sanitized odm native test binary",
585 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700586 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800587 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900588 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800589 earlyModuleContext: earlyModuleContext{
590 kind: deviceSpecificModule,
591 },
Jiyong Park2db76922017-11-08 16:03:48 +0900592 },
593 inData: true,
594 inSanitizerDir: true,
595 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900596 in: []string{"nativetest", "my_test"},
597 out: "target/product/test_device/data/asan/data/nativetest/my_test",
598 partitionDir: "target/product/test_device/data/asan/data",
Jiyong Park2db76922017-11-08 16:03:48 +0900599 },
600 {
Jaekyun Seok5cfbfbb2018-01-10 19:00:15 +0900601 name: "sanitized product native test binary",
Jiyong Park2db76922017-11-08 16:03:48 +0900602 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700603 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800604 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900605 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800606 earlyModuleContext: earlyModuleContext{
607 kind: productSpecificModule,
608 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700609 },
610 inData: true,
611 inSanitizerDir: true,
612 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900613 in: []string{"nativetest", "my_test"},
614 out: "target/product/test_device/data/asan/data/nativetest/my_test",
615 partitionDir: "target/product/test_device/data/asan/data",
Dan Willemsen00269f22017-07-06 16:59:48 -0700616 },
Dario Frenifd05a742018-05-29 13:28:54 +0100617 {
Justin Yund5f6c822019-06-25 16:47:17 +0900618 name: "sanitized system_ext native test binary",
Dario Frenifd05a742018-05-29 13:28:54 +0100619 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700620 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800621 os: deviceTarget.Os,
Dario Frenifd05a742018-05-29 13:28:54 +0100622 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800623 earlyModuleContext: earlyModuleContext{
624 kind: systemExtSpecificModule,
625 },
Dario Frenifd05a742018-05-29 13:28:54 +0100626 },
627 inData: true,
628 inSanitizerDir: true,
629 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900630 in: []string{"nativetest", "my_test"},
631 out: "target/product/test_device/data/asan/data/nativetest/my_test",
632 partitionDir: "target/product/test_device/data/asan/data",
Colin Cross6e359402020-02-10 15:29:54 -0800633 }, {
634 name: "device testcases",
635 ctx: &moduleInstallPathContextImpl{
636 baseModuleContext: baseModuleContext{
637 os: deviceTarget.Os,
638 target: deviceTarget,
639 },
640 inTestcases: true,
641 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900642 in: []string{"my_test", "my_test_bin"},
643 out: "target/product/test_device/testcases/my_test/my_test_bin",
644 partitionDir: "target/product/test_device/testcases",
Colin Cross6e359402020-02-10 15:29:54 -0800645 }, {
646 name: "host testcases",
647 ctx: &moduleInstallPathContextImpl{
648 baseModuleContext: baseModuleContext{
649 os: hostTarget.Os,
650 target: hostTarget,
651 },
652 inTestcases: true,
653 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900654 in: []string{"my_test", "my_test_bin"},
655 out: "host/linux-x86/testcases/my_test/my_test_bin",
656 partitionDir: "host/linux-x86/testcases",
Colin Cross6e359402020-02-10 15:29:54 -0800657 }, {
658 name: "forced host testcases",
659 ctx: &moduleInstallPathContextImpl{
660 baseModuleContext: baseModuleContext{
661 os: deviceTarget.Os,
662 target: deviceTarget,
663 },
664 inTestcases: true,
665 forceOS: &Linux,
Jiyong Park87788b52020-09-01 12:37:45 +0900666 forceArch: &X86,
Colin Cross6e359402020-02-10 15:29:54 -0800667 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900668 in: []string{"my_test", "my_test_bin"},
669 out: "host/linux-x86/testcases/my_test/my_test_bin",
670 partitionDir: "host/linux-x86/testcases",
Dario Frenifd05a742018-05-29 13:28:54 +0100671 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700672 }
673
674 for _, tc := range testCases {
675 t.Run(tc.name, func(t *testing.T) {
Colin Cross0ea8ba82019-06-06 14:33:29 -0700676 tc.ctx.baseModuleContext.config = testConfig
Dan Willemsen00269f22017-07-06 16:59:48 -0700677 output := PathForModuleInstall(tc.ctx, tc.in...)
678 if output.basePath.path != tc.out {
679 t.Errorf("unexpected path:\n got: %q\nwant: %q\n",
680 output.basePath.path,
681 tc.out)
682 }
Jiyong Park957bcd92020-10-20 18:23:33 +0900683 if output.partitionDir != tc.partitionDir {
684 t.Errorf("unexpected partitionDir:\n got: %q\nwant: %q\n",
685 output.partitionDir, tc.partitionDir)
686 }
Dan Willemsen00269f22017-07-06 16:59:48 -0700687 })
688 }
689}
Colin Cross5e6cfbe2017-11-03 15:20:35 -0700690
Jiyong Park957bcd92020-10-20 18:23:33 +0900691func TestBaseDirForInstallPath(t *testing.T) {
692 testConfig := pathTestConfig("")
693 deviceTarget := Target{Os: Android, Arch: Arch{ArchType: Arm64}}
694
695 ctx := &moduleInstallPathContextImpl{
696 baseModuleContext: baseModuleContext{
697 os: deviceTarget.Os,
698 target: deviceTarget,
699 },
700 }
701 ctx.baseModuleContext.config = testConfig
702
703 actual := PathForModuleInstall(ctx, "foo", "bar")
704 expectedBaseDir := "target/product/test_device/system"
705 if actual.partitionDir != expectedBaseDir {
706 t.Errorf("unexpected partitionDir:\n got: %q\nwant: %q\n", actual.partitionDir, expectedBaseDir)
707 }
708 expectedRelPath := "foo/bar"
709 if actual.Rel() != expectedRelPath {
710 t.Errorf("unexpected Rel():\n got: %q\nwant: %q\n", actual.Rel(), expectedRelPath)
711 }
712
713 actualAfterJoin := actual.Join(ctx, "baz")
714 // partitionDir is preserved even after joining
715 if actualAfterJoin.partitionDir != expectedBaseDir {
716 t.Errorf("unexpected partitionDir after joining:\n got: %q\nwant: %q\n", actualAfterJoin.partitionDir, expectedBaseDir)
717 }
718 // Rel() is updated though
719 expectedRelAfterJoin := "baz"
720 if actualAfterJoin.Rel() != expectedRelAfterJoin {
721 t.Errorf("unexpected Rel() after joining:\n got: %q\nwant: %q\n", actualAfterJoin.Rel(), expectedRelAfterJoin)
722 }
723}
724
Colin Cross5e6cfbe2017-11-03 15:20:35 -0700725func TestDirectorySortedPaths(t *testing.T) {
Colin Cross98be1bb2019-12-13 20:41:13 -0800726 config := TestConfig("out", nil, "", map[string][]byte{
727 "Android.bp": nil,
728 "a.txt": nil,
729 "a/txt": nil,
730 "a/b/c": nil,
731 "a/b/d": nil,
732 "b": nil,
733 "b/b.txt": nil,
734 "a/a.txt": nil,
Colin Cross07e51612019-03-05 12:46:40 -0800735 })
736
Colin Cross98be1bb2019-12-13 20:41:13 -0800737 ctx := PathContextForTesting(config)
738
Colin Cross5e6cfbe2017-11-03 15:20:35 -0700739 makePaths := func() Paths {
740 return Paths{
Colin Cross07e51612019-03-05 12:46:40 -0800741 PathForSource(ctx, "a.txt"),
742 PathForSource(ctx, "a/txt"),
743 PathForSource(ctx, "a/b/c"),
744 PathForSource(ctx, "a/b/d"),
745 PathForSource(ctx, "b"),
746 PathForSource(ctx, "b/b.txt"),
747 PathForSource(ctx, "a/a.txt"),
Colin Cross5e6cfbe2017-11-03 15:20:35 -0700748 }
749 }
750
751 expected := []string{
752 "a.txt",
753 "a/a.txt",
754 "a/b/c",
755 "a/b/d",
756 "a/txt",
757 "b",
758 "b/b.txt",
759 }
760
761 paths := makePaths()
Colin Crossa140bb02018-04-17 10:52:26 -0700762 reversePaths := ReversePaths(paths)
Colin Cross5e6cfbe2017-11-03 15:20:35 -0700763
764 sortedPaths := PathsToDirectorySortedPaths(paths)
765 reverseSortedPaths := PathsToDirectorySortedPaths(reversePaths)
766
767 if !reflect.DeepEqual(Paths(sortedPaths).Strings(), expected) {
768 t.Fatalf("sorted paths:\n %#v\n != \n %#v", paths.Strings(), expected)
769 }
770
771 if !reflect.DeepEqual(Paths(reverseSortedPaths).Strings(), expected) {
772 t.Fatalf("sorted reversed paths:\n %#v\n !=\n %#v", reversePaths.Strings(), expected)
773 }
774
775 expectedA := []string{
776 "a/a.txt",
777 "a/b/c",
778 "a/b/d",
779 "a/txt",
780 }
781
782 inA := sortedPaths.PathsInDirectory("a")
783 if !reflect.DeepEqual(inA.Strings(), expectedA) {
784 t.Errorf("FilesInDirectory(a):\n %#v\n != \n %#v", inA.Strings(), expectedA)
785 }
786
787 expectedA_B := []string{
788 "a/b/c",
789 "a/b/d",
790 }
791
792 inA_B := sortedPaths.PathsInDirectory("a/b")
793 if !reflect.DeepEqual(inA_B.Strings(), expectedA_B) {
794 t.Errorf("FilesInDirectory(a/b):\n %#v\n != \n %#v", inA_B.Strings(), expectedA_B)
795 }
796
797 expectedB := []string{
798 "b/b.txt",
799 }
800
801 inB := sortedPaths.PathsInDirectory("b")
802 if !reflect.DeepEqual(inB.Strings(), expectedB) {
803 t.Errorf("FilesInDirectory(b):\n %#v\n != \n %#v", inA.Strings(), expectedA)
804 }
805}
Colin Cross43f08db2018-11-12 10:13:39 -0800806
807func TestMaybeRel(t *testing.T) {
808 testCases := []struct {
809 name string
810 base string
811 target string
812 out string
813 isRel bool
814 }{
815 {
816 name: "normal",
817 base: "a/b/c",
818 target: "a/b/c/d",
819 out: "d",
820 isRel: true,
821 },
822 {
823 name: "parent",
824 base: "a/b/c/d",
825 target: "a/b/c",
826 isRel: false,
827 },
828 {
829 name: "not relative",
830 base: "a/b",
831 target: "c/d",
832 isRel: false,
833 },
834 {
835 name: "abs1",
836 base: "/a",
837 target: "a",
838 isRel: false,
839 },
840 {
841 name: "abs2",
842 base: "a",
843 target: "/a",
844 isRel: false,
845 },
846 }
847
848 for _, testCase := range testCases {
849 t.Run(testCase.name, func(t *testing.T) {
850 ctx := &configErrorWrapper{}
851 out, isRel := MaybeRel(ctx, testCase.base, testCase.target)
852 if len(ctx.errors) > 0 {
853 t.Errorf("MaybeRel(..., %s, %s) reported unexpected errors %v",
854 testCase.base, testCase.target, ctx.errors)
855 }
856 if isRel != testCase.isRel || out != testCase.out {
857 t.Errorf("MaybeRel(..., %s, %s) want %v, %v got %v, %v",
858 testCase.base, testCase.target, testCase.out, testCase.isRel, out, isRel)
859 }
860 })
861 }
862}
Colin Cross7b3dcc32019-01-24 13:14:39 -0800863
864func TestPathForSource(t *testing.T) {
865 testCases := []struct {
866 name string
867 buildDir string
868 src string
869 err string
870 }{
871 {
872 name: "normal",
873 buildDir: "out",
874 src: "a/b/c",
875 },
876 {
877 name: "abs",
878 buildDir: "out",
879 src: "/a/b/c",
880 err: "is outside directory",
881 },
882 {
883 name: "in out dir",
884 buildDir: "out",
885 src: "out/a/b/c",
886 err: "is in output",
887 },
888 }
889
890 funcs := []struct {
891 name string
892 f func(ctx PathContext, pathComponents ...string) (SourcePath, error)
893 }{
894 {"pathForSource", pathForSource},
895 {"safePathForSource", safePathForSource},
896 }
897
898 for _, f := range funcs {
899 t.Run(f.name, func(t *testing.T) {
900 for _, test := range testCases {
901 t.Run(test.name, func(t *testing.T) {
Colin Cross98be1bb2019-12-13 20:41:13 -0800902 testConfig := pathTestConfig(test.buildDir)
Colin Cross7b3dcc32019-01-24 13:14:39 -0800903 ctx := &configErrorWrapper{config: testConfig}
904 _, err := f.f(ctx, test.src)
905 if len(ctx.errors) > 0 {
906 t.Fatalf("unexpected errors %v", ctx.errors)
907 }
908 if err != nil {
909 if test.err == "" {
910 t.Fatalf("unexpected error %q", err.Error())
911 } else if !strings.Contains(err.Error(), test.err) {
912 t.Fatalf("incorrect error, want substring %q got %q", test.err, err.Error())
913 }
914 } else {
915 if test.err != "" {
916 t.Fatalf("missing error %q", test.err)
917 }
918 }
919 })
920 }
921 })
922 }
923}
Colin Cross8854a5a2019-02-11 14:14:16 -0800924
Colin Cross8a497952019-03-05 22:25:09 -0800925type pathForModuleSrcTestModule struct {
Colin Cross937664a2019-03-06 10:17:32 -0800926 ModuleBase
927 props struct {
928 Srcs []string `android:"path"`
929 Exclude_srcs []string `android:"path"`
Colin Cross8a497952019-03-05 22:25:09 -0800930
931 Src *string `android:"path"`
Colin Crossba71a3f2019-03-18 12:12:48 -0700932
933 Module_handles_missing_deps bool
Colin Cross937664a2019-03-06 10:17:32 -0800934 }
935
Colin Cross8a497952019-03-05 22:25:09 -0800936 src string
937 rel string
938
939 srcs []string
Colin Cross937664a2019-03-06 10:17:32 -0800940 rels []string
Colin Cross8a497952019-03-05 22:25:09 -0800941
942 missingDeps []string
Colin Cross937664a2019-03-06 10:17:32 -0800943}
944
Colin Cross8a497952019-03-05 22:25:09 -0800945func pathForModuleSrcTestModuleFactory() Module {
946 module := &pathForModuleSrcTestModule{}
Colin Cross937664a2019-03-06 10:17:32 -0800947 module.AddProperties(&module.props)
948 InitAndroidModule(module)
949 return module
950}
951
Colin Cross8a497952019-03-05 22:25:09 -0800952func (p *pathForModuleSrcTestModule) GenerateAndroidBuildActions(ctx ModuleContext) {
Colin Crossba71a3f2019-03-18 12:12:48 -0700953 var srcs Paths
954 if p.props.Module_handles_missing_deps {
955 srcs, p.missingDeps = PathsAndMissingDepsForModuleSrcExcludes(ctx, p.props.Srcs, p.props.Exclude_srcs)
956 } else {
957 srcs = PathsForModuleSrcExcludes(ctx, p.props.Srcs, p.props.Exclude_srcs)
958 }
Colin Cross8a497952019-03-05 22:25:09 -0800959 p.srcs = srcs.Strings()
Colin Cross937664a2019-03-06 10:17:32 -0800960
Colin Cross8a497952019-03-05 22:25:09 -0800961 for _, src := range srcs {
Colin Cross937664a2019-03-06 10:17:32 -0800962 p.rels = append(p.rels, src.Rel())
963 }
Colin Cross8a497952019-03-05 22:25:09 -0800964
965 if p.props.Src != nil {
966 src := PathForModuleSrc(ctx, *p.props.Src)
967 if src != nil {
968 p.src = src.String()
969 p.rel = src.Rel()
970 }
971 }
972
Colin Crossba71a3f2019-03-18 12:12:48 -0700973 if !p.props.Module_handles_missing_deps {
974 p.missingDeps = ctx.GetMissingDependencies()
975 }
Colin Cross6c4f21f2019-06-06 15:41:36 -0700976
977 ctx.Build(pctx, BuildParams{
978 Rule: Touch,
979 Output: PathForModuleOut(ctx, "output"),
980 })
Colin Cross8a497952019-03-05 22:25:09 -0800981}
982
Colin Cross41955e82019-05-29 14:40:35 -0700983type pathForModuleSrcOutputFileProviderModule struct {
984 ModuleBase
985 props struct {
986 Outs []string
987 Tagged []string
988 }
989
990 outs Paths
991 tagged Paths
992}
993
994func pathForModuleSrcOutputFileProviderModuleFactory() Module {
995 module := &pathForModuleSrcOutputFileProviderModule{}
996 module.AddProperties(&module.props)
997 InitAndroidModule(module)
998 return module
999}
1000
1001func (p *pathForModuleSrcOutputFileProviderModule) GenerateAndroidBuildActions(ctx ModuleContext) {
1002 for _, out := range p.props.Outs {
1003 p.outs = append(p.outs, PathForModuleOut(ctx, out))
1004 }
1005
1006 for _, tagged := range p.props.Tagged {
1007 p.tagged = append(p.tagged, PathForModuleOut(ctx, tagged))
1008 }
1009}
1010
1011func (p *pathForModuleSrcOutputFileProviderModule) OutputFiles(tag string) (Paths, error) {
1012 switch tag {
1013 case "":
1014 return p.outs, nil
1015 case ".tagged":
1016 return p.tagged, nil
1017 default:
1018 return nil, fmt.Errorf("unsupported tag %q", tag)
1019 }
1020}
1021
Colin Cross8a497952019-03-05 22:25:09 -08001022type pathForModuleSrcTestCase struct {
1023 name string
1024 bp string
1025 srcs []string
1026 rels []string
1027 src string
1028 rel string
1029}
1030
1031func testPathForModuleSrc(t *testing.T, buildDir string, tests []pathForModuleSrcTestCase) {
1032 for _, test := range tests {
1033 t.Run(test.name, func(t *testing.T) {
Colin Cross8a497952019-03-05 22:25:09 -08001034 ctx := NewTestContext()
1035
Colin Cross4b49b762019-11-22 15:25:03 -08001036 ctx.RegisterModuleType("test", pathForModuleSrcTestModuleFactory)
1037 ctx.RegisterModuleType("output_file_provider", pathForModuleSrcOutputFileProviderModuleFactory)
1038 ctx.RegisterModuleType("filegroup", FileGroupFactory)
Colin Cross8a497952019-03-05 22:25:09 -08001039
1040 fgBp := `
1041 filegroup {
1042 name: "a",
1043 srcs: ["src/a"],
1044 }
1045 `
1046
Colin Cross41955e82019-05-29 14:40:35 -07001047 ofpBp := `
1048 output_file_provider {
1049 name: "b",
1050 outs: ["gen/b"],
1051 tagged: ["gen/c"],
1052 }
1053 `
1054
Colin Cross8a497952019-03-05 22:25:09 -08001055 mockFS := map[string][]byte{
1056 "fg/Android.bp": []byte(fgBp),
1057 "foo/Android.bp": []byte(test.bp),
Colin Cross41955e82019-05-29 14:40:35 -07001058 "ofp/Android.bp": []byte(ofpBp),
Colin Cross8a497952019-03-05 22:25:09 -08001059 "fg/src/a": nil,
1060 "foo/src/b": nil,
1061 "foo/src/c": nil,
1062 "foo/src/d": nil,
1063 "foo/src/e/e": nil,
1064 "foo/src_special/$": nil,
1065 }
1066
Colin Cross98be1bb2019-12-13 20:41:13 -08001067 config := TestConfig(buildDir, nil, "", mockFS)
Colin Cross8a497952019-03-05 22:25:09 -08001068
Colin Cross98be1bb2019-12-13 20:41:13 -08001069 ctx.Register(config)
Colin Cross41955e82019-05-29 14:40:35 -07001070 _, errs := ctx.ParseFileList(".", []string{"fg/Android.bp", "foo/Android.bp", "ofp/Android.bp"})
Colin Cross8a497952019-03-05 22:25:09 -08001071 FailIfErrored(t, errs)
1072 _, errs = ctx.PrepareBuildActions(config)
1073 FailIfErrored(t, errs)
1074
1075 m := ctx.ModuleForTests("foo", "").Module().(*pathForModuleSrcTestModule)
1076
1077 if g, w := m.srcs, test.srcs; !reflect.DeepEqual(g, w) {
1078 t.Errorf("want srcs %q, got %q", w, g)
1079 }
1080
1081 if g, w := m.rels, test.rels; !reflect.DeepEqual(g, w) {
1082 t.Errorf("want rels %q, got %q", w, g)
1083 }
1084
1085 if g, w := m.src, test.src; g != w {
1086 t.Errorf("want src %q, got %q", w, g)
1087 }
1088
1089 if g, w := m.rel, test.rel; g != w {
1090 t.Errorf("want rel %q, got %q", w, g)
1091 }
1092 })
1093 }
Colin Cross937664a2019-03-06 10:17:32 -08001094}
1095
Colin Cross8a497952019-03-05 22:25:09 -08001096func TestPathsForModuleSrc(t *testing.T) {
1097 tests := []pathForModuleSrcTestCase{
Colin Cross937664a2019-03-06 10:17:32 -08001098 {
1099 name: "path",
1100 bp: `
1101 test {
1102 name: "foo",
1103 srcs: ["src/b"],
1104 }`,
1105 srcs: []string{"foo/src/b"},
1106 rels: []string{"src/b"},
1107 },
1108 {
1109 name: "glob",
1110 bp: `
1111 test {
1112 name: "foo",
1113 srcs: [
1114 "src/*",
1115 "src/e/*",
1116 ],
1117 }`,
1118 srcs: []string{"foo/src/b", "foo/src/c", "foo/src/d", "foo/src/e/e"},
1119 rels: []string{"src/b", "src/c", "src/d", "src/e/e"},
1120 },
1121 {
1122 name: "recursive glob",
1123 bp: `
1124 test {
1125 name: "foo",
1126 srcs: ["src/**/*"],
1127 }`,
1128 srcs: []string{"foo/src/b", "foo/src/c", "foo/src/d", "foo/src/e/e"},
1129 rels: []string{"src/b", "src/c", "src/d", "src/e/e"},
1130 },
1131 {
1132 name: "filegroup",
1133 bp: `
1134 test {
1135 name: "foo",
1136 srcs: [":a"],
1137 }`,
1138 srcs: []string{"fg/src/a"},
1139 rels: []string{"src/a"},
1140 },
1141 {
Colin Cross41955e82019-05-29 14:40:35 -07001142 name: "output file provider",
1143 bp: `
1144 test {
1145 name: "foo",
1146 srcs: [":b"],
1147 }`,
1148 srcs: []string{buildDir + "/.intermediates/ofp/b/gen/b"},
1149 rels: []string{"gen/b"},
1150 },
1151 {
1152 name: "output file provider tagged",
1153 bp: `
1154 test {
1155 name: "foo",
1156 srcs: [":b{.tagged}"],
1157 }`,
1158 srcs: []string{buildDir + "/.intermediates/ofp/b/gen/c"},
1159 rels: []string{"gen/c"},
1160 },
1161 {
Jooyung Han7607dd32020-07-05 10:23:14 +09001162 name: "output file provider with exclude",
1163 bp: `
1164 test {
1165 name: "foo",
1166 srcs: [":b", ":c"],
1167 exclude_srcs: [":c"]
1168 }
1169 output_file_provider {
1170 name: "c",
1171 outs: ["gen/c"],
1172 }`,
1173 srcs: []string{buildDir + "/.intermediates/ofp/b/gen/b"},
1174 rels: []string{"gen/b"},
1175 },
1176 {
Colin Cross937664a2019-03-06 10:17:32 -08001177 name: "special characters glob",
1178 bp: `
1179 test {
1180 name: "foo",
1181 srcs: ["src_special/*"],
1182 }`,
1183 srcs: []string{"foo/src_special/$"},
1184 rels: []string{"src_special/$"},
1185 },
1186 }
1187
Colin Cross41955e82019-05-29 14:40:35 -07001188 testPathForModuleSrc(t, buildDir, tests)
1189}
1190
1191func TestPathForModuleSrc(t *testing.T) {
Colin Cross8a497952019-03-05 22:25:09 -08001192 tests := []pathForModuleSrcTestCase{
1193 {
1194 name: "path",
1195 bp: `
1196 test {
1197 name: "foo",
1198 src: "src/b",
1199 }`,
1200 src: "foo/src/b",
1201 rel: "src/b",
1202 },
1203 {
1204 name: "glob",
1205 bp: `
1206 test {
1207 name: "foo",
1208 src: "src/e/*",
1209 }`,
1210 src: "foo/src/e/e",
1211 rel: "src/e/e",
1212 },
1213 {
1214 name: "filegroup",
1215 bp: `
1216 test {
1217 name: "foo",
1218 src: ":a",
1219 }`,
1220 src: "fg/src/a",
1221 rel: "src/a",
1222 },
1223 {
Colin Cross41955e82019-05-29 14:40:35 -07001224 name: "output file provider",
1225 bp: `
1226 test {
1227 name: "foo",
1228 src: ":b",
1229 }`,
1230 src: buildDir + "/.intermediates/ofp/b/gen/b",
1231 rel: "gen/b",
1232 },
1233 {
1234 name: "output file provider tagged",
1235 bp: `
1236 test {
1237 name: "foo",
1238 src: ":b{.tagged}",
1239 }`,
1240 src: buildDir + "/.intermediates/ofp/b/gen/c",
1241 rel: "gen/c",
1242 },
1243 {
Colin Cross8a497952019-03-05 22:25:09 -08001244 name: "special characters glob",
1245 bp: `
1246 test {
1247 name: "foo",
1248 src: "src_special/*",
1249 }`,
1250 src: "foo/src_special/$",
1251 rel: "src_special/$",
1252 },
1253 }
1254
Colin Cross8a497952019-03-05 22:25:09 -08001255 testPathForModuleSrc(t, buildDir, tests)
1256}
Colin Cross937664a2019-03-06 10:17:32 -08001257
Colin Cross8a497952019-03-05 22:25:09 -08001258func TestPathsForModuleSrc_AllowMissingDependencies(t *testing.T) {
Colin Cross8a497952019-03-05 22:25:09 -08001259 bp := `
1260 test {
1261 name: "foo",
1262 srcs: [":a"],
1263 exclude_srcs: [":b"],
1264 src: ":c",
1265 }
Colin Crossba71a3f2019-03-18 12:12:48 -07001266
1267 test {
1268 name: "bar",
1269 srcs: [":d"],
1270 exclude_srcs: [":e"],
1271 module_handles_missing_deps: true,
1272 }
Colin Cross8a497952019-03-05 22:25:09 -08001273 `
1274
Colin Cross98be1bb2019-12-13 20:41:13 -08001275 config := TestConfig(buildDir, nil, bp, nil)
1276 config.TestProductVariables.Allow_missing_dependencies = proptools.BoolPtr(true)
Colin Cross8a497952019-03-05 22:25:09 -08001277
Colin Cross98be1bb2019-12-13 20:41:13 -08001278 ctx := NewTestContext()
1279 ctx.SetAllowMissingDependencies(true)
Colin Cross8a497952019-03-05 22:25:09 -08001280
Colin Cross98be1bb2019-12-13 20:41:13 -08001281 ctx.RegisterModuleType("test", pathForModuleSrcTestModuleFactory)
1282
1283 ctx.Register(config)
1284
Colin Cross8a497952019-03-05 22:25:09 -08001285 _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
1286 FailIfErrored(t, errs)
1287 _, errs = ctx.PrepareBuildActions(config)
1288 FailIfErrored(t, errs)
1289
1290 foo := ctx.ModuleForTests("foo", "").Module().(*pathForModuleSrcTestModule)
1291
1292 if g, w := foo.missingDeps, []string{"a", "b", "c"}; !reflect.DeepEqual(g, w) {
Colin Crossba71a3f2019-03-18 12:12:48 -07001293 t.Errorf("want foo missing deps %q, got %q", w, g)
Colin Cross8a497952019-03-05 22:25:09 -08001294 }
1295
1296 if g, w := foo.srcs, []string{}; !reflect.DeepEqual(g, w) {
Colin Crossba71a3f2019-03-18 12:12:48 -07001297 t.Errorf("want foo srcs %q, got %q", w, g)
Colin Cross8a497952019-03-05 22:25:09 -08001298 }
1299
1300 if g, w := foo.src, ""; g != w {
Colin Crossba71a3f2019-03-18 12:12:48 -07001301 t.Errorf("want foo src %q, got %q", w, g)
Colin Cross8a497952019-03-05 22:25:09 -08001302 }
1303
Colin Crossba71a3f2019-03-18 12:12:48 -07001304 bar := ctx.ModuleForTests("bar", "").Module().(*pathForModuleSrcTestModule)
1305
1306 if g, w := bar.missingDeps, []string{"d", "e"}; !reflect.DeepEqual(g, w) {
1307 t.Errorf("want bar missing deps %q, got %q", w, g)
1308 }
1309
1310 if g, w := bar.srcs, []string{}; !reflect.DeepEqual(g, w) {
1311 t.Errorf("want bar srcs %q, got %q", w, g)
1312 }
Colin Cross937664a2019-03-06 10:17:32 -08001313}
1314
Colin Cross8854a5a2019-02-11 14:14:16 -08001315func ExampleOutputPath_ReplaceExtension() {
1316 ctx := &configErrorWrapper{
Colin Cross98be1bb2019-12-13 20:41:13 -08001317 config: TestConfig("out", nil, "", nil),
Colin Cross8854a5a2019-02-11 14:14:16 -08001318 }
Colin Cross2cdd5df2019-02-25 10:25:24 -08001319 p := PathForOutput(ctx, "system/framework").Join(ctx, "boot.art")
Colin Cross8854a5a2019-02-11 14:14:16 -08001320 p2 := p.ReplaceExtension(ctx, "oat")
1321 fmt.Println(p, p2)
Colin Cross2cdd5df2019-02-25 10:25:24 -08001322 fmt.Println(p.Rel(), p2.Rel())
Colin Cross8854a5a2019-02-11 14:14:16 -08001323
1324 // Output:
1325 // out/system/framework/boot.art out/system/framework/boot.oat
Colin Cross2cdd5df2019-02-25 10:25:24 -08001326 // boot.art boot.oat
Colin Cross8854a5a2019-02-11 14:14:16 -08001327}
Colin Cross40e33732019-02-15 11:08:35 -08001328
Colin Cross41b46762020-10-09 19:26:32 -07001329func ExampleOutputPath_InSameDir() {
Colin Cross40e33732019-02-15 11:08:35 -08001330 ctx := &configErrorWrapper{
Colin Cross98be1bb2019-12-13 20:41:13 -08001331 config: TestConfig("out", nil, "", nil),
Colin Cross40e33732019-02-15 11:08:35 -08001332 }
Colin Cross2cdd5df2019-02-25 10:25:24 -08001333 p := PathForOutput(ctx, "system/framework").Join(ctx, "boot.art")
Colin Cross40e33732019-02-15 11:08:35 -08001334 p2 := p.InSameDir(ctx, "oat", "arm", "boot.vdex")
1335 fmt.Println(p, p2)
Colin Cross2cdd5df2019-02-25 10:25:24 -08001336 fmt.Println(p.Rel(), p2.Rel())
Colin Cross40e33732019-02-15 11:08:35 -08001337
1338 // Output:
1339 // out/system/framework/boot.art out/system/framework/oat/arm/boot.vdex
Colin Cross2cdd5df2019-02-25 10:25:24 -08001340 // boot.art oat/arm/boot.vdex
Colin Cross40e33732019-02-15 11:08:35 -08001341}
Colin Cross27027c72020-02-28 15:34:17 -08001342
1343func BenchmarkFirstUniquePaths(b *testing.B) {
1344 implementations := []struct {
1345 name string
1346 f func(Paths) Paths
1347 }{
1348 {
1349 name: "list",
1350 f: firstUniquePathsList,
1351 },
1352 {
1353 name: "map",
1354 f: firstUniquePathsMap,
1355 },
1356 }
1357 const maxSize = 1024
1358 uniquePaths := make(Paths, maxSize)
1359 for i := range uniquePaths {
1360 uniquePaths[i] = PathForTesting(strconv.Itoa(i))
1361 }
1362 samePath := make(Paths, maxSize)
1363 for i := range samePath {
1364 samePath[i] = uniquePaths[0]
1365 }
1366
1367 f := func(b *testing.B, imp func(Paths) Paths, paths Paths) {
1368 for i := 0; i < b.N; i++ {
1369 b.ReportAllocs()
1370 paths = append(Paths(nil), paths...)
1371 imp(paths)
1372 }
1373 }
1374
1375 for n := 1; n <= maxSize; n <<= 1 {
1376 b.Run(strconv.Itoa(n), func(b *testing.B) {
1377 for _, implementation := range implementations {
1378 b.Run(implementation.name, func(b *testing.B) {
1379 b.Run("same", func(b *testing.B) {
1380 f(b, implementation.f, samePath[:n])
1381 })
1382 b.Run("unique", func(b *testing.B) {
1383 f(b, implementation.f, uniquePaths[:n])
1384 })
1385 })
1386 }
1387 })
1388 }
1389}