blob: 465ea3b555752533456e4f5d4a57e24e5db8f45a [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"
24)
25
26type strsTestCase struct {
27 in []string
28 out string
29 err []error
30}
31
32var commonValidatePathTestCases = []strsTestCase{
33 {
34 in: []string{""},
35 out: "",
36 },
37 {
38 in: []string{"a/b"},
39 out: "a/b",
40 },
41 {
42 in: []string{"a/b", "c"},
43 out: "a/b/c",
44 },
45 {
46 in: []string{"a/.."},
47 out: ".",
48 },
49 {
50 in: []string{"."},
51 out: ".",
52 },
53 {
54 in: []string{".."},
55 out: "",
56 err: []error{errors.New("Path is outside directory: ..")},
57 },
58 {
59 in: []string{"../a"},
60 out: "",
61 err: []error{errors.New("Path is outside directory: ../a")},
62 },
63 {
64 in: []string{"b/../../a"},
65 out: "",
66 err: []error{errors.New("Path is outside directory: ../a")},
67 },
68 {
69 in: []string{"/a"},
70 out: "",
71 err: []error{errors.New("Path is outside directory: /a")},
72 },
Dan Willemsen80a7c2a2015-12-21 14:57:11 -080073 {
74 in: []string{"a", "../b"},
75 out: "",
76 err: []error{errors.New("Path is outside directory: ../b")},
77 },
78 {
79 in: []string{"a", "b/../../c"},
80 out: "",
81 err: []error{errors.New("Path is outside directory: ../c")},
82 },
83 {
84 in: []string{"a", "./.."},
85 out: "",
86 err: []error{errors.New("Path is outside directory: ..")},
87 },
Dan Willemsen34cc69e2015-09-23 15:26:20 -070088}
89
90var validateSafePathTestCases = append(commonValidatePathTestCases, []strsTestCase{
91 {
92 in: []string{"$host/../$a"},
93 out: "$a",
94 },
95}...)
96
97var validatePathTestCases = append(commonValidatePathTestCases, []strsTestCase{
98 {
99 in: []string{"$host/../$a"},
100 out: "",
101 err: []error{errors.New("Path contains invalid character($): $host/../$a")},
102 },
103 {
104 in: []string{"$host/.."},
105 out: "",
106 err: []error{errors.New("Path contains invalid character($): $host/..")},
107 },
108}...)
109
110func TestValidateSafePath(t *testing.T) {
111 for _, testCase := range validateSafePathTestCases {
Colin Crossdc75ae72018-02-22 13:48:13 -0800112 t.Run(strings.Join(testCase.in, ","), func(t *testing.T) {
113 ctx := &configErrorWrapper{}
Colin Cross1ccfcc32018-02-22 13:54:26 -0800114 out, err := validateSafePath(testCase.in...)
115 if err != nil {
116 reportPathError(ctx, err)
117 }
Colin Crossdc75ae72018-02-22 13:48:13 -0800118 check(t, "validateSafePath", p(testCase.in), out, ctx.errors, testCase.out, testCase.err)
119 })
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700120 }
121}
122
123func TestValidatePath(t *testing.T) {
124 for _, testCase := range validatePathTestCases {
Colin Crossdc75ae72018-02-22 13:48:13 -0800125 t.Run(strings.Join(testCase.in, ","), func(t *testing.T) {
126 ctx := &configErrorWrapper{}
Colin Cross1ccfcc32018-02-22 13:54:26 -0800127 out, err := validatePath(testCase.in...)
128 if err != nil {
129 reportPathError(ctx, err)
130 }
Colin Crossdc75ae72018-02-22 13:48:13 -0800131 check(t, "validatePath", p(testCase.in), out, ctx.errors, testCase.out, testCase.err)
132 })
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700133 }
134}
135
136func TestOptionalPath(t *testing.T) {
137 var path OptionalPath
138 checkInvalidOptionalPath(t, path)
139
140 path = OptionalPathForPath(nil)
141 checkInvalidOptionalPath(t, path)
142}
143
144func checkInvalidOptionalPath(t *testing.T, path OptionalPath) {
Colin Crossdc75ae72018-02-22 13:48:13 -0800145 t.Helper()
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700146 if path.Valid() {
147 t.Errorf("Uninitialized OptionalPath should not be valid")
148 }
149 if path.String() != "" {
150 t.Errorf("Uninitialized OptionalPath String() should return \"\", not %q", path.String())
151 }
152 defer func() {
153 if r := recover(); r == nil {
154 t.Errorf("Expected a panic when calling Path() on an uninitialized OptionalPath")
155 }
156 }()
157 path.Path()
158}
159
160func check(t *testing.T, testType, testString string,
161 got interface{}, err []error,
162 expected interface{}, expectedErr []error) {
Colin Crossdc75ae72018-02-22 13:48:13 -0800163 t.Helper()
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700164
165 printedTestCase := false
166 e := func(s string, expected, got interface{}) {
Colin Crossdc75ae72018-02-22 13:48:13 -0800167 t.Helper()
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700168 if !printedTestCase {
169 t.Errorf("test case %s: %s", testType, testString)
170 printedTestCase = true
171 }
172 t.Errorf("incorrect %s", s)
173 t.Errorf(" expected: %s", p(expected))
174 t.Errorf(" got: %s", p(got))
175 }
176
177 if !reflect.DeepEqual(expectedErr, err) {
178 e("errors:", expectedErr, err)
179 }
180
181 if !reflect.DeepEqual(expected, got) {
182 e("output:", expected, got)
183 }
184}
185
186func p(in interface{}) string {
187 if v, ok := in.([]interface{}); ok {
188 s := make([]string, len(v))
189 for i := range v {
190 s[i] = fmt.Sprintf("%#v", v[i])
191 }
192 return "[" + strings.Join(s, ", ") + "]"
193 } else {
194 return fmt.Sprintf("%#v", in)
195 }
196}
Dan Willemsen00269f22017-07-06 16:59:48 -0700197
Colin Cross98be1bb2019-12-13 20:41:13 -0800198func pathTestConfig(buildDir string) Config {
199 return TestConfig(buildDir, nil, "", nil)
200}
201
Dan Willemsen00269f22017-07-06 16:59:48 -0700202func TestPathForModuleInstall(t *testing.T) {
Colin Cross98be1bb2019-12-13 20:41:13 -0800203 testConfig := pathTestConfig("")
Dan Willemsen00269f22017-07-06 16:59:48 -0700204
Jiyong Park87788b52020-09-01 12:37:45 +0900205 hostTarget := Target{Os: Linux, Arch: Arch{ArchType: X86}}
206 deviceTarget := Target{Os: Android, Arch: Arch{ArchType: Arm64}}
Dan Willemsen00269f22017-07-06 16:59:48 -0700207
208 testCases := []struct {
Jiyong Park957bcd92020-10-20 18:23:33 +0900209 name string
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100210 ctx *testModuleInstallPathContext
Jiyong Park957bcd92020-10-20 18:23:33 +0900211 in []string
212 out string
213 partitionDir string
Dan Willemsen00269f22017-07-06 16:59:48 -0700214 }{
215 {
216 name: "host binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100217 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700218 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800219 os: hostTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700220 target: hostTarget,
221 },
222 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900223 in: []string{"bin", "my_test"},
224 out: "host/linux-x86/bin/my_test",
225 partitionDir: "host/linux-x86",
Dan Willemsen00269f22017-07-06 16:59:48 -0700226 },
227
228 {
229 name: "system binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100230 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700231 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800232 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700233 target: deviceTarget,
234 },
235 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900236 in: []string{"bin", "my_test"},
237 out: "target/product/test_device/system/bin/my_test",
238 partitionDir: "target/product/test_device/system",
Dan Willemsen00269f22017-07-06 16:59:48 -0700239 },
240 {
241 name: "vendor binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100242 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700243 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800244 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700245 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800246 earlyModuleContext: earlyModuleContext{
247 kind: socSpecificModule,
248 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700249 },
250 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900251 in: []string{"bin", "my_test"},
252 out: "target/product/test_device/vendor/bin/my_test",
253 partitionDir: "target/product/test_device/vendor",
Dan Willemsen00269f22017-07-06 16:59:48 -0700254 },
Jiyong Park2db76922017-11-08 16:03:48 +0900255 {
256 name: "odm binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100257 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700258 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800259 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900260 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800261 earlyModuleContext: earlyModuleContext{
262 kind: deviceSpecificModule,
263 },
Jiyong Park2db76922017-11-08 16:03:48 +0900264 },
265 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900266 in: []string{"bin", "my_test"},
267 out: "target/product/test_device/odm/bin/my_test",
268 partitionDir: "target/product/test_device/odm",
Jiyong Park2db76922017-11-08 16:03:48 +0900269 },
270 {
Jaekyun Seok5cfbfbb2018-01-10 19:00:15 +0900271 name: "product binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100272 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700273 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800274 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900275 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800276 earlyModuleContext: earlyModuleContext{
277 kind: productSpecificModule,
278 },
Jiyong Park2db76922017-11-08 16:03:48 +0900279 },
280 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900281 in: []string{"bin", "my_test"},
282 out: "target/product/test_device/product/bin/my_test",
283 partitionDir: "target/product/test_device/product",
Jiyong Park2db76922017-11-08 16:03:48 +0900284 },
Dario Frenifd05a742018-05-29 13:28:54 +0100285 {
Justin Yund5f6c822019-06-25 16:47:17 +0900286 name: "system_ext binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100287 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700288 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800289 os: deviceTarget.Os,
Dario Frenifd05a742018-05-29 13:28:54 +0100290 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800291 earlyModuleContext: earlyModuleContext{
292 kind: systemExtSpecificModule,
293 },
Dario Frenifd05a742018-05-29 13:28:54 +0100294 },
295 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900296 in: []string{"bin", "my_test"},
297 out: "target/product/test_device/system_ext/bin/my_test",
298 partitionDir: "target/product/test_device/system_ext",
Dario Frenifd05a742018-05-29 13:28:54 +0100299 },
Colin Cross90ba5f42019-10-02 11:10:58 -0700300 {
301 name: "root binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100302 ctx: &testModuleInstallPathContext{
Colin Cross90ba5f42019-10-02 11:10:58 -0700303 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800304 os: deviceTarget.Os,
Colin Cross90ba5f42019-10-02 11:10:58 -0700305 target: deviceTarget,
306 },
307 inRoot: true,
308 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900309 in: []string{"my_test"},
310 out: "target/product/test_device/root/my_test",
311 partitionDir: "target/product/test_device/root",
Colin Cross90ba5f42019-10-02 11:10:58 -0700312 },
313 {
314 name: "recovery binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100315 ctx: &testModuleInstallPathContext{
Colin Cross90ba5f42019-10-02 11:10:58 -0700316 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800317 os: deviceTarget.Os,
Colin Cross90ba5f42019-10-02 11:10:58 -0700318 target: deviceTarget,
319 },
320 inRecovery: true,
321 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900322 in: []string{"bin/my_test"},
323 out: "target/product/test_device/recovery/root/system/bin/my_test",
324 partitionDir: "target/product/test_device/recovery/root/system",
Colin Cross90ba5f42019-10-02 11:10:58 -0700325 },
326 {
327 name: "recovery root binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100328 ctx: &testModuleInstallPathContext{
Colin Cross90ba5f42019-10-02 11:10:58 -0700329 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800330 os: deviceTarget.Os,
Colin Cross90ba5f42019-10-02 11:10:58 -0700331 target: deviceTarget,
332 },
333 inRecovery: true,
334 inRoot: true,
335 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900336 in: []string{"my_test"},
337 out: "target/product/test_device/recovery/root/my_test",
338 partitionDir: "target/product/test_device/recovery/root",
Colin Cross90ba5f42019-10-02 11:10:58 -0700339 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700340
341 {
342 name: "system native test binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100343 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700344 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800345 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700346 target: deviceTarget,
347 },
348 inData: true,
349 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900350 in: []string{"nativetest", "my_test"},
351 out: "target/product/test_device/data/nativetest/my_test",
352 partitionDir: "target/product/test_device/data",
Dan Willemsen00269f22017-07-06 16:59:48 -0700353 },
354 {
355 name: "vendor native test binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100356 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700357 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800358 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700359 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800360 earlyModuleContext: earlyModuleContext{
361 kind: socSpecificModule,
362 },
Jiyong Park2db76922017-11-08 16:03:48 +0900363 },
364 inData: true,
365 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900366 in: []string{"nativetest", "my_test"},
367 out: "target/product/test_device/data/nativetest/my_test",
368 partitionDir: "target/product/test_device/data",
Jiyong Park2db76922017-11-08 16:03:48 +0900369 },
370 {
371 name: "odm native test binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100372 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700373 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800374 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900375 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800376 earlyModuleContext: earlyModuleContext{
377 kind: deviceSpecificModule,
378 },
Jiyong Park2db76922017-11-08 16:03:48 +0900379 },
380 inData: true,
381 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900382 in: []string{"nativetest", "my_test"},
383 out: "target/product/test_device/data/nativetest/my_test",
384 partitionDir: "target/product/test_device/data",
Jiyong Park2db76922017-11-08 16:03:48 +0900385 },
386 {
Jaekyun Seok5cfbfbb2018-01-10 19:00:15 +0900387 name: "product native test binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100388 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700389 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800390 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900391 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800392 earlyModuleContext: earlyModuleContext{
393 kind: productSpecificModule,
394 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700395 },
396 inData: true,
397 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900398 in: []string{"nativetest", "my_test"},
399 out: "target/product/test_device/data/nativetest/my_test",
400 partitionDir: "target/product/test_device/data",
Dan Willemsen00269f22017-07-06 16:59:48 -0700401 },
402
403 {
Justin Yund5f6c822019-06-25 16:47:17 +0900404 name: "system_ext native test binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100405 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700406 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800407 os: deviceTarget.Os,
Dario Frenifd05a742018-05-29 13:28:54 +0100408 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800409 earlyModuleContext: earlyModuleContext{
410 kind: systemExtSpecificModule,
411 },
Dario Frenifd05a742018-05-29 13:28:54 +0100412 },
413 inData: true,
414 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900415 in: []string{"nativetest", "my_test"},
416 out: "target/product/test_device/data/nativetest/my_test",
417 partitionDir: "target/product/test_device/data",
Dario Frenifd05a742018-05-29 13:28:54 +0100418 },
419
420 {
Dan Willemsen00269f22017-07-06 16:59:48 -0700421 name: "sanitized system binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100422 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700423 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800424 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700425 target: deviceTarget,
426 },
427 inSanitizerDir: true,
428 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900429 in: []string{"bin", "my_test"},
430 out: "target/product/test_device/data/asan/system/bin/my_test",
431 partitionDir: "target/product/test_device/data/asan/system",
Dan Willemsen00269f22017-07-06 16:59:48 -0700432 },
433 {
434 name: "sanitized vendor binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100435 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700436 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800437 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700438 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800439 earlyModuleContext: earlyModuleContext{
440 kind: socSpecificModule,
441 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700442 },
443 inSanitizerDir: true,
444 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900445 in: []string{"bin", "my_test"},
446 out: "target/product/test_device/data/asan/vendor/bin/my_test",
447 partitionDir: "target/product/test_device/data/asan/vendor",
Dan Willemsen00269f22017-07-06 16:59:48 -0700448 },
Jiyong Park2db76922017-11-08 16:03:48 +0900449 {
450 name: "sanitized odm binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100451 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700452 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800453 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900454 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800455 earlyModuleContext: earlyModuleContext{
456 kind: deviceSpecificModule,
457 },
Jiyong Park2db76922017-11-08 16:03:48 +0900458 },
459 inSanitizerDir: true,
460 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900461 in: []string{"bin", "my_test"},
462 out: "target/product/test_device/data/asan/odm/bin/my_test",
463 partitionDir: "target/product/test_device/data/asan/odm",
Jiyong Park2db76922017-11-08 16:03:48 +0900464 },
465 {
Jaekyun Seok5cfbfbb2018-01-10 19:00:15 +0900466 name: "sanitized product binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100467 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700468 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800469 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900470 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800471 earlyModuleContext: earlyModuleContext{
472 kind: productSpecificModule,
473 },
Jiyong Park2db76922017-11-08 16:03:48 +0900474 },
475 inSanitizerDir: true,
476 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900477 in: []string{"bin", "my_test"},
478 out: "target/product/test_device/data/asan/product/bin/my_test",
479 partitionDir: "target/product/test_device/data/asan/product",
Jiyong Park2db76922017-11-08 16:03:48 +0900480 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700481
482 {
Justin Yund5f6c822019-06-25 16:47:17 +0900483 name: "sanitized system_ext binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100484 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700485 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800486 os: deviceTarget.Os,
Dario Frenifd05a742018-05-29 13:28:54 +0100487 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800488 earlyModuleContext: earlyModuleContext{
489 kind: systemExtSpecificModule,
490 },
Dario Frenifd05a742018-05-29 13:28:54 +0100491 },
492 inSanitizerDir: true,
493 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900494 in: []string{"bin", "my_test"},
495 out: "target/product/test_device/data/asan/system_ext/bin/my_test",
496 partitionDir: "target/product/test_device/data/asan/system_ext",
Dario Frenifd05a742018-05-29 13:28:54 +0100497 },
498
499 {
Dan Willemsen00269f22017-07-06 16:59:48 -0700500 name: "sanitized system native test binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100501 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700502 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800503 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700504 target: deviceTarget,
505 },
506 inData: true,
507 inSanitizerDir: true,
508 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900509 in: []string{"nativetest", "my_test"},
510 out: "target/product/test_device/data/asan/data/nativetest/my_test",
511 partitionDir: "target/product/test_device/data/asan/data",
Dan Willemsen00269f22017-07-06 16:59:48 -0700512 },
513 {
514 name: "sanitized vendor native test binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100515 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700516 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800517 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700518 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800519 earlyModuleContext: earlyModuleContext{
520 kind: socSpecificModule,
521 },
Jiyong Park2db76922017-11-08 16:03:48 +0900522 },
523 inData: true,
524 inSanitizerDir: true,
525 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900526 in: []string{"nativetest", "my_test"},
527 out: "target/product/test_device/data/asan/data/nativetest/my_test",
528 partitionDir: "target/product/test_device/data/asan/data",
Jiyong Park2db76922017-11-08 16:03:48 +0900529 },
530 {
531 name: "sanitized odm native test binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100532 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700533 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800534 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900535 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800536 earlyModuleContext: earlyModuleContext{
537 kind: deviceSpecificModule,
538 },
Jiyong Park2db76922017-11-08 16:03:48 +0900539 },
540 inData: true,
541 inSanitizerDir: true,
542 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900543 in: []string{"nativetest", "my_test"},
544 out: "target/product/test_device/data/asan/data/nativetest/my_test",
545 partitionDir: "target/product/test_device/data/asan/data",
Jiyong Park2db76922017-11-08 16:03:48 +0900546 },
547 {
Jaekyun Seok5cfbfbb2018-01-10 19:00:15 +0900548 name: "sanitized product native test binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100549 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700550 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800551 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900552 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800553 earlyModuleContext: earlyModuleContext{
554 kind: productSpecificModule,
555 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700556 },
557 inData: true,
558 inSanitizerDir: true,
559 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900560 in: []string{"nativetest", "my_test"},
561 out: "target/product/test_device/data/asan/data/nativetest/my_test",
562 partitionDir: "target/product/test_device/data/asan/data",
Dan Willemsen00269f22017-07-06 16:59:48 -0700563 },
Dario Frenifd05a742018-05-29 13:28:54 +0100564 {
Justin Yund5f6c822019-06-25 16:47:17 +0900565 name: "sanitized system_ext native test binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100566 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700567 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800568 os: deviceTarget.Os,
Dario Frenifd05a742018-05-29 13:28:54 +0100569 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800570 earlyModuleContext: earlyModuleContext{
571 kind: systemExtSpecificModule,
572 },
Dario Frenifd05a742018-05-29 13:28:54 +0100573 },
574 inData: true,
575 inSanitizerDir: true,
576 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900577 in: []string{"nativetest", "my_test"},
578 out: "target/product/test_device/data/asan/data/nativetest/my_test",
579 partitionDir: "target/product/test_device/data/asan/data",
Colin Cross6e359402020-02-10 15:29:54 -0800580 }, {
581 name: "device testcases",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100582 ctx: &testModuleInstallPathContext{
Colin Cross6e359402020-02-10 15:29:54 -0800583 baseModuleContext: baseModuleContext{
584 os: deviceTarget.Os,
585 target: deviceTarget,
586 },
587 inTestcases: true,
588 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900589 in: []string{"my_test", "my_test_bin"},
590 out: "target/product/test_device/testcases/my_test/my_test_bin",
591 partitionDir: "target/product/test_device/testcases",
Colin Cross6e359402020-02-10 15:29:54 -0800592 }, {
593 name: "host testcases",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100594 ctx: &testModuleInstallPathContext{
Colin Cross6e359402020-02-10 15:29:54 -0800595 baseModuleContext: baseModuleContext{
596 os: hostTarget.Os,
597 target: hostTarget,
598 },
599 inTestcases: true,
600 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900601 in: []string{"my_test", "my_test_bin"},
602 out: "host/linux-x86/testcases/my_test/my_test_bin",
603 partitionDir: "host/linux-x86/testcases",
Colin Cross6e359402020-02-10 15:29:54 -0800604 }, {
605 name: "forced host testcases",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100606 ctx: &testModuleInstallPathContext{
Colin Cross6e359402020-02-10 15:29:54 -0800607 baseModuleContext: baseModuleContext{
608 os: deviceTarget.Os,
609 target: deviceTarget,
610 },
611 inTestcases: true,
612 forceOS: &Linux,
Jiyong Park87788b52020-09-01 12:37:45 +0900613 forceArch: &X86,
Colin Cross6e359402020-02-10 15:29:54 -0800614 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900615 in: []string{"my_test", "my_test_bin"},
616 out: "host/linux-x86/testcases/my_test/my_test_bin",
617 partitionDir: "host/linux-x86/testcases",
Dario Frenifd05a742018-05-29 13:28:54 +0100618 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700619 }
620
621 for _, tc := range testCases {
622 t.Run(tc.name, func(t *testing.T) {
Colin Cross0ea8ba82019-06-06 14:33:29 -0700623 tc.ctx.baseModuleContext.config = testConfig
Dan Willemsen00269f22017-07-06 16:59:48 -0700624 output := PathForModuleInstall(tc.ctx, tc.in...)
625 if output.basePath.path != tc.out {
626 t.Errorf("unexpected path:\n got: %q\nwant: %q\n",
627 output.basePath.path,
628 tc.out)
629 }
Jiyong Park957bcd92020-10-20 18:23:33 +0900630 if output.partitionDir != tc.partitionDir {
631 t.Errorf("unexpected partitionDir:\n got: %q\nwant: %q\n",
632 output.partitionDir, tc.partitionDir)
633 }
Dan Willemsen00269f22017-07-06 16:59:48 -0700634 })
635 }
636}
Colin Cross5e6cfbe2017-11-03 15:20:35 -0700637
Jiyong Park957bcd92020-10-20 18:23:33 +0900638func TestBaseDirForInstallPath(t *testing.T) {
639 testConfig := pathTestConfig("")
640 deviceTarget := Target{Os: Android, Arch: Arch{ArchType: Arm64}}
641
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100642 ctx := &testModuleInstallPathContext{
Jiyong Park957bcd92020-10-20 18:23:33 +0900643 baseModuleContext: baseModuleContext{
644 os: deviceTarget.Os,
645 target: deviceTarget,
646 },
647 }
648 ctx.baseModuleContext.config = testConfig
649
650 actual := PathForModuleInstall(ctx, "foo", "bar")
651 expectedBaseDir := "target/product/test_device/system"
652 if actual.partitionDir != expectedBaseDir {
653 t.Errorf("unexpected partitionDir:\n got: %q\nwant: %q\n", actual.partitionDir, expectedBaseDir)
654 }
655 expectedRelPath := "foo/bar"
656 if actual.Rel() != expectedRelPath {
657 t.Errorf("unexpected Rel():\n got: %q\nwant: %q\n", actual.Rel(), expectedRelPath)
658 }
659
660 actualAfterJoin := actual.Join(ctx, "baz")
661 // partitionDir is preserved even after joining
662 if actualAfterJoin.partitionDir != expectedBaseDir {
663 t.Errorf("unexpected partitionDir after joining:\n got: %q\nwant: %q\n", actualAfterJoin.partitionDir, expectedBaseDir)
664 }
665 // Rel() is updated though
666 expectedRelAfterJoin := "baz"
667 if actualAfterJoin.Rel() != expectedRelAfterJoin {
668 t.Errorf("unexpected Rel() after joining:\n got: %q\nwant: %q\n", actualAfterJoin.Rel(), expectedRelAfterJoin)
669 }
670}
671
Colin Cross5e6cfbe2017-11-03 15:20:35 -0700672func TestDirectorySortedPaths(t *testing.T) {
Colin Cross98be1bb2019-12-13 20:41:13 -0800673 config := TestConfig("out", nil, "", map[string][]byte{
674 "Android.bp": nil,
675 "a.txt": nil,
676 "a/txt": nil,
677 "a/b/c": nil,
678 "a/b/d": nil,
679 "b": nil,
680 "b/b.txt": nil,
681 "a/a.txt": nil,
Colin Cross07e51612019-03-05 12:46:40 -0800682 })
683
Colin Cross98be1bb2019-12-13 20:41:13 -0800684 ctx := PathContextForTesting(config)
685
Colin Cross5e6cfbe2017-11-03 15:20:35 -0700686 makePaths := func() Paths {
687 return Paths{
Colin Cross07e51612019-03-05 12:46:40 -0800688 PathForSource(ctx, "a.txt"),
689 PathForSource(ctx, "a/txt"),
690 PathForSource(ctx, "a/b/c"),
691 PathForSource(ctx, "a/b/d"),
692 PathForSource(ctx, "b"),
693 PathForSource(ctx, "b/b.txt"),
694 PathForSource(ctx, "a/a.txt"),
Colin Cross5e6cfbe2017-11-03 15:20:35 -0700695 }
696 }
697
698 expected := []string{
699 "a.txt",
700 "a/a.txt",
701 "a/b/c",
702 "a/b/d",
703 "a/txt",
704 "b",
705 "b/b.txt",
706 }
707
708 paths := makePaths()
Colin Crossa140bb02018-04-17 10:52:26 -0700709 reversePaths := ReversePaths(paths)
Colin Cross5e6cfbe2017-11-03 15:20:35 -0700710
711 sortedPaths := PathsToDirectorySortedPaths(paths)
712 reverseSortedPaths := PathsToDirectorySortedPaths(reversePaths)
713
714 if !reflect.DeepEqual(Paths(sortedPaths).Strings(), expected) {
715 t.Fatalf("sorted paths:\n %#v\n != \n %#v", paths.Strings(), expected)
716 }
717
718 if !reflect.DeepEqual(Paths(reverseSortedPaths).Strings(), expected) {
719 t.Fatalf("sorted reversed paths:\n %#v\n !=\n %#v", reversePaths.Strings(), expected)
720 }
721
722 expectedA := []string{
723 "a/a.txt",
724 "a/b/c",
725 "a/b/d",
726 "a/txt",
727 }
728
729 inA := sortedPaths.PathsInDirectory("a")
730 if !reflect.DeepEqual(inA.Strings(), expectedA) {
731 t.Errorf("FilesInDirectory(a):\n %#v\n != \n %#v", inA.Strings(), expectedA)
732 }
733
734 expectedA_B := []string{
735 "a/b/c",
736 "a/b/d",
737 }
738
739 inA_B := sortedPaths.PathsInDirectory("a/b")
740 if !reflect.DeepEqual(inA_B.Strings(), expectedA_B) {
741 t.Errorf("FilesInDirectory(a/b):\n %#v\n != \n %#v", inA_B.Strings(), expectedA_B)
742 }
743
744 expectedB := []string{
745 "b/b.txt",
746 }
747
748 inB := sortedPaths.PathsInDirectory("b")
749 if !reflect.DeepEqual(inB.Strings(), expectedB) {
750 t.Errorf("FilesInDirectory(b):\n %#v\n != \n %#v", inA.Strings(), expectedA)
751 }
752}
Colin Cross43f08db2018-11-12 10:13:39 -0800753
754func TestMaybeRel(t *testing.T) {
755 testCases := []struct {
756 name string
757 base string
758 target string
759 out string
760 isRel bool
761 }{
762 {
763 name: "normal",
764 base: "a/b/c",
765 target: "a/b/c/d",
766 out: "d",
767 isRel: true,
768 },
769 {
770 name: "parent",
771 base: "a/b/c/d",
772 target: "a/b/c",
773 isRel: false,
774 },
775 {
776 name: "not relative",
777 base: "a/b",
778 target: "c/d",
779 isRel: false,
780 },
781 {
782 name: "abs1",
783 base: "/a",
784 target: "a",
785 isRel: false,
786 },
787 {
788 name: "abs2",
789 base: "a",
790 target: "/a",
791 isRel: false,
792 },
793 }
794
795 for _, testCase := range testCases {
796 t.Run(testCase.name, func(t *testing.T) {
797 ctx := &configErrorWrapper{}
798 out, isRel := MaybeRel(ctx, testCase.base, testCase.target)
799 if len(ctx.errors) > 0 {
800 t.Errorf("MaybeRel(..., %s, %s) reported unexpected errors %v",
801 testCase.base, testCase.target, ctx.errors)
802 }
803 if isRel != testCase.isRel || out != testCase.out {
804 t.Errorf("MaybeRel(..., %s, %s) want %v, %v got %v, %v",
805 testCase.base, testCase.target, testCase.out, testCase.isRel, out, isRel)
806 }
807 })
808 }
809}
Colin Cross7b3dcc32019-01-24 13:14:39 -0800810
811func TestPathForSource(t *testing.T) {
812 testCases := []struct {
813 name string
814 buildDir string
815 src string
816 err string
817 }{
818 {
819 name: "normal",
820 buildDir: "out",
821 src: "a/b/c",
822 },
823 {
824 name: "abs",
825 buildDir: "out",
826 src: "/a/b/c",
827 err: "is outside directory",
828 },
829 {
830 name: "in out dir",
831 buildDir: "out",
832 src: "out/a/b/c",
833 err: "is in output",
834 },
835 }
836
837 funcs := []struct {
838 name string
839 f func(ctx PathContext, pathComponents ...string) (SourcePath, error)
840 }{
841 {"pathForSource", pathForSource},
842 {"safePathForSource", safePathForSource},
843 }
844
845 for _, f := range funcs {
846 t.Run(f.name, func(t *testing.T) {
847 for _, test := range testCases {
848 t.Run(test.name, func(t *testing.T) {
Colin Cross98be1bb2019-12-13 20:41:13 -0800849 testConfig := pathTestConfig(test.buildDir)
Colin Cross7b3dcc32019-01-24 13:14:39 -0800850 ctx := &configErrorWrapper{config: testConfig}
851 _, err := f.f(ctx, test.src)
852 if len(ctx.errors) > 0 {
853 t.Fatalf("unexpected errors %v", ctx.errors)
854 }
855 if err != nil {
856 if test.err == "" {
857 t.Fatalf("unexpected error %q", err.Error())
858 } else if !strings.Contains(err.Error(), test.err) {
859 t.Fatalf("incorrect error, want substring %q got %q", test.err, err.Error())
860 }
861 } else {
862 if test.err != "" {
863 t.Fatalf("missing error %q", test.err)
864 }
865 }
866 })
867 }
868 })
869 }
870}
Colin Cross8854a5a2019-02-11 14:14:16 -0800871
Colin Cross8a497952019-03-05 22:25:09 -0800872type pathForModuleSrcTestModule struct {
Colin Cross937664a2019-03-06 10:17:32 -0800873 ModuleBase
874 props struct {
875 Srcs []string `android:"path"`
876 Exclude_srcs []string `android:"path"`
Colin Cross8a497952019-03-05 22:25:09 -0800877
878 Src *string `android:"path"`
Colin Crossba71a3f2019-03-18 12:12:48 -0700879
880 Module_handles_missing_deps bool
Colin Cross937664a2019-03-06 10:17:32 -0800881 }
882
Colin Cross8a497952019-03-05 22:25:09 -0800883 src string
884 rel string
885
886 srcs []string
Colin Cross937664a2019-03-06 10:17:32 -0800887 rels []string
Colin Cross8a497952019-03-05 22:25:09 -0800888
889 missingDeps []string
Colin Cross937664a2019-03-06 10:17:32 -0800890}
891
Colin Cross8a497952019-03-05 22:25:09 -0800892func pathForModuleSrcTestModuleFactory() Module {
893 module := &pathForModuleSrcTestModule{}
Colin Cross937664a2019-03-06 10:17:32 -0800894 module.AddProperties(&module.props)
895 InitAndroidModule(module)
896 return module
897}
898
Colin Cross8a497952019-03-05 22:25:09 -0800899func (p *pathForModuleSrcTestModule) GenerateAndroidBuildActions(ctx ModuleContext) {
Colin Crossba71a3f2019-03-18 12:12:48 -0700900 var srcs Paths
901 if p.props.Module_handles_missing_deps {
902 srcs, p.missingDeps = PathsAndMissingDepsForModuleSrcExcludes(ctx, p.props.Srcs, p.props.Exclude_srcs)
903 } else {
904 srcs = PathsForModuleSrcExcludes(ctx, p.props.Srcs, p.props.Exclude_srcs)
905 }
Colin Cross8a497952019-03-05 22:25:09 -0800906 p.srcs = srcs.Strings()
Colin Cross937664a2019-03-06 10:17:32 -0800907
Colin Cross8a497952019-03-05 22:25:09 -0800908 for _, src := range srcs {
Colin Cross937664a2019-03-06 10:17:32 -0800909 p.rels = append(p.rels, src.Rel())
910 }
Colin Cross8a497952019-03-05 22:25:09 -0800911
912 if p.props.Src != nil {
913 src := PathForModuleSrc(ctx, *p.props.Src)
914 if src != nil {
915 p.src = src.String()
916 p.rel = src.Rel()
917 }
918 }
919
Colin Crossba71a3f2019-03-18 12:12:48 -0700920 if !p.props.Module_handles_missing_deps {
921 p.missingDeps = ctx.GetMissingDependencies()
922 }
Colin Cross6c4f21f2019-06-06 15:41:36 -0700923
924 ctx.Build(pctx, BuildParams{
925 Rule: Touch,
926 Output: PathForModuleOut(ctx, "output"),
927 })
Colin Cross8a497952019-03-05 22:25:09 -0800928}
929
Colin Cross41955e82019-05-29 14:40:35 -0700930type pathForModuleSrcOutputFileProviderModule struct {
931 ModuleBase
932 props struct {
933 Outs []string
934 Tagged []string
935 }
936
937 outs Paths
938 tagged Paths
939}
940
941func pathForModuleSrcOutputFileProviderModuleFactory() Module {
942 module := &pathForModuleSrcOutputFileProviderModule{}
943 module.AddProperties(&module.props)
944 InitAndroidModule(module)
945 return module
946}
947
948func (p *pathForModuleSrcOutputFileProviderModule) GenerateAndroidBuildActions(ctx ModuleContext) {
949 for _, out := range p.props.Outs {
950 p.outs = append(p.outs, PathForModuleOut(ctx, out))
951 }
952
953 for _, tagged := range p.props.Tagged {
954 p.tagged = append(p.tagged, PathForModuleOut(ctx, tagged))
955 }
956}
957
958func (p *pathForModuleSrcOutputFileProviderModule) OutputFiles(tag string) (Paths, error) {
959 switch tag {
960 case "":
961 return p.outs, nil
962 case ".tagged":
963 return p.tagged, nil
964 default:
965 return nil, fmt.Errorf("unsupported tag %q", tag)
966 }
967}
968
Colin Cross8a497952019-03-05 22:25:09 -0800969type pathForModuleSrcTestCase struct {
970 name string
971 bp string
972 srcs []string
973 rels []string
974 src string
975 rel string
976}
977
Paul Duffin54054682021-03-16 21:11:42 +0000978func testPathForModuleSrc(t *testing.T, tests []pathForModuleSrcTestCase) {
Colin Cross8a497952019-03-05 22:25:09 -0800979 for _, test := range tests {
980 t.Run(test.name, func(t *testing.T) {
Colin Cross8a497952019-03-05 22:25:09 -0800981 fgBp := `
982 filegroup {
983 name: "a",
984 srcs: ["src/a"],
985 }
986 `
987
Colin Cross41955e82019-05-29 14:40:35 -0700988 ofpBp := `
989 output_file_provider {
990 name: "b",
991 outs: ["gen/b"],
992 tagged: ["gen/c"],
993 }
994 `
995
Paul Duffin54054682021-03-16 21:11:42 +0000996 mockFS := MockFS{
Colin Cross8a497952019-03-05 22:25:09 -0800997 "fg/Android.bp": []byte(fgBp),
998 "foo/Android.bp": []byte(test.bp),
Colin Cross41955e82019-05-29 14:40:35 -0700999 "ofp/Android.bp": []byte(ofpBp),
Colin Cross8a497952019-03-05 22:25:09 -08001000 "fg/src/a": nil,
1001 "foo/src/b": nil,
1002 "foo/src/c": nil,
1003 "foo/src/d": nil,
1004 "foo/src/e/e": nil,
1005 "foo/src_special/$": nil,
1006 }
1007
Paul Duffin30ac3e72021-03-20 00:36:14 +00001008 result := GroupFixturePreparers(
Paul Duffin54054682021-03-16 21:11:42 +00001009 FixtureRegisterWithContext(func(ctx RegistrationContext) {
1010 ctx.RegisterModuleType("test", pathForModuleSrcTestModuleFactory)
1011 ctx.RegisterModuleType("output_file_provider", pathForModuleSrcOutputFileProviderModuleFactory)
1012 ctx.RegisterModuleType("filegroup", FileGroupFactory)
1013 }),
1014 mockFS.AddToFixture(),
Paul Duffin30ac3e72021-03-20 00:36:14 +00001015 ).RunTest(t)
Colin Cross8a497952019-03-05 22:25:09 -08001016
Paul Duffin54054682021-03-16 21:11:42 +00001017 m := result.ModuleForTests("foo", "").Module().(*pathForModuleSrcTestModule)
Colin Crossae8600b2020-10-29 17:09:13 -07001018
Paul Duffin54054682021-03-16 21:11:42 +00001019 AssertStringPathsRelativeToTopEquals(t, "srcs", result.Config, test.srcs, m.srcs)
1020 AssertStringPathsRelativeToTopEquals(t, "rels", result.Config, test.rels, m.rels)
1021 AssertStringPathRelativeToTopEquals(t, "src", result.Config, test.src, m.src)
1022 AssertStringPathRelativeToTopEquals(t, "rel", result.Config, test.rel, m.rel)
Colin Cross8a497952019-03-05 22:25:09 -08001023 })
1024 }
Colin Cross937664a2019-03-06 10:17:32 -08001025}
1026
Colin Cross8a497952019-03-05 22:25:09 -08001027func TestPathsForModuleSrc(t *testing.T) {
1028 tests := []pathForModuleSrcTestCase{
Colin Cross937664a2019-03-06 10:17:32 -08001029 {
1030 name: "path",
1031 bp: `
1032 test {
1033 name: "foo",
1034 srcs: ["src/b"],
1035 }`,
1036 srcs: []string{"foo/src/b"},
1037 rels: []string{"src/b"},
1038 },
1039 {
1040 name: "glob",
1041 bp: `
1042 test {
1043 name: "foo",
1044 srcs: [
1045 "src/*",
1046 "src/e/*",
1047 ],
1048 }`,
1049 srcs: []string{"foo/src/b", "foo/src/c", "foo/src/d", "foo/src/e/e"},
1050 rels: []string{"src/b", "src/c", "src/d", "src/e/e"},
1051 },
1052 {
1053 name: "recursive glob",
1054 bp: `
1055 test {
1056 name: "foo",
1057 srcs: ["src/**/*"],
1058 }`,
1059 srcs: []string{"foo/src/b", "foo/src/c", "foo/src/d", "foo/src/e/e"},
1060 rels: []string{"src/b", "src/c", "src/d", "src/e/e"},
1061 },
1062 {
1063 name: "filegroup",
1064 bp: `
1065 test {
1066 name: "foo",
1067 srcs: [":a"],
1068 }`,
1069 srcs: []string{"fg/src/a"},
1070 rels: []string{"src/a"},
1071 },
1072 {
Colin Cross41955e82019-05-29 14:40:35 -07001073 name: "output file provider",
1074 bp: `
1075 test {
1076 name: "foo",
1077 srcs: [":b"],
1078 }`,
Paul Duffin54054682021-03-16 21:11:42 +00001079 srcs: []string{"out/soong/.intermediates/ofp/b/gen/b"},
Colin Cross41955e82019-05-29 14:40:35 -07001080 rels: []string{"gen/b"},
1081 },
1082 {
1083 name: "output file provider tagged",
1084 bp: `
1085 test {
1086 name: "foo",
1087 srcs: [":b{.tagged}"],
1088 }`,
Paul Duffin54054682021-03-16 21:11:42 +00001089 srcs: []string{"out/soong/.intermediates/ofp/b/gen/c"},
Colin Cross41955e82019-05-29 14:40:35 -07001090 rels: []string{"gen/c"},
1091 },
1092 {
Jooyung Han7607dd32020-07-05 10:23:14 +09001093 name: "output file provider with exclude",
1094 bp: `
1095 test {
1096 name: "foo",
1097 srcs: [":b", ":c"],
1098 exclude_srcs: [":c"]
1099 }
1100 output_file_provider {
1101 name: "c",
1102 outs: ["gen/c"],
1103 }`,
Paul Duffin54054682021-03-16 21:11:42 +00001104 srcs: []string{"out/soong/.intermediates/ofp/b/gen/b"},
Jooyung Han7607dd32020-07-05 10:23:14 +09001105 rels: []string{"gen/b"},
1106 },
1107 {
Colin Cross937664a2019-03-06 10:17:32 -08001108 name: "special characters glob",
1109 bp: `
1110 test {
1111 name: "foo",
1112 srcs: ["src_special/*"],
1113 }`,
1114 srcs: []string{"foo/src_special/$"},
1115 rels: []string{"src_special/$"},
1116 },
1117 }
1118
Paul Duffin54054682021-03-16 21:11:42 +00001119 testPathForModuleSrc(t, tests)
Colin Cross41955e82019-05-29 14:40:35 -07001120}
1121
1122func TestPathForModuleSrc(t *testing.T) {
Colin Cross8a497952019-03-05 22:25:09 -08001123 tests := []pathForModuleSrcTestCase{
1124 {
1125 name: "path",
1126 bp: `
1127 test {
1128 name: "foo",
1129 src: "src/b",
1130 }`,
1131 src: "foo/src/b",
1132 rel: "src/b",
1133 },
1134 {
1135 name: "glob",
1136 bp: `
1137 test {
1138 name: "foo",
1139 src: "src/e/*",
1140 }`,
1141 src: "foo/src/e/e",
1142 rel: "src/e/e",
1143 },
1144 {
1145 name: "filegroup",
1146 bp: `
1147 test {
1148 name: "foo",
1149 src: ":a",
1150 }`,
1151 src: "fg/src/a",
1152 rel: "src/a",
1153 },
1154 {
Colin Cross41955e82019-05-29 14:40:35 -07001155 name: "output file provider",
1156 bp: `
1157 test {
1158 name: "foo",
1159 src: ":b",
1160 }`,
Paul Duffin54054682021-03-16 21:11:42 +00001161 src: "out/soong/.intermediates/ofp/b/gen/b",
Colin Cross41955e82019-05-29 14:40:35 -07001162 rel: "gen/b",
1163 },
1164 {
1165 name: "output file provider tagged",
1166 bp: `
1167 test {
1168 name: "foo",
1169 src: ":b{.tagged}",
1170 }`,
Paul Duffin54054682021-03-16 21:11:42 +00001171 src: "out/soong/.intermediates/ofp/b/gen/c",
Colin Cross41955e82019-05-29 14:40:35 -07001172 rel: "gen/c",
1173 },
1174 {
Colin Cross8a497952019-03-05 22:25:09 -08001175 name: "special characters glob",
1176 bp: `
1177 test {
1178 name: "foo",
1179 src: "src_special/*",
1180 }`,
1181 src: "foo/src_special/$",
1182 rel: "src_special/$",
1183 },
1184 }
1185
Paul Duffin54054682021-03-16 21:11:42 +00001186 testPathForModuleSrc(t, tests)
Colin Cross8a497952019-03-05 22:25:09 -08001187}
Colin Cross937664a2019-03-06 10:17:32 -08001188
Colin Cross8a497952019-03-05 22:25:09 -08001189func TestPathsForModuleSrc_AllowMissingDependencies(t *testing.T) {
Colin Cross8a497952019-03-05 22:25:09 -08001190 bp := `
1191 test {
1192 name: "foo",
1193 srcs: [":a"],
1194 exclude_srcs: [":b"],
1195 src: ":c",
1196 }
Colin Crossba71a3f2019-03-18 12:12:48 -07001197
1198 test {
1199 name: "bar",
1200 srcs: [":d"],
1201 exclude_srcs: [":e"],
1202 module_handles_missing_deps: true,
1203 }
Colin Cross8a497952019-03-05 22:25:09 -08001204 `
1205
Paul Duffin30ac3e72021-03-20 00:36:14 +00001206 result := GroupFixturePreparers(
Paul Duffin54054682021-03-16 21:11:42 +00001207 PrepareForTestWithAllowMissingDependencies,
1208 FixtureRegisterWithContext(func(ctx RegistrationContext) {
1209 ctx.RegisterModuleType("test", pathForModuleSrcTestModuleFactory)
1210 }),
1211 FixtureWithRootAndroidBp(bp),
Paul Duffin30ac3e72021-03-20 00:36:14 +00001212 ).RunTest(t)
Colin Cross8a497952019-03-05 22:25:09 -08001213
Paul Duffin54054682021-03-16 21:11:42 +00001214 foo := result.ModuleForTests("foo", "").Module().(*pathForModuleSrcTestModule)
Colin Cross8a497952019-03-05 22:25:09 -08001215
Paul Duffin54054682021-03-16 21:11:42 +00001216 AssertArrayString(t, "foo missing deps", []string{"a", "b", "c"}, foo.missingDeps)
1217 AssertArrayString(t, "foo srcs", []string{}, foo.srcs)
1218 AssertStringEquals(t, "foo src", "", foo.src)
Colin Cross98be1bb2019-12-13 20:41:13 -08001219
Paul Duffin54054682021-03-16 21:11:42 +00001220 bar := result.ModuleForTests("bar", "").Module().(*pathForModuleSrcTestModule)
Colin Cross98be1bb2019-12-13 20:41:13 -08001221
Paul Duffin54054682021-03-16 21:11:42 +00001222 AssertArrayString(t, "bar missing deps", []string{"d", "e"}, bar.missingDeps)
1223 AssertArrayString(t, "bar srcs", []string{}, bar.srcs)
Colin Cross937664a2019-03-06 10:17:32 -08001224}
1225
Paul Duffin567465d2021-03-16 01:21:34 +00001226func TestPathRelativeToTop(t *testing.T) {
1227 testConfig := pathTestConfig("/tmp/build/top")
1228 deviceTarget := Target{Os: Android, Arch: Arch{ArchType: Arm64}}
1229
1230 ctx := &testModuleInstallPathContext{
1231 baseModuleContext: baseModuleContext{
1232 os: deviceTarget.Os,
1233 target: deviceTarget,
1234 },
1235 }
1236 ctx.baseModuleContext.config = testConfig
1237
1238 t.Run("install for soong", func(t *testing.T) {
1239 p := PathForModuleInstall(ctx, "install/path")
1240 AssertPathRelativeToTopEquals(t, "install path for soong", "out/soong/target/product/test_device/system/install/path", p)
1241 })
1242 t.Run("install for make", func(t *testing.T) {
1243 p := PathForModuleInstall(ctx, "install/path").ToMakePath()
1244 AssertPathRelativeToTopEquals(t, "install path for make", "out/target/product/test_device/system/install/path", p)
1245 })
1246 t.Run("output", func(t *testing.T) {
1247 p := PathForOutput(ctx, "output/path")
1248 AssertPathRelativeToTopEquals(t, "output path", "out/soong/output/path", p)
1249 })
1250 t.Run("source", func(t *testing.T) {
1251 p := PathForSource(ctx, "source/path")
1252 AssertPathRelativeToTopEquals(t, "source path", "source/path", p)
1253 })
1254 t.Run("mixture", func(t *testing.T) {
1255 paths := Paths{
1256 PathForModuleInstall(ctx, "install/path"),
1257 PathForModuleInstall(ctx, "install/path").ToMakePath(),
1258 PathForOutput(ctx, "output/path"),
1259 PathForSource(ctx, "source/path"),
1260 }
1261
1262 expected := []string{
1263 "out/soong/target/product/test_device/system/install/path",
1264 "out/target/product/test_device/system/install/path",
1265 "out/soong/output/path",
1266 "source/path",
1267 }
1268 AssertPathsRelativeToTopEquals(t, "mixture", expected, paths)
1269 })
1270}
1271
Colin Cross8854a5a2019-02-11 14:14:16 -08001272func ExampleOutputPath_ReplaceExtension() {
1273 ctx := &configErrorWrapper{
Colin Cross98be1bb2019-12-13 20:41:13 -08001274 config: TestConfig("out", nil, "", nil),
Colin Cross8854a5a2019-02-11 14:14:16 -08001275 }
Colin Cross2cdd5df2019-02-25 10:25:24 -08001276 p := PathForOutput(ctx, "system/framework").Join(ctx, "boot.art")
Colin Cross8854a5a2019-02-11 14:14:16 -08001277 p2 := p.ReplaceExtension(ctx, "oat")
1278 fmt.Println(p, p2)
Colin Cross2cdd5df2019-02-25 10:25:24 -08001279 fmt.Println(p.Rel(), p2.Rel())
Colin Cross8854a5a2019-02-11 14:14:16 -08001280
1281 // Output:
1282 // out/system/framework/boot.art out/system/framework/boot.oat
Colin Cross2cdd5df2019-02-25 10:25:24 -08001283 // boot.art boot.oat
Colin Cross8854a5a2019-02-11 14:14:16 -08001284}
Colin Cross40e33732019-02-15 11:08:35 -08001285
Colin Cross41b46762020-10-09 19:26:32 -07001286func ExampleOutputPath_InSameDir() {
Colin Cross40e33732019-02-15 11:08:35 -08001287 ctx := &configErrorWrapper{
Colin Cross98be1bb2019-12-13 20:41:13 -08001288 config: TestConfig("out", nil, "", nil),
Colin Cross40e33732019-02-15 11:08:35 -08001289 }
Colin Cross2cdd5df2019-02-25 10:25:24 -08001290 p := PathForOutput(ctx, "system/framework").Join(ctx, "boot.art")
Colin Cross40e33732019-02-15 11:08:35 -08001291 p2 := p.InSameDir(ctx, "oat", "arm", "boot.vdex")
1292 fmt.Println(p, p2)
Colin Cross2cdd5df2019-02-25 10:25:24 -08001293 fmt.Println(p.Rel(), p2.Rel())
Colin Cross40e33732019-02-15 11:08:35 -08001294
1295 // Output:
1296 // out/system/framework/boot.art out/system/framework/oat/arm/boot.vdex
Colin Cross2cdd5df2019-02-25 10:25:24 -08001297 // boot.art oat/arm/boot.vdex
Colin Cross40e33732019-02-15 11:08:35 -08001298}
Colin Cross27027c72020-02-28 15:34:17 -08001299
1300func BenchmarkFirstUniquePaths(b *testing.B) {
1301 implementations := []struct {
1302 name string
1303 f func(Paths) Paths
1304 }{
1305 {
1306 name: "list",
1307 f: firstUniquePathsList,
1308 },
1309 {
1310 name: "map",
1311 f: firstUniquePathsMap,
1312 },
1313 }
1314 const maxSize = 1024
1315 uniquePaths := make(Paths, maxSize)
1316 for i := range uniquePaths {
1317 uniquePaths[i] = PathForTesting(strconv.Itoa(i))
1318 }
1319 samePath := make(Paths, maxSize)
1320 for i := range samePath {
1321 samePath[i] = uniquePaths[0]
1322 }
1323
1324 f := func(b *testing.B, imp func(Paths) Paths, paths Paths) {
1325 for i := 0; i < b.N; i++ {
1326 b.ReportAllocs()
1327 paths = append(Paths(nil), paths...)
1328 imp(paths)
1329 }
1330 }
1331
1332 for n := 1; n <= maxSize; n <<= 1 {
1333 b.Run(strconv.Itoa(n), func(b *testing.B) {
1334 for _, implementation := range implementations {
1335 b.Run(implementation.name, func(b *testing.B) {
1336 b.Run("same", func(b *testing.B) {
1337 f(b, implementation.f, samePath[:n])
1338 })
1339 b.Run("unique", func(b *testing.B) {
1340 f(b, implementation.f, uniquePaths[:n])
1341 })
1342 })
1343 }
1344 })
1345 }
1346}