with the same name. Also add capability to test for errors raised in bp2build mutators / contexts. This CL does two things to filegroups: 1) If the filegroup has only 1 source file with the same name as itself, don't generate a filegroup target. Instead, dependents will depend directly on the Bazel file target instead. 2) If the filegroup has more than 1 source file and 1 of them has the same name as itself, the bp2build mutator will error out. If bp2build on CI passes, it means that the source tree / product we're testing against does not have such a case (which seems to be true for most source trees). Either way, this will allow us to be unblocked for most of the errant filegroups (case 1) in the tree. Test: CI Test: New test cases in filegroup_conversion_test.go Fixes: 194762573 Change-Id: I830c53efc8808569afe3c5f9f08436855bcdafed
1608 lines
44 KiB
Go
1608 lines
44 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 (
|
|
"android/soong/android"
|
|
"android/soong/genrule"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
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,
|
|
)`,
|
|
},
|
|
{
|
|
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,
|
|
)`,
|
|
},
|
|
{
|
|
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\\\\",
|
|
)`,
|
|
},
|
|
{
|
|
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"],
|
|
)`,
|
|
},
|
|
{
|
|
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,
|
|
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"],
|
|
}],
|
|
)`,
|
|
},
|
|
{
|
|
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"],
|
|
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", customModuleFactory)
|
|
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 := generateBazelTargetsForDir(codegenCtx, dir)
|
|
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{
|
|
{
|
|
blueprint: `custom {
|
|
name: "foo",
|
|
string_list_prop: ["a", "b"],
|
|
string_prop: "a",
|
|
bazel_module: { bp2build_available: true },
|
|
}`,
|
|
expectedBazelTargets: []string{`custom(
|
|
name = "foo",
|
|
string_list_prop = [
|
|
"a",
|
|
"b",
|
|
],
|
|
string_prop = "a",
|
|
)`,
|
|
},
|
|
},
|
|
{
|
|
blueprint: `custom {
|
|
name: "control_characters",
|
|
string_list_prop: ["\t", "\n"],
|
|
string_prop: "a\t\n\r",
|
|
bazel_module: { bp2build_available: true },
|
|
}`,
|
|
expectedBazelTargets: []string{`custom(
|
|
name = "control_characters",
|
|
string_list_prop = [
|
|
"\t",
|
|
"\n",
|
|
],
|
|
string_prop = "a\t\n\r",
|
|
)`,
|
|
},
|
|
},
|
|
{
|
|
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{`custom(
|
|
name = "dep",
|
|
arch_paths = ["abc"],
|
|
)`,
|
|
`custom(
|
|
name = "has_dep",
|
|
arch_paths = [":dep"],
|
|
)`,
|
|
},
|
|
},
|
|
{
|
|
blueprint: `custom {
|
|
name: "arch_paths",
|
|
arch: {
|
|
x86: {
|
|
arch_paths: ["abc"],
|
|
},
|
|
},
|
|
bazel_module: { bp2build_available: true },
|
|
}`,
|
|
expectedBazelTargets: []string{`custom(
|
|
name = "arch_paths",
|
|
arch_paths = select({
|
|
"//build/bazel/platforms/arch:x86": ["abc"],
|
|
"//conditions:default": [],
|
|
}),
|
|
)`,
|
|
},
|
|
},
|
|
{
|
|
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{`custom(
|
|
name = "dep",
|
|
arch_paths = ["abc"],
|
|
)`,
|
|
`custom(
|
|
name = "has_dep",
|
|
arch_paths = select({
|
|
"//build/bazel/platforms/arch:x86": [":dep"],
|
|
"//conditions:default": [],
|
|
}),
|
|
)`,
|
|
},
|
|
},
|
|
}
|
|
|
|
dir := "."
|
|
for _, testCase := range testCases {
|
|
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) {
|
|
continue
|
|
}
|
|
_, errs = ctx.ResolveDependencies(config)
|
|
if errored(t, testCase, errs) {
|
|
continue
|
|
}
|
|
|
|
codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
|
|
bazelTargets := generateBazelTargetsForDir(codegenCtx, dir)
|
|
|
|
if actualCount, expectedCount := len(bazelTargets), len(testCase.expectedBazelTargets); actualCount != expectedCount {
|
|
t.Errorf("Expected %d bazel target, got %d", expectedCount, actualCount)
|
|
} 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 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",
|
|
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", customModuleFactory)
|
|
ctx.RegisterBp2BuildMutator("custom", customBp2BuildMutatorFromStarlark)
|
|
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 := generateBazelTargetsForDir(codegenCtx, dir)
|
|
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) {
|
|
otherGenruleBp := map[string]string{
|
|
"other/Android.bp": `genrule {
|
|
name: "foo.tool",
|
|
out: ["foo_tool.out"],
|
|
srcs: ["foo_tool.in"],
|
|
cmd: "cp $(in) $(out)",
|
|
}
|
|
genrule {
|
|
name: "other.tool",
|
|
out: ["other_tool.out"],
|
|
srcs: ["other_tool.in"],
|
|
cmd: "cp $(in) $(out)",
|
|
}`,
|
|
}
|
|
|
|
testCases := []bp2buildTestCase{
|
|
{
|
|
description: "filegroup with does not specify srcs",
|
|
moduleTypeUnderTest: "filegroup",
|
|
moduleTypeUnderTestFactory: android.FileGroupFactory,
|
|
moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
|
|
blueprint: `filegroup {
|
|
name: "fg_foo",
|
|
bazel_module: { bp2build_available: true },
|
|
}`,
|
|
expectedBazelTargets: []string{
|
|
`filegroup(
|
|
name = "fg_foo",
|
|
)`,
|
|
},
|
|
},
|
|
{
|
|
description: "filegroup with no srcs",
|
|
moduleTypeUnderTest: "filegroup",
|
|
moduleTypeUnderTestFactory: android.FileGroupFactory,
|
|
moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
|
|
blueprint: `filegroup {
|
|
name: "fg_foo",
|
|
srcs: [],
|
|
bazel_module: { bp2build_available: true },
|
|
}`,
|
|
expectedBazelTargets: []string{
|
|
`filegroup(
|
|
name = "fg_foo",
|
|
)`,
|
|
},
|
|
},
|
|
{
|
|
description: "filegroup with srcs",
|
|
moduleTypeUnderTest: "filegroup",
|
|
moduleTypeUnderTestFactory: android.FileGroupFactory,
|
|
moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
|
|
blueprint: `filegroup {
|
|
name: "fg_foo",
|
|
srcs: ["a", "b"],
|
|
bazel_module: { bp2build_available: true },
|
|
}`,
|
|
expectedBazelTargets: []string{`filegroup(
|
|
name = "fg_foo",
|
|
srcs = [
|
|
"a",
|
|
"b",
|
|
],
|
|
)`,
|
|
},
|
|
},
|
|
{
|
|
description: "filegroup with excludes srcs",
|
|
moduleTypeUnderTest: "filegroup",
|
|
moduleTypeUnderTestFactory: android.FileGroupFactory,
|
|
moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
|
|
blueprint: `filegroup {
|
|
name: "fg_foo",
|
|
srcs: ["a", "b"],
|
|
exclude_srcs: ["a"],
|
|
bazel_module: { bp2build_available: true },
|
|
}`,
|
|
expectedBazelTargets: []string{`filegroup(
|
|
name = "fg_foo",
|
|
srcs = ["b"],
|
|
)`,
|
|
},
|
|
},
|
|
{
|
|
description: "filegroup with glob",
|
|
moduleTypeUnderTest: "filegroup",
|
|
moduleTypeUnderTestFactory: android.FileGroupFactory,
|
|
moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
|
|
blueprint: `filegroup {
|
|
name: "foo",
|
|
srcs: ["**/*.txt"],
|
|
bazel_module: { bp2build_available: true },
|
|
}`,
|
|
expectedBazelTargets: []string{`filegroup(
|
|
name = "foo",
|
|
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,
|
|
moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
|
|
blueprint: `filegroup {
|
|
name: "foo",
|
|
srcs: ["a.txt"],
|
|
bazel_module: { bp2build_available: true },
|
|
}`,
|
|
dir: "other",
|
|
expectedBazelTargets: []string{`filegroup(
|
|
name = "fg_foo",
|
|
srcs = [
|
|
"a.txt",
|
|
"b.txt",
|
|
"subdir/a.txt",
|
|
],
|
|
)`,
|
|
},
|
|
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": "",
|
|
},
|
|
},
|
|
{
|
|
description: "depends_on_other_dir_module",
|
|
moduleTypeUnderTest: "filegroup",
|
|
moduleTypeUnderTestFactory: android.FileGroupFactory,
|
|
moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
|
|
blueprint: `filegroup {
|
|
name: "foobar",
|
|
srcs: [
|
|
":foo",
|
|
"c",
|
|
],
|
|
bazel_module: { bp2build_available: true },
|
|
}`,
|
|
expectedBazelTargets: []string{`filegroup(
|
|
name = "foobar",
|
|
srcs = [
|
|
"//other:foo",
|
|
"c",
|
|
],
|
|
)`,
|
|
},
|
|
filesystem: map[string]string{
|
|
"other/Android.bp": `filegroup {
|
|
name: "foo",
|
|
srcs: ["a", "b"],
|
|
}`,
|
|
},
|
|
},
|
|
{
|
|
description: "genrule with command line variable replacements",
|
|
moduleTypeUnderTest: "genrule",
|
|
moduleTypeUnderTestFactory: genrule.GenRuleFactory,
|
|
moduleTypeUnderTestBp2BuildMutator: genrule.GenruleBp2Build,
|
|
blueprint: `genrule {
|
|
name: "foo.tool",
|
|
out: ["foo_tool.out"],
|
|
srcs: ["foo_tool.in"],
|
|
cmd: "cp $(in) $(out)",
|
|
bazel_module: { bp2build_available: true },
|
|
}
|
|
|
|
genrule {
|
|
name: "foo",
|
|
out: ["foo.out"],
|
|
srcs: ["foo.in"],
|
|
tools: [":foo.tool"],
|
|
cmd: "$(location :foo.tool) --genDir=$(genDir) arg $(in) $(out)",
|
|
bazel_module: { bp2build_available: true },
|
|
}`,
|
|
expectedBazelTargets: []string{
|
|
`genrule(
|
|
name = "foo",
|
|
cmd = "$(location :foo.tool) --genDir=$(GENDIR) arg $(SRCS) $(OUTS)",
|
|
outs = ["foo.out"],
|
|
srcs = ["foo.in"],
|
|
tools = [":foo.tool"],
|
|
)`,
|
|
`genrule(
|
|
name = "foo.tool",
|
|
cmd = "cp $(SRCS) $(OUTS)",
|
|
outs = ["foo_tool.out"],
|
|
srcs = ["foo_tool.in"],
|
|
)`,
|
|
},
|
|
},
|
|
{
|
|
description: "genrule using $(locations :label)",
|
|
moduleTypeUnderTest: "genrule",
|
|
moduleTypeUnderTestFactory: genrule.GenRuleFactory,
|
|
moduleTypeUnderTestBp2BuildMutator: genrule.GenruleBp2Build,
|
|
blueprint: `genrule {
|
|
name: "foo.tools",
|
|
out: ["foo_tool.out", "foo_tool2.out"],
|
|
srcs: ["foo_tool.in"],
|
|
cmd: "cp $(in) $(out)",
|
|
bazel_module: { bp2build_available: true },
|
|
}
|
|
|
|
genrule {
|
|
name: "foo",
|
|
out: ["foo.out"],
|
|
srcs: ["foo.in"],
|
|
tools: [":foo.tools"],
|
|
cmd: "$(locations :foo.tools) -s $(out) $(in)",
|
|
bazel_module: { bp2build_available: true },
|
|
}`,
|
|
expectedBazelTargets: []string{`genrule(
|
|
name = "foo",
|
|
cmd = "$(locations :foo.tools) -s $(OUTS) $(SRCS)",
|
|
outs = ["foo.out"],
|
|
srcs = ["foo.in"],
|
|
tools = [":foo.tools"],
|
|
)`,
|
|
`genrule(
|
|
name = "foo.tools",
|
|
cmd = "cp $(SRCS) $(OUTS)",
|
|
outs = [
|
|
"foo_tool.out",
|
|
"foo_tool2.out",
|
|
],
|
|
srcs = ["foo_tool.in"],
|
|
)`,
|
|
},
|
|
},
|
|
{
|
|
description: "genrule using $(locations //absolute:label)",
|
|
moduleTypeUnderTest: "genrule",
|
|
moduleTypeUnderTestFactory: genrule.GenRuleFactory,
|
|
moduleTypeUnderTestBp2BuildMutator: genrule.GenruleBp2Build,
|
|
blueprint: `genrule {
|
|
name: "foo",
|
|
out: ["foo.out"],
|
|
srcs: ["foo.in"],
|
|
tool_files: [":foo.tool"],
|
|
cmd: "$(locations :foo.tool) -s $(out) $(in)",
|
|
bazel_module: { bp2build_available: true },
|
|
}`,
|
|
expectedBazelTargets: []string{`genrule(
|
|
name = "foo",
|
|
cmd = "$(locations //other:foo.tool) -s $(OUTS) $(SRCS)",
|
|
outs = ["foo.out"],
|
|
srcs = ["foo.in"],
|
|
tools = ["//other:foo.tool"],
|
|
)`,
|
|
},
|
|
filesystem: otherGenruleBp,
|
|
},
|
|
{
|
|
description: "genrule srcs using $(locations //absolute:label)",
|
|
moduleTypeUnderTest: "genrule",
|
|
moduleTypeUnderTestFactory: genrule.GenRuleFactory,
|
|
moduleTypeUnderTestBp2BuildMutator: genrule.GenruleBp2Build,
|
|
blueprint: `genrule {
|
|
name: "foo",
|
|
out: ["foo.out"],
|
|
srcs: [":other.tool"],
|
|
tool_files: [":foo.tool"],
|
|
cmd: "$(locations :foo.tool) -s $(out) $(location :other.tool)",
|
|
bazel_module: { bp2build_available: true },
|
|
}`,
|
|
expectedBazelTargets: []string{`genrule(
|
|
name = "foo",
|
|
cmd = "$(locations //other:foo.tool) -s $(OUTS) $(location //other:other.tool)",
|
|
outs = ["foo.out"],
|
|
srcs = ["//other:other.tool"],
|
|
tools = ["//other:foo.tool"],
|
|
)`,
|
|
},
|
|
filesystem: otherGenruleBp,
|
|
},
|
|
{
|
|
description: "genrule using $(location) label should substitute first tool label automatically",
|
|
moduleTypeUnderTest: "genrule",
|
|
moduleTypeUnderTestFactory: genrule.GenRuleFactory,
|
|
moduleTypeUnderTestBp2BuildMutator: genrule.GenruleBp2Build,
|
|
blueprint: `genrule {
|
|
name: "foo",
|
|
out: ["foo.out"],
|
|
srcs: ["foo.in"],
|
|
tool_files: [":foo.tool", ":other.tool"],
|
|
cmd: "$(location) -s $(out) $(in)",
|
|
bazel_module: { bp2build_available: true },
|
|
}`,
|
|
expectedBazelTargets: []string{`genrule(
|
|
name = "foo",
|
|
cmd = "$(location //other:foo.tool) -s $(OUTS) $(SRCS)",
|
|
outs = ["foo.out"],
|
|
srcs = ["foo.in"],
|
|
tools = [
|
|
"//other:foo.tool",
|
|
"//other:other.tool",
|
|
],
|
|
)`,
|
|
},
|
|
filesystem: otherGenruleBp,
|
|
},
|
|
{
|
|
description: "genrule using $(locations) label should substitute first tool label automatically",
|
|
moduleTypeUnderTest: "genrule",
|
|
moduleTypeUnderTestFactory: genrule.GenRuleFactory,
|
|
moduleTypeUnderTestBp2BuildMutator: genrule.GenruleBp2Build,
|
|
blueprint: `genrule {
|
|
name: "foo",
|
|
out: ["foo.out"],
|
|
srcs: ["foo.in"],
|
|
tools: [":foo.tool", ":other.tool"],
|
|
cmd: "$(locations) -s $(out) $(in)",
|
|
bazel_module: { bp2build_available: true },
|
|
}`,
|
|
expectedBazelTargets: []string{`genrule(
|
|
name = "foo",
|
|
cmd = "$(locations //other:foo.tool) -s $(OUTS) $(SRCS)",
|
|
outs = ["foo.out"],
|
|
srcs = ["foo.in"],
|
|
tools = [
|
|
"//other:foo.tool",
|
|
"//other:other.tool",
|
|
],
|
|
)`,
|
|
},
|
|
filesystem: otherGenruleBp,
|
|
},
|
|
{
|
|
description: "genrule without tools or tool_files can convert successfully",
|
|
moduleTypeUnderTest: "genrule",
|
|
moduleTypeUnderTestFactory: genrule.GenRuleFactory,
|
|
moduleTypeUnderTestBp2BuildMutator: genrule.GenruleBp2Build,
|
|
blueprint: `genrule {
|
|
name: "foo",
|
|
out: ["foo.out"],
|
|
srcs: ["foo.in"],
|
|
cmd: "cp $(in) $(out)",
|
|
bazel_module: { bp2build_available: true },
|
|
}`,
|
|
expectedBazelTargets: []string{`genrule(
|
|
name = "foo",
|
|
cmd = "cp $(SRCS) $(OUTS)",
|
|
outs = ["foo.out"],
|
|
srcs = ["foo.in"],
|
|
)`,
|
|
},
|
|
},
|
|
}
|
|
|
|
dir := "."
|
|
for _, testCase := range testCases {
|
|
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.RegisterBp2BuildMutator(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestBp2BuildMutator)
|
|
ctx.RegisterForBazelConversion()
|
|
|
|
_, errs := ctx.ParseFileList(dir, toParse)
|
|
if errored(t, testCase, errs) {
|
|
continue
|
|
}
|
|
_, errs = ctx.ResolveDependencies(config)
|
|
if errored(t, testCase, errs) {
|
|
continue
|
|
}
|
|
|
|
checkDir := dir
|
|
if testCase.dir != "" {
|
|
checkDir = testCase.dir
|
|
}
|
|
|
|
codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
|
|
bazelTargets := generateBazelTargetsForDir(codegenCtx, checkDir)
|
|
if actualCount, expectedCount := len(bazelTargets), len(testCase.expectedBazelTargets); actualCount != expectedCount {
|
|
t.Errorf("%s: Expected %d bazel target, got %d", testCase.description, expectedCount, actualCount)
|
|
} else {
|
|
for i, target := range bazelTargets {
|
|
if w, g := testCase.expectedBazelTargets[i], target.content; w != g {
|
|
t.Errorf(
|
|
"%s: Expected generated Bazel target to be '%s', got '%s'",
|
|
testCase.description,
|
|
w,
|
|
g,
|
|
)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
type bp2buildMutator = func(android.TopDownMutatorContext)
|
|
|
|
func TestBp2BuildInlinesDefaults(t *testing.T) {
|
|
testCases := []struct {
|
|
moduleTypesUnderTest map[string]android.ModuleFactory
|
|
bp2buildMutatorsUnderTest map[string]bp2buildMutator
|
|
bp string
|
|
expectedBazelTarget string
|
|
description string
|
|
}{
|
|
{
|
|
moduleTypesUnderTest: map[string]android.ModuleFactory{
|
|
"genrule": genrule.GenRuleFactory,
|
|
"genrule_defaults": func() android.Module { return genrule.DefaultsFactory() },
|
|
},
|
|
bp2buildMutatorsUnderTest: map[string]bp2buildMutator{
|
|
"genrule": genrule.GenruleBp2Build,
|
|
},
|
|
bp: `genrule_defaults {
|
|
name: "gen_defaults",
|
|
cmd: "do-something $(in) $(out)",
|
|
}
|
|
genrule {
|
|
name: "gen",
|
|
out: ["out"],
|
|
srcs: ["in1"],
|
|
defaults: ["gen_defaults"],
|
|
bazel_module: { bp2build_available: true },
|
|
}
|
|
`,
|
|
expectedBazelTarget: `genrule(
|
|
name = "gen",
|
|
cmd = "do-something $(SRCS) $(OUTS)",
|
|
outs = ["out"],
|
|
srcs = ["in1"],
|
|
)`,
|
|
description: "genrule applies properties from a genrule_defaults dependency if not specified",
|
|
},
|
|
{
|
|
moduleTypesUnderTest: map[string]android.ModuleFactory{
|
|
"genrule": genrule.GenRuleFactory,
|
|
"genrule_defaults": func() android.Module { return genrule.DefaultsFactory() },
|
|
},
|
|
bp2buildMutatorsUnderTest: map[string]bp2buildMutator{
|
|
"genrule": genrule.GenruleBp2Build,
|
|
},
|
|
bp: `genrule_defaults {
|
|
name: "gen_defaults",
|
|
out: ["out-from-defaults"],
|
|
srcs: ["in-from-defaults"],
|
|
cmd: "cmd-from-defaults",
|
|
}
|
|
genrule {
|
|
name: "gen",
|
|
out: ["out"],
|
|
srcs: ["in1"],
|
|
defaults: ["gen_defaults"],
|
|
cmd: "do-something $(in) $(out)",
|
|
bazel_module: { bp2build_available: true },
|
|
}
|
|
`,
|
|
expectedBazelTarget: `genrule(
|
|
name = "gen",
|
|
cmd = "do-something $(SRCS) $(OUTS)",
|
|
outs = [
|
|
"out-from-defaults",
|
|
"out",
|
|
],
|
|
srcs = [
|
|
"in-from-defaults",
|
|
"in1",
|
|
],
|
|
)`,
|
|
description: "genrule does merges properties from a genrule_defaults dependency, latest-first",
|
|
},
|
|
{
|
|
moduleTypesUnderTest: map[string]android.ModuleFactory{
|
|
"genrule": genrule.GenRuleFactory,
|
|
"genrule_defaults": func() android.Module { return genrule.DefaultsFactory() },
|
|
},
|
|
bp2buildMutatorsUnderTest: map[string]bp2buildMutator{
|
|
"genrule": genrule.GenruleBp2Build,
|
|
},
|
|
bp: `genrule_defaults {
|
|
name: "gen_defaults1",
|
|
cmd: "cp $(in) $(out)",
|
|
}
|
|
|
|
genrule_defaults {
|
|
name: "gen_defaults2",
|
|
srcs: ["in1"],
|
|
}
|
|
|
|
genrule {
|
|
name: "gen",
|
|
out: ["out"],
|
|
defaults: ["gen_defaults1", "gen_defaults2"],
|
|
bazel_module: { bp2build_available: true },
|
|
}
|
|
`,
|
|
expectedBazelTarget: `genrule(
|
|
name = "gen",
|
|
cmd = "cp $(SRCS) $(OUTS)",
|
|
outs = ["out"],
|
|
srcs = ["in1"],
|
|
)`,
|
|
description: "genrule applies properties from list of genrule_defaults",
|
|
},
|
|
{
|
|
moduleTypesUnderTest: map[string]android.ModuleFactory{
|
|
"genrule": genrule.GenRuleFactory,
|
|
"genrule_defaults": func() android.Module { return genrule.DefaultsFactory() },
|
|
},
|
|
bp2buildMutatorsUnderTest: map[string]bp2buildMutator{
|
|
"genrule": genrule.GenruleBp2Build,
|
|
},
|
|
bp: `genrule_defaults {
|
|
name: "gen_defaults1",
|
|
defaults: ["gen_defaults2"],
|
|
cmd: "cmd1 $(in) $(out)", // overrides gen_defaults2's cmd property value.
|
|
}
|
|
|
|
genrule_defaults {
|
|
name: "gen_defaults2",
|
|
defaults: ["gen_defaults3"],
|
|
cmd: "cmd2 $(in) $(out)",
|
|
out: ["out-from-2"],
|
|
srcs: ["in1"],
|
|
}
|
|
|
|
genrule_defaults {
|
|
name: "gen_defaults3",
|
|
out: ["out-from-3"],
|
|
srcs: ["srcs-from-3"],
|
|
}
|
|
|
|
genrule {
|
|
name: "gen",
|
|
out: ["out"],
|
|
defaults: ["gen_defaults1"],
|
|
bazel_module: { bp2build_available: true },
|
|
}
|
|
`,
|
|
expectedBazelTarget: `genrule(
|
|
name = "gen",
|
|
cmd = "cmd1 $(SRCS) $(OUTS)",
|
|
outs = [
|
|
"out-from-3",
|
|
"out-from-2",
|
|
"out",
|
|
],
|
|
srcs = [
|
|
"srcs-from-3",
|
|
"in1",
|
|
],
|
|
)`,
|
|
description: "genrule applies properties from genrule_defaults transitively",
|
|
},
|
|
}
|
|
|
|
dir := "."
|
|
for _, testCase := range testCases {
|
|
config := android.TestConfig(buildDir, nil, testCase.bp, nil)
|
|
ctx := android.NewTestContext(config)
|
|
for m, factory := range testCase.moduleTypesUnderTest {
|
|
ctx.RegisterModuleType(m, factory)
|
|
}
|
|
for mutator, f := range testCase.bp2buildMutatorsUnderTest {
|
|
ctx.RegisterBp2BuildMutator(mutator, f)
|
|
}
|
|
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 := generateBazelTargetsForDir(codegenCtx, dir)
|
|
if actualCount := len(bazelTargets); actualCount != 1 {
|
|
t.Fatalf("%s: Expected 1 bazel target, got %d", testCase.description, actualCount)
|
|
}
|
|
|
|
actualBazelTarget := bazelTargets[0]
|
|
if actualBazelTarget.content != testCase.expectedBazelTarget {
|
|
t.Errorf(
|
|
"%s: Expected generated Bazel target to be '%s', got '%s'",
|
|
testCase.description,
|
|
testCase.expectedBazelTarget,
|
|
actualBazelTarget.content,
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestAllowlistingBp2buildTargetsExplicitly(t *testing.T) {
|
|
testCases := []struct {
|
|
moduleTypeUnderTest string
|
|
moduleTypeUnderTestFactory android.ModuleFactory
|
|
moduleTypeUnderTestBp2BuildMutator bp2buildMutator
|
|
bp string
|
|
expectedCount int
|
|
description string
|
|
}{
|
|
{
|
|
description: "explicitly unavailable",
|
|
moduleTypeUnderTest: "filegroup",
|
|
moduleTypeUnderTestFactory: android.FileGroupFactory,
|
|
moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
|
|
bp: `filegroup {
|
|
name: "foo",
|
|
srcs: ["a", "b"],
|
|
bazel_module: { bp2build_available: false },
|
|
}`,
|
|
expectedCount: 0,
|
|
},
|
|
{
|
|
description: "implicitly unavailable",
|
|
moduleTypeUnderTest: "filegroup",
|
|
moduleTypeUnderTestFactory: android.FileGroupFactory,
|
|
moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
|
|
bp: `filegroup {
|
|
name: "foo",
|
|
srcs: ["a", "b"],
|
|
}`,
|
|
expectedCount: 0,
|
|
},
|
|
{
|
|
description: "explicitly available",
|
|
moduleTypeUnderTest: "filegroup",
|
|
moduleTypeUnderTestFactory: android.FileGroupFactory,
|
|
moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
|
|
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: customModuleFactory,
|
|
moduleTypeUnderTestBp2BuildMutator: customBp2BuildMutatorFromStarlark,
|
|
bp: `custom {
|
|
name: "foo",
|
|
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.RegisterBp2BuildMutator(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestBp2BuildMutator)
|
|
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 := generateBazelTargetsForDir(codegenCtx, dir)
|
|
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
|
|
moduleTypeUnderTestBp2BuildMutator bp2buildMutator
|
|
expectedCount map[string]int
|
|
description string
|
|
bp2buildConfig android.Bp2BuildConfig
|
|
checkDir string
|
|
fs map[string]string
|
|
}{
|
|
{
|
|
description: "test bp2build config package and subpackages config",
|
|
moduleTypeUnderTest: "filegroup",
|
|
moduleTypeUnderTestFactory: android.FileGroupFactory,
|
|
moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
|
|
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: android.Bp2BuildConfig{
|
|
"migrated": android.Bp2BuildDefaultTrueRecursively,
|
|
"migrated/but_not_really": android.Bp2BuildDefaultFalse,
|
|
"not_migrated": android.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,
|
|
moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
|
|
expectedCount: map[string]int{
|
|
"package-opt-in": 2,
|
|
"package-opt-in/subpackage": 0,
|
|
"package-opt-out": 1,
|
|
"package-opt-out/subpackage": 0,
|
|
},
|
|
bp2buildConfig: android.Bp2BuildConfig{
|
|
"package-opt-in": android.Bp2BuildDefaultFalse,
|
|
"package-opt-out": android.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)
|
|
ctx.RegisterBp2BuildMutator(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestBp2BuildMutator)
|
|
ctx.RegisterBp2BuildConfig(testCase.bp2buildConfig)
|
|
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 := generateBazelTargetsForDir(codegenCtx, dir)
|
|
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,
|
|
moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
|
|
blueprint: `filegroup {
|
|
name: "fg_foo",
|
|
bazel_module: { label: "//other:fg_foo" },
|
|
}`,
|
|
expectedBazelTargets: []string{
|
|
`// BUILD file`,
|
|
},
|
|
filesystem: map[string]string{
|
|
"other/BUILD.bazel": `// BUILD file`,
|
|
},
|
|
},
|
|
{
|
|
description: "multiple bazel_module.label same BUILD",
|
|
moduleTypeUnderTest: "filegroup",
|
|
moduleTypeUnderTestFactory: android.FileGroupFactory,
|
|
moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
|
|
blueprint: `filegroup {
|
|
name: "fg_foo",
|
|
bazel_module: { label: "//other:fg_foo" },
|
|
}
|
|
|
|
filegroup {
|
|
name: "foo",
|
|
bazel_module: { label: "//other:foo" },
|
|
}`,
|
|
expectedBazelTargets: []string{
|
|
`// BUILD file`,
|
|
},
|
|
filesystem: map[string]string{
|
|
"other/BUILD.bazel": `// BUILD file`,
|
|
},
|
|
},
|
|
{
|
|
description: "filegroup bazel_module.label and bp2build in subdir",
|
|
moduleTypeUnderTest: "filegroup",
|
|
moduleTypeUnderTestFactory: android.FileGroupFactory,
|
|
moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
|
|
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{
|
|
`filegroup(
|
|
name = "fg_foo",
|
|
)`, `// definition for fg_bar`,
|
|
},
|
|
},
|
|
{
|
|
description: "filegroup bazel_module.label and filegroup bp2build",
|
|
moduleTypeUnderTest: "filegroup",
|
|
moduleTypeUnderTestFactory: android.FileGroupFactory,
|
|
moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
|
|
blueprint: `filegroup {
|
|
name: "fg_foo",
|
|
bazel_module: {
|
|
label: "//other:fg_foo",
|
|
},
|
|
}
|
|
|
|
filegroup {
|
|
name: "fg_bar",
|
|
bazel_module: {
|
|
bp2build_available: true,
|
|
},
|
|
}`,
|
|
expectedBazelTargets: []string{
|
|
`filegroup(
|
|
name = "fg_bar",
|
|
)`,
|
|
`// BUILD file`,
|
|
},
|
|
filesystem: map[string]string{
|
|
"other/BUILD.bazel": `// BUILD file`,
|
|
},
|
|
},
|
|
}
|
|
|
|
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.RegisterBp2BuildMutator(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestBp2BuildMutator)
|
|
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
|
|
}
|
|
bazelTargets := generateBazelTargetsForDir(NewCodegenContext(config, *ctx.Context, Bp2Build), checkDir)
|
|
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)
|
|
}
|
|
if !strings.Contains(bazelTargets.String(), "Section: Handcrafted targets. ") {
|
|
t.Errorf("Expected string representation of bazelTargets to contain handcrafted section header.")
|
|
}
|
|
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 TestGlobExcludeSrcs(t *testing.T) {
|
|
testCases := []bp2buildTestCase{
|
|
{
|
|
description: "filegroup top level exclude_srcs",
|
|
moduleTypeUnderTest: "filegroup",
|
|
moduleTypeUnderTestFactory: android.FileGroupFactory,
|
|
moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
|
|
blueprint: `filegroup {
|
|
name: "fg_foo",
|
|
srcs: ["**/*.txt"],
|
|
exclude_srcs: ["c.txt"],
|
|
bazel_module: { bp2build_available: true },
|
|
}`,
|
|
expectedBazelTargets: []string{`filegroup(
|
|
name = "fg_foo",
|
|
srcs = [
|
|
"a.txt",
|
|
"b.txt",
|
|
"//dir:e.txt",
|
|
"//dir:f.txt",
|
|
],
|
|
)`,
|
|
},
|
|
filesystem: map[string]string{
|
|
"a.txt": "",
|
|
"b.txt": "",
|
|
"c.txt": "",
|
|
"dir/Android.bp": "",
|
|
"dir/e.txt": "",
|
|
"dir/f.txt": "",
|
|
},
|
|
},
|
|
{
|
|
description: "filegroup in subdir exclude_srcs",
|
|
moduleTypeUnderTest: "filegroup",
|
|
moduleTypeUnderTestFactory: android.FileGroupFactory,
|
|
moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
|
|
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{`filegroup(
|
|
name = "fg_foo",
|
|
srcs = [
|
|
"a.txt",
|
|
"//dir/subdir:e.txt",
|
|
"//dir/subdir:f.txt",
|
|
],
|
|
)`,
|
|
},
|
|
},
|
|
}
|
|
|
|
dir := "."
|
|
for _, testCase := range testCases {
|
|
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.RegisterBp2BuildMutator(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestBp2BuildMutator)
|
|
ctx.RegisterForBazelConversion()
|
|
|
|
_, errs := ctx.ParseFileList(dir, toParse)
|
|
if errored(t, testCase, errs) {
|
|
continue
|
|
}
|
|
_, errs = ctx.ResolveDependencies(config)
|
|
if errored(t, testCase, errs) {
|
|
continue
|
|
}
|
|
|
|
checkDir := dir
|
|
if testCase.dir != "" {
|
|
checkDir = testCase.dir
|
|
}
|
|
bazelTargets := generateBazelTargetsForDir(NewCodegenContext(config, *ctx.Context, Bp2Build), checkDir)
|
|
if actualCount, expectedCount := len(bazelTargets), len(testCase.expectedBazelTargets); actualCount != expectedCount {
|
|
t.Errorf("%s: Expected %d bazel target, got %d\n%s", testCase.description, expectedCount, actualCount, bazelTargets)
|
|
} else {
|
|
for i, target := range bazelTargets {
|
|
if w, g := testCase.expectedBazelTargets[i], target.content; w != g {
|
|
t.Errorf(
|
|
"%s: Expected generated Bazel target to be '%s', got '%s'",
|
|
testCase.description,
|
|
w,
|
|
g,
|
|
)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|