From 40e3373d41cea54beb6f3138aac06ae1605661db Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Fri, 15 Feb 2019 11:08:35 -0800 Subject: [PATCH] Add more paths helper methods Add PathsForOutput to convert multiple strings into WritablePaths. Add OutputPath.InSameDir to build a new OutputPath pointing to a file in the same directory as an existing OutputPath. Add WritablePathForTesting and WritablePathsForTesting that mirror PathForTesting and PathsForTesting but return WritablePaths. Add PathContextForTesting to return a minimal PathContext implementation. Test: paths_test.go Change-Id: I9708eb164b273514a96dae0a260ef9a963fb9bcf --- android/paths.go | 71 ++++++++++++++++++++++++++++++++++++++++++- android/paths_test.go | 12 ++++++++ cc/cc_test.go | 2 +- 3 files changed, 83 insertions(+), 2 deletions(-) diff --git a/android/paths.go b/android/paths.go index 31500ab82..3366db140 100644 --- a/android/paths.go +++ b/android/paths.go @@ -677,6 +677,15 @@ func PathForOutput(ctx PathContext, pathComponents ...string) OutputPath { return OutputPath{basePath{path, ctx.Config(), ""}} } +// PathsForOutput returns Paths rooted from buildDir +func PathsForOutput(ctx PathContext, paths []string) WritablePaths { + ret := make(WritablePaths, len(paths)) + for i, path := range paths { + ret[i] = PathForOutput(ctx, path) + } + return ret +} + func (p OutputPath) writablePath() {} func (p OutputPath) String() string { @@ -707,6 +716,18 @@ func (p OutputPath) ReplaceExtension(ctx PathContext, ext string) OutputPath { return ret } +// InSameDir creates a new OutputPath from the directory of the current OutputPath joined with the elements in paths. +func (p OutputPath) InSameDir(ctx PathContext, paths ...string) OutputPath { + path, err := validatePath(paths...) + if err != nil { + reportPathError(ctx, err) + } + + ret := PathForOutput(ctx, filepath.Dir(p.path), path) + ret.rel = p.rel + return ret +} + // PathForIntermediates returns an OutputPath representing the top-level // intermediates directory. func PathForIntermediates(ctx PathContext, paths ...string) OutputPath { @@ -1019,6 +1040,14 @@ func (p testPath) String() string { return p.path } +type testWritablePath struct { + testPath +} + +func (p testPath) writablePath() {} + +// PathForTesting returns a Path constructed from joining the elements of paths with '/'. It should only be used from +// within tests. func PathForTesting(paths ...string) Path { p, err := validateSafePath(paths...) if err != nil { @@ -1027,7 +1056,8 @@ func PathForTesting(paths ...string) Path { return testPath{basePath{path: p, rel: p}} } -func PathsForTesting(strs []string) Paths { +// PathsForTesting returns a Path constructed from each element in strs. It should only be used from within tests. +func PathsForTesting(strs ...string) Paths { p := make(Paths, len(strs)) for i, s := range strs { p[i] = PathForTesting(s) @@ -1036,6 +1066,45 @@ func PathsForTesting(strs []string) Paths { return p } +// WritablePathForTesting returns a Path constructed from joining the elements of paths with '/'. It should only be +// used from within tests. +func WritablePathForTesting(paths ...string) WritablePath { + p, err := validateSafePath(paths...) + if err != nil { + panic(err) + } + return testWritablePath{testPath{basePath{path: p, rel: p}}} +} + +// WritablePathsForTesting returns a Path constructed from each element in strs. It should only be used from within +// tests. +func WritablePathsForTesting(strs ...string) WritablePaths { + p := make(WritablePaths, len(strs)) + for i, s := range strs { + p[i] = WritablePathForTesting(s) + } + + return p +} + +type testPathContext struct { + config Config + fs pathtools.FileSystem +} + +func (x *testPathContext) Fs() pathtools.FileSystem { return x.fs } +func (x *testPathContext) Config() Config { return x.config } +func (x *testPathContext) AddNinjaFileDeps(...string) {} + +// PathContextForTesting returns a PathContext that can be used in tests, for example to create an OutputPath with +// PathForOutput. +func PathContextForTesting(config Config, fs map[string][]byte) PathContext { + return &testPathContext{ + config: config, + fs: pathtools.MockFs(fs), + } +} + // Rel performs the same function as filepath.Rel, but reports errors to a PathContext, and reports an error if // targetPath is not inside basePath. func Rel(ctx PathContext, basePath string, targetPath string) string { diff --git a/android/paths_test.go b/android/paths_test.go index 1972591d2..3b6d2ec5d 100644 --- a/android/paths_test.go +++ b/android/paths_test.go @@ -703,3 +703,15 @@ func ExampleOutputPath_ReplaceExtension() { // Output: // out/system/framework/boot.art out/system/framework/boot.oat } + +func ExampleOutputPath_FileInSameDir() { + ctx := &configErrorWrapper{ + config: TestConfig("out", nil), + } + p := PathForOutput(ctx, "system/framework/boot.art") + p2 := p.InSameDir(ctx, "oat", "arm", "boot.vdex") + fmt.Println(p, p2) + + // Output: + // out/system/framework/boot.art out/system/framework/oat/arm/boot.vdex +} diff --git a/cc/cc_test.go b/cc/cc_test.go index 22ac0d949..a0914c859 100644 --- a/cc/cc_test.go +++ b/cc/cc_test.go @@ -1039,7 +1039,7 @@ var splitListForSizeTestCases = []struct { func TestSplitListForSize(t *testing.T) { for _, testCase := range splitListForSizeTestCases { - out, _ := splitListForSize(android.PathsForTesting(testCase.in), testCase.size) + out, _ := splitListForSize(android.PathsForTesting(testCase.in...), testCase.size) var outStrings [][]string