blob: 6ec75b42b39393308a7ac29ae3dc649ec9183b66 [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"
Inseob Kimd9580b82021-04-13 21:13:49 +090024
25 "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
Colin Cross98be1bb2019-12-13 20:41:13 -0800200func pathTestConfig(buildDir string) Config {
201 return TestConfig(buildDir, nil, "", nil)
202}
203
Dan Willemsen00269f22017-07-06 16:59:48 -0700204func TestPathForModuleInstall(t *testing.T) {
Colin Cross98be1bb2019-12-13 20:41:13 -0800205 testConfig := pathTestConfig("")
Dan Willemsen00269f22017-07-06 16:59:48 -0700206
Jiyong Park87788b52020-09-01 12:37:45 +0900207 hostTarget := Target{Os: Linux, Arch: Arch{ArchType: X86}}
208 deviceTarget := Target{Os: Android, Arch: Arch{ArchType: Arm64}}
Dan Willemsen00269f22017-07-06 16:59:48 -0700209
210 testCases := []struct {
Jiyong Park957bcd92020-10-20 18:23:33 +0900211 name string
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100212 ctx *testModuleInstallPathContext
Jiyong Park957bcd92020-10-20 18:23:33 +0900213 in []string
214 out string
215 partitionDir string
Dan Willemsen00269f22017-07-06 16:59:48 -0700216 }{
217 {
218 name: "host binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100219 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700220 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800221 os: hostTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700222 target: hostTarget,
223 },
224 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900225 in: []string{"bin", "my_test"},
226 out: "host/linux-x86/bin/my_test",
227 partitionDir: "host/linux-x86",
Dan Willemsen00269f22017-07-06 16:59:48 -0700228 },
229
230 {
231 name: "system binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100232 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700233 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800234 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700235 target: deviceTarget,
236 },
237 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900238 in: []string{"bin", "my_test"},
239 out: "target/product/test_device/system/bin/my_test",
240 partitionDir: "target/product/test_device/system",
Dan Willemsen00269f22017-07-06 16:59:48 -0700241 },
242 {
243 name: "vendor binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100244 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700245 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800246 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700247 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800248 earlyModuleContext: earlyModuleContext{
249 kind: socSpecificModule,
250 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700251 },
252 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900253 in: []string{"bin", "my_test"},
254 out: "target/product/test_device/vendor/bin/my_test",
255 partitionDir: "target/product/test_device/vendor",
Dan Willemsen00269f22017-07-06 16:59:48 -0700256 },
Jiyong Park2db76922017-11-08 16:03:48 +0900257 {
258 name: "odm binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100259 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700260 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800261 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900262 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800263 earlyModuleContext: earlyModuleContext{
264 kind: deviceSpecificModule,
265 },
Jiyong Park2db76922017-11-08 16:03:48 +0900266 },
267 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900268 in: []string{"bin", "my_test"},
269 out: "target/product/test_device/odm/bin/my_test",
270 partitionDir: "target/product/test_device/odm",
Jiyong Park2db76922017-11-08 16:03:48 +0900271 },
272 {
Jaekyun Seok5cfbfbb2018-01-10 19:00:15 +0900273 name: "product binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100274 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700275 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800276 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900277 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800278 earlyModuleContext: earlyModuleContext{
279 kind: productSpecificModule,
280 },
Jiyong Park2db76922017-11-08 16:03:48 +0900281 },
282 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900283 in: []string{"bin", "my_test"},
284 out: "target/product/test_device/product/bin/my_test",
285 partitionDir: "target/product/test_device/product",
Jiyong Park2db76922017-11-08 16:03:48 +0900286 },
Dario Frenifd05a742018-05-29 13:28:54 +0100287 {
Justin Yund5f6c822019-06-25 16:47:17 +0900288 name: "system_ext binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100289 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700290 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800291 os: deviceTarget.Os,
Dario Frenifd05a742018-05-29 13:28:54 +0100292 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800293 earlyModuleContext: earlyModuleContext{
294 kind: systemExtSpecificModule,
295 },
Dario Frenifd05a742018-05-29 13:28:54 +0100296 },
297 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900298 in: []string{"bin", "my_test"},
299 out: "target/product/test_device/system_ext/bin/my_test",
300 partitionDir: "target/product/test_device/system_ext",
Dario Frenifd05a742018-05-29 13:28:54 +0100301 },
Colin Cross90ba5f42019-10-02 11:10:58 -0700302 {
303 name: "root binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100304 ctx: &testModuleInstallPathContext{
Colin Cross90ba5f42019-10-02 11:10:58 -0700305 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800306 os: deviceTarget.Os,
Colin Cross90ba5f42019-10-02 11:10:58 -0700307 target: deviceTarget,
308 },
309 inRoot: true,
310 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900311 in: []string{"my_test"},
312 out: "target/product/test_device/root/my_test",
313 partitionDir: "target/product/test_device/root",
Colin Cross90ba5f42019-10-02 11:10:58 -0700314 },
315 {
316 name: "recovery binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100317 ctx: &testModuleInstallPathContext{
Colin Cross90ba5f42019-10-02 11:10:58 -0700318 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800319 os: deviceTarget.Os,
Colin Cross90ba5f42019-10-02 11:10:58 -0700320 target: deviceTarget,
321 },
322 inRecovery: true,
323 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900324 in: []string{"bin/my_test"},
325 out: "target/product/test_device/recovery/root/system/bin/my_test",
326 partitionDir: "target/product/test_device/recovery/root/system",
Colin Cross90ba5f42019-10-02 11:10:58 -0700327 },
328 {
329 name: "recovery root binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100330 ctx: &testModuleInstallPathContext{
Colin Cross90ba5f42019-10-02 11:10:58 -0700331 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800332 os: deviceTarget.Os,
Colin Cross90ba5f42019-10-02 11:10:58 -0700333 target: deviceTarget,
334 },
335 inRecovery: true,
336 inRoot: true,
337 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900338 in: []string{"my_test"},
339 out: "target/product/test_device/recovery/root/my_test",
340 partitionDir: "target/product/test_device/recovery/root",
Colin Cross90ba5f42019-10-02 11:10:58 -0700341 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700342
343 {
Inseob Kimd9580b82021-04-13 21:13:49 +0900344 name: "ramdisk binary",
345 ctx: &testModuleInstallPathContext{
346 baseModuleContext: baseModuleContext{
347 os: deviceTarget.Os,
348 target: deviceTarget,
349 },
350 inRamdisk: true,
351 },
352 in: []string{"my_test"},
353 out: "target/product/test_device/ramdisk/system/my_test",
354 partitionDir: "target/product/test_device/ramdisk/system",
355 },
356 {
357 name: "ramdisk root binary",
358 ctx: &testModuleInstallPathContext{
359 baseModuleContext: baseModuleContext{
360 os: deviceTarget.Os,
361 target: deviceTarget,
362 },
363 inRamdisk: true,
364 inRoot: true,
365 },
366 in: []string{"my_test"},
367 out: "target/product/test_device/ramdisk/my_test",
368 partitionDir: "target/product/test_device/ramdisk",
369 },
370 {
371 name: "vendor_ramdisk binary",
372 ctx: &testModuleInstallPathContext{
373 baseModuleContext: baseModuleContext{
374 os: deviceTarget.Os,
375 target: deviceTarget,
376 },
377 inVendorRamdisk: true,
378 },
379 in: []string{"my_test"},
380 out: "target/product/test_device/vendor_ramdisk/system/my_test",
381 partitionDir: "target/product/test_device/vendor_ramdisk/system",
382 },
383 {
384 name: "vendor_ramdisk root binary",
385 ctx: &testModuleInstallPathContext{
386 baseModuleContext: baseModuleContext{
387 os: deviceTarget.Os,
388 target: deviceTarget,
389 },
390 inVendorRamdisk: true,
391 inRoot: true,
392 },
393 in: []string{"my_test"},
394 out: "target/product/test_device/vendor_ramdisk/my_test",
395 partitionDir: "target/product/test_device/vendor_ramdisk",
396 },
397 {
Dan Willemsen00269f22017-07-06 16:59:48 -0700398 name: "system native test binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100399 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700400 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800401 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700402 target: deviceTarget,
403 },
404 inData: true,
405 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900406 in: []string{"nativetest", "my_test"},
407 out: "target/product/test_device/data/nativetest/my_test",
408 partitionDir: "target/product/test_device/data",
Dan Willemsen00269f22017-07-06 16:59:48 -0700409 },
410 {
411 name: "vendor native test binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100412 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700413 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800414 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700415 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800416 earlyModuleContext: earlyModuleContext{
417 kind: socSpecificModule,
418 },
Jiyong Park2db76922017-11-08 16:03:48 +0900419 },
420 inData: true,
421 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900422 in: []string{"nativetest", "my_test"},
423 out: "target/product/test_device/data/nativetest/my_test",
424 partitionDir: "target/product/test_device/data",
Jiyong Park2db76922017-11-08 16:03:48 +0900425 },
426 {
427 name: "odm native test binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100428 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700429 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800430 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900431 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800432 earlyModuleContext: earlyModuleContext{
433 kind: deviceSpecificModule,
434 },
Jiyong Park2db76922017-11-08 16:03:48 +0900435 },
436 inData: true,
437 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900438 in: []string{"nativetest", "my_test"},
439 out: "target/product/test_device/data/nativetest/my_test",
440 partitionDir: "target/product/test_device/data",
Jiyong Park2db76922017-11-08 16:03:48 +0900441 },
442 {
Jaekyun Seok5cfbfbb2018-01-10 19:00:15 +0900443 name: "product native test binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100444 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700445 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800446 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900447 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800448 earlyModuleContext: earlyModuleContext{
449 kind: productSpecificModule,
450 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700451 },
452 inData: true,
453 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900454 in: []string{"nativetest", "my_test"},
455 out: "target/product/test_device/data/nativetest/my_test",
456 partitionDir: "target/product/test_device/data",
Dan Willemsen00269f22017-07-06 16:59:48 -0700457 },
458
459 {
Justin Yund5f6c822019-06-25 16:47:17 +0900460 name: "system_ext native test binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100461 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700462 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800463 os: deviceTarget.Os,
Dario Frenifd05a742018-05-29 13:28:54 +0100464 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800465 earlyModuleContext: earlyModuleContext{
466 kind: systemExtSpecificModule,
467 },
Dario Frenifd05a742018-05-29 13:28:54 +0100468 },
469 inData: true,
470 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900471 in: []string{"nativetest", "my_test"},
472 out: "target/product/test_device/data/nativetest/my_test",
473 partitionDir: "target/product/test_device/data",
Dario Frenifd05a742018-05-29 13:28:54 +0100474 },
475
476 {
Dan Willemsen00269f22017-07-06 16:59:48 -0700477 name: "sanitized system binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100478 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700479 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800480 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700481 target: deviceTarget,
482 },
483 inSanitizerDir: true,
484 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900485 in: []string{"bin", "my_test"},
486 out: "target/product/test_device/data/asan/system/bin/my_test",
487 partitionDir: "target/product/test_device/data/asan/system",
Dan Willemsen00269f22017-07-06 16:59:48 -0700488 },
489 {
490 name: "sanitized vendor binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100491 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700492 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800493 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700494 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800495 earlyModuleContext: earlyModuleContext{
496 kind: socSpecificModule,
497 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700498 },
499 inSanitizerDir: true,
500 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900501 in: []string{"bin", "my_test"},
502 out: "target/product/test_device/data/asan/vendor/bin/my_test",
503 partitionDir: "target/product/test_device/data/asan/vendor",
Dan Willemsen00269f22017-07-06 16:59:48 -0700504 },
Jiyong Park2db76922017-11-08 16:03:48 +0900505 {
506 name: "sanitized odm binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100507 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700508 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800509 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900510 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800511 earlyModuleContext: earlyModuleContext{
512 kind: deviceSpecificModule,
513 },
Jiyong Park2db76922017-11-08 16:03:48 +0900514 },
515 inSanitizerDir: true,
516 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900517 in: []string{"bin", "my_test"},
518 out: "target/product/test_device/data/asan/odm/bin/my_test",
519 partitionDir: "target/product/test_device/data/asan/odm",
Jiyong Park2db76922017-11-08 16:03:48 +0900520 },
521 {
Jaekyun Seok5cfbfbb2018-01-10 19:00:15 +0900522 name: "sanitized product binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100523 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700524 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800525 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900526 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800527 earlyModuleContext: earlyModuleContext{
528 kind: productSpecificModule,
529 },
Jiyong Park2db76922017-11-08 16:03:48 +0900530 },
531 inSanitizerDir: true,
532 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900533 in: []string{"bin", "my_test"},
534 out: "target/product/test_device/data/asan/product/bin/my_test",
535 partitionDir: "target/product/test_device/data/asan/product",
Jiyong Park2db76922017-11-08 16:03:48 +0900536 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700537
538 {
Justin Yund5f6c822019-06-25 16:47:17 +0900539 name: "sanitized system_ext binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100540 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700541 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800542 os: deviceTarget.Os,
Dario Frenifd05a742018-05-29 13:28:54 +0100543 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800544 earlyModuleContext: earlyModuleContext{
545 kind: systemExtSpecificModule,
546 },
Dario Frenifd05a742018-05-29 13:28:54 +0100547 },
548 inSanitizerDir: true,
549 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900550 in: []string{"bin", "my_test"},
551 out: "target/product/test_device/data/asan/system_ext/bin/my_test",
552 partitionDir: "target/product/test_device/data/asan/system_ext",
Dario Frenifd05a742018-05-29 13:28:54 +0100553 },
554
555 {
Dan Willemsen00269f22017-07-06 16:59:48 -0700556 name: "sanitized system native test binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100557 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700558 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800559 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700560 target: deviceTarget,
561 },
562 inData: true,
563 inSanitizerDir: true,
564 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900565 in: []string{"nativetest", "my_test"},
566 out: "target/product/test_device/data/asan/data/nativetest/my_test",
567 partitionDir: "target/product/test_device/data/asan/data",
Dan Willemsen00269f22017-07-06 16:59:48 -0700568 },
569 {
570 name: "sanitized vendor native test binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100571 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700572 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800573 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700574 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800575 earlyModuleContext: earlyModuleContext{
576 kind: socSpecificModule,
577 },
Jiyong Park2db76922017-11-08 16:03:48 +0900578 },
579 inData: true,
580 inSanitizerDir: true,
581 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900582 in: []string{"nativetest", "my_test"},
583 out: "target/product/test_device/data/asan/data/nativetest/my_test",
584 partitionDir: "target/product/test_device/data/asan/data",
Jiyong Park2db76922017-11-08 16:03:48 +0900585 },
586 {
587 name: "sanitized odm native test binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100588 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700589 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800590 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900591 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800592 earlyModuleContext: earlyModuleContext{
593 kind: deviceSpecificModule,
594 },
Jiyong Park2db76922017-11-08 16:03:48 +0900595 },
596 inData: true,
597 inSanitizerDir: true,
598 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900599 in: []string{"nativetest", "my_test"},
600 out: "target/product/test_device/data/asan/data/nativetest/my_test",
601 partitionDir: "target/product/test_device/data/asan/data",
Jiyong Park2db76922017-11-08 16:03:48 +0900602 },
603 {
Jaekyun Seok5cfbfbb2018-01-10 19:00:15 +0900604 name: "sanitized product native test binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100605 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700606 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800607 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900608 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800609 earlyModuleContext: earlyModuleContext{
610 kind: productSpecificModule,
611 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700612 },
613 inData: true,
614 inSanitizerDir: true,
615 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900616 in: []string{"nativetest", "my_test"},
617 out: "target/product/test_device/data/asan/data/nativetest/my_test",
618 partitionDir: "target/product/test_device/data/asan/data",
Dan Willemsen00269f22017-07-06 16:59:48 -0700619 },
Dario Frenifd05a742018-05-29 13:28:54 +0100620 {
Justin Yund5f6c822019-06-25 16:47:17 +0900621 name: "sanitized system_ext native test binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100622 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700623 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800624 os: deviceTarget.Os,
Dario Frenifd05a742018-05-29 13:28:54 +0100625 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800626 earlyModuleContext: earlyModuleContext{
627 kind: systemExtSpecificModule,
628 },
Dario Frenifd05a742018-05-29 13:28:54 +0100629 },
630 inData: true,
631 inSanitizerDir: true,
632 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900633 in: []string{"nativetest", "my_test"},
634 out: "target/product/test_device/data/asan/data/nativetest/my_test",
635 partitionDir: "target/product/test_device/data/asan/data",
Colin Cross6e359402020-02-10 15:29:54 -0800636 }, {
637 name: "device testcases",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100638 ctx: &testModuleInstallPathContext{
Colin Cross6e359402020-02-10 15:29:54 -0800639 baseModuleContext: baseModuleContext{
640 os: deviceTarget.Os,
641 target: deviceTarget,
642 },
643 inTestcases: true,
644 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900645 in: []string{"my_test", "my_test_bin"},
646 out: "target/product/test_device/testcases/my_test/my_test_bin",
647 partitionDir: "target/product/test_device/testcases",
Colin Cross6e359402020-02-10 15:29:54 -0800648 }, {
649 name: "host testcases",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100650 ctx: &testModuleInstallPathContext{
Colin Cross6e359402020-02-10 15:29:54 -0800651 baseModuleContext: baseModuleContext{
652 os: hostTarget.Os,
653 target: hostTarget,
654 },
655 inTestcases: true,
656 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900657 in: []string{"my_test", "my_test_bin"},
658 out: "host/linux-x86/testcases/my_test/my_test_bin",
659 partitionDir: "host/linux-x86/testcases",
Colin Cross6e359402020-02-10 15:29:54 -0800660 }, {
661 name: "forced host testcases",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100662 ctx: &testModuleInstallPathContext{
Colin Cross6e359402020-02-10 15:29:54 -0800663 baseModuleContext: baseModuleContext{
664 os: deviceTarget.Os,
665 target: deviceTarget,
666 },
667 inTestcases: true,
668 forceOS: &Linux,
Jiyong Park87788b52020-09-01 12:37:45 +0900669 forceArch: &X86,
Colin Cross6e359402020-02-10 15:29:54 -0800670 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900671 in: []string{"my_test", "my_test_bin"},
672 out: "host/linux-x86/testcases/my_test/my_test_bin",
673 partitionDir: "host/linux-x86/testcases",
Dario Frenifd05a742018-05-29 13:28:54 +0100674 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700675 }
676
677 for _, tc := range testCases {
678 t.Run(tc.name, func(t *testing.T) {
Colin Cross0ea8ba82019-06-06 14:33:29 -0700679 tc.ctx.baseModuleContext.config = testConfig
Dan Willemsen00269f22017-07-06 16:59:48 -0700680 output := PathForModuleInstall(tc.ctx, tc.in...)
681 if output.basePath.path != tc.out {
682 t.Errorf("unexpected path:\n got: %q\nwant: %q\n",
683 output.basePath.path,
684 tc.out)
685 }
Jiyong Park957bcd92020-10-20 18:23:33 +0900686 if output.partitionDir != tc.partitionDir {
687 t.Errorf("unexpected partitionDir:\n got: %q\nwant: %q\n",
688 output.partitionDir, tc.partitionDir)
689 }
Dan Willemsen00269f22017-07-06 16:59:48 -0700690 })
691 }
692}
Colin Cross5e6cfbe2017-11-03 15:20:35 -0700693
Inseob Kimd9580b82021-04-13 21:13:49 +0900694func TestPathForModuleInstallRecoveryAsBoot(t *testing.T) {
695 testConfig := pathTestConfig("")
696 testConfig.TestProductVariables.BoardUsesRecoveryAsBoot = proptools.BoolPtr(true)
697 testConfig.TestProductVariables.BoardMoveRecoveryResourcesToVendorBoot = proptools.BoolPtr(true)
698 deviceTarget := Target{Os: Android, Arch: Arch{ArchType: Arm64}}
699
700 testCases := []struct {
701 name string
702 ctx *testModuleInstallPathContext
703 in []string
704 out string
705 partitionDir string
706 }{
707 {
708 name: "ramdisk binary",
709 ctx: &testModuleInstallPathContext{
710 baseModuleContext: baseModuleContext{
711 os: deviceTarget.Os,
712 target: deviceTarget,
713 },
714 inRamdisk: true,
715 inRoot: true,
716 },
717 in: []string{"my_test"},
718 out: "target/product/test_device/recovery/root/first_stage_ramdisk/my_test",
719 partitionDir: "target/product/test_device/recovery/root/first_stage_ramdisk",
720 },
721
722 {
723 name: "vendor_ramdisk binary",
724 ctx: &testModuleInstallPathContext{
725 baseModuleContext: baseModuleContext{
726 os: deviceTarget.Os,
727 target: deviceTarget,
728 },
729 inVendorRamdisk: true,
730 inRoot: true,
731 },
732 in: []string{"my_test"},
733 out: "target/product/test_device/vendor_ramdisk/first_stage_ramdisk/my_test",
734 partitionDir: "target/product/test_device/vendor_ramdisk/first_stage_ramdisk",
735 },
736 }
737
738 for _, tc := range testCases {
739 t.Run(tc.name, func(t *testing.T) {
740 tc.ctx.baseModuleContext.config = testConfig
741 output := PathForModuleInstall(tc.ctx, tc.in...)
742 if output.basePath.path != tc.out {
743 t.Errorf("unexpected path:\n got: %q\nwant: %q\n",
744 output.basePath.path,
745 tc.out)
746 }
747 if output.partitionDir != tc.partitionDir {
748 t.Errorf("unexpected partitionDir:\n got: %q\nwant: %q\n",
749 output.partitionDir, tc.partitionDir)
750 }
751 })
752 }
753}
754
Jiyong Park957bcd92020-10-20 18:23:33 +0900755func TestBaseDirForInstallPath(t *testing.T) {
756 testConfig := pathTestConfig("")
757 deviceTarget := Target{Os: Android, Arch: Arch{ArchType: Arm64}}
758
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100759 ctx := &testModuleInstallPathContext{
Jiyong Park957bcd92020-10-20 18:23:33 +0900760 baseModuleContext: baseModuleContext{
761 os: deviceTarget.Os,
762 target: deviceTarget,
763 },
764 }
765 ctx.baseModuleContext.config = testConfig
766
767 actual := PathForModuleInstall(ctx, "foo", "bar")
768 expectedBaseDir := "target/product/test_device/system"
769 if actual.partitionDir != expectedBaseDir {
770 t.Errorf("unexpected partitionDir:\n got: %q\nwant: %q\n", actual.partitionDir, expectedBaseDir)
771 }
772 expectedRelPath := "foo/bar"
773 if actual.Rel() != expectedRelPath {
774 t.Errorf("unexpected Rel():\n got: %q\nwant: %q\n", actual.Rel(), expectedRelPath)
775 }
776
777 actualAfterJoin := actual.Join(ctx, "baz")
778 // partitionDir is preserved even after joining
779 if actualAfterJoin.partitionDir != expectedBaseDir {
780 t.Errorf("unexpected partitionDir after joining:\n got: %q\nwant: %q\n", actualAfterJoin.partitionDir, expectedBaseDir)
781 }
782 // Rel() is updated though
783 expectedRelAfterJoin := "baz"
784 if actualAfterJoin.Rel() != expectedRelAfterJoin {
785 t.Errorf("unexpected Rel() after joining:\n got: %q\nwant: %q\n", actualAfterJoin.Rel(), expectedRelAfterJoin)
786 }
787}
788
Colin Cross5e6cfbe2017-11-03 15:20:35 -0700789func TestDirectorySortedPaths(t *testing.T) {
Colin Cross98be1bb2019-12-13 20:41:13 -0800790 config := TestConfig("out", nil, "", map[string][]byte{
791 "Android.bp": nil,
792 "a.txt": nil,
793 "a/txt": nil,
794 "a/b/c": nil,
795 "a/b/d": nil,
796 "b": nil,
797 "b/b.txt": nil,
798 "a/a.txt": nil,
Colin Cross07e51612019-03-05 12:46:40 -0800799 })
800
Colin Cross98be1bb2019-12-13 20:41:13 -0800801 ctx := PathContextForTesting(config)
802
Colin Cross5e6cfbe2017-11-03 15:20:35 -0700803 makePaths := func() Paths {
804 return Paths{
Colin Cross07e51612019-03-05 12:46:40 -0800805 PathForSource(ctx, "a.txt"),
806 PathForSource(ctx, "a/txt"),
807 PathForSource(ctx, "a/b/c"),
808 PathForSource(ctx, "a/b/d"),
809 PathForSource(ctx, "b"),
810 PathForSource(ctx, "b/b.txt"),
811 PathForSource(ctx, "a/a.txt"),
Colin Cross5e6cfbe2017-11-03 15:20:35 -0700812 }
813 }
814
815 expected := []string{
816 "a.txt",
817 "a/a.txt",
818 "a/b/c",
819 "a/b/d",
820 "a/txt",
821 "b",
822 "b/b.txt",
823 }
824
825 paths := makePaths()
Colin Crossa140bb02018-04-17 10:52:26 -0700826 reversePaths := ReversePaths(paths)
Colin Cross5e6cfbe2017-11-03 15:20:35 -0700827
828 sortedPaths := PathsToDirectorySortedPaths(paths)
829 reverseSortedPaths := PathsToDirectorySortedPaths(reversePaths)
830
831 if !reflect.DeepEqual(Paths(sortedPaths).Strings(), expected) {
832 t.Fatalf("sorted paths:\n %#v\n != \n %#v", paths.Strings(), expected)
833 }
834
835 if !reflect.DeepEqual(Paths(reverseSortedPaths).Strings(), expected) {
836 t.Fatalf("sorted reversed paths:\n %#v\n !=\n %#v", reversePaths.Strings(), expected)
837 }
838
839 expectedA := []string{
840 "a/a.txt",
841 "a/b/c",
842 "a/b/d",
843 "a/txt",
844 }
845
846 inA := sortedPaths.PathsInDirectory("a")
847 if !reflect.DeepEqual(inA.Strings(), expectedA) {
848 t.Errorf("FilesInDirectory(a):\n %#v\n != \n %#v", inA.Strings(), expectedA)
849 }
850
851 expectedA_B := []string{
852 "a/b/c",
853 "a/b/d",
854 }
855
856 inA_B := sortedPaths.PathsInDirectory("a/b")
857 if !reflect.DeepEqual(inA_B.Strings(), expectedA_B) {
858 t.Errorf("FilesInDirectory(a/b):\n %#v\n != \n %#v", inA_B.Strings(), expectedA_B)
859 }
860
861 expectedB := []string{
862 "b/b.txt",
863 }
864
865 inB := sortedPaths.PathsInDirectory("b")
866 if !reflect.DeepEqual(inB.Strings(), expectedB) {
867 t.Errorf("FilesInDirectory(b):\n %#v\n != \n %#v", inA.Strings(), expectedA)
868 }
869}
Colin Cross43f08db2018-11-12 10:13:39 -0800870
871func TestMaybeRel(t *testing.T) {
872 testCases := []struct {
873 name string
874 base string
875 target string
876 out string
877 isRel bool
878 }{
879 {
880 name: "normal",
881 base: "a/b/c",
882 target: "a/b/c/d",
883 out: "d",
884 isRel: true,
885 },
886 {
887 name: "parent",
888 base: "a/b/c/d",
889 target: "a/b/c",
890 isRel: false,
891 },
892 {
893 name: "not relative",
894 base: "a/b",
895 target: "c/d",
896 isRel: false,
897 },
898 {
899 name: "abs1",
900 base: "/a",
901 target: "a",
902 isRel: false,
903 },
904 {
905 name: "abs2",
906 base: "a",
907 target: "/a",
908 isRel: false,
909 },
910 }
911
912 for _, testCase := range testCases {
913 t.Run(testCase.name, func(t *testing.T) {
914 ctx := &configErrorWrapper{}
915 out, isRel := MaybeRel(ctx, testCase.base, testCase.target)
916 if len(ctx.errors) > 0 {
917 t.Errorf("MaybeRel(..., %s, %s) reported unexpected errors %v",
918 testCase.base, testCase.target, ctx.errors)
919 }
920 if isRel != testCase.isRel || out != testCase.out {
921 t.Errorf("MaybeRel(..., %s, %s) want %v, %v got %v, %v",
922 testCase.base, testCase.target, testCase.out, testCase.isRel, out, isRel)
923 }
924 })
925 }
926}
Colin Cross7b3dcc32019-01-24 13:14:39 -0800927
928func TestPathForSource(t *testing.T) {
929 testCases := []struct {
930 name string
931 buildDir string
932 src string
933 err string
934 }{
935 {
936 name: "normal",
937 buildDir: "out",
938 src: "a/b/c",
939 },
940 {
941 name: "abs",
942 buildDir: "out",
943 src: "/a/b/c",
944 err: "is outside directory",
945 },
946 {
947 name: "in out dir",
948 buildDir: "out",
949 src: "out/a/b/c",
950 err: "is in output",
951 },
952 }
953
954 funcs := []struct {
955 name string
956 f func(ctx PathContext, pathComponents ...string) (SourcePath, error)
957 }{
958 {"pathForSource", pathForSource},
959 {"safePathForSource", safePathForSource},
960 }
961
962 for _, f := range funcs {
963 t.Run(f.name, func(t *testing.T) {
964 for _, test := range testCases {
965 t.Run(test.name, func(t *testing.T) {
Colin Cross98be1bb2019-12-13 20:41:13 -0800966 testConfig := pathTestConfig(test.buildDir)
Colin Cross7b3dcc32019-01-24 13:14:39 -0800967 ctx := &configErrorWrapper{config: testConfig}
968 _, err := f.f(ctx, test.src)
969 if len(ctx.errors) > 0 {
970 t.Fatalf("unexpected errors %v", ctx.errors)
971 }
972 if err != nil {
973 if test.err == "" {
974 t.Fatalf("unexpected error %q", err.Error())
975 } else if !strings.Contains(err.Error(), test.err) {
976 t.Fatalf("incorrect error, want substring %q got %q", test.err, err.Error())
977 }
978 } else {
979 if test.err != "" {
980 t.Fatalf("missing error %q", test.err)
981 }
982 }
983 })
984 }
985 })
986 }
987}
Colin Cross8854a5a2019-02-11 14:14:16 -0800988
Colin Cross8a497952019-03-05 22:25:09 -0800989type pathForModuleSrcTestModule struct {
Colin Cross937664a2019-03-06 10:17:32 -0800990 ModuleBase
991 props struct {
992 Srcs []string `android:"path"`
993 Exclude_srcs []string `android:"path"`
Colin Cross8a497952019-03-05 22:25:09 -0800994
995 Src *string `android:"path"`
Colin Crossba71a3f2019-03-18 12:12:48 -0700996
997 Module_handles_missing_deps bool
Colin Cross937664a2019-03-06 10:17:32 -0800998 }
999
Colin Cross8a497952019-03-05 22:25:09 -08001000 src string
1001 rel string
1002
1003 srcs []string
Colin Cross937664a2019-03-06 10:17:32 -08001004 rels []string
Colin Cross8a497952019-03-05 22:25:09 -08001005
1006 missingDeps []string
Colin Cross937664a2019-03-06 10:17:32 -08001007}
1008
Colin Cross8a497952019-03-05 22:25:09 -08001009func pathForModuleSrcTestModuleFactory() Module {
1010 module := &pathForModuleSrcTestModule{}
Colin Cross937664a2019-03-06 10:17:32 -08001011 module.AddProperties(&module.props)
1012 InitAndroidModule(module)
1013 return module
1014}
1015
Colin Cross8a497952019-03-05 22:25:09 -08001016func (p *pathForModuleSrcTestModule) GenerateAndroidBuildActions(ctx ModuleContext) {
Colin Crossba71a3f2019-03-18 12:12:48 -07001017 var srcs Paths
1018 if p.props.Module_handles_missing_deps {
1019 srcs, p.missingDeps = PathsAndMissingDepsForModuleSrcExcludes(ctx, p.props.Srcs, p.props.Exclude_srcs)
1020 } else {
1021 srcs = PathsForModuleSrcExcludes(ctx, p.props.Srcs, p.props.Exclude_srcs)
1022 }
Colin Cross8a497952019-03-05 22:25:09 -08001023 p.srcs = srcs.Strings()
Colin Cross937664a2019-03-06 10:17:32 -08001024
Colin Cross8a497952019-03-05 22:25:09 -08001025 for _, src := range srcs {
Colin Cross937664a2019-03-06 10:17:32 -08001026 p.rels = append(p.rels, src.Rel())
1027 }
Colin Cross8a497952019-03-05 22:25:09 -08001028
1029 if p.props.Src != nil {
1030 src := PathForModuleSrc(ctx, *p.props.Src)
1031 if src != nil {
1032 p.src = src.String()
1033 p.rel = src.Rel()
1034 }
1035 }
1036
Colin Crossba71a3f2019-03-18 12:12:48 -07001037 if !p.props.Module_handles_missing_deps {
1038 p.missingDeps = ctx.GetMissingDependencies()
1039 }
Colin Cross6c4f21f2019-06-06 15:41:36 -07001040
1041 ctx.Build(pctx, BuildParams{
1042 Rule: Touch,
1043 Output: PathForModuleOut(ctx, "output"),
1044 })
Colin Cross8a497952019-03-05 22:25:09 -08001045}
1046
Colin Cross41955e82019-05-29 14:40:35 -07001047type pathForModuleSrcOutputFileProviderModule struct {
1048 ModuleBase
1049 props struct {
1050 Outs []string
1051 Tagged []string
1052 }
1053
1054 outs Paths
1055 tagged Paths
1056}
1057
1058func pathForModuleSrcOutputFileProviderModuleFactory() Module {
1059 module := &pathForModuleSrcOutputFileProviderModule{}
1060 module.AddProperties(&module.props)
1061 InitAndroidModule(module)
1062 return module
1063}
1064
1065func (p *pathForModuleSrcOutputFileProviderModule) GenerateAndroidBuildActions(ctx ModuleContext) {
1066 for _, out := range p.props.Outs {
1067 p.outs = append(p.outs, PathForModuleOut(ctx, out))
1068 }
1069
1070 for _, tagged := range p.props.Tagged {
1071 p.tagged = append(p.tagged, PathForModuleOut(ctx, tagged))
1072 }
1073}
1074
1075func (p *pathForModuleSrcOutputFileProviderModule) OutputFiles(tag string) (Paths, error) {
1076 switch tag {
1077 case "":
1078 return p.outs, nil
1079 case ".tagged":
1080 return p.tagged, nil
1081 default:
1082 return nil, fmt.Errorf("unsupported tag %q", tag)
1083 }
1084}
1085
Colin Cross8a497952019-03-05 22:25:09 -08001086type pathForModuleSrcTestCase struct {
1087 name string
1088 bp string
1089 srcs []string
1090 rels []string
1091 src string
1092 rel string
1093}
1094
Paul Duffin54054682021-03-16 21:11:42 +00001095func testPathForModuleSrc(t *testing.T, tests []pathForModuleSrcTestCase) {
Colin Cross8a497952019-03-05 22:25:09 -08001096 for _, test := range tests {
1097 t.Run(test.name, func(t *testing.T) {
Colin Cross8a497952019-03-05 22:25:09 -08001098 fgBp := `
1099 filegroup {
1100 name: "a",
1101 srcs: ["src/a"],
1102 }
1103 `
1104
Colin Cross41955e82019-05-29 14:40:35 -07001105 ofpBp := `
1106 output_file_provider {
1107 name: "b",
1108 outs: ["gen/b"],
1109 tagged: ["gen/c"],
1110 }
1111 `
1112
Paul Duffin54054682021-03-16 21:11:42 +00001113 mockFS := MockFS{
Colin Cross8a497952019-03-05 22:25:09 -08001114 "fg/Android.bp": []byte(fgBp),
1115 "foo/Android.bp": []byte(test.bp),
Colin Cross41955e82019-05-29 14:40:35 -07001116 "ofp/Android.bp": []byte(ofpBp),
Colin Cross8a497952019-03-05 22:25:09 -08001117 "fg/src/a": nil,
1118 "foo/src/b": nil,
1119 "foo/src/c": nil,
1120 "foo/src/d": nil,
1121 "foo/src/e/e": nil,
1122 "foo/src_special/$": nil,
1123 }
1124
Paul Duffin30ac3e72021-03-20 00:36:14 +00001125 result := GroupFixturePreparers(
Paul Duffin54054682021-03-16 21:11:42 +00001126 FixtureRegisterWithContext(func(ctx RegistrationContext) {
1127 ctx.RegisterModuleType("test", pathForModuleSrcTestModuleFactory)
1128 ctx.RegisterModuleType("output_file_provider", pathForModuleSrcOutputFileProviderModuleFactory)
1129 ctx.RegisterModuleType("filegroup", FileGroupFactory)
1130 }),
1131 mockFS.AddToFixture(),
Paul Duffin30ac3e72021-03-20 00:36:14 +00001132 ).RunTest(t)
Colin Cross8a497952019-03-05 22:25:09 -08001133
Paul Duffin54054682021-03-16 21:11:42 +00001134 m := result.ModuleForTests("foo", "").Module().(*pathForModuleSrcTestModule)
Colin Crossae8600b2020-10-29 17:09:13 -07001135
Paul Duffin54054682021-03-16 21:11:42 +00001136 AssertStringPathsRelativeToTopEquals(t, "srcs", result.Config, test.srcs, m.srcs)
1137 AssertStringPathsRelativeToTopEquals(t, "rels", result.Config, test.rels, m.rels)
1138 AssertStringPathRelativeToTopEquals(t, "src", result.Config, test.src, m.src)
1139 AssertStringPathRelativeToTopEquals(t, "rel", result.Config, test.rel, m.rel)
Colin Cross8a497952019-03-05 22:25:09 -08001140 })
1141 }
Colin Cross937664a2019-03-06 10:17:32 -08001142}
1143
Colin Cross8a497952019-03-05 22:25:09 -08001144func TestPathsForModuleSrc(t *testing.T) {
1145 tests := []pathForModuleSrcTestCase{
Colin Cross937664a2019-03-06 10:17:32 -08001146 {
1147 name: "path",
1148 bp: `
1149 test {
1150 name: "foo",
1151 srcs: ["src/b"],
1152 }`,
1153 srcs: []string{"foo/src/b"},
1154 rels: []string{"src/b"},
1155 },
1156 {
1157 name: "glob",
1158 bp: `
1159 test {
1160 name: "foo",
1161 srcs: [
1162 "src/*",
1163 "src/e/*",
1164 ],
1165 }`,
1166 srcs: []string{"foo/src/b", "foo/src/c", "foo/src/d", "foo/src/e/e"},
1167 rels: []string{"src/b", "src/c", "src/d", "src/e/e"},
1168 },
1169 {
1170 name: "recursive glob",
1171 bp: `
1172 test {
1173 name: "foo",
1174 srcs: ["src/**/*"],
1175 }`,
1176 srcs: []string{"foo/src/b", "foo/src/c", "foo/src/d", "foo/src/e/e"},
1177 rels: []string{"src/b", "src/c", "src/d", "src/e/e"},
1178 },
1179 {
1180 name: "filegroup",
1181 bp: `
1182 test {
1183 name: "foo",
1184 srcs: [":a"],
1185 }`,
1186 srcs: []string{"fg/src/a"},
1187 rels: []string{"src/a"},
1188 },
1189 {
Colin Cross41955e82019-05-29 14:40:35 -07001190 name: "output file provider",
1191 bp: `
1192 test {
1193 name: "foo",
1194 srcs: [":b"],
1195 }`,
Paul Duffin54054682021-03-16 21:11:42 +00001196 srcs: []string{"out/soong/.intermediates/ofp/b/gen/b"},
Colin Cross41955e82019-05-29 14:40:35 -07001197 rels: []string{"gen/b"},
1198 },
1199 {
1200 name: "output file provider tagged",
1201 bp: `
1202 test {
1203 name: "foo",
1204 srcs: [":b{.tagged}"],
1205 }`,
Paul Duffin54054682021-03-16 21:11:42 +00001206 srcs: []string{"out/soong/.intermediates/ofp/b/gen/c"},
Colin Cross41955e82019-05-29 14:40:35 -07001207 rels: []string{"gen/c"},
1208 },
1209 {
Jooyung Han7607dd32020-07-05 10:23:14 +09001210 name: "output file provider with exclude",
1211 bp: `
1212 test {
1213 name: "foo",
1214 srcs: [":b", ":c"],
1215 exclude_srcs: [":c"]
1216 }
1217 output_file_provider {
1218 name: "c",
1219 outs: ["gen/c"],
1220 }`,
Paul Duffin54054682021-03-16 21:11:42 +00001221 srcs: []string{"out/soong/.intermediates/ofp/b/gen/b"},
Jooyung Han7607dd32020-07-05 10:23:14 +09001222 rels: []string{"gen/b"},
1223 },
1224 {
Colin Cross937664a2019-03-06 10:17:32 -08001225 name: "special characters glob",
1226 bp: `
1227 test {
1228 name: "foo",
1229 srcs: ["src_special/*"],
1230 }`,
1231 srcs: []string{"foo/src_special/$"},
1232 rels: []string{"src_special/$"},
1233 },
1234 }
1235
Paul Duffin54054682021-03-16 21:11:42 +00001236 testPathForModuleSrc(t, tests)
Colin Cross41955e82019-05-29 14:40:35 -07001237}
1238
1239func TestPathForModuleSrc(t *testing.T) {
Colin Cross8a497952019-03-05 22:25:09 -08001240 tests := []pathForModuleSrcTestCase{
1241 {
1242 name: "path",
1243 bp: `
1244 test {
1245 name: "foo",
1246 src: "src/b",
1247 }`,
1248 src: "foo/src/b",
1249 rel: "src/b",
1250 },
1251 {
1252 name: "glob",
1253 bp: `
1254 test {
1255 name: "foo",
1256 src: "src/e/*",
1257 }`,
1258 src: "foo/src/e/e",
1259 rel: "src/e/e",
1260 },
1261 {
1262 name: "filegroup",
1263 bp: `
1264 test {
1265 name: "foo",
1266 src: ":a",
1267 }`,
1268 src: "fg/src/a",
1269 rel: "src/a",
1270 },
1271 {
Colin Cross41955e82019-05-29 14:40:35 -07001272 name: "output file provider",
1273 bp: `
1274 test {
1275 name: "foo",
1276 src: ":b",
1277 }`,
Paul Duffin54054682021-03-16 21:11:42 +00001278 src: "out/soong/.intermediates/ofp/b/gen/b",
Colin Cross41955e82019-05-29 14:40:35 -07001279 rel: "gen/b",
1280 },
1281 {
1282 name: "output file provider tagged",
1283 bp: `
1284 test {
1285 name: "foo",
1286 src: ":b{.tagged}",
1287 }`,
Paul Duffin54054682021-03-16 21:11:42 +00001288 src: "out/soong/.intermediates/ofp/b/gen/c",
Colin Cross41955e82019-05-29 14:40:35 -07001289 rel: "gen/c",
1290 },
1291 {
Colin Cross8a497952019-03-05 22:25:09 -08001292 name: "special characters glob",
1293 bp: `
1294 test {
1295 name: "foo",
1296 src: "src_special/*",
1297 }`,
1298 src: "foo/src_special/$",
1299 rel: "src_special/$",
1300 },
1301 }
1302
Paul Duffin54054682021-03-16 21:11:42 +00001303 testPathForModuleSrc(t, tests)
Colin Cross8a497952019-03-05 22:25:09 -08001304}
Colin Cross937664a2019-03-06 10:17:32 -08001305
Colin Cross8a497952019-03-05 22:25:09 -08001306func TestPathsForModuleSrc_AllowMissingDependencies(t *testing.T) {
Colin Cross8a497952019-03-05 22:25:09 -08001307 bp := `
1308 test {
1309 name: "foo",
1310 srcs: [":a"],
1311 exclude_srcs: [":b"],
1312 src: ":c",
1313 }
Colin Crossba71a3f2019-03-18 12:12:48 -07001314
1315 test {
1316 name: "bar",
1317 srcs: [":d"],
1318 exclude_srcs: [":e"],
1319 module_handles_missing_deps: true,
1320 }
Colin Cross8a497952019-03-05 22:25:09 -08001321 `
1322
Paul Duffin30ac3e72021-03-20 00:36:14 +00001323 result := GroupFixturePreparers(
Paul Duffin54054682021-03-16 21:11:42 +00001324 PrepareForTestWithAllowMissingDependencies,
1325 FixtureRegisterWithContext(func(ctx RegistrationContext) {
1326 ctx.RegisterModuleType("test", pathForModuleSrcTestModuleFactory)
1327 }),
1328 FixtureWithRootAndroidBp(bp),
Paul Duffin30ac3e72021-03-20 00:36:14 +00001329 ).RunTest(t)
Colin Cross8a497952019-03-05 22:25:09 -08001330
Paul Duffin54054682021-03-16 21:11:42 +00001331 foo := result.ModuleForTests("foo", "").Module().(*pathForModuleSrcTestModule)
Colin Cross8a497952019-03-05 22:25:09 -08001332
Paul Duffin54054682021-03-16 21:11:42 +00001333 AssertArrayString(t, "foo missing deps", []string{"a", "b", "c"}, foo.missingDeps)
1334 AssertArrayString(t, "foo srcs", []string{}, foo.srcs)
1335 AssertStringEquals(t, "foo src", "", foo.src)
Colin Cross98be1bb2019-12-13 20:41:13 -08001336
Paul Duffin54054682021-03-16 21:11:42 +00001337 bar := result.ModuleForTests("bar", "").Module().(*pathForModuleSrcTestModule)
Colin Cross98be1bb2019-12-13 20:41:13 -08001338
Paul Duffin54054682021-03-16 21:11:42 +00001339 AssertArrayString(t, "bar missing deps", []string{"d", "e"}, bar.missingDeps)
1340 AssertArrayString(t, "bar srcs", []string{}, bar.srcs)
Colin Cross937664a2019-03-06 10:17:32 -08001341}
1342
Paul Duffin567465d2021-03-16 01:21:34 +00001343func TestPathRelativeToTop(t *testing.T) {
1344 testConfig := pathTestConfig("/tmp/build/top")
1345 deviceTarget := Target{Os: Android, Arch: Arch{ArchType: Arm64}}
1346
1347 ctx := &testModuleInstallPathContext{
1348 baseModuleContext: baseModuleContext{
1349 os: deviceTarget.Os,
1350 target: deviceTarget,
1351 },
1352 }
1353 ctx.baseModuleContext.config = testConfig
1354
1355 t.Run("install for soong", func(t *testing.T) {
1356 p := PathForModuleInstall(ctx, "install/path")
1357 AssertPathRelativeToTopEquals(t, "install path for soong", "out/soong/target/product/test_device/system/install/path", p)
1358 })
1359 t.Run("install for make", func(t *testing.T) {
1360 p := PathForModuleInstall(ctx, "install/path").ToMakePath()
1361 AssertPathRelativeToTopEquals(t, "install path for make", "out/target/product/test_device/system/install/path", p)
1362 })
1363 t.Run("output", func(t *testing.T) {
1364 p := PathForOutput(ctx, "output/path")
1365 AssertPathRelativeToTopEquals(t, "output path", "out/soong/output/path", p)
1366 })
1367 t.Run("source", func(t *testing.T) {
1368 p := PathForSource(ctx, "source/path")
1369 AssertPathRelativeToTopEquals(t, "source path", "source/path", p)
1370 })
1371 t.Run("mixture", func(t *testing.T) {
1372 paths := Paths{
1373 PathForModuleInstall(ctx, "install/path"),
1374 PathForModuleInstall(ctx, "install/path").ToMakePath(),
1375 PathForOutput(ctx, "output/path"),
1376 PathForSource(ctx, "source/path"),
1377 }
1378
1379 expected := []string{
1380 "out/soong/target/product/test_device/system/install/path",
1381 "out/target/product/test_device/system/install/path",
1382 "out/soong/output/path",
1383 "source/path",
1384 }
1385 AssertPathsRelativeToTopEquals(t, "mixture", expected, paths)
1386 })
1387}
1388
Colin Cross8854a5a2019-02-11 14:14:16 -08001389func ExampleOutputPath_ReplaceExtension() {
1390 ctx := &configErrorWrapper{
Colin Cross98be1bb2019-12-13 20:41:13 -08001391 config: TestConfig("out", nil, "", nil),
Colin Cross8854a5a2019-02-11 14:14:16 -08001392 }
Colin Cross2cdd5df2019-02-25 10:25:24 -08001393 p := PathForOutput(ctx, "system/framework").Join(ctx, "boot.art")
Colin Cross8854a5a2019-02-11 14:14:16 -08001394 p2 := p.ReplaceExtension(ctx, "oat")
1395 fmt.Println(p, p2)
Colin Cross2cdd5df2019-02-25 10:25:24 -08001396 fmt.Println(p.Rel(), p2.Rel())
Colin Cross8854a5a2019-02-11 14:14:16 -08001397
1398 // Output:
1399 // out/system/framework/boot.art out/system/framework/boot.oat
Colin Cross2cdd5df2019-02-25 10:25:24 -08001400 // boot.art boot.oat
Colin Cross8854a5a2019-02-11 14:14:16 -08001401}
Colin Cross40e33732019-02-15 11:08:35 -08001402
Colin Cross41b46762020-10-09 19:26:32 -07001403func ExampleOutputPath_InSameDir() {
Colin Cross40e33732019-02-15 11:08:35 -08001404 ctx := &configErrorWrapper{
Colin Cross98be1bb2019-12-13 20:41:13 -08001405 config: TestConfig("out", nil, "", nil),
Colin Cross40e33732019-02-15 11:08:35 -08001406 }
Colin Cross2cdd5df2019-02-25 10:25:24 -08001407 p := PathForOutput(ctx, "system/framework").Join(ctx, "boot.art")
Colin Cross40e33732019-02-15 11:08:35 -08001408 p2 := p.InSameDir(ctx, "oat", "arm", "boot.vdex")
1409 fmt.Println(p, p2)
Colin Cross2cdd5df2019-02-25 10:25:24 -08001410 fmt.Println(p.Rel(), p2.Rel())
Colin Cross40e33732019-02-15 11:08:35 -08001411
1412 // Output:
1413 // out/system/framework/boot.art out/system/framework/oat/arm/boot.vdex
Colin Cross2cdd5df2019-02-25 10:25:24 -08001414 // boot.art oat/arm/boot.vdex
Colin Cross40e33732019-02-15 11:08:35 -08001415}
Colin Cross27027c72020-02-28 15:34:17 -08001416
1417func BenchmarkFirstUniquePaths(b *testing.B) {
1418 implementations := []struct {
1419 name string
1420 f func(Paths) Paths
1421 }{
1422 {
1423 name: "list",
1424 f: firstUniquePathsList,
1425 },
1426 {
1427 name: "map",
1428 f: firstUniquePathsMap,
1429 },
1430 }
1431 const maxSize = 1024
1432 uniquePaths := make(Paths, maxSize)
1433 for i := range uniquePaths {
1434 uniquePaths[i] = PathForTesting(strconv.Itoa(i))
1435 }
1436 samePath := make(Paths, maxSize)
1437 for i := range samePath {
1438 samePath[i] = uniquePaths[0]
1439 }
1440
1441 f := func(b *testing.B, imp func(Paths) Paths, paths Paths) {
1442 for i := 0; i < b.N; i++ {
1443 b.ReportAllocs()
1444 paths = append(Paths(nil), paths...)
1445 imp(paths)
1446 }
1447 }
1448
1449 for n := 1; n <= maxSize; n <<= 1 {
1450 b.Run(strconv.Itoa(n), func(b *testing.B) {
1451 for _, implementation := range implementations {
1452 b.Run(implementation.name, func(b *testing.B) {
1453 b.Run("same", func(b *testing.B) {
1454 f(b, implementation.f, samePath[:n])
1455 })
1456 b.Run("unique", func(b *testing.B) {
1457 f(b, implementation.f, uniquePaths[:n])
1458 })
1459 })
1460 }
1461 })
1462 }
1463}