blob: 3b6d2ec5d090c201d5d646b4668e11fb6e1103ce [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"
Dan Willemsen34cc69e2015-09-23 15:26:20 -070025)
26
27type strsTestCase struct {
28 in []string
29 out string
30 err []error
31}
32
33var commonValidatePathTestCases = []strsTestCase{
34 {
35 in: []string{""},
36 out: "",
37 },
38 {
39 in: []string{"a/b"},
40 out: "a/b",
41 },
42 {
43 in: []string{"a/b", "c"},
44 out: "a/b/c",
45 },
46 {
47 in: []string{"a/.."},
48 out: ".",
49 },
50 {
51 in: []string{"."},
52 out: ".",
53 },
54 {
55 in: []string{".."},
56 out: "",
57 err: []error{errors.New("Path is outside directory: ..")},
58 },
59 {
60 in: []string{"../a"},
61 out: "",
62 err: []error{errors.New("Path is outside directory: ../a")},
63 },
64 {
65 in: []string{"b/../../a"},
66 out: "",
67 err: []error{errors.New("Path is outside directory: ../a")},
68 },
69 {
70 in: []string{"/a"},
71 out: "",
72 err: []error{errors.New("Path is outside directory: /a")},
73 },
Dan Willemsen80a7c2a2015-12-21 14:57:11 -080074 {
75 in: []string{"a", "../b"},
76 out: "",
77 err: []error{errors.New("Path is outside directory: ../b")},
78 },
79 {
80 in: []string{"a", "b/../../c"},
81 out: "",
82 err: []error{errors.New("Path is outside directory: ../c")},
83 },
84 {
85 in: []string{"a", "./.."},
86 out: "",
87 err: []error{errors.New("Path is outside directory: ..")},
88 },
Dan Willemsen34cc69e2015-09-23 15:26:20 -070089}
90
91var validateSafePathTestCases = append(commonValidatePathTestCases, []strsTestCase{
92 {
93 in: []string{"$host/../$a"},
94 out: "$a",
95 },
96}...)
97
98var validatePathTestCases = append(commonValidatePathTestCases, []strsTestCase{
99 {
100 in: []string{"$host/../$a"},
101 out: "",
102 err: []error{errors.New("Path contains invalid character($): $host/../$a")},
103 },
104 {
105 in: []string{"$host/.."},
106 out: "",
107 err: []error{errors.New("Path contains invalid character($): $host/..")},
108 },
109}...)
110
111func TestValidateSafePath(t *testing.T) {
112 for _, testCase := range validateSafePathTestCases {
Colin Crossdc75ae72018-02-22 13:48:13 -0800113 t.Run(strings.Join(testCase.in, ","), func(t *testing.T) {
114 ctx := &configErrorWrapper{}
Colin Cross1ccfcc32018-02-22 13:54:26 -0800115 out, err := validateSafePath(testCase.in...)
116 if err != nil {
117 reportPathError(ctx, err)
118 }
Colin Crossdc75ae72018-02-22 13:48:13 -0800119 check(t, "validateSafePath", p(testCase.in), out, ctx.errors, testCase.out, testCase.err)
120 })
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700121 }
122}
123
124func TestValidatePath(t *testing.T) {
125 for _, testCase := range validatePathTestCases {
Colin Crossdc75ae72018-02-22 13:48:13 -0800126 t.Run(strings.Join(testCase.in, ","), func(t *testing.T) {
127 ctx := &configErrorWrapper{}
Colin Cross1ccfcc32018-02-22 13:54:26 -0800128 out, err := validatePath(testCase.in...)
129 if err != nil {
130 reportPathError(ctx, err)
131 }
Colin Crossdc75ae72018-02-22 13:48:13 -0800132 check(t, "validatePath", p(testCase.in), out, ctx.errors, testCase.out, testCase.err)
133 })
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700134 }
135}
136
137func TestOptionalPath(t *testing.T) {
138 var path OptionalPath
139 checkInvalidOptionalPath(t, path)
140
141 path = OptionalPathForPath(nil)
142 checkInvalidOptionalPath(t, path)
143}
144
145func checkInvalidOptionalPath(t *testing.T, path OptionalPath) {
Colin Crossdc75ae72018-02-22 13:48:13 -0800146 t.Helper()
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700147 if path.Valid() {
148 t.Errorf("Uninitialized OptionalPath should not be valid")
149 }
150 if path.String() != "" {
151 t.Errorf("Uninitialized OptionalPath String() should return \"\", not %q", path.String())
152 }
153 defer func() {
154 if r := recover(); r == nil {
155 t.Errorf("Expected a panic when calling Path() on an uninitialized OptionalPath")
156 }
157 }()
158 path.Path()
159}
160
161func check(t *testing.T, testType, testString string,
162 got interface{}, err []error,
163 expected interface{}, expectedErr []error) {
Colin Crossdc75ae72018-02-22 13:48:13 -0800164 t.Helper()
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700165
166 printedTestCase := false
167 e := func(s string, expected, got interface{}) {
Colin Crossdc75ae72018-02-22 13:48:13 -0800168 t.Helper()
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700169 if !printedTestCase {
170 t.Errorf("test case %s: %s", testType, testString)
171 printedTestCase = true
172 }
173 t.Errorf("incorrect %s", s)
174 t.Errorf(" expected: %s", p(expected))
175 t.Errorf(" got: %s", p(got))
176 }
177
178 if !reflect.DeepEqual(expectedErr, err) {
179 e("errors:", expectedErr, err)
180 }
181
182 if !reflect.DeepEqual(expected, got) {
183 e("output:", expected, got)
184 }
185}
186
187func p(in interface{}) string {
188 if v, ok := in.([]interface{}); ok {
189 s := make([]string, len(v))
190 for i := range v {
191 s[i] = fmt.Sprintf("%#v", v[i])
192 }
193 return "[" + strings.Join(s, ", ") + "]"
194 } else {
195 return fmt.Sprintf("%#v", in)
196 }
197}
Dan Willemsen00269f22017-07-06 16:59:48 -0700198
199type moduleInstallPathContextImpl struct {
200 androidBaseContextImpl
201
202 inData bool
203 inSanitizerDir bool
Jiyong Parkf9332f12018-02-01 00:54:12 +0900204 inRecovery bool
Dan Willemsen00269f22017-07-06 16:59:48 -0700205}
206
207func (moduleInstallPathContextImpl) Fs() pathtools.FileSystem {
208 return pathtools.MockFs(nil)
209}
210
Colin Crossaabf6792017-11-29 00:27:14 -0800211func (m moduleInstallPathContextImpl) Config() Config {
Dan Willemsen00269f22017-07-06 16:59:48 -0700212 return m.androidBaseContextImpl.config
213}
214
215func (moduleInstallPathContextImpl) AddNinjaFileDeps(deps ...string) {}
216
217func (m moduleInstallPathContextImpl) InstallInData() bool {
218 return m.inData
219}
220
221func (m moduleInstallPathContextImpl) InstallInSanitizerDir() bool {
222 return m.inSanitizerDir
223}
224
Jiyong Parkf9332f12018-02-01 00:54:12 +0900225func (m moduleInstallPathContextImpl) InstallInRecovery() bool {
226 return m.inRecovery
227}
228
Dan Willemsen00269f22017-07-06 16:59:48 -0700229func TestPathForModuleInstall(t *testing.T) {
Colin Cross6ccbc912017-10-10 23:07:38 -0700230 testConfig := TestConfig("", nil)
Dan Willemsen00269f22017-07-06 16:59:48 -0700231
232 hostTarget := Target{Os: Linux}
233 deviceTarget := Target{Os: Android}
234
235 testCases := []struct {
236 name string
237 ctx *moduleInstallPathContextImpl
238 in []string
239 out string
240 }{
241 {
242 name: "host binary",
243 ctx: &moduleInstallPathContextImpl{
244 androidBaseContextImpl: androidBaseContextImpl{
245 target: hostTarget,
246 },
247 },
248 in: []string{"bin", "my_test"},
249 out: "host/linux-x86/bin/my_test",
250 },
251
252 {
253 name: "system binary",
254 ctx: &moduleInstallPathContextImpl{
255 androidBaseContextImpl: androidBaseContextImpl{
256 target: deviceTarget,
257 },
258 },
259 in: []string{"bin", "my_test"},
260 out: "target/product/test_device/system/bin/my_test",
261 },
262 {
263 name: "vendor binary",
264 ctx: &moduleInstallPathContextImpl{
265 androidBaseContextImpl: androidBaseContextImpl{
266 target: deviceTarget,
Jiyong Park2db76922017-11-08 16:03:48 +0900267 kind: socSpecificModule,
Dan Willemsen00269f22017-07-06 16:59:48 -0700268 },
269 },
270 in: []string{"bin", "my_test"},
271 out: "target/product/test_device/vendor/bin/my_test",
272 },
Jiyong Park2db76922017-11-08 16:03:48 +0900273 {
274 name: "odm binary",
275 ctx: &moduleInstallPathContextImpl{
276 androidBaseContextImpl: androidBaseContextImpl{
277 target: deviceTarget,
278 kind: deviceSpecificModule,
279 },
280 },
281 in: []string{"bin", "my_test"},
282 out: "target/product/test_device/odm/bin/my_test",
283 },
284 {
Jaekyun Seok5cfbfbb2018-01-10 19:00:15 +0900285 name: "product binary",
Jiyong Park2db76922017-11-08 16:03:48 +0900286 ctx: &moduleInstallPathContextImpl{
287 androidBaseContextImpl: androidBaseContextImpl{
288 target: deviceTarget,
289 kind: productSpecificModule,
290 },
291 },
292 in: []string{"bin", "my_test"},
Jaekyun Seok5cfbfbb2018-01-10 19:00:15 +0900293 out: "target/product/test_device/product/bin/my_test",
Jiyong Park2db76922017-11-08 16:03:48 +0900294 },
Dario Frenifd05a742018-05-29 13:28:54 +0100295 {
Dario Freni95cf7672018-08-17 00:57:57 +0100296 name: "product_services binary",
Dario Frenifd05a742018-05-29 13:28:54 +0100297 ctx: &moduleInstallPathContextImpl{
298 androidBaseContextImpl: androidBaseContextImpl{
299 target: deviceTarget,
300 kind: productServicesSpecificModule,
301 },
302 },
303 in: []string{"bin", "my_test"},
Dario Freni95cf7672018-08-17 00:57:57 +0100304 out: "target/product/test_device/product_services/bin/my_test",
Dario Frenifd05a742018-05-29 13:28:54 +0100305 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700306
307 {
308 name: "system native test binary",
309 ctx: &moduleInstallPathContextImpl{
310 androidBaseContextImpl: androidBaseContextImpl{
311 target: deviceTarget,
312 },
313 inData: true,
314 },
315 in: []string{"nativetest", "my_test"},
316 out: "target/product/test_device/data/nativetest/my_test",
317 },
318 {
319 name: "vendor native test binary",
320 ctx: &moduleInstallPathContextImpl{
321 androidBaseContextImpl: androidBaseContextImpl{
322 target: deviceTarget,
Jiyong Park2db76922017-11-08 16:03:48 +0900323 kind: socSpecificModule,
324 },
325 inData: true,
326 },
327 in: []string{"nativetest", "my_test"},
328 out: "target/product/test_device/data/nativetest/my_test",
329 },
330 {
331 name: "odm native test binary",
332 ctx: &moduleInstallPathContextImpl{
333 androidBaseContextImpl: androidBaseContextImpl{
334 target: deviceTarget,
335 kind: deviceSpecificModule,
336 },
337 inData: true,
338 },
339 in: []string{"nativetest", "my_test"},
340 out: "target/product/test_device/data/nativetest/my_test",
341 },
342 {
Jaekyun Seok5cfbfbb2018-01-10 19:00:15 +0900343 name: "product native test binary",
Jiyong Park2db76922017-11-08 16:03:48 +0900344 ctx: &moduleInstallPathContextImpl{
345 androidBaseContextImpl: androidBaseContextImpl{
346 target: deviceTarget,
347 kind: productSpecificModule,
Dan Willemsen00269f22017-07-06 16:59:48 -0700348 },
349 inData: true,
350 },
351 in: []string{"nativetest", "my_test"},
352 out: "target/product/test_device/data/nativetest/my_test",
353 },
354
355 {
Dario Freni95cf7672018-08-17 00:57:57 +0100356 name: "product_services native test binary",
Dario Frenifd05a742018-05-29 13:28:54 +0100357 ctx: &moduleInstallPathContextImpl{
358 androidBaseContextImpl: androidBaseContextImpl{
359 target: deviceTarget,
360 kind: productServicesSpecificModule,
361 },
362 inData: true,
363 },
364 in: []string{"nativetest", "my_test"},
365 out: "target/product/test_device/data/nativetest/my_test",
366 },
367
368 {
Dan Willemsen00269f22017-07-06 16:59:48 -0700369 name: "sanitized system binary",
370 ctx: &moduleInstallPathContextImpl{
371 androidBaseContextImpl: androidBaseContextImpl{
372 target: deviceTarget,
373 },
374 inSanitizerDir: true,
375 },
376 in: []string{"bin", "my_test"},
377 out: "target/product/test_device/data/asan/system/bin/my_test",
378 },
379 {
380 name: "sanitized vendor binary",
381 ctx: &moduleInstallPathContextImpl{
382 androidBaseContextImpl: androidBaseContextImpl{
383 target: deviceTarget,
Jiyong Park2db76922017-11-08 16:03:48 +0900384 kind: socSpecificModule,
Dan Willemsen00269f22017-07-06 16:59:48 -0700385 },
386 inSanitizerDir: true,
387 },
388 in: []string{"bin", "my_test"},
389 out: "target/product/test_device/data/asan/vendor/bin/my_test",
390 },
Jiyong Park2db76922017-11-08 16:03:48 +0900391 {
392 name: "sanitized odm binary",
393 ctx: &moduleInstallPathContextImpl{
394 androidBaseContextImpl: androidBaseContextImpl{
395 target: deviceTarget,
396 kind: deviceSpecificModule,
397 },
398 inSanitizerDir: true,
399 },
400 in: []string{"bin", "my_test"},
401 out: "target/product/test_device/data/asan/odm/bin/my_test",
402 },
403 {
Jaekyun Seok5cfbfbb2018-01-10 19:00:15 +0900404 name: "sanitized product binary",
Jiyong Park2db76922017-11-08 16:03:48 +0900405 ctx: &moduleInstallPathContextImpl{
406 androidBaseContextImpl: androidBaseContextImpl{
407 target: deviceTarget,
408 kind: productSpecificModule,
409 },
410 inSanitizerDir: true,
411 },
412 in: []string{"bin", "my_test"},
Jaekyun Seok5cfbfbb2018-01-10 19:00:15 +0900413 out: "target/product/test_device/data/asan/product/bin/my_test",
Jiyong Park2db76922017-11-08 16:03:48 +0900414 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700415
416 {
Dario Freni95cf7672018-08-17 00:57:57 +0100417 name: "sanitized product_services binary",
Dario Frenifd05a742018-05-29 13:28:54 +0100418 ctx: &moduleInstallPathContextImpl{
419 androidBaseContextImpl: androidBaseContextImpl{
420 target: deviceTarget,
421 kind: productServicesSpecificModule,
422 },
423 inSanitizerDir: true,
424 },
425 in: []string{"bin", "my_test"},
Dario Freni95cf7672018-08-17 00:57:57 +0100426 out: "target/product/test_device/data/asan/product_services/bin/my_test",
Dario Frenifd05a742018-05-29 13:28:54 +0100427 },
428
429 {
Dan Willemsen00269f22017-07-06 16:59:48 -0700430 name: "sanitized system native test binary",
431 ctx: &moduleInstallPathContextImpl{
432 androidBaseContextImpl: androidBaseContextImpl{
433 target: deviceTarget,
434 },
435 inData: true,
436 inSanitizerDir: true,
437 },
438 in: []string{"nativetest", "my_test"},
439 out: "target/product/test_device/data/asan/data/nativetest/my_test",
440 },
441 {
442 name: "sanitized vendor native test binary",
443 ctx: &moduleInstallPathContextImpl{
444 androidBaseContextImpl: androidBaseContextImpl{
445 target: deviceTarget,
Jiyong Park2db76922017-11-08 16:03:48 +0900446 kind: socSpecificModule,
447 },
448 inData: true,
449 inSanitizerDir: true,
450 },
451 in: []string{"nativetest", "my_test"},
452 out: "target/product/test_device/data/asan/data/nativetest/my_test",
453 },
454 {
455 name: "sanitized odm native test binary",
456 ctx: &moduleInstallPathContextImpl{
457 androidBaseContextImpl: androidBaseContextImpl{
458 target: deviceTarget,
459 kind: deviceSpecificModule,
460 },
461 inData: true,
462 inSanitizerDir: true,
463 },
464 in: []string{"nativetest", "my_test"},
465 out: "target/product/test_device/data/asan/data/nativetest/my_test",
466 },
467 {
Jaekyun Seok5cfbfbb2018-01-10 19:00:15 +0900468 name: "sanitized product native test binary",
Jiyong Park2db76922017-11-08 16:03:48 +0900469 ctx: &moduleInstallPathContextImpl{
470 androidBaseContextImpl: androidBaseContextImpl{
471 target: deviceTarget,
472 kind: productSpecificModule,
Dan Willemsen00269f22017-07-06 16:59:48 -0700473 },
474 inData: true,
475 inSanitizerDir: true,
476 },
477 in: []string{"nativetest", "my_test"},
478 out: "target/product/test_device/data/asan/data/nativetest/my_test",
479 },
Dario Frenifd05a742018-05-29 13:28:54 +0100480 {
Dario Freni95cf7672018-08-17 00:57:57 +0100481 name: "sanitized product_services native test binary",
Dario Frenifd05a742018-05-29 13:28:54 +0100482 ctx: &moduleInstallPathContextImpl{
483 androidBaseContextImpl: androidBaseContextImpl{
484 target: deviceTarget,
485 kind: productServicesSpecificModule,
486 },
487 inData: true,
488 inSanitizerDir: true,
489 },
490 in: []string{"nativetest", "my_test"},
491 out: "target/product/test_device/data/asan/data/nativetest/my_test",
492 },
Dan Willemsen00269f22017-07-06 16:59:48 -0700493 }
494
495 for _, tc := range testCases {
496 t.Run(tc.name, func(t *testing.T) {
497 tc.ctx.androidBaseContextImpl.config = testConfig
498 output := PathForModuleInstall(tc.ctx, tc.in...)
499 if output.basePath.path != tc.out {
500 t.Errorf("unexpected path:\n got: %q\nwant: %q\n",
501 output.basePath.path,
502 tc.out)
503 }
504 })
505 }
506}
Colin Cross5e6cfbe2017-11-03 15:20:35 -0700507
508func TestDirectorySortedPaths(t *testing.T) {
509 makePaths := func() Paths {
510 return Paths{
511 PathForTesting("a.txt"),
512 PathForTesting("a/txt"),
513 PathForTesting("a/b/c"),
514 PathForTesting("a/b/d"),
515 PathForTesting("b"),
516 PathForTesting("b/b.txt"),
517 PathForTesting("a/a.txt"),
518 }
519 }
520
521 expected := []string{
522 "a.txt",
523 "a/a.txt",
524 "a/b/c",
525 "a/b/d",
526 "a/txt",
527 "b",
528 "b/b.txt",
529 }
530
531 paths := makePaths()
Colin Crossa140bb02018-04-17 10:52:26 -0700532 reversePaths := ReversePaths(paths)
Colin Cross5e6cfbe2017-11-03 15:20:35 -0700533
534 sortedPaths := PathsToDirectorySortedPaths(paths)
535 reverseSortedPaths := PathsToDirectorySortedPaths(reversePaths)
536
537 if !reflect.DeepEqual(Paths(sortedPaths).Strings(), expected) {
538 t.Fatalf("sorted paths:\n %#v\n != \n %#v", paths.Strings(), expected)
539 }
540
541 if !reflect.DeepEqual(Paths(reverseSortedPaths).Strings(), expected) {
542 t.Fatalf("sorted reversed paths:\n %#v\n !=\n %#v", reversePaths.Strings(), expected)
543 }
544
545 expectedA := []string{
546 "a/a.txt",
547 "a/b/c",
548 "a/b/d",
549 "a/txt",
550 }
551
552 inA := sortedPaths.PathsInDirectory("a")
553 if !reflect.DeepEqual(inA.Strings(), expectedA) {
554 t.Errorf("FilesInDirectory(a):\n %#v\n != \n %#v", inA.Strings(), expectedA)
555 }
556
557 expectedA_B := []string{
558 "a/b/c",
559 "a/b/d",
560 }
561
562 inA_B := sortedPaths.PathsInDirectory("a/b")
563 if !reflect.DeepEqual(inA_B.Strings(), expectedA_B) {
564 t.Errorf("FilesInDirectory(a/b):\n %#v\n != \n %#v", inA_B.Strings(), expectedA_B)
565 }
566
567 expectedB := []string{
568 "b/b.txt",
569 }
570
571 inB := sortedPaths.PathsInDirectory("b")
572 if !reflect.DeepEqual(inB.Strings(), expectedB) {
573 t.Errorf("FilesInDirectory(b):\n %#v\n != \n %#v", inA.Strings(), expectedA)
574 }
575}
Colin Cross43f08db2018-11-12 10:13:39 -0800576
577func TestMaybeRel(t *testing.T) {
578 testCases := []struct {
579 name string
580 base string
581 target string
582 out string
583 isRel bool
584 }{
585 {
586 name: "normal",
587 base: "a/b/c",
588 target: "a/b/c/d",
589 out: "d",
590 isRel: true,
591 },
592 {
593 name: "parent",
594 base: "a/b/c/d",
595 target: "a/b/c",
596 isRel: false,
597 },
598 {
599 name: "not relative",
600 base: "a/b",
601 target: "c/d",
602 isRel: false,
603 },
604 {
605 name: "abs1",
606 base: "/a",
607 target: "a",
608 isRel: false,
609 },
610 {
611 name: "abs2",
612 base: "a",
613 target: "/a",
614 isRel: false,
615 },
616 }
617
618 for _, testCase := range testCases {
619 t.Run(testCase.name, func(t *testing.T) {
620 ctx := &configErrorWrapper{}
621 out, isRel := MaybeRel(ctx, testCase.base, testCase.target)
622 if len(ctx.errors) > 0 {
623 t.Errorf("MaybeRel(..., %s, %s) reported unexpected errors %v",
624 testCase.base, testCase.target, ctx.errors)
625 }
626 if isRel != testCase.isRel || out != testCase.out {
627 t.Errorf("MaybeRel(..., %s, %s) want %v, %v got %v, %v",
628 testCase.base, testCase.target, testCase.out, testCase.isRel, out, isRel)
629 }
630 })
631 }
632}
Colin Cross7b3dcc32019-01-24 13:14:39 -0800633
634func TestPathForSource(t *testing.T) {
635 testCases := []struct {
636 name string
637 buildDir string
638 src string
639 err string
640 }{
641 {
642 name: "normal",
643 buildDir: "out",
644 src: "a/b/c",
645 },
646 {
647 name: "abs",
648 buildDir: "out",
649 src: "/a/b/c",
650 err: "is outside directory",
651 },
652 {
653 name: "in out dir",
654 buildDir: "out",
655 src: "out/a/b/c",
656 err: "is in output",
657 },
658 }
659
660 funcs := []struct {
661 name string
662 f func(ctx PathContext, pathComponents ...string) (SourcePath, error)
663 }{
664 {"pathForSource", pathForSource},
665 {"safePathForSource", safePathForSource},
666 }
667
668 for _, f := range funcs {
669 t.Run(f.name, func(t *testing.T) {
670 for _, test := range testCases {
671 t.Run(test.name, func(t *testing.T) {
672 testConfig := TestConfig(test.buildDir, nil)
673 ctx := &configErrorWrapper{config: testConfig}
674 _, err := f.f(ctx, test.src)
675 if len(ctx.errors) > 0 {
676 t.Fatalf("unexpected errors %v", ctx.errors)
677 }
678 if err != nil {
679 if test.err == "" {
680 t.Fatalf("unexpected error %q", err.Error())
681 } else if !strings.Contains(err.Error(), test.err) {
682 t.Fatalf("incorrect error, want substring %q got %q", test.err, err.Error())
683 }
684 } else {
685 if test.err != "" {
686 t.Fatalf("missing error %q", test.err)
687 }
688 }
689 })
690 }
691 })
692 }
693}
Colin Cross8854a5a2019-02-11 14:14:16 -0800694
695func ExampleOutputPath_ReplaceExtension() {
696 ctx := &configErrorWrapper{
697 config: TestConfig("out", nil),
698 }
699 p := PathForOutput(ctx, "system/framework/boot.art")
700 p2 := p.ReplaceExtension(ctx, "oat")
701 fmt.Println(p, p2)
702
703 // Output:
704 // out/system/framework/boot.art out/system/framework/boot.oat
705}
Colin Cross40e33732019-02-15 11:08:35 -0800706
707func ExampleOutputPath_FileInSameDir() {
708 ctx := &configErrorWrapper{
709 config: TestConfig("out", nil),
710 }
711 p := PathForOutput(ctx, "system/framework/boot.art")
712 p2 := p.InSameDir(ctx, "oat", "arm", "boot.vdex")
713 fmt.Println(p, p2)
714
715 // Output:
716 // out/system/framework/boot.art out/system/framework/oat/arm/boot.vdex
717}