d078337796
This implements a number of in-place unit test changes to prepare for some fundamental changes to bp2build ("allowlist v2"). This will change bp2build so that rdeps of unconverted or missing modules will not be converted by bp2build. Bug: 301312260 Test: Unit tests Test: Unit tests, with a local copy of allowlist v2 on Change-Id: I8c8c0a24ba173e213fffcb0f8d7e99845705f4a7
2306 lines
63 KiB
Go
2306 lines
63 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/bazel"
|
|
"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: "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": `select({
|
|
"//build/bazel/product_config/config_settings:unbundled_build": [],
|
|
"//conditions:default": ["@platforms//:incompatible"],
|
|
})`,
|
|
}),
|
|
},
|
|
},
|
|
{
|
|
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",
|
|
loads: []BazelLoad{{
|
|
file: "//build/bazel/rules:cc.bzl",
|
|
symbols: []BazelLoadSymbol{{symbol: "cc_library"}},
|
|
}},
|
|
},
|
|
},
|
|
expectedLoadStatements: `load("//build/bazel/rules:cc.bzl", "cc_library")`,
|
|
},
|
|
{
|
|
bazelTargets: BazelTargets{
|
|
BazelTarget{
|
|
name: "foo",
|
|
ruleClass: "cc_library",
|
|
loads: []BazelLoad{{
|
|
file: "//build/bazel/rules:cc.bzl",
|
|
symbols: []BazelLoadSymbol{{symbol: "cc_library"}},
|
|
}},
|
|
},
|
|
BazelTarget{
|
|
name: "bar",
|
|
ruleClass: "cc_library",
|
|
loads: []BazelLoad{{
|
|
file: "//build/bazel/rules:cc.bzl",
|
|
symbols: []BazelLoadSymbol{{symbol: "cc_library"}},
|
|
}},
|
|
},
|
|
},
|
|
expectedLoadStatements: `load("//build/bazel/rules:cc.bzl", "cc_library")`,
|
|
},
|
|
{
|
|
bazelTargets: BazelTargets{
|
|
BazelTarget{
|
|
name: "foo",
|
|
ruleClass: "cc_library",
|
|
loads: []BazelLoad{{
|
|
file: "//build/bazel/rules:cc.bzl",
|
|
symbols: []BazelLoadSymbol{{symbol: "cc_library"}},
|
|
}},
|
|
},
|
|
BazelTarget{
|
|
name: "bar",
|
|
ruleClass: "cc_binary",
|
|
loads: []BazelLoad{{
|
|
file: "//build/bazel/rules:cc.bzl",
|
|
symbols: []BazelLoadSymbol{{symbol: "cc_binary"}},
|
|
}},
|
|
},
|
|
},
|
|
expectedLoadStatements: `load("//build/bazel/rules:cc.bzl", "cc_binary", "cc_library")`,
|
|
},
|
|
{
|
|
bazelTargets: BazelTargets{
|
|
BazelTarget{
|
|
name: "foo",
|
|
ruleClass: "cc_library",
|
|
loads: []BazelLoad{{
|
|
file: "//build/bazel/rules:cc.bzl",
|
|
symbols: []BazelLoadSymbol{{symbol: "cc_library"}},
|
|
}},
|
|
},
|
|
BazelTarget{
|
|
name: "bar",
|
|
ruleClass: "cc_binary",
|
|
loads: []BazelLoad{{
|
|
file: "//build/bazel/rules:cc.bzl",
|
|
symbols: []BazelLoadSymbol{{symbol: "cc_binary"}},
|
|
}},
|
|
},
|
|
BazelTarget{
|
|
name: "baz",
|
|
ruleClass: "java_binary",
|
|
loads: []BazelLoad{{
|
|
file: "//build/bazel/rules:java.bzl",
|
|
symbols: []BazelLoadSymbol{{symbol: "java_binary"}},
|
|
}},
|
|
},
|
|
},
|
|
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",
|
|
loads: []BazelLoad{{
|
|
file: "//build/bazel/rules:cc.bzl",
|
|
symbols: []BazelLoadSymbol{{symbol: "cc_binary"}},
|
|
}},
|
|
},
|
|
BazelTarget{
|
|
name: "bar",
|
|
ruleClass: "java_binary",
|
|
loads: []BazelLoad{{
|
|
file: "//build/bazel/rules:java.bzl",
|
|
symbols: []BazelLoadSymbol{{symbol: "java_binary"}},
|
|
}},
|
|
},
|
|
BazelTarget{
|
|
name: "baz",
|
|
ruleClass: "genrule",
|
|
// Note: no loads 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
|
|
forceEnabledModules []string
|
|
expectedErrorMessages []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 } }
|
|
`,
|
|
},
|
|
},
|
|
{
|
|
description: "test force-enabled errors out",
|
|
moduleTypeUnderTest: "filegroup",
|
|
moduleTypeUnderTestFactory: android.FileGroupFactory,
|
|
expectedCount: map[string]int{
|
|
"migrated": 0,
|
|
"not_migrated": 0,
|
|
},
|
|
bp2buildConfig: allowlists.Bp2BuildConfig{
|
|
"migrated/but_not_really": allowlists.Bp2BuildDefaultFalse,
|
|
"not_migrated": allowlists.Bp2BuildDefaultFalse,
|
|
},
|
|
fs: map[string]string{
|
|
"migrated/Android.bp": `filegroup { name: "a" }`,
|
|
},
|
|
forceEnabledModules: []string{"a"},
|
|
expectedErrorMessages: []string{"Force Enabled Module a not converted"},
|
|
},
|
|
}
|
|
|
|
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)
|
|
config.AddForceEnabledModules(testCase.forceEnabledModules)
|
|
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.CheckErrorsAgainstExpectations(t, err, testCase.expectedErrorMessages)
|
|
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,
|
|
StubbedBuildDefinitions: []string{"reqd"},
|
|
Blueprint: simpleModule("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,
|
|
StubbedBuildDefinitions: []string{"reqd"},
|
|
Blueprint: simpleModule("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,
|
|
StubbedBuildDefinitions: []string{"reqdx86", "reqdarm"},
|
|
Blueprint: simpleModule("python_library", "reqdx86") +
|
|
simpleModule("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": "",
|
|
},
|
|
StubbedBuildDefinitions: []string{"reqd"},
|
|
Blueprint: simpleModule("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,
|
|
StubbedBuildDefinitions: []string{"reqd"},
|
|
Blueprint: simpleModule("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 TestGenerateConfigSetting(t *testing.T) {
|
|
bp := `
|
|
custom {
|
|
name: "foo",
|
|
test_config_setting: true,
|
|
}
|
|
`
|
|
expectedBazelTargets := []string{
|
|
MakeBazelTargetNoRestrictions(
|
|
"config_setting",
|
|
"foo_config_setting",
|
|
AttrNameToString{
|
|
"flag_values": `{
|
|
"//build/bazel/rules/my_string_setting": "foo",
|
|
}`,
|
|
},
|
|
),
|
|
MakeBazelTarget(
|
|
"custom",
|
|
"foo",
|
|
AttrNameToString{},
|
|
),
|
|
}
|
|
registerCustomModule := func(ctx android.RegistrationContext) {
|
|
ctx.RegisterModuleType("custom", customModuleFactoryHostAndDevice)
|
|
}
|
|
RunBp2BuildTestCase(t, registerCustomModule, Bp2buildTestCase{
|
|
Blueprint: bp,
|
|
ExpectedBazelTargets: expectedBazelTargets,
|
|
Description: "Generating API contribution Bazel targets for custom module",
|
|
})
|
|
}
|
|
|
|
// If values of all keys in an axis are equal to //conditions:default, drop the axis and print the common value
|
|
func TestPrettyPrintSelectMapEqualValues(t *testing.T) {
|
|
lla := bazel.LabelListAttribute{
|
|
Value: bazel.LabelList{},
|
|
}
|
|
libFooImplLabel := bazel.Label{
|
|
Label: ":libfoo.impl",
|
|
}
|
|
lla.SetSelectValue(bazel.OsAndInApexAxis, bazel.AndroidPlatform, bazel.MakeLabelList([]bazel.Label{libFooImplLabel}))
|
|
lla.SetSelectValue(bazel.OsAndInApexAxis, bazel.ConditionsDefaultConfigKey, bazel.MakeLabelList([]bazel.Label{libFooImplLabel}))
|
|
actual, _ := prettyPrintAttribute(lla, 0)
|
|
android.AssertStringEquals(t, "Print the common value if all keys in an axis have the same value", `[":libfoo.impl"]`, actual)
|
|
}
|
|
|
|
func TestAlreadyPresentBuildTarget(t *testing.T) {
|
|
bp := `
|
|
custom {
|
|
name: "foo",
|
|
}
|
|
custom {
|
|
name: "bar",
|
|
}
|
|
`
|
|
alreadyPresentBuildFile :=
|
|
MakeBazelTarget(
|
|
"custom",
|
|
"foo",
|
|
AttrNameToString{},
|
|
)
|
|
expectedBazelTargets := []string{
|
|
MakeBazelTarget(
|
|
"custom",
|
|
"bar",
|
|
AttrNameToString{},
|
|
),
|
|
}
|
|
registerCustomModule := func(ctx android.RegistrationContext) {
|
|
ctx.RegisterModuleType("custom", customModuleFactoryHostAndDevice)
|
|
}
|
|
RunBp2BuildTestCase(t, registerCustomModule, Bp2buildTestCase{
|
|
AlreadyExistingBuildContents: alreadyPresentBuildFile,
|
|
Blueprint: bp,
|
|
ExpectedBazelTargets: expectedBazelTargets,
|
|
Description: "Not duplicating work for an already-present BUILD target.",
|
|
})
|
|
}
|
|
|
|
func TestAlreadyPresentOneToManyBuildTarget(t *testing.T) {
|
|
bp := `
|
|
custom {
|
|
name: "foo",
|
|
one_to_many_prop: true,
|
|
}
|
|
custom {
|
|
name: "bar",
|
|
}
|
|
`
|
|
alreadyPresentBuildFile :=
|
|
MakeBazelTarget(
|
|
"custom",
|
|
// one_to_many_prop ensures that foo generates "foo_proto_library_deps".
|
|
"foo_proto_library_deps",
|
|
AttrNameToString{},
|
|
)
|
|
expectedBazelTargets := []string{
|
|
MakeBazelTarget(
|
|
"custom",
|
|
"bar",
|
|
AttrNameToString{},
|
|
),
|
|
}
|
|
registerCustomModule := func(ctx android.RegistrationContext) {
|
|
ctx.RegisterModuleType("custom", customModuleFactoryHostAndDevice)
|
|
}
|
|
RunBp2BuildTestCase(t, registerCustomModule, Bp2buildTestCase{
|
|
AlreadyExistingBuildContents: alreadyPresentBuildFile,
|
|
Blueprint: bp,
|
|
ExpectedBazelTargets: expectedBazelTargets,
|
|
Description: "Not duplicating work for an already-present BUILD target (different generated name)",
|
|
})
|
|
}
|
|
|
|
// Verifies that if a module is defined in pkg1/Android.bp, that a target present
|
|
// in pkg2/BUILD.bazel does not result in the module being labeled "already defined
|
|
// in a BUILD file".
|
|
func TestBuildTargetPresentOtherDirectory(t *testing.T) {
|
|
bp := `
|
|
custom {
|
|
name: "foo",
|
|
}
|
|
`
|
|
expectedBazelTargets := []string{
|
|
MakeBazelTarget(
|
|
"custom",
|
|
"foo",
|
|
AttrNameToString{},
|
|
),
|
|
}
|
|
registerCustomModule := func(ctx android.RegistrationContext) {
|
|
ctx.RegisterModuleType("custom", customModuleFactoryHostAndDevice)
|
|
}
|
|
RunBp2BuildTestCase(t, registerCustomModule, Bp2buildTestCase{
|
|
KeepBuildFileForDirs: []string{"other_pkg"},
|
|
Filesystem: map[string]string{
|
|
"other_pkg/BUILD.bazel": MakeBazelTarget("custom", "foo", AttrNameToString{}),
|
|
},
|
|
Blueprint: bp,
|
|
ExpectedBazelTargets: expectedBazelTargets,
|
|
Description: "Not treating a BUILD target as the bazel definition for a module in another package",
|
|
})
|
|
}
|
|
|
|
// If CommonAttributes.Dir is set, the bazel target should be created in that dir
|
|
func TestCreateBazelTargetInDifferentDir(t *testing.T) {
|
|
t.Parallel()
|
|
bp := `
|
|
custom {
|
|
name: "foo",
|
|
dir: "subdir",
|
|
}
|
|
`
|
|
registerCustomModule := func(ctx android.RegistrationContext) {
|
|
ctx.RegisterModuleType("custom", customModuleFactoryHostAndDevice)
|
|
}
|
|
// Check that foo is not created in root dir
|
|
RunBp2BuildTestCase(t, registerCustomModule, Bp2buildTestCase{
|
|
Description: "foo is not created in root dir because it sets dir explicitly",
|
|
Blueprint: bp,
|
|
Filesystem: map[string]string{
|
|
"subdir/Android.bp": "",
|
|
},
|
|
ExpectedBazelTargets: []string{},
|
|
})
|
|
// Check that foo is created in `subdir`
|
|
RunBp2BuildTestCase(t, registerCustomModule, Bp2buildTestCase{
|
|
Description: "foo is created in `subdir` because it sets dir explicitly",
|
|
Blueprint: bp,
|
|
Filesystem: map[string]string{
|
|
"subdir/Android.bp": "",
|
|
},
|
|
Dir: "subdir",
|
|
ExpectedBazelTargets: []string{
|
|
MakeBazelTarget("custom", "foo", AttrNameToString{}),
|
|
},
|
|
})
|
|
// Check that we cannot create target in different dir if it is does not an Android.bp
|
|
RunBp2BuildTestCase(t, registerCustomModule, Bp2buildTestCase{
|
|
Description: "foo cannot be created in `subdir` because it does not contain an Android.bp file",
|
|
Blueprint: bp,
|
|
Dir: "subdir",
|
|
ExpectedErr: fmt.Errorf("Cannot use ca.Dir to create a BazelTarget in dir: subdir since it does not contain an Android.bp file"),
|
|
})
|
|
|
|
}
|
|
|
|
func TestBp2buildDepsMutator_missingTransitiveDep(t *testing.T) {
|
|
bp := `
|
|
custom {
|
|
name: "foo",
|
|
}
|
|
|
|
custom {
|
|
name: "has_deps",
|
|
arch_paths: [":has_missing_dep", ":foo"],
|
|
}
|
|
|
|
custom {
|
|
name: "has_missing_dep",
|
|
arch_paths: [":missing"],
|
|
}
|
|
`
|
|
expectedBazelTargets := []string{
|
|
MakeBazelTarget(
|
|
"custom",
|
|
"foo",
|
|
AttrNameToString{},
|
|
),
|
|
}
|
|
registerCustomModule := func(ctx android.RegistrationContext) {
|
|
ctx.RegisterModuleType("custom", customModuleFactoryHostAndDevice)
|
|
}
|
|
RunBp2BuildTestCase(t, registerCustomModule, Bp2buildTestCase{
|
|
Blueprint: bp,
|
|
ExpectedBazelTargets: expectedBazelTargets,
|
|
Description: "Skipping conversion of a target with missing transitive dep",
|
|
DepsMutator: true,
|
|
})
|
|
}
|
|
|
|
func TestBp2buildDepsMutator_missingDirectDep(t *testing.T) {
|
|
bp := `
|
|
custom {
|
|
name: "foo",
|
|
arch_paths: [":exists"],
|
|
}
|
|
custom {
|
|
name: "exists",
|
|
}
|
|
|
|
custom {
|
|
name: "has_missing_dep",
|
|
arch_paths: [":missing"],
|
|
}
|
|
`
|
|
expectedBazelTargets := []string{
|
|
MakeBazelTarget(
|
|
"custom",
|
|
"foo",
|
|
AttrNameToString{"arch_paths": `[":exists"]`},
|
|
),
|
|
MakeBazelTarget(
|
|
"custom",
|
|
"exists",
|
|
AttrNameToString{},
|
|
),
|
|
}
|
|
registerCustomModule := func(ctx android.RegistrationContext) {
|
|
ctx.RegisterModuleType("custom", customModuleFactoryHostAndDevice)
|
|
}
|
|
RunBp2BuildTestCase(t, registerCustomModule, Bp2buildTestCase{
|
|
Blueprint: bp,
|
|
ExpectedBazelTargets: expectedBazelTargets,
|
|
Description: "Skipping conversion of a target with missing direct dep",
|
|
DepsMutator: true,
|
|
})
|
|
}
|
|
|
|
func TestBp2buildDepsMutator_unconvertedDirectDep(t *testing.T) {
|
|
bp := `
|
|
custom {
|
|
name: "has_unconverted_dep",
|
|
arch_paths: [":unconvertible"],
|
|
}
|
|
|
|
custom {
|
|
name: "unconvertible",
|
|
does_not_convert_to_bazel: true
|
|
}
|
|
`
|
|
registerCustomModule := func(ctx android.RegistrationContext) {
|
|
ctx.RegisterModuleType("custom", customModuleFactoryHostAndDevice)
|
|
}
|
|
RunBp2BuildTestCase(t, registerCustomModule, Bp2buildTestCase{
|
|
Blueprint: bp,
|
|
ExpectedBazelTargets: []string{},
|
|
Description: "Skipping conversion of a target with unconverted direct dep",
|
|
DepsMutator: true,
|
|
})
|
|
}
|
|
|
|
func TestBp2buildDepsMutator_unconvertedTransitiveDep(t *testing.T) {
|
|
bp := `
|
|
custom {
|
|
name: "foo",
|
|
arch_paths: [":has_unconverted_dep", ":bar"],
|
|
}
|
|
|
|
custom {
|
|
name: "bar",
|
|
}
|
|
|
|
custom {
|
|
name: "has_unconverted_dep",
|
|
arch_paths: [":unconvertible"],
|
|
}
|
|
|
|
custom {
|
|
name: "unconvertible",
|
|
does_not_convert_to_bazel: true
|
|
}
|
|
`
|
|
expectedBazelTargets := []string{
|
|
MakeBazelTarget(
|
|
"custom",
|
|
"bar",
|
|
AttrNameToString{},
|
|
),
|
|
}
|
|
registerCustomModule := func(ctx android.RegistrationContext) {
|
|
ctx.RegisterModuleType("custom", customModuleFactoryHostAndDevice)
|
|
}
|
|
RunBp2BuildTestCase(t, registerCustomModule, Bp2buildTestCase{
|
|
Blueprint: bp,
|
|
ExpectedBazelTargets: expectedBazelTargets,
|
|
Description: "Skipping conversion of a target with unconverted transitive dep",
|
|
DepsMutator: true,
|
|
})
|
|
}
|
|
|
|
func TestBp2buildDepsMutator_alreadyExistsBuildDeps(t *testing.T) {
|
|
bp := `
|
|
custom {
|
|
name: "foo",
|
|
arch_paths: [":bar"],
|
|
}
|
|
custom {
|
|
name: "bar",
|
|
arch_paths: [":checked_in"],
|
|
}
|
|
custom {
|
|
name: "checked_in",
|
|
arch_paths: [":checked_in"],
|
|
does_not_convert_to_bazel: true
|
|
}
|
|
`
|
|
expectedBazelTargets := []string{
|
|
MakeBazelTarget(
|
|
"custom",
|
|
"foo",
|
|
AttrNameToString{"arch_paths": `[":bar"]`},
|
|
),
|
|
MakeBazelTarget(
|
|
"custom",
|
|
"bar",
|
|
AttrNameToString{"arch_paths": `[":checked_in"]`},
|
|
),
|
|
}
|
|
registerCustomModule := func(ctx android.RegistrationContext) {
|
|
ctx.RegisterModuleType("custom", customModuleFactoryHostAndDevice)
|
|
}
|
|
RunBp2BuildTestCase(t, registerCustomModule, Bp2buildTestCase{
|
|
StubbedBuildDefinitions: []string{"checked_in"},
|
|
Blueprint: bp,
|
|
ExpectedBazelTargets: expectedBazelTargets,
|
|
Description: "Convert target with already-existing build dep",
|
|
DepsMutator: true,
|
|
})
|
|
}
|
|
|
|
// Tests that deps of libc are always considered valid for libc. This circumvents
|
|
// an issue that, in a variantless graph (such as bp2build's), libc has the
|
|
// unique predicament that it depends on itself.
|
|
func TestBp2buildDepsMutator_depOnLibc(t *testing.T) {
|
|
bp := `
|
|
custom {
|
|
name: "foo",
|
|
arch_paths: [":libc"],
|
|
}
|
|
custom {
|
|
name: "libc",
|
|
arch_paths: [":libc_dep"],
|
|
}
|
|
custom {
|
|
name: "libc_dep",
|
|
does_not_convert_to_bazel: true
|
|
}
|
|
`
|
|
expectedBazelTargets := []string{
|
|
MakeBazelTarget(
|
|
"custom",
|
|
"foo",
|
|
AttrNameToString{"arch_paths": `[":libc"]`},
|
|
),
|
|
MakeBazelTarget(
|
|
"custom",
|
|
"libc",
|
|
AttrNameToString{"arch_paths": `[":libc_dep"]`},
|
|
),
|
|
}
|
|
registerCustomModule := func(ctx android.RegistrationContext) {
|
|
ctx.RegisterModuleType("custom", customModuleFactoryHostAndDevice)
|
|
}
|
|
RunBp2BuildTestCase(t, registerCustomModule, Bp2buildTestCase{
|
|
StubbedBuildDefinitions: []string{"checked_in"},
|
|
Blueprint: bp,
|
|
ExpectedBazelTargets: expectedBazelTargets,
|
|
Description: "Convert target with dep on libc",
|
|
DepsMutator: true,
|
|
})
|
|
}
|