blob: bf46c34f3cca359886732c05499f7c472065ad6e [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 {
Colin Crossbf9ed3f2023-10-24 14:17:03 -070040 in: []string{"", ""},
41 out: "",
42 },
43 {
44 in: []string{"a", ""},
45 out: "a",
46 },
47 {
48 in: []string{"", "a"},
49 out: "a",
50 },
51 {
52 in: []string{"", "a", ""},
53 out: "a",
54 },
55 {
Dan Willemsen34cc69e2015-09-23 15:26:20 -070056 in: []string{"a/b"},
57 out: "a/b",
58 },
59 {
60 in: []string{"a/b", "c"},
61 out: "a/b/c",
62 },
63 {
64 in: []string{"a/.."},
65 out: ".",
66 },
67 {
68 in: []string{"."},
69 out: ".",
70 },
71 {
72 in: []string{".."},
73 out: "",
74 err: []error{errors.New("Path is outside directory: ..")},
75 },
76 {
77 in: []string{"../a"},
78 out: "",
79 err: []error{errors.New("Path is outside directory: ../a")},
80 },
81 {
82 in: []string{"b/../../a"},
83 out: "",
84 err: []error{errors.New("Path is outside directory: ../a")},
85 },
86 {
87 in: []string{"/a"},
88 out: "",
89 err: []error{errors.New("Path is outside directory: /a")},
90 },
Dan Willemsen80a7c2a2015-12-21 14:57:11 -080091 {
92 in: []string{"a", "../b"},
93 out: "",
94 err: []error{errors.New("Path is outside directory: ../b")},
95 },
96 {
97 in: []string{"a", "b/../../c"},
98 out: "",
99 err: []error{errors.New("Path is outside directory: ../c")},
100 },
101 {
102 in: []string{"a", "./.."},
103 out: "",
104 err: []error{errors.New("Path is outside directory: ..")},
105 },
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700106}
107
108var validateSafePathTestCases = append(commonValidatePathTestCases, []strsTestCase{
109 {
110 in: []string{"$host/../$a"},
111 out: "$a",
112 },
113}...)
114
115var validatePathTestCases = append(commonValidatePathTestCases, []strsTestCase{
116 {
117 in: []string{"$host/../$a"},
118 out: "",
119 err: []error{errors.New("Path contains invalid character($): $host/../$a")},
120 },
121 {
122 in: []string{"$host/.."},
123 out: "",
124 err: []error{errors.New("Path contains invalid character($): $host/..")},
125 },
126}...)
127
128func TestValidateSafePath(t *testing.T) {
129 for _, testCase := range validateSafePathTestCases {
Colin Crossdc75ae72018-02-22 13:48:13 -0800130 t.Run(strings.Join(testCase.in, ","), func(t *testing.T) {
131 ctx := &configErrorWrapper{}
Colin Cross1ccfcc32018-02-22 13:54:26 -0800132 out, err := validateSafePath(testCase.in...)
133 if err != nil {
134 reportPathError(ctx, err)
135 }
Colin Crossdc75ae72018-02-22 13:48:13 -0800136 check(t, "validateSafePath", p(testCase.in), out, ctx.errors, testCase.out, testCase.err)
137 })
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700138 }
139}
140
141func TestValidatePath(t *testing.T) {
142 for _, testCase := range validatePathTestCases {
Colin Crossdc75ae72018-02-22 13:48:13 -0800143 t.Run(strings.Join(testCase.in, ","), func(t *testing.T) {
144 ctx := &configErrorWrapper{}
Colin Cross1ccfcc32018-02-22 13:54:26 -0800145 out, err := validatePath(testCase.in...)
146 if err != nil {
147 reportPathError(ctx, err)
148 }
Colin Crossdc75ae72018-02-22 13:48:13 -0800149 check(t, "validatePath", p(testCase.in), out, ctx.errors, testCase.out, testCase.err)
150 })
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700151 }
152}
153
154func TestOptionalPath(t *testing.T) {
155 var path OptionalPath
Martin Stjernholmc32dd1c2021-09-15 02:39:00 +0100156 checkInvalidOptionalPath(t, path, "unknown")
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700157
158 path = OptionalPathForPath(nil)
Martin Stjernholmc32dd1c2021-09-15 02:39:00 +0100159 checkInvalidOptionalPath(t, path, "unknown")
160
161 path = InvalidOptionalPath("foo")
162 checkInvalidOptionalPath(t, path, "foo")
163
164 path = InvalidOptionalPath("")
165 checkInvalidOptionalPath(t, path, "unknown")
Paul Duffinef081852021-05-13 11:11:15 +0100166
167 path = OptionalPathForPath(PathForTesting("path"))
168 checkValidOptionalPath(t, path, "path")
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700169}
170
Martin Stjernholmc32dd1c2021-09-15 02:39:00 +0100171func checkInvalidOptionalPath(t *testing.T, path OptionalPath, expectedInvalidReason string) {
Colin Crossdc75ae72018-02-22 13:48:13 -0800172 t.Helper()
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700173 if path.Valid() {
Martin Stjernholmc32dd1c2021-09-15 02:39:00 +0100174 t.Errorf("Invalid OptionalPath should not be valid")
175 }
176 if path.InvalidReason() != expectedInvalidReason {
177 t.Errorf("Wrong invalid reason: expected %q, got %q", expectedInvalidReason, path.InvalidReason())
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700178 }
179 if path.String() != "" {
Martin Stjernholmc32dd1c2021-09-15 02:39:00 +0100180 t.Errorf("Invalid OptionalPath String() should return \"\", not %q", path.String())
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700181 }
Paul Duffinef081852021-05-13 11:11:15 +0100182 paths := path.AsPaths()
183 if len(paths) != 0 {
Martin Stjernholmc32dd1c2021-09-15 02:39:00 +0100184 t.Errorf("Invalid OptionalPath AsPaths() should return empty Paths, not %q", paths)
Paul Duffinef081852021-05-13 11:11:15 +0100185 }
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700186 defer func() {
187 if r := recover(); r == nil {
188 t.Errorf("Expected a panic when calling Path() on an uninitialized OptionalPath")
189 }
190 }()
191 path.Path()
192}
193
Paul Duffinef081852021-05-13 11:11:15 +0100194func checkValidOptionalPath(t *testing.T, path OptionalPath, expectedString string) {
195 t.Helper()
196 if !path.Valid() {
197 t.Errorf("Initialized OptionalPath should not be invalid")
198 }
Martin Stjernholmc32dd1c2021-09-15 02:39:00 +0100199 if path.InvalidReason() != "" {
200 t.Errorf("Initialized OptionalPath should not have an invalid reason, got: %q", path.InvalidReason())
201 }
Paul Duffinef081852021-05-13 11:11:15 +0100202 if path.String() != expectedString {
203 t.Errorf("Initialized OptionalPath String() should return %q, not %q", expectedString, path.String())
204 }
205 paths := path.AsPaths()
206 if len(paths) != 1 {
207 t.Errorf("Initialized OptionalPath AsPaths() should return Paths with length 1, not %q", paths)
208 }
209 path.Path()
210}
211
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700212func check(t *testing.T, testType, testString string,
213 got interface{}, err []error,
214 expected interface{}, expectedErr []error) {
Colin Crossdc75ae72018-02-22 13:48:13 -0800215 t.Helper()
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700216
217 printedTestCase := false
218 e := func(s string, expected, got interface{}) {
Colin Crossdc75ae72018-02-22 13:48:13 -0800219 t.Helper()
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700220 if !printedTestCase {
221 t.Errorf("test case %s: %s", testType, testString)
222 printedTestCase = true
223 }
224 t.Errorf("incorrect %s", s)
225 t.Errorf(" expected: %s", p(expected))
226 t.Errorf(" got: %s", p(got))
227 }
228
229 if !reflect.DeepEqual(expectedErr, err) {
230 e("errors:", expectedErr, err)
231 }
232
233 if !reflect.DeepEqual(expected, got) {
234 e("output:", expected, got)
235 }
236}
237
238func p(in interface{}) string {
239 if v, ok := in.([]interface{}); ok {
240 s := make([]string, len(v))
241 for i := range v {
242 s[i] = fmt.Sprintf("%#v", v[i])
243 }
244 return "[" + strings.Join(s, ", ") + "]"
245 } else {
246 return fmt.Sprintf("%#v", in)
247 }
248}
Dan Willemsen00269f22017-07-06 16:59:48 -0700249
Colin Cross98be1bb2019-12-13 20:41:13 -0800250func pathTestConfig(buildDir string) Config {
251 return TestConfig(buildDir, nil, "", nil)
252}
253
Dan Willemsen00269f22017-07-06 16:59:48 -0700254func TestPathForModuleInstall(t *testing.T) {
Colin Cross98be1bb2019-12-13 20:41:13 -0800255 testConfig := pathTestConfig("")
Dan Willemsen00269f22017-07-06 16:59:48 -0700256
Jiyong Park87788b52020-09-01 12:37:45 +0900257 hostTarget := Target{Os: Linux, Arch: Arch{ArchType: X86}}
258 deviceTarget := Target{Os: Android, Arch: Arch{ArchType: Arm64}}
Dan Willemsen00269f22017-07-06 16:59:48 -0700259
260 testCases := []struct {
Jiyong Park957bcd92020-10-20 18:23:33 +0900261 name string
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100262 ctx *testModuleInstallPathContext
Jiyong Park957bcd92020-10-20 18:23:33 +0900263 in []string
264 out string
265 partitionDir string
Dan Willemsen00269f22017-07-06 16:59:48 -0700266 }{
267 {
268 name: "host binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100269 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700270 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800271 os: hostTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700272 target: hostTarget,
273 },
274 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900275 in: []string{"bin", "my_test"},
276 out: "host/linux-x86/bin/my_test",
277 partitionDir: "host/linux-x86",
Dan Willemsen00269f22017-07-06 16:59:48 -0700278 },
279
280 {
281 name: "system binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100282 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700283 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800284 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700285 target: deviceTarget,
286 },
287 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900288 in: []string{"bin", "my_test"},
289 out: "target/product/test_device/system/bin/my_test",
290 partitionDir: "target/product/test_device/system",
Dan Willemsen00269f22017-07-06 16:59:48 -0700291 },
292 {
293 name: "vendor binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100294 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700295 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800296 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700297 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800298 earlyModuleContext: earlyModuleContext{
299 kind: socSpecificModule,
300 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700301 },
302 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900303 in: []string{"bin", "my_test"},
304 out: "target/product/test_device/vendor/bin/my_test",
305 partitionDir: "target/product/test_device/vendor",
Dan Willemsen00269f22017-07-06 16:59:48 -0700306 },
Jiyong Park2db76922017-11-08 16:03:48 +0900307 {
308 name: "odm binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100309 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700310 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800311 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900312 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800313 earlyModuleContext: earlyModuleContext{
314 kind: deviceSpecificModule,
315 },
Jiyong Park2db76922017-11-08 16:03:48 +0900316 },
317 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900318 in: []string{"bin", "my_test"},
319 out: "target/product/test_device/odm/bin/my_test",
320 partitionDir: "target/product/test_device/odm",
Jiyong Park2db76922017-11-08 16:03:48 +0900321 },
322 {
Jaekyun Seok5cfbfbb2018-01-10 19:00:15 +0900323 name: "product binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100324 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700325 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800326 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900327 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800328 earlyModuleContext: earlyModuleContext{
329 kind: productSpecificModule,
330 },
Jiyong Park2db76922017-11-08 16:03:48 +0900331 },
332 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900333 in: []string{"bin", "my_test"},
334 out: "target/product/test_device/product/bin/my_test",
335 partitionDir: "target/product/test_device/product",
Jiyong Park2db76922017-11-08 16:03:48 +0900336 },
Dario Frenifd05a742018-05-29 13:28:54 +0100337 {
Justin Yund5f6c822019-06-25 16:47:17 +0900338 name: "system_ext binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100339 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700340 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800341 os: deviceTarget.Os,
Dario Frenifd05a742018-05-29 13:28:54 +0100342 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800343 earlyModuleContext: earlyModuleContext{
344 kind: systemExtSpecificModule,
345 },
Dario Frenifd05a742018-05-29 13:28:54 +0100346 },
347 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900348 in: []string{"bin", "my_test"},
349 out: "target/product/test_device/system_ext/bin/my_test",
350 partitionDir: "target/product/test_device/system_ext",
Dario Frenifd05a742018-05-29 13:28:54 +0100351 },
Colin Cross90ba5f42019-10-02 11:10:58 -0700352 {
353 name: "root binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100354 ctx: &testModuleInstallPathContext{
Colin Cross90ba5f42019-10-02 11:10:58 -0700355 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800356 os: deviceTarget.Os,
Colin Cross90ba5f42019-10-02 11:10:58 -0700357 target: deviceTarget,
358 },
359 inRoot: true,
360 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900361 in: []string{"my_test"},
362 out: "target/product/test_device/root/my_test",
363 partitionDir: "target/product/test_device/root",
Colin Cross90ba5f42019-10-02 11:10:58 -0700364 },
365 {
366 name: "recovery binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100367 ctx: &testModuleInstallPathContext{
Colin Cross90ba5f42019-10-02 11:10:58 -0700368 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800369 os: deviceTarget.Os,
Colin Cross90ba5f42019-10-02 11:10:58 -0700370 target: deviceTarget,
371 },
372 inRecovery: true,
373 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900374 in: []string{"bin/my_test"},
375 out: "target/product/test_device/recovery/root/system/bin/my_test",
376 partitionDir: "target/product/test_device/recovery/root/system",
Colin Cross90ba5f42019-10-02 11:10:58 -0700377 },
378 {
379 name: "recovery root binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100380 ctx: &testModuleInstallPathContext{
Colin Cross90ba5f42019-10-02 11:10:58 -0700381 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800382 os: deviceTarget.Os,
Colin Cross90ba5f42019-10-02 11:10:58 -0700383 target: deviceTarget,
384 },
385 inRecovery: true,
386 inRoot: true,
387 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900388 in: []string{"my_test"},
389 out: "target/product/test_device/recovery/root/my_test",
390 partitionDir: "target/product/test_device/recovery/root",
Colin Cross90ba5f42019-10-02 11:10:58 -0700391 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700392
393 {
Inseob Kimd9580b82021-04-13 21:13:49 +0900394 name: "ramdisk binary",
395 ctx: &testModuleInstallPathContext{
396 baseModuleContext: baseModuleContext{
397 os: deviceTarget.Os,
398 target: deviceTarget,
399 },
400 inRamdisk: true,
401 },
402 in: []string{"my_test"},
403 out: "target/product/test_device/ramdisk/system/my_test",
404 partitionDir: "target/product/test_device/ramdisk/system",
405 },
406 {
407 name: "ramdisk root binary",
408 ctx: &testModuleInstallPathContext{
409 baseModuleContext: baseModuleContext{
410 os: deviceTarget.Os,
411 target: deviceTarget,
412 },
413 inRamdisk: true,
414 inRoot: true,
415 },
416 in: []string{"my_test"},
417 out: "target/product/test_device/ramdisk/my_test",
418 partitionDir: "target/product/test_device/ramdisk",
419 },
420 {
421 name: "vendor_ramdisk binary",
422 ctx: &testModuleInstallPathContext{
423 baseModuleContext: baseModuleContext{
424 os: deviceTarget.Os,
425 target: deviceTarget,
426 },
427 inVendorRamdisk: true,
428 },
429 in: []string{"my_test"},
430 out: "target/product/test_device/vendor_ramdisk/system/my_test",
431 partitionDir: "target/product/test_device/vendor_ramdisk/system",
432 },
433 {
434 name: "vendor_ramdisk root binary",
435 ctx: &testModuleInstallPathContext{
436 baseModuleContext: baseModuleContext{
437 os: deviceTarget.Os,
438 target: deviceTarget,
439 },
440 inVendorRamdisk: true,
441 inRoot: true,
442 },
443 in: []string{"my_test"},
444 out: "target/product/test_device/vendor_ramdisk/my_test",
445 partitionDir: "target/product/test_device/vendor_ramdisk",
446 },
447 {
Inseob Kim08758f02021-04-08 21:13:22 +0900448 name: "debug_ramdisk binary",
449 ctx: &testModuleInstallPathContext{
450 baseModuleContext: baseModuleContext{
451 os: deviceTarget.Os,
452 target: deviceTarget,
453 },
454 inDebugRamdisk: true,
455 },
456 in: []string{"my_test"},
457 out: "target/product/test_device/debug_ramdisk/my_test",
458 partitionDir: "target/product/test_device/debug_ramdisk",
459 },
460 {
Dan Willemsen00269f22017-07-06 16:59:48 -0700461 name: "system native test binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100462 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700463 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800464 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700465 target: deviceTarget,
466 },
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",
Dan Willemsen00269f22017-07-06 16:59:48 -0700472 },
473 {
474 name: "vendor 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,
Dan Willemsen00269f22017-07-06 16:59:48 -0700478 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800479 earlyModuleContext: earlyModuleContext{
480 kind: socSpecificModule,
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 {
490 name: "odm 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: deviceSpecificModule,
497 },
Jiyong Park2db76922017-11-08 16:03:48 +0900498 },
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",
Jiyong Park2db76922017-11-08 16:03:48 +0900504 },
505 {
Jaekyun Seok5cfbfbb2018-01-10 19:00:15 +0900506 name: "product native test 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: productSpecificModule,
513 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700514 },
515 inData: true,
516 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900517 in: []string{"nativetest", "my_test"},
518 out: "target/product/test_device/data/nativetest/my_test",
519 partitionDir: "target/product/test_device/data",
Dan Willemsen00269f22017-07-06 16:59:48 -0700520 },
521
522 {
Justin Yund5f6c822019-06-25 16:47:17 +0900523 name: "system_ext native test binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100524 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700525 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800526 os: deviceTarget.Os,
Dario Frenifd05a742018-05-29 13:28:54 +0100527 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800528 earlyModuleContext: earlyModuleContext{
529 kind: systemExtSpecificModule,
530 },
Dario Frenifd05a742018-05-29 13:28:54 +0100531 },
532 inData: true,
533 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900534 in: []string{"nativetest", "my_test"},
535 out: "target/product/test_device/data/nativetest/my_test",
536 partitionDir: "target/product/test_device/data",
Dario Frenifd05a742018-05-29 13:28:54 +0100537 },
538
539 {
Dan Willemsen00269f22017-07-06 16:59:48 -0700540 name: "sanitized system binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100541 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700542 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800543 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700544 target: deviceTarget,
545 },
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/system/bin/my_test",
550 partitionDir: "target/product/test_device/data/asan/system",
Dan Willemsen00269f22017-07-06 16:59:48 -0700551 },
552 {
553 name: "sanitized vendor 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,
Dan Willemsen00269f22017-07-06 16:59:48 -0700557 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800558 earlyModuleContext: earlyModuleContext{
559 kind: socSpecificModule,
560 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700561 },
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/vendor/bin/my_test",
566 partitionDir: "target/product/test_device/data/asan/vendor",
Dan Willemsen00269f22017-07-06 16:59:48 -0700567 },
Jiyong Park2db76922017-11-08 16:03:48 +0900568 {
569 name: "sanitized odm 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: deviceSpecificModule,
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/odm/bin/my_test",
582 partitionDir: "target/product/test_device/data/asan/odm",
Jiyong Park2db76922017-11-08 16:03:48 +0900583 },
584 {
Jaekyun Seok5cfbfbb2018-01-10 19:00:15 +0900585 name: "sanitized product binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100586 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700587 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800588 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900589 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800590 earlyModuleContext: earlyModuleContext{
591 kind: productSpecificModule,
592 },
Jiyong Park2db76922017-11-08 16:03:48 +0900593 },
594 inSanitizerDir: true,
595 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900596 in: []string{"bin", "my_test"},
597 out: "target/product/test_device/data/asan/product/bin/my_test",
598 partitionDir: "target/product/test_device/data/asan/product",
Jiyong Park2db76922017-11-08 16:03:48 +0900599 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700600
601 {
Justin Yund5f6c822019-06-25 16:47:17 +0900602 name: "sanitized system_ext binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100603 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700604 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800605 os: deviceTarget.Os,
Dario Frenifd05a742018-05-29 13:28:54 +0100606 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800607 earlyModuleContext: earlyModuleContext{
608 kind: systemExtSpecificModule,
609 },
Dario Frenifd05a742018-05-29 13:28:54 +0100610 },
611 inSanitizerDir: true,
612 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900613 in: []string{"bin", "my_test"},
614 out: "target/product/test_device/data/asan/system_ext/bin/my_test",
615 partitionDir: "target/product/test_device/data/asan/system_ext",
Dario Frenifd05a742018-05-29 13:28:54 +0100616 },
617
618 {
Dan Willemsen00269f22017-07-06 16:59:48 -0700619 name: "sanitized system native test binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100620 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700621 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800622 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700623 target: deviceTarget,
624 },
625 inData: true,
626 inSanitizerDir: true,
627 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900628 in: []string{"nativetest", "my_test"},
629 out: "target/product/test_device/data/asan/data/nativetest/my_test",
630 partitionDir: "target/product/test_device/data/asan/data",
Dan Willemsen00269f22017-07-06 16:59:48 -0700631 },
632 {
633 name: "sanitized vendor native test binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100634 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700635 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800636 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700637 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800638 earlyModuleContext: earlyModuleContext{
639 kind: socSpecificModule,
640 },
Jiyong Park2db76922017-11-08 16:03:48 +0900641 },
642 inData: true,
643 inSanitizerDir: true,
644 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900645 in: []string{"nativetest", "my_test"},
646 out: "target/product/test_device/data/asan/data/nativetest/my_test",
647 partitionDir: "target/product/test_device/data/asan/data",
Jiyong Park2db76922017-11-08 16:03:48 +0900648 },
649 {
650 name: "sanitized odm native test binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100651 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700652 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800653 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900654 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800655 earlyModuleContext: earlyModuleContext{
656 kind: deviceSpecificModule,
657 },
Jiyong Park2db76922017-11-08 16:03:48 +0900658 },
659 inData: true,
660 inSanitizerDir: true,
661 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900662 in: []string{"nativetest", "my_test"},
663 out: "target/product/test_device/data/asan/data/nativetest/my_test",
664 partitionDir: "target/product/test_device/data/asan/data",
Jiyong Park2db76922017-11-08 16:03:48 +0900665 },
666 {
Jaekyun Seok5cfbfbb2018-01-10 19:00:15 +0900667 name: "sanitized product native test binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100668 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700669 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800670 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900671 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800672 earlyModuleContext: earlyModuleContext{
673 kind: productSpecificModule,
674 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700675 },
676 inData: true,
677 inSanitizerDir: true,
678 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900679 in: []string{"nativetest", "my_test"},
680 out: "target/product/test_device/data/asan/data/nativetest/my_test",
681 partitionDir: "target/product/test_device/data/asan/data",
Dan Willemsen00269f22017-07-06 16:59:48 -0700682 },
Dario Frenifd05a742018-05-29 13:28:54 +0100683 {
Justin Yund5f6c822019-06-25 16:47:17 +0900684 name: "sanitized system_ext native test binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100685 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700686 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800687 os: deviceTarget.Os,
Dario Frenifd05a742018-05-29 13:28:54 +0100688 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800689 earlyModuleContext: earlyModuleContext{
690 kind: systemExtSpecificModule,
691 },
Dario Frenifd05a742018-05-29 13:28:54 +0100692 },
693 inData: true,
694 inSanitizerDir: true,
695 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900696 in: []string{"nativetest", "my_test"},
697 out: "target/product/test_device/data/asan/data/nativetest/my_test",
698 partitionDir: "target/product/test_device/data/asan/data",
Colin Cross6e359402020-02-10 15:29:54 -0800699 }, {
700 name: "device testcases",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100701 ctx: &testModuleInstallPathContext{
Colin Cross6e359402020-02-10 15:29:54 -0800702 baseModuleContext: baseModuleContext{
703 os: deviceTarget.Os,
704 target: deviceTarget,
705 },
706 inTestcases: true,
707 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900708 in: []string{"my_test", "my_test_bin"},
709 out: "target/product/test_device/testcases/my_test/my_test_bin",
710 partitionDir: "target/product/test_device/testcases",
Colin Cross6e359402020-02-10 15:29:54 -0800711 }, {
712 name: "host testcases",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100713 ctx: &testModuleInstallPathContext{
Colin Cross6e359402020-02-10 15:29:54 -0800714 baseModuleContext: baseModuleContext{
715 os: hostTarget.Os,
716 target: hostTarget,
717 },
718 inTestcases: true,
719 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900720 in: []string{"my_test", "my_test_bin"},
721 out: "host/linux-x86/testcases/my_test/my_test_bin",
722 partitionDir: "host/linux-x86/testcases",
Colin Cross6e359402020-02-10 15:29:54 -0800723 }, {
724 name: "forced host testcases",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100725 ctx: &testModuleInstallPathContext{
Colin Cross6e359402020-02-10 15:29:54 -0800726 baseModuleContext: baseModuleContext{
727 os: deviceTarget.Os,
728 target: deviceTarget,
729 },
730 inTestcases: true,
731 forceOS: &Linux,
Jiyong Park87788b52020-09-01 12:37:45 +0900732 forceArch: &X86,
Colin Cross6e359402020-02-10 15:29:54 -0800733 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900734 in: []string{"my_test", "my_test_bin"},
735 out: "host/linux-x86/testcases/my_test/my_test_bin",
736 partitionDir: "host/linux-x86/testcases",
Dario Frenifd05a742018-05-29 13:28:54 +0100737 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700738 }
739
740 for _, tc := range testCases {
741 t.Run(tc.name, func(t *testing.T) {
Colin Cross0ea8ba82019-06-06 14:33:29 -0700742 tc.ctx.baseModuleContext.config = testConfig
Dan Willemsen00269f22017-07-06 16:59:48 -0700743 output := PathForModuleInstall(tc.ctx, tc.in...)
744 if output.basePath.path != tc.out {
745 t.Errorf("unexpected path:\n got: %q\nwant: %q\n",
746 output.basePath.path,
747 tc.out)
748 }
Jiyong Park957bcd92020-10-20 18:23:33 +0900749 if output.partitionDir != tc.partitionDir {
750 t.Errorf("unexpected partitionDir:\n got: %q\nwant: %q\n",
751 output.partitionDir, tc.partitionDir)
752 }
Dan Willemsen00269f22017-07-06 16:59:48 -0700753 })
754 }
755}
Colin Cross5e6cfbe2017-11-03 15:20:35 -0700756
Inseob Kimd9580b82021-04-13 21:13:49 +0900757func TestPathForModuleInstallRecoveryAsBoot(t *testing.T) {
758 testConfig := pathTestConfig("")
759 testConfig.TestProductVariables.BoardUsesRecoveryAsBoot = proptools.BoolPtr(true)
760 testConfig.TestProductVariables.BoardMoveRecoveryResourcesToVendorBoot = proptools.BoolPtr(true)
761 deviceTarget := Target{Os: Android, Arch: Arch{ArchType: Arm64}}
762
763 testCases := []struct {
764 name string
765 ctx *testModuleInstallPathContext
766 in []string
767 out string
768 partitionDir string
769 }{
770 {
771 name: "ramdisk binary",
772 ctx: &testModuleInstallPathContext{
773 baseModuleContext: baseModuleContext{
774 os: deviceTarget.Os,
775 target: deviceTarget,
776 },
777 inRamdisk: true,
778 inRoot: true,
779 },
780 in: []string{"my_test"},
781 out: "target/product/test_device/recovery/root/first_stage_ramdisk/my_test",
782 partitionDir: "target/product/test_device/recovery/root/first_stage_ramdisk",
783 },
784
785 {
786 name: "vendor_ramdisk binary",
787 ctx: &testModuleInstallPathContext{
788 baseModuleContext: baseModuleContext{
789 os: deviceTarget.Os,
790 target: deviceTarget,
791 },
792 inVendorRamdisk: true,
793 inRoot: true,
794 },
795 in: []string{"my_test"},
796 out: "target/product/test_device/vendor_ramdisk/first_stage_ramdisk/my_test",
797 partitionDir: "target/product/test_device/vendor_ramdisk/first_stage_ramdisk",
798 },
799 }
800
801 for _, tc := range testCases {
802 t.Run(tc.name, func(t *testing.T) {
803 tc.ctx.baseModuleContext.config = testConfig
804 output := PathForModuleInstall(tc.ctx, tc.in...)
805 if output.basePath.path != tc.out {
806 t.Errorf("unexpected path:\n got: %q\nwant: %q\n",
807 output.basePath.path,
808 tc.out)
809 }
810 if output.partitionDir != tc.partitionDir {
811 t.Errorf("unexpected partitionDir:\n got: %q\nwant: %q\n",
812 output.partitionDir, tc.partitionDir)
813 }
814 })
815 }
816}
817
Jiyong Park957bcd92020-10-20 18:23:33 +0900818func TestBaseDirForInstallPath(t *testing.T) {
819 testConfig := pathTestConfig("")
820 deviceTarget := Target{Os: Android, Arch: Arch{ArchType: Arm64}}
821
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100822 ctx := &testModuleInstallPathContext{
Jiyong Park957bcd92020-10-20 18:23:33 +0900823 baseModuleContext: baseModuleContext{
824 os: deviceTarget.Os,
825 target: deviceTarget,
826 },
827 }
828 ctx.baseModuleContext.config = testConfig
829
830 actual := PathForModuleInstall(ctx, "foo", "bar")
831 expectedBaseDir := "target/product/test_device/system"
832 if actual.partitionDir != expectedBaseDir {
833 t.Errorf("unexpected partitionDir:\n got: %q\nwant: %q\n", actual.partitionDir, expectedBaseDir)
834 }
835 expectedRelPath := "foo/bar"
836 if actual.Rel() != expectedRelPath {
837 t.Errorf("unexpected Rel():\n got: %q\nwant: %q\n", actual.Rel(), expectedRelPath)
838 }
839
840 actualAfterJoin := actual.Join(ctx, "baz")
841 // partitionDir is preserved even after joining
842 if actualAfterJoin.partitionDir != expectedBaseDir {
843 t.Errorf("unexpected partitionDir after joining:\n got: %q\nwant: %q\n", actualAfterJoin.partitionDir, expectedBaseDir)
844 }
845 // Rel() is updated though
846 expectedRelAfterJoin := "baz"
847 if actualAfterJoin.Rel() != expectedRelAfterJoin {
848 t.Errorf("unexpected Rel() after joining:\n got: %q\nwant: %q\n", actualAfterJoin.Rel(), expectedRelAfterJoin)
849 }
850}
851
Colin Cross5e6cfbe2017-11-03 15:20:35 -0700852func TestDirectorySortedPaths(t *testing.T) {
Colin Cross98be1bb2019-12-13 20:41:13 -0800853 config := TestConfig("out", nil, "", map[string][]byte{
854 "Android.bp": nil,
855 "a.txt": nil,
856 "a/txt": nil,
857 "a/b/c": nil,
858 "a/b/d": nil,
859 "b": nil,
860 "b/b.txt": nil,
861 "a/a.txt": nil,
Colin Cross07e51612019-03-05 12:46:40 -0800862 })
863
Colin Cross98be1bb2019-12-13 20:41:13 -0800864 ctx := PathContextForTesting(config)
865
Colin Cross5e6cfbe2017-11-03 15:20:35 -0700866 makePaths := func() Paths {
867 return Paths{
Colin Cross07e51612019-03-05 12:46:40 -0800868 PathForSource(ctx, "a.txt"),
869 PathForSource(ctx, "a/txt"),
870 PathForSource(ctx, "a/b/c"),
871 PathForSource(ctx, "a/b/d"),
872 PathForSource(ctx, "b"),
873 PathForSource(ctx, "b/b.txt"),
874 PathForSource(ctx, "a/a.txt"),
Colin Cross5e6cfbe2017-11-03 15:20:35 -0700875 }
876 }
877
878 expected := []string{
879 "a.txt",
880 "a/a.txt",
881 "a/b/c",
882 "a/b/d",
883 "a/txt",
884 "b",
885 "b/b.txt",
886 }
887
888 paths := makePaths()
Colin Crossa140bb02018-04-17 10:52:26 -0700889 reversePaths := ReversePaths(paths)
Colin Cross5e6cfbe2017-11-03 15:20:35 -0700890
891 sortedPaths := PathsToDirectorySortedPaths(paths)
892 reverseSortedPaths := PathsToDirectorySortedPaths(reversePaths)
893
894 if !reflect.DeepEqual(Paths(sortedPaths).Strings(), expected) {
895 t.Fatalf("sorted paths:\n %#v\n != \n %#v", paths.Strings(), expected)
896 }
897
898 if !reflect.DeepEqual(Paths(reverseSortedPaths).Strings(), expected) {
899 t.Fatalf("sorted reversed paths:\n %#v\n !=\n %#v", reversePaths.Strings(), expected)
900 }
901
902 expectedA := []string{
903 "a/a.txt",
904 "a/b/c",
905 "a/b/d",
906 "a/txt",
907 }
908
909 inA := sortedPaths.PathsInDirectory("a")
910 if !reflect.DeepEqual(inA.Strings(), expectedA) {
911 t.Errorf("FilesInDirectory(a):\n %#v\n != \n %#v", inA.Strings(), expectedA)
912 }
913
914 expectedA_B := []string{
915 "a/b/c",
916 "a/b/d",
917 }
918
919 inA_B := sortedPaths.PathsInDirectory("a/b")
920 if !reflect.DeepEqual(inA_B.Strings(), expectedA_B) {
921 t.Errorf("FilesInDirectory(a/b):\n %#v\n != \n %#v", inA_B.Strings(), expectedA_B)
922 }
923
924 expectedB := []string{
925 "b/b.txt",
926 }
927
928 inB := sortedPaths.PathsInDirectory("b")
929 if !reflect.DeepEqual(inB.Strings(), expectedB) {
930 t.Errorf("FilesInDirectory(b):\n %#v\n != \n %#v", inA.Strings(), expectedA)
931 }
932}
Colin Cross43f08db2018-11-12 10:13:39 -0800933
934func TestMaybeRel(t *testing.T) {
935 testCases := []struct {
936 name string
937 base string
938 target string
939 out string
940 isRel bool
941 }{
942 {
943 name: "normal",
944 base: "a/b/c",
945 target: "a/b/c/d",
946 out: "d",
947 isRel: true,
948 },
949 {
950 name: "parent",
951 base: "a/b/c/d",
952 target: "a/b/c",
953 isRel: false,
954 },
955 {
956 name: "not relative",
957 base: "a/b",
958 target: "c/d",
959 isRel: false,
960 },
961 {
962 name: "abs1",
963 base: "/a",
964 target: "a",
965 isRel: false,
966 },
967 {
968 name: "abs2",
969 base: "a",
970 target: "/a",
971 isRel: false,
972 },
973 }
974
975 for _, testCase := range testCases {
976 t.Run(testCase.name, func(t *testing.T) {
977 ctx := &configErrorWrapper{}
978 out, isRel := MaybeRel(ctx, testCase.base, testCase.target)
979 if len(ctx.errors) > 0 {
980 t.Errorf("MaybeRel(..., %s, %s) reported unexpected errors %v",
981 testCase.base, testCase.target, ctx.errors)
982 }
983 if isRel != testCase.isRel || out != testCase.out {
984 t.Errorf("MaybeRel(..., %s, %s) want %v, %v got %v, %v",
985 testCase.base, testCase.target, testCase.out, testCase.isRel, out, isRel)
986 }
987 })
988 }
989}
Colin Cross7b3dcc32019-01-24 13:14:39 -0800990
991func TestPathForSource(t *testing.T) {
992 testCases := []struct {
993 name string
994 buildDir string
995 src string
996 err string
997 }{
998 {
999 name: "normal",
1000 buildDir: "out",
1001 src: "a/b/c",
1002 },
1003 {
1004 name: "abs",
1005 buildDir: "out",
1006 src: "/a/b/c",
1007 err: "is outside directory",
1008 },
1009 {
1010 name: "in out dir",
1011 buildDir: "out",
Colin Cross7b6a55f2021-11-09 12:34:39 -08001012 src: "out/soong/a/b/c",
Colin Cross7b3dcc32019-01-24 13:14:39 -08001013 err: "is in output",
1014 },
1015 }
1016
1017 funcs := []struct {
1018 name string
1019 f func(ctx PathContext, pathComponents ...string) (SourcePath, error)
1020 }{
1021 {"pathForSource", pathForSource},
1022 {"safePathForSource", safePathForSource},
1023 }
1024
1025 for _, f := range funcs {
1026 t.Run(f.name, func(t *testing.T) {
1027 for _, test := range testCases {
1028 t.Run(test.name, func(t *testing.T) {
Colin Cross98be1bb2019-12-13 20:41:13 -08001029 testConfig := pathTestConfig(test.buildDir)
Colin Cross7b3dcc32019-01-24 13:14:39 -08001030 ctx := &configErrorWrapper{config: testConfig}
1031 _, err := f.f(ctx, test.src)
1032 if len(ctx.errors) > 0 {
1033 t.Fatalf("unexpected errors %v", ctx.errors)
1034 }
1035 if err != nil {
1036 if test.err == "" {
1037 t.Fatalf("unexpected error %q", err.Error())
1038 } else if !strings.Contains(err.Error(), test.err) {
1039 t.Fatalf("incorrect error, want substring %q got %q", test.err, err.Error())
1040 }
1041 } else {
1042 if test.err != "" {
1043 t.Fatalf("missing error %q", test.err)
1044 }
1045 }
1046 })
1047 }
1048 })
1049 }
1050}
Colin Cross8854a5a2019-02-11 14:14:16 -08001051
Colin Cross8a497952019-03-05 22:25:09 -08001052type pathForModuleSrcTestModule struct {
Colin Cross937664a2019-03-06 10:17:32 -08001053 ModuleBase
1054 props struct {
1055 Srcs []string `android:"path"`
1056 Exclude_srcs []string `android:"path"`
Colin Cross8a497952019-03-05 22:25:09 -08001057
1058 Src *string `android:"path"`
Colin Crossba71a3f2019-03-18 12:12:48 -07001059
1060 Module_handles_missing_deps bool
Colin Cross937664a2019-03-06 10:17:32 -08001061 }
1062
Colin Cross8a497952019-03-05 22:25:09 -08001063 src string
1064 rel string
1065
1066 srcs []string
Colin Cross937664a2019-03-06 10:17:32 -08001067 rels []string
Colin Cross8a497952019-03-05 22:25:09 -08001068
1069 missingDeps []string
Colin Cross937664a2019-03-06 10:17:32 -08001070}
1071
Colin Cross8a497952019-03-05 22:25:09 -08001072func pathForModuleSrcTestModuleFactory() Module {
1073 module := &pathForModuleSrcTestModule{}
Colin Cross937664a2019-03-06 10:17:32 -08001074 module.AddProperties(&module.props)
1075 InitAndroidModule(module)
1076 return module
1077}
1078
Colin Cross8a497952019-03-05 22:25:09 -08001079func (p *pathForModuleSrcTestModule) GenerateAndroidBuildActions(ctx ModuleContext) {
Colin Crossba71a3f2019-03-18 12:12:48 -07001080 var srcs Paths
1081 if p.props.Module_handles_missing_deps {
1082 srcs, p.missingDeps = PathsAndMissingDepsForModuleSrcExcludes(ctx, p.props.Srcs, p.props.Exclude_srcs)
1083 } else {
1084 srcs = PathsForModuleSrcExcludes(ctx, p.props.Srcs, p.props.Exclude_srcs)
1085 }
Colin Cross8a497952019-03-05 22:25:09 -08001086 p.srcs = srcs.Strings()
Colin Cross937664a2019-03-06 10:17:32 -08001087
Colin Cross8a497952019-03-05 22:25:09 -08001088 for _, src := range srcs {
Colin Cross937664a2019-03-06 10:17:32 -08001089 p.rels = append(p.rels, src.Rel())
1090 }
Colin Cross8a497952019-03-05 22:25:09 -08001091
1092 if p.props.Src != nil {
1093 src := PathForModuleSrc(ctx, *p.props.Src)
1094 if src != nil {
1095 p.src = src.String()
1096 p.rel = src.Rel()
1097 }
1098 }
1099
Colin Crossba71a3f2019-03-18 12:12:48 -07001100 if !p.props.Module_handles_missing_deps {
1101 p.missingDeps = ctx.GetMissingDependencies()
1102 }
Colin Cross6c4f21f2019-06-06 15:41:36 -07001103
1104 ctx.Build(pctx, BuildParams{
1105 Rule: Touch,
1106 Output: PathForModuleOut(ctx, "output"),
1107 })
Colin Cross8a497952019-03-05 22:25:09 -08001108}
1109
Colin Cross41955e82019-05-29 14:40:35 -07001110type pathForModuleSrcOutputFileProviderModule struct {
1111 ModuleBase
1112 props struct {
1113 Outs []string
1114 Tagged []string
1115 }
1116
1117 outs Paths
1118 tagged Paths
1119}
1120
1121func pathForModuleSrcOutputFileProviderModuleFactory() Module {
1122 module := &pathForModuleSrcOutputFileProviderModule{}
1123 module.AddProperties(&module.props)
1124 InitAndroidModule(module)
1125 return module
1126}
1127
1128func (p *pathForModuleSrcOutputFileProviderModule) GenerateAndroidBuildActions(ctx ModuleContext) {
1129 for _, out := range p.props.Outs {
1130 p.outs = append(p.outs, PathForModuleOut(ctx, out))
1131 }
1132
1133 for _, tagged := range p.props.Tagged {
1134 p.tagged = append(p.tagged, PathForModuleOut(ctx, tagged))
1135 }
1136}
1137
1138func (p *pathForModuleSrcOutputFileProviderModule) OutputFiles(tag string) (Paths, error) {
1139 switch tag {
1140 case "":
1141 return p.outs, nil
1142 case ".tagged":
1143 return p.tagged, nil
1144 default:
1145 return nil, fmt.Errorf("unsupported tag %q", tag)
1146 }
1147}
1148
Colin Cross8a497952019-03-05 22:25:09 -08001149type pathForModuleSrcTestCase struct {
1150 name string
1151 bp string
1152 srcs []string
1153 rels []string
1154 src string
1155 rel string
Paul Duffinec0bd8c2021-07-09 16:56:15 +01001156
1157 // Make test specific preparations to the test fixture.
1158 preparer FixturePreparer
1159
1160 // A test specific error handler.
1161 errorHandler FixtureErrorHandler
Colin Cross8a497952019-03-05 22:25:09 -08001162}
1163
Paul Duffin54054682021-03-16 21:11:42 +00001164func testPathForModuleSrc(t *testing.T, tests []pathForModuleSrcTestCase) {
Colin Cross8a497952019-03-05 22:25:09 -08001165 for _, test := range tests {
1166 t.Run(test.name, func(t *testing.T) {
Colin Cross8a497952019-03-05 22:25:09 -08001167 fgBp := `
1168 filegroup {
1169 name: "a",
1170 srcs: ["src/a"],
1171 }
1172 `
1173
Colin Cross41955e82019-05-29 14:40:35 -07001174 ofpBp := `
1175 output_file_provider {
1176 name: "b",
1177 outs: ["gen/b"],
1178 tagged: ["gen/c"],
1179 }
1180 `
1181
Paul Duffin54054682021-03-16 21:11:42 +00001182 mockFS := MockFS{
Colin Cross8a497952019-03-05 22:25:09 -08001183 "fg/Android.bp": []byte(fgBp),
1184 "foo/Android.bp": []byte(test.bp),
Colin Cross41955e82019-05-29 14:40:35 -07001185 "ofp/Android.bp": []byte(ofpBp),
Colin Cross8a497952019-03-05 22:25:09 -08001186 "fg/src/a": nil,
1187 "foo/src/b": nil,
1188 "foo/src/c": nil,
1189 "foo/src/d": nil,
1190 "foo/src/e/e": nil,
1191 "foo/src_special/$": nil,
1192 }
1193
Paul Duffinec0bd8c2021-07-09 16:56:15 +01001194 errorHandler := test.errorHandler
1195 if errorHandler == nil {
1196 errorHandler = FixtureExpectsNoErrors
1197 }
1198
Paul Duffin30ac3e72021-03-20 00:36:14 +00001199 result := GroupFixturePreparers(
Paul Duffin54054682021-03-16 21:11:42 +00001200 FixtureRegisterWithContext(func(ctx RegistrationContext) {
1201 ctx.RegisterModuleType("test", pathForModuleSrcTestModuleFactory)
1202 ctx.RegisterModuleType("output_file_provider", pathForModuleSrcOutputFileProviderModuleFactory)
Paul Duffin54054682021-03-16 21:11:42 +00001203 }),
Paul Duffinec0bd8c2021-07-09 16:56:15 +01001204 PrepareForTestWithFilegroup,
1205 PrepareForTestWithNamespace,
Paul Duffin54054682021-03-16 21:11:42 +00001206 mockFS.AddToFixture(),
Paul Duffinec0bd8c2021-07-09 16:56:15 +01001207 OptionalFixturePreparer(test.preparer),
1208 ).
1209 ExtendWithErrorHandler(errorHandler).
1210 RunTest(t)
Colin Cross8a497952019-03-05 22:25:09 -08001211
Paul Duffin54054682021-03-16 21:11:42 +00001212 m := result.ModuleForTests("foo", "").Module().(*pathForModuleSrcTestModule)
Colin Crossae8600b2020-10-29 17:09:13 -07001213
Paul Duffin54054682021-03-16 21:11:42 +00001214 AssertStringPathsRelativeToTopEquals(t, "srcs", result.Config, test.srcs, m.srcs)
1215 AssertStringPathsRelativeToTopEquals(t, "rels", result.Config, test.rels, m.rels)
1216 AssertStringPathRelativeToTopEquals(t, "src", result.Config, test.src, m.src)
1217 AssertStringPathRelativeToTopEquals(t, "rel", result.Config, test.rel, m.rel)
Colin Cross8a497952019-03-05 22:25:09 -08001218 })
1219 }
Colin Cross937664a2019-03-06 10:17:32 -08001220}
1221
Colin Cross8a497952019-03-05 22:25:09 -08001222func TestPathsForModuleSrc(t *testing.T) {
1223 tests := []pathForModuleSrcTestCase{
Colin Cross937664a2019-03-06 10:17:32 -08001224 {
1225 name: "path",
1226 bp: `
1227 test {
1228 name: "foo",
1229 srcs: ["src/b"],
1230 }`,
1231 srcs: []string{"foo/src/b"},
1232 rels: []string{"src/b"},
1233 },
1234 {
1235 name: "glob",
1236 bp: `
1237 test {
1238 name: "foo",
1239 srcs: [
1240 "src/*",
1241 "src/e/*",
1242 ],
1243 }`,
1244 srcs: []string{"foo/src/b", "foo/src/c", "foo/src/d", "foo/src/e/e"},
1245 rels: []string{"src/b", "src/c", "src/d", "src/e/e"},
1246 },
1247 {
1248 name: "recursive glob",
1249 bp: `
1250 test {
1251 name: "foo",
1252 srcs: ["src/**/*"],
1253 }`,
1254 srcs: []string{"foo/src/b", "foo/src/c", "foo/src/d", "foo/src/e/e"},
1255 rels: []string{"src/b", "src/c", "src/d", "src/e/e"},
1256 },
1257 {
1258 name: "filegroup",
1259 bp: `
1260 test {
1261 name: "foo",
1262 srcs: [":a"],
1263 }`,
1264 srcs: []string{"fg/src/a"},
1265 rels: []string{"src/a"},
1266 },
1267 {
Colin Cross41955e82019-05-29 14:40:35 -07001268 name: "output file provider",
1269 bp: `
1270 test {
1271 name: "foo",
1272 srcs: [":b"],
1273 }`,
Paul Duffin54054682021-03-16 21:11:42 +00001274 srcs: []string{"out/soong/.intermediates/ofp/b/gen/b"},
Colin Cross41955e82019-05-29 14:40:35 -07001275 rels: []string{"gen/b"},
1276 },
1277 {
1278 name: "output file provider tagged",
1279 bp: `
1280 test {
1281 name: "foo",
1282 srcs: [":b{.tagged}"],
1283 }`,
Paul Duffin54054682021-03-16 21:11:42 +00001284 srcs: []string{"out/soong/.intermediates/ofp/b/gen/c"},
Colin Cross41955e82019-05-29 14:40:35 -07001285 rels: []string{"gen/c"},
1286 },
1287 {
Jooyung Han7607dd32020-07-05 10:23:14 +09001288 name: "output file provider with exclude",
1289 bp: `
1290 test {
1291 name: "foo",
1292 srcs: [":b", ":c"],
1293 exclude_srcs: [":c"]
1294 }
1295 output_file_provider {
1296 name: "c",
1297 outs: ["gen/c"],
1298 }`,
Paul Duffin54054682021-03-16 21:11:42 +00001299 srcs: []string{"out/soong/.intermediates/ofp/b/gen/b"},
Jooyung Han7607dd32020-07-05 10:23:14 +09001300 rels: []string{"gen/b"},
1301 },
1302 {
Colin Cross937664a2019-03-06 10:17:32 -08001303 name: "special characters glob",
1304 bp: `
1305 test {
1306 name: "foo",
1307 srcs: ["src_special/*"],
1308 }`,
1309 srcs: []string{"foo/src_special/$"},
1310 rels: []string{"src_special/$"},
1311 },
1312 }
1313
Paul Duffin54054682021-03-16 21:11:42 +00001314 testPathForModuleSrc(t, tests)
Colin Cross41955e82019-05-29 14:40:35 -07001315}
1316
1317func TestPathForModuleSrc(t *testing.T) {
Colin Cross8a497952019-03-05 22:25:09 -08001318 tests := []pathForModuleSrcTestCase{
1319 {
1320 name: "path",
1321 bp: `
1322 test {
1323 name: "foo",
1324 src: "src/b",
1325 }`,
1326 src: "foo/src/b",
1327 rel: "src/b",
1328 },
1329 {
1330 name: "glob",
1331 bp: `
1332 test {
1333 name: "foo",
1334 src: "src/e/*",
1335 }`,
1336 src: "foo/src/e/e",
1337 rel: "src/e/e",
1338 },
1339 {
1340 name: "filegroup",
1341 bp: `
1342 test {
1343 name: "foo",
1344 src: ":a",
1345 }`,
1346 src: "fg/src/a",
1347 rel: "src/a",
1348 },
1349 {
Colin Cross41955e82019-05-29 14:40:35 -07001350 name: "output file provider",
1351 bp: `
1352 test {
1353 name: "foo",
1354 src: ":b",
1355 }`,
Paul Duffin54054682021-03-16 21:11:42 +00001356 src: "out/soong/.intermediates/ofp/b/gen/b",
Colin Cross41955e82019-05-29 14:40:35 -07001357 rel: "gen/b",
1358 },
1359 {
1360 name: "output file provider tagged",
1361 bp: `
1362 test {
1363 name: "foo",
1364 src: ":b{.tagged}",
1365 }`,
Paul Duffin54054682021-03-16 21:11:42 +00001366 src: "out/soong/.intermediates/ofp/b/gen/c",
Colin Cross41955e82019-05-29 14:40:35 -07001367 rel: "gen/c",
1368 },
1369 {
Colin Cross8a497952019-03-05 22:25:09 -08001370 name: "special characters glob",
1371 bp: `
1372 test {
1373 name: "foo",
1374 src: "src_special/*",
1375 }`,
1376 src: "foo/src_special/$",
1377 rel: "src_special/$",
1378 },
Paul Duffinec0bd8c2021-07-09 16:56:15 +01001379 {
1380 // This test makes sure that an unqualified module name cannot contain characters that make
1381 // it appear as a qualified module name.
Paul Duffinec0bd8c2021-07-09 16:56:15 +01001382 name: "output file provider, invalid fully qualified name",
1383 bp: `
1384 test {
1385 name: "foo",
1386 src: "://other:b",
1387 srcs: ["://other:c"],
1388 }`,
1389 preparer: FixtureAddTextFile("other/Android.bp", `
1390 soong_namespace {}
1391
1392 output_file_provider {
1393 name: "b",
1394 outs: ["gen/b"],
1395 }
1396
1397 output_file_provider {
1398 name: "c",
1399 outs: ["gen/c"],
1400 }
1401 `),
Paul Duffine6ba0722021-07-12 20:12:12 +01001402 src: "foo/:/other:b",
1403 rel: ":/other:b",
1404 srcs: []string{"foo/:/other:c"},
1405 rels: []string{":/other:c"},
Paul Duffinec0bd8c2021-07-09 16:56:15 +01001406 },
1407 {
Paul Duffinec0bd8c2021-07-09 16:56:15 +01001408 name: "output file provider, missing fully qualified name",
1409 bp: `
1410 test {
1411 name: "foo",
1412 src: "//other:b",
1413 srcs: ["//other:c"],
1414 }`,
Paul Duffinec0bd8c2021-07-09 16:56:15 +01001415 errorHandler: FixtureExpectsAllErrorsToMatchAPattern([]string{
Paul Duffine6ba0722021-07-12 20:12:12 +01001416 `"foo" depends on undefined module "//other:b"`,
1417 `"foo" depends on undefined module "//other:c"`,
Paul Duffinec0bd8c2021-07-09 16:56:15 +01001418 }),
1419 },
1420 {
Paul Duffinec0bd8c2021-07-09 16:56:15 +01001421 name: "output file provider, fully qualified name",
1422 bp: `
1423 test {
1424 name: "foo",
1425 src: "//other:b",
1426 srcs: ["//other:c"],
1427 }`,
Paul Duffin40131a32021-07-09 17:10:35 +01001428 src: "out/soong/.intermediates/other/b/gen/b",
1429 rel: "gen/b",
1430 srcs: []string{"out/soong/.intermediates/other/c/gen/c"},
1431 rels: []string{"gen/c"},
Paul Duffinec0bd8c2021-07-09 16:56:15 +01001432 preparer: FixtureAddTextFile("other/Android.bp", `
1433 soong_namespace {}
1434
1435 output_file_provider {
1436 name: "b",
1437 outs: ["gen/b"],
1438 }
1439
1440 output_file_provider {
1441 name: "c",
1442 outs: ["gen/c"],
1443 }
1444 `),
Paul Duffinec0bd8c2021-07-09 16:56:15 +01001445 },
Colin Cross8a497952019-03-05 22:25:09 -08001446 }
1447
Paul Duffin54054682021-03-16 21:11:42 +00001448 testPathForModuleSrc(t, tests)
Colin Cross8a497952019-03-05 22:25:09 -08001449}
Colin Cross937664a2019-03-06 10:17:32 -08001450
Colin Cross8a497952019-03-05 22:25:09 -08001451func TestPathsForModuleSrc_AllowMissingDependencies(t *testing.T) {
Colin Cross8a497952019-03-05 22:25:09 -08001452 bp := `
1453 test {
1454 name: "foo",
1455 srcs: [":a"],
1456 exclude_srcs: [":b"],
1457 src: ":c",
1458 }
Colin Crossba71a3f2019-03-18 12:12:48 -07001459
1460 test {
1461 name: "bar",
1462 srcs: [":d"],
1463 exclude_srcs: [":e"],
1464 module_handles_missing_deps: true,
1465 }
Colin Cross8a497952019-03-05 22:25:09 -08001466 `
1467
Paul Duffin30ac3e72021-03-20 00:36:14 +00001468 result := GroupFixturePreparers(
Paul Duffin54054682021-03-16 21:11:42 +00001469 PrepareForTestWithAllowMissingDependencies,
1470 FixtureRegisterWithContext(func(ctx RegistrationContext) {
1471 ctx.RegisterModuleType("test", pathForModuleSrcTestModuleFactory)
1472 }),
1473 FixtureWithRootAndroidBp(bp),
Paul Duffin30ac3e72021-03-20 00:36:14 +00001474 ).RunTest(t)
Colin Cross8a497952019-03-05 22:25:09 -08001475
Paul Duffin54054682021-03-16 21:11:42 +00001476 foo := result.ModuleForTests("foo", "").Module().(*pathForModuleSrcTestModule)
Colin Cross8a497952019-03-05 22:25:09 -08001477
Paul Duffin54054682021-03-16 21:11:42 +00001478 AssertArrayString(t, "foo missing deps", []string{"a", "b", "c"}, foo.missingDeps)
1479 AssertArrayString(t, "foo srcs", []string{}, foo.srcs)
1480 AssertStringEquals(t, "foo src", "", foo.src)
Colin Cross98be1bb2019-12-13 20:41:13 -08001481
Paul Duffin54054682021-03-16 21:11:42 +00001482 bar := result.ModuleForTests("bar", "").Module().(*pathForModuleSrcTestModule)
Colin Cross98be1bb2019-12-13 20:41:13 -08001483
Paul Duffin54054682021-03-16 21:11:42 +00001484 AssertArrayString(t, "bar missing deps", []string{"d", "e"}, bar.missingDeps)
1485 AssertArrayString(t, "bar srcs", []string{}, bar.srcs)
Colin Cross937664a2019-03-06 10:17:32 -08001486}
1487
Paul Duffin567465d2021-03-16 01:21:34 +00001488func TestPathRelativeToTop(t *testing.T) {
1489 testConfig := pathTestConfig("/tmp/build/top")
1490 deviceTarget := Target{Os: Android, Arch: Arch{ArchType: Arm64}}
1491
1492 ctx := &testModuleInstallPathContext{
1493 baseModuleContext: baseModuleContext{
1494 os: deviceTarget.Os,
1495 target: deviceTarget,
1496 },
1497 }
1498 ctx.baseModuleContext.config = testConfig
1499
1500 t.Run("install for soong", func(t *testing.T) {
1501 p := PathForModuleInstall(ctx, "install/path")
1502 AssertPathRelativeToTopEquals(t, "install path for soong", "out/soong/target/product/test_device/system/install/path", p)
1503 })
1504 t.Run("install for make", func(t *testing.T) {
Colin Crossc68db4b2021-11-11 18:59:15 -08001505 p := PathForModuleInstall(ctx, "install/path")
1506 p.makePath = true
Paul Duffin567465d2021-03-16 01:21:34 +00001507 AssertPathRelativeToTopEquals(t, "install path for make", "out/target/product/test_device/system/install/path", p)
1508 })
1509 t.Run("output", func(t *testing.T) {
1510 p := PathForOutput(ctx, "output/path")
1511 AssertPathRelativeToTopEquals(t, "output path", "out/soong/output/path", p)
1512 })
1513 t.Run("source", func(t *testing.T) {
1514 p := PathForSource(ctx, "source/path")
1515 AssertPathRelativeToTopEquals(t, "source path", "source/path", p)
1516 })
1517 t.Run("mixture", func(t *testing.T) {
1518 paths := Paths{
1519 PathForModuleInstall(ctx, "install/path"),
Paul Duffin567465d2021-03-16 01:21:34 +00001520 PathForOutput(ctx, "output/path"),
1521 PathForSource(ctx, "source/path"),
1522 }
1523
1524 expected := []string{
1525 "out/soong/target/product/test_device/system/install/path",
Paul Duffin567465d2021-03-16 01:21:34 +00001526 "out/soong/output/path",
1527 "source/path",
1528 }
1529 AssertPathsRelativeToTopEquals(t, "mixture", expected, paths)
1530 })
1531}
1532
Colin Cross8854a5a2019-02-11 14:14:16 -08001533func ExampleOutputPath_ReplaceExtension() {
1534 ctx := &configErrorWrapper{
Colin Cross98be1bb2019-12-13 20:41:13 -08001535 config: TestConfig("out", nil, "", nil),
Colin Cross8854a5a2019-02-11 14:14:16 -08001536 }
Colin Cross2cdd5df2019-02-25 10:25:24 -08001537 p := PathForOutput(ctx, "system/framework").Join(ctx, "boot.art")
Colin Cross8854a5a2019-02-11 14:14:16 -08001538 p2 := p.ReplaceExtension(ctx, "oat")
1539 fmt.Println(p, p2)
Colin Cross2cdd5df2019-02-25 10:25:24 -08001540 fmt.Println(p.Rel(), p2.Rel())
Colin Cross8854a5a2019-02-11 14:14:16 -08001541
1542 // Output:
Colin Cross7b6a55f2021-11-09 12:34:39 -08001543 // out/soong/system/framework/boot.art out/soong/system/framework/boot.oat
Colin Cross2cdd5df2019-02-25 10:25:24 -08001544 // boot.art boot.oat
Colin Cross8854a5a2019-02-11 14:14:16 -08001545}
Colin Cross40e33732019-02-15 11:08:35 -08001546
Colin Cross41b46762020-10-09 19:26:32 -07001547func ExampleOutputPath_InSameDir() {
Colin Cross40e33732019-02-15 11:08:35 -08001548 ctx := &configErrorWrapper{
Colin Cross98be1bb2019-12-13 20:41:13 -08001549 config: TestConfig("out", nil, "", nil),
Colin Cross40e33732019-02-15 11:08:35 -08001550 }
Colin Cross2cdd5df2019-02-25 10:25:24 -08001551 p := PathForOutput(ctx, "system/framework").Join(ctx, "boot.art")
Colin Cross40e33732019-02-15 11:08:35 -08001552 p2 := p.InSameDir(ctx, "oat", "arm", "boot.vdex")
1553 fmt.Println(p, p2)
Colin Cross2cdd5df2019-02-25 10:25:24 -08001554 fmt.Println(p.Rel(), p2.Rel())
Colin Cross40e33732019-02-15 11:08:35 -08001555
1556 // Output:
Colin Cross7b6a55f2021-11-09 12:34:39 -08001557 // out/soong/system/framework/boot.art out/soong/system/framework/oat/arm/boot.vdex
Colin Cross2cdd5df2019-02-25 10:25:24 -08001558 // boot.art oat/arm/boot.vdex
Colin Cross40e33732019-02-15 11:08:35 -08001559}
Colin Cross27027c72020-02-28 15:34:17 -08001560
1561func BenchmarkFirstUniquePaths(b *testing.B) {
1562 implementations := []struct {
1563 name string
1564 f func(Paths) Paths
1565 }{
1566 {
1567 name: "list",
1568 f: firstUniquePathsList,
1569 },
1570 {
1571 name: "map",
1572 f: firstUniquePathsMap,
1573 },
1574 }
1575 const maxSize = 1024
1576 uniquePaths := make(Paths, maxSize)
1577 for i := range uniquePaths {
1578 uniquePaths[i] = PathForTesting(strconv.Itoa(i))
1579 }
1580 samePath := make(Paths, maxSize)
1581 for i := range samePath {
1582 samePath[i] = uniquePaths[0]
1583 }
1584
1585 f := func(b *testing.B, imp func(Paths) Paths, paths Paths) {
1586 for i := 0; i < b.N; i++ {
1587 b.ReportAllocs()
1588 paths = append(Paths(nil), paths...)
1589 imp(paths)
1590 }
1591 }
1592
1593 for n := 1; n <= maxSize; n <<= 1 {
1594 b.Run(strconv.Itoa(n), func(b *testing.B) {
1595 for _, implementation := range implementations {
1596 b.Run(implementation.name, func(b *testing.B) {
1597 b.Run("same", func(b *testing.B) {
1598 f(b, implementation.f, samePath[:n])
1599 })
1600 b.Run("unique", func(b *testing.B) {
1601 f(b, implementation.f, uniquePaths[:n])
1602 })
1603 })
1604 }
1605 })
1606 }
1607}