platform_build_soong/bp2build/build_conversion_test.go
Cole Faust b85d1a15cc Bp2build support for multiple product configs
Create a
build/bazel/product_config/generated/products/<product_name>/BUILD
file that contains the platform definitions needed for
a particular product. Currently we just create it for the
current lunch target, but the idea is that eventually when
all product config is in starlark, all the products will
have their platform definitions in the tree at once.

Bug: 249685973
Test: Presubmits
Change-Id: I08c82ff28dcf62f09d3b1d2e3186a6b961e12f6e
2023-01-05 12:49:14 -08:00

1879 lines
52 KiB
Go

// Copyright 2020 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package bp2build
import (
"fmt"
"strings"
"testing"
"android/soong/android"
"android/soong/android/allowlists"
"android/soong/python"
)
func TestGenerateSoongModuleTargets(t *testing.T) {
testCases := []struct {
description string
bp string
expectedBazelTarget string
}{
{
description: "only name",
bp: `custom { name: "foo" }
`,
expectedBazelTarget: `soong_module(
name = "foo",
soong_module_name = "foo",
soong_module_type = "custom",
soong_module_variant = "",
soong_module_deps = [
],
bool_prop = False,
string_prop = "",
)`,
},
{
description: "handles bool",
bp: `custom {
name: "foo",
bool_prop: true,
}
`,
expectedBazelTarget: `soong_module(
name = "foo",
soong_module_name = "foo",
soong_module_type = "custom",
soong_module_variant = "",
soong_module_deps = [
],
bool_prop = True,
string_prop = "",
)`,
},
{
description: "string escaping",
bp: `custom {
name: "foo",
owner: "a_string_with\"quotes\"_and_\\backslashes\\\\",
}
`,
expectedBazelTarget: `soong_module(
name = "foo",
soong_module_name = "foo",
soong_module_type = "custom",
soong_module_variant = "",
soong_module_deps = [
],
bool_prop = False,
owner = "a_string_with\"quotes\"_and_\\backslashes\\\\",
string_prop = "",
)`,
},
{
description: "single item string list",
bp: `custom {
name: "foo",
required: ["bar"],
}
`,
expectedBazelTarget: `soong_module(
name = "foo",
soong_module_name = "foo",
soong_module_type = "custom",
soong_module_variant = "",
soong_module_deps = [
],
bool_prop = False,
required = ["bar"],
string_prop = "",
)`,
},
{
description: "list of strings",
bp: `custom {
name: "foo",
target_required: ["qux", "bazqux"],
}
`,
expectedBazelTarget: `soong_module(
name = "foo",
soong_module_name = "foo",
soong_module_type = "custom",
soong_module_variant = "",
soong_module_deps = [
],
bool_prop = False,
string_prop = "",
target_required = [
"qux",
"bazqux",
],
)`,
},
{
description: "dist/dists",
bp: `custom {
name: "foo",
dist: {
targets: ["goal_foo"],
tag: ".foo",
},
dists: [{
targets: ["goal_bar"],
tag: ".bar",
}],
}
`,
expectedBazelTarget: `soong_module(
name = "foo",
soong_module_name = "foo",
soong_module_type = "custom",
soong_module_variant = "",
soong_module_deps = [
],
bool_prop = False,
dist = {
"tag": ".foo",
"targets": ["goal_foo"],
},
dists = [{
"tag": ".bar",
"targets": ["goal_bar"],
}],
string_prop = "",
)`,
},
{
description: "put it together",
bp: `custom {
name: "foo",
required: ["bar"],
target_required: ["qux", "bazqux"],
bool_prop: true,
owner: "custom_owner",
dists: [
{
tag: ".tag",
targets: ["my_goal"],
},
],
}
`,
expectedBazelTarget: `soong_module(
name = "foo",
soong_module_name = "foo",
soong_module_type = "custom",
soong_module_variant = "",
soong_module_deps = [
],
bool_prop = True,
dists = [{
"tag": ".tag",
"targets": ["my_goal"],
}],
owner = "custom_owner",
required = ["bar"],
string_prop = "",
target_required = [
"qux",
"bazqux",
],
)`,
},
}
dir := "."
for _, testCase := range testCases {
t.Run(testCase.description, func(t *testing.T) {
config := android.TestConfig(buildDir, nil, testCase.bp, nil)
ctx := android.NewTestContext(config)
ctx.RegisterModuleType("custom", customModuleFactoryHostAndDevice)
ctx.Register()
_, errs := ctx.ParseFileList(dir, []string{"Android.bp"})
android.FailIfErrored(t, errs)
_, errs = ctx.PrepareBuildActions(config)
android.FailIfErrored(t, errs)
codegenCtx := NewCodegenContext(config, ctx.Context, QueryView, "")
bazelTargets, err := generateBazelTargetsForDir(codegenCtx, dir)
android.FailIfErrored(t, err)
if actualCount, expectedCount := len(bazelTargets), 1; actualCount != expectedCount {
t.Fatalf("Expected %d bazel target, got %d", expectedCount, actualCount)
}
actualBazelTarget := bazelTargets[0]
if actualBazelTarget.content != testCase.expectedBazelTarget {
t.Errorf(
"Expected generated Bazel target to be '%s', got '%s'",
testCase.expectedBazelTarget,
actualBazelTarget.content,
)
}
})
}
}
func TestGenerateBazelTargetModules(t *testing.T) {
testCases := []Bp2buildTestCase{
{
Description: "string prop empty",
Blueprint: `custom {
name: "foo",
string_literal_prop: "",
bazel_module: { bp2build_available: true },
}`,
ExpectedBazelTargets: []string{
MakeBazelTarget("custom", "foo", AttrNameToString{
"string_literal_prop": `""`,
}),
},
},
{
Description: `string prop "PROP"`,
Blueprint: `custom {
name: "foo",
string_literal_prop: "PROP",
bazel_module: { bp2build_available: true },
}`,
ExpectedBazelTargets: []string{
MakeBazelTarget("custom", "foo", AttrNameToString{
"string_literal_prop": `"PROP"`,
}),
},
},
{
Description: `string prop arch variant`,
Blueprint: `custom {
name: "foo",
arch: {
arm: { string_literal_prop: "ARM" },
arm64: { string_literal_prop: "ARM64" },
},
bazel_module: { bp2build_available: true },
}`,
ExpectedBazelTargets: []string{
MakeBazelTarget("custom", "foo", AttrNameToString{
"string_literal_prop": `select({
"//build/bazel/platforms/arch:arm": "ARM",
"//build/bazel/platforms/arch:arm64": "ARM64",
"//conditions:default": None,
})`,
}),
},
},
{
Description: "string ptr props",
Blueprint: `custom {
name: "foo",
string_ptr_prop: "",
bazel_module: { bp2build_available: true },
}`,
ExpectedBazelTargets: []string{
MakeBazelTarget("custom", "foo", AttrNameToString{
"string_ptr_prop": `""`,
}),
},
},
{
Description: "string list props",
Blueprint: `custom {
name: "foo",
string_list_prop: ["a", "b"],
string_ptr_prop: "a",
bazel_module: { bp2build_available: true },
}`,
ExpectedBazelTargets: []string{
MakeBazelTarget("custom", "foo", AttrNameToString{
"string_list_prop": `[
"a",
"b",
]`,
"string_ptr_prop": `"a"`,
}),
},
},
{
Description: "control characters",
Blueprint: `custom {
name: "foo",
string_list_prop: ["\t", "\n"],
string_ptr_prop: "a\t\n\r",
bazel_module: { bp2build_available: true },
}`,
ExpectedBazelTargets: []string{
MakeBazelTarget("custom", "foo", AttrNameToString{
"string_list_prop": `[
"\t",
"\n",
]`,
"string_ptr_prop": `"a\t\n\r"`,
}),
},
},
{
Description: "handles dep",
Blueprint: `custom {
name: "has_dep",
arch_paths: [":dep"],
bazel_module: { bp2build_available: true },
}
custom {
name: "dep",
arch_paths: ["abc"],
bazel_module: { bp2build_available: true },
}`,
ExpectedBazelTargets: []string{
MakeBazelTarget("custom", "dep", AttrNameToString{
"arch_paths": `["abc"]`,
}),
MakeBazelTarget("custom", "has_dep", AttrNameToString{
"arch_paths": `[":dep"]`,
}),
},
},
{
Description: "non-existent dep",
Blueprint: `custom {
name: "has_dep",
arch_paths: [":dep"],
bazel_module: { bp2build_available: true },
}`,
ExpectedBazelTargets: []string{
MakeBazelTarget("custom", "has_dep", AttrNameToString{
"arch_paths": `[":dep__BP2BUILD__MISSING__DEP"]`,
}),
},
},
{
Description: "arch-variant srcs",
Blueprint: `custom {
name: "arch_paths",
arch: {
x86: { arch_paths: ["x86.txt"] },
x86_64: { arch_paths: ["x86_64.txt"] },
arm: { arch_paths: ["arm.txt"] },
arm64: { arch_paths: ["arm64.txt"] },
riscv64: { arch_paths: ["riscv64.txt"] },
},
target: {
linux: { arch_paths: ["linux.txt"] },
bionic: { arch_paths: ["bionic.txt"] },
host: { arch_paths: ["host.txt"] },
not_windows: { arch_paths: ["not_windows.txt"] },
android: { arch_paths: ["android.txt"] },
linux_musl: { arch_paths: ["linux_musl.txt"] },
musl: { arch_paths: ["musl.txt"] },
linux_glibc: { arch_paths: ["linux_glibc.txt"] },
glibc: { arch_paths: ["glibc.txt"] },
linux_bionic: { arch_paths: ["linux_bionic.txt"] },
darwin: { arch_paths: ["darwin.txt"] },
windows: { arch_paths: ["windows.txt"] },
},
multilib: {
lib32: { arch_paths: ["lib32.txt"] },
lib64: { arch_paths: ["lib64.txt"] },
},
bazel_module: { bp2build_available: true },
}`,
ExpectedBazelTargets: []string{
MakeBazelTarget("custom", "arch_paths", AttrNameToString{
"arch_paths": `select({
"//build/bazel/platforms/arch:arm": [
"arm.txt",
"lib32.txt",
],
"//build/bazel/platforms/arch:arm64": [
"arm64.txt",
"lib64.txt",
],
"//build/bazel/platforms/arch:riscv64": [
"riscv64.txt",
"lib64.txt",
],
"//build/bazel/platforms/arch:x86": [
"x86.txt",
"lib32.txt",
],
"//build/bazel/platforms/arch:x86_64": [
"x86_64.txt",
"lib64.txt",
],
"//conditions:default": [],
}) + select({
"//build/bazel/platforms/os:android": [
"linux.txt",
"bionic.txt",
"android.txt",
],
"//build/bazel/platforms/os:darwin": [
"host.txt",
"darwin.txt",
"not_windows.txt",
],
"//build/bazel/platforms/os:linux_bionic": [
"host.txt",
"linux.txt",
"bionic.txt",
"linux_bionic.txt",
"not_windows.txt",
],
"//build/bazel/platforms/os:linux_glibc": [
"host.txt",
"linux.txt",
"glibc.txt",
"linux_glibc.txt",
"not_windows.txt",
],
"//build/bazel/platforms/os:linux_musl": [
"host.txt",
"linux.txt",
"musl.txt",
"linux_musl.txt",
"not_windows.txt",
],
"//build/bazel/platforms/os:windows": [
"host.txt",
"windows.txt",
],
"//conditions:default": [],
})`,
}),
},
},
{
Description: "arch-variant deps",
Blueprint: `custom {
name: "has_dep",
arch: {
x86: {
arch_paths: [":dep"],
},
},
bazel_module: { bp2build_available: true },
}
custom {
name: "dep",
arch_paths: ["abc"],
bazel_module: { bp2build_available: true },
}`,
ExpectedBazelTargets: []string{
MakeBazelTarget("custom", "dep", AttrNameToString{
"arch_paths": `["abc"]`,
}),
MakeBazelTarget("custom", "has_dep", AttrNameToString{
"arch_paths": `select({
"//build/bazel/platforms/arch:x86": [":dep"],
"//conditions:default": [],
})`,
}),
},
},
{
Description: "embedded props",
Blueprint: `custom {
name: "embedded_props",
embedded_prop: "abc",
bazel_module: { bp2build_available: true },
}`,
ExpectedBazelTargets: []string{
MakeBazelTarget("custom", "embedded_props", AttrNameToString{
"embedded_attr": `"abc"`,
}),
},
},
{
Description: "ptr to embedded props",
Blueprint: `custom {
name: "ptr_to_embedded_props",
other_embedded_prop: "abc",
bazel_module: { bp2build_available: true },
}`,
ExpectedBazelTargets: []string{
MakeBazelTarget("custom", "ptr_to_embedded_props", AttrNameToString{
"other_embedded_attr": `"abc"`,
}),
},
},
}
dir := "."
for _, testCase := range testCases {
t.Run(testCase.Description, func(t *testing.T) {
config := android.TestConfig(buildDir, nil, testCase.Blueprint, nil)
ctx := android.NewTestContext(config)
registerCustomModuleForBp2buildConversion(ctx)
_, errs := ctx.ParseFileList(dir, []string{"Android.bp"})
if errored(t, testCase, errs) {
return
}
_, errs = ctx.ResolveDependencies(config)
if errored(t, testCase, errs) {
return
}
codegenCtx := NewCodegenContext(config, ctx.Context, Bp2Build, "")
bazelTargets, err := generateBazelTargetsForDir(codegenCtx, dir)
android.FailIfErrored(t, err)
if actualCount, expectedCount := len(bazelTargets), len(testCase.ExpectedBazelTargets); actualCount != expectedCount {
t.Errorf("Expected %d bazel target (%s),\ngot %d (%s)", expectedCount, testCase.ExpectedBazelTargets, actualCount, bazelTargets)
} else {
for i, expectedBazelTarget := range testCase.ExpectedBazelTargets {
actualBazelTarget := bazelTargets[i]
if actualBazelTarget.content != expectedBazelTarget {
t.Errorf(
"Expected generated Bazel target to be '%s', got '%s'",
expectedBazelTarget,
actualBazelTarget.content,
)
}
}
}
})
}
}
func TestBp2buildHostAndDevice(t *testing.T) {
testCases := []Bp2buildTestCase{
{
Description: "host and device, device only",
ModuleTypeUnderTest: "custom",
ModuleTypeUnderTestFactory: customModuleFactoryHostAndDevice,
Blueprint: `custom {
name: "foo",
bazel_module: { bp2build_available: true },
}`,
ExpectedBazelTargets: []string{
makeBazelTargetHostOrDevice("custom", "foo", AttrNameToString{}, android.DeviceSupported),
},
},
{
Description: "host and device, both",
ModuleTypeUnderTest: "custom",
ModuleTypeUnderTestFactory: customModuleFactoryHostAndDevice,
Blueprint: `custom {
name: "foo",
host_supported: true,
bazel_module: { bp2build_available: true },
}`,
ExpectedBazelTargets: []string{
MakeBazelTargetNoRestrictions("custom", "foo", AttrNameToString{}),
},
},
{
Description: "host and device, host explicitly disabled",
ModuleTypeUnderTest: "custom",
ModuleTypeUnderTestFactory: customModuleFactoryHostAndDevice,
Blueprint: `custom {
name: "foo",
host_supported: false,
bazel_module: { bp2build_available: true },
}`,
ExpectedBazelTargets: []string{
makeBazelTargetHostOrDevice("custom", "foo", AttrNameToString{}, android.DeviceSupported),
},
},
{
Description: "host and device, neither",
ModuleTypeUnderTest: "custom",
ModuleTypeUnderTestFactory: customModuleFactoryHostAndDevice,
Blueprint: `custom {
name: "foo",
host_supported: false,
device_supported: false,
bazel_module: { bp2build_available: true },
}`,
ExpectedBazelTargets: []string{
MakeBazelTargetNoRestrictions("custom", "foo", AttrNameToString{
"target_compatible_with": `["@platforms//:incompatible"]`,
}),
},
},
{
Description: "host and device, neither, cannot override with product_var",
ModuleTypeUnderTest: "custom",
ModuleTypeUnderTestFactory: customModuleFactoryHostAndDevice,
Blueprint: `custom {
name: "foo",
host_supported: false,
device_supported: false,
product_variables: { unbundled_build: { enabled: true } },
bazel_module: { bp2build_available: true },
}`,
ExpectedBazelTargets: []string{
MakeBazelTargetNoRestrictions("custom", "foo", AttrNameToString{
"target_compatible_with": `["@platforms//:incompatible"]`,
}),
},
},
{
Description: "host and device, both, disabled overrided with product_var",
ModuleTypeUnderTest: "custom",
ModuleTypeUnderTestFactory: customModuleFactoryHostAndDevice,
Blueprint: `custom {
name: "foo",
host_supported: true,
device_supported: true,
enabled: false,
product_variables: { unbundled_build: { enabled: true } },
bazel_module: { bp2build_available: true },
}`,
ExpectedBazelTargets: []string{
MakeBazelTargetNoRestrictions("custom", "foo", AttrNameToString{
"target_compatible_with": `["//build/bazel/product_variables:unbundled_build"]`,
}),
},
},
{
Description: "host and device, neither, cannot override with arch enabled",
ModuleTypeUnderTest: "custom",
ModuleTypeUnderTestFactory: customModuleFactoryHostAndDevice,
Blueprint: `custom {
name: "foo",
host_supported: false,
device_supported: false,
arch: { x86: { enabled: true } },
bazel_module: { bp2build_available: true },
}`,
ExpectedBazelTargets: []string{
MakeBazelTargetNoRestrictions("custom", "foo", AttrNameToString{
"target_compatible_with": `["@platforms//:incompatible"]`,
}),
},
},
{
Description: "host and device, host only",
ModuleTypeUnderTest: "custom",
ModuleTypeUnderTestFactory: customModuleFactoryHostAndDevice,
Blueprint: `custom {
name: "foo",
host_supported: true,
device_supported: false,
bazel_module: { bp2build_available: true },
}`,
ExpectedBazelTargets: []string{
makeBazelTargetHostOrDevice("custom", "foo", AttrNameToString{}, android.HostSupported),
},
},
{
Description: "host only",
ModuleTypeUnderTest: "custom",
ModuleTypeUnderTestFactory: customModuleFactoryHostSupported,
Blueprint: `custom {
name: "foo",
bazel_module: { bp2build_available: true },
}`,
ExpectedBazelTargets: []string{
makeBazelTargetHostOrDevice("custom", "foo", AttrNameToString{}, android.HostSupported),
},
},
{
Description: "device only",
ModuleTypeUnderTest: "custom",
ModuleTypeUnderTestFactory: customModuleFactoryDeviceSupported,
Blueprint: `custom {
name: "foo",
bazel_module: { bp2build_available: true },
}`,
ExpectedBazelTargets: []string{
makeBazelTargetHostOrDevice("custom", "foo", AttrNameToString{}, android.DeviceSupported),
},
},
{
Description: "host and device default, default",
ModuleTypeUnderTest: "custom",
ModuleTypeUnderTestFactory: customModuleFactoryHostAndDeviceDefault,
Blueprint: `custom {
name: "foo",
bazel_module: { bp2build_available: true },
}`,
ExpectedBazelTargets: []string{
MakeBazelTargetNoRestrictions("custom", "foo", AttrNameToString{}),
},
},
{
Description: "host and device default, device only",
ModuleTypeUnderTest: "custom",
ModuleTypeUnderTestFactory: customModuleFactoryHostAndDeviceDefault,
Blueprint: `custom {
name: "foo",
host_supported: false,
bazel_module: { bp2build_available: true },
}`,
ExpectedBazelTargets: []string{
makeBazelTargetHostOrDevice("custom", "foo", AttrNameToString{}, android.DeviceSupported),
},
},
{
Description: "host and device default, host only",
ModuleTypeUnderTest: "custom",
ModuleTypeUnderTestFactory: customModuleFactoryHostAndDeviceDefault,
Blueprint: `custom {
name: "foo",
device_supported: false,
bazel_module: { bp2build_available: true },
}`,
ExpectedBazelTargets: []string{
makeBazelTargetHostOrDevice("custom", "foo", AttrNameToString{}, android.HostSupported),
},
},
{
Description: "host and device default, neither",
ModuleTypeUnderTest: "custom",
ModuleTypeUnderTestFactory: customModuleFactoryHostAndDeviceDefault,
Blueprint: `custom {
name: "foo",
host_supported: false,
device_supported: false,
bazel_module: { bp2build_available: true },
}`,
ExpectedBazelTargets: []string{
MakeBazelTargetNoRestrictions("custom", "foo", AttrNameToString{
"target_compatible_with": `["@platforms//:incompatible"]`,
}),
},
},
}
for _, tc := range testCases {
t.Run(tc.Description, func(t *testing.T) {
RunBp2BuildTestCaseSimple(t, tc)
})
}
}
func TestLoadStatements(t *testing.T) {
testCases := []struct {
bazelTargets BazelTargets
expectedLoadStatements string
}{
{
bazelTargets: BazelTargets{
BazelTarget{
name: "foo",
ruleClass: "cc_library",
bzlLoadLocation: "//build/bazel/rules:cc.bzl",
},
},
expectedLoadStatements: `load("//build/bazel/rules:cc.bzl", "cc_library")`,
},
{
bazelTargets: BazelTargets{
BazelTarget{
name: "foo",
ruleClass: "cc_library",
bzlLoadLocation: "//build/bazel/rules:cc.bzl",
},
BazelTarget{
name: "bar",
ruleClass: "cc_library",
bzlLoadLocation: "//build/bazel/rules:cc.bzl",
},
},
expectedLoadStatements: `load("//build/bazel/rules:cc.bzl", "cc_library")`,
},
{
bazelTargets: BazelTargets{
BazelTarget{
name: "foo",
ruleClass: "cc_library",
bzlLoadLocation: "//build/bazel/rules:cc.bzl",
},
BazelTarget{
name: "bar",
ruleClass: "cc_binary",
bzlLoadLocation: "//build/bazel/rules:cc.bzl",
},
},
expectedLoadStatements: `load("//build/bazel/rules:cc.bzl", "cc_binary", "cc_library")`,
},
{
bazelTargets: BazelTargets{
BazelTarget{
name: "foo",
ruleClass: "cc_library",
bzlLoadLocation: "//build/bazel/rules:cc.bzl",
},
BazelTarget{
name: "bar",
ruleClass: "cc_binary",
bzlLoadLocation: "//build/bazel/rules:cc.bzl",
},
BazelTarget{
name: "baz",
ruleClass: "java_binary",
bzlLoadLocation: "//build/bazel/rules:java.bzl",
},
},
expectedLoadStatements: `load("//build/bazel/rules:cc.bzl", "cc_binary", "cc_library")
load("//build/bazel/rules:java.bzl", "java_binary")`,
},
{
bazelTargets: BazelTargets{
BazelTarget{
name: "foo",
ruleClass: "cc_binary",
bzlLoadLocation: "//build/bazel/rules:cc.bzl",
},
BazelTarget{
name: "bar",
ruleClass: "java_binary",
bzlLoadLocation: "//build/bazel/rules:java.bzl",
},
BazelTarget{
name: "baz",
ruleClass: "genrule",
// Note: no bzlLoadLocation for native rules
},
},
expectedLoadStatements: `load("//build/bazel/rules:cc.bzl", "cc_binary")
load("//build/bazel/rules:java.bzl", "java_binary")`,
},
}
for _, testCase := range testCases {
actual := testCase.bazelTargets.LoadStatements()
expected := testCase.expectedLoadStatements
if actual != expected {
t.Fatalf("Expected load statements to be %s, got %s", expected, actual)
}
}
}
func TestGenerateBazelTargetModules_OneToMany_LoadedFromStarlark(t *testing.T) {
testCases := []struct {
bp string
expectedBazelTarget string
expectedBazelTargetCount int
expectedLoadStatements string
}{
{
bp: `custom {
name: "bar",
host_supported: true,
one_to_many_prop: true,
bazel_module: { bp2build_available: true },
}`,
expectedBazelTarget: `my_library(
name = "bar",
)
proto_library(
name = "bar_proto_library_deps",
)
my_proto_library(
name = "bar_my_proto_library_deps",
)`,
expectedBazelTargetCount: 3,
expectedLoadStatements: `load("//build/bazel/rules:proto.bzl", "my_proto_library", "proto_library")
load("//build/bazel/rules:rules.bzl", "my_library")`,
},
}
dir := "."
for _, testCase := range testCases {
config := android.TestConfig(buildDir, nil, testCase.bp, nil)
ctx := android.NewTestContext(config)
ctx.RegisterModuleType("custom", customModuleFactoryHostAndDevice)
ctx.RegisterForBazelConversion()
_, errs := ctx.ParseFileList(dir, []string{"Android.bp"})
android.FailIfErrored(t, errs)
_, errs = ctx.ResolveDependencies(config)
android.FailIfErrored(t, errs)
codegenCtx := NewCodegenContext(config, ctx.Context, Bp2Build, "")
bazelTargets, err := generateBazelTargetsForDir(codegenCtx, dir)
android.FailIfErrored(t, err)
if actualCount := len(bazelTargets); actualCount != testCase.expectedBazelTargetCount {
t.Fatalf("Expected %d bazel target, got %d", testCase.expectedBazelTargetCount, actualCount)
}
actualBazelTargets := bazelTargets.String()
if actualBazelTargets != testCase.expectedBazelTarget {
t.Errorf(
"Expected generated Bazel target to be '%s', got '%s'",
testCase.expectedBazelTarget,
actualBazelTargets,
)
}
actualLoadStatements := bazelTargets.LoadStatements()
if actualLoadStatements != testCase.expectedLoadStatements {
t.Errorf(
"Expected generated load statements to be '%s', got '%s'",
testCase.expectedLoadStatements,
actualLoadStatements,
)
}
}
}
func TestModuleTypeBp2Build(t *testing.T) {
testCases := []Bp2buildTestCase{
{
Description: "filegroup with does not specify srcs",
ModuleTypeUnderTest: "filegroup",
ModuleTypeUnderTestFactory: android.FileGroupFactory,
Blueprint: `filegroup {
name: "fg_foo",
bazel_module: { bp2build_available: true },
}`,
ExpectedBazelTargets: []string{
MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{}),
},
},
{
Description: "filegroup with no srcs",
ModuleTypeUnderTest: "filegroup",
ModuleTypeUnderTestFactory: android.FileGroupFactory,
Blueprint: `filegroup {
name: "fg_foo",
srcs: [],
bazel_module: { bp2build_available: true },
}`,
ExpectedBazelTargets: []string{
MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{}),
},
},
{
Description: "filegroup with srcs",
ModuleTypeUnderTest: "filegroup",
ModuleTypeUnderTestFactory: android.FileGroupFactory,
Blueprint: `filegroup {
name: "fg_foo",
srcs: ["a", "b"],
bazel_module: { bp2build_available: true },
}`,
ExpectedBazelTargets: []string{
MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{
"srcs": `[
"a",
"b",
]`,
}),
},
},
{
Description: "filegroup with dot-slash-prefixed srcs",
ModuleTypeUnderTest: "filegroup",
ModuleTypeUnderTestFactory: android.FileGroupFactory,
Blueprint: `filegroup {
name: "fg_foo",
srcs: ["./a", "./b"],
bazel_module: { bp2build_available: true },
}`,
ExpectedBazelTargets: []string{
MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{
"srcs": `[
"a",
"b",
]`,
}),
},
},
{
Description: "filegroup with excludes srcs",
ModuleTypeUnderTest: "filegroup",
ModuleTypeUnderTestFactory: android.FileGroupFactory,
Blueprint: `filegroup {
name: "fg_foo",
srcs: ["a", "b"],
exclude_srcs: ["a"],
bazel_module: { bp2build_available: true },
}`,
ExpectedBazelTargets: []string{
MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{
"srcs": `["b"]`,
}),
},
},
{
Description: "depends_on_other_dir_module",
ModuleTypeUnderTest: "filegroup",
ModuleTypeUnderTestFactory: android.FileGroupFactory,
Blueprint: `filegroup {
name: "fg_foo",
srcs: [
":foo",
"c",
],
bazel_module: { bp2build_available: true },
}`,
Filesystem: map[string]string{
"other/Android.bp": `filegroup {
name: "foo",
srcs: ["a", "b"],
bazel_module: { bp2build_available: true },
}`,
},
ExpectedBazelTargets: []string{
MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{
"srcs": `[
"//other:foo",
"c",
]`,
}),
},
},
{
Description: "depends_on_other_unconverted_module_error",
ModuleTypeUnderTest: "filegroup",
ModuleTypeUnderTestFactory: android.FileGroupFactory,
UnconvertedDepsMode: errorModulesUnconvertedDeps,
Blueprint: `filegroup {
name: "foobar",
srcs: [
":foo",
"c",
],
bazel_module: { bp2build_available: true },
}`,
ExpectedErr: fmt.Errorf(`filegroup .:foobar depends on unconverted modules: foo`),
Filesystem: map[string]string{
"other/Android.bp": `filegroup {
name: "foo",
srcs: ["a", "b"],
}`,
},
},
{
Description: "depends_on_other_missing_module_error",
ModuleTypeUnderTest: "filegroup",
ModuleTypeUnderTestFactory: android.FileGroupFactory,
UnconvertedDepsMode: errorModulesUnconvertedDeps,
Blueprint: `filegroup {
name: "foobar",
srcs: [
"c",
"//other:foo",
"//other:goo",
],
bazel_module: { bp2build_available: true },
}`,
ExpectedErr: fmt.Errorf(`filegroup .:foobar depends on missing modules: //other:goo`),
Filesystem: map[string]string{"other/Android.bp": `filegroup {
name: "foo",
srcs: ["a"],
bazel_module: { bp2build_available: true },
}
`,
},
},
}
for _, testCase := range testCases {
t.Run(testCase.Description, func(t *testing.T) {
RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {}, testCase)
})
}
}
func TestAllowlistingBp2buildTargetsExplicitly(t *testing.T) {
testCases := []struct {
moduleTypeUnderTest string
moduleTypeUnderTestFactory android.ModuleFactory
bp string
expectedCount int
description string
}{
{
description: "explicitly unavailable",
moduleTypeUnderTest: "filegroup",
moduleTypeUnderTestFactory: android.FileGroupFactory,
bp: `filegroup {
name: "foo",
srcs: ["a", "b"],
bazel_module: { bp2build_available: false },
}`,
expectedCount: 0,
},
{
description: "implicitly unavailable",
moduleTypeUnderTest: "filegroup",
moduleTypeUnderTestFactory: android.FileGroupFactory,
bp: `filegroup {
name: "foo",
srcs: ["a", "b"],
}`,
expectedCount: 0,
},
{
description: "explicitly available",
moduleTypeUnderTest: "filegroup",
moduleTypeUnderTestFactory: android.FileGroupFactory,
bp: `filegroup {
name: "foo",
srcs: ["a", "b"],
bazel_module: { bp2build_available: true },
}`,
expectedCount: 1,
},
{
description: "generates more than 1 target if needed",
moduleTypeUnderTest: "custom",
moduleTypeUnderTestFactory: customModuleFactoryHostAndDevice,
bp: `custom {
name: "foo",
one_to_many_prop: true,
bazel_module: { bp2build_available: true },
}`,
expectedCount: 3,
},
}
dir := "."
for _, testCase := range testCases {
t.Run(testCase.description, func(t *testing.T) {
config := android.TestConfig(buildDir, nil, testCase.bp, nil)
ctx := android.NewTestContext(config)
ctx.RegisterModuleType(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestFactory)
ctx.RegisterForBazelConversion()
_, errs := ctx.ParseFileList(dir, []string{"Android.bp"})
android.FailIfErrored(t, errs)
_, errs = ctx.ResolveDependencies(config)
android.FailIfErrored(t, errs)
codegenCtx := NewCodegenContext(config, ctx.Context, Bp2Build, "")
bazelTargets, err := generateBazelTargetsForDir(codegenCtx, dir)
android.FailIfErrored(t, err)
if actualCount := len(bazelTargets); actualCount != testCase.expectedCount {
t.Fatalf("%s: Expected %d bazel target, got %d", testCase.description, testCase.expectedCount, actualCount)
}
})
}
}
func TestAllowlistingBp2buildTargetsWithConfig(t *testing.T) {
testCases := []struct {
moduleTypeUnderTest string
moduleTypeUnderTestFactory android.ModuleFactory
expectedCount map[string]int
description string
bp2buildConfig allowlists.Bp2BuildConfig
checkDir string
fs map[string]string
}{
{
description: "test bp2build config package and subpackages config",
moduleTypeUnderTest: "filegroup",
moduleTypeUnderTestFactory: android.FileGroupFactory,
expectedCount: map[string]int{
"migrated": 1,
"migrated/but_not_really": 0,
"migrated/but_not_really/but_really": 1,
"not_migrated": 0,
"also_not_migrated": 0,
},
bp2buildConfig: allowlists.Bp2BuildConfig{
"migrated": allowlists.Bp2BuildDefaultTrueRecursively,
"migrated/but_not_really": allowlists.Bp2BuildDefaultFalse,
"not_migrated": allowlists.Bp2BuildDefaultFalse,
},
fs: map[string]string{
"migrated/Android.bp": `filegroup { name: "a" }`,
"migrated/but_not_really/Android.bp": `filegroup { name: "b" }`,
"migrated/but_not_really/but_really/Android.bp": `filegroup { name: "c" }`,
"not_migrated/Android.bp": `filegroup { name: "d" }`,
"also_not_migrated/Android.bp": `filegroup { name: "e" }`,
},
},
{
description: "test bp2build config opt-in and opt-out",
moduleTypeUnderTest: "filegroup",
moduleTypeUnderTestFactory: android.FileGroupFactory,
expectedCount: map[string]int{
"package-opt-in": 2,
"package-opt-in/subpackage": 0,
"package-opt-out": 1,
"package-opt-out/subpackage": 0,
},
bp2buildConfig: allowlists.Bp2BuildConfig{
"package-opt-in": allowlists.Bp2BuildDefaultFalse,
"package-opt-out": allowlists.Bp2BuildDefaultTrueRecursively,
},
fs: map[string]string{
"package-opt-in/Android.bp": `
filegroup { name: "opt-in-a" }
filegroup { name: "opt-in-b", bazel_module: { bp2build_available: true } }
filegroup { name: "opt-in-c", bazel_module: { bp2build_available: true } }
`,
"package-opt-in/subpackage/Android.bp": `
filegroup { name: "opt-in-d" } // parent package not configured to DefaultTrueRecursively
`,
"package-opt-out/Android.bp": `
filegroup { name: "opt-out-a" }
filegroup { name: "opt-out-b", bazel_module: { bp2build_available: false } }
filegroup { name: "opt-out-c", bazel_module: { bp2build_available: false } }
`,
"package-opt-out/subpackage/Android.bp": `
filegroup { name: "opt-out-g", bazel_module: { bp2build_available: false } }
filegroup { name: "opt-out-h", bazel_module: { bp2build_available: false } }
`,
},
},
}
dir := "."
for _, testCase := range testCases {
fs := make(map[string][]byte)
toParse := []string{
"Android.bp",
}
for f, content := range testCase.fs {
if strings.HasSuffix(f, "Android.bp") {
toParse = append(toParse, f)
}
fs[f] = []byte(content)
}
config := android.TestConfig(buildDir, nil, "", fs)
ctx := android.NewTestContext(config)
ctx.RegisterModuleType(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestFactory)
allowlist := android.NewBp2BuildAllowlist().SetDefaultConfig(testCase.bp2buildConfig)
ctx.RegisterBp2BuildConfig(allowlist)
ctx.RegisterForBazelConversion()
_, errs := ctx.ParseFileList(dir, toParse)
android.FailIfErrored(t, errs)
_, errs = ctx.ResolveDependencies(config)
android.FailIfErrored(t, errs)
codegenCtx := NewCodegenContext(config, ctx.Context, Bp2Build, "")
// For each directory, test that the expected number of generated targets is correct.
for dir, expectedCount := range testCase.expectedCount {
bazelTargets, err := generateBazelTargetsForDir(codegenCtx, dir)
android.FailIfErrored(t, err)
if actualCount := len(bazelTargets); actualCount != expectedCount {
t.Fatalf(
"%s: Expected %d bazel target for %s package, got %d",
testCase.description,
expectedCount,
dir,
actualCount)
}
}
}
}
func TestCombineBuildFilesBp2buildTargets(t *testing.T) {
testCases := []Bp2buildTestCase{
{
Description: "filegroup bazel_module.label",
ModuleTypeUnderTest: "filegroup",
ModuleTypeUnderTestFactory: android.FileGroupFactory,
Blueprint: `filegroup {
name: "fg_foo",
bazel_module: { label: "//other:fg_foo" },
}`,
ExpectedBazelTargets: []string{},
Filesystem: map[string]string{
"other/BUILD.bazel": `// BUILD file`,
},
},
{
Description: "multiple bazel_module.label same BUILD",
ModuleTypeUnderTest: "filegroup",
ModuleTypeUnderTestFactory: android.FileGroupFactory,
Blueprint: `filegroup {
name: "fg_foo",
bazel_module: { label: "//other:fg_foo" },
}
filegroup {
name: "foo",
bazel_module: { label: "//other:foo" },
}`,
ExpectedBazelTargets: []string{},
Filesystem: map[string]string{
"other/BUILD.bazel": `// BUILD file`,
},
},
{
Description: "filegroup bazel_module.label and bp2build in subdir",
ModuleTypeUnderTest: "filegroup",
ModuleTypeUnderTestFactory: android.FileGroupFactory,
Dir: "other",
Blueprint: ``,
Filesystem: map[string]string{
"other/Android.bp": `filegroup {
name: "fg_foo",
bazel_module: {
bp2build_available: true,
},
}
filegroup {
name: "fg_bar",
bazel_module: {
label: "//other:fg_bar"
},
}`,
"other/BUILD.bazel": `// definition for fg_bar`,
},
ExpectedBazelTargets: []string{
MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{}),
},
},
{
Description: "filegroup bazel_module.label and filegroup bp2build",
ModuleTypeUnderTest: "filegroup",
ModuleTypeUnderTestFactory: android.FileGroupFactory,
Filesystem: map[string]string{
"other/BUILD.bazel": `// BUILD file`,
},
Blueprint: `filegroup {
name: "fg_foo",
bazel_module: {
label: "//other:fg_foo",
},
}
filegroup {
name: "fg_bar",
bazel_module: {
bp2build_available: true,
},
}`,
ExpectedBazelTargets: []string{
MakeBazelTargetNoRestrictions("filegroup", "fg_bar", map[string]string{}),
},
},
}
dir := "."
for _, testCase := range testCases {
t.Run(testCase.Description, func(t *testing.T) {
fs := make(map[string][]byte)
toParse := []string{
"Android.bp",
}
for f, content := range testCase.Filesystem {
if strings.HasSuffix(f, "Android.bp") {
toParse = append(toParse, f)
}
fs[f] = []byte(content)
}
config := android.TestConfig(buildDir, nil, testCase.Blueprint, fs)
ctx := android.NewTestContext(config)
ctx.RegisterModuleType(testCase.ModuleTypeUnderTest, testCase.ModuleTypeUnderTestFactory)
ctx.RegisterForBazelConversion()
_, errs := ctx.ParseFileList(dir, toParse)
if errored(t, testCase, errs) {
return
}
_, errs = ctx.ResolveDependencies(config)
if errored(t, testCase, errs) {
return
}
checkDir := dir
if testCase.Dir != "" {
checkDir = testCase.Dir
}
codegenCtx := NewCodegenContext(config, ctx.Context, Bp2Build, "")
bazelTargets, err := generateBazelTargetsForDir(codegenCtx, checkDir)
android.FailIfErrored(t, err)
bazelTargets.sort()
actualCount := len(bazelTargets)
expectedCount := len(testCase.ExpectedBazelTargets)
if actualCount != expectedCount {
t.Errorf("Expected %d bazel target, got %d\n%s", expectedCount, actualCount, bazelTargets)
}
for i, target := range bazelTargets {
actualContent := target.content
expectedContent := testCase.ExpectedBazelTargets[i]
if expectedContent != actualContent {
t.Errorf(
"Expected generated Bazel target to be '%s', got '%s'",
expectedContent,
actualContent,
)
}
}
})
}
}
func TestGlob(t *testing.T) {
testCases := []Bp2buildTestCase{
{
Description: "filegroup with glob",
ModuleTypeUnderTest: "filegroup",
ModuleTypeUnderTestFactory: android.FileGroupFactory,
Blueprint: `filegroup {
name: "fg_foo",
srcs: ["**/*.txt"],
bazel_module: { bp2build_available: true },
}`,
ExpectedBazelTargets: []string{
MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{
"srcs": `[
"other/a.txt",
"other/b.txt",
"other/subdir/a.txt",
]`,
}),
},
Filesystem: map[string]string{
"other/a.txt": "",
"other/b.txt": "",
"other/subdir/a.txt": "",
"other/file": "",
},
},
{
Description: "filegroup with glob in subdir",
ModuleTypeUnderTest: "filegroup",
ModuleTypeUnderTestFactory: android.FileGroupFactory,
Dir: "other",
Filesystem: map[string]string{
"other/Android.bp": `filegroup {
name: "fg_foo",
srcs: ["**/*.txt"],
bazel_module: { bp2build_available: true },
}`,
"other/a.txt": "",
"other/b.txt": "",
"other/subdir/a.txt": "",
"other/file": "",
},
ExpectedBazelTargets: []string{
MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{
"srcs": `[
"a.txt",
"b.txt",
"subdir/a.txt",
]`,
}),
},
},
{
Description: "filegroup with glob with no kept BUILD files",
ModuleTypeUnderTest: "filegroup",
ModuleTypeUnderTestFactory: android.FileGroupFactory,
KeepBuildFileForDirs: []string{
// empty
},
Blueprint: `filegroup {
name: "fg_foo",
srcs: ["**/*.txt"],
bazel_module: { bp2build_available: true },
}`,
Filesystem: map[string]string{
"a.txt": "",
"b.txt": "",
"foo/BUILD": "",
"foo/a.txt": "",
"foo/bar/BUILD": "",
"foo/bar/b.txt": "",
},
ExpectedBazelTargets: []string{
MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{
"srcs": `[
"a.txt",
"b.txt",
"foo/a.txt",
"foo/bar/b.txt",
]`,
}),
},
},
{
Description: "filegroup with glob with kept BUILD file",
ModuleTypeUnderTest: "filegroup",
ModuleTypeUnderTestFactory: android.FileGroupFactory,
KeepBuildFileForDirs: []string{
"foo",
},
Blueprint: `filegroup {
name: "fg_foo",
srcs: ["**/*.txt"],
bazel_module: { bp2build_available: true },
}`,
Filesystem: map[string]string{
"a.txt": "",
"b.txt": "",
"foo/BUILD": "",
"foo/a.txt": "",
"foo/bar/BUILD": "",
"foo/bar/b.txt": "",
},
ExpectedBazelTargets: []string{
MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{
"srcs": `[
"a.txt",
"b.txt",
"//foo:a.txt",
"//foo:bar/b.txt",
]`,
}),
},
},
{
Description: "filegroup with glob with kept BUILD.bazel file",
ModuleTypeUnderTest: "filegroup",
ModuleTypeUnderTestFactory: android.FileGroupFactory,
KeepBuildFileForDirs: []string{
"foo",
},
Blueprint: `filegroup {
name: "fg_foo",
srcs: ["**/*.txt"],
bazel_module: { bp2build_available: true },
}`,
Filesystem: map[string]string{
"a.txt": "",
"b.txt": "",
"foo/BUILD.bazel": "",
"foo/a.txt": "",
"foo/bar/BUILD.bazel": "",
"foo/bar/b.txt": "",
},
ExpectedBazelTargets: []string{
MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{
"srcs": `[
"a.txt",
"b.txt",
"//foo:a.txt",
"//foo:bar/b.txt",
]`,
}),
},
},
{
Description: "filegroup with glob with Android.bp file as boundary",
ModuleTypeUnderTest: "filegroup",
ModuleTypeUnderTestFactory: android.FileGroupFactory,
Blueprint: `filegroup {
name: "fg_foo",
srcs: ["**/*.txt"],
bazel_module: { bp2build_available: true },
}`,
Filesystem: map[string]string{
"a.txt": "",
"b.txt": "",
"foo/Android.bp": "",
"foo/a.txt": "",
"foo/bar/Android.bp": "",
"foo/bar/b.txt": "",
},
ExpectedBazelTargets: []string{
MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{
"srcs": `[
"a.txt",
"b.txt",
"//foo:a.txt",
"//foo/bar:b.txt",
]`,
}),
},
},
{
Description: "filegroup with glob in subdir with kept BUILD and BUILD.bazel file",
ModuleTypeUnderTest: "filegroup",
ModuleTypeUnderTestFactory: android.FileGroupFactory,
Dir: "other",
KeepBuildFileForDirs: []string{
"other/foo",
"other/foo/bar",
// deliberately not other/foo/baz/BUILD.
},
Filesystem: map[string]string{
"other/Android.bp": `filegroup {
name: "fg_foo",
srcs: ["**/*.txt"],
bazel_module: { bp2build_available: true },
}`,
"other/a.txt": "",
"other/b.txt": "",
"other/foo/BUILD": "",
"other/foo/a.txt": "",
"other/foo/bar/BUILD.bazel": "",
"other/foo/bar/b.txt": "",
"other/foo/baz/BUILD": "",
"other/foo/baz/c.txt": "",
},
ExpectedBazelTargets: []string{
MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{
"srcs": `[
"a.txt",
"b.txt",
"//other/foo:a.txt",
"//other/foo/bar:b.txt",
"//other/foo:baz/c.txt",
]`,
}),
},
},
}
for _, testCase := range testCases {
t.Run(testCase.Description, func(t *testing.T) {
RunBp2BuildTestCaseSimple(t, testCase)
})
}
}
func TestGlobExcludeSrcs(t *testing.T) {
testCases := []Bp2buildTestCase{
{
Description: "filegroup top level exclude_srcs",
ModuleTypeUnderTest: "filegroup",
ModuleTypeUnderTestFactory: android.FileGroupFactory,
Blueprint: `filegroup {
name: "fg_foo",
srcs: ["**/*.txt"],
exclude_srcs: ["c.txt"],
bazel_module: { bp2build_available: true },
}`,
Filesystem: map[string]string{
"a.txt": "",
"b.txt": "",
"c.txt": "",
"dir/Android.bp": "",
"dir/e.txt": "",
"dir/f.txt": "",
},
ExpectedBazelTargets: []string{
MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{
"srcs": `[
"a.txt",
"b.txt",
"//dir:e.txt",
"//dir:f.txt",
]`,
}),
},
},
{
Description: "filegroup in subdir exclude_srcs",
ModuleTypeUnderTest: "filegroup",
ModuleTypeUnderTestFactory: android.FileGroupFactory,
Blueprint: "",
Dir: "dir",
Filesystem: map[string]string{
"dir/Android.bp": `filegroup {
name: "fg_foo",
srcs: ["**/*.txt"],
exclude_srcs: ["b.txt"],
bazel_module: { bp2build_available: true },
}
`,
"dir/a.txt": "",
"dir/b.txt": "",
"dir/subdir/Android.bp": "",
"dir/subdir/e.txt": "",
"dir/subdir/f.txt": "",
},
ExpectedBazelTargets: []string{
MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{
"srcs": `[
"a.txt",
"//dir/subdir:e.txt",
"//dir/subdir:f.txt",
]`,
}),
},
},
}
for _, testCase := range testCases {
t.Run(testCase.Description, func(t *testing.T) {
RunBp2BuildTestCaseSimple(t, testCase)
})
}
}
func TestCommonBp2BuildModuleAttrs(t *testing.T) {
testCases := []Bp2buildTestCase{
{
Description: "Required into data test",
ModuleTypeUnderTest: "filegroup",
ModuleTypeUnderTestFactory: android.FileGroupFactory,
Blueprint: simpleModuleDoNotConvertBp2build("filegroup", "reqd") + `
filegroup {
name: "fg_foo",
required: ["reqd"],
bazel_module: { bp2build_available: true },
}`,
ExpectedBazelTargets: []string{
MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{
"data": `[":reqd"]`,
}),
},
},
{
Description: "Required into data test, cyclic self reference is filtered out",
ModuleTypeUnderTest: "filegroup",
ModuleTypeUnderTestFactory: android.FileGroupFactory,
Blueprint: simpleModuleDoNotConvertBp2build("filegroup", "reqd") + `
filegroup {
name: "fg_foo",
required: ["reqd", "fg_foo"],
bazel_module: { bp2build_available: true },
}`,
ExpectedBazelTargets: []string{
MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{
"data": `[":reqd"]`,
}),
},
},
{
Description: "Required via arch into data test",
ModuleTypeUnderTest: "python_library",
ModuleTypeUnderTestFactory: python.PythonLibraryFactory,
Blueprint: simpleModuleDoNotConvertBp2build("python_library", "reqdx86") +
simpleModuleDoNotConvertBp2build("python_library", "reqdarm") + `
python_library {
name: "fg_foo",
arch: {
arm: {
required: ["reqdarm"],
},
x86: {
required: ["reqdx86"],
},
},
bazel_module: { bp2build_available: true },
}`,
ExpectedBazelTargets: []string{
MakeBazelTarget("py_library", "fg_foo", map[string]string{
"data": `select({
"//build/bazel/platforms/arch:arm": [":reqdarm"],
"//build/bazel/platforms/arch:x86": [":reqdx86"],
"//conditions:default": [],
})`,
"srcs_version": `"PY3"`,
"imports": `["."]`,
}),
},
},
{
Description: "Required appended to data test",
ModuleTypeUnderTest: "python_library",
ModuleTypeUnderTestFactory: python.PythonLibraryFactory,
Filesystem: map[string]string{
"data.bin": "",
"src.py": "",
},
Blueprint: simpleModuleDoNotConvertBp2build("python_library", "reqd") + `
python_library {
name: "fg_foo",
data: ["data.bin"],
required: ["reqd"],
bazel_module: { bp2build_available: true },
}`,
ExpectedBazelTargets: []string{
MakeBazelTarget("py_library", "fg_foo", map[string]string{
"data": `[
"data.bin",
":reqd",
]`,
"srcs_version": `"PY3"`,
"imports": `["."]`,
}),
},
},
{
Description: "All props-to-attrs at once together test",
ModuleTypeUnderTest: "filegroup",
ModuleTypeUnderTestFactory: android.FileGroupFactory,
Blueprint: simpleModuleDoNotConvertBp2build("filegroup", "reqd") + `
filegroup {
name: "fg_foo",
required: ["reqd"],
bazel_module: { bp2build_available: true },
}`,
ExpectedBazelTargets: []string{
MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{
"data": `[":reqd"]`,
}),
},
},
}
for _, tc := range testCases {
t.Run(tc.Description, func(t *testing.T) {
RunBp2BuildTestCaseSimple(t, tc)
})
}
}
func TestLicensesAttrConversion(t *testing.T) {
RunBp2BuildTestCase(t,
func(ctx android.RegistrationContext) {
ctx.RegisterModuleType("license", android.LicenseFactory)
},
Bp2buildTestCase{
Description: "Test that licenses: attribute is converted",
ModuleTypeUnderTest: "filegroup",
ModuleTypeUnderTestFactory: android.FileGroupFactory,
Blueprint: `
license {
name: "my_license",
}
filegroup {
name: "my_filegroup",
licenses: ["my_license"],
}
`,
ExpectedBazelTargets: []string{
MakeBazelTargetNoRestrictions("filegroup", "my_filegroup", AttrNameToString{
"applicable_licenses": `[":my_license"]`,
}),
MakeBazelTargetNoRestrictions("android_license", "my_license", AttrNameToString{}),
},
})
}
func TestGenerateApiBazelTargets(t *testing.T) {
bp := `
custom {
name: "foo",
api: "foo.txt",
}
`
expectedBazelTarget := MakeBazelTarget(
"custom_api_contribution",
"foo",
AttrNameToString{
"api": `"foo.txt"`,
},
)
registerCustomModule := func(ctx android.RegistrationContext) {
ctx.RegisterModuleType("custom", customModuleFactoryHostAndDevice)
}
RunApiBp2BuildTestCase(t, registerCustomModule, Bp2buildTestCase{
Blueprint: bp,
ExpectedBazelTargets: []string{expectedBazelTarget},
Description: "Generating API contribution Bazel targets for custom module",
})
}