blob: 51e4ba54512993ccd67980e0ad59bc2c2835ca29 [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
Yifan Hong60e0cfb2020-10-21 15:17:56 -0700203 inData bool
204 inTestcases bool
205 inSanitizerDir bool
206 inRamdisk bool
207 inVendorRamdisk bool
208 inRecovery bool
209 inRoot bool
210 forceOS *OsType
211 forceArch *ArchType
Dan Willemsen00269f22017-07-06 16:59:48 -0700212}
213
Colin Crossaabf6792017-11-29 00:27:14 -0800214func (m moduleInstallPathContextImpl) Config() Config {
Colin Cross0ea8ba82019-06-06 14:33:29 -0700215 return m.baseModuleContext.config
Dan Willemsen00269f22017-07-06 16:59:48 -0700216}
217
218func (moduleInstallPathContextImpl) AddNinjaFileDeps(deps ...string) {}
219
220func (m moduleInstallPathContextImpl) InstallInData() bool {
221 return m.inData
222}
223
Jaewoong Jung0949f312019-09-11 10:25:18 -0700224func (m moduleInstallPathContextImpl) InstallInTestcases() bool {
225 return m.inTestcases
226}
227
Dan Willemsen00269f22017-07-06 16:59:48 -0700228func (m moduleInstallPathContextImpl) InstallInSanitizerDir() bool {
229 return m.inSanitizerDir
230}
231
Yifan Hong1b3348d2020-01-21 15:53:22 -0800232func (m moduleInstallPathContextImpl) InstallInRamdisk() bool {
233 return m.inRamdisk
234}
235
Yifan Hong60e0cfb2020-10-21 15:17:56 -0700236func (m moduleInstallPathContextImpl) InstallInVendorRamdisk() bool {
237 return m.inVendorRamdisk
238}
239
Jiyong Parkf9332f12018-02-01 00:54:12 +0900240func (m moduleInstallPathContextImpl) InstallInRecovery() bool {
241 return m.inRecovery
242}
243
Colin Cross90ba5f42019-10-02 11:10:58 -0700244func (m moduleInstallPathContextImpl) InstallInRoot() bool {
245 return m.inRoot
246}
247
Colin Cross607d8582019-07-29 16:44:46 -0700248func (m moduleInstallPathContextImpl) InstallBypassMake() bool {
249 return false
250}
251
Jiyong Park87788b52020-09-01 12:37:45 +0900252func (m moduleInstallPathContextImpl) InstallForceOS() (*OsType, *ArchType) {
253 return m.forceOS, m.forceArch
Colin Cross6e359402020-02-10 15:29:54 -0800254}
255
Colin Cross98be1bb2019-12-13 20:41:13 -0800256func pathTestConfig(buildDir string) Config {
257 return TestConfig(buildDir, nil, "", nil)
258}
259
Dan Willemsen00269f22017-07-06 16:59:48 -0700260func TestPathForModuleInstall(t *testing.T) {
Colin Cross98be1bb2019-12-13 20:41:13 -0800261 testConfig := pathTestConfig("")
Dan Willemsen00269f22017-07-06 16:59:48 -0700262
Jiyong Park87788b52020-09-01 12:37:45 +0900263 hostTarget := Target{Os: Linux, Arch: Arch{ArchType: X86}}
264 deviceTarget := Target{Os: Android, Arch: Arch{ArchType: Arm64}}
Dan Willemsen00269f22017-07-06 16:59:48 -0700265
266 testCases := []struct {
Jiyong Park957bcd92020-10-20 18:23:33 +0900267 name string
268 ctx *moduleInstallPathContextImpl
269 in []string
270 out string
271 partitionDir string
Dan Willemsen00269f22017-07-06 16:59:48 -0700272 }{
273 {
274 name: "host binary",
275 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700276 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800277 os: hostTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700278 target: hostTarget,
279 },
280 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900281 in: []string{"bin", "my_test"},
282 out: "host/linux-x86/bin/my_test",
283 partitionDir: "host/linux-x86",
Dan Willemsen00269f22017-07-06 16:59:48 -0700284 },
285
286 {
287 name: "system binary",
288 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700289 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800290 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700291 target: deviceTarget,
292 },
293 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900294 in: []string{"bin", "my_test"},
295 out: "target/product/test_device/system/bin/my_test",
296 partitionDir: "target/product/test_device/system",
Dan Willemsen00269f22017-07-06 16:59:48 -0700297 },
298 {
299 name: "vendor binary",
300 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700301 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800302 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700303 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800304 earlyModuleContext: earlyModuleContext{
305 kind: socSpecificModule,
306 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700307 },
308 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900309 in: []string{"bin", "my_test"},
310 out: "target/product/test_device/vendor/bin/my_test",
311 partitionDir: "target/product/test_device/vendor",
Dan Willemsen00269f22017-07-06 16:59:48 -0700312 },
Jiyong Park2db76922017-11-08 16:03:48 +0900313 {
314 name: "odm binary",
315 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700316 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800317 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900318 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800319 earlyModuleContext: earlyModuleContext{
320 kind: deviceSpecificModule,
321 },
Jiyong Park2db76922017-11-08 16:03:48 +0900322 },
323 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900324 in: []string{"bin", "my_test"},
325 out: "target/product/test_device/odm/bin/my_test",
326 partitionDir: "target/product/test_device/odm",
Jiyong Park2db76922017-11-08 16:03:48 +0900327 },
328 {
Jaekyun Seok5cfbfbb2018-01-10 19:00:15 +0900329 name: "product binary",
Jiyong Park2db76922017-11-08 16:03:48 +0900330 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700331 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800332 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900333 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800334 earlyModuleContext: earlyModuleContext{
335 kind: productSpecificModule,
336 },
Jiyong Park2db76922017-11-08 16:03:48 +0900337 },
338 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900339 in: []string{"bin", "my_test"},
340 out: "target/product/test_device/product/bin/my_test",
341 partitionDir: "target/product/test_device/product",
Jiyong Park2db76922017-11-08 16:03:48 +0900342 },
Dario Frenifd05a742018-05-29 13:28:54 +0100343 {
Justin Yund5f6c822019-06-25 16:47:17 +0900344 name: "system_ext binary",
Dario Frenifd05a742018-05-29 13:28:54 +0100345 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700346 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800347 os: deviceTarget.Os,
Dario Frenifd05a742018-05-29 13:28:54 +0100348 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800349 earlyModuleContext: earlyModuleContext{
350 kind: systemExtSpecificModule,
351 },
Dario Frenifd05a742018-05-29 13:28:54 +0100352 },
353 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900354 in: []string{"bin", "my_test"},
355 out: "target/product/test_device/system_ext/bin/my_test",
356 partitionDir: "target/product/test_device/system_ext",
Dario Frenifd05a742018-05-29 13:28:54 +0100357 },
Colin Cross90ba5f42019-10-02 11:10:58 -0700358 {
359 name: "root binary",
360 ctx: &moduleInstallPathContextImpl{
361 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800362 os: deviceTarget.Os,
Colin Cross90ba5f42019-10-02 11:10:58 -0700363 target: deviceTarget,
364 },
365 inRoot: true,
366 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900367 in: []string{"my_test"},
368 out: "target/product/test_device/root/my_test",
369 partitionDir: "target/product/test_device/root",
Colin Cross90ba5f42019-10-02 11:10:58 -0700370 },
371 {
372 name: "recovery binary",
373 ctx: &moduleInstallPathContextImpl{
374 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800375 os: deviceTarget.Os,
Colin Cross90ba5f42019-10-02 11:10:58 -0700376 target: deviceTarget,
377 },
378 inRecovery: true,
379 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900380 in: []string{"bin/my_test"},
381 out: "target/product/test_device/recovery/root/system/bin/my_test",
382 partitionDir: "target/product/test_device/recovery/root/system",
Colin Cross90ba5f42019-10-02 11:10:58 -0700383 },
384 {
385 name: "recovery root binary",
386 ctx: &moduleInstallPathContextImpl{
387 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800388 os: deviceTarget.Os,
Colin Cross90ba5f42019-10-02 11:10:58 -0700389 target: deviceTarget,
390 },
391 inRecovery: true,
392 inRoot: true,
393 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900394 in: []string{"my_test"},
395 out: "target/product/test_device/recovery/root/my_test",
396 partitionDir: "target/product/test_device/recovery/root",
Colin Cross90ba5f42019-10-02 11:10:58 -0700397 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700398
399 {
400 name: "system native test binary",
401 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700402 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800403 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700404 target: deviceTarget,
405 },
406 inData: true,
407 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900408 in: []string{"nativetest", "my_test"},
409 out: "target/product/test_device/data/nativetest/my_test",
410 partitionDir: "target/product/test_device/data",
Dan Willemsen00269f22017-07-06 16:59:48 -0700411 },
412 {
413 name: "vendor native test binary",
414 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700415 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800416 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700417 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800418 earlyModuleContext: earlyModuleContext{
419 kind: socSpecificModule,
420 },
Jiyong Park2db76922017-11-08 16:03:48 +0900421 },
422 inData: true,
423 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900424 in: []string{"nativetest", "my_test"},
425 out: "target/product/test_device/data/nativetest/my_test",
426 partitionDir: "target/product/test_device/data",
Jiyong Park2db76922017-11-08 16:03:48 +0900427 },
428 {
429 name: "odm native test binary",
430 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700431 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800432 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900433 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800434 earlyModuleContext: earlyModuleContext{
435 kind: deviceSpecificModule,
436 },
Jiyong Park2db76922017-11-08 16:03:48 +0900437 },
438 inData: true,
439 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900440 in: []string{"nativetest", "my_test"},
441 out: "target/product/test_device/data/nativetest/my_test",
442 partitionDir: "target/product/test_device/data",
Jiyong Park2db76922017-11-08 16:03:48 +0900443 },
444 {
Jaekyun Seok5cfbfbb2018-01-10 19:00:15 +0900445 name: "product native test binary",
Jiyong Park2db76922017-11-08 16:03:48 +0900446 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700447 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800448 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900449 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800450 earlyModuleContext: earlyModuleContext{
451 kind: productSpecificModule,
452 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700453 },
454 inData: true,
455 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900456 in: []string{"nativetest", "my_test"},
457 out: "target/product/test_device/data/nativetest/my_test",
458 partitionDir: "target/product/test_device/data",
Dan Willemsen00269f22017-07-06 16:59:48 -0700459 },
460
461 {
Justin Yund5f6c822019-06-25 16:47:17 +0900462 name: "system_ext native test binary",
Dario Frenifd05a742018-05-29 13:28:54 +0100463 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700464 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800465 os: deviceTarget.Os,
Dario Frenifd05a742018-05-29 13:28:54 +0100466 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800467 earlyModuleContext: earlyModuleContext{
468 kind: systemExtSpecificModule,
469 },
Dario Frenifd05a742018-05-29 13:28:54 +0100470 },
471 inData: true,
472 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900473 in: []string{"nativetest", "my_test"},
474 out: "target/product/test_device/data/nativetest/my_test",
475 partitionDir: "target/product/test_device/data",
Dario Frenifd05a742018-05-29 13:28:54 +0100476 },
477
478 {
Dan Willemsen00269f22017-07-06 16:59:48 -0700479 name: "sanitized system binary",
480 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700481 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800482 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700483 target: deviceTarget,
484 },
485 inSanitizerDir: true,
486 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900487 in: []string{"bin", "my_test"},
488 out: "target/product/test_device/data/asan/system/bin/my_test",
489 partitionDir: "target/product/test_device/data/asan/system",
Dan Willemsen00269f22017-07-06 16:59:48 -0700490 },
491 {
492 name: "sanitized vendor binary",
493 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700494 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800495 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700496 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800497 earlyModuleContext: earlyModuleContext{
498 kind: socSpecificModule,
499 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700500 },
501 inSanitizerDir: true,
502 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900503 in: []string{"bin", "my_test"},
504 out: "target/product/test_device/data/asan/vendor/bin/my_test",
505 partitionDir: "target/product/test_device/data/asan/vendor",
Dan Willemsen00269f22017-07-06 16:59:48 -0700506 },
Jiyong Park2db76922017-11-08 16:03:48 +0900507 {
508 name: "sanitized odm binary",
509 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700510 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800511 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900512 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800513 earlyModuleContext: earlyModuleContext{
514 kind: deviceSpecificModule,
515 },
Jiyong Park2db76922017-11-08 16:03:48 +0900516 },
517 inSanitizerDir: true,
518 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900519 in: []string{"bin", "my_test"},
520 out: "target/product/test_device/data/asan/odm/bin/my_test",
521 partitionDir: "target/product/test_device/data/asan/odm",
Jiyong Park2db76922017-11-08 16:03:48 +0900522 },
523 {
Jaekyun Seok5cfbfbb2018-01-10 19:00:15 +0900524 name: "sanitized product binary",
Jiyong Park2db76922017-11-08 16:03:48 +0900525 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700526 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800527 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900528 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800529 earlyModuleContext: earlyModuleContext{
530 kind: productSpecificModule,
531 },
Jiyong Park2db76922017-11-08 16:03:48 +0900532 },
533 inSanitizerDir: true,
534 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900535 in: []string{"bin", "my_test"},
536 out: "target/product/test_device/data/asan/product/bin/my_test",
537 partitionDir: "target/product/test_device/data/asan/product",
Jiyong Park2db76922017-11-08 16:03:48 +0900538 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700539
540 {
Justin Yund5f6c822019-06-25 16:47:17 +0900541 name: "sanitized system_ext binary",
Dario Frenifd05a742018-05-29 13:28:54 +0100542 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700543 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800544 os: deviceTarget.Os,
Dario Frenifd05a742018-05-29 13:28:54 +0100545 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800546 earlyModuleContext: earlyModuleContext{
547 kind: systemExtSpecificModule,
548 },
Dario Frenifd05a742018-05-29 13:28:54 +0100549 },
550 inSanitizerDir: true,
551 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900552 in: []string{"bin", "my_test"},
553 out: "target/product/test_device/data/asan/system_ext/bin/my_test",
554 partitionDir: "target/product/test_device/data/asan/system_ext",
Dario Frenifd05a742018-05-29 13:28:54 +0100555 },
556
557 {
Dan Willemsen00269f22017-07-06 16:59:48 -0700558 name: "sanitized system native test binary",
559 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700560 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800561 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700562 target: deviceTarget,
563 },
564 inData: true,
565 inSanitizerDir: true,
566 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900567 in: []string{"nativetest", "my_test"},
568 out: "target/product/test_device/data/asan/data/nativetest/my_test",
569 partitionDir: "target/product/test_device/data/asan/data",
Dan Willemsen00269f22017-07-06 16:59:48 -0700570 },
571 {
572 name: "sanitized vendor native test binary",
573 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700574 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800575 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700576 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800577 earlyModuleContext: earlyModuleContext{
578 kind: socSpecificModule,
579 },
Jiyong Park2db76922017-11-08 16:03:48 +0900580 },
581 inData: true,
582 inSanitizerDir: true,
583 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900584 in: []string{"nativetest", "my_test"},
585 out: "target/product/test_device/data/asan/data/nativetest/my_test",
586 partitionDir: "target/product/test_device/data/asan/data",
Jiyong Park2db76922017-11-08 16:03:48 +0900587 },
588 {
589 name: "sanitized odm native test binary",
590 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700591 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800592 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900593 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800594 earlyModuleContext: earlyModuleContext{
595 kind: deviceSpecificModule,
596 },
Jiyong Park2db76922017-11-08 16:03:48 +0900597 },
598 inData: true,
599 inSanitizerDir: true,
600 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900601 in: []string{"nativetest", "my_test"},
602 out: "target/product/test_device/data/asan/data/nativetest/my_test",
603 partitionDir: "target/product/test_device/data/asan/data",
Jiyong Park2db76922017-11-08 16:03:48 +0900604 },
605 {
Jaekyun Seok5cfbfbb2018-01-10 19:00:15 +0900606 name: "sanitized product native test binary",
Jiyong Park2db76922017-11-08 16:03:48 +0900607 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700608 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800609 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900610 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800611 earlyModuleContext: earlyModuleContext{
612 kind: productSpecificModule,
613 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700614 },
615 inData: true,
616 inSanitizerDir: true,
617 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900618 in: []string{"nativetest", "my_test"},
619 out: "target/product/test_device/data/asan/data/nativetest/my_test",
620 partitionDir: "target/product/test_device/data/asan/data",
Dan Willemsen00269f22017-07-06 16:59:48 -0700621 },
Dario Frenifd05a742018-05-29 13:28:54 +0100622 {
Justin Yund5f6c822019-06-25 16:47:17 +0900623 name: "sanitized system_ext native test binary",
Dario Frenifd05a742018-05-29 13:28:54 +0100624 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700625 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800626 os: deviceTarget.Os,
Dario Frenifd05a742018-05-29 13:28:54 +0100627 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800628 earlyModuleContext: earlyModuleContext{
629 kind: systemExtSpecificModule,
630 },
Dario Frenifd05a742018-05-29 13:28:54 +0100631 },
632 inData: true,
633 inSanitizerDir: true,
634 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900635 in: []string{"nativetest", "my_test"},
636 out: "target/product/test_device/data/asan/data/nativetest/my_test",
637 partitionDir: "target/product/test_device/data/asan/data",
Colin Cross6e359402020-02-10 15:29:54 -0800638 }, {
639 name: "device testcases",
640 ctx: &moduleInstallPathContextImpl{
641 baseModuleContext: baseModuleContext{
642 os: deviceTarget.Os,
643 target: deviceTarget,
644 },
645 inTestcases: true,
646 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900647 in: []string{"my_test", "my_test_bin"},
648 out: "target/product/test_device/testcases/my_test/my_test_bin",
649 partitionDir: "target/product/test_device/testcases",
Colin Cross6e359402020-02-10 15:29:54 -0800650 }, {
651 name: "host testcases",
652 ctx: &moduleInstallPathContextImpl{
653 baseModuleContext: baseModuleContext{
654 os: hostTarget.Os,
655 target: hostTarget,
656 },
657 inTestcases: true,
658 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900659 in: []string{"my_test", "my_test_bin"},
660 out: "host/linux-x86/testcases/my_test/my_test_bin",
661 partitionDir: "host/linux-x86/testcases",
Colin Cross6e359402020-02-10 15:29:54 -0800662 }, {
663 name: "forced host testcases",
664 ctx: &moduleInstallPathContextImpl{
665 baseModuleContext: baseModuleContext{
666 os: deviceTarget.Os,
667 target: deviceTarget,
668 },
669 inTestcases: true,
670 forceOS: &Linux,
Jiyong Park87788b52020-09-01 12:37:45 +0900671 forceArch: &X86,
Colin Cross6e359402020-02-10 15:29:54 -0800672 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900673 in: []string{"my_test", "my_test_bin"},
674 out: "host/linux-x86/testcases/my_test/my_test_bin",
675 partitionDir: "host/linux-x86/testcases",
Dario Frenifd05a742018-05-29 13:28:54 +0100676 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700677 }
678
679 for _, tc := range testCases {
680 t.Run(tc.name, func(t *testing.T) {
Colin Cross0ea8ba82019-06-06 14:33:29 -0700681 tc.ctx.baseModuleContext.config = testConfig
Dan Willemsen00269f22017-07-06 16:59:48 -0700682 output := PathForModuleInstall(tc.ctx, tc.in...)
683 if output.basePath.path != tc.out {
684 t.Errorf("unexpected path:\n got: %q\nwant: %q\n",
685 output.basePath.path,
686 tc.out)
687 }
Jiyong Park957bcd92020-10-20 18:23:33 +0900688 if output.partitionDir != tc.partitionDir {
689 t.Errorf("unexpected partitionDir:\n got: %q\nwant: %q\n",
690 output.partitionDir, tc.partitionDir)
691 }
Dan Willemsen00269f22017-07-06 16:59:48 -0700692 })
693 }
694}
Colin Cross5e6cfbe2017-11-03 15:20:35 -0700695
Jiyong Park957bcd92020-10-20 18:23:33 +0900696func TestBaseDirForInstallPath(t *testing.T) {
697 testConfig := pathTestConfig("")
698 deviceTarget := Target{Os: Android, Arch: Arch{ArchType: Arm64}}
699
700 ctx := &moduleInstallPathContextImpl{
701 baseModuleContext: baseModuleContext{
702 os: deviceTarget.Os,
703 target: deviceTarget,
704 },
705 }
706 ctx.baseModuleContext.config = testConfig
707
708 actual := PathForModuleInstall(ctx, "foo", "bar")
709 expectedBaseDir := "target/product/test_device/system"
710 if actual.partitionDir != expectedBaseDir {
711 t.Errorf("unexpected partitionDir:\n got: %q\nwant: %q\n", actual.partitionDir, expectedBaseDir)
712 }
713 expectedRelPath := "foo/bar"
714 if actual.Rel() != expectedRelPath {
715 t.Errorf("unexpected Rel():\n got: %q\nwant: %q\n", actual.Rel(), expectedRelPath)
716 }
717
718 actualAfterJoin := actual.Join(ctx, "baz")
719 // partitionDir is preserved even after joining
720 if actualAfterJoin.partitionDir != expectedBaseDir {
721 t.Errorf("unexpected partitionDir after joining:\n got: %q\nwant: %q\n", actualAfterJoin.partitionDir, expectedBaseDir)
722 }
723 // Rel() is updated though
724 expectedRelAfterJoin := "baz"
725 if actualAfterJoin.Rel() != expectedRelAfterJoin {
726 t.Errorf("unexpected Rel() after joining:\n got: %q\nwant: %q\n", actualAfterJoin.Rel(), expectedRelAfterJoin)
727 }
728}
729
Colin Cross5e6cfbe2017-11-03 15:20:35 -0700730func TestDirectorySortedPaths(t *testing.T) {
Colin Cross98be1bb2019-12-13 20:41:13 -0800731 config := TestConfig("out", nil, "", map[string][]byte{
732 "Android.bp": nil,
733 "a.txt": nil,
734 "a/txt": nil,
735 "a/b/c": nil,
736 "a/b/d": nil,
737 "b": nil,
738 "b/b.txt": nil,
739 "a/a.txt": nil,
Colin Cross07e51612019-03-05 12:46:40 -0800740 })
741
Colin Cross98be1bb2019-12-13 20:41:13 -0800742 ctx := PathContextForTesting(config)
743
Colin Cross5e6cfbe2017-11-03 15:20:35 -0700744 makePaths := func() Paths {
745 return Paths{
Colin Cross07e51612019-03-05 12:46:40 -0800746 PathForSource(ctx, "a.txt"),
747 PathForSource(ctx, "a/txt"),
748 PathForSource(ctx, "a/b/c"),
749 PathForSource(ctx, "a/b/d"),
750 PathForSource(ctx, "b"),
751 PathForSource(ctx, "b/b.txt"),
752 PathForSource(ctx, "a/a.txt"),
Colin Cross5e6cfbe2017-11-03 15:20:35 -0700753 }
754 }
755
756 expected := []string{
757 "a.txt",
758 "a/a.txt",
759 "a/b/c",
760 "a/b/d",
761 "a/txt",
762 "b",
763 "b/b.txt",
764 }
765
766 paths := makePaths()
Colin Crossa140bb02018-04-17 10:52:26 -0700767 reversePaths := ReversePaths(paths)
Colin Cross5e6cfbe2017-11-03 15:20:35 -0700768
769 sortedPaths := PathsToDirectorySortedPaths(paths)
770 reverseSortedPaths := PathsToDirectorySortedPaths(reversePaths)
771
772 if !reflect.DeepEqual(Paths(sortedPaths).Strings(), expected) {
773 t.Fatalf("sorted paths:\n %#v\n != \n %#v", paths.Strings(), expected)
774 }
775
776 if !reflect.DeepEqual(Paths(reverseSortedPaths).Strings(), expected) {
777 t.Fatalf("sorted reversed paths:\n %#v\n !=\n %#v", reversePaths.Strings(), expected)
778 }
779
780 expectedA := []string{
781 "a/a.txt",
782 "a/b/c",
783 "a/b/d",
784 "a/txt",
785 }
786
787 inA := sortedPaths.PathsInDirectory("a")
788 if !reflect.DeepEqual(inA.Strings(), expectedA) {
789 t.Errorf("FilesInDirectory(a):\n %#v\n != \n %#v", inA.Strings(), expectedA)
790 }
791
792 expectedA_B := []string{
793 "a/b/c",
794 "a/b/d",
795 }
796
797 inA_B := sortedPaths.PathsInDirectory("a/b")
798 if !reflect.DeepEqual(inA_B.Strings(), expectedA_B) {
799 t.Errorf("FilesInDirectory(a/b):\n %#v\n != \n %#v", inA_B.Strings(), expectedA_B)
800 }
801
802 expectedB := []string{
803 "b/b.txt",
804 }
805
806 inB := sortedPaths.PathsInDirectory("b")
807 if !reflect.DeepEqual(inB.Strings(), expectedB) {
808 t.Errorf("FilesInDirectory(b):\n %#v\n != \n %#v", inA.Strings(), expectedA)
809 }
810}
Colin Cross43f08db2018-11-12 10:13:39 -0800811
812func TestMaybeRel(t *testing.T) {
813 testCases := []struct {
814 name string
815 base string
816 target string
817 out string
818 isRel bool
819 }{
820 {
821 name: "normal",
822 base: "a/b/c",
823 target: "a/b/c/d",
824 out: "d",
825 isRel: true,
826 },
827 {
828 name: "parent",
829 base: "a/b/c/d",
830 target: "a/b/c",
831 isRel: false,
832 },
833 {
834 name: "not relative",
835 base: "a/b",
836 target: "c/d",
837 isRel: false,
838 },
839 {
840 name: "abs1",
841 base: "/a",
842 target: "a",
843 isRel: false,
844 },
845 {
846 name: "abs2",
847 base: "a",
848 target: "/a",
849 isRel: false,
850 },
851 }
852
853 for _, testCase := range testCases {
854 t.Run(testCase.name, func(t *testing.T) {
855 ctx := &configErrorWrapper{}
856 out, isRel := MaybeRel(ctx, testCase.base, testCase.target)
857 if len(ctx.errors) > 0 {
858 t.Errorf("MaybeRel(..., %s, %s) reported unexpected errors %v",
859 testCase.base, testCase.target, ctx.errors)
860 }
861 if isRel != testCase.isRel || out != testCase.out {
862 t.Errorf("MaybeRel(..., %s, %s) want %v, %v got %v, %v",
863 testCase.base, testCase.target, testCase.out, testCase.isRel, out, isRel)
864 }
865 })
866 }
867}
Colin Cross7b3dcc32019-01-24 13:14:39 -0800868
869func TestPathForSource(t *testing.T) {
870 testCases := []struct {
871 name string
872 buildDir string
873 src string
874 err string
875 }{
876 {
877 name: "normal",
878 buildDir: "out",
879 src: "a/b/c",
880 },
881 {
882 name: "abs",
883 buildDir: "out",
884 src: "/a/b/c",
885 err: "is outside directory",
886 },
887 {
888 name: "in out dir",
889 buildDir: "out",
890 src: "out/a/b/c",
891 err: "is in output",
892 },
893 }
894
895 funcs := []struct {
896 name string
897 f func(ctx PathContext, pathComponents ...string) (SourcePath, error)
898 }{
899 {"pathForSource", pathForSource},
900 {"safePathForSource", safePathForSource},
901 }
902
903 for _, f := range funcs {
904 t.Run(f.name, func(t *testing.T) {
905 for _, test := range testCases {
906 t.Run(test.name, func(t *testing.T) {
Colin Cross98be1bb2019-12-13 20:41:13 -0800907 testConfig := pathTestConfig(test.buildDir)
Colin Cross7b3dcc32019-01-24 13:14:39 -0800908 ctx := &configErrorWrapper{config: testConfig}
909 _, err := f.f(ctx, test.src)
910 if len(ctx.errors) > 0 {
911 t.Fatalf("unexpected errors %v", ctx.errors)
912 }
913 if err != nil {
914 if test.err == "" {
915 t.Fatalf("unexpected error %q", err.Error())
916 } else if !strings.Contains(err.Error(), test.err) {
917 t.Fatalf("incorrect error, want substring %q got %q", test.err, err.Error())
918 }
919 } else {
920 if test.err != "" {
921 t.Fatalf("missing error %q", test.err)
922 }
923 }
924 })
925 }
926 })
927 }
928}
Colin Cross8854a5a2019-02-11 14:14:16 -0800929
Colin Cross8a497952019-03-05 22:25:09 -0800930type pathForModuleSrcTestModule struct {
Colin Cross937664a2019-03-06 10:17:32 -0800931 ModuleBase
932 props struct {
933 Srcs []string `android:"path"`
934 Exclude_srcs []string `android:"path"`
Colin Cross8a497952019-03-05 22:25:09 -0800935
936 Src *string `android:"path"`
Colin Crossba71a3f2019-03-18 12:12:48 -0700937
938 Module_handles_missing_deps bool
Colin Cross937664a2019-03-06 10:17:32 -0800939 }
940
Colin Cross8a497952019-03-05 22:25:09 -0800941 src string
942 rel string
943
944 srcs []string
Colin Cross937664a2019-03-06 10:17:32 -0800945 rels []string
Colin Cross8a497952019-03-05 22:25:09 -0800946
947 missingDeps []string
Colin Cross937664a2019-03-06 10:17:32 -0800948}
949
Colin Cross8a497952019-03-05 22:25:09 -0800950func pathForModuleSrcTestModuleFactory() Module {
951 module := &pathForModuleSrcTestModule{}
Colin Cross937664a2019-03-06 10:17:32 -0800952 module.AddProperties(&module.props)
953 InitAndroidModule(module)
954 return module
955}
956
Colin Cross8a497952019-03-05 22:25:09 -0800957func (p *pathForModuleSrcTestModule) GenerateAndroidBuildActions(ctx ModuleContext) {
Colin Crossba71a3f2019-03-18 12:12:48 -0700958 var srcs Paths
959 if p.props.Module_handles_missing_deps {
960 srcs, p.missingDeps = PathsAndMissingDepsForModuleSrcExcludes(ctx, p.props.Srcs, p.props.Exclude_srcs)
961 } else {
962 srcs = PathsForModuleSrcExcludes(ctx, p.props.Srcs, p.props.Exclude_srcs)
963 }
Colin Cross8a497952019-03-05 22:25:09 -0800964 p.srcs = srcs.Strings()
Colin Cross937664a2019-03-06 10:17:32 -0800965
Colin Cross8a497952019-03-05 22:25:09 -0800966 for _, src := range srcs {
Colin Cross937664a2019-03-06 10:17:32 -0800967 p.rels = append(p.rels, src.Rel())
968 }
Colin Cross8a497952019-03-05 22:25:09 -0800969
970 if p.props.Src != nil {
971 src := PathForModuleSrc(ctx, *p.props.Src)
972 if src != nil {
973 p.src = src.String()
974 p.rel = src.Rel()
975 }
976 }
977
Colin Crossba71a3f2019-03-18 12:12:48 -0700978 if !p.props.Module_handles_missing_deps {
979 p.missingDeps = ctx.GetMissingDependencies()
980 }
Colin Cross6c4f21f2019-06-06 15:41:36 -0700981
982 ctx.Build(pctx, BuildParams{
983 Rule: Touch,
984 Output: PathForModuleOut(ctx, "output"),
985 })
Colin Cross8a497952019-03-05 22:25:09 -0800986}
987
Colin Cross41955e82019-05-29 14:40:35 -0700988type pathForModuleSrcOutputFileProviderModule struct {
989 ModuleBase
990 props struct {
991 Outs []string
992 Tagged []string
993 }
994
995 outs Paths
996 tagged Paths
997}
998
999func pathForModuleSrcOutputFileProviderModuleFactory() Module {
1000 module := &pathForModuleSrcOutputFileProviderModule{}
1001 module.AddProperties(&module.props)
1002 InitAndroidModule(module)
1003 return module
1004}
1005
1006func (p *pathForModuleSrcOutputFileProviderModule) GenerateAndroidBuildActions(ctx ModuleContext) {
1007 for _, out := range p.props.Outs {
1008 p.outs = append(p.outs, PathForModuleOut(ctx, out))
1009 }
1010
1011 for _, tagged := range p.props.Tagged {
1012 p.tagged = append(p.tagged, PathForModuleOut(ctx, tagged))
1013 }
1014}
1015
1016func (p *pathForModuleSrcOutputFileProviderModule) OutputFiles(tag string) (Paths, error) {
1017 switch tag {
1018 case "":
1019 return p.outs, nil
1020 case ".tagged":
1021 return p.tagged, nil
1022 default:
1023 return nil, fmt.Errorf("unsupported tag %q", tag)
1024 }
1025}
1026
Colin Cross8a497952019-03-05 22:25:09 -08001027type pathForModuleSrcTestCase struct {
1028 name string
1029 bp string
1030 srcs []string
1031 rels []string
1032 src string
1033 rel string
1034}
1035
1036func testPathForModuleSrc(t *testing.T, buildDir string, tests []pathForModuleSrcTestCase) {
1037 for _, test := range tests {
1038 t.Run(test.name, func(t *testing.T) {
Colin Cross8a497952019-03-05 22:25:09 -08001039 ctx := NewTestContext()
1040
Colin Cross4b49b762019-11-22 15:25:03 -08001041 ctx.RegisterModuleType("test", pathForModuleSrcTestModuleFactory)
1042 ctx.RegisterModuleType("output_file_provider", pathForModuleSrcOutputFileProviderModuleFactory)
1043 ctx.RegisterModuleType("filegroup", FileGroupFactory)
Colin Cross8a497952019-03-05 22:25:09 -08001044
1045 fgBp := `
1046 filegroup {
1047 name: "a",
1048 srcs: ["src/a"],
1049 }
1050 `
1051
Colin Cross41955e82019-05-29 14:40:35 -07001052 ofpBp := `
1053 output_file_provider {
1054 name: "b",
1055 outs: ["gen/b"],
1056 tagged: ["gen/c"],
1057 }
1058 `
1059
Colin Cross8a497952019-03-05 22:25:09 -08001060 mockFS := map[string][]byte{
1061 "fg/Android.bp": []byte(fgBp),
1062 "foo/Android.bp": []byte(test.bp),
Colin Cross41955e82019-05-29 14:40:35 -07001063 "ofp/Android.bp": []byte(ofpBp),
Colin Cross8a497952019-03-05 22:25:09 -08001064 "fg/src/a": nil,
1065 "foo/src/b": nil,
1066 "foo/src/c": nil,
1067 "foo/src/d": nil,
1068 "foo/src/e/e": nil,
1069 "foo/src_special/$": nil,
1070 }
1071
Colin Cross98be1bb2019-12-13 20:41:13 -08001072 config := TestConfig(buildDir, nil, "", mockFS)
Colin Cross8a497952019-03-05 22:25:09 -08001073
Colin Cross98be1bb2019-12-13 20:41:13 -08001074 ctx.Register(config)
Colin Cross41955e82019-05-29 14:40:35 -07001075 _, errs := ctx.ParseFileList(".", []string{"fg/Android.bp", "foo/Android.bp", "ofp/Android.bp"})
Colin Cross8a497952019-03-05 22:25:09 -08001076 FailIfErrored(t, errs)
1077 _, errs = ctx.PrepareBuildActions(config)
1078 FailIfErrored(t, errs)
1079
1080 m := ctx.ModuleForTests("foo", "").Module().(*pathForModuleSrcTestModule)
1081
1082 if g, w := m.srcs, test.srcs; !reflect.DeepEqual(g, w) {
1083 t.Errorf("want srcs %q, got %q", w, g)
1084 }
1085
1086 if g, w := m.rels, test.rels; !reflect.DeepEqual(g, w) {
1087 t.Errorf("want rels %q, got %q", w, g)
1088 }
1089
1090 if g, w := m.src, test.src; g != w {
1091 t.Errorf("want src %q, got %q", w, g)
1092 }
1093
1094 if g, w := m.rel, test.rel; g != w {
1095 t.Errorf("want rel %q, got %q", w, g)
1096 }
1097 })
1098 }
Colin Cross937664a2019-03-06 10:17:32 -08001099}
1100
Colin Cross8a497952019-03-05 22:25:09 -08001101func TestPathsForModuleSrc(t *testing.T) {
1102 tests := []pathForModuleSrcTestCase{
Colin Cross937664a2019-03-06 10:17:32 -08001103 {
1104 name: "path",
1105 bp: `
1106 test {
1107 name: "foo",
1108 srcs: ["src/b"],
1109 }`,
1110 srcs: []string{"foo/src/b"},
1111 rels: []string{"src/b"},
1112 },
1113 {
1114 name: "glob",
1115 bp: `
1116 test {
1117 name: "foo",
1118 srcs: [
1119 "src/*",
1120 "src/e/*",
1121 ],
1122 }`,
1123 srcs: []string{"foo/src/b", "foo/src/c", "foo/src/d", "foo/src/e/e"},
1124 rels: []string{"src/b", "src/c", "src/d", "src/e/e"},
1125 },
1126 {
1127 name: "recursive glob",
1128 bp: `
1129 test {
1130 name: "foo",
1131 srcs: ["src/**/*"],
1132 }`,
1133 srcs: []string{"foo/src/b", "foo/src/c", "foo/src/d", "foo/src/e/e"},
1134 rels: []string{"src/b", "src/c", "src/d", "src/e/e"},
1135 },
1136 {
1137 name: "filegroup",
1138 bp: `
1139 test {
1140 name: "foo",
1141 srcs: [":a"],
1142 }`,
1143 srcs: []string{"fg/src/a"},
1144 rels: []string{"src/a"},
1145 },
1146 {
Colin Cross41955e82019-05-29 14:40:35 -07001147 name: "output file provider",
1148 bp: `
1149 test {
1150 name: "foo",
1151 srcs: [":b"],
1152 }`,
1153 srcs: []string{buildDir + "/.intermediates/ofp/b/gen/b"},
1154 rels: []string{"gen/b"},
1155 },
1156 {
1157 name: "output file provider tagged",
1158 bp: `
1159 test {
1160 name: "foo",
1161 srcs: [":b{.tagged}"],
1162 }`,
1163 srcs: []string{buildDir + "/.intermediates/ofp/b/gen/c"},
1164 rels: []string{"gen/c"},
1165 },
1166 {
Jooyung Han7607dd32020-07-05 10:23:14 +09001167 name: "output file provider with exclude",
1168 bp: `
1169 test {
1170 name: "foo",
1171 srcs: [":b", ":c"],
1172 exclude_srcs: [":c"]
1173 }
1174 output_file_provider {
1175 name: "c",
1176 outs: ["gen/c"],
1177 }`,
1178 srcs: []string{buildDir + "/.intermediates/ofp/b/gen/b"},
1179 rels: []string{"gen/b"},
1180 },
1181 {
Colin Cross937664a2019-03-06 10:17:32 -08001182 name: "special characters glob",
1183 bp: `
1184 test {
1185 name: "foo",
1186 srcs: ["src_special/*"],
1187 }`,
1188 srcs: []string{"foo/src_special/$"},
1189 rels: []string{"src_special/$"},
1190 },
1191 }
1192
Colin Cross41955e82019-05-29 14:40:35 -07001193 testPathForModuleSrc(t, buildDir, tests)
1194}
1195
1196func TestPathForModuleSrc(t *testing.T) {
Colin Cross8a497952019-03-05 22:25:09 -08001197 tests := []pathForModuleSrcTestCase{
1198 {
1199 name: "path",
1200 bp: `
1201 test {
1202 name: "foo",
1203 src: "src/b",
1204 }`,
1205 src: "foo/src/b",
1206 rel: "src/b",
1207 },
1208 {
1209 name: "glob",
1210 bp: `
1211 test {
1212 name: "foo",
1213 src: "src/e/*",
1214 }`,
1215 src: "foo/src/e/e",
1216 rel: "src/e/e",
1217 },
1218 {
1219 name: "filegroup",
1220 bp: `
1221 test {
1222 name: "foo",
1223 src: ":a",
1224 }`,
1225 src: "fg/src/a",
1226 rel: "src/a",
1227 },
1228 {
Colin Cross41955e82019-05-29 14:40:35 -07001229 name: "output file provider",
1230 bp: `
1231 test {
1232 name: "foo",
1233 src: ":b",
1234 }`,
1235 src: buildDir + "/.intermediates/ofp/b/gen/b",
1236 rel: "gen/b",
1237 },
1238 {
1239 name: "output file provider tagged",
1240 bp: `
1241 test {
1242 name: "foo",
1243 src: ":b{.tagged}",
1244 }`,
1245 src: buildDir + "/.intermediates/ofp/b/gen/c",
1246 rel: "gen/c",
1247 },
1248 {
Colin Cross8a497952019-03-05 22:25:09 -08001249 name: "special characters glob",
1250 bp: `
1251 test {
1252 name: "foo",
1253 src: "src_special/*",
1254 }`,
1255 src: "foo/src_special/$",
1256 rel: "src_special/$",
1257 },
1258 }
1259
Colin Cross8a497952019-03-05 22:25:09 -08001260 testPathForModuleSrc(t, buildDir, tests)
1261}
Colin Cross937664a2019-03-06 10:17:32 -08001262
Colin Cross8a497952019-03-05 22:25:09 -08001263func TestPathsForModuleSrc_AllowMissingDependencies(t *testing.T) {
Colin Cross8a497952019-03-05 22:25:09 -08001264 bp := `
1265 test {
1266 name: "foo",
1267 srcs: [":a"],
1268 exclude_srcs: [":b"],
1269 src: ":c",
1270 }
Colin Crossba71a3f2019-03-18 12:12:48 -07001271
1272 test {
1273 name: "bar",
1274 srcs: [":d"],
1275 exclude_srcs: [":e"],
1276 module_handles_missing_deps: true,
1277 }
Colin Cross8a497952019-03-05 22:25:09 -08001278 `
1279
Colin Cross98be1bb2019-12-13 20:41:13 -08001280 config := TestConfig(buildDir, nil, bp, nil)
1281 config.TestProductVariables.Allow_missing_dependencies = proptools.BoolPtr(true)
Colin Cross8a497952019-03-05 22:25:09 -08001282
Colin Cross98be1bb2019-12-13 20:41:13 -08001283 ctx := NewTestContext()
1284 ctx.SetAllowMissingDependencies(true)
Colin Cross8a497952019-03-05 22:25:09 -08001285
Colin Cross98be1bb2019-12-13 20:41:13 -08001286 ctx.RegisterModuleType("test", pathForModuleSrcTestModuleFactory)
1287
1288 ctx.Register(config)
1289
Colin Cross8a497952019-03-05 22:25:09 -08001290 _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
1291 FailIfErrored(t, errs)
1292 _, errs = ctx.PrepareBuildActions(config)
1293 FailIfErrored(t, errs)
1294
1295 foo := ctx.ModuleForTests("foo", "").Module().(*pathForModuleSrcTestModule)
1296
1297 if g, w := foo.missingDeps, []string{"a", "b", "c"}; !reflect.DeepEqual(g, w) {
Colin Crossba71a3f2019-03-18 12:12:48 -07001298 t.Errorf("want foo missing deps %q, got %q", w, g)
Colin Cross8a497952019-03-05 22:25:09 -08001299 }
1300
1301 if g, w := foo.srcs, []string{}; !reflect.DeepEqual(g, w) {
Colin Crossba71a3f2019-03-18 12:12:48 -07001302 t.Errorf("want foo srcs %q, got %q", w, g)
Colin Cross8a497952019-03-05 22:25:09 -08001303 }
1304
1305 if g, w := foo.src, ""; g != w {
Colin Crossba71a3f2019-03-18 12:12:48 -07001306 t.Errorf("want foo src %q, got %q", w, g)
Colin Cross8a497952019-03-05 22:25:09 -08001307 }
1308
Colin Crossba71a3f2019-03-18 12:12:48 -07001309 bar := ctx.ModuleForTests("bar", "").Module().(*pathForModuleSrcTestModule)
1310
1311 if g, w := bar.missingDeps, []string{"d", "e"}; !reflect.DeepEqual(g, w) {
1312 t.Errorf("want bar missing deps %q, got %q", w, g)
1313 }
1314
1315 if g, w := bar.srcs, []string{}; !reflect.DeepEqual(g, w) {
1316 t.Errorf("want bar srcs %q, got %q", w, g)
1317 }
Colin Cross937664a2019-03-06 10:17:32 -08001318}
1319
Colin Cross8854a5a2019-02-11 14:14:16 -08001320func ExampleOutputPath_ReplaceExtension() {
1321 ctx := &configErrorWrapper{
Colin Cross98be1bb2019-12-13 20:41:13 -08001322 config: TestConfig("out", nil, "", nil),
Colin Cross8854a5a2019-02-11 14:14:16 -08001323 }
Colin Cross2cdd5df2019-02-25 10:25:24 -08001324 p := PathForOutput(ctx, "system/framework").Join(ctx, "boot.art")
Colin Cross8854a5a2019-02-11 14:14:16 -08001325 p2 := p.ReplaceExtension(ctx, "oat")
1326 fmt.Println(p, p2)
Colin Cross2cdd5df2019-02-25 10:25:24 -08001327 fmt.Println(p.Rel(), p2.Rel())
Colin Cross8854a5a2019-02-11 14:14:16 -08001328
1329 // Output:
1330 // out/system/framework/boot.art out/system/framework/boot.oat
Colin Cross2cdd5df2019-02-25 10:25:24 -08001331 // boot.art boot.oat
Colin Cross8854a5a2019-02-11 14:14:16 -08001332}
Colin Cross40e33732019-02-15 11:08:35 -08001333
Colin Cross41b46762020-10-09 19:26:32 -07001334func ExampleOutputPath_InSameDir() {
Colin Cross40e33732019-02-15 11:08:35 -08001335 ctx := &configErrorWrapper{
Colin Cross98be1bb2019-12-13 20:41:13 -08001336 config: TestConfig("out", nil, "", nil),
Colin Cross40e33732019-02-15 11:08:35 -08001337 }
Colin Cross2cdd5df2019-02-25 10:25:24 -08001338 p := PathForOutput(ctx, "system/framework").Join(ctx, "boot.art")
Colin Cross40e33732019-02-15 11:08:35 -08001339 p2 := p.InSameDir(ctx, "oat", "arm", "boot.vdex")
1340 fmt.Println(p, p2)
Colin Cross2cdd5df2019-02-25 10:25:24 -08001341 fmt.Println(p.Rel(), p2.Rel())
Colin Cross40e33732019-02-15 11:08:35 -08001342
1343 // Output:
1344 // out/system/framework/boot.art out/system/framework/oat/arm/boot.vdex
Colin Cross2cdd5df2019-02-25 10:25:24 -08001345 // boot.art oat/arm/boot.vdex
Colin Cross40e33732019-02-15 11:08:35 -08001346}
Colin Cross27027c72020-02-28 15:34:17 -08001347
1348func BenchmarkFirstUniquePaths(b *testing.B) {
1349 implementations := []struct {
1350 name string
1351 f func(Paths) Paths
1352 }{
1353 {
1354 name: "list",
1355 f: firstUniquePathsList,
1356 },
1357 {
1358 name: "map",
1359 f: firstUniquePathsMap,
1360 },
1361 }
1362 const maxSize = 1024
1363 uniquePaths := make(Paths, maxSize)
1364 for i := range uniquePaths {
1365 uniquePaths[i] = PathForTesting(strconv.Itoa(i))
1366 }
1367 samePath := make(Paths, maxSize)
1368 for i := range samePath {
1369 samePath[i] = uniquePaths[0]
1370 }
1371
1372 f := func(b *testing.B, imp func(Paths) Paths, paths Paths) {
1373 for i := 0; i < b.N; i++ {
1374 b.ReportAllocs()
1375 paths = append(Paths(nil), paths...)
1376 imp(paths)
1377 }
1378 }
1379
1380 for n := 1; n <= maxSize; n <<= 1 {
1381 b.Run(strconv.Itoa(n), func(b *testing.B) {
1382 for _, implementation := range implementations {
1383 b.Run(implementation.name, func(b *testing.B) {
1384 b.Run("same", func(b *testing.B) {
1385 f(b, implementation.f, samePath[:n])
1386 })
1387 b.Run("unique", func(b *testing.B) {
1388 f(b, implementation.f, uniquePaths[:n])
1389 })
1390 })
1391 }
1392 })
1393 }
1394}