blob: a8560a1cd2add4caf56b803e264a4fef7391257c [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"
21 "strings"
22 "testing"
Dan Willemsen00269f22017-07-06 16:59:48 -070023
24 "github.com/google/blueprint/pathtools"
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
200type moduleInstallPathContextImpl struct {
Colin Cross0ea8ba82019-06-06 14:33:29 -0700201 baseModuleContext
Dan Willemsen00269f22017-07-06 16:59:48 -0700202
203 inData bool
Jaewoong Jung0949f312019-09-11 10:25:18 -0700204 inTestcases bool
Dan Willemsen00269f22017-07-06 16:59:48 -0700205 inSanitizerDir bool
Jiyong Parkf9332f12018-02-01 00:54:12 +0900206 inRecovery bool
Colin Cross90ba5f42019-10-02 11:10:58 -0700207 inRoot bool
Dan Willemsen00269f22017-07-06 16:59:48 -0700208}
209
210func (moduleInstallPathContextImpl) Fs() pathtools.FileSystem {
211 return pathtools.MockFs(nil)
212}
213
Colin Crossaabf6792017-11-29 00:27:14 -0800214func (m moduleInstallPathContextImpl) Config() Config {
Colin Cross0ea8ba82019-06-06 14:33:29 -0700215 return m.baseModuleContext.config
Dan Willemsen00269f22017-07-06 16:59:48 -0700216}
217
218func (moduleInstallPathContextImpl) AddNinjaFileDeps(deps ...string) {}
219
220func (m moduleInstallPathContextImpl) InstallInData() bool {
221 return m.inData
222}
223
Jaewoong Jung0949f312019-09-11 10:25:18 -0700224func (m moduleInstallPathContextImpl) InstallInTestcases() bool {
225 return m.inTestcases
226}
227
Dan Willemsen00269f22017-07-06 16:59:48 -0700228func (m moduleInstallPathContextImpl) InstallInSanitizerDir() bool {
229 return m.inSanitizerDir
230}
231
Jiyong Parkf9332f12018-02-01 00:54:12 +0900232func (m moduleInstallPathContextImpl) InstallInRecovery() bool {
233 return m.inRecovery
234}
235
Colin Cross90ba5f42019-10-02 11:10:58 -0700236func (m moduleInstallPathContextImpl) InstallInRoot() bool {
237 return m.inRoot
238}
239
Colin Cross607d8582019-07-29 16:44:46 -0700240func (m moduleInstallPathContextImpl) InstallBypassMake() bool {
241 return false
242}
243
Dan Willemsen00269f22017-07-06 16:59:48 -0700244func TestPathForModuleInstall(t *testing.T) {
Colin Cross6ccbc912017-10-10 23:07:38 -0700245 testConfig := TestConfig("", nil)
Dan Willemsen00269f22017-07-06 16:59:48 -0700246
247 hostTarget := Target{Os: Linux}
248 deviceTarget := Target{Os: Android}
249
250 testCases := []struct {
251 name string
252 ctx *moduleInstallPathContextImpl
253 in []string
254 out string
255 }{
256 {
257 name: "host binary",
258 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700259 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800260 os: hostTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700261 target: hostTarget,
262 },
263 },
264 in: []string{"bin", "my_test"},
265 out: "host/linux-x86/bin/my_test",
266 },
267
268 {
269 name: "system binary",
270 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700271 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800272 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700273 target: deviceTarget,
274 },
275 },
276 in: []string{"bin", "my_test"},
277 out: "target/product/test_device/system/bin/my_test",
278 },
279 {
280 name: "vendor binary",
281 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700282 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800283 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700284 target: deviceTarget,
Jiyong Park2db76922017-11-08 16:03:48 +0900285 kind: socSpecificModule,
Dan Willemsen00269f22017-07-06 16:59:48 -0700286 },
287 },
288 in: []string{"bin", "my_test"},
289 out: "target/product/test_device/vendor/bin/my_test",
290 },
Jiyong Park2db76922017-11-08 16:03:48 +0900291 {
292 name: "odm binary",
293 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700294 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800295 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900296 target: deviceTarget,
297 kind: deviceSpecificModule,
298 },
299 },
300 in: []string{"bin", "my_test"},
301 out: "target/product/test_device/odm/bin/my_test",
302 },
303 {
Jaekyun Seok5cfbfbb2018-01-10 19:00:15 +0900304 name: "product binary",
Jiyong Park2db76922017-11-08 16:03:48 +0900305 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700306 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800307 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900308 target: deviceTarget,
309 kind: productSpecificModule,
310 },
311 },
312 in: []string{"bin", "my_test"},
Jaekyun Seok5cfbfbb2018-01-10 19:00:15 +0900313 out: "target/product/test_device/product/bin/my_test",
Jiyong Park2db76922017-11-08 16:03:48 +0900314 },
Dario Frenifd05a742018-05-29 13:28:54 +0100315 {
Justin Yund5f6c822019-06-25 16:47:17 +0900316 name: "system_ext binary",
Dario Frenifd05a742018-05-29 13:28:54 +0100317 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700318 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800319 os: deviceTarget.Os,
Dario Frenifd05a742018-05-29 13:28:54 +0100320 target: deviceTarget,
Justin Yund5f6c822019-06-25 16:47:17 +0900321 kind: systemExtSpecificModule,
Dario Frenifd05a742018-05-29 13:28:54 +0100322 },
323 },
324 in: []string{"bin", "my_test"},
Justin Yund5f6c822019-06-25 16:47:17 +0900325 out: "target/product/test_device/system_ext/bin/my_test",
Dario Frenifd05a742018-05-29 13:28:54 +0100326 },
Colin Cross90ba5f42019-10-02 11:10:58 -0700327 {
328 name: "root binary",
329 ctx: &moduleInstallPathContextImpl{
330 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800331 os: deviceTarget.Os,
Colin Cross90ba5f42019-10-02 11:10:58 -0700332 target: deviceTarget,
333 },
334 inRoot: true,
335 },
336 in: []string{"my_test"},
337 out: "target/product/test_device/root/my_test",
338 },
339 {
340 name: "recovery binary",
341 ctx: &moduleInstallPathContextImpl{
342 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800343 os: deviceTarget.Os,
Colin Cross90ba5f42019-10-02 11:10:58 -0700344 target: deviceTarget,
345 },
346 inRecovery: true,
347 },
348 in: []string{"bin/my_test"},
349 out: "target/product/test_device/recovery/root/system/bin/my_test",
350 },
351 {
352 name: "recovery root binary",
353 ctx: &moduleInstallPathContextImpl{
354 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800355 os: deviceTarget.Os,
Colin Cross90ba5f42019-10-02 11:10:58 -0700356 target: deviceTarget,
357 },
358 inRecovery: true,
359 inRoot: true,
360 },
361 in: []string{"my_test"},
362 out: "target/product/test_device/recovery/root/my_test",
363 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700364
365 {
366 name: "system native test binary",
367 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700368 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800369 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700370 target: deviceTarget,
371 },
372 inData: true,
373 },
374 in: []string{"nativetest", "my_test"},
375 out: "target/product/test_device/data/nativetest/my_test",
376 },
377 {
378 name: "vendor native test binary",
379 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700380 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800381 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700382 target: deviceTarget,
Jiyong Park2db76922017-11-08 16:03:48 +0900383 kind: socSpecificModule,
384 },
385 inData: true,
386 },
387 in: []string{"nativetest", "my_test"},
388 out: "target/product/test_device/data/nativetest/my_test",
389 },
390 {
391 name: "odm native test binary",
392 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700393 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800394 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900395 target: deviceTarget,
396 kind: deviceSpecificModule,
397 },
398 inData: true,
399 },
400 in: []string{"nativetest", "my_test"},
401 out: "target/product/test_device/data/nativetest/my_test",
402 },
403 {
Jaekyun Seok5cfbfbb2018-01-10 19:00:15 +0900404 name: "product native test binary",
Jiyong Park2db76922017-11-08 16:03:48 +0900405 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700406 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800407 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900408 target: deviceTarget,
409 kind: productSpecificModule,
Dan Willemsen00269f22017-07-06 16:59:48 -0700410 },
411 inData: true,
412 },
413 in: []string{"nativetest", "my_test"},
414 out: "target/product/test_device/data/nativetest/my_test",
415 },
416
417 {
Justin Yund5f6c822019-06-25 16:47:17 +0900418 name: "system_ext native test binary",
Dario Frenifd05a742018-05-29 13:28:54 +0100419 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700420 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800421 os: deviceTarget.Os,
Dario Frenifd05a742018-05-29 13:28:54 +0100422 target: deviceTarget,
Justin Yund5f6c822019-06-25 16:47:17 +0900423 kind: systemExtSpecificModule,
Dario Frenifd05a742018-05-29 13:28:54 +0100424 },
425 inData: true,
426 },
427 in: []string{"nativetest", "my_test"},
428 out: "target/product/test_device/data/nativetest/my_test",
429 },
430
431 {
Dan Willemsen00269f22017-07-06 16:59:48 -0700432 name: "sanitized system binary",
433 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700434 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800435 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700436 target: deviceTarget,
437 },
438 inSanitizerDir: true,
439 },
440 in: []string{"bin", "my_test"},
441 out: "target/product/test_device/data/asan/system/bin/my_test",
442 },
443 {
444 name: "sanitized vendor binary",
445 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700446 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800447 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700448 target: deviceTarget,
Jiyong Park2db76922017-11-08 16:03:48 +0900449 kind: socSpecificModule,
Dan Willemsen00269f22017-07-06 16:59:48 -0700450 },
451 inSanitizerDir: true,
452 },
453 in: []string{"bin", "my_test"},
454 out: "target/product/test_device/data/asan/vendor/bin/my_test",
455 },
Jiyong Park2db76922017-11-08 16:03:48 +0900456 {
457 name: "sanitized odm binary",
458 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700459 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800460 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900461 target: deviceTarget,
462 kind: deviceSpecificModule,
463 },
464 inSanitizerDir: true,
465 },
466 in: []string{"bin", "my_test"},
467 out: "target/product/test_device/data/asan/odm/bin/my_test",
468 },
469 {
Jaekyun Seok5cfbfbb2018-01-10 19:00:15 +0900470 name: "sanitized product binary",
Jiyong Park2db76922017-11-08 16:03:48 +0900471 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700472 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800473 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900474 target: deviceTarget,
475 kind: productSpecificModule,
476 },
477 inSanitizerDir: true,
478 },
479 in: []string{"bin", "my_test"},
Jaekyun Seok5cfbfbb2018-01-10 19:00:15 +0900480 out: "target/product/test_device/data/asan/product/bin/my_test",
Jiyong Park2db76922017-11-08 16:03:48 +0900481 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700482
483 {
Justin Yund5f6c822019-06-25 16:47:17 +0900484 name: "sanitized system_ext binary",
Dario Frenifd05a742018-05-29 13:28:54 +0100485 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700486 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800487 os: deviceTarget.Os,
Dario Frenifd05a742018-05-29 13:28:54 +0100488 target: deviceTarget,
Justin Yund5f6c822019-06-25 16:47:17 +0900489 kind: systemExtSpecificModule,
Dario Frenifd05a742018-05-29 13:28:54 +0100490 },
491 inSanitizerDir: true,
492 },
493 in: []string{"bin", "my_test"},
Justin Yund5f6c822019-06-25 16:47:17 +0900494 out: "target/product/test_device/data/asan/system_ext/bin/my_test",
Dario Frenifd05a742018-05-29 13:28:54 +0100495 },
496
497 {
Dan Willemsen00269f22017-07-06 16:59:48 -0700498 name: "sanitized system native test binary",
499 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700500 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800501 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700502 target: deviceTarget,
503 },
504 inData: true,
505 inSanitizerDir: true,
506 },
507 in: []string{"nativetest", "my_test"},
508 out: "target/product/test_device/data/asan/data/nativetest/my_test",
509 },
510 {
511 name: "sanitized vendor native test binary",
512 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700513 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800514 os: deviceTarget.Os,
Dan Willemsen00269f22017-07-06 16:59:48 -0700515 target: deviceTarget,
Jiyong Park2db76922017-11-08 16:03:48 +0900516 kind: socSpecificModule,
517 },
518 inData: true,
519 inSanitizerDir: true,
520 },
521 in: []string{"nativetest", "my_test"},
522 out: "target/product/test_device/data/asan/data/nativetest/my_test",
523 },
524 {
525 name: "sanitized odm native test binary",
526 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700527 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800528 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900529 target: deviceTarget,
530 kind: deviceSpecificModule,
531 },
532 inData: true,
533 inSanitizerDir: true,
534 },
535 in: []string{"nativetest", "my_test"},
536 out: "target/product/test_device/data/asan/data/nativetest/my_test",
537 },
538 {
Jaekyun Seok5cfbfbb2018-01-10 19:00:15 +0900539 name: "sanitized product native test binary",
Jiyong Park2db76922017-11-08 16:03:48 +0900540 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700541 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800542 os: deviceTarget.Os,
Jiyong Park2db76922017-11-08 16:03:48 +0900543 target: deviceTarget,
544 kind: productSpecificModule,
Dan Willemsen00269f22017-07-06 16:59:48 -0700545 },
546 inData: true,
547 inSanitizerDir: true,
548 },
549 in: []string{"nativetest", "my_test"},
550 out: "target/product/test_device/data/asan/data/nativetest/my_test",
551 },
Dario Frenifd05a742018-05-29 13:28:54 +0100552 {
Justin Yund5f6c822019-06-25 16:47:17 +0900553 name: "sanitized system_ext native test binary",
Dario Frenifd05a742018-05-29 13:28:54 +0100554 ctx: &moduleInstallPathContextImpl{
Colin Cross0ea8ba82019-06-06 14:33:29 -0700555 baseModuleContext: baseModuleContext{
Colin Crossfb0c16e2019-11-20 17:12:35 -0800556 os: deviceTarget.Os,
Dario Frenifd05a742018-05-29 13:28:54 +0100557 target: deviceTarget,
Justin Yund5f6c822019-06-25 16:47:17 +0900558 kind: systemExtSpecificModule,
Dario Frenifd05a742018-05-29 13:28:54 +0100559 },
560 inData: true,
561 inSanitizerDir: true,
562 },
563 in: []string{"nativetest", "my_test"},
564 out: "target/product/test_device/data/asan/data/nativetest/my_test",
565 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700566 }
567
568 for _, tc := range testCases {
569 t.Run(tc.name, func(t *testing.T) {
Colin Cross0ea8ba82019-06-06 14:33:29 -0700570 tc.ctx.baseModuleContext.config = testConfig
Dan Willemsen00269f22017-07-06 16:59:48 -0700571 output := PathForModuleInstall(tc.ctx, tc.in...)
572 if output.basePath.path != tc.out {
573 t.Errorf("unexpected path:\n got: %q\nwant: %q\n",
574 output.basePath.path,
575 tc.out)
576 }
577 })
578 }
579}
Colin Cross5e6cfbe2017-11-03 15:20:35 -0700580
581func TestDirectorySortedPaths(t *testing.T) {
Colin Cross07e51612019-03-05 12:46:40 -0800582 config := TestConfig("out", nil)
583
584 ctx := PathContextForTesting(config, map[string][]byte{
585 "a.txt": nil,
586 "a/txt": nil,
587 "a/b/c": nil,
588 "a/b/d": nil,
589 "b": nil,
590 "b/b.txt": nil,
591 "a/a.txt": nil,
592 })
593
Colin Cross5e6cfbe2017-11-03 15:20:35 -0700594 makePaths := func() Paths {
595 return Paths{
Colin Cross07e51612019-03-05 12:46:40 -0800596 PathForSource(ctx, "a.txt"),
597 PathForSource(ctx, "a/txt"),
598 PathForSource(ctx, "a/b/c"),
599 PathForSource(ctx, "a/b/d"),
600 PathForSource(ctx, "b"),
601 PathForSource(ctx, "b/b.txt"),
602 PathForSource(ctx, "a/a.txt"),
Colin Cross5e6cfbe2017-11-03 15:20:35 -0700603 }
604 }
605
606 expected := []string{
607 "a.txt",
608 "a/a.txt",
609 "a/b/c",
610 "a/b/d",
611 "a/txt",
612 "b",
613 "b/b.txt",
614 }
615
616 paths := makePaths()
Colin Crossa140bb02018-04-17 10:52:26 -0700617 reversePaths := ReversePaths(paths)
Colin Cross5e6cfbe2017-11-03 15:20:35 -0700618
619 sortedPaths := PathsToDirectorySortedPaths(paths)
620 reverseSortedPaths := PathsToDirectorySortedPaths(reversePaths)
621
622 if !reflect.DeepEqual(Paths(sortedPaths).Strings(), expected) {
623 t.Fatalf("sorted paths:\n %#v\n != \n %#v", paths.Strings(), expected)
624 }
625
626 if !reflect.DeepEqual(Paths(reverseSortedPaths).Strings(), expected) {
627 t.Fatalf("sorted reversed paths:\n %#v\n !=\n %#v", reversePaths.Strings(), expected)
628 }
629
630 expectedA := []string{
631 "a/a.txt",
632 "a/b/c",
633 "a/b/d",
634 "a/txt",
635 }
636
637 inA := sortedPaths.PathsInDirectory("a")
638 if !reflect.DeepEqual(inA.Strings(), expectedA) {
639 t.Errorf("FilesInDirectory(a):\n %#v\n != \n %#v", inA.Strings(), expectedA)
640 }
641
642 expectedA_B := []string{
643 "a/b/c",
644 "a/b/d",
645 }
646
647 inA_B := sortedPaths.PathsInDirectory("a/b")
648 if !reflect.DeepEqual(inA_B.Strings(), expectedA_B) {
649 t.Errorf("FilesInDirectory(a/b):\n %#v\n != \n %#v", inA_B.Strings(), expectedA_B)
650 }
651
652 expectedB := []string{
653 "b/b.txt",
654 }
655
656 inB := sortedPaths.PathsInDirectory("b")
657 if !reflect.DeepEqual(inB.Strings(), expectedB) {
658 t.Errorf("FilesInDirectory(b):\n %#v\n != \n %#v", inA.Strings(), expectedA)
659 }
660}
Colin Cross43f08db2018-11-12 10:13:39 -0800661
662func TestMaybeRel(t *testing.T) {
663 testCases := []struct {
664 name string
665 base string
666 target string
667 out string
668 isRel bool
669 }{
670 {
671 name: "normal",
672 base: "a/b/c",
673 target: "a/b/c/d",
674 out: "d",
675 isRel: true,
676 },
677 {
678 name: "parent",
679 base: "a/b/c/d",
680 target: "a/b/c",
681 isRel: false,
682 },
683 {
684 name: "not relative",
685 base: "a/b",
686 target: "c/d",
687 isRel: false,
688 },
689 {
690 name: "abs1",
691 base: "/a",
692 target: "a",
693 isRel: false,
694 },
695 {
696 name: "abs2",
697 base: "a",
698 target: "/a",
699 isRel: false,
700 },
701 }
702
703 for _, testCase := range testCases {
704 t.Run(testCase.name, func(t *testing.T) {
705 ctx := &configErrorWrapper{}
706 out, isRel := MaybeRel(ctx, testCase.base, testCase.target)
707 if len(ctx.errors) > 0 {
708 t.Errorf("MaybeRel(..., %s, %s) reported unexpected errors %v",
709 testCase.base, testCase.target, ctx.errors)
710 }
711 if isRel != testCase.isRel || out != testCase.out {
712 t.Errorf("MaybeRel(..., %s, %s) want %v, %v got %v, %v",
713 testCase.base, testCase.target, testCase.out, testCase.isRel, out, isRel)
714 }
715 })
716 }
717}
Colin Cross7b3dcc32019-01-24 13:14:39 -0800718
719func TestPathForSource(t *testing.T) {
720 testCases := []struct {
721 name string
722 buildDir string
723 src string
724 err string
725 }{
726 {
727 name: "normal",
728 buildDir: "out",
729 src: "a/b/c",
730 },
731 {
732 name: "abs",
733 buildDir: "out",
734 src: "/a/b/c",
735 err: "is outside directory",
736 },
737 {
738 name: "in out dir",
739 buildDir: "out",
740 src: "out/a/b/c",
741 err: "is in output",
742 },
743 }
744
745 funcs := []struct {
746 name string
747 f func(ctx PathContext, pathComponents ...string) (SourcePath, error)
748 }{
749 {"pathForSource", pathForSource},
750 {"safePathForSource", safePathForSource},
751 }
752
753 for _, f := range funcs {
754 t.Run(f.name, func(t *testing.T) {
755 for _, test := range testCases {
756 t.Run(test.name, func(t *testing.T) {
757 testConfig := TestConfig(test.buildDir, nil)
758 ctx := &configErrorWrapper{config: testConfig}
759 _, err := f.f(ctx, test.src)
760 if len(ctx.errors) > 0 {
761 t.Fatalf("unexpected errors %v", ctx.errors)
762 }
763 if err != nil {
764 if test.err == "" {
765 t.Fatalf("unexpected error %q", err.Error())
766 } else if !strings.Contains(err.Error(), test.err) {
767 t.Fatalf("incorrect error, want substring %q got %q", test.err, err.Error())
768 }
769 } else {
770 if test.err != "" {
771 t.Fatalf("missing error %q", test.err)
772 }
773 }
774 })
775 }
776 })
777 }
778}
Colin Cross8854a5a2019-02-11 14:14:16 -0800779
Colin Cross8a497952019-03-05 22:25:09 -0800780type pathForModuleSrcTestModule struct {
Colin Cross937664a2019-03-06 10:17:32 -0800781 ModuleBase
782 props struct {
783 Srcs []string `android:"path"`
784 Exclude_srcs []string `android:"path"`
Colin Cross8a497952019-03-05 22:25:09 -0800785
786 Src *string `android:"path"`
Colin Crossba71a3f2019-03-18 12:12:48 -0700787
788 Module_handles_missing_deps bool
Colin Cross937664a2019-03-06 10:17:32 -0800789 }
790
Colin Cross8a497952019-03-05 22:25:09 -0800791 src string
792 rel string
793
794 srcs []string
Colin Cross937664a2019-03-06 10:17:32 -0800795 rels []string
Colin Cross8a497952019-03-05 22:25:09 -0800796
797 missingDeps []string
Colin Cross937664a2019-03-06 10:17:32 -0800798}
799
Colin Cross8a497952019-03-05 22:25:09 -0800800func pathForModuleSrcTestModuleFactory() Module {
801 module := &pathForModuleSrcTestModule{}
Colin Cross937664a2019-03-06 10:17:32 -0800802 module.AddProperties(&module.props)
803 InitAndroidModule(module)
804 return module
805}
806
Colin Cross8a497952019-03-05 22:25:09 -0800807func (p *pathForModuleSrcTestModule) GenerateAndroidBuildActions(ctx ModuleContext) {
Colin Crossba71a3f2019-03-18 12:12:48 -0700808 var srcs Paths
809 if p.props.Module_handles_missing_deps {
810 srcs, p.missingDeps = PathsAndMissingDepsForModuleSrcExcludes(ctx, p.props.Srcs, p.props.Exclude_srcs)
811 } else {
812 srcs = PathsForModuleSrcExcludes(ctx, p.props.Srcs, p.props.Exclude_srcs)
813 }
Colin Cross8a497952019-03-05 22:25:09 -0800814 p.srcs = srcs.Strings()
Colin Cross937664a2019-03-06 10:17:32 -0800815
Colin Cross8a497952019-03-05 22:25:09 -0800816 for _, src := range srcs {
Colin Cross937664a2019-03-06 10:17:32 -0800817 p.rels = append(p.rels, src.Rel())
818 }
Colin Cross8a497952019-03-05 22:25:09 -0800819
820 if p.props.Src != nil {
821 src := PathForModuleSrc(ctx, *p.props.Src)
822 if src != nil {
823 p.src = src.String()
824 p.rel = src.Rel()
825 }
826 }
827
Colin Crossba71a3f2019-03-18 12:12:48 -0700828 if !p.props.Module_handles_missing_deps {
829 p.missingDeps = ctx.GetMissingDependencies()
830 }
Colin Cross6c4f21f2019-06-06 15:41:36 -0700831
832 ctx.Build(pctx, BuildParams{
833 Rule: Touch,
834 Output: PathForModuleOut(ctx, "output"),
835 })
Colin Cross8a497952019-03-05 22:25:09 -0800836}
837
Colin Cross41955e82019-05-29 14:40:35 -0700838type pathForModuleSrcOutputFileProviderModule struct {
839 ModuleBase
840 props struct {
841 Outs []string
842 Tagged []string
843 }
844
845 outs Paths
846 tagged Paths
847}
848
849func pathForModuleSrcOutputFileProviderModuleFactory() Module {
850 module := &pathForModuleSrcOutputFileProviderModule{}
851 module.AddProperties(&module.props)
852 InitAndroidModule(module)
853 return module
854}
855
856func (p *pathForModuleSrcOutputFileProviderModule) GenerateAndroidBuildActions(ctx ModuleContext) {
857 for _, out := range p.props.Outs {
858 p.outs = append(p.outs, PathForModuleOut(ctx, out))
859 }
860
861 for _, tagged := range p.props.Tagged {
862 p.tagged = append(p.tagged, PathForModuleOut(ctx, tagged))
863 }
864}
865
866func (p *pathForModuleSrcOutputFileProviderModule) OutputFiles(tag string) (Paths, error) {
867 switch tag {
868 case "":
869 return p.outs, nil
870 case ".tagged":
871 return p.tagged, nil
872 default:
873 return nil, fmt.Errorf("unsupported tag %q", tag)
874 }
875}
876
Colin Cross8a497952019-03-05 22:25:09 -0800877type pathForModuleSrcTestCase struct {
878 name string
879 bp string
880 srcs []string
881 rels []string
882 src string
883 rel string
884}
885
886func testPathForModuleSrc(t *testing.T, buildDir string, tests []pathForModuleSrcTestCase) {
887 for _, test := range tests {
888 t.Run(test.name, func(t *testing.T) {
889 config := TestConfig(buildDir, nil)
890 ctx := NewTestContext()
891
Colin Cross4b49b762019-11-22 15:25:03 -0800892 ctx.RegisterModuleType("test", pathForModuleSrcTestModuleFactory)
893 ctx.RegisterModuleType("output_file_provider", pathForModuleSrcOutputFileProviderModuleFactory)
894 ctx.RegisterModuleType("filegroup", FileGroupFactory)
Colin Cross8a497952019-03-05 22:25:09 -0800895
896 fgBp := `
897 filegroup {
898 name: "a",
899 srcs: ["src/a"],
900 }
901 `
902
Colin Cross41955e82019-05-29 14:40:35 -0700903 ofpBp := `
904 output_file_provider {
905 name: "b",
906 outs: ["gen/b"],
907 tagged: ["gen/c"],
908 }
909 `
910
Colin Cross8a497952019-03-05 22:25:09 -0800911 mockFS := map[string][]byte{
912 "fg/Android.bp": []byte(fgBp),
913 "foo/Android.bp": []byte(test.bp),
Colin Cross41955e82019-05-29 14:40:35 -0700914 "ofp/Android.bp": []byte(ofpBp),
Colin Cross8a497952019-03-05 22:25:09 -0800915 "fg/src/a": nil,
916 "foo/src/b": nil,
917 "foo/src/c": nil,
918 "foo/src/d": nil,
919 "foo/src/e/e": nil,
920 "foo/src_special/$": nil,
921 }
922
923 ctx.MockFileSystem(mockFS)
924
925 ctx.Register()
Colin Cross41955e82019-05-29 14:40:35 -0700926 _, errs := ctx.ParseFileList(".", []string{"fg/Android.bp", "foo/Android.bp", "ofp/Android.bp"})
Colin Cross8a497952019-03-05 22:25:09 -0800927 FailIfErrored(t, errs)
928 _, errs = ctx.PrepareBuildActions(config)
929 FailIfErrored(t, errs)
930
931 m := ctx.ModuleForTests("foo", "").Module().(*pathForModuleSrcTestModule)
932
933 if g, w := m.srcs, test.srcs; !reflect.DeepEqual(g, w) {
934 t.Errorf("want srcs %q, got %q", w, g)
935 }
936
937 if g, w := m.rels, test.rels; !reflect.DeepEqual(g, w) {
938 t.Errorf("want rels %q, got %q", w, g)
939 }
940
941 if g, w := m.src, test.src; g != w {
942 t.Errorf("want src %q, got %q", w, g)
943 }
944
945 if g, w := m.rel, test.rel; g != w {
946 t.Errorf("want rel %q, got %q", w, g)
947 }
948 })
949 }
Colin Cross937664a2019-03-06 10:17:32 -0800950}
951
Colin Cross8a497952019-03-05 22:25:09 -0800952func TestPathsForModuleSrc(t *testing.T) {
953 tests := []pathForModuleSrcTestCase{
Colin Cross937664a2019-03-06 10:17:32 -0800954 {
955 name: "path",
956 bp: `
957 test {
958 name: "foo",
959 srcs: ["src/b"],
960 }`,
961 srcs: []string{"foo/src/b"},
962 rels: []string{"src/b"},
963 },
964 {
965 name: "glob",
966 bp: `
967 test {
968 name: "foo",
969 srcs: [
970 "src/*",
971 "src/e/*",
972 ],
973 }`,
974 srcs: []string{"foo/src/b", "foo/src/c", "foo/src/d", "foo/src/e/e"},
975 rels: []string{"src/b", "src/c", "src/d", "src/e/e"},
976 },
977 {
978 name: "recursive glob",
979 bp: `
980 test {
981 name: "foo",
982 srcs: ["src/**/*"],
983 }`,
984 srcs: []string{"foo/src/b", "foo/src/c", "foo/src/d", "foo/src/e/e"},
985 rels: []string{"src/b", "src/c", "src/d", "src/e/e"},
986 },
987 {
988 name: "filegroup",
989 bp: `
990 test {
991 name: "foo",
992 srcs: [":a"],
993 }`,
994 srcs: []string{"fg/src/a"},
995 rels: []string{"src/a"},
996 },
997 {
Colin Cross41955e82019-05-29 14:40:35 -0700998 name: "output file provider",
999 bp: `
1000 test {
1001 name: "foo",
1002 srcs: [":b"],
1003 }`,
1004 srcs: []string{buildDir + "/.intermediates/ofp/b/gen/b"},
1005 rels: []string{"gen/b"},
1006 },
1007 {
1008 name: "output file provider tagged",
1009 bp: `
1010 test {
1011 name: "foo",
1012 srcs: [":b{.tagged}"],
1013 }`,
1014 srcs: []string{buildDir + "/.intermediates/ofp/b/gen/c"},
1015 rels: []string{"gen/c"},
1016 },
1017 {
Colin Cross937664a2019-03-06 10:17:32 -08001018 name: "special characters glob",
1019 bp: `
1020 test {
1021 name: "foo",
1022 srcs: ["src_special/*"],
1023 }`,
1024 srcs: []string{"foo/src_special/$"},
1025 rels: []string{"src_special/$"},
1026 },
1027 }
1028
Colin Cross41955e82019-05-29 14:40:35 -07001029 testPathForModuleSrc(t, buildDir, tests)
1030}
1031
1032func TestPathForModuleSrc(t *testing.T) {
Colin Cross8a497952019-03-05 22:25:09 -08001033 tests := []pathForModuleSrcTestCase{
1034 {
1035 name: "path",
1036 bp: `
1037 test {
1038 name: "foo",
1039 src: "src/b",
1040 }`,
1041 src: "foo/src/b",
1042 rel: "src/b",
1043 },
1044 {
1045 name: "glob",
1046 bp: `
1047 test {
1048 name: "foo",
1049 src: "src/e/*",
1050 }`,
1051 src: "foo/src/e/e",
1052 rel: "src/e/e",
1053 },
1054 {
1055 name: "filegroup",
1056 bp: `
1057 test {
1058 name: "foo",
1059 src: ":a",
1060 }`,
1061 src: "fg/src/a",
1062 rel: "src/a",
1063 },
1064 {
Colin Cross41955e82019-05-29 14:40:35 -07001065 name: "output file provider",
1066 bp: `
1067 test {
1068 name: "foo",
1069 src: ":b",
1070 }`,
1071 src: buildDir + "/.intermediates/ofp/b/gen/b",
1072 rel: "gen/b",
1073 },
1074 {
1075 name: "output file provider tagged",
1076 bp: `
1077 test {
1078 name: "foo",
1079 src: ":b{.tagged}",
1080 }`,
1081 src: buildDir + "/.intermediates/ofp/b/gen/c",
1082 rel: "gen/c",
1083 },
1084 {
Colin Cross8a497952019-03-05 22:25:09 -08001085 name: "special characters glob",
1086 bp: `
1087 test {
1088 name: "foo",
1089 src: "src_special/*",
1090 }`,
1091 src: "foo/src_special/$",
1092 rel: "src_special/$",
1093 },
1094 }
1095
Colin Cross8a497952019-03-05 22:25:09 -08001096 testPathForModuleSrc(t, buildDir, tests)
1097}
Colin Cross937664a2019-03-06 10:17:32 -08001098
Colin Cross8a497952019-03-05 22:25:09 -08001099func TestPathsForModuleSrc_AllowMissingDependencies(t *testing.T) {
Colin Cross8a497952019-03-05 22:25:09 -08001100 config := TestConfig(buildDir, nil)
1101 config.TestProductVariables.Allow_missing_dependencies = proptools.BoolPtr(true)
1102
1103 ctx := NewTestContext()
1104 ctx.SetAllowMissingDependencies(true)
1105
Colin Cross4b49b762019-11-22 15:25:03 -08001106 ctx.RegisterModuleType("test", pathForModuleSrcTestModuleFactory)
Colin Cross8a497952019-03-05 22:25:09 -08001107
1108 bp := `
1109 test {
1110 name: "foo",
1111 srcs: [":a"],
1112 exclude_srcs: [":b"],
1113 src: ":c",
1114 }
Colin Crossba71a3f2019-03-18 12:12:48 -07001115
1116 test {
1117 name: "bar",
1118 srcs: [":d"],
1119 exclude_srcs: [":e"],
1120 module_handles_missing_deps: true,
1121 }
Colin Cross8a497952019-03-05 22:25:09 -08001122 `
1123
1124 mockFS := map[string][]byte{
1125 "Android.bp": []byte(bp),
1126 }
1127
1128 ctx.MockFileSystem(mockFS)
1129
1130 ctx.Register()
1131 _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
1132 FailIfErrored(t, errs)
1133 _, errs = ctx.PrepareBuildActions(config)
1134 FailIfErrored(t, errs)
1135
1136 foo := ctx.ModuleForTests("foo", "").Module().(*pathForModuleSrcTestModule)
1137
1138 if g, w := foo.missingDeps, []string{"a", "b", "c"}; !reflect.DeepEqual(g, w) {
Colin Crossba71a3f2019-03-18 12:12:48 -07001139 t.Errorf("want foo missing deps %q, got %q", w, g)
Colin Cross8a497952019-03-05 22:25:09 -08001140 }
1141
1142 if g, w := foo.srcs, []string{}; !reflect.DeepEqual(g, w) {
Colin Crossba71a3f2019-03-18 12:12:48 -07001143 t.Errorf("want foo srcs %q, got %q", w, g)
Colin Cross8a497952019-03-05 22:25:09 -08001144 }
1145
1146 if g, w := foo.src, ""; g != w {
Colin Crossba71a3f2019-03-18 12:12:48 -07001147 t.Errorf("want foo src %q, got %q", w, g)
Colin Cross8a497952019-03-05 22:25:09 -08001148 }
1149
Colin Crossba71a3f2019-03-18 12:12:48 -07001150 bar := ctx.ModuleForTests("bar", "").Module().(*pathForModuleSrcTestModule)
1151
1152 if g, w := bar.missingDeps, []string{"d", "e"}; !reflect.DeepEqual(g, w) {
1153 t.Errorf("want bar missing deps %q, got %q", w, g)
1154 }
1155
1156 if g, w := bar.srcs, []string{}; !reflect.DeepEqual(g, w) {
1157 t.Errorf("want bar srcs %q, got %q", w, g)
1158 }
Colin Cross937664a2019-03-06 10:17:32 -08001159}
1160
Colin Cross8854a5a2019-02-11 14:14:16 -08001161func ExampleOutputPath_ReplaceExtension() {
1162 ctx := &configErrorWrapper{
1163 config: TestConfig("out", nil),
1164 }
Colin Cross2cdd5df2019-02-25 10:25:24 -08001165 p := PathForOutput(ctx, "system/framework").Join(ctx, "boot.art")
Colin Cross8854a5a2019-02-11 14:14:16 -08001166 p2 := p.ReplaceExtension(ctx, "oat")
1167 fmt.Println(p, p2)
Colin Cross2cdd5df2019-02-25 10:25:24 -08001168 fmt.Println(p.Rel(), p2.Rel())
Colin Cross8854a5a2019-02-11 14:14:16 -08001169
1170 // Output:
1171 // out/system/framework/boot.art out/system/framework/boot.oat
Colin Cross2cdd5df2019-02-25 10:25:24 -08001172 // boot.art boot.oat
Colin Cross8854a5a2019-02-11 14:14:16 -08001173}
Colin Cross40e33732019-02-15 11:08:35 -08001174
1175func ExampleOutputPath_FileInSameDir() {
1176 ctx := &configErrorWrapper{
1177 config: TestConfig("out", nil),
1178 }
Colin Cross2cdd5df2019-02-25 10:25:24 -08001179 p := PathForOutput(ctx, "system/framework").Join(ctx, "boot.art")
Colin Cross40e33732019-02-15 11:08:35 -08001180 p2 := p.InSameDir(ctx, "oat", "arm", "boot.vdex")
1181 fmt.Println(p, p2)
Colin Cross2cdd5df2019-02-25 10:25:24 -08001182 fmt.Println(p.Rel(), p2.Rel())
Colin Cross40e33732019-02-15 11:08:35 -08001183
1184 // Output:
1185 // out/system/framework/boot.art out/system/framework/oat/arm/boot.vdex
Colin Cross2cdd5df2019-02-25 10:25:24 -08001186 // boot.art oat/arm/boot.vdex
Colin Cross40e33732019-02-15 11:08:35 -08001187}