platform_build_soong/bp2build/python_library_conversion_test.go
Chris Parsons cd209035aa Refactor bp2build tests for allowlist v2
Allowlist v2 will change bp2build by automatically disabling rdeps of
unconvertible modules. Many bp2build tests create bp2build stub modules
without an implementation,
This CL changes setup of such tests to also contain a BUILD file with
"stub implementations" of equivalent targets, to keep these test targets
convertible.

To verify this change in-place, this CL removes `bp2build_available:
false` from these dependencies.

This is a test-only change for bp2build tests.

Bug: 285631638
Test: m bp2build
Change-Id: I489480cbc4158a416b7abf57c35a6e2bc2ad6173
2023-09-19 17:04:11 +00:00

392 lines
9.8 KiB
Go

package bp2build
import (
"fmt"
"strings"
"testing"
"android/soong/android"
"android/soong/python"
)
// TODO(alexmarquez): Should be lifted into a generic Bp2Build file
type PythonLibBp2Build func(ctx android.TopDownMutatorContext)
type pythonLibBp2BuildTestCase struct {
description string
filesystem map[string]string
blueprint string
expectedBazelTargets []testBazelTarget
dir string
expectedError error
stubbedBuildDefinitions []string
}
func convertPythonLibTestCaseToBp2build_Host(tc pythonLibBp2BuildTestCase) Bp2buildTestCase {
for i := range tc.expectedBazelTargets {
tc.expectedBazelTargets[i].attrs["target_compatible_with"] = `select({
"//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
"//conditions:default": [],
})`
}
return convertPythonLibTestCaseToBp2build(tc)
}
func convertPythonLibTestCaseToBp2build(tc pythonLibBp2BuildTestCase) Bp2buildTestCase {
var bp2BuildTargets []string
for _, t := range tc.expectedBazelTargets {
bp2BuildTargets = append(bp2BuildTargets, MakeBazelTarget(t.typ, t.name, t.attrs))
}
// Copy the filesystem so that we can change stuff in it later without it
// affecting the original pythonLibBp2BuildTestCase
filesystemCopy := make(map[string]string)
for k, v := range tc.filesystem {
filesystemCopy[k] = v
}
return Bp2buildTestCase{
Description: tc.description,
Filesystem: filesystemCopy,
Blueprint: tc.blueprint,
ExpectedBazelTargets: bp2BuildTargets,
Dir: tc.dir,
ExpectedErr: tc.expectedError,
StubbedBuildDefinitions: tc.stubbedBuildDefinitions,
}
}
func runPythonLibraryTestCase(t *testing.T, tc pythonLibBp2BuildTestCase) {
t.Helper()
testCase := convertPythonLibTestCaseToBp2build(tc)
testCase.Description = fmt.Sprintf(testCase.Description, "python_library")
testCase.Blueprint = fmt.Sprintf(testCase.Blueprint, "python_library")
for name, contents := range testCase.Filesystem {
if strings.HasSuffix(name, "Android.bp") {
testCase.Filesystem[name] = fmt.Sprintf(contents, "python_library")
}
}
testCase.ModuleTypeUnderTest = "python_library"
testCase.ModuleTypeUnderTestFactory = python.PythonLibraryFactory
RunBp2BuildTestCaseSimple(t, testCase)
}
func runPythonLibraryHostTestCase(t *testing.T, tc pythonLibBp2BuildTestCase) {
t.Helper()
testCase := convertPythonLibTestCaseToBp2build_Host(tc)
testCase.Description = fmt.Sprintf(testCase.Description, "python_library_host")
testCase.Blueprint = fmt.Sprintf(testCase.Blueprint, "python_library_host")
for name, contents := range testCase.Filesystem {
if strings.HasSuffix(name, "Android.bp") {
testCase.Filesystem[name] = fmt.Sprintf(contents, "python_library_host")
}
}
testCase.ModuleTypeUnderTest = "python_library_host"
testCase.ModuleTypeUnderTestFactory = python.PythonLibraryHostFactory
RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {
ctx.RegisterModuleType("python_library", python.PythonLibraryFactory)
},
testCase)
}
func runPythonLibraryTestCases(t *testing.T, tc pythonLibBp2BuildTestCase) {
t.Helper()
runPythonLibraryTestCase(t, tc)
runPythonLibraryHostTestCase(t, tc)
}
func TestSimplePythonLib(t *testing.T) {
testCases := []pythonLibBp2BuildTestCase{
{
description: "simple %s converts to a native py_library",
filesystem: map[string]string{
"a.py": "",
"b/c.py": "",
"b/d.py": "",
"b/e.py": "",
"files/data.txt": "",
},
stubbedBuildDefinitions: []string{"bar"},
blueprint: `%s {
name: "foo",
srcs: ["**/*.py"],
exclude_srcs: ["b/e.py"],
data: ["files/data.txt",],
libs: ["bar"],
bazel_module: { bp2build_available: true },
}
python_library {
name: "bar",
srcs: ["b/e.py"],
}`,
expectedBazelTargets: []testBazelTarget{
{
typ: "py_library",
name: "foo",
attrs: AttrNameToString{
"data": `["files/data.txt"]`,
"deps": `[":bar"]`,
"srcs": `[
"a.py",
"b/c.py",
"b/d.py",
]`,
"srcs_version": `"PY3"`,
"imports": `["."]`,
},
},
},
},
{
description: "py2 %s converts to a native py_library",
blueprint: `%s {
name: "foo",
srcs: ["a.py"],
version: {
py2: {
enabled: true,
},
py3: {
enabled: false,
},
},
bazel_module: { bp2build_available: true },
}`,
expectedBazelTargets: []testBazelTarget{
{
typ: "py_library",
name: "foo",
attrs: AttrNameToString{
"srcs": `["a.py"]`,
"srcs_version": `"PY2"`,
"imports": `["."]`,
},
},
},
},
{
description: "py3 %s converts to a native py_library",
blueprint: `%s {
name: "foo",
srcs: ["a.py"],
version: {
py2: {
enabled: false,
},
py3: {
enabled: true,
},
},
bazel_module: { bp2build_available: true },
}`,
expectedBazelTargets: []testBazelTarget{
{
typ: "py_library",
name: "foo",
attrs: AttrNameToString{
"srcs": `["a.py"]`,
"srcs_version": `"PY3"`,
"imports": `["."]`,
},
},
},
},
{
description: "py2&3 %s converts to a native py_library",
blueprint: `%s {
name: "foo",
srcs: ["a.py"],
version: {
py2: {
enabled: true,
},
py3: {
enabled: true,
},
},
bazel_module: { bp2build_available: true },
}`,
expectedBazelTargets: []testBazelTarget{
{
// srcs_version is PY2ANDPY3 by default.
typ: "py_library",
name: "foo",
attrs: AttrNameToString{
"srcs": `["a.py"]`,
"imports": `["."]`,
},
},
},
},
{
description: "%s: pkg_path in a subdirectory of the same name converts correctly",
dir: "mylib/subpackage",
filesystem: map[string]string{
"mylib/subpackage/a.py": "",
"mylib/subpackage/Android.bp": `%s {
name: "foo",
srcs: ["a.py"],
pkg_path: "mylib/subpackage",
bazel_module: { bp2build_available: true },
}`,
},
blueprint: `%s {name: "bar"}`,
expectedBazelTargets: []testBazelTarget{
{
// srcs_version is PY2ANDPY3 by default.
typ: "py_library",
name: "foo",
attrs: AttrNameToString{
"srcs": `["a.py"]`,
"imports": `["../.."]`,
"srcs_version": `"PY3"`,
},
},
},
},
{
description: "%s: pkg_path in a subdirectory of a different name fails",
dir: "mylib/subpackage",
filesystem: map[string]string{
"mylib/subpackage/a.py": "",
"mylib/subpackage/Android.bp": `%s {
name: "foo",
srcs: ["a.py"],
pkg_path: "mylib/subpackage2",
bazel_module: { bp2build_available: true },
}`,
},
blueprint: `%s {name: "bar"}`,
expectedError: fmt.Errorf("Currently, bp2build only supports pkg_paths that are the same as the folders the Android.bp file is in."),
},
}
for _, tc := range testCases {
t.Run(tc.description, func(t *testing.T) {
runPythonLibraryTestCases(t, tc)
})
}
}
func TestPythonArchVariance(t *testing.T) {
runPythonLibraryTestCases(t, pythonLibBp2BuildTestCase{
description: "test %s arch variants",
filesystem: map[string]string{
"dir/arm.py": "",
"dir/x86.py": "",
},
blueprint: `%s {
name: "foo",
arch: {
arm: {
srcs: ["arm.py"],
},
x86: {
srcs: ["x86.py"],
},
},
}`,
expectedBazelTargets: []testBazelTarget{
{
typ: "py_library",
name: "foo",
attrs: AttrNameToString{
"srcs": `select({
"//build/bazel/platforms/arch:arm": ["arm.py"],
"//build/bazel/platforms/arch:x86": ["x86.py"],
"//conditions:default": [],
})`,
"srcs_version": `"PY3"`,
"imports": `["."]`,
},
},
},
})
}
func TestPythonLibraryWithProtobufs(t *testing.T) {
runPythonLibraryTestCases(t, pythonLibBp2BuildTestCase{
description: "test %s protobuf",
filesystem: map[string]string{
"dir/mylib.py": "",
"dir/myproto.proto": "",
},
blueprint: `%s {
name: "foo",
srcs: [
"dir/mylib.py",
"dir/myproto.proto",
],
}`,
expectedBazelTargets: []testBazelTarget{
{
typ: "proto_library",
name: "foo_proto",
attrs: AttrNameToString{
"srcs": `["dir/myproto.proto"]`,
},
},
{
typ: "py_proto_library",
name: "foo_py_proto",
attrs: AttrNameToString{
"deps": `[":foo_proto"]`,
},
},
{
typ: "py_library",
name: "foo",
attrs: AttrNameToString{
"srcs": `["dir/mylib.py"]`,
"srcs_version": `"PY3"`,
"imports": `["."]`,
"deps": `[":foo_py_proto"]`,
},
},
},
})
}
func TestPythonLibraryWithProtobufsAndPkgPath(t *testing.T) {
t.Parallel()
runBp2BuildTestCaseWithPythonLibraries(t, Bp2buildTestCase{
Description: "test python_library protobuf with pkg_path",
Filesystem: map[string]string{
"dir/foo.proto": "",
"dir/bar.proto": "", // bar contains "import dir/foo.proto"
"dir/Android.bp": `
python_library {
name: "foo",
pkg_path: "dir",
srcs: [
"foo.proto",
"bar.proto",
],
bazel_module: {bp2build_available: true},
}`,
},
Dir: "dir",
ExpectedBazelTargets: []string{
MakeBazelTarget("proto_library", "foo_proto", AttrNameToString{
"import_prefix": `"dir"`,
"strip_import_prefix": `""`,
"srcs": `[
"foo.proto",
"bar.proto",
]`,
}),
MakeBazelTarget("py_proto_library", "foo_py_proto", AttrNameToString{
"deps": `[":foo_proto"]`,
}),
MakeBazelTarget("py_library", "foo", AttrNameToString{
"srcs_version": `"PY3"`,
"imports": `[".."]`,
"deps": `[":foo_py_proto"]`,
}),
},
})
}