Merge "Add (String)Path(s)RelativeToTop and assert functions" am: 6dcd2bfaa5 am: 160fde0333

Original change: https://android-review.googlesource.com/c/platform/build/soong/+/1636428

Change-Id: I02f4b35298de5d344fc2d99a11f28ff726e58b96
This commit is contained in:
Paul Duffin 2021-03-16 16:19:42 +00:00 committed by Automerger Merge Worker
commit 82f76c4dcf
3 changed files with 179 additions and 0 deletions

View File

@ -1261,6 +1261,52 @@ func TestPathsForModuleSrc_AllowMissingDependencies(t *testing.T) {
}
}
func TestPathRelativeToTop(t *testing.T) {
testConfig := pathTestConfig("/tmp/build/top")
deviceTarget := Target{Os: Android, Arch: Arch{ArchType: Arm64}}
ctx := &testModuleInstallPathContext{
baseModuleContext: baseModuleContext{
os: deviceTarget.Os,
target: deviceTarget,
},
}
ctx.baseModuleContext.config = testConfig
t.Run("install for soong", func(t *testing.T) {
p := PathForModuleInstall(ctx, "install/path")
AssertPathRelativeToTopEquals(t, "install path for soong", "out/soong/target/product/test_device/system/install/path", p)
})
t.Run("install for make", func(t *testing.T) {
p := PathForModuleInstall(ctx, "install/path").ToMakePath()
AssertPathRelativeToTopEquals(t, "install path for make", "out/target/product/test_device/system/install/path", p)
})
t.Run("output", func(t *testing.T) {
p := PathForOutput(ctx, "output/path")
AssertPathRelativeToTopEquals(t, "output path", "out/soong/output/path", p)
})
t.Run("source", func(t *testing.T) {
p := PathForSource(ctx, "source/path")
AssertPathRelativeToTopEquals(t, "source path", "source/path", p)
})
t.Run("mixture", func(t *testing.T) {
paths := Paths{
PathForModuleInstall(ctx, "install/path"),
PathForModuleInstall(ctx, "install/path").ToMakePath(),
PathForOutput(ctx, "output/path"),
PathForSource(ctx, "source/path"),
}
expected := []string{
"out/soong/target/product/test_device/system/install/path",
"out/target/product/test_device/system/install/path",
"out/soong/output/path",
"source/path",
}
AssertPathsRelativeToTopEquals(t, "mixture", expected, paths)
})
}
func ExampleOutputPath_ReplaceExtension() {
ctx := &configErrorWrapper{
config: TestConfig("out", nil, "", nil),

View File

@ -40,6 +40,34 @@ func AssertStringEquals(t *testing.T, message string, expected string, actual st
}
}
// AssertPathRelativeToTopEquals checks if the expected value is equal to the result of calling
// PathRelativeToTop on the actual Path.
func AssertPathRelativeToTopEquals(t *testing.T, message string, expected string, actual Path) {
t.Helper()
AssertStringEquals(t, message, expected, PathRelativeToTop(actual))
}
// AssertPathsRelativeToTopEquals checks if the expected value is equal to the result of calling
// PathsRelativeToTop on the actual Paths.
func AssertPathsRelativeToTopEquals(t *testing.T, message string, expected []string, actual Paths) {
t.Helper()
AssertDeepEquals(t, message, expected, PathsRelativeToTop(actual))
}
// AssertStringPathRelativeToTopEquals checks if the expected value is equal to the result of calling
// StringPathRelativeToTop on the actual string path.
func AssertStringPathRelativeToTopEquals(t *testing.T, message string, config Config, expected string, actual string) {
t.Helper()
AssertStringEquals(t, message, expected, StringPathRelativeToTop(config.buildDir, actual))
}
// AssertStringPathsRelativeToTopEquals checks if the expected value is equal to the result of
// calling StringPathsRelativeToTop on the actual string paths.
func AssertStringPathsRelativeToTopEquals(t *testing.T, message string, config Config, expected []string, actual []string) {
t.Helper()
AssertDeepEquals(t, message, expected, StringPathsRelativeToTop(config.buildDir, actual))
}
// AssertErrorMessageEquals checks if the error is not nil and has the expected message. If it does
// not then this reports an error prefixed with the supplied message and including a reason for why
// it failed.

View File

@ -813,6 +813,9 @@ func AndroidMkDataForTest(t *testing.T, ctx *TestContext, mod blueprint.Module)
// that is relative to the root of the source tree.
//
// The build and source paths should be distinguishable based on their contents.
//
// deprecated: use PathRelativeToTop instead as it handles make install paths and differentiates
// between output and source properly.
func NormalizePathForTesting(path Path) string {
if path == nil {
return "<nil path>"
@ -828,6 +831,11 @@ func NormalizePathForTesting(path Path) string {
return p
}
// NormalizePathsForTesting creates a slice of strings where each string is the result of applying
// NormalizePathForTesting to the corresponding Path in the input slice.
//
// deprecated: use PathsRelativeToTop instead as it handles make install paths and differentiates
// between output and source properly.
func NormalizePathsForTesting(paths Paths) []string {
var result []string
for _, path := range paths {
@ -836,3 +844,100 @@ func NormalizePathsForTesting(paths Paths) []string {
}
return result
}
// PathRelativeToTop returns a string representation of the path relative to a notional top
// directory.
//
// For a WritablePath it applies StringPathRelativeToTop to it, using the buildDir returned from the
// WritablePath's buildDir() method. For all other paths, i.e. source paths, that are already
// relative to the top it just returns their string representation.
func PathRelativeToTop(path Path) string {
if path == nil {
return "<nil path>"
}
p := path.String()
if w, ok := path.(WritablePath); ok {
buildDir := w.buildDir()
return StringPathRelativeToTop(buildDir, p)
}
return p
}
// PathsRelativeToTop creates a slice of strings where each string is the result of applying
// PathRelativeToTop to the corresponding Path in the input slice.
func PathsRelativeToTop(paths Paths) []string {
var result []string
for _, path := range paths {
relative := PathRelativeToTop(path)
result = append(result, relative)
}
return result
}
// StringPathRelativeToTop returns a string representation of the path relative to a notional top
// directory.
//
// A standard build has the following structure:
// ../top/
// out/ - make install files go here.
// out/soong - this is the buildDir passed to NewTestConfig()
// ... - the source files
//
// This function converts a path so that it appears relative to the ../top/ directory, i.e.
// * Make install paths, which have the pattern "buildDir/../<path>" are converted into the top
// relative path "out/<path>"
// * Soong install paths and other writable paths, which have the pattern "buildDir/<path>" are
// converted into the top relative path "out/soong/<path>".
// * Source paths are already relative to the top.
//
// This is provided for processing paths that have already been converted into a string, e.g. paths
// in AndroidMkEntries structures. As a result it needs to be supplied the soong output dir against
// which it can try and relativize paths. PathRelativeToTop must be used for process Path objects.
func StringPathRelativeToTop(soongOutDir string, path string) string {
// A relative path must be a source path so leave it as it is.
if !filepath.IsAbs(path) {
return path
}
// Check to see if the path is relative to the soong out dir.
rel, isRel, err := maybeRelErr(soongOutDir, path)
if err != nil {
panic(err)
}
if isRel {
// The path is in the soong out dir so indicate that in the relative path.
return filepath.Join("out/soong", rel)
}
// Check to see if the path is relative to the top level out dir.
outDir := filepath.Dir(soongOutDir)
rel, isRel, err = maybeRelErr(outDir, path)
if err != nil {
panic(err)
}
if isRel {
// The path is in the out dir so indicate that in the relative path.
return filepath.Join("out", rel)
}
// This should never happen.
panic(fmt.Errorf("internal error: absolute path %s is not relative to the out dir %s", path, outDir))
}
// StringPathsRelativeToTop creates a slice of strings where each string is the result of applying
// StringPathRelativeToTop to the corresponding string path in the input slice.
//
// This is provided for processing paths that have already been converted into a string, e.g. paths
// in AndroidMkEntries structures. As a result it needs to be supplied the soong output dir against
// which it can try and relativize paths. PathsRelativeToTop must be used for process Paths objects.
func StringPathsRelativeToTop(soongOutDir string, paths []string) []string {
var result []string
for _, path := range paths {
relative := StringPathRelativeToTop(soongOutDir, path)
result = append(result, relative)
}
return result
}