blob: 7675905fc47d7c0acf71e2e710cef39a8ffa3ade [file] [log] [blame]
Dan Willemsen34cc69e2015-09-23 15:26:20 -07001// Copyright 2015 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
Colin Cross635c3b02016-05-18 15:37:25 -070015package android
Dan Willemsen34cc69e2015-09-23 15:26:20 -070016
17import (
18 "errors"
19 "fmt"
20 "reflect"
Colin Cross27027c72020-02-28 15:34:17 -080021 "strconv"
Dan Willemsen34cc69e2015-09-23 15:26:20 -070022 "strings"
23 "testing"
Inseob Kimd9580b82021-04-13 21:13:49 +090024
25 "github.com/google/blueprint/proptools"
Dan Willemsen34cc69e2015-09-23 15:26:20 -070026)
27
28type strsTestCase struct {
29 in []string
30 out string
31 err []error
32}
33
34var commonValidatePathTestCases = []strsTestCase{
35 {
36 in: []string{""},
37 out: "",
38 },
39 {
40 in: []string{"a/b"},
41 out: "a/b",
42 },
43 {
44 in: []string{"a/b", "c"},
45 out: "a/b/c",
46 },
47 {
48 in: []string{"a/.."},
49 out: ".",
50 },
51 {
52 in: []string{"."},
53 out: ".",
54 },
55 {
56 in: []string{".."},
57 out: "",
58 err: []error{errors.New("Path is outside directory: ..")},
59 },
60 {
61 in: []string{"../a"},
62 out: "",
63 err: []error{errors.New("Path is outside directory: ../a")},
64 },
65 {
66 in: []string{"b/../../a"},
67 out: "",
68 err: []error{errors.New("Path is outside directory: ../a")},
69 },
70 {
71 in: []string{"/a"},
72 out: "",
73 err: []error{errors.New("Path is outside directory: /a")},
74 },
Dan Willemsen80a7c2a2015-12-21 14:57:11 -080075 {
76 in: []string{"a", "../b"},
77 out: "",
78 err: []error{errors.New("Path is outside directory: ../b")},
79 },
80 {
81 in: []string{"a", "b/../../c"},
82 out: "",
83 err: []error{errors.New("Path is outside directory: ../c")},
84 },
85 {
86 in: []string{"a", "./.."},
87 out: "",
88 err: []error{errors.New("Path is outside directory: ..")},
89 },
Dan Willemsen34cc69e2015-09-23 15:26:20 -070090}
91
92var validateSafePathTestCases = append(commonValidatePathTestCases, []strsTestCase{
93 {
94 in: []string{"$host/../$a"},
95 out: "$a",
96 },
97}...)
98
99var validatePathTestCases = append(commonValidatePathTestCases, []strsTestCase{
100 {
101 in: []string{"$host/../$a"},
102 out: "",
103 err: []error{errors.New("Path contains invalid character($): $host/../$a")},
104 },
105 {
106 in: []string{"$host/.."},
107 out: "",
108 err: []error{errors.New("Path contains invalid character($): $host/..")},
109 },
110}...)
111
112func TestValidateSafePath(t *testing.T) {
113 for _, testCase := range validateSafePathTestCases {
Colin Crossdc75ae72018-02-22 13:48:13 -0800114 t.Run(strings.Join(testCase.in, ","), func(t *testing.T) {
115 ctx := &configErrorWrapper{}
Colin Cross1ccfcc32018-02-22 13:54:26 -0800116 out, err := validateSafePath(testCase.in...)
117 if err != nil {
118 reportPathError(ctx, err)
119 }
Colin Crossdc75ae72018-02-22 13:48:13 -0800120 check(t, "validateSafePath", p(testCase.in), out, ctx.errors, testCase.out, testCase.err)
121 })
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700122 }
123}
124
125func TestValidatePath(t *testing.T) {
126 for _, testCase := range validatePathTestCases {
Colin Crossdc75ae72018-02-22 13:48:13 -0800127 t.Run(strings.Join(testCase.in, ","), func(t *testing.T) {
128 ctx := &configErrorWrapper{}
Colin Cross1ccfcc32018-02-22 13:54:26 -0800129 out, err := validatePath(testCase.in...)
130 if err != nil {
131 reportPathError(ctx, err)
132 }
Colin Crossdc75ae72018-02-22 13:48:13 -0800133 check(t, "validatePath", p(testCase.in), out, ctx.errors, testCase.out, testCase.err)
134 })
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700135 }
136}
137
138func TestOptionalPath(t *testing.T) {
139 var path OptionalPath
140 checkInvalidOptionalPath(t, path)
141
142 path = OptionalPathForPath(nil)
143 checkInvalidOptionalPath(t, path)
Paul Duffinef081852021-05-13 11:11:15 +0100144
145 path = OptionalPathForPath(PathForTesting("path"))
146 checkValidOptionalPath(t, path, "path")
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700147}
148
149func checkInvalidOptionalPath(t *testing.T, path OptionalPath) {
Colin Crossdc75ae72018-02-22 13:48:13 -0800150 t.Helper()
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700151 if path.Valid() {
152 t.Errorf("Uninitialized OptionalPath should not be valid")
153 }
154 if path.String() != "" {
155 t.Errorf("Uninitialized OptionalPath String() should return \"\", not %q", path.String())
156 }
Paul Duffinef081852021-05-13 11:11:15 +0100157 paths := path.AsPaths()
158 if len(paths) != 0 {
159 t.Errorf("Uninitialized OptionalPath AsPaths() should return empty Paths, not %q", paths)
160 }
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700161 defer func() {
162 if r := recover(); r == nil {
163 t.Errorf("Expected a panic when calling Path() on an uninitialized OptionalPath")
164 }
165 }()
166 path.Path()
167}
168
Paul Duffinef081852021-05-13 11:11:15 +0100169func checkValidOptionalPath(t *testing.T, path OptionalPath, expectedString string) {
170 t.Helper()
171 if !path.Valid() {
172 t.Errorf("Initialized OptionalPath should not be invalid")
173 }
174 if path.String() != expectedString {
175 t.Errorf("Initialized OptionalPath String() should return %q, not %q", expectedString, path.String())
176 }
177 paths := path.AsPaths()
178 if len(paths) != 1 {
179 t.Errorf("Initialized OptionalPath AsPaths() should return Paths with length 1, not %q", paths)
180 }
181 path.Path()
182}
183
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700184func check(t *testing.T, testType, testString string,
185 got interface{}, err []error,
186 expected interface{}, expectedErr []error) {
Colin Crossdc75ae72018-02-22 13:48:13 -0800187 t.Helper()
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700188
189 printedTestCase := false
190 e := func(s string, expected, got interface{}) {
Colin Crossdc75ae72018-02-22 13:48:13 -0800191 t.Helper()
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700192 if !printedTestCase {
193 t.Errorf("test case %s: %s", testType, testString)
194 printedTestCase = true
195 }
196 t.Errorf("incorrect %s", s)
197 t.Errorf(" expected: %s", p(expected))
198 t.Errorf(" got: %s", p(got))
199 }
200
201 if !reflect.DeepEqual(expectedErr, err) {
202 e("errors:", expectedErr, err)
203 }
204
205 if !reflect.DeepEqual(expected, got) {
206 e("output:", expected, got)
207 }
208}
209
210func p(in interface{}) string {
211 if v, ok := in.([]interface{}); ok {
212 s := make([]string, len(v))
213 for i := range v {
214 s[i] = fmt.Sprintf("%#v", v[i])
215 }
216 return "[" + strings.Join(s, ", ") + "]"
217 } else {
218 return fmt.Sprintf("%#v", in)
219 }
220}
Dan Willemsen00269f22017-07-06 16:59:48 -0700221
Colin Cross98be1bb2019-12-13 20:41:13 -0800222func pathTestConfig(buildDir string) Config {
223 return TestConfig(buildDir, nil, "", nil)
224}
225
Dan Willemsen00269f22017-07-06 16:59:48 -0700226func TestPathForModuleInstall(t *testing.T) {
Colin Cross98be1bb2019-12-13 20:41:13 -0800227 testConfig := pathTestConfig("")
Dan Willemsen00269f22017-07-06 16:59:48 -0700228
Jiyong Park87788b52020-09-01 12:37:45 +0900229 hostTarget := Target{Os: Linux, Arch: Arch{ArchType: X86}}
230 deviceTarget := Target{Os: Android, Arch: Arch{ArchType: Arm64}}
Dan Willemsen00269f22017-07-06 16:59:48 -0700231
232 testCases := []struct {
Jiyong Park957bcd92020-10-20 18:23:33 +0900233 name string
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100234 ctx *testModuleInstallPathContext
Jiyong Park957bcd92020-10-20 18:23:33 +0900235 in []string
236 out string
237 partitionDir string
Dan Willemsen00269f22017-07-06 16:59:48 -0700238 }{
239 {
240 name: "host binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100241 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700242 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800243 os: hostTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700244 target: hostTarget,
245 },
246 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900247 in: []string{"bin", "my_test"},
248 out: "host/linux-x86/bin/my_test",
249 partitionDir: "host/linux-x86",
Dan Willemsen00269f22017-07-06 16:59:48 -0700250 },
251
252 {
253 name: "system binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100254 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700255 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800256 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700257 target: deviceTarget,
258 },
259 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900260 in: []string{"bin", "my_test"},
261 out: "target/product/test_device/system/bin/my_test",
262 partitionDir: "target/product/test_device/system",
Dan Willemsen00269f22017-07-06 16:59:48 -0700263 },
264 {
265 name: "vendor 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,
Colin Cross1184b642019-12-30 18:43:07 -0800270 earlyModuleContext: earlyModuleContext{
271 kind: socSpecificModule,
272 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700273 },
274 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900275 in: []string{"bin", "my_test"},
276 out: "target/product/test_device/vendor/bin/my_test",
277 partitionDir: "target/product/test_device/vendor",
Dan Willemsen00269f22017-07-06 16:59:48 -0700278 },
Jiyong Park2db76922017-11-08 16:03:48 +0900279 {
280 name: "odm binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100281 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700282 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800283 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900284 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800285 earlyModuleContext: earlyModuleContext{
286 kind: deviceSpecificModule,
287 },
Jiyong Park2db76922017-11-08 16:03:48 +0900288 },
289 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900290 in: []string{"bin", "my_test"},
291 out: "target/product/test_device/odm/bin/my_test",
292 partitionDir: "target/product/test_device/odm",
Jiyong Park2db76922017-11-08 16:03:48 +0900293 },
294 {
Jaekyun Seok5cfbfbb2018-01-10 19:00:15 +0900295 name: "product binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100296 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700297 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800298 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900299 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800300 earlyModuleContext: earlyModuleContext{
301 kind: productSpecificModule,
302 },
Jiyong Park2db76922017-11-08 16:03:48 +0900303 },
304 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900305 in: []string{"bin", "my_test"},
306 out: "target/product/test_device/product/bin/my_test",
307 partitionDir: "target/product/test_device/product",
Jiyong Park2db76922017-11-08 16:03:48 +0900308 },
Dario Frenifd05a742018-05-29 13:28:54 +0100309 {
Justin Yund5f6c822019-06-25 16:47:17 +0900310 name: "system_ext binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100311 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700312 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800313 os: deviceTarget.Os,
Dario Frenifd05a742018-05-29 13:28:54 +0100314 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800315 earlyModuleContext: earlyModuleContext{
316 kind: systemExtSpecificModule,
317 },
Dario Frenifd05a742018-05-29 13:28:54 +0100318 },
319 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900320 in: []string{"bin", "my_test"},
321 out: "target/product/test_device/system_ext/bin/my_test",
322 partitionDir: "target/product/test_device/system_ext",
Dario Frenifd05a742018-05-29 13:28:54 +0100323 },
Colin Cross90ba5f42019-10-02 11:10:58 -0700324 {
325 name: "root binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100326 ctx: &testModuleInstallPathContext{
Colin Cross90ba5f42019-10-02 11:10:58 -0700327 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800328 os: deviceTarget.Os,
Colin Cross90ba5f42019-10-02 11:10:58 -0700329 target: deviceTarget,
330 },
331 inRoot: true,
332 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900333 in: []string{"my_test"},
334 out: "target/product/test_device/root/my_test",
335 partitionDir: "target/product/test_device/root",
Colin Cross90ba5f42019-10-02 11:10:58 -0700336 },
337 {
338 name: "recovery binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100339 ctx: &testModuleInstallPathContext{
Colin Cross90ba5f42019-10-02 11:10:58 -0700340 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800341 os: deviceTarget.Os,
Colin Cross90ba5f42019-10-02 11:10:58 -0700342 target: deviceTarget,
343 },
344 inRecovery: true,
345 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900346 in: []string{"bin/my_test"},
347 out: "target/product/test_device/recovery/root/system/bin/my_test",
348 partitionDir: "target/product/test_device/recovery/root/system",
Colin Cross90ba5f42019-10-02 11:10:58 -0700349 },
350 {
351 name: "recovery root binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100352 ctx: &testModuleInstallPathContext{
Colin Cross90ba5f42019-10-02 11:10:58 -0700353 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800354 os: deviceTarget.Os,
Colin Cross90ba5f42019-10-02 11:10:58 -0700355 target: deviceTarget,
356 },
357 inRecovery: true,
358 inRoot: true,
359 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900360 in: []string{"my_test"},
361 out: "target/product/test_device/recovery/root/my_test",
362 partitionDir: "target/product/test_device/recovery/root",
Colin Cross90ba5f42019-10-02 11:10:58 -0700363 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700364
365 {
Inseob Kimd9580b82021-04-13 21:13:49 +0900366 name: "ramdisk binary",
367 ctx: &testModuleInstallPathContext{
368 baseModuleContext: baseModuleContext{
369 os: deviceTarget.Os,
370 target: deviceTarget,
371 },
372 inRamdisk: true,
373 },
374 in: []string{"my_test"},
375 out: "target/product/test_device/ramdisk/system/my_test",
376 partitionDir: "target/product/test_device/ramdisk/system",
377 },
378 {
379 name: "ramdisk root binary",
380 ctx: &testModuleInstallPathContext{
381 baseModuleContext: baseModuleContext{
382 os: deviceTarget.Os,
383 target: deviceTarget,
384 },
385 inRamdisk: true,
386 inRoot: true,
387 },
388 in: []string{"my_test"},
389 out: "target/product/test_device/ramdisk/my_test",
390 partitionDir: "target/product/test_device/ramdisk",
391 },
392 {
393 name: "vendor_ramdisk binary",
394 ctx: &testModuleInstallPathContext{
395 baseModuleContext: baseModuleContext{
396 os: deviceTarget.Os,
397 target: deviceTarget,
398 },
399 inVendorRamdisk: true,
400 },
401 in: []string{"my_test"},
402 out: "target/product/test_device/vendor_ramdisk/system/my_test",
403 partitionDir: "target/product/test_device/vendor_ramdisk/system",
404 },
405 {
406 name: "vendor_ramdisk root binary",
407 ctx: &testModuleInstallPathContext{
408 baseModuleContext: baseModuleContext{
409 os: deviceTarget.Os,
410 target: deviceTarget,
411 },
412 inVendorRamdisk: true,
413 inRoot: true,
414 },
415 in: []string{"my_test"},
416 out: "target/product/test_device/vendor_ramdisk/my_test",
417 partitionDir: "target/product/test_device/vendor_ramdisk",
418 },
419 {
Inseob Kim08758f02021-04-08 21:13:22 +0900420 name: "debug_ramdisk binary",
421 ctx: &testModuleInstallPathContext{
422 baseModuleContext: baseModuleContext{
423 os: deviceTarget.Os,
424 target: deviceTarget,
425 },
426 inDebugRamdisk: true,
427 },
428 in: []string{"my_test"},
429 out: "target/product/test_device/debug_ramdisk/my_test",
430 partitionDir: "target/product/test_device/debug_ramdisk",
431 },
432 {
Dan Willemsen00269f22017-07-06 16:59:48 -0700433 name: "system native test binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100434 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700435 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800436 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700437 target: deviceTarget,
438 },
439 inData: true,
440 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900441 in: []string{"nativetest", "my_test"},
442 out: "target/product/test_device/data/nativetest/my_test",
443 partitionDir: "target/product/test_device/data",
Dan Willemsen00269f22017-07-06 16:59:48 -0700444 },
445 {
446 name: "vendor native test binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100447 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700448 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800449 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700450 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800451 earlyModuleContext: earlyModuleContext{
452 kind: socSpecificModule,
453 },
Jiyong Park2db76922017-11-08 16:03:48 +0900454 },
455 inData: true,
456 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900457 in: []string{"nativetest", "my_test"},
458 out: "target/product/test_device/data/nativetest/my_test",
459 partitionDir: "target/product/test_device/data",
Jiyong Park2db76922017-11-08 16:03:48 +0900460 },
461 {
462 name: "odm native test binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100463 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700464 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800465 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900466 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800467 earlyModuleContext: earlyModuleContext{
468 kind: deviceSpecificModule,
469 },
Jiyong Park2db76922017-11-08 16:03:48 +0900470 },
471 inData: true,
472 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900473 in: []string{"nativetest", "my_test"},
474 out: "target/product/test_device/data/nativetest/my_test",
475 partitionDir: "target/product/test_device/data",
Jiyong Park2db76922017-11-08 16:03:48 +0900476 },
477 {
Jaekyun Seok5cfbfbb2018-01-10 19:00:15 +0900478 name: "product native test binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100479 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700480 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800481 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900482 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800483 earlyModuleContext: earlyModuleContext{
484 kind: productSpecificModule,
485 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700486 },
487 inData: true,
488 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900489 in: []string{"nativetest", "my_test"},
490 out: "target/product/test_device/data/nativetest/my_test",
491 partitionDir: "target/product/test_device/data",
Dan Willemsen00269f22017-07-06 16:59:48 -0700492 },
493
494 {
Justin Yund5f6c822019-06-25 16:47:17 +0900495 name: "system_ext native test binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100496 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700497 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800498 os: deviceTarget.Os,
Dario Frenifd05a742018-05-29 13:28:54 +0100499 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800500 earlyModuleContext: earlyModuleContext{
501 kind: systemExtSpecificModule,
502 },
Dario Frenifd05a742018-05-29 13:28:54 +0100503 },
504 inData: true,
505 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900506 in: []string{"nativetest", "my_test"},
507 out: "target/product/test_device/data/nativetest/my_test",
508 partitionDir: "target/product/test_device/data",
Dario Frenifd05a742018-05-29 13:28:54 +0100509 },
510
511 {
Dan Willemsen00269f22017-07-06 16:59:48 -0700512 name: "sanitized system binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100513 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700514 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800515 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700516 target: deviceTarget,
517 },
518 inSanitizerDir: true,
519 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900520 in: []string{"bin", "my_test"},
521 out: "target/product/test_device/data/asan/system/bin/my_test",
522 partitionDir: "target/product/test_device/data/asan/system",
Dan Willemsen00269f22017-07-06 16:59:48 -0700523 },
524 {
525 name: "sanitized vendor binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100526 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700527 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800528 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700529 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800530 earlyModuleContext: earlyModuleContext{
531 kind: socSpecificModule,
532 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700533 },
534 inSanitizerDir: true,
535 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900536 in: []string{"bin", "my_test"},
537 out: "target/product/test_device/data/asan/vendor/bin/my_test",
538 partitionDir: "target/product/test_device/data/asan/vendor",
Dan Willemsen00269f22017-07-06 16:59:48 -0700539 },
Jiyong Park2db76922017-11-08 16:03:48 +0900540 {
541 name: "sanitized odm binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100542 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700543 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800544 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900545 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800546 earlyModuleContext: earlyModuleContext{
547 kind: deviceSpecificModule,
548 },
Jiyong Park2db76922017-11-08 16:03:48 +0900549 },
550 inSanitizerDir: true,
551 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900552 in: []string{"bin", "my_test"},
553 out: "target/product/test_device/data/asan/odm/bin/my_test",
554 partitionDir: "target/product/test_device/data/asan/odm",
Jiyong Park2db76922017-11-08 16:03:48 +0900555 },
556 {
Jaekyun Seok5cfbfbb2018-01-10 19:00:15 +0900557 name: "sanitized product binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100558 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700559 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800560 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900561 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800562 earlyModuleContext: earlyModuleContext{
563 kind: productSpecificModule,
564 },
Jiyong Park2db76922017-11-08 16:03:48 +0900565 },
566 inSanitizerDir: true,
567 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900568 in: []string{"bin", "my_test"},
569 out: "target/product/test_device/data/asan/product/bin/my_test",
570 partitionDir: "target/product/test_device/data/asan/product",
Jiyong Park2db76922017-11-08 16:03:48 +0900571 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700572
573 {
Justin Yund5f6c822019-06-25 16:47:17 +0900574 name: "sanitized system_ext binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100575 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700576 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800577 os: deviceTarget.Os,
Dario Frenifd05a742018-05-29 13:28:54 +0100578 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800579 earlyModuleContext: earlyModuleContext{
580 kind: systemExtSpecificModule,
581 },
Dario Frenifd05a742018-05-29 13:28:54 +0100582 },
583 inSanitizerDir: true,
584 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900585 in: []string{"bin", "my_test"},
586 out: "target/product/test_device/data/asan/system_ext/bin/my_test",
587 partitionDir: "target/product/test_device/data/asan/system_ext",
Dario Frenifd05a742018-05-29 13:28:54 +0100588 },
589
590 {
Dan Willemsen00269f22017-07-06 16:59:48 -0700591 name: "sanitized system native test binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100592 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700593 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800594 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700595 target: deviceTarget,
596 },
597 inData: true,
598 inSanitizerDir: true,
599 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900600 in: []string{"nativetest", "my_test"},
601 out: "target/product/test_device/data/asan/data/nativetest/my_test",
602 partitionDir: "target/product/test_device/data/asan/data",
Dan Willemsen00269f22017-07-06 16:59:48 -0700603 },
604 {
605 name: "sanitized vendor native test binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100606 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700607 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800608 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700609 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800610 earlyModuleContext: earlyModuleContext{
611 kind: socSpecificModule,
612 },
Jiyong Park2db76922017-11-08 16:03:48 +0900613 },
614 inData: true,
615 inSanitizerDir: true,
616 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900617 in: []string{"nativetest", "my_test"},
618 out: "target/product/test_device/data/asan/data/nativetest/my_test",
619 partitionDir: "target/product/test_device/data/asan/data",
Jiyong Park2db76922017-11-08 16:03:48 +0900620 },
621 {
622 name: "sanitized odm native test binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100623 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700624 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800625 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900626 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800627 earlyModuleContext: earlyModuleContext{
628 kind: deviceSpecificModule,
629 },
Jiyong Park2db76922017-11-08 16:03:48 +0900630 },
631 inData: true,
632 inSanitizerDir: true,
633 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900634 in: []string{"nativetest", "my_test"},
635 out: "target/product/test_device/data/asan/data/nativetest/my_test",
636 partitionDir: "target/product/test_device/data/asan/data",
Jiyong Park2db76922017-11-08 16:03:48 +0900637 },
638 {
Jaekyun Seok5cfbfbb2018-01-10 19:00:15 +0900639 name: "sanitized product native test binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100640 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700641 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800642 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900643 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800644 earlyModuleContext: earlyModuleContext{
645 kind: productSpecificModule,
646 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700647 },
648 inData: true,
649 inSanitizerDir: true,
650 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900651 in: []string{"nativetest", "my_test"},
652 out: "target/product/test_device/data/asan/data/nativetest/my_test",
653 partitionDir: "target/product/test_device/data/asan/data",
Dan Willemsen00269f22017-07-06 16:59:48 -0700654 },
Dario Frenifd05a742018-05-29 13:28:54 +0100655 {
Justin Yund5f6c822019-06-25 16:47:17 +0900656 name: "sanitized system_ext native test binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100657 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700658 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800659 os: deviceTarget.Os,
Dario Frenifd05a742018-05-29 13:28:54 +0100660 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800661 earlyModuleContext: earlyModuleContext{
662 kind: systemExtSpecificModule,
663 },
Dario Frenifd05a742018-05-29 13:28:54 +0100664 },
665 inData: true,
666 inSanitizerDir: true,
667 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900668 in: []string{"nativetest", "my_test"},
669 out: "target/product/test_device/data/asan/data/nativetest/my_test",
670 partitionDir: "target/product/test_device/data/asan/data",
Colin Cross6e359402020-02-10 15:29:54 -0800671 }, {
672 name: "device testcases",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100673 ctx: &testModuleInstallPathContext{
Colin Cross6e359402020-02-10 15:29:54 -0800674 baseModuleContext: baseModuleContext{
675 os: deviceTarget.Os,
676 target: deviceTarget,
677 },
678 inTestcases: true,
679 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900680 in: []string{"my_test", "my_test_bin"},
681 out: "target/product/test_device/testcases/my_test/my_test_bin",
682 partitionDir: "target/product/test_device/testcases",
Colin Cross6e359402020-02-10 15:29:54 -0800683 }, {
684 name: "host testcases",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100685 ctx: &testModuleInstallPathContext{
Colin Cross6e359402020-02-10 15:29:54 -0800686 baseModuleContext: baseModuleContext{
687 os: hostTarget.Os,
688 target: hostTarget,
689 },
690 inTestcases: true,
691 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900692 in: []string{"my_test", "my_test_bin"},
693 out: "host/linux-x86/testcases/my_test/my_test_bin",
694 partitionDir: "host/linux-x86/testcases",
Colin Cross6e359402020-02-10 15:29:54 -0800695 }, {
696 name: "forced host testcases",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100697 ctx: &testModuleInstallPathContext{
Colin Cross6e359402020-02-10 15:29:54 -0800698 baseModuleContext: baseModuleContext{
699 os: deviceTarget.Os,
700 target: deviceTarget,
701 },
702 inTestcases: true,
703 forceOS: &Linux,
Jiyong Park87788b52020-09-01 12:37:45 +0900704 forceArch: &X86,
Colin Cross6e359402020-02-10 15:29:54 -0800705 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900706 in: []string{"my_test", "my_test_bin"},
707 out: "host/linux-x86/testcases/my_test/my_test_bin",
708 partitionDir: "host/linux-x86/testcases",
Dario Frenifd05a742018-05-29 13:28:54 +0100709 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700710 }
711
712 for _, tc := range testCases {
713 t.Run(tc.name, func(t *testing.T) {
Colin Cross0ea8ba82019-06-06 14:33:29 -0700714 tc.ctx.baseModuleContext.config = testConfig
Dan Willemsen00269f22017-07-06 16:59:48 -0700715 output := PathForModuleInstall(tc.ctx, tc.in...)
716 if output.basePath.path != tc.out {
717 t.Errorf("unexpected path:\n got: %q\nwant: %q\n",
718 output.basePath.path,
719 tc.out)
720 }
Jiyong Park957bcd92020-10-20 18:23:33 +0900721 if output.partitionDir != tc.partitionDir {
722 t.Errorf("unexpected partitionDir:\n got: %q\nwant: %q\n",
723 output.partitionDir, tc.partitionDir)
724 }
Dan Willemsen00269f22017-07-06 16:59:48 -0700725 })
726 }
727}
Colin Cross5e6cfbe2017-11-03 15:20:35 -0700728
Inseob Kimd9580b82021-04-13 21:13:49 +0900729func TestPathForModuleInstallRecoveryAsBoot(t *testing.T) {
730 testConfig := pathTestConfig("")
731 testConfig.TestProductVariables.BoardUsesRecoveryAsBoot = proptools.BoolPtr(true)
732 testConfig.TestProductVariables.BoardMoveRecoveryResourcesToVendorBoot = proptools.BoolPtr(true)
733 deviceTarget := Target{Os: Android, Arch: Arch{ArchType: Arm64}}
734
735 testCases := []struct {
736 name string
737 ctx *testModuleInstallPathContext
738 in []string
739 out string
740 partitionDir string
741 }{
742 {
743 name: "ramdisk binary",
744 ctx: &testModuleInstallPathContext{
745 baseModuleContext: baseModuleContext{
746 os: deviceTarget.Os,
747 target: deviceTarget,
748 },
749 inRamdisk: true,
750 inRoot: true,
751 },
752 in: []string{"my_test"},
753 out: "target/product/test_device/recovery/root/first_stage_ramdisk/my_test",
754 partitionDir: "target/product/test_device/recovery/root/first_stage_ramdisk",
755 },
756
757 {
758 name: "vendor_ramdisk binary",
759 ctx: &testModuleInstallPathContext{
760 baseModuleContext: baseModuleContext{
761 os: deviceTarget.Os,
762 target: deviceTarget,
763 },
764 inVendorRamdisk: true,
765 inRoot: true,
766 },
767 in: []string{"my_test"},
768 out: "target/product/test_device/vendor_ramdisk/first_stage_ramdisk/my_test",
769 partitionDir: "target/product/test_device/vendor_ramdisk/first_stage_ramdisk",
770 },
771 }
772
773 for _, tc := range testCases {
774 t.Run(tc.name, func(t *testing.T) {
775 tc.ctx.baseModuleContext.config = testConfig
776 output := PathForModuleInstall(tc.ctx, tc.in...)
777 if output.basePath.path != tc.out {
778 t.Errorf("unexpected path:\n got: %q\nwant: %q\n",
779 output.basePath.path,
780 tc.out)
781 }
782 if output.partitionDir != tc.partitionDir {
783 t.Errorf("unexpected partitionDir:\n got: %q\nwant: %q\n",
784 output.partitionDir, tc.partitionDir)
785 }
786 })
787 }
788}
789
Jiyong Park957bcd92020-10-20 18:23:33 +0900790func TestBaseDirForInstallPath(t *testing.T) {
791 testConfig := pathTestConfig("")
792 deviceTarget := Target{Os: Android, Arch: Arch{ArchType: Arm64}}
793
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100794 ctx := &testModuleInstallPathContext{
Jiyong Park957bcd92020-10-20 18:23:33 +0900795 baseModuleContext: baseModuleContext{
796 os: deviceTarget.Os,
797 target: deviceTarget,
798 },
799 }
800 ctx.baseModuleContext.config = testConfig
801
802 actual := PathForModuleInstall(ctx, "foo", "bar")
803 expectedBaseDir := "target/product/test_device/system"
804 if actual.partitionDir != expectedBaseDir {
805 t.Errorf("unexpected partitionDir:\n got: %q\nwant: %q\n", actual.partitionDir, expectedBaseDir)
806 }
807 expectedRelPath := "foo/bar"
808 if actual.Rel() != expectedRelPath {
809 t.Errorf("unexpected Rel():\n got: %q\nwant: %q\n", actual.Rel(), expectedRelPath)
810 }
811
812 actualAfterJoin := actual.Join(ctx, "baz")
813 // partitionDir is preserved even after joining
814 if actualAfterJoin.partitionDir != expectedBaseDir {
815 t.Errorf("unexpected partitionDir after joining:\n got: %q\nwant: %q\n", actualAfterJoin.partitionDir, expectedBaseDir)
816 }
817 // Rel() is updated though
818 expectedRelAfterJoin := "baz"
819 if actualAfterJoin.Rel() != expectedRelAfterJoin {
820 t.Errorf("unexpected Rel() after joining:\n got: %q\nwant: %q\n", actualAfterJoin.Rel(), expectedRelAfterJoin)
821 }
822}
823
Colin Cross5e6cfbe2017-11-03 15:20:35 -0700824func TestDirectorySortedPaths(t *testing.T) {
Colin Cross98be1bb2019-12-13 20:41:13 -0800825 config := TestConfig("out", nil, "", map[string][]byte{
826 "Android.bp": nil,
827 "a.txt": nil,
828 "a/txt": nil,
829 "a/b/c": nil,
830 "a/b/d": nil,
831 "b": nil,
832 "b/b.txt": nil,
833 "a/a.txt": nil,
Colin Cross07e51612019-03-05 12:46:40 -0800834 })
835
Colin Cross98be1bb2019-12-13 20:41:13 -0800836 ctx := PathContextForTesting(config)
837
Colin Cross5e6cfbe2017-11-03 15:20:35 -0700838 makePaths := func() Paths {
839 return Paths{
Colin Cross07e51612019-03-05 12:46:40 -0800840 PathForSource(ctx, "a.txt"),
841 PathForSource(ctx, "a/txt"),
842 PathForSource(ctx, "a/b/c"),
843 PathForSource(ctx, "a/b/d"),
844 PathForSource(ctx, "b"),
845 PathForSource(ctx, "b/b.txt"),
846 PathForSource(ctx, "a/a.txt"),
Colin Cross5e6cfbe2017-11-03 15:20:35 -0700847 }
848 }
849
850 expected := []string{
851 "a.txt",
852 "a/a.txt",
853 "a/b/c",
854 "a/b/d",
855 "a/txt",
856 "b",
857 "b/b.txt",
858 }
859
860 paths := makePaths()
Colin Crossa140bb02018-04-17 10:52:26 -0700861 reversePaths := ReversePaths(paths)
Colin Cross5e6cfbe2017-11-03 15:20:35 -0700862
863 sortedPaths := PathsToDirectorySortedPaths(paths)
864 reverseSortedPaths := PathsToDirectorySortedPaths(reversePaths)
865
866 if !reflect.DeepEqual(Paths(sortedPaths).Strings(), expected) {
867 t.Fatalf("sorted paths:\n %#v\n != \n %#v", paths.Strings(), expected)
868 }
869
870 if !reflect.DeepEqual(Paths(reverseSortedPaths).Strings(), expected) {
871 t.Fatalf("sorted reversed paths:\n %#v\n !=\n %#v", reversePaths.Strings(), expected)
872 }
873
874 expectedA := []string{
875 "a/a.txt",
876 "a/b/c",
877 "a/b/d",
878 "a/txt",
879 }
880
881 inA := sortedPaths.PathsInDirectory("a")
882 if !reflect.DeepEqual(inA.Strings(), expectedA) {
883 t.Errorf("FilesInDirectory(a):\n %#v\n != \n %#v", inA.Strings(), expectedA)
884 }
885
886 expectedA_B := []string{
887 "a/b/c",
888 "a/b/d",
889 }
890
891 inA_B := sortedPaths.PathsInDirectory("a/b")
892 if !reflect.DeepEqual(inA_B.Strings(), expectedA_B) {
893 t.Errorf("FilesInDirectory(a/b):\n %#v\n != \n %#v", inA_B.Strings(), expectedA_B)
894 }
895
896 expectedB := []string{
897 "b/b.txt",
898 }
899
900 inB := sortedPaths.PathsInDirectory("b")
901 if !reflect.DeepEqual(inB.Strings(), expectedB) {
902 t.Errorf("FilesInDirectory(b):\n %#v\n != \n %#v", inA.Strings(), expectedA)
903 }
904}
Colin Cross43f08db2018-11-12 10:13:39 -0800905
906func TestMaybeRel(t *testing.T) {
907 testCases := []struct {
908 name string
909 base string
910 target string
911 out string
912 isRel bool
913 }{
914 {
915 name: "normal",
916 base: "a/b/c",
917 target: "a/b/c/d",
918 out: "d",
919 isRel: true,
920 },
921 {
922 name: "parent",
923 base: "a/b/c/d",
924 target: "a/b/c",
925 isRel: false,
926 },
927 {
928 name: "not relative",
929 base: "a/b",
930 target: "c/d",
931 isRel: false,
932 },
933 {
934 name: "abs1",
935 base: "/a",
936 target: "a",
937 isRel: false,
938 },
939 {
940 name: "abs2",
941 base: "a",
942 target: "/a",
943 isRel: false,
944 },
945 }
946
947 for _, testCase := range testCases {
948 t.Run(testCase.name, func(t *testing.T) {
949 ctx := &configErrorWrapper{}
950 out, isRel := MaybeRel(ctx, testCase.base, testCase.target)
951 if len(ctx.errors) > 0 {
952 t.Errorf("MaybeRel(..., %s, %s) reported unexpected errors %v",
953 testCase.base, testCase.target, ctx.errors)
954 }
955 if isRel != testCase.isRel || out != testCase.out {
956 t.Errorf("MaybeRel(..., %s, %s) want %v, %v got %v, %v",
957 testCase.base, testCase.target, testCase.out, testCase.isRel, out, isRel)
958 }
959 })
960 }
961}
Colin Cross7b3dcc32019-01-24 13:14:39 -0800962
963func TestPathForSource(t *testing.T) {
964 testCases := []struct {
965 name string
966 buildDir string
967 src string
968 err string
969 }{
970 {
971 name: "normal",
972 buildDir: "out",
973 src: "a/b/c",
974 },
975 {
976 name: "abs",
977 buildDir: "out",
978 src: "/a/b/c",
979 err: "is outside directory",
980 },
981 {
982 name: "in out dir",
983 buildDir: "out",
984 src: "out/a/b/c",
985 err: "is in output",
986 },
987 }
988
989 funcs := []struct {
990 name string
991 f func(ctx PathContext, pathComponents ...string) (SourcePath, error)
992 }{
993 {"pathForSource", pathForSource},
994 {"safePathForSource", safePathForSource},
995 }
996
997 for _, f := range funcs {
998 t.Run(f.name, func(t *testing.T) {
999 for _, test := range testCases {
1000 t.Run(test.name, func(t *testing.T) {
Colin Cross98be1bb2019-12-13 20:41:13 -08001001 testConfig := pathTestConfig(test.buildDir)
Colin Cross7b3dcc32019-01-24 13:14:39 -08001002 ctx := &configErrorWrapper{config: testConfig}
1003 _, err := f.f(ctx, test.src)
1004 if len(ctx.errors) > 0 {
1005 t.Fatalf("unexpected errors %v", ctx.errors)
1006 }
1007 if err != nil {
1008 if test.err == "" {
1009 t.Fatalf("unexpected error %q", err.Error())
1010 } else if !strings.Contains(err.Error(), test.err) {
1011 t.Fatalf("incorrect error, want substring %q got %q", test.err, err.Error())
1012 }
1013 } else {
1014 if test.err != "" {
1015 t.Fatalf("missing error %q", test.err)
1016 }
1017 }
1018 })
1019 }
1020 })
1021 }
1022}
Colin Cross8854a5a2019-02-11 14:14:16 -08001023
Colin Cross8a497952019-03-05 22:25:09 -08001024type pathForModuleSrcTestModule struct {
Colin Cross937664a2019-03-06 10:17:32 -08001025 ModuleBase
1026 props struct {
1027 Srcs []string `android:"path"`
1028 Exclude_srcs []string `android:"path"`
Colin Cross8a497952019-03-05 22:25:09 -08001029
1030 Src *string `android:"path"`
Colin Crossba71a3f2019-03-18 12:12:48 -07001031
1032 Module_handles_missing_deps bool
Colin Cross937664a2019-03-06 10:17:32 -08001033 }
1034
Colin Cross8a497952019-03-05 22:25:09 -08001035 src string
1036 rel string
1037
1038 srcs []string
Colin Cross937664a2019-03-06 10:17:32 -08001039 rels []string
Colin Cross8a497952019-03-05 22:25:09 -08001040
1041 missingDeps []string
Colin Cross937664a2019-03-06 10:17:32 -08001042}
1043
Colin Cross8a497952019-03-05 22:25:09 -08001044func pathForModuleSrcTestModuleFactory() Module {
1045 module := &pathForModuleSrcTestModule{}
Colin Cross937664a2019-03-06 10:17:32 -08001046 module.AddProperties(&module.props)
1047 InitAndroidModule(module)
1048 return module
1049}
1050
Colin Cross8a497952019-03-05 22:25:09 -08001051func (p *pathForModuleSrcTestModule) GenerateAndroidBuildActions(ctx ModuleContext) {
Colin Crossba71a3f2019-03-18 12:12:48 -07001052 var srcs Paths
1053 if p.props.Module_handles_missing_deps {
1054 srcs, p.missingDeps = PathsAndMissingDepsForModuleSrcExcludes(ctx, p.props.Srcs, p.props.Exclude_srcs)
1055 } else {
1056 srcs = PathsForModuleSrcExcludes(ctx, p.props.Srcs, p.props.Exclude_srcs)
1057 }
Colin Cross8a497952019-03-05 22:25:09 -08001058 p.srcs = srcs.Strings()
Colin Cross937664a2019-03-06 10:17:32 -08001059
Colin Cross8a497952019-03-05 22:25:09 -08001060 for _, src := range srcs {
Colin Cross937664a2019-03-06 10:17:32 -08001061 p.rels = append(p.rels, src.Rel())
1062 }
Colin Cross8a497952019-03-05 22:25:09 -08001063
1064 if p.props.Src != nil {
1065 src := PathForModuleSrc(ctx, *p.props.Src)
1066 if src != nil {
1067 p.src = src.String()
1068 p.rel = src.Rel()
1069 }
1070 }
1071
Colin Crossba71a3f2019-03-18 12:12:48 -07001072 if !p.props.Module_handles_missing_deps {
1073 p.missingDeps = ctx.GetMissingDependencies()
1074 }
Colin Cross6c4f21f2019-06-06 15:41:36 -07001075
1076 ctx.Build(pctx, BuildParams{
1077 Rule: Touch,
1078 Output: PathForModuleOut(ctx, "output"),
1079 })
Colin Cross8a497952019-03-05 22:25:09 -08001080}
1081
Colin Cross41955e82019-05-29 14:40:35 -07001082type pathForModuleSrcOutputFileProviderModule struct {
1083 ModuleBase
1084 props struct {
1085 Outs []string
1086 Tagged []string
1087 }
1088
1089 outs Paths
1090 tagged Paths
1091}
1092
1093func pathForModuleSrcOutputFileProviderModuleFactory() Module {
1094 module := &pathForModuleSrcOutputFileProviderModule{}
1095 module.AddProperties(&module.props)
1096 InitAndroidModule(module)
1097 return module
1098}
1099
1100func (p *pathForModuleSrcOutputFileProviderModule) GenerateAndroidBuildActions(ctx ModuleContext) {
1101 for _, out := range p.props.Outs {
1102 p.outs = append(p.outs, PathForModuleOut(ctx, out))
1103 }
1104
1105 for _, tagged := range p.props.Tagged {
1106 p.tagged = append(p.tagged, PathForModuleOut(ctx, tagged))
1107 }
1108}
1109
1110func (p *pathForModuleSrcOutputFileProviderModule) OutputFiles(tag string) (Paths, error) {
1111 switch tag {
1112 case "":
1113 return p.outs, nil
1114 case ".tagged":
1115 return p.tagged, nil
1116 default:
1117 return nil, fmt.Errorf("unsupported tag %q", tag)
1118 }
1119}
1120
Colin Cross8a497952019-03-05 22:25:09 -08001121type pathForModuleSrcTestCase struct {
1122 name string
1123 bp string
1124 srcs []string
1125 rels []string
1126 src string
1127 rel string
Paul Duffinec0bd8c2021-07-09 16:56:15 +01001128
1129 // Make test specific preparations to the test fixture.
1130 preparer FixturePreparer
1131
1132 // A test specific error handler.
1133 errorHandler FixtureErrorHandler
Colin Cross8a497952019-03-05 22:25:09 -08001134}
1135
Paul Duffin54054682021-03-16 21:11:42 +00001136func testPathForModuleSrc(t *testing.T, tests []pathForModuleSrcTestCase) {
Colin Cross8a497952019-03-05 22:25:09 -08001137 for _, test := range tests {
1138 t.Run(test.name, func(t *testing.T) {
Colin Cross8a497952019-03-05 22:25:09 -08001139 fgBp := `
1140 filegroup {
1141 name: "a",
1142 srcs: ["src/a"],
1143 }
1144 `
1145
Colin Cross41955e82019-05-29 14:40:35 -07001146 ofpBp := `
1147 output_file_provider {
1148 name: "b",
1149 outs: ["gen/b"],
1150 tagged: ["gen/c"],
1151 }
1152 `
1153
Paul Duffin54054682021-03-16 21:11:42 +00001154 mockFS := MockFS{
Colin Cross8a497952019-03-05 22:25:09 -08001155 "fg/Android.bp": []byte(fgBp),
1156 "foo/Android.bp": []byte(test.bp),
Colin Cross41955e82019-05-29 14:40:35 -07001157 "ofp/Android.bp": []byte(ofpBp),
Colin Cross8a497952019-03-05 22:25:09 -08001158 "fg/src/a": nil,
1159 "foo/src/b": nil,
1160 "foo/src/c": nil,
1161 "foo/src/d": nil,
1162 "foo/src/e/e": nil,
1163 "foo/src_special/$": nil,
1164 }
1165
Paul Duffinec0bd8c2021-07-09 16:56:15 +01001166 errorHandler := test.errorHandler
1167 if errorHandler == nil {
1168 errorHandler = FixtureExpectsNoErrors
1169 }
1170
Paul Duffin30ac3e72021-03-20 00:36:14 +00001171 result := GroupFixturePreparers(
Paul Duffin54054682021-03-16 21:11:42 +00001172 FixtureRegisterWithContext(func(ctx RegistrationContext) {
1173 ctx.RegisterModuleType("test", pathForModuleSrcTestModuleFactory)
1174 ctx.RegisterModuleType("output_file_provider", pathForModuleSrcOutputFileProviderModuleFactory)
Paul Duffin54054682021-03-16 21:11:42 +00001175 }),
Paul Duffinec0bd8c2021-07-09 16:56:15 +01001176 PrepareForTestWithFilegroup,
1177 PrepareForTestWithNamespace,
Paul Duffin54054682021-03-16 21:11:42 +00001178 mockFS.AddToFixture(),
Paul Duffinec0bd8c2021-07-09 16:56:15 +01001179 OptionalFixturePreparer(test.preparer),
1180 ).
1181 ExtendWithErrorHandler(errorHandler).
1182 RunTest(t)
Colin Cross8a497952019-03-05 22:25:09 -08001183
Paul Duffin54054682021-03-16 21:11:42 +00001184 m := result.ModuleForTests("foo", "").Module().(*pathForModuleSrcTestModule)
Colin Crossae8600b2020-10-29 17:09:13 -07001185
Paul Duffin54054682021-03-16 21:11:42 +00001186 AssertStringPathsRelativeToTopEquals(t, "srcs", result.Config, test.srcs, m.srcs)
1187 AssertStringPathsRelativeToTopEquals(t, "rels", result.Config, test.rels, m.rels)
1188 AssertStringPathRelativeToTopEquals(t, "src", result.Config, test.src, m.src)
1189 AssertStringPathRelativeToTopEquals(t, "rel", result.Config, test.rel, m.rel)
Colin Cross8a497952019-03-05 22:25:09 -08001190 })
1191 }
Colin Cross937664a2019-03-06 10:17:32 -08001192}
1193
Colin Cross8a497952019-03-05 22:25:09 -08001194func TestPathsForModuleSrc(t *testing.T) {
1195 tests := []pathForModuleSrcTestCase{
Colin Cross937664a2019-03-06 10:17:32 -08001196 {
1197 name: "path",
1198 bp: `
1199 test {
1200 name: "foo",
1201 srcs: ["src/b"],
1202 }`,
1203 srcs: []string{"foo/src/b"},
1204 rels: []string{"src/b"},
1205 },
1206 {
1207 name: "glob",
1208 bp: `
1209 test {
1210 name: "foo",
1211 srcs: [
1212 "src/*",
1213 "src/e/*",
1214 ],
1215 }`,
1216 srcs: []string{"foo/src/b", "foo/src/c", "foo/src/d", "foo/src/e/e"},
1217 rels: []string{"src/b", "src/c", "src/d", "src/e/e"},
1218 },
1219 {
1220 name: "recursive glob",
1221 bp: `
1222 test {
1223 name: "foo",
1224 srcs: ["src/**/*"],
1225 }`,
1226 srcs: []string{"foo/src/b", "foo/src/c", "foo/src/d", "foo/src/e/e"},
1227 rels: []string{"src/b", "src/c", "src/d", "src/e/e"},
1228 },
1229 {
1230 name: "filegroup",
1231 bp: `
1232 test {
1233 name: "foo",
1234 srcs: [":a"],
1235 }`,
1236 srcs: []string{"fg/src/a"},
1237 rels: []string{"src/a"},
1238 },
1239 {
Colin Cross41955e82019-05-29 14:40:35 -07001240 name: "output file provider",
1241 bp: `
1242 test {
1243 name: "foo",
1244 srcs: [":b"],
1245 }`,
Paul Duffin54054682021-03-16 21:11:42 +00001246 srcs: []string{"out/soong/.intermediates/ofp/b/gen/b"},
Colin Cross41955e82019-05-29 14:40:35 -07001247 rels: []string{"gen/b"},
1248 },
1249 {
1250 name: "output file provider tagged",
1251 bp: `
1252 test {
1253 name: "foo",
1254 srcs: [":b{.tagged}"],
1255 }`,
Paul Duffin54054682021-03-16 21:11:42 +00001256 srcs: []string{"out/soong/.intermediates/ofp/b/gen/c"},
Colin Cross41955e82019-05-29 14:40:35 -07001257 rels: []string{"gen/c"},
1258 },
1259 {
Jooyung Han7607dd32020-07-05 10:23:14 +09001260 name: "output file provider with exclude",
1261 bp: `
1262 test {
1263 name: "foo",
1264 srcs: [":b", ":c"],
1265 exclude_srcs: [":c"]
1266 }
1267 output_file_provider {
1268 name: "c",
1269 outs: ["gen/c"],
1270 }`,
Paul Duffin54054682021-03-16 21:11:42 +00001271 srcs: []string{"out/soong/.intermediates/ofp/b/gen/b"},
Jooyung Han7607dd32020-07-05 10:23:14 +09001272 rels: []string{"gen/b"},
1273 },
1274 {
Colin Cross937664a2019-03-06 10:17:32 -08001275 name: "special characters glob",
1276 bp: `
1277 test {
1278 name: "foo",
1279 srcs: ["src_special/*"],
1280 }`,
1281 srcs: []string{"foo/src_special/$"},
1282 rels: []string{"src_special/$"},
1283 },
1284 }
1285
Paul Duffin54054682021-03-16 21:11:42 +00001286 testPathForModuleSrc(t, tests)
Colin Cross41955e82019-05-29 14:40:35 -07001287}
1288
1289func TestPathForModuleSrc(t *testing.T) {
Colin Cross8a497952019-03-05 22:25:09 -08001290 tests := []pathForModuleSrcTestCase{
1291 {
1292 name: "path",
1293 bp: `
1294 test {
1295 name: "foo",
1296 src: "src/b",
1297 }`,
1298 src: "foo/src/b",
1299 rel: "src/b",
1300 },
1301 {
1302 name: "glob",
1303 bp: `
1304 test {
1305 name: "foo",
1306 src: "src/e/*",
1307 }`,
1308 src: "foo/src/e/e",
1309 rel: "src/e/e",
1310 },
1311 {
1312 name: "filegroup",
1313 bp: `
1314 test {
1315 name: "foo",
1316 src: ":a",
1317 }`,
1318 src: "fg/src/a",
1319 rel: "src/a",
1320 },
1321 {
Colin Cross41955e82019-05-29 14:40:35 -07001322 name: "output file provider",
1323 bp: `
1324 test {
1325 name: "foo",
1326 src: ":b",
1327 }`,
Paul Duffin54054682021-03-16 21:11:42 +00001328 src: "out/soong/.intermediates/ofp/b/gen/b",
Colin Cross41955e82019-05-29 14:40:35 -07001329 rel: "gen/b",
1330 },
1331 {
1332 name: "output file provider tagged",
1333 bp: `
1334 test {
1335 name: "foo",
1336 src: ":b{.tagged}",
1337 }`,
Paul Duffin54054682021-03-16 21:11:42 +00001338 src: "out/soong/.intermediates/ofp/b/gen/c",
Colin Cross41955e82019-05-29 14:40:35 -07001339 rel: "gen/c",
1340 },
1341 {
Colin Cross8a497952019-03-05 22:25:09 -08001342 name: "special characters glob",
1343 bp: `
1344 test {
1345 name: "foo",
1346 src: "src_special/*",
1347 }`,
1348 src: "foo/src_special/$",
1349 rel: "src_special/$",
1350 },
Paul Duffinec0bd8c2021-07-09 16:56:15 +01001351 {
1352 // This test makes sure that an unqualified module name cannot contain characters that make
1353 // it appear as a qualified module name.
Paul Duffinec0bd8c2021-07-09 16:56:15 +01001354 name: "output file provider, invalid fully qualified name",
1355 bp: `
1356 test {
1357 name: "foo",
1358 src: "://other:b",
1359 srcs: ["://other:c"],
1360 }`,
1361 preparer: FixtureAddTextFile("other/Android.bp", `
1362 soong_namespace {}
1363
1364 output_file_provider {
1365 name: "b",
1366 outs: ["gen/b"],
1367 }
1368
1369 output_file_provider {
1370 name: "c",
1371 outs: ["gen/c"],
1372 }
1373 `),
Paul Duffine6ba0722021-07-12 20:12:12 +01001374 src: "foo/:/other:b",
1375 rel: ":/other:b",
1376 srcs: []string{"foo/:/other:c"},
1377 rels: []string{":/other:c"},
Paul Duffinec0bd8c2021-07-09 16:56:15 +01001378 },
1379 {
Paul Duffinec0bd8c2021-07-09 16:56:15 +01001380 name: "output file provider, missing fully qualified name",
1381 bp: `
1382 test {
1383 name: "foo",
1384 src: "//other:b",
1385 srcs: ["//other:c"],
1386 }`,
Paul Duffinec0bd8c2021-07-09 16:56:15 +01001387 errorHandler: FixtureExpectsAllErrorsToMatchAPattern([]string{
Paul Duffine6ba0722021-07-12 20:12:12 +01001388 `"foo" depends on undefined module "//other:b"`,
1389 `"foo" depends on undefined module "//other:c"`,
Paul Duffinec0bd8c2021-07-09 16:56:15 +01001390 }),
1391 },
1392 {
1393 // TODO(b/193228441): Fix broken test.
1394 name: "output file provider, fully qualified name",
1395 bp: `
1396 test {
1397 name: "foo",
1398 src: "//other:b",
1399 srcs: ["//other:c"],
1400 }`,
1401 preparer: FixtureAddTextFile("other/Android.bp", `
1402 soong_namespace {}
1403
1404 output_file_provider {
1405 name: "b",
1406 outs: ["gen/b"],
1407 }
1408
1409 output_file_provider {
1410 name: "c",
1411 outs: ["gen/c"],
1412 }
1413 `),
Paul Duffinec0bd8c2021-07-09 16:56:15 +01001414 errorHandler: FixtureExpectsAllErrorsToMatchAPattern([]string{
Paul Duffine6ba0722021-07-12 20:12:12 +01001415 `"foo": missing dependencies: //other:b, is the property annotated with android:"path"`,
1416 `"foo": missing dependency on "//other:c", is the property annotated with android:"path"`,
Paul Duffinec0bd8c2021-07-09 16:56:15 +01001417 }),
1418 },
Colin Cross8a497952019-03-05 22:25:09 -08001419 }
1420
Paul Duffin54054682021-03-16 21:11:42 +00001421 testPathForModuleSrc(t, tests)
Colin Cross8a497952019-03-05 22:25:09 -08001422}
Colin Cross937664a2019-03-06 10:17:32 -08001423
Colin Cross8a497952019-03-05 22:25:09 -08001424func TestPathsForModuleSrc_AllowMissingDependencies(t *testing.T) {
Colin Cross8a497952019-03-05 22:25:09 -08001425 bp := `
1426 test {
1427 name: "foo",
1428 srcs: [":a"],
1429 exclude_srcs: [":b"],
1430 src: ":c",
1431 }
Colin Crossba71a3f2019-03-18 12:12:48 -07001432
1433 test {
1434 name: "bar",
1435 srcs: [":d"],
1436 exclude_srcs: [":e"],
1437 module_handles_missing_deps: true,
1438 }
Colin Cross8a497952019-03-05 22:25:09 -08001439 `
1440
Paul Duffin30ac3e72021-03-20 00:36:14 +00001441 result := GroupFixturePreparers(
Paul Duffin54054682021-03-16 21:11:42 +00001442 PrepareForTestWithAllowMissingDependencies,
1443 FixtureRegisterWithContext(func(ctx RegistrationContext) {
1444 ctx.RegisterModuleType("test", pathForModuleSrcTestModuleFactory)
1445 }),
1446 FixtureWithRootAndroidBp(bp),
Paul Duffin30ac3e72021-03-20 00:36:14 +00001447 ).RunTest(t)
Colin Cross8a497952019-03-05 22:25:09 -08001448
Paul Duffin54054682021-03-16 21:11:42 +00001449 foo := result.ModuleForTests("foo", "").Module().(*pathForModuleSrcTestModule)
Colin Cross8a497952019-03-05 22:25:09 -08001450
Paul Duffin54054682021-03-16 21:11:42 +00001451 AssertArrayString(t, "foo missing deps", []string{"a", "b", "c"}, foo.missingDeps)
1452 AssertArrayString(t, "foo srcs", []string{}, foo.srcs)
1453 AssertStringEquals(t, "foo src", "", foo.src)
Colin Cross98be1bb2019-12-13 20:41:13 -08001454
Paul Duffin54054682021-03-16 21:11:42 +00001455 bar := result.ModuleForTests("bar", "").Module().(*pathForModuleSrcTestModule)
Colin Cross98be1bb2019-12-13 20:41:13 -08001456
Paul Duffin54054682021-03-16 21:11:42 +00001457 AssertArrayString(t, "bar missing deps", []string{"d", "e"}, bar.missingDeps)
1458 AssertArrayString(t, "bar srcs", []string{}, bar.srcs)
Colin Cross937664a2019-03-06 10:17:32 -08001459}
1460
Paul Duffin567465d2021-03-16 01:21:34 +00001461func TestPathRelativeToTop(t *testing.T) {
1462 testConfig := pathTestConfig("/tmp/build/top")
1463 deviceTarget := Target{Os: Android, Arch: Arch{ArchType: Arm64}}
1464
1465 ctx := &testModuleInstallPathContext{
1466 baseModuleContext: baseModuleContext{
1467 os: deviceTarget.Os,
1468 target: deviceTarget,
1469 },
1470 }
1471 ctx.baseModuleContext.config = testConfig
1472
1473 t.Run("install for soong", func(t *testing.T) {
1474 p := PathForModuleInstall(ctx, "install/path")
1475 AssertPathRelativeToTopEquals(t, "install path for soong", "out/soong/target/product/test_device/system/install/path", p)
1476 })
1477 t.Run("install for make", func(t *testing.T) {
1478 p := PathForModuleInstall(ctx, "install/path").ToMakePath()
1479 AssertPathRelativeToTopEquals(t, "install path for make", "out/target/product/test_device/system/install/path", p)
1480 })
1481 t.Run("output", func(t *testing.T) {
1482 p := PathForOutput(ctx, "output/path")
1483 AssertPathRelativeToTopEquals(t, "output path", "out/soong/output/path", p)
1484 })
1485 t.Run("source", func(t *testing.T) {
1486 p := PathForSource(ctx, "source/path")
1487 AssertPathRelativeToTopEquals(t, "source path", "source/path", p)
1488 })
1489 t.Run("mixture", func(t *testing.T) {
1490 paths := Paths{
1491 PathForModuleInstall(ctx, "install/path"),
1492 PathForModuleInstall(ctx, "install/path").ToMakePath(),
1493 PathForOutput(ctx, "output/path"),
1494 PathForSource(ctx, "source/path"),
1495 }
1496
1497 expected := []string{
1498 "out/soong/target/product/test_device/system/install/path",
1499 "out/target/product/test_device/system/install/path",
1500 "out/soong/output/path",
1501 "source/path",
1502 }
1503 AssertPathsRelativeToTopEquals(t, "mixture", expected, paths)
1504 })
1505}
1506
Colin Cross8854a5a2019-02-11 14:14:16 -08001507func ExampleOutputPath_ReplaceExtension() {
1508 ctx := &configErrorWrapper{
Colin Cross98be1bb2019-12-13 20:41:13 -08001509 config: TestConfig("out", nil, "", nil),
Colin Cross8854a5a2019-02-11 14:14:16 -08001510 }
Colin Cross2cdd5df2019-02-25 10:25:24 -08001511 p := PathForOutput(ctx, "system/framework").Join(ctx, "boot.art")
Colin Cross8854a5a2019-02-11 14:14:16 -08001512 p2 := p.ReplaceExtension(ctx, "oat")
1513 fmt.Println(p, p2)
Colin Cross2cdd5df2019-02-25 10:25:24 -08001514 fmt.Println(p.Rel(), p2.Rel())
Colin Cross8854a5a2019-02-11 14:14:16 -08001515
1516 // Output:
1517 // out/system/framework/boot.art out/system/framework/boot.oat
Colin Cross2cdd5df2019-02-25 10:25:24 -08001518 // boot.art boot.oat
Colin Cross8854a5a2019-02-11 14:14:16 -08001519}
Colin Cross40e33732019-02-15 11:08:35 -08001520
Colin Cross41b46762020-10-09 19:26:32 -07001521func ExampleOutputPath_InSameDir() {
Colin Cross40e33732019-02-15 11:08:35 -08001522 ctx := &configErrorWrapper{
Colin Cross98be1bb2019-12-13 20:41:13 -08001523 config: TestConfig("out", nil, "", nil),
Colin Cross40e33732019-02-15 11:08:35 -08001524 }
Colin Cross2cdd5df2019-02-25 10:25:24 -08001525 p := PathForOutput(ctx, "system/framework").Join(ctx, "boot.art")
Colin Cross40e33732019-02-15 11:08:35 -08001526 p2 := p.InSameDir(ctx, "oat", "arm", "boot.vdex")
1527 fmt.Println(p, p2)
Colin Cross2cdd5df2019-02-25 10:25:24 -08001528 fmt.Println(p.Rel(), p2.Rel())
Colin Cross40e33732019-02-15 11:08:35 -08001529
1530 // Output:
1531 // out/system/framework/boot.art out/system/framework/oat/arm/boot.vdex
Colin Cross2cdd5df2019-02-25 10:25:24 -08001532 // boot.art oat/arm/boot.vdex
Colin Cross40e33732019-02-15 11:08:35 -08001533}
Colin Cross27027c72020-02-28 15:34:17 -08001534
1535func BenchmarkFirstUniquePaths(b *testing.B) {
1536 implementations := []struct {
1537 name string
1538 f func(Paths) Paths
1539 }{
1540 {
1541 name: "list",
1542 f: firstUniquePathsList,
1543 },
1544 {
1545 name: "map",
1546 f: firstUniquePathsMap,
1547 },
1548 }
1549 const maxSize = 1024
1550 uniquePaths := make(Paths, maxSize)
1551 for i := range uniquePaths {
1552 uniquePaths[i] = PathForTesting(strconv.Itoa(i))
1553 }
1554 samePath := make(Paths, maxSize)
1555 for i := range samePath {
1556 samePath[i] = uniquePaths[0]
1557 }
1558
1559 f := func(b *testing.B, imp func(Paths) Paths, paths Paths) {
1560 for i := 0; i < b.N; i++ {
1561 b.ReportAllocs()
1562 paths = append(Paths(nil), paths...)
1563 imp(paths)
1564 }
1565 }
1566
1567 for n := 1; n <= maxSize; n <<= 1 {
1568 b.Run(strconv.Itoa(n), func(b *testing.B) {
1569 for _, implementation := range implementations {
1570 b.Run(implementation.name, func(b *testing.B) {
1571 b.Run("same", func(b *testing.B) {
1572 f(b, implementation.f, samePath[:n])
1573 })
1574 b.Run("unique", func(b *testing.B) {
1575 f(b, implementation.f, uniquePaths[:n])
1576 })
1577 })
1578 }
1579 })
1580 }
1581}