c639059fd8
Previously, it stored an android.Context (no pointer) which while it worked (because the current contents are themselves pointers) it is inconsistent with how the rest of the code references it and could cause weird behavior if additional fields were added to the Context. Test: m nothing m bp2build Change-Id: I9c70f925dde85e5b15431cc232b0c2eb6371ec6d
1879 lines
52 KiB
Go
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": [
|
|
"host.txt",
|
|
"linux.txt",
|
|
"glibc.txt",
|
|
"linux_glibc.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_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",
|
|
})
|
|
}
|