blob: 3cad8529d77e5866ecd940ebd91e073cf1652615 [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
Martin Stjernholmc32dd1c2021-09-15 02:39:00 +0100140 checkInvalidOptionalPath(t, path, "unknown")
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700141
142 path = OptionalPathForPath(nil)
Martin Stjernholmc32dd1c2021-09-15 02:39:00 +0100143 checkInvalidOptionalPath(t, path, "unknown")
144
145 path = InvalidOptionalPath("foo")
146 checkInvalidOptionalPath(t, path, "foo")
147
148 path = InvalidOptionalPath("")
149 checkInvalidOptionalPath(t, path, "unknown")
Paul Duffinef081852021-05-13 11:11:15 +0100150
151 path = OptionalPathForPath(PathForTesting("path"))
152 checkValidOptionalPath(t, path, "path")
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700153}
154
Martin Stjernholmc32dd1c2021-09-15 02:39:00 +0100155func checkInvalidOptionalPath(t *testing.T, path OptionalPath, expectedInvalidReason string) {
Colin Crossdc75ae72018-02-22 13:48:13 -0800156 t.Helper()
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700157 if path.Valid() {
Martin Stjernholmc32dd1c2021-09-15 02:39:00 +0100158 t.Errorf("Invalid OptionalPath should not be valid")
159 }
160 if path.InvalidReason() != expectedInvalidReason {
161 t.Errorf("Wrong invalid reason: expected %q, got %q", expectedInvalidReason, path.InvalidReason())
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700162 }
163 if path.String() != "" {
Martin Stjernholmc32dd1c2021-09-15 02:39:00 +0100164 t.Errorf("Invalid OptionalPath String() should return \"\", not %q", path.String())
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700165 }
Paul Duffinef081852021-05-13 11:11:15 +0100166 paths := path.AsPaths()
167 if len(paths) != 0 {
Martin Stjernholmc32dd1c2021-09-15 02:39:00 +0100168 t.Errorf("Invalid OptionalPath AsPaths() should return empty Paths, not %q", paths)
Paul Duffinef081852021-05-13 11:11:15 +0100169 }
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700170 defer func() {
171 if r := recover(); r == nil {
172 t.Errorf("Expected a panic when calling Path() on an uninitialized OptionalPath")
173 }
174 }()
175 path.Path()
176}
177
Paul Duffinef081852021-05-13 11:11:15 +0100178func checkValidOptionalPath(t *testing.T, path OptionalPath, expectedString string) {
179 t.Helper()
180 if !path.Valid() {
181 t.Errorf("Initialized OptionalPath should not be invalid")
182 }
Martin Stjernholmc32dd1c2021-09-15 02:39:00 +0100183 if path.InvalidReason() != "" {
184 t.Errorf("Initialized OptionalPath should not have an invalid reason, got: %q", path.InvalidReason())
185 }
Paul Duffinef081852021-05-13 11:11:15 +0100186 if path.String() != expectedString {
187 t.Errorf("Initialized OptionalPath String() should return %q, not %q", expectedString, path.String())
188 }
189 paths := path.AsPaths()
190 if len(paths) != 1 {
191 t.Errorf("Initialized OptionalPath AsPaths() should return Paths with length 1, not %q", paths)
192 }
193 path.Path()
194}
195
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700196func check(t *testing.T, testType, testString string,
197 got interface{}, err []error,
198 expected interface{}, expectedErr []error) {
Colin Crossdc75ae72018-02-22 13:48:13 -0800199 t.Helper()
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700200
201 printedTestCase := false
202 e := func(s string, expected, got interface{}) {
Colin Crossdc75ae72018-02-22 13:48:13 -0800203 t.Helper()
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700204 if !printedTestCase {
205 t.Errorf("test case %s: %s", testType, testString)
206 printedTestCase = true
207 }
208 t.Errorf("incorrect %s", s)
209 t.Errorf(" expected: %s", p(expected))
210 t.Errorf(" got: %s", p(got))
211 }
212
213 if !reflect.DeepEqual(expectedErr, err) {
214 e("errors:", expectedErr, err)
215 }
216
217 if !reflect.DeepEqual(expected, got) {
218 e("output:", expected, got)
219 }
220}
221
222func p(in interface{}) string {
223 if v, ok := in.([]interface{}); ok {
224 s := make([]string, len(v))
225 for i := range v {
226 s[i] = fmt.Sprintf("%#v", v[i])
227 }
228 return "[" + strings.Join(s, ", ") + "]"
229 } else {
230 return fmt.Sprintf("%#v", in)
231 }
232}
Dan Willemsen00269f22017-07-06 16:59:48 -0700233
Colin Cross98be1bb2019-12-13 20:41:13 -0800234func pathTestConfig(buildDir string) Config {
235 return TestConfig(buildDir, nil, "", nil)
236}
237
Dan Willemsen00269f22017-07-06 16:59:48 -0700238func TestPathForModuleInstall(t *testing.T) {
Colin Cross98be1bb2019-12-13 20:41:13 -0800239 testConfig := pathTestConfig("")
Dan Willemsen00269f22017-07-06 16:59:48 -0700240
Jiyong Park87788b52020-09-01 12:37:45 +0900241 hostTarget := Target{Os: Linux, Arch: Arch{ArchType: X86}}
242 deviceTarget := Target{Os: Android, Arch: Arch{ArchType: Arm64}}
Dan Willemsen00269f22017-07-06 16:59:48 -0700243
244 testCases := []struct {
Jiyong Park957bcd92020-10-20 18:23:33 +0900245 name string
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100246 ctx *testModuleInstallPathContext
Jiyong Park957bcd92020-10-20 18:23:33 +0900247 in []string
248 out string
249 partitionDir string
Dan Willemsen00269f22017-07-06 16:59:48 -0700250 }{
251 {
252 name: "host binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100253 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700254 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800255 os: hostTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700256 target: hostTarget,
257 },
258 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900259 in: []string{"bin", "my_test"},
260 out: "host/linux-x86/bin/my_test",
261 partitionDir: "host/linux-x86",
Dan Willemsen00269f22017-07-06 16:59:48 -0700262 },
263
264 {
265 name: "system binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100266 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700267 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800268 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700269 target: deviceTarget,
270 },
271 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900272 in: []string{"bin", "my_test"},
273 out: "target/product/test_device/system/bin/my_test",
274 partitionDir: "target/product/test_device/system",
Dan Willemsen00269f22017-07-06 16:59:48 -0700275 },
276 {
277 name: "vendor binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100278 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700279 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800280 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700281 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800282 earlyModuleContext: earlyModuleContext{
283 kind: socSpecificModule,
284 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700285 },
286 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900287 in: []string{"bin", "my_test"},
288 out: "target/product/test_device/vendor/bin/my_test",
289 partitionDir: "target/product/test_device/vendor",
Dan Willemsen00269f22017-07-06 16:59:48 -0700290 },
Jiyong Park2db76922017-11-08 16:03:48 +0900291 {
292 name: "odm binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100293 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700294 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800295 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900296 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800297 earlyModuleContext: earlyModuleContext{
298 kind: deviceSpecificModule,
299 },
Jiyong Park2db76922017-11-08 16:03:48 +0900300 },
301 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900302 in: []string{"bin", "my_test"},
303 out: "target/product/test_device/odm/bin/my_test",
304 partitionDir: "target/product/test_device/odm",
Jiyong Park2db76922017-11-08 16:03:48 +0900305 },
306 {
Jaekyun Seok5cfbfbb2018-01-10 19:00:15 +0900307 name: "product binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100308 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700309 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800310 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900311 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800312 earlyModuleContext: earlyModuleContext{
313 kind: productSpecificModule,
314 },
Jiyong Park2db76922017-11-08 16:03:48 +0900315 },
316 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900317 in: []string{"bin", "my_test"},
318 out: "target/product/test_device/product/bin/my_test",
319 partitionDir: "target/product/test_device/product",
Jiyong Park2db76922017-11-08 16:03:48 +0900320 },
Dario Frenifd05a742018-05-29 13:28:54 +0100321 {
Justin Yund5f6c822019-06-25 16:47:17 +0900322 name: "system_ext binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100323 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700324 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800325 os: deviceTarget.Os,
Dario Frenifd05a742018-05-29 13:28:54 +0100326 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800327 earlyModuleContext: earlyModuleContext{
328 kind: systemExtSpecificModule,
329 },
Dario Frenifd05a742018-05-29 13:28:54 +0100330 },
331 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900332 in: []string{"bin", "my_test"},
333 out: "target/product/test_device/system_ext/bin/my_test",
334 partitionDir: "target/product/test_device/system_ext",
Dario Frenifd05a742018-05-29 13:28:54 +0100335 },
Colin Cross90ba5f42019-10-02 11:10:58 -0700336 {
337 name: "root binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100338 ctx: &testModuleInstallPathContext{
Colin Cross90ba5f42019-10-02 11:10:58 -0700339 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800340 os: deviceTarget.Os,
Colin Cross90ba5f42019-10-02 11:10:58 -0700341 target: deviceTarget,
342 },
343 inRoot: true,
344 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900345 in: []string{"my_test"},
346 out: "target/product/test_device/root/my_test",
347 partitionDir: "target/product/test_device/root",
Colin Cross90ba5f42019-10-02 11:10:58 -0700348 },
349 {
350 name: "recovery binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100351 ctx: &testModuleInstallPathContext{
Colin Cross90ba5f42019-10-02 11:10:58 -0700352 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800353 os: deviceTarget.Os,
Colin Cross90ba5f42019-10-02 11:10:58 -0700354 target: deviceTarget,
355 },
356 inRecovery: true,
357 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900358 in: []string{"bin/my_test"},
359 out: "target/product/test_device/recovery/root/system/bin/my_test",
360 partitionDir: "target/product/test_device/recovery/root/system",
Colin Cross90ba5f42019-10-02 11:10:58 -0700361 },
362 {
363 name: "recovery root binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100364 ctx: &testModuleInstallPathContext{
Colin Cross90ba5f42019-10-02 11:10:58 -0700365 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800366 os: deviceTarget.Os,
Colin Cross90ba5f42019-10-02 11:10:58 -0700367 target: deviceTarget,
368 },
369 inRecovery: true,
370 inRoot: true,
371 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900372 in: []string{"my_test"},
373 out: "target/product/test_device/recovery/root/my_test",
374 partitionDir: "target/product/test_device/recovery/root",
Colin Cross90ba5f42019-10-02 11:10:58 -0700375 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700376
377 {
Inseob Kimd9580b82021-04-13 21:13:49 +0900378 name: "ramdisk binary",
379 ctx: &testModuleInstallPathContext{
380 baseModuleContext: baseModuleContext{
381 os: deviceTarget.Os,
382 target: deviceTarget,
383 },
384 inRamdisk: true,
385 },
386 in: []string{"my_test"},
387 out: "target/product/test_device/ramdisk/system/my_test",
388 partitionDir: "target/product/test_device/ramdisk/system",
389 },
390 {
391 name: "ramdisk root binary",
392 ctx: &testModuleInstallPathContext{
393 baseModuleContext: baseModuleContext{
394 os: deviceTarget.Os,
395 target: deviceTarget,
396 },
397 inRamdisk: true,
398 inRoot: true,
399 },
400 in: []string{"my_test"},
401 out: "target/product/test_device/ramdisk/my_test",
402 partitionDir: "target/product/test_device/ramdisk",
403 },
404 {
405 name: "vendor_ramdisk binary",
406 ctx: &testModuleInstallPathContext{
407 baseModuleContext: baseModuleContext{
408 os: deviceTarget.Os,
409 target: deviceTarget,
410 },
411 inVendorRamdisk: true,
412 },
413 in: []string{"my_test"},
414 out: "target/product/test_device/vendor_ramdisk/system/my_test",
415 partitionDir: "target/product/test_device/vendor_ramdisk/system",
416 },
417 {
418 name: "vendor_ramdisk root binary",
419 ctx: &testModuleInstallPathContext{
420 baseModuleContext: baseModuleContext{
421 os: deviceTarget.Os,
422 target: deviceTarget,
423 },
424 inVendorRamdisk: true,
425 inRoot: true,
426 },
427 in: []string{"my_test"},
428 out: "target/product/test_device/vendor_ramdisk/my_test",
429 partitionDir: "target/product/test_device/vendor_ramdisk",
430 },
431 {
Inseob Kim08758f02021-04-08 21:13:22 +0900432 name: "debug_ramdisk binary",
433 ctx: &testModuleInstallPathContext{
434 baseModuleContext: baseModuleContext{
435 os: deviceTarget.Os,
436 target: deviceTarget,
437 },
438 inDebugRamdisk: true,
439 },
440 in: []string{"my_test"},
441 out: "target/product/test_device/debug_ramdisk/my_test",
442 partitionDir: "target/product/test_device/debug_ramdisk",
443 },
444 {
Dan Willemsen00269f22017-07-06 16:59:48 -0700445 name: "system native test binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100446 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700447 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800448 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700449 target: deviceTarget,
450 },
451 inData: true,
452 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900453 in: []string{"nativetest", "my_test"},
454 out: "target/product/test_device/data/nativetest/my_test",
455 partitionDir: "target/product/test_device/data",
Dan Willemsen00269f22017-07-06 16:59:48 -0700456 },
457 {
458 name: "vendor native test binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100459 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700460 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800461 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700462 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800463 earlyModuleContext: earlyModuleContext{
464 kind: socSpecificModule,
465 },
Jiyong Park2db76922017-11-08 16:03:48 +0900466 },
467 inData: true,
468 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900469 in: []string{"nativetest", "my_test"},
470 out: "target/product/test_device/data/nativetest/my_test",
471 partitionDir: "target/product/test_device/data",
Jiyong Park2db76922017-11-08 16:03:48 +0900472 },
473 {
474 name: "odm native test binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100475 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700476 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800477 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900478 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800479 earlyModuleContext: earlyModuleContext{
480 kind: deviceSpecificModule,
481 },
Jiyong Park2db76922017-11-08 16:03:48 +0900482 },
483 inData: true,
484 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900485 in: []string{"nativetest", "my_test"},
486 out: "target/product/test_device/data/nativetest/my_test",
487 partitionDir: "target/product/test_device/data",
Jiyong Park2db76922017-11-08 16:03:48 +0900488 },
489 {
Jaekyun Seok5cfbfbb2018-01-10 19:00:15 +0900490 name: "product native test 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,
Jiyong Park2db76922017-11-08 16:03:48 +0900494 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800495 earlyModuleContext: earlyModuleContext{
496 kind: productSpecificModule,
497 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700498 },
499 inData: true,
500 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900501 in: []string{"nativetest", "my_test"},
502 out: "target/product/test_device/data/nativetest/my_test",
503 partitionDir: "target/product/test_device/data",
Dan Willemsen00269f22017-07-06 16:59:48 -0700504 },
505
506 {
Justin Yund5f6c822019-06-25 16:47:17 +0900507 name: "system_ext native test binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100508 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700509 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800510 os: deviceTarget.Os,
Dario Frenifd05a742018-05-29 13:28:54 +0100511 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800512 earlyModuleContext: earlyModuleContext{
513 kind: systemExtSpecificModule,
514 },
Dario Frenifd05a742018-05-29 13:28:54 +0100515 },
516 inData: true,
517 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900518 in: []string{"nativetest", "my_test"},
519 out: "target/product/test_device/data/nativetest/my_test",
520 partitionDir: "target/product/test_device/data",
Dario Frenifd05a742018-05-29 13:28:54 +0100521 },
522
523 {
Dan Willemsen00269f22017-07-06 16:59:48 -0700524 name: "sanitized system binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100525 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700526 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800527 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700528 target: deviceTarget,
529 },
530 inSanitizerDir: true,
531 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900532 in: []string{"bin", "my_test"},
533 out: "target/product/test_device/data/asan/system/bin/my_test",
534 partitionDir: "target/product/test_device/data/asan/system",
Dan Willemsen00269f22017-07-06 16:59:48 -0700535 },
536 {
537 name: "sanitized vendor binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100538 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700539 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800540 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700541 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800542 earlyModuleContext: earlyModuleContext{
543 kind: socSpecificModule,
544 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700545 },
546 inSanitizerDir: true,
547 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900548 in: []string{"bin", "my_test"},
549 out: "target/product/test_device/data/asan/vendor/bin/my_test",
550 partitionDir: "target/product/test_device/data/asan/vendor",
Dan Willemsen00269f22017-07-06 16:59:48 -0700551 },
Jiyong Park2db76922017-11-08 16:03:48 +0900552 {
553 name: "sanitized odm binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100554 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700555 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800556 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900557 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800558 earlyModuleContext: earlyModuleContext{
559 kind: deviceSpecificModule,
560 },
Jiyong Park2db76922017-11-08 16:03:48 +0900561 },
562 inSanitizerDir: true,
563 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900564 in: []string{"bin", "my_test"},
565 out: "target/product/test_device/data/asan/odm/bin/my_test",
566 partitionDir: "target/product/test_device/data/asan/odm",
Jiyong Park2db76922017-11-08 16:03:48 +0900567 },
568 {
Jaekyun Seok5cfbfbb2018-01-10 19:00:15 +0900569 name: "sanitized product binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100570 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700571 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800572 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900573 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800574 earlyModuleContext: earlyModuleContext{
575 kind: productSpecificModule,
576 },
Jiyong Park2db76922017-11-08 16:03:48 +0900577 },
578 inSanitizerDir: true,
579 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900580 in: []string{"bin", "my_test"},
581 out: "target/product/test_device/data/asan/product/bin/my_test",
582 partitionDir: "target/product/test_device/data/asan/product",
Jiyong Park2db76922017-11-08 16:03:48 +0900583 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700584
585 {
Justin Yund5f6c822019-06-25 16:47:17 +0900586 name: "sanitized system_ext binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100587 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700588 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800589 os: deviceTarget.Os,
Dario Frenifd05a742018-05-29 13:28:54 +0100590 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800591 earlyModuleContext: earlyModuleContext{
592 kind: systemExtSpecificModule,
593 },
Dario Frenifd05a742018-05-29 13:28:54 +0100594 },
595 inSanitizerDir: true,
596 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900597 in: []string{"bin", "my_test"},
598 out: "target/product/test_device/data/asan/system_ext/bin/my_test",
599 partitionDir: "target/product/test_device/data/asan/system_ext",
Dario Frenifd05a742018-05-29 13:28:54 +0100600 },
601
602 {
Dan Willemsen00269f22017-07-06 16:59:48 -0700603 name: "sanitized system native test binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100604 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700605 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800606 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700607 target: deviceTarget,
608 },
609 inData: true,
610 inSanitizerDir: true,
611 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900612 in: []string{"nativetest", "my_test"},
613 out: "target/product/test_device/data/asan/data/nativetest/my_test",
614 partitionDir: "target/product/test_device/data/asan/data",
Dan Willemsen00269f22017-07-06 16:59:48 -0700615 },
616 {
617 name: "sanitized vendor native test binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100618 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700619 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800620 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700621 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800622 earlyModuleContext: earlyModuleContext{
623 kind: socSpecificModule,
624 },
Jiyong Park2db76922017-11-08 16:03:48 +0900625 },
626 inData: true,
627 inSanitizerDir: true,
628 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900629 in: []string{"nativetest", "my_test"},
630 out: "target/product/test_device/data/asan/data/nativetest/my_test",
631 partitionDir: "target/product/test_device/data/asan/data",
Jiyong Park2db76922017-11-08 16:03:48 +0900632 },
633 {
634 name: "sanitized odm native test binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100635 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700636 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800637 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900638 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800639 earlyModuleContext: earlyModuleContext{
640 kind: deviceSpecificModule,
641 },
Jiyong Park2db76922017-11-08 16:03:48 +0900642 },
643 inData: true,
644 inSanitizerDir: true,
645 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900646 in: []string{"nativetest", "my_test"},
647 out: "target/product/test_device/data/asan/data/nativetest/my_test",
648 partitionDir: "target/product/test_device/data/asan/data",
Jiyong Park2db76922017-11-08 16:03:48 +0900649 },
650 {
Jaekyun Seok5cfbfbb2018-01-10 19:00:15 +0900651 name: "sanitized product native test binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100652 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700653 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800654 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900655 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800656 earlyModuleContext: earlyModuleContext{
657 kind: productSpecificModule,
658 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700659 },
660 inData: true,
661 inSanitizerDir: true,
662 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900663 in: []string{"nativetest", "my_test"},
664 out: "target/product/test_device/data/asan/data/nativetest/my_test",
665 partitionDir: "target/product/test_device/data/asan/data",
Dan Willemsen00269f22017-07-06 16:59:48 -0700666 },
Dario Frenifd05a742018-05-29 13:28:54 +0100667 {
Justin Yund5f6c822019-06-25 16:47:17 +0900668 name: "sanitized system_ext native test binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100669 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700670 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800671 os: deviceTarget.Os,
Dario Frenifd05a742018-05-29 13:28:54 +0100672 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800673 earlyModuleContext: earlyModuleContext{
674 kind: systemExtSpecificModule,
675 },
Dario Frenifd05a742018-05-29 13:28:54 +0100676 },
677 inData: true,
678 inSanitizerDir: true,
679 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900680 in: []string{"nativetest", "my_test"},
681 out: "target/product/test_device/data/asan/data/nativetest/my_test",
682 partitionDir: "target/product/test_device/data/asan/data",
Colin Cross6e359402020-02-10 15:29:54 -0800683 }, {
684 name: "device testcases",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100685 ctx: &testModuleInstallPathContext{
Colin Cross6e359402020-02-10 15:29:54 -0800686 baseModuleContext: baseModuleContext{
687 os: deviceTarget.Os,
688 target: deviceTarget,
689 },
690 inTestcases: true,
691 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900692 in: []string{"my_test", "my_test_bin"},
693 out: "target/product/test_device/testcases/my_test/my_test_bin",
694 partitionDir: "target/product/test_device/testcases",
Colin Cross6e359402020-02-10 15:29:54 -0800695 }, {
696 name: "host testcases",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100697 ctx: &testModuleInstallPathContext{
Colin Cross6e359402020-02-10 15:29:54 -0800698 baseModuleContext: baseModuleContext{
699 os: hostTarget.Os,
700 target: hostTarget,
701 },
702 inTestcases: true,
703 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900704 in: []string{"my_test", "my_test_bin"},
705 out: "host/linux-x86/testcases/my_test/my_test_bin",
706 partitionDir: "host/linux-x86/testcases",
Colin Cross6e359402020-02-10 15:29:54 -0800707 }, {
708 name: "forced host testcases",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100709 ctx: &testModuleInstallPathContext{
Colin Cross6e359402020-02-10 15:29:54 -0800710 baseModuleContext: baseModuleContext{
711 os: deviceTarget.Os,
712 target: deviceTarget,
713 },
714 inTestcases: true,
715 forceOS: &Linux,
Jiyong Park87788b52020-09-01 12:37:45 +0900716 forceArch: &X86,
Colin Cross6e359402020-02-10 15:29:54 -0800717 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900718 in: []string{"my_test", "my_test_bin"},
719 out: "host/linux-x86/testcases/my_test/my_test_bin",
720 partitionDir: "host/linux-x86/testcases",
Dario Frenifd05a742018-05-29 13:28:54 +0100721 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700722 }
723
724 for _, tc := range testCases {
725 t.Run(tc.name, func(t *testing.T) {
Colin Cross0ea8ba82019-06-06 14:33:29 -0700726 tc.ctx.baseModuleContext.config = testConfig
Dan Willemsen00269f22017-07-06 16:59:48 -0700727 output := PathForModuleInstall(tc.ctx, tc.in...)
728 if output.basePath.path != tc.out {
729 t.Errorf("unexpected path:\n got: %q\nwant: %q\n",
730 output.basePath.path,
731 tc.out)
732 }
Jiyong Park957bcd92020-10-20 18:23:33 +0900733 if output.partitionDir != tc.partitionDir {
734 t.Errorf("unexpected partitionDir:\n got: %q\nwant: %q\n",
735 output.partitionDir, tc.partitionDir)
736 }
Dan Willemsen00269f22017-07-06 16:59:48 -0700737 })
738 }
739}
Colin Cross5e6cfbe2017-11-03 15:20:35 -0700740
Inseob Kimd9580b82021-04-13 21:13:49 +0900741func TestPathForModuleInstallRecoveryAsBoot(t *testing.T) {
742 testConfig := pathTestConfig("")
743 testConfig.TestProductVariables.BoardUsesRecoveryAsBoot = proptools.BoolPtr(true)
744 testConfig.TestProductVariables.BoardMoveRecoveryResourcesToVendorBoot = proptools.BoolPtr(true)
745 deviceTarget := Target{Os: Android, Arch: Arch{ArchType: Arm64}}
746
747 testCases := []struct {
748 name string
749 ctx *testModuleInstallPathContext
750 in []string
751 out string
752 partitionDir string
753 }{
754 {
755 name: "ramdisk binary",
756 ctx: &testModuleInstallPathContext{
757 baseModuleContext: baseModuleContext{
758 os: deviceTarget.Os,
759 target: deviceTarget,
760 },
761 inRamdisk: true,
762 inRoot: true,
763 },
764 in: []string{"my_test"},
765 out: "target/product/test_device/recovery/root/first_stage_ramdisk/my_test",
766 partitionDir: "target/product/test_device/recovery/root/first_stage_ramdisk",
767 },
768
769 {
770 name: "vendor_ramdisk binary",
771 ctx: &testModuleInstallPathContext{
772 baseModuleContext: baseModuleContext{
773 os: deviceTarget.Os,
774 target: deviceTarget,
775 },
776 inVendorRamdisk: true,
777 inRoot: true,
778 },
779 in: []string{"my_test"},
780 out: "target/product/test_device/vendor_ramdisk/first_stage_ramdisk/my_test",
781 partitionDir: "target/product/test_device/vendor_ramdisk/first_stage_ramdisk",
782 },
783 }
784
785 for _, tc := range testCases {
786 t.Run(tc.name, func(t *testing.T) {
787 tc.ctx.baseModuleContext.config = testConfig
788 output := PathForModuleInstall(tc.ctx, tc.in...)
789 if output.basePath.path != tc.out {
790 t.Errorf("unexpected path:\n got: %q\nwant: %q\n",
791 output.basePath.path,
792 tc.out)
793 }
794 if output.partitionDir != tc.partitionDir {
795 t.Errorf("unexpected partitionDir:\n got: %q\nwant: %q\n",
796 output.partitionDir, tc.partitionDir)
797 }
798 })
799 }
800}
801
Jiyong Park957bcd92020-10-20 18:23:33 +0900802func TestBaseDirForInstallPath(t *testing.T) {
803 testConfig := pathTestConfig("")
804 deviceTarget := Target{Os: Android, Arch: Arch{ArchType: Arm64}}
805
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100806 ctx := &testModuleInstallPathContext{
Jiyong Park957bcd92020-10-20 18:23:33 +0900807 baseModuleContext: baseModuleContext{
808 os: deviceTarget.Os,
809 target: deviceTarget,
810 },
811 }
812 ctx.baseModuleContext.config = testConfig
813
814 actual := PathForModuleInstall(ctx, "foo", "bar")
815 expectedBaseDir := "target/product/test_device/system"
816 if actual.partitionDir != expectedBaseDir {
817 t.Errorf("unexpected partitionDir:\n got: %q\nwant: %q\n", actual.partitionDir, expectedBaseDir)
818 }
819 expectedRelPath := "foo/bar"
820 if actual.Rel() != expectedRelPath {
821 t.Errorf("unexpected Rel():\n got: %q\nwant: %q\n", actual.Rel(), expectedRelPath)
822 }
823
824 actualAfterJoin := actual.Join(ctx, "baz")
825 // partitionDir is preserved even after joining
826 if actualAfterJoin.partitionDir != expectedBaseDir {
827 t.Errorf("unexpected partitionDir after joining:\n got: %q\nwant: %q\n", actualAfterJoin.partitionDir, expectedBaseDir)
828 }
829 // Rel() is updated though
830 expectedRelAfterJoin := "baz"
831 if actualAfterJoin.Rel() != expectedRelAfterJoin {
832 t.Errorf("unexpected Rel() after joining:\n got: %q\nwant: %q\n", actualAfterJoin.Rel(), expectedRelAfterJoin)
833 }
834}
835
Colin Cross5e6cfbe2017-11-03 15:20:35 -0700836func TestDirectorySortedPaths(t *testing.T) {
Colin Cross98be1bb2019-12-13 20:41:13 -0800837 config := TestConfig("out", nil, "", map[string][]byte{
838 "Android.bp": nil,
839 "a.txt": nil,
840 "a/txt": nil,
841 "a/b/c": nil,
842 "a/b/d": nil,
843 "b": nil,
844 "b/b.txt": nil,
845 "a/a.txt": nil,
Colin Cross07e51612019-03-05 12:46:40 -0800846 })
847
Colin Cross98be1bb2019-12-13 20:41:13 -0800848 ctx := PathContextForTesting(config)
849
Colin Cross5e6cfbe2017-11-03 15:20:35 -0700850 makePaths := func() Paths {
851 return Paths{
Colin Cross07e51612019-03-05 12:46:40 -0800852 PathForSource(ctx, "a.txt"),
853 PathForSource(ctx, "a/txt"),
854 PathForSource(ctx, "a/b/c"),
855 PathForSource(ctx, "a/b/d"),
856 PathForSource(ctx, "b"),
857 PathForSource(ctx, "b/b.txt"),
858 PathForSource(ctx, "a/a.txt"),
Colin Cross5e6cfbe2017-11-03 15:20:35 -0700859 }
860 }
861
862 expected := []string{
863 "a.txt",
864 "a/a.txt",
865 "a/b/c",
866 "a/b/d",
867 "a/txt",
868 "b",
869 "b/b.txt",
870 }
871
872 paths := makePaths()
Colin Crossa140bb02018-04-17 10:52:26 -0700873 reversePaths := ReversePaths(paths)
Colin Cross5e6cfbe2017-11-03 15:20:35 -0700874
875 sortedPaths := PathsToDirectorySortedPaths(paths)
876 reverseSortedPaths := PathsToDirectorySortedPaths(reversePaths)
877
878 if !reflect.DeepEqual(Paths(sortedPaths).Strings(), expected) {
879 t.Fatalf("sorted paths:\n %#v\n != \n %#v", paths.Strings(), expected)
880 }
881
882 if !reflect.DeepEqual(Paths(reverseSortedPaths).Strings(), expected) {
883 t.Fatalf("sorted reversed paths:\n %#v\n !=\n %#v", reversePaths.Strings(), expected)
884 }
885
886 expectedA := []string{
887 "a/a.txt",
888 "a/b/c",
889 "a/b/d",
890 "a/txt",
891 }
892
893 inA := sortedPaths.PathsInDirectory("a")
894 if !reflect.DeepEqual(inA.Strings(), expectedA) {
895 t.Errorf("FilesInDirectory(a):\n %#v\n != \n %#v", inA.Strings(), expectedA)
896 }
897
898 expectedA_B := []string{
899 "a/b/c",
900 "a/b/d",
901 }
902
903 inA_B := sortedPaths.PathsInDirectory("a/b")
904 if !reflect.DeepEqual(inA_B.Strings(), expectedA_B) {
905 t.Errorf("FilesInDirectory(a/b):\n %#v\n != \n %#v", inA_B.Strings(), expectedA_B)
906 }
907
908 expectedB := []string{
909 "b/b.txt",
910 }
911
912 inB := sortedPaths.PathsInDirectory("b")
913 if !reflect.DeepEqual(inB.Strings(), expectedB) {
914 t.Errorf("FilesInDirectory(b):\n %#v\n != \n %#v", inA.Strings(), expectedA)
915 }
916}
Colin Cross43f08db2018-11-12 10:13:39 -0800917
918func TestMaybeRel(t *testing.T) {
919 testCases := []struct {
920 name string
921 base string
922 target string
923 out string
924 isRel bool
925 }{
926 {
927 name: "normal",
928 base: "a/b/c",
929 target: "a/b/c/d",
930 out: "d",
931 isRel: true,
932 },
933 {
934 name: "parent",
935 base: "a/b/c/d",
936 target: "a/b/c",
937 isRel: false,
938 },
939 {
940 name: "not relative",
941 base: "a/b",
942 target: "c/d",
943 isRel: false,
944 },
945 {
946 name: "abs1",
947 base: "/a",
948 target: "a",
949 isRel: false,
950 },
951 {
952 name: "abs2",
953 base: "a",
954 target: "/a",
955 isRel: false,
956 },
957 }
958
959 for _, testCase := range testCases {
960 t.Run(testCase.name, func(t *testing.T) {
961 ctx := &configErrorWrapper{}
962 out, isRel := MaybeRel(ctx, testCase.base, testCase.target)
963 if len(ctx.errors) > 0 {
964 t.Errorf("MaybeRel(..., %s, %s) reported unexpected errors %v",
965 testCase.base, testCase.target, ctx.errors)
966 }
967 if isRel != testCase.isRel || out != testCase.out {
968 t.Errorf("MaybeRel(..., %s, %s) want %v, %v got %v, %v",
969 testCase.base, testCase.target, testCase.out, testCase.isRel, out, isRel)
970 }
971 })
972 }
973}
Colin Cross7b3dcc32019-01-24 13:14:39 -0800974
975func TestPathForSource(t *testing.T) {
976 testCases := []struct {
977 name string
978 buildDir string
979 src string
980 err string
981 }{
982 {
983 name: "normal",
984 buildDir: "out",
985 src: "a/b/c",
986 },
987 {
988 name: "abs",
989 buildDir: "out",
990 src: "/a/b/c",
991 err: "is outside directory",
992 },
993 {
994 name: "in out dir",
995 buildDir: "out",
Colin Cross7b6a55f2021-11-09 12:34:39 -0800996 src: "out/soong/a/b/c",
Colin Cross7b3dcc32019-01-24 13:14:39 -0800997 err: "is in output",
998 },
999 }
1000
1001 funcs := []struct {
1002 name string
1003 f func(ctx PathContext, pathComponents ...string) (SourcePath, error)
1004 }{
1005 {"pathForSource", pathForSource},
1006 {"safePathForSource", safePathForSource},
1007 }
1008
1009 for _, f := range funcs {
1010 t.Run(f.name, func(t *testing.T) {
1011 for _, test := range testCases {
1012 t.Run(test.name, func(t *testing.T) {
Colin Cross98be1bb2019-12-13 20:41:13 -08001013 testConfig := pathTestConfig(test.buildDir)
Colin Cross7b3dcc32019-01-24 13:14:39 -08001014 ctx := &configErrorWrapper{config: testConfig}
1015 _, err := f.f(ctx, test.src)
1016 if len(ctx.errors) > 0 {
1017 t.Fatalf("unexpected errors %v", ctx.errors)
1018 }
1019 if err != nil {
1020 if test.err == "" {
1021 t.Fatalf("unexpected error %q", err.Error())
1022 } else if !strings.Contains(err.Error(), test.err) {
1023 t.Fatalf("incorrect error, want substring %q got %q", test.err, err.Error())
1024 }
1025 } else {
1026 if test.err != "" {
1027 t.Fatalf("missing error %q", test.err)
1028 }
1029 }
1030 })
1031 }
1032 })
1033 }
1034}
Colin Cross8854a5a2019-02-11 14:14:16 -08001035
Colin Cross8a497952019-03-05 22:25:09 -08001036type pathForModuleSrcTestModule struct {
Colin Cross937664a2019-03-06 10:17:32 -08001037 ModuleBase
1038 props struct {
1039 Srcs []string `android:"path"`
1040 Exclude_srcs []string `android:"path"`
Colin Cross8a497952019-03-05 22:25:09 -08001041
1042 Src *string `android:"path"`
Colin Crossba71a3f2019-03-18 12:12:48 -07001043
1044 Module_handles_missing_deps bool
Colin Cross937664a2019-03-06 10:17:32 -08001045 }
1046
Colin Cross8a497952019-03-05 22:25:09 -08001047 src string
1048 rel string
1049
1050 srcs []string
Colin Cross937664a2019-03-06 10:17:32 -08001051 rels []string
Colin Cross8a497952019-03-05 22:25:09 -08001052
1053 missingDeps []string
Colin Cross937664a2019-03-06 10:17:32 -08001054}
1055
Colin Cross8a497952019-03-05 22:25:09 -08001056func pathForModuleSrcTestModuleFactory() Module {
1057 module := &pathForModuleSrcTestModule{}
Colin Cross937664a2019-03-06 10:17:32 -08001058 module.AddProperties(&module.props)
1059 InitAndroidModule(module)
1060 return module
1061}
1062
Colin Cross8a497952019-03-05 22:25:09 -08001063func (p *pathForModuleSrcTestModule) GenerateAndroidBuildActions(ctx ModuleContext) {
Colin Crossba71a3f2019-03-18 12:12:48 -07001064 var srcs Paths
1065 if p.props.Module_handles_missing_deps {
1066 srcs, p.missingDeps = PathsAndMissingDepsForModuleSrcExcludes(ctx, p.props.Srcs, p.props.Exclude_srcs)
1067 } else {
1068 srcs = PathsForModuleSrcExcludes(ctx, p.props.Srcs, p.props.Exclude_srcs)
1069 }
Colin Cross8a497952019-03-05 22:25:09 -08001070 p.srcs = srcs.Strings()
Colin Cross937664a2019-03-06 10:17:32 -08001071
Colin Cross8a497952019-03-05 22:25:09 -08001072 for _, src := range srcs {
Colin Cross937664a2019-03-06 10:17:32 -08001073 p.rels = append(p.rels, src.Rel())
1074 }
Colin Cross8a497952019-03-05 22:25:09 -08001075
1076 if p.props.Src != nil {
1077 src := PathForModuleSrc(ctx, *p.props.Src)
1078 if src != nil {
1079 p.src = src.String()
1080 p.rel = src.Rel()
1081 }
1082 }
1083
Colin Crossba71a3f2019-03-18 12:12:48 -07001084 if !p.props.Module_handles_missing_deps {
1085 p.missingDeps = ctx.GetMissingDependencies()
1086 }
Colin Cross6c4f21f2019-06-06 15:41:36 -07001087
1088 ctx.Build(pctx, BuildParams{
1089 Rule: Touch,
1090 Output: PathForModuleOut(ctx, "output"),
1091 })
Colin Cross8a497952019-03-05 22:25:09 -08001092}
1093
Colin Cross41955e82019-05-29 14:40:35 -07001094type pathForModuleSrcOutputFileProviderModule struct {
1095 ModuleBase
1096 props struct {
1097 Outs []string
1098 Tagged []string
1099 }
1100
1101 outs Paths
1102 tagged Paths
1103}
1104
1105func pathForModuleSrcOutputFileProviderModuleFactory() Module {
1106 module := &pathForModuleSrcOutputFileProviderModule{}
1107 module.AddProperties(&module.props)
1108 InitAndroidModule(module)
1109 return module
1110}
1111
1112func (p *pathForModuleSrcOutputFileProviderModule) GenerateAndroidBuildActions(ctx ModuleContext) {
1113 for _, out := range p.props.Outs {
1114 p.outs = append(p.outs, PathForModuleOut(ctx, out))
1115 }
1116
1117 for _, tagged := range p.props.Tagged {
1118 p.tagged = append(p.tagged, PathForModuleOut(ctx, tagged))
1119 }
1120}
1121
1122func (p *pathForModuleSrcOutputFileProviderModule) OutputFiles(tag string) (Paths, error) {
1123 switch tag {
1124 case "":
1125 return p.outs, nil
1126 case ".tagged":
1127 return p.tagged, nil
1128 default:
1129 return nil, fmt.Errorf("unsupported tag %q", tag)
1130 }
1131}
1132
Colin Cross8a497952019-03-05 22:25:09 -08001133type pathForModuleSrcTestCase struct {
1134 name string
1135 bp string
1136 srcs []string
1137 rels []string
1138 src string
1139 rel string
Paul Duffinec0bd8c2021-07-09 16:56:15 +01001140
1141 // Make test specific preparations to the test fixture.
1142 preparer FixturePreparer
1143
1144 // A test specific error handler.
1145 errorHandler FixtureErrorHandler
Colin Cross8a497952019-03-05 22:25:09 -08001146}
1147
Paul Duffin54054682021-03-16 21:11:42 +00001148func testPathForModuleSrc(t *testing.T, tests []pathForModuleSrcTestCase) {
Colin Cross8a497952019-03-05 22:25:09 -08001149 for _, test := range tests {
1150 t.Run(test.name, func(t *testing.T) {
Colin Cross8a497952019-03-05 22:25:09 -08001151 fgBp := `
1152 filegroup {
1153 name: "a",
1154 srcs: ["src/a"],
1155 }
1156 `
1157
Colin Cross41955e82019-05-29 14:40:35 -07001158 ofpBp := `
1159 output_file_provider {
1160 name: "b",
1161 outs: ["gen/b"],
1162 tagged: ["gen/c"],
1163 }
1164 `
1165
Paul Duffin54054682021-03-16 21:11:42 +00001166 mockFS := MockFS{
Colin Cross8a497952019-03-05 22:25:09 -08001167 "fg/Android.bp": []byte(fgBp),
1168 "foo/Android.bp": []byte(test.bp),
Colin Cross41955e82019-05-29 14:40:35 -07001169 "ofp/Android.bp": []byte(ofpBp),
Colin Cross8a497952019-03-05 22:25:09 -08001170 "fg/src/a": nil,
1171 "foo/src/b": nil,
1172 "foo/src/c": nil,
1173 "foo/src/d": nil,
1174 "foo/src/e/e": nil,
1175 "foo/src_special/$": nil,
1176 }
1177
Paul Duffinec0bd8c2021-07-09 16:56:15 +01001178 errorHandler := test.errorHandler
1179 if errorHandler == nil {
1180 errorHandler = FixtureExpectsNoErrors
1181 }
1182
Paul Duffin30ac3e72021-03-20 00:36:14 +00001183 result := GroupFixturePreparers(
Paul Duffin54054682021-03-16 21:11:42 +00001184 FixtureRegisterWithContext(func(ctx RegistrationContext) {
1185 ctx.RegisterModuleType("test", pathForModuleSrcTestModuleFactory)
1186 ctx.RegisterModuleType("output_file_provider", pathForModuleSrcOutputFileProviderModuleFactory)
Paul Duffin54054682021-03-16 21:11:42 +00001187 }),
Paul Duffinec0bd8c2021-07-09 16:56:15 +01001188 PrepareForTestWithFilegroup,
1189 PrepareForTestWithNamespace,
Paul Duffin54054682021-03-16 21:11:42 +00001190 mockFS.AddToFixture(),
Paul Duffinec0bd8c2021-07-09 16:56:15 +01001191 OptionalFixturePreparer(test.preparer),
1192 ).
1193 ExtendWithErrorHandler(errorHandler).
1194 RunTest(t)
Colin Cross8a497952019-03-05 22:25:09 -08001195
Paul Duffin54054682021-03-16 21:11:42 +00001196 m := result.ModuleForTests("foo", "").Module().(*pathForModuleSrcTestModule)
Colin Crossae8600b2020-10-29 17:09:13 -07001197
Paul Duffin54054682021-03-16 21:11:42 +00001198 AssertStringPathsRelativeToTopEquals(t, "srcs", result.Config, test.srcs, m.srcs)
1199 AssertStringPathsRelativeToTopEquals(t, "rels", result.Config, test.rels, m.rels)
1200 AssertStringPathRelativeToTopEquals(t, "src", result.Config, test.src, m.src)
1201 AssertStringPathRelativeToTopEquals(t, "rel", result.Config, test.rel, m.rel)
Colin Cross8a497952019-03-05 22:25:09 -08001202 })
1203 }
Colin Cross937664a2019-03-06 10:17:32 -08001204}
1205
Colin Cross8a497952019-03-05 22:25:09 -08001206func TestPathsForModuleSrc(t *testing.T) {
1207 tests := []pathForModuleSrcTestCase{
Colin Cross937664a2019-03-06 10:17:32 -08001208 {
1209 name: "path",
1210 bp: `
1211 test {
1212 name: "foo",
1213 srcs: ["src/b"],
1214 }`,
1215 srcs: []string{"foo/src/b"},
1216 rels: []string{"src/b"},
1217 },
1218 {
1219 name: "glob",
1220 bp: `
1221 test {
1222 name: "foo",
1223 srcs: [
1224 "src/*",
1225 "src/e/*",
1226 ],
1227 }`,
1228 srcs: []string{"foo/src/b", "foo/src/c", "foo/src/d", "foo/src/e/e"},
1229 rels: []string{"src/b", "src/c", "src/d", "src/e/e"},
1230 },
1231 {
1232 name: "recursive glob",
1233 bp: `
1234 test {
1235 name: "foo",
1236 srcs: ["src/**/*"],
1237 }`,
1238 srcs: []string{"foo/src/b", "foo/src/c", "foo/src/d", "foo/src/e/e"},
1239 rels: []string{"src/b", "src/c", "src/d", "src/e/e"},
1240 },
1241 {
1242 name: "filegroup",
1243 bp: `
1244 test {
1245 name: "foo",
1246 srcs: [":a"],
1247 }`,
1248 srcs: []string{"fg/src/a"},
1249 rels: []string{"src/a"},
1250 },
1251 {
Colin Cross41955e82019-05-29 14:40:35 -07001252 name: "output file provider",
1253 bp: `
1254 test {
1255 name: "foo",
1256 srcs: [":b"],
1257 }`,
Paul Duffin54054682021-03-16 21:11:42 +00001258 srcs: []string{"out/soong/.intermediates/ofp/b/gen/b"},
Colin Cross41955e82019-05-29 14:40:35 -07001259 rels: []string{"gen/b"},
1260 },
1261 {
1262 name: "output file provider tagged",
1263 bp: `
1264 test {
1265 name: "foo",
1266 srcs: [":b{.tagged}"],
1267 }`,
Paul Duffin54054682021-03-16 21:11:42 +00001268 srcs: []string{"out/soong/.intermediates/ofp/b/gen/c"},
Colin Cross41955e82019-05-29 14:40:35 -07001269 rels: []string{"gen/c"},
1270 },
1271 {
Jooyung Han7607dd32020-07-05 10:23:14 +09001272 name: "output file provider with exclude",
1273 bp: `
1274 test {
1275 name: "foo",
1276 srcs: [":b", ":c"],
1277 exclude_srcs: [":c"]
1278 }
1279 output_file_provider {
1280 name: "c",
1281 outs: ["gen/c"],
1282 }`,
Paul Duffin54054682021-03-16 21:11:42 +00001283 srcs: []string{"out/soong/.intermediates/ofp/b/gen/b"},
Jooyung Han7607dd32020-07-05 10:23:14 +09001284 rels: []string{"gen/b"},
1285 },
1286 {
Colin Cross937664a2019-03-06 10:17:32 -08001287 name: "special characters glob",
1288 bp: `
1289 test {
1290 name: "foo",
1291 srcs: ["src_special/*"],
1292 }`,
1293 srcs: []string{"foo/src_special/$"},
1294 rels: []string{"src_special/$"},
1295 },
1296 }
1297
Paul Duffin54054682021-03-16 21:11:42 +00001298 testPathForModuleSrc(t, tests)
Colin Cross41955e82019-05-29 14:40:35 -07001299}
1300
1301func TestPathForModuleSrc(t *testing.T) {
Colin Cross8a497952019-03-05 22:25:09 -08001302 tests := []pathForModuleSrcTestCase{
1303 {
1304 name: "path",
1305 bp: `
1306 test {
1307 name: "foo",
1308 src: "src/b",
1309 }`,
1310 src: "foo/src/b",
1311 rel: "src/b",
1312 },
1313 {
1314 name: "glob",
1315 bp: `
1316 test {
1317 name: "foo",
1318 src: "src/e/*",
1319 }`,
1320 src: "foo/src/e/e",
1321 rel: "src/e/e",
1322 },
1323 {
1324 name: "filegroup",
1325 bp: `
1326 test {
1327 name: "foo",
1328 src: ":a",
1329 }`,
1330 src: "fg/src/a",
1331 rel: "src/a",
1332 },
1333 {
Colin Cross41955e82019-05-29 14:40:35 -07001334 name: "output file provider",
1335 bp: `
1336 test {
1337 name: "foo",
1338 src: ":b",
1339 }`,
Paul Duffin54054682021-03-16 21:11:42 +00001340 src: "out/soong/.intermediates/ofp/b/gen/b",
Colin Cross41955e82019-05-29 14:40:35 -07001341 rel: "gen/b",
1342 },
1343 {
1344 name: "output file provider tagged",
1345 bp: `
1346 test {
1347 name: "foo",
1348 src: ":b{.tagged}",
1349 }`,
Paul Duffin54054682021-03-16 21:11:42 +00001350 src: "out/soong/.intermediates/ofp/b/gen/c",
Colin Cross41955e82019-05-29 14:40:35 -07001351 rel: "gen/c",
1352 },
1353 {
Colin Cross8a497952019-03-05 22:25:09 -08001354 name: "special characters glob",
1355 bp: `
1356 test {
1357 name: "foo",
1358 src: "src_special/*",
1359 }`,
1360 src: "foo/src_special/$",
1361 rel: "src_special/$",
1362 },
Paul Duffinec0bd8c2021-07-09 16:56:15 +01001363 {
1364 // This test makes sure that an unqualified module name cannot contain characters that make
1365 // it appear as a qualified module name.
Paul Duffinec0bd8c2021-07-09 16:56:15 +01001366 name: "output file provider, invalid fully qualified name",
1367 bp: `
1368 test {
1369 name: "foo",
1370 src: "://other:b",
1371 srcs: ["://other:c"],
1372 }`,
1373 preparer: FixtureAddTextFile("other/Android.bp", `
1374 soong_namespace {}
1375
1376 output_file_provider {
1377 name: "b",
1378 outs: ["gen/b"],
1379 }
1380
1381 output_file_provider {
1382 name: "c",
1383 outs: ["gen/c"],
1384 }
1385 `),
Paul Duffine6ba0722021-07-12 20:12:12 +01001386 src: "foo/:/other:b",
1387 rel: ":/other:b",
1388 srcs: []string{"foo/:/other:c"},
1389 rels: []string{":/other:c"},
Paul Duffinec0bd8c2021-07-09 16:56:15 +01001390 },
1391 {
Paul Duffinec0bd8c2021-07-09 16:56:15 +01001392 name: "output file provider, missing fully qualified name",
1393 bp: `
1394 test {
1395 name: "foo",
1396 src: "//other:b",
1397 srcs: ["//other:c"],
1398 }`,
Paul Duffinec0bd8c2021-07-09 16:56:15 +01001399 errorHandler: FixtureExpectsAllErrorsToMatchAPattern([]string{
Paul Duffine6ba0722021-07-12 20:12:12 +01001400 `"foo" depends on undefined module "//other:b"`,
1401 `"foo" depends on undefined module "//other:c"`,
Paul Duffinec0bd8c2021-07-09 16:56:15 +01001402 }),
1403 },
1404 {
Paul Duffinec0bd8c2021-07-09 16:56:15 +01001405 name: "output file provider, fully qualified name",
1406 bp: `
1407 test {
1408 name: "foo",
1409 src: "//other:b",
1410 srcs: ["//other:c"],
1411 }`,
Paul Duffin40131a32021-07-09 17:10:35 +01001412 src: "out/soong/.intermediates/other/b/gen/b",
1413 rel: "gen/b",
1414 srcs: []string{"out/soong/.intermediates/other/c/gen/c"},
1415 rels: []string{"gen/c"},
Paul Duffinec0bd8c2021-07-09 16:56:15 +01001416 preparer: FixtureAddTextFile("other/Android.bp", `
1417 soong_namespace {}
1418
1419 output_file_provider {
1420 name: "b",
1421 outs: ["gen/b"],
1422 }
1423
1424 output_file_provider {
1425 name: "c",
1426 outs: ["gen/c"],
1427 }
1428 `),
Paul Duffinec0bd8c2021-07-09 16:56:15 +01001429 },
Colin Cross8a497952019-03-05 22:25:09 -08001430 }
1431
Paul Duffin54054682021-03-16 21:11:42 +00001432 testPathForModuleSrc(t, tests)
Colin Cross8a497952019-03-05 22:25:09 -08001433}
Colin Cross937664a2019-03-06 10:17:32 -08001434
Colin Cross8a497952019-03-05 22:25:09 -08001435func TestPathsForModuleSrc_AllowMissingDependencies(t *testing.T) {
Colin Cross8a497952019-03-05 22:25:09 -08001436 bp := `
1437 test {
1438 name: "foo",
1439 srcs: [":a"],
1440 exclude_srcs: [":b"],
1441 src: ":c",
1442 }
Colin Crossba71a3f2019-03-18 12:12:48 -07001443
1444 test {
1445 name: "bar",
1446 srcs: [":d"],
1447 exclude_srcs: [":e"],
1448 module_handles_missing_deps: true,
1449 }
Colin Cross8a497952019-03-05 22:25:09 -08001450 `
1451
Paul Duffin30ac3e72021-03-20 00:36:14 +00001452 result := GroupFixturePreparers(
Paul Duffin54054682021-03-16 21:11:42 +00001453 PrepareForTestWithAllowMissingDependencies,
1454 FixtureRegisterWithContext(func(ctx RegistrationContext) {
1455 ctx.RegisterModuleType("test", pathForModuleSrcTestModuleFactory)
1456 }),
1457 FixtureWithRootAndroidBp(bp),
Paul Duffin30ac3e72021-03-20 00:36:14 +00001458 ).RunTest(t)
Colin Cross8a497952019-03-05 22:25:09 -08001459
Paul Duffin54054682021-03-16 21:11:42 +00001460 foo := result.ModuleForTests("foo", "").Module().(*pathForModuleSrcTestModule)
Colin Cross8a497952019-03-05 22:25:09 -08001461
Paul Duffin54054682021-03-16 21:11:42 +00001462 AssertArrayString(t, "foo missing deps", []string{"a", "b", "c"}, foo.missingDeps)
1463 AssertArrayString(t, "foo srcs", []string{}, foo.srcs)
1464 AssertStringEquals(t, "foo src", "", foo.src)
Colin Cross98be1bb2019-12-13 20:41:13 -08001465
Paul Duffin54054682021-03-16 21:11:42 +00001466 bar := result.ModuleForTests("bar", "").Module().(*pathForModuleSrcTestModule)
Colin Cross98be1bb2019-12-13 20:41:13 -08001467
Paul Duffin54054682021-03-16 21:11:42 +00001468 AssertArrayString(t, "bar missing deps", []string{"d", "e"}, bar.missingDeps)
1469 AssertArrayString(t, "bar srcs", []string{}, bar.srcs)
Colin Cross937664a2019-03-06 10:17:32 -08001470}
1471
Paul Duffin567465d2021-03-16 01:21:34 +00001472func TestPathRelativeToTop(t *testing.T) {
1473 testConfig := pathTestConfig("/tmp/build/top")
1474 deviceTarget := Target{Os: Android, Arch: Arch{ArchType: Arm64}}
1475
1476 ctx := &testModuleInstallPathContext{
1477 baseModuleContext: baseModuleContext{
1478 os: deviceTarget.Os,
1479 target: deviceTarget,
1480 },
1481 }
1482 ctx.baseModuleContext.config = testConfig
1483
1484 t.Run("install for soong", func(t *testing.T) {
1485 p := PathForModuleInstall(ctx, "install/path")
1486 AssertPathRelativeToTopEquals(t, "install path for soong", "out/soong/target/product/test_device/system/install/path", p)
1487 })
1488 t.Run("install for make", func(t *testing.T) {
1489 p := PathForModuleInstall(ctx, "install/path").ToMakePath()
1490 AssertPathRelativeToTopEquals(t, "install path for make", "out/target/product/test_device/system/install/path", p)
1491 })
1492 t.Run("output", func(t *testing.T) {
1493 p := PathForOutput(ctx, "output/path")
1494 AssertPathRelativeToTopEquals(t, "output path", "out/soong/output/path", p)
1495 })
1496 t.Run("source", func(t *testing.T) {
1497 p := PathForSource(ctx, "source/path")
1498 AssertPathRelativeToTopEquals(t, "source path", "source/path", p)
1499 })
1500 t.Run("mixture", func(t *testing.T) {
1501 paths := Paths{
1502 PathForModuleInstall(ctx, "install/path"),
1503 PathForModuleInstall(ctx, "install/path").ToMakePath(),
1504 PathForOutput(ctx, "output/path"),
1505 PathForSource(ctx, "source/path"),
1506 }
1507
1508 expected := []string{
1509 "out/soong/target/product/test_device/system/install/path",
1510 "out/target/product/test_device/system/install/path",
1511 "out/soong/output/path",
1512 "source/path",
1513 }
1514 AssertPathsRelativeToTopEquals(t, "mixture", expected, paths)
1515 })
1516}
1517
Colin Cross8854a5a2019-02-11 14:14:16 -08001518func ExampleOutputPath_ReplaceExtension() {
1519 ctx := &configErrorWrapper{
Colin Cross98be1bb2019-12-13 20:41:13 -08001520 config: TestConfig("out", nil, "", nil),
Colin Cross8854a5a2019-02-11 14:14:16 -08001521 }
Colin Cross2cdd5df2019-02-25 10:25:24 -08001522 p := PathForOutput(ctx, "system/framework").Join(ctx, "boot.art")
Colin Cross8854a5a2019-02-11 14:14:16 -08001523 p2 := p.ReplaceExtension(ctx, "oat")
1524 fmt.Println(p, p2)
Colin Cross2cdd5df2019-02-25 10:25:24 -08001525 fmt.Println(p.Rel(), p2.Rel())
Colin Cross8854a5a2019-02-11 14:14:16 -08001526
1527 // Output:
Colin Cross7b6a55f2021-11-09 12:34:39 -08001528 // out/soong/system/framework/boot.art out/soong/system/framework/boot.oat
Colin Cross2cdd5df2019-02-25 10:25:24 -08001529 // boot.art boot.oat
Colin Cross8854a5a2019-02-11 14:14:16 -08001530}
Colin Cross40e33732019-02-15 11:08:35 -08001531
Colin Cross41b46762020-10-09 19:26:32 -07001532func ExampleOutputPath_InSameDir() {
Colin Cross40e33732019-02-15 11:08:35 -08001533 ctx := &configErrorWrapper{
Colin Cross98be1bb2019-12-13 20:41:13 -08001534 config: TestConfig("out", nil, "", nil),
Colin Cross40e33732019-02-15 11:08:35 -08001535 }
Colin Cross2cdd5df2019-02-25 10:25:24 -08001536 p := PathForOutput(ctx, "system/framework").Join(ctx, "boot.art")
Colin Cross40e33732019-02-15 11:08:35 -08001537 p2 := p.InSameDir(ctx, "oat", "arm", "boot.vdex")
1538 fmt.Println(p, p2)
Colin Cross2cdd5df2019-02-25 10:25:24 -08001539 fmt.Println(p.Rel(), p2.Rel())
Colin Cross40e33732019-02-15 11:08:35 -08001540
1541 // Output:
Colin Cross7b6a55f2021-11-09 12:34:39 -08001542 // out/soong/system/framework/boot.art out/soong/system/framework/oat/arm/boot.vdex
Colin Cross2cdd5df2019-02-25 10:25:24 -08001543 // boot.art oat/arm/boot.vdex
Colin Cross40e33732019-02-15 11:08:35 -08001544}
Colin Cross27027c72020-02-28 15:34:17 -08001545
1546func BenchmarkFirstUniquePaths(b *testing.B) {
1547 implementations := []struct {
1548 name string
1549 f func(Paths) Paths
1550 }{
1551 {
1552 name: "list",
1553 f: firstUniquePathsList,
1554 },
1555 {
1556 name: "map",
1557 f: firstUniquePathsMap,
1558 },
1559 }
1560 const maxSize = 1024
1561 uniquePaths := make(Paths, maxSize)
1562 for i := range uniquePaths {
1563 uniquePaths[i] = PathForTesting(strconv.Itoa(i))
1564 }
1565 samePath := make(Paths, maxSize)
1566 for i := range samePath {
1567 samePath[i] = uniquePaths[0]
1568 }
1569
1570 f := func(b *testing.B, imp func(Paths) Paths, paths Paths) {
1571 for i := 0; i < b.N; i++ {
1572 b.ReportAllocs()
1573 paths = append(Paths(nil), paths...)
1574 imp(paths)
1575 }
1576 }
1577
1578 for n := 1; n <= maxSize; n <<= 1 {
1579 b.Run(strconv.Itoa(n), func(b *testing.B) {
1580 for _, implementation := range implementations {
1581 b.Run(implementation.name, func(b *testing.B) {
1582 b.Run("same", func(b *testing.B) {
1583 f(b, implementation.f, samePath[:n])
1584 })
1585 b.Run("unique", func(b *testing.B) {
1586 f(b, implementation.f, uniquePaths[:n])
1587 })
1588 })
1589 }
1590 })
1591 }
1592}