blob: e7fd763e4247105d100f7c19d30b5757dac245a1 [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"
Dan Willemsen00269f22017-07-06 16:59:48 -070024
Colin Cross8a497952019-03-05 22:25:09 -080025 "github.com/google/blueprint/proptools"
Dan Willemsen34cc69e2015-09-23 15:26:20 -070026)
27
28type strsTestCase struct {
29 in []string
30 out string
31 err []error
32}
33
34var commonValidatePathTestCases = []strsTestCase{
35 {
36 in: []string{""},
37 out: "",
38 },
39 {
40 in: []string{"a/b"},
41 out: "a/b",
42 },
43 {
44 in: []string{"a/b", "c"},
45 out: "a/b/c",
46 },
47 {
48 in: []string{"a/.."},
49 out: ".",
50 },
51 {
52 in: []string{"."},
53 out: ".",
54 },
55 {
56 in: []string{".."},
57 out: "",
58 err: []error{errors.New("Path is outside directory: ..")},
59 },
60 {
61 in: []string{"../a"},
62 out: "",
63 err: []error{errors.New("Path is outside directory: ../a")},
64 },
65 {
66 in: []string{"b/../../a"},
67 out: "",
68 err: []error{errors.New("Path is outside directory: ../a")},
69 },
70 {
71 in: []string{"/a"},
72 out: "",
73 err: []error{errors.New("Path is outside directory: /a")},
74 },
Dan Willemsen80a7c2a2015-12-21 14:57:11 -080075 {
76 in: []string{"a", "../b"},
77 out: "",
78 err: []error{errors.New("Path is outside directory: ../b")},
79 },
80 {
81 in: []string{"a", "b/../../c"},
82 out: "",
83 err: []error{errors.New("Path is outside directory: ../c")},
84 },
85 {
86 in: []string{"a", "./.."},
87 out: "",
88 err: []error{errors.New("Path is outside directory: ..")},
89 },
Dan Willemsen34cc69e2015-09-23 15:26:20 -070090}
91
92var validateSafePathTestCases = append(commonValidatePathTestCases, []strsTestCase{
93 {
94 in: []string{"$host/../$a"},
95 out: "$a",
96 },
97}...)
98
99var validatePathTestCases = append(commonValidatePathTestCases, []strsTestCase{
100 {
101 in: []string{"$host/../$a"},
102 out: "",
103 err: []error{errors.New("Path contains invalid character($): $host/../$a")},
104 },
105 {
106 in: []string{"$host/.."},
107 out: "",
108 err: []error{errors.New("Path contains invalid character($): $host/..")},
109 },
110}...)
111
112func TestValidateSafePath(t *testing.T) {
113 for _, testCase := range validateSafePathTestCases {
Colin Crossdc75ae72018-02-22 13:48:13 -0800114 t.Run(strings.Join(testCase.in, ","), func(t *testing.T) {
115 ctx := &configErrorWrapper{}
Colin Cross1ccfcc32018-02-22 13:54:26 -0800116 out, err := validateSafePath(testCase.in...)
117 if err != nil {
118 reportPathError(ctx, err)
119 }
Colin Crossdc75ae72018-02-22 13:48:13 -0800120 check(t, "validateSafePath", p(testCase.in), out, ctx.errors, testCase.out, testCase.err)
121 })
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700122 }
123}
124
125func TestValidatePath(t *testing.T) {
126 for _, testCase := range validatePathTestCases {
Colin Crossdc75ae72018-02-22 13:48:13 -0800127 t.Run(strings.Join(testCase.in, ","), func(t *testing.T) {
128 ctx := &configErrorWrapper{}
Colin Cross1ccfcc32018-02-22 13:54:26 -0800129 out, err := validatePath(testCase.in...)
130 if err != nil {
131 reportPathError(ctx, err)
132 }
Colin Crossdc75ae72018-02-22 13:48:13 -0800133 check(t, "validatePath", p(testCase.in), out, ctx.errors, testCase.out, testCase.err)
134 })
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700135 }
136}
137
138func TestOptionalPath(t *testing.T) {
139 var path OptionalPath
140 checkInvalidOptionalPath(t, path)
141
142 path = OptionalPathForPath(nil)
143 checkInvalidOptionalPath(t, path)
144}
145
146func checkInvalidOptionalPath(t *testing.T, path OptionalPath) {
Colin Crossdc75ae72018-02-22 13:48:13 -0800147 t.Helper()
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700148 if path.Valid() {
149 t.Errorf("Uninitialized OptionalPath should not be valid")
150 }
151 if path.String() != "" {
152 t.Errorf("Uninitialized OptionalPath String() should return \"\", not %q", path.String())
153 }
154 defer func() {
155 if r := recover(); r == nil {
156 t.Errorf("Expected a panic when calling Path() on an uninitialized OptionalPath")
157 }
158 }()
159 path.Path()
160}
161
162func check(t *testing.T, testType, testString string,
163 got interface{}, err []error,
164 expected interface{}, expectedErr []error) {
Colin Crossdc75ae72018-02-22 13:48:13 -0800165 t.Helper()
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700166
167 printedTestCase := false
168 e := func(s string, expected, got interface{}) {
Colin Crossdc75ae72018-02-22 13:48:13 -0800169 t.Helper()
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700170 if !printedTestCase {
171 t.Errorf("test case %s: %s", testType, testString)
172 printedTestCase = true
173 }
174 t.Errorf("incorrect %s", s)
175 t.Errorf(" expected: %s", p(expected))
176 t.Errorf(" got: %s", p(got))
177 }
178
179 if !reflect.DeepEqual(expectedErr, err) {
180 e("errors:", expectedErr, err)
181 }
182
183 if !reflect.DeepEqual(expected, got) {
184 e("output:", expected, got)
185 }
186}
187
188func p(in interface{}) string {
189 if v, ok := in.([]interface{}); ok {
190 s := make([]string, len(v))
191 for i := range v {
192 s[i] = fmt.Sprintf("%#v", v[i])
193 }
194 return "[" + strings.Join(s, ", ") + "]"
195 } else {
196 return fmt.Sprintf("%#v", in)
197 }
198}
Dan Willemsen00269f22017-07-06 16:59:48 -0700199
Colin Cross98be1bb2019-12-13 20:41:13 -0800200func pathTestConfig(buildDir string) Config {
201 return TestConfig(buildDir, nil, "", nil)
202}
203
Dan Willemsen00269f22017-07-06 16:59:48 -0700204func TestPathForModuleInstall(t *testing.T) {
Colin Cross98be1bb2019-12-13 20:41:13 -0800205 testConfig := pathTestConfig("")
Dan Willemsen00269f22017-07-06 16:59:48 -0700206
Jiyong Park87788b52020-09-01 12:37:45 +0900207 hostTarget := Target{Os: Linux, Arch: Arch{ArchType: X86}}
208 deviceTarget := Target{Os: Android, Arch: Arch{ArchType: Arm64}}
Dan Willemsen00269f22017-07-06 16:59:48 -0700209
210 testCases := []struct {
Jiyong Park957bcd92020-10-20 18:23:33 +0900211 name string
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100212 ctx *testModuleInstallPathContext
Jiyong Park957bcd92020-10-20 18:23:33 +0900213 in []string
214 out string
215 partitionDir string
Dan Willemsen00269f22017-07-06 16:59:48 -0700216 }{
217 {
218 name: "host binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100219 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700220 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800221 os: hostTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700222 target: hostTarget,
223 },
224 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900225 in: []string{"bin", "my_test"},
226 out: "host/linux-x86/bin/my_test",
227 partitionDir: "host/linux-x86",
Dan Willemsen00269f22017-07-06 16:59:48 -0700228 },
229
230 {
231 name: "system binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100232 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700233 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800234 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700235 target: deviceTarget,
236 },
237 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900238 in: []string{"bin", "my_test"},
239 out: "target/product/test_device/system/bin/my_test",
240 partitionDir: "target/product/test_device/system",
Dan Willemsen00269f22017-07-06 16:59:48 -0700241 },
242 {
243 name: "vendor binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100244 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700245 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800246 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700247 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800248 earlyModuleContext: earlyModuleContext{
249 kind: socSpecificModule,
250 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700251 },
252 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900253 in: []string{"bin", "my_test"},
254 out: "target/product/test_device/vendor/bin/my_test",
255 partitionDir: "target/product/test_device/vendor",
Dan Willemsen00269f22017-07-06 16:59:48 -0700256 },
Jiyong Park2db76922017-11-08 16:03:48 +0900257 {
258 name: "odm binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100259 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700260 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800261 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900262 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800263 earlyModuleContext: earlyModuleContext{
264 kind: deviceSpecificModule,
265 },
Jiyong Park2db76922017-11-08 16:03:48 +0900266 },
267 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900268 in: []string{"bin", "my_test"},
269 out: "target/product/test_device/odm/bin/my_test",
270 partitionDir: "target/product/test_device/odm",
Jiyong Park2db76922017-11-08 16:03:48 +0900271 },
272 {
Jaekyun Seok5cfbfbb2018-01-10 19:00:15 +0900273 name: "product binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100274 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700275 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800276 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900277 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800278 earlyModuleContext: earlyModuleContext{
279 kind: productSpecificModule,
280 },
Jiyong Park2db76922017-11-08 16:03:48 +0900281 },
282 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900283 in: []string{"bin", "my_test"},
284 out: "target/product/test_device/product/bin/my_test",
285 partitionDir: "target/product/test_device/product",
Jiyong Park2db76922017-11-08 16:03:48 +0900286 },
Dario Frenifd05a742018-05-29 13:28:54 +0100287 {
Justin Yund5f6c822019-06-25 16:47:17 +0900288 name: "system_ext binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100289 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700290 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800291 os: deviceTarget.Os,
Dario Frenifd05a742018-05-29 13:28:54 +0100292 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800293 earlyModuleContext: earlyModuleContext{
294 kind: systemExtSpecificModule,
295 },
Dario Frenifd05a742018-05-29 13:28:54 +0100296 },
297 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900298 in: []string{"bin", "my_test"},
299 out: "target/product/test_device/system_ext/bin/my_test",
300 partitionDir: "target/product/test_device/system_ext",
Dario Frenifd05a742018-05-29 13:28:54 +0100301 },
Colin Cross90ba5f42019-10-02 11:10:58 -0700302 {
303 name: "root binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100304 ctx: &testModuleInstallPathContext{
Colin Cross90ba5f42019-10-02 11:10:58 -0700305 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800306 os: deviceTarget.Os,
Colin Cross90ba5f42019-10-02 11:10:58 -0700307 target: deviceTarget,
308 },
309 inRoot: true,
310 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900311 in: []string{"my_test"},
312 out: "target/product/test_device/root/my_test",
313 partitionDir: "target/product/test_device/root",
Colin Cross90ba5f42019-10-02 11:10:58 -0700314 },
315 {
316 name: "recovery binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100317 ctx: &testModuleInstallPathContext{
Colin Cross90ba5f42019-10-02 11:10:58 -0700318 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800319 os: deviceTarget.Os,
Colin Cross90ba5f42019-10-02 11:10:58 -0700320 target: deviceTarget,
321 },
322 inRecovery: true,
323 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900324 in: []string{"bin/my_test"},
325 out: "target/product/test_device/recovery/root/system/bin/my_test",
326 partitionDir: "target/product/test_device/recovery/root/system",
Colin Cross90ba5f42019-10-02 11:10:58 -0700327 },
328 {
329 name: "recovery root binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100330 ctx: &testModuleInstallPathContext{
Colin Cross90ba5f42019-10-02 11:10:58 -0700331 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800332 os: deviceTarget.Os,
Colin Cross90ba5f42019-10-02 11:10:58 -0700333 target: deviceTarget,
334 },
335 inRecovery: true,
336 inRoot: true,
337 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900338 in: []string{"my_test"},
339 out: "target/product/test_device/recovery/root/my_test",
340 partitionDir: "target/product/test_device/recovery/root",
Colin Cross90ba5f42019-10-02 11:10:58 -0700341 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700342
343 {
344 name: "system native test binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100345 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700346 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800347 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700348 target: deviceTarget,
349 },
350 inData: true,
351 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900352 in: []string{"nativetest", "my_test"},
353 out: "target/product/test_device/data/nativetest/my_test",
354 partitionDir: "target/product/test_device/data",
Dan Willemsen00269f22017-07-06 16:59:48 -0700355 },
356 {
357 name: "vendor native test binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100358 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700359 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800360 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700361 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800362 earlyModuleContext: earlyModuleContext{
363 kind: socSpecificModule,
364 },
Jiyong Park2db76922017-11-08 16:03:48 +0900365 },
366 inData: true,
367 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900368 in: []string{"nativetest", "my_test"},
369 out: "target/product/test_device/data/nativetest/my_test",
370 partitionDir: "target/product/test_device/data",
Jiyong Park2db76922017-11-08 16:03:48 +0900371 },
372 {
373 name: "odm native test binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100374 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700375 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800376 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900377 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800378 earlyModuleContext: earlyModuleContext{
379 kind: deviceSpecificModule,
380 },
Jiyong Park2db76922017-11-08 16:03:48 +0900381 },
382 inData: true,
383 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900384 in: []string{"nativetest", "my_test"},
385 out: "target/product/test_device/data/nativetest/my_test",
386 partitionDir: "target/product/test_device/data",
Jiyong Park2db76922017-11-08 16:03:48 +0900387 },
388 {
Jaekyun Seok5cfbfbb2018-01-10 19:00:15 +0900389 name: "product native test binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100390 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700391 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800392 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900393 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800394 earlyModuleContext: earlyModuleContext{
395 kind: productSpecificModule,
396 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700397 },
398 inData: true,
399 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900400 in: []string{"nativetest", "my_test"},
401 out: "target/product/test_device/data/nativetest/my_test",
402 partitionDir: "target/product/test_device/data",
Dan Willemsen00269f22017-07-06 16:59:48 -0700403 },
404
405 {
Justin Yund5f6c822019-06-25 16:47:17 +0900406 name: "system_ext native test binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100407 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700408 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800409 os: deviceTarget.Os,
Dario Frenifd05a742018-05-29 13:28:54 +0100410 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800411 earlyModuleContext: earlyModuleContext{
412 kind: systemExtSpecificModule,
413 },
Dario Frenifd05a742018-05-29 13:28:54 +0100414 },
415 inData: true,
416 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900417 in: []string{"nativetest", "my_test"},
418 out: "target/product/test_device/data/nativetest/my_test",
419 partitionDir: "target/product/test_device/data",
Dario Frenifd05a742018-05-29 13:28:54 +0100420 },
421
422 {
Dan Willemsen00269f22017-07-06 16:59:48 -0700423 name: "sanitized system binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100424 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700425 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800426 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700427 target: deviceTarget,
428 },
429 inSanitizerDir: true,
430 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900431 in: []string{"bin", "my_test"},
432 out: "target/product/test_device/data/asan/system/bin/my_test",
433 partitionDir: "target/product/test_device/data/asan/system",
Dan Willemsen00269f22017-07-06 16:59:48 -0700434 },
435 {
436 name: "sanitized vendor binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100437 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700438 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800439 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700440 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800441 earlyModuleContext: earlyModuleContext{
442 kind: socSpecificModule,
443 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700444 },
445 inSanitizerDir: true,
446 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900447 in: []string{"bin", "my_test"},
448 out: "target/product/test_device/data/asan/vendor/bin/my_test",
449 partitionDir: "target/product/test_device/data/asan/vendor",
Dan Willemsen00269f22017-07-06 16:59:48 -0700450 },
Jiyong Park2db76922017-11-08 16:03:48 +0900451 {
452 name: "sanitized odm binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100453 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700454 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800455 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900456 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800457 earlyModuleContext: earlyModuleContext{
458 kind: deviceSpecificModule,
459 },
Jiyong Park2db76922017-11-08 16:03:48 +0900460 },
461 inSanitizerDir: true,
462 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900463 in: []string{"bin", "my_test"},
464 out: "target/product/test_device/data/asan/odm/bin/my_test",
465 partitionDir: "target/product/test_device/data/asan/odm",
Jiyong Park2db76922017-11-08 16:03:48 +0900466 },
467 {
Jaekyun Seok5cfbfbb2018-01-10 19:00:15 +0900468 name: "sanitized product binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100469 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700470 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800471 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900472 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800473 earlyModuleContext: earlyModuleContext{
474 kind: productSpecificModule,
475 },
Jiyong Park2db76922017-11-08 16:03:48 +0900476 },
477 inSanitizerDir: true,
478 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900479 in: []string{"bin", "my_test"},
480 out: "target/product/test_device/data/asan/product/bin/my_test",
481 partitionDir: "target/product/test_device/data/asan/product",
Jiyong Park2db76922017-11-08 16:03:48 +0900482 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700483
484 {
Justin Yund5f6c822019-06-25 16:47:17 +0900485 name: "sanitized system_ext binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100486 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700487 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800488 os: deviceTarget.Os,
Dario Frenifd05a742018-05-29 13:28:54 +0100489 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800490 earlyModuleContext: earlyModuleContext{
491 kind: systemExtSpecificModule,
492 },
Dario Frenifd05a742018-05-29 13:28:54 +0100493 },
494 inSanitizerDir: true,
495 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900496 in: []string{"bin", "my_test"},
497 out: "target/product/test_device/data/asan/system_ext/bin/my_test",
498 partitionDir: "target/product/test_device/data/asan/system_ext",
Dario Frenifd05a742018-05-29 13:28:54 +0100499 },
500
501 {
Dan Willemsen00269f22017-07-06 16:59:48 -0700502 name: "sanitized system native test binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100503 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700504 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800505 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700506 target: deviceTarget,
507 },
508 inData: true,
509 inSanitizerDir: true,
510 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900511 in: []string{"nativetest", "my_test"},
512 out: "target/product/test_device/data/asan/data/nativetest/my_test",
513 partitionDir: "target/product/test_device/data/asan/data",
Dan Willemsen00269f22017-07-06 16:59:48 -0700514 },
515 {
516 name: "sanitized vendor native test binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100517 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700518 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800519 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700520 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800521 earlyModuleContext: earlyModuleContext{
522 kind: socSpecificModule,
523 },
Jiyong Park2db76922017-11-08 16:03:48 +0900524 },
525 inData: true,
526 inSanitizerDir: true,
527 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900528 in: []string{"nativetest", "my_test"},
529 out: "target/product/test_device/data/asan/data/nativetest/my_test",
530 partitionDir: "target/product/test_device/data/asan/data",
Jiyong Park2db76922017-11-08 16:03:48 +0900531 },
532 {
533 name: "sanitized odm native test binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100534 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700535 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800536 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900537 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800538 earlyModuleContext: earlyModuleContext{
539 kind: deviceSpecificModule,
540 },
Jiyong Park2db76922017-11-08 16:03:48 +0900541 },
542 inData: true,
543 inSanitizerDir: true,
544 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900545 in: []string{"nativetest", "my_test"},
546 out: "target/product/test_device/data/asan/data/nativetest/my_test",
547 partitionDir: "target/product/test_device/data/asan/data",
Jiyong Park2db76922017-11-08 16:03:48 +0900548 },
549 {
Jaekyun Seok5cfbfbb2018-01-10 19:00:15 +0900550 name: "sanitized product native test binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100551 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700552 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800553 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900554 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800555 earlyModuleContext: earlyModuleContext{
556 kind: productSpecificModule,
557 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700558 },
559 inData: true,
560 inSanitizerDir: true,
561 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900562 in: []string{"nativetest", "my_test"},
563 out: "target/product/test_device/data/asan/data/nativetest/my_test",
564 partitionDir: "target/product/test_device/data/asan/data",
Dan Willemsen00269f22017-07-06 16:59:48 -0700565 },
Dario Frenifd05a742018-05-29 13:28:54 +0100566 {
Justin Yund5f6c822019-06-25 16:47:17 +0900567 name: "sanitized system_ext native test binary",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100568 ctx: &testModuleInstallPathContext{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700569 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800570 os: deviceTarget.Os,
Dario Frenifd05a742018-05-29 13:28:54 +0100571 target: deviceTarget,
Colin Cross1184b642019-12-30 18:43:07 -0800572 earlyModuleContext: earlyModuleContext{
573 kind: systemExtSpecificModule,
574 },
Dario Frenifd05a742018-05-29 13:28:54 +0100575 },
576 inData: true,
577 inSanitizerDir: true,
578 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900579 in: []string{"nativetest", "my_test"},
580 out: "target/product/test_device/data/asan/data/nativetest/my_test",
581 partitionDir: "target/product/test_device/data/asan/data",
Colin Cross6e359402020-02-10 15:29:54 -0800582 }, {
583 name: "device testcases",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100584 ctx: &testModuleInstallPathContext{
Colin Cross6e359402020-02-10 15:29:54 -0800585 baseModuleContext: baseModuleContext{
586 os: deviceTarget.Os,
587 target: deviceTarget,
588 },
589 inTestcases: true,
590 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900591 in: []string{"my_test", "my_test_bin"},
592 out: "target/product/test_device/testcases/my_test/my_test_bin",
593 partitionDir: "target/product/test_device/testcases",
Colin Cross6e359402020-02-10 15:29:54 -0800594 }, {
595 name: "host testcases",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100596 ctx: &testModuleInstallPathContext{
Colin Cross6e359402020-02-10 15:29:54 -0800597 baseModuleContext: baseModuleContext{
598 os: hostTarget.Os,
599 target: hostTarget,
600 },
601 inTestcases: true,
602 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900603 in: []string{"my_test", "my_test_bin"},
604 out: "host/linux-x86/testcases/my_test/my_test_bin",
605 partitionDir: "host/linux-x86/testcases",
Colin Cross6e359402020-02-10 15:29:54 -0800606 }, {
607 name: "forced host testcases",
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100608 ctx: &testModuleInstallPathContext{
Colin Cross6e359402020-02-10 15:29:54 -0800609 baseModuleContext: baseModuleContext{
610 os: deviceTarget.Os,
611 target: deviceTarget,
612 },
613 inTestcases: true,
614 forceOS: &Linux,
Jiyong Park87788b52020-09-01 12:37:45 +0900615 forceArch: &X86,
Colin Cross6e359402020-02-10 15:29:54 -0800616 },
Jiyong Park957bcd92020-10-20 18:23:33 +0900617 in: []string{"my_test", "my_test_bin"},
618 out: "host/linux-x86/testcases/my_test/my_test_bin",
619 partitionDir: "host/linux-x86/testcases",
Dario Frenifd05a742018-05-29 13:28:54 +0100620 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700621 }
622
623 for _, tc := range testCases {
624 t.Run(tc.name, func(t *testing.T) {
Colin Cross0ea8ba82019-06-06 14:33:29 -0700625 tc.ctx.baseModuleContext.config = testConfig
Dan Willemsen00269f22017-07-06 16:59:48 -0700626 output := PathForModuleInstall(tc.ctx, tc.in...)
627 if output.basePath.path != tc.out {
628 t.Errorf("unexpected path:\n got: %q\nwant: %q\n",
629 output.basePath.path,
630 tc.out)
631 }
Jiyong Park957bcd92020-10-20 18:23:33 +0900632 if output.partitionDir != tc.partitionDir {
633 t.Errorf("unexpected partitionDir:\n got: %q\nwant: %q\n",
634 output.partitionDir, tc.partitionDir)
635 }
Dan Willemsen00269f22017-07-06 16:59:48 -0700636 })
637 }
638}
Colin Cross5e6cfbe2017-11-03 15:20:35 -0700639
Jiyong Park957bcd92020-10-20 18:23:33 +0900640func TestBaseDirForInstallPath(t *testing.T) {
641 testConfig := pathTestConfig("")
642 deviceTarget := Target{Os: Android, Arch: Arch{ArchType: Arm64}}
643
Ulya Trafimovichccc8c852020-10-14 11:29:07 +0100644 ctx := &testModuleInstallPathContext{
Jiyong Park957bcd92020-10-20 18:23:33 +0900645 baseModuleContext: baseModuleContext{
646 os: deviceTarget.Os,
647 target: deviceTarget,
648 },
649 }
650 ctx.baseModuleContext.config = testConfig
651
652 actual := PathForModuleInstall(ctx, "foo", "bar")
653 expectedBaseDir := "target/product/test_device/system"
654 if actual.partitionDir != expectedBaseDir {
655 t.Errorf("unexpected partitionDir:\n got: %q\nwant: %q\n", actual.partitionDir, expectedBaseDir)
656 }
657 expectedRelPath := "foo/bar"
658 if actual.Rel() != expectedRelPath {
659 t.Errorf("unexpected Rel():\n got: %q\nwant: %q\n", actual.Rel(), expectedRelPath)
660 }
661
662 actualAfterJoin := actual.Join(ctx, "baz")
663 // partitionDir is preserved even after joining
664 if actualAfterJoin.partitionDir != expectedBaseDir {
665 t.Errorf("unexpected partitionDir after joining:\n got: %q\nwant: %q\n", actualAfterJoin.partitionDir, expectedBaseDir)
666 }
667 // Rel() is updated though
668 expectedRelAfterJoin := "baz"
669 if actualAfterJoin.Rel() != expectedRelAfterJoin {
670 t.Errorf("unexpected Rel() after joining:\n got: %q\nwant: %q\n", actualAfterJoin.Rel(), expectedRelAfterJoin)
671 }
672}
673
Colin Cross5e6cfbe2017-11-03 15:20:35 -0700674func TestDirectorySortedPaths(t *testing.T) {
Colin Cross98be1bb2019-12-13 20:41:13 -0800675 config := TestConfig("out", nil, "", map[string][]byte{
676 "Android.bp": nil,
677 "a.txt": nil,
678 "a/txt": nil,
679 "a/b/c": nil,
680 "a/b/d": nil,
681 "b": nil,
682 "b/b.txt": nil,
683 "a/a.txt": nil,
Colin Cross07e51612019-03-05 12:46:40 -0800684 })
685
Colin Cross98be1bb2019-12-13 20:41:13 -0800686 ctx := PathContextForTesting(config)
687
Colin Cross5e6cfbe2017-11-03 15:20:35 -0700688 makePaths := func() Paths {
689 return Paths{
Colin Cross07e51612019-03-05 12:46:40 -0800690 PathForSource(ctx, "a.txt"),
691 PathForSource(ctx, "a/txt"),
692 PathForSource(ctx, "a/b/c"),
693 PathForSource(ctx, "a/b/d"),
694 PathForSource(ctx, "b"),
695 PathForSource(ctx, "b/b.txt"),
696 PathForSource(ctx, "a/a.txt"),
Colin Cross5e6cfbe2017-11-03 15:20:35 -0700697 }
698 }
699
700 expected := []string{
701 "a.txt",
702 "a/a.txt",
703 "a/b/c",
704 "a/b/d",
705 "a/txt",
706 "b",
707 "b/b.txt",
708 }
709
710 paths := makePaths()
Colin Crossa140bb02018-04-17 10:52:26 -0700711 reversePaths := ReversePaths(paths)
Colin Cross5e6cfbe2017-11-03 15:20:35 -0700712
713 sortedPaths := PathsToDirectorySortedPaths(paths)
714 reverseSortedPaths := PathsToDirectorySortedPaths(reversePaths)
715
716 if !reflect.DeepEqual(Paths(sortedPaths).Strings(), expected) {
717 t.Fatalf("sorted paths:\n %#v\n != \n %#v", paths.Strings(), expected)
718 }
719
720 if !reflect.DeepEqual(Paths(reverseSortedPaths).Strings(), expected) {
721 t.Fatalf("sorted reversed paths:\n %#v\n !=\n %#v", reversePaths.Strings(), expected)
722 }
723
724 expectedA := []string{
725 "a/a.txt",
726 "a/b/c",
727 "a/b/d",
728 "a/txt",
729 }
730
731 inA := sortedPaths.PathsInDirectory("a")
732 if !reflect.DeepEqual(inA.Strings(), expectedA) {
733 t.Errorf("FilesInDirectory(a):\n %#v\n != \n %#v", inA.Strings(), expectedA)
734 }
735
736 expectedA_B := []string{
737 "a/b/c",
738 "a/b/d",
739 }
740
741 inA_B := sortedPaths.PathsInDirectory("a/b")
742 if !reflect.DeepEqual(inA_B.Strings(), expectedA_B) {
743 t.Errorf("FilesInDirectory(a/b):\n %#v\n != \n %#v", inA_B.Strings(), expectedA_B)
744 }
745
746 expectedB := []string{
747 "b/b.txt",
748 }
749
750 inB := sortedPaths.PathsInDirectory("b")
751 if !reflect.DeepEqual(inB.Strings(), expectedB) {
752 t.Errorf("FilesInDirectory(b):\n %#v\n != \n %#v", inA.Strings(), expectedA)
753 }
754}
Colin Cross43f08db2018-11-12 10:13:39 -0800755
756func TestMaybeRel(t *testing.T) {
757 testCases := []struct {
758 name string
759 base string
760 target string
761 out string
762 isRel bool
763 }{
764 {
765 name: "normal",
766 base: "a/b/c",
767 target: "a/b/c/d",
768 out: "d",
769 isRel: true,
770 },
771 {
772 name: "parent",
773 base: "a/b/c/d",
774 target: "a/b/c",
775 isRel: false,
776 },
777 {
778 name: "not relative",
779 base: "a/b",
780 target: "c/d",
781 isRel: false,
782 },
783 {
784 name: "abs1",
785 base: "/a",
786 target: "a",
787 isRel: false,
788 },
789 {
790 name: "abs2",
791 base: "a",
792 target: "/a",
793 isRel: false,
794 },
795 }
796
797 for _, testCase := range testCases {
798 t.Run(testCase.name, func(t *testing.T) {
799 ctx := &configErrorWrapper{}
800 out, isRel := MaybeRel(ctx, testCase.base, testCase.target)
801 if len(ctx.errors) > 0 {
802 t.Errorf("MaybeRel(..., %s, %s) reported unexpected errors %v",
803 testCase.base, testCase.target, ctx.errors)
804 }
805 if isRel != testCase.isRel || out != testCase.out {
806 t.Errorf("MaybeRel(..., %s, %s) want %v, %v got %v, %v",
807 testCase.base, testCase.target, testCase.out, testCase.isRel, out, isRel)
808 }
809 })
810 }
811}
Colin Cross7b3dcc32019-01-24 13:14:39 -0800812
813func TestPathForSource(t *testing.T) {
814 testCases := []struct {
815 name string
816 buildDir string
817 src string
818 err string
819 }{
820 {
821 name: "normal",
822 buildDir: "out",
823 src: "a/b/c",
824 },
825 {
826 name: "abs",
827 buildDir: "out",
828 src: "/a/b/c",
829 err: "is outside directory",
830 },
831 {
832 name: "in out dir",
833 buildDir: "out",
834 src: "out/a/b/c",
835 err: "is in output",
836 },
837 }
838
839 funcs := []struct {
840 name string
841 f func(ctx PathContext, pathComponents ...string) (SourcePath, error)
842 }{
843 {"pathForSource", pathForSource},
844 {"safePathForSource", safePathForSource},
845 }
846
847 for _, f := range funcs {
848 t.Run(f.name, func(t *testing.T) {
849 for _, test := range testCases {
850 t.Run(test.name, func(t *testing.T) {
Colin Cross98be1bb2019-12-13 20:41:13 -0800851 testConfig := pathTestConfig(test.buildDir)
Colin Cross7b3dcc32019-01-24 13:14:39 -0800852 ctx := &configErrorWrapper{config: testConfig}
853 _, err := f.f(ctx, test.src)
854 if len(ctx.errors) > 0 {
855 t.Fatalf("unexpected errors %v", ctx.errors)
856 }
857 if err != nil {
858 if test.err == "" {
859 t.Fatalf("unexpected error %q", err.Error())
860 } else if !strings.Contains(err.Error(), test.err) {
861 t.Fatalf("incorrect error, want substring %q got %q", test.err, err.Error())
862 }
863 } else {
864 if test.err != "" {
865 t.Fatalf("missing error %q", test.err)
866 }
867 }
868 })
869 }
870 })
871 }
872}
Colin Cross8854a5a2019-02-11 14:14:16 -0800873
Colin Cross8a497952019-03-05 22:25:09 -0800874type pathForModuleSrcTestModule struct {
Colin Cross937664a2019-03-06 10:17:32 -0800875 ModuleBase
876 props struct {
877 Srcs []string `android:"path"`
878 Exclude_srcs []string `android:"path"`
Colin Cross8a497952019-03-05 22:25:09 -0800879
880 Src *string `android:"path"`
Colin Crossba71a3f2019-03-18 12:12:48 -0700881
882 Module_handles_missing_deps bool
Colin Cross937664a2019-03-06 10:17:32 -0800883 }
884
Colin Cross8a497952019-03-05 22:25:09 -0800885 src string
886 rel string
887
888 srcs []string
Colin Cross937664a2019-03-06 10:17:32 -0800889 rels []string
Colin Cross8a497952019-03-05 22:25:09 -0800890
891 missingDeps []string
Colin Cross937664a2019-03-06 10:17:32 -0800892}
893
Colin Cross8a497952019-03-05 22:25:09 -0800894func pathForModuleSrcTestModuleFactory() Module {
895 module := &pathForModuleSrcTestModule{}
Colin Cross937664a2019-03-06 10:17:32 -0800896 module.AddProperties(&module.props)
897 InitAndroidModule(module)
898 return module
899}
900
Colin Cross8a497952019-03-05 22:25:09 -0800901func (p *pathForModuleSrcTestModule) GenerateAndroidBuildActions(ctx ModuleContext) {
Colin Crossba71a3f2019-03-18 12:12:48 -0700902 var srcs Paths
903 if p.props.Module_handles_missing_deps {
904 srcs, p.missingDeps = PathsAndMissingDepsForModuleSrcExcludes(ctx, p.props.Srcs, p.props.Exclude_srcs)
905 } else {
906 srcs = PathsForModuleSrcExcludes(ctx, p.props.Srcs, p.props.Exclude_srcs)
907 }
Colin Cross8a497952019-03-05 22:25:09 -0800908 p.srcs = srcs.Strings()
Colin Cross937664a2019-03-06 10:17:32 -0800909
Colin Cross8a497952019-03-05 22:25:09 -0800910 for _, src := range srcs {
Colin Cross937664a2019-03-06 10:17:32 -0800911 p.rels = append(p.rels, src.Rel())
912 }
Colin Cross8a497952019-03-05 22:25:09 -0800913
914 if p.props.Src != nil {
915 src := PathForModuleSrc(ctx, *p.props.Src)
916 if src != nil {
917 p.src = src.String()
918 p.rel = src.Rel()
919 }
920 }
921
Colin Crossba71a3f2019-03-18 12:12:48 -0700922 if !p.props.Module_handles_missing_deps {
923 p.missingDeps = ctx.GetMissingDependencies()
924 }
Colin Cross6c4f21f2019-06-06 15:41:36 -0700925
926 ctx.Build(pctx, BuildParams{
927 Rule: Touch,
928 Output: PathForModuleOut(ctx, "output"),
929 })
Colin Cross8a497952019-03-05 22:25:09 -0800930}
931
Colin Cross41955e82019-05-29 14:40:35 -0700932type pathForModuleSrcOutputFileProviderModule struct {
933 ModuleBase
934 props struct {
935 Outs []string
936 Tagged []string
937 }
938
939 outs Paths
940 tagged Paths
941}
942
943func pathForModuleSrcOutputFileProviderModuleFactory() Module {
944 module := &pathForModuleSrcOutputFileProviderModule{}
945 module.AddProperties(&module.props)
946 InitAndroidModule(module)
947 return module
948}
949
950func (p *pathForModuleSrcOutputFileProviderModule) GenerateAndroidBuildActions(ctx ModuleContext) {
951 for _, out := range p.props.Outs {
952 p.outs = append(p.outs, PathForModuleOut(ctx, out))
953 }
954
955 for _, tagged := range p.props.Tagged {
956 p.tagged = append(p.tagged, PathForModuleOut(ctx, tagged))
957 }
958}
959
960func (p *pathForModuleSrcOutputFileProviderModule) OutputFiles(tag string) (Paths, error) {
961 switch tag {
962 case "":
963 return p.outs, nil
964 case ".tagged":
965 return p.tagged, nil
966 default:
967 return nil, fmt.Errorf("unsupported tag %q", tag)
968 }
969}
970
Colin Cross8a497952019-03-05 22:25:09 -0800971type pathForModuleSrcTestCase struct {
972 name string
973 bp string
974 srcs []string
975 rels []string
976 src string
977 rel string
978}
979
980func testPathForModuleSrc(t *testing.T, buildDir string, tests []pathForModuleSrcTestCase) {
981 for _, test := range tests {
982 t.Run(test.name, func(t *testing.T) {
Colin Cross8a497952019-03-05 22:25:09 -0800983 ctx := NewTestContext()
984
Colin Cross4b49b762019-11-22 15:25:03 -0800985 ctx.RegisterModuleType("test", pathForModuleSrcTestModuleFactory)
986 ctx.RegisterModuleType("output_file_provider", pathForModuleSrcOutputFileProviderModuleFactory)
987 ctx.RegisterModuleType("filegroup", FileGroupFactory)
Colin Cross8a497952019-03-05 22:25:09 -0800988
989 fgBp := `
990 filegroup {
991 name: "a",
992 srcs: ["src/a"],
993 }
994 `
995
Colin Cross41955e82019-05-29 14:40:35 -0700996 ofpBp := `
997 output_file_provider {
998 name: "b",
999 outs: ["gen/b"],
1000 tagged: ["gen/c"],
1001 }
1002 `
1003
Colin Cross8a497952019-03-05 22:25:09 -08001004 mockFS := map[string][]byte{
1005 "fg/Android.bp": []byte(fgBp),
1006 "foo/Android.bp": []byte(test.bp),
Colin Cross41955e82019-05-29 14:40:35 -07001007 "ofp/Android.bp": []byte(ofpBp),
Colin Cross8a497952019-03-05 22:25:09 -08001008 "fg/src/a": nil,
1009 "foo/src/b": nil,
1010 "foo/src/c": nil,
1011 "foo/src/d": nil,
1012 "foo/src/e/e": nil,
1013 "foo/src_special/$": nil,
1014 }
1015
Colin Cross98be1bb2019-12-13 20:41:13 -08001016 config := TestConfig(buildDir, nil, "", mockFS)
Colin Cross8a497952019-03-05 22:25:09 -08001017
Colin Cross98be1bb2019-12-13 20:41:13 -08001018 ctx.Register(config)
Colin Cross41955e82019-05-29 14:40:35 -07001019 _, errs := ctx.ParseFileList(".", []string{"fg/Android.bp", "foo/Android.bp", "ofp/Android.bp"})
Colin Cross8a497952019-03-05 22:25:09 -08001020 FailIfErrored(t, errs)
1021 _, errs = ctx.PrepareBuildActions(config)
1022 FailIfErrored(t, errs)
1023
1024 m := ctx.ModuleForTests("foo", "").Module().(*pathForModuleSrcTestModule)
1025
1026 if g, w := m.srcs, test.srcs; !reflect.DeepEqual(g, w) {
1027 t.Errorf("want srcs %q, got %q", w, g)
1028 }
1029
1030 if g, w := m.rels, test.rels; !reflect.DeepEqual(g, w) {
1031 t.Errorf("want rels %q, got %q", w, g)
1032 }
1033
1034 if g, w := m.src, test.src; g != w {
1035 t.Errorf("want src %q, got %q", w, g)
1036 }
1037
1038 if g, w := m.rel, test.rel; g != w {
1039 t.Errorf("want rel %q, got %q", w, g)
1040 }
1041 })
1042 }
Colin Cross937664a2019-03-06 10:17:32 -08001043}
1044
Colin Cross8a497952019-03-05 22:25:09 -08001045func TestPathsForModuleSrc(t *testing.T) {
1046 tests := []pathForModuleSrcTestCase{
Colin Cross937664a2019-03-06 10:17:32 -08001047 {
1048 name: "path",
1049 bp: `
1050 test {
1051 name: "foo",
1052 srcs: ["src/b"],
1053 }`,
1054 srcs: []string{"foo/src/b"},
1055 rels: []string{"src/b"},
1056 },
1057 {
1058 name: "glob",
1059 bp: `
1060 test {
1061 name: "foo",
1062 srcs: [
1063 "src/*",
1064 "src/e/*",
1065 ],
1066 }`,
1067 srcs: []string{"foo/src/b", "foo/src/c", "foo/src/d", "foo/src/e/e"},
1068 rels: []string{"src/b", "src/c", "src/d", "src/e/e"},
1069 },
1070 {
1071 name: "recursive glob",
1072 bp: `
1073 test {
1074 name: "foo",
1075 srcs: ["src/**/*"],
1076 }`,
1077 srcs: []string{"foo/src/b", "foo/src/c", "foo/src/d", "foo/src/e/e"},
1078 rels: []string{"src/b", "src/c", "src/d", "src/e/e"},
1079 },
1080 {
1081 name: "filegroup",
1082 bp: `
1083 test {
1084 name: "foo",
1085 srcs: [":a"],
1086 }`,
1087 srcs: []string{"fg/src/a"},
1088 rels: []string{"src/a"},
1089 },
1090 {
Colin Cross41955e82019-05-29 14:40:35 -07001091 name: "output file provider",
1092 bp: `
1093 test {
1094 name: "foo",
1095 srcs: [":b"],
1096 }`,
1097 srcs: []string{buildDir + "/.intermediates/ofp/b/gen/b"},
1098 rels: []string{"gen/b"},
1099 },
1100 {
1101 name: "output file provider tagged",
1102 bp: `
1103 test {
1104 name: "foo",
1105 srcs: [":b{.tagged}"],
1106 }`,
1107 srcs: []string{buildDir + "/.intermediates/ofp/b/gen/c"},
1108 rels: []string{"gen/c"},
1109 },
1110 {
Jooyung Han7607dd32020-07-05 10:23:14 +09001111 name: "output file provider with exclude",
1112 bp: `
1113 test {
1114 name: "foo",
1115 srcs: [":b", ":c"],
1116 exclude_srcs: [":c"]
1117 }
1118 output_file_provider {
1119 name: "c",
1120 outs: ["gen/c"],
1121 }`,
1122 srcs: []string{buildDir + "/.intermediates/ofp/b/gen/b"},
1123 rels: []string{"gen/b"},
1124 },
1125 {
Colin Cross937664a2019-03-06 10:17:32 -08001126 name: "special characters glob",
1127 bp: `
1128 test {
1129 name: "foo",
1130 srcs: ["src_special/*"],
1131 }`,
1132 srcs: []string{"foo/src_special/$"},
1133 rels: []string{"src_special/$"},
1134 },
1135 }
1136
Colin Cross41955e82019-05-29 14:40:35 -07001137 testPathForModuleSrc(t, buildDir, tests)
1138}
1139
1140func TestPathForModuleSrc(t *testing.T) {
Colin Cross8a497952019-03-05 22:25:09 -08001141 tests := []pathForModuleSrcTestCase{
1142 {
1143 name: "path",
1144 bp: `
1145 test {
1146 name: "foo",
1147 src: "src/b",
1148 }`,
1149 src: "foo/src/b",
1150 rel: "src/b",
1151 },
1152 {
1153 name: "glob",
1154 bp: `
1155 test {
1156 name: "foo",
1157 src: "src/e/*",
1158 }`,
1159 src: "foo/src/e/e",
1160 rel: "src/e/e",
1161 },
1162 {
1163 name: "filegroup",
1164 bp: `
1165 test {
1166 name: "foo",
1167 src: ":a",
1168 }`,
1169 src: "fg/src/a",
1170 rel: "src/a",
1171 },
1172 {
Colin Cross41955e82019-05-29 14:40:35 -07001173 name: "output file provider",
1174 bp: `
1175 test {
1176 name: "foo",
1177 src: ":b",
1178 }`,
1179 src: buildDir + "/.intermediates/ofp/b/gen/b",
1180 rel: "gen/b",
1181 },
1182 {
1183 name: "output file provider tagged",
1184 bp: `
1185 test {
1186 name: "foo",
1187 src: ":b{.tagged}",
1188 }`,
1189 src: buildDir + "/.intermediates/ofp/b/gen/c",
1190 rel: "gen/c",
1191 },
1192 {
Colin Cross8a497952019-03-05 22:25:09 -08001193 name: "special characters glob",
1194 bp: `
1195 test {
1196 name: "foo",
1197 src: "src_special/*",
1198 }`,
1199 src: "foo/src_special/$",
1200 rel: "src_special/$",
1201 },
1202 }
1203
Colin Cross8a497952019-03-05 22:25:09 -08001204 testPathForModuleSrc(t, buildDir, tests)
1205}
Colin Cross937664a2019-03-06 10:17:32 -08001206
Colin Cross8a497952019-03-05 22:25:09 -08001207func TestPathsForModuleSrc_AllowMissingDependencies(t *testing.T) {
Colin Cross8a497952019-03-05 22:25:09 -08001208 bp := `
1209 test {
1210 name: "foo",
1211 srcs: [":a"],
1212 exclude_srcs: [":b"],
1213 src: ":c",
1214 }
Colin Crossba71a3f2019-03-18 12:12:48 -07001215
1216 test {
1217 name: "bar",
1218 srcs: [":d"],
1219 exclude_srcs: [":e"],
1220 module_handles_missing_deps: true,
1221 }
Colin Cross8a497952019-03-05 22:25:09 -08001222 `
1223
Colin Cross98be1bb2019-12-13 20:41:13 -08001224 config := TestConfig(buildDir, nil, bp, nil)
1225 config.TestProductVariables.Allow_missing_dependencies = proptools.BoolPtr(true)
Colin Cross8a497952019-03-05 22:25:09 -08001226
Colin Cross98be1bb2019-12-13 20:41:13 -08001227 ctx := NewTestContext()
1228 ctx.SetAllowMissingDependencies(true)
Colin Cross8a497952019-03-05 22:25:09 -08001229
Colin Cross98be1bb2019-12-13 20:41:13 -08001230 ctx.RegisterModuleType("test", pathForModuleSrcTestModuleFactory)
1231
1232 ctx.Register(config)
1233
Colin Cross8a497952019-03-05 22:25:09 -08001234 _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
1235 FailIfErrored(t, errs)
1236 _, errs = ctx.PrepareBuildActions(config)
1237 FailIfErrored(t, errs)
1238
1239 foo := ctx.ModuleForTests("foo", "").Module().(*pathForModuleSrcTestModule)
1240
1241 if g, w := foo.missingDeps, []string{"a", "b", "c"}; !reflect.DeepEqual(g, w) {
Colin Crossba71a3f2019-03-18 12:12:48 -07001242 t.Errorf("want foo missing deps %q, got %q", w, g)
Colin Cross8a497952019-03-05 22:25:09 -08001243 }
1244
1245 if g, w := foo.srcs, []string{}; !reflect.DeepEqual(g, w) {
Colin Crossba71a3f2019-03-18 12:12:48 -07001246 t.Errorf("want foo srcs %q, got %q", w, g)
Colin Cross8a497952019-03-05 22:25:09 -08001247 }
1248
1249 if g, w := foo.src, ""; g != w {
Colin Crossba71a3f2019-03-18 12:12:48 -07001250 t.Errorf("want foo src %q, got %q", w, g)
Colin Cross8a497952019-03-05 22:25:09 -08001251 }
1252
Colin Crossba71a3f2019-03-18 12:12:48 -07001253 bar := ctx.ModuleForTests("bar", "").Module().(*pathForModuleSrcTestModule)
1254
1255 if g, w := bar.missingDeps, []string{"d", "e"}; !reflect.DeepEqual(g, w) {
1256 t.Errorf("want bar missing deps %q, got %q", w, g)
1257 }
1258
1259 if g, w := bar.srcs, []string{}; !reflect.DeepEqual(g, w) {
1260 t.Errorf("want bar srcs %q, got %q", w, g)
1261 }
Colin Cross937664a2019-03-06 10:17:32 -08001262}
1263
Colin Cross8854a5a2019-02-11 14:14:16 -08001264func ExampleOutputPath_ReplaceExtension() {
1265 ctx := &configErrorWrapper{
Colin Cross98be1bb2019-12-13 20:41:13 -08001266 config: TestConfig("out", nil, "", nil),
Colin Cross8854a5a2019-02-11 14:14:16 -08001267 }
Colin Cross2cdd5df2019-02-25 10:25:24 -08001268 p := PathForOutput(ctx, "system/framework").Join(ctx, "boot.art")
Colin Cross8854a5a2019-02-11 14:14:16 -08001269 p2 := p.ReplaceExtension(ctx, "oat")
1270 fmt.Println(p, p2)
Colin Cross2cdd5df2019-02-25 10:25:24 -08001271 fmt.Println(p.Rel(), p2.Rel())
Colin Cross8854a5a2019-02-11 14:14:16 -08001272
1273 // Output:
1274 // out/system/framework/boot.art out/system/framework/boot.oat
Colin Cross2cdd5df2019-02-25 10:25:24 -08001275 // boot.art boot.oat
Colin Cross8854a5a2019-02-11 14:14:16 -08001276}
Colin Cross40e33732019-02-15 11:08:35 -08001277
Colin Cross41b46762020-10-09 19:26:32 -07001278func ExampleOutputPath_InSameDir() {
Colin Cross40e33732019-02-15 11:08:35 -08001279 ctx := &configErrorWrapper{
Colin Cross98be1bb2019-12-13 20:41:13 -08001280 config: TestConfig("out", nil, "", nil),
Colin Cross40e33732019-02-15 11:08:35 -08001281 }
Colin Cross2cdd5df2019-02-25 10:25:24 -08001282 p := PathForOutput(ctx, "system/framework").Join(ctx, "boot.art")
Colin Cross40e33732019-02-15 11:08:35 -08001283 p2 := p.InSameDir(ctx, "oat", "arm", "boot.vdex")
1284 fmt.Println(p, p2)
Colin Cross2cdd5df2019-02-25 10:25:24 -08001285 fmt.Println(p.Rel(), p2.Rel())
Colin Cross40e33732019-02-15 11:08:35 -08001286
1287 // Output:
1288 // out/system/framework/boot.art out/system/framework/oat/arm/boot.vdex
Colin Cross2cdd5df2019-02-25 10:25:24 -08001289 // boot.art oat/arm/boot.vdex
Colin Cross40e33732019-02-15 11:08:35 -08001290}
Colin Cross27027c72020-02-28 15:34:17 -08001291
1292func BenchmarkFirstUniquePaths(b *testing.B) {
1293 implementations := []struct {
1294 name string
1295 f func(Paths) Paths
1296 }{
1297 {
1298 name: "list",
1299 f: firstUniquePathsList,
1300 },
1301 {
1302 name: "map",
1303 f: firstUniquePathsMap,
1304 },
1305 }
1306 const maxSize = 1024
1307 uniquePaths := make(Paths, maxSize)
1308 for i := range uniquePaths {
1309 uniquePaths[i] = PathForTesting(strconv.Itoa(i))
1310 }
1311 samePath := make(Paths, maxSize)
1312 for i := range samePath {
1313 samePath[i] = uniquePaths[0]
1314 }
1315
1316 f := func(b *testing.B, imp func(Paths) Paths, paths Paths) {
1317 for i := 0; i < b.N; i++ {
1318 b.ReportAllocs()
1319 paths = append(Paths(nil), paths...)
1320 imp(paths)
1321 }
1322 }
1323
1324 for n := 1; n <= maxSize; n <<= 1 {
1325 b.Run(strconv.Itoa(n), func(b *testing.B) {
1326 for _, implementation := range implementations {
1327 b.Run(implementation.name, func(b *testing.B) {
1328 b.Run("same", func(b *testing.B) {
1329 f(b, implementation.f, samePath[:n])
1330 })
1331 b.Run("unique", func(b *testing.B) {
1332 f(b, implementation.f, uniquePaths[:n])
1333 })
1334 })
1335 }
1336 })
1337 }
1338}