465 lines
9.9 KiB
Go
465 lines
9.9 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 main
|
|
|
|
import (
|
|
"android/soong/android"
|
|
"io/ioutil"
|
|
"os"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/google/blueprint/bootstrap/bpdoc"
|
|
)
|
|
|
|
var buildDir string
|
|
|
|
func setUp() {
|
|
var err error
|
|
buildDir, err = ioutil.TempDir("", "bazel_queryview_test")
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
|
|
func tearDown() {
|
|
os.RemoveAll(buildDir)
|
|
}
|
|
|
|
func TestMain(m *testing.M) {
|
|
run := func() int {
|
|
setUp()
|
|
defer tearDown()
|
|
|
|
return m.Run()
|
|
}
|
|
|
|
os.Exit(run())
|
|
}
|
|
|
|
type customModule struct {
|
|
android.ModuleBase
|
|
}
|
|
|
|
func (m *customModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
|
// nothing for now.
|
|
}
|
|
|
|
func customModuleFactory() android.Module {
|
|
module := &customModule{}
|
|
android.InitAndroidModule(module)
|
|
return module
|
|
}
|
|
|
|
func TestGenerateBazelQueryViewFromBlueprint(t *testing.T) {
|
|
testCases := []struct {
|
|
bp string
|
|
expectedBazelTarget string
|
|
}{
|
|
{
|
|
bp: `custom {
|
|
name: "foo",
|
|
}
|
|
`,
|
|
expectedBazelTarget: `soong_module(
|
|
name = "foo",
|
|
module_name = "foo",
|
|
module_type = "custom",
|
|
module_variant = "",
|
|
module_deps = [
|
|
],
|
|
)`,
|
|
},
|
|
{
|
|
bp: `custom {
|
|
name: "foo",
|
|
ramdisk: true,
|
|
}
|
|
`,
|
|
expectedBazelTarget: `soong_module(
|
|
name = "foo",
|
|
module_name = "foo",
|
|
module_type = "custom",
|
|
module_variant = "",
|
|
module_deps = [
|
|
],
|
|
ramdisk = True,
|
|
)`,
|
|
},
|
|
{
|
|
bp: `custom {
|
|
name: "foo",
|
|
owner: "a_string_with\"quotes\"_and_\\backslashes\\\\",
|
|
}
|
|
`,
|
|
expectedBazelTarget: `soong_module(
|
|
name = "foo",
|
|
module_name = "foo",
|
|
module_type = "custom",
|
|
module_variant = "",
|
|
module_deps = [
|
|
],
|
|
owner = "a_string_with\"quotes\"_and_\\backslashes\\\\",
|
|
)`,
|
|
},
|
|
{
|
|
bp: `custom {
|
|
name: "foo",
|
|
required: ["bar"],
|
|
}
|
|
`,
|
|
expectedBazelTarget: `soong_module(
|
|
name = "foo",
|
|
module_name = "foo",
|
|
module_type = "custom",
|
|
module_variant = "",
|
|
module_deps = [
|
|
],
|
|
required = [
|
|
"bar",
|
|
],
|
|
)`,
|
|
},
|
|
{
|
|
bp: `custom {
|
|
name: "foo",
|
|
target_required: ["qux", "bazqux"],
|
|
}
|
|
`,
|
|
expectedBazelTarget: `soong_module(
|
|
name = "foo",
|
|
module_name = "foo",
|
|
module_type = "custom",
|
|
module_variant = "",
|
|
module_deps = [
|
|
],
|
|
target_required = [
|
|
"qux",
|
|
"bazqux",
|
|
],
|
|
)`,
|
|
},
|
|
{
|
|
bp: `custom {
|
|
name: "foo",
|
|
dist: {
|
|
targets: ["goal_foo"],
|
|
tag: ".foo",
|
|
},
|
|
dists: [
|
|
{
|
|
targets: ["goal_bar"],
|
|
tag: ".bar",
|
|
},
|
|
],
|
|
}
|
|
`,
|
|
expectedBazelTarget: `soong_module(
|
|
name = "foo",
|
|
module_name = "foo",
|
|
module_type = "custom",
|
|
module_variant = "",
|
|
module_deps = [
|
|
],
|
|
dist = {
|
|
"tag": ".foo",
|
|
"targets": [
|
|
"goal_foo",
|
|
],
|
|
},
|
|
dists = [
|
|
{
|
|
"tag": ".bar",
|
|
"targets": [
|
|
"goal_bar",
|
|
],
|
|
},
|
|
],
|
|
)`,
|
|
},
|
|
{
|
|
bp: `custom {
|
|
name: "foo",
|
|
required: ["bar"],
|
|
target_required: ["qux", "bazqux"],
|
|
ramdisk: true,
|
|
owner: "custom_owner",
|
|
dists: [
|
|
{
|
|
tag: ".tag",
|
|
targets: ["my_goal"],
|
|
},
|
|
],
|
|
}
|
|
`,
|
|
expectedBazelTarget: `soong_module(
|
|
name = "foo",
|
|
module_name = "foo",
|
|
module_type = "custom",
|
|
module_variant = "",
|
|
module_deps = [
|
|
],
|
|
dists = [
|
|
{
|
|
"tag": ".tag",
|
|
"targets": [
|
|
"my_goal",
|
|
],
|
|
},
|
|
],
|
|
owner = "custom_owner",
|
|
ramdisk = True,
|
|
required = [
|
|
"bar",
|
|
],
|
|
target_required = [
|
|
"qux",
|
|
"bazqux",
|
|
],
|
|
)`,
|
|
},
|
|
}
|
|
|
|
for _, testCase := range testCases {
|
|
config := android.TestConfig(buildDir, nil, testCase.bp, nil)
|
|
ctx := android.NewTestContext(config)
|
|
ctx.RegisterModuleType("custom", customModuleFactory)
|
|
ctx.Register()
|
|
|
|
_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
|
|
android.FailIfErrored(t, errs)
|
|
_, errs = ctx.PrepareBuildActions(config)
|
|
android.FailIfErrored(t, errs)
|
|
|
|
module := ctx.ModuleForTests("foo", "").Module().(*customModule)
|
|
blueprintCtx := ctx.Context.Context
|
|
|
|
actualBazelTarget := generateSoongModuleTarget(blueprintCtx, module)
|
|
if actualBazelTarget != testCase.expectedBazelTarget {
|
|
t.Errorf(
|
|
"Expected generated Bazel target to be '%s', got '%s'",
|
|
testCase.expectedBazelTarget,
|
|
actualBazelTarget,
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
func createPackageFixtures() []*bpdoc.Package {
|
|
properties := []bpdoc.Property{
|
|
bpdoc.Property{
|
|
Name: "int64_prop",
|
|
Type: "int64",
|
|
},
|
|
bpdoc.Property{
|
|
Name: "int_prop",
|
|
Type: "int",
|
|
},
|
|
bpdoc.Property{
|
|
Name: "bool_prop",
|
|
Type: "bool",
|
|
},
|
|
bpdoc.Property{
|
|
Name: "string_prop",
|
|
Type: "string",
|
|
},
|
|
bpdoc.Property{
|
|
Name: "string_list_prop",
|
|
Type: "list of string",
|
|
},
|
|
bpdoc.Property{
|
|
Name: "nested_prop",
|
|
Type: "",
|
|
Properties: []bpdoc.Property{
|
|
bpdoc.Property{
|
|
Name: "int_prop",
|
|
Type: "int",
|
|
},
|
|
bpdoc.Property{
|
|
Name: "bool_prop",
|
|
Type: "bool",
|
|
},
|
|
bpdoc.Property{
|
|
Name: "string_prop",
|
|
Type: "string",
|
|
},
|
|
},
|
|
},
|
|
bpdoc.Property{
|
|
Name: "unknown_type",
|
|
Type: "unknown",
|
|
},
|
|
}
|
|
|
|
fooPropertyStruct := &bpdoc.PropertyStruct{
|
|
Name: "FooProperties",
|
|
Properties: properties,
|
|
}
|
|
|
|
moduleTypes := []*bpdoc.ModuleType{
|
|
&bpdoc.ModuleType{
|
|
Name: "foo_library",
|
|
PropertyStructs: []*bpdoc.PropertyStruct{
|
|
fooPropertyStruct,
|
|
},
|
|
},
|
|
|
|
&bpdoc.ModuleType{
|
|
Name: "foo_binary",
|
|
PropertyStructs: []*bpdoc.PropertyStruct{
|
|
fooPropertyStruct,
|
|
},
|
|
},
|
|
&bpdoc.ModuleType{
|
|
Name: "foo_test",
|
|
PropertyStructs: []*bpdoc.PropertyStruct{
|
|
fooPropertyStruct,
|
|
},
|
|
},
|
|
}
|
|
|
|
return [](*bpdoc.Package){
|
|
&bpdoc.Package{
|
|
Name: "foo_language",
|
|
Path: "android/soong/foo",
|
|
ModuleTypes: moduleTypes,
|
|
},
|
|
}
|
|
}
|
|
|
|
func TestGenerateModuleRuleShims(t *testing.T) {
|
|
ruleShims, err := createRuleShims(createPackageFixtures())
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
if len(ruleShims) != 1 {
|
|
t.Errorf("Expected to generate 1 rule shim, but got %d", len(ruleShims))
|
|
}
|
|
|
|
fooRuleShim := ruleShims["foo"]
|
|
expectedRules := []string{"foo_binary", "foo_library", "foo_test_"}
|
|
|
|
if len(fooRuleShim.rules) != 3 {
|
|
t.Errorf("Expected 3 rules, but got %d", len(fooRuleShim.rules))
|
|
}
|
|
|
|
for i, rule := range fooRuleShim.rules {
|
|
if rule != expectedRules[i] {
|
|
t.Errorf("Expected rule shim to contain %s, but got %s", expectedRules[i], rule)
|
|
}
|
|
}
|
|
|
|
expectedBzl := `load("//build/bazel/queryview_rules:providers.bzl", "SoongModuleInfo")
|
|
|
|
def _foo_binary_impl(ctx):
|
|
return [SoongModuleInfo()]
|
|
|
|
foo_binary = rule(
|
|
implementation = _foo_binary_impl,
|
|
attrs = {
|
|
"module_name": attr.string(mandatory = True),
|
|
"module_variant": attr.string(),
|
|
"module_deps": attr.label_list(providers = [SoongModuleInfo]),
|
|
"bool_prop": attr.bool(),
|
|
"int64_prop": attr.int(),
|
|
"int_prop": attr.int(),
|
|
# "nested_prop__int_prop": attr.int(),
|
|
# "nested_prop__bool_prop": attr.bool(),
|
|
# "nested_prop__string_prop": attr.string(),
|
|
"string_list_prop": attr.string_list(),
|
|
"string_prop": attr.string(),
|
|
},
|
|
)
|
|
|
|
def _foo_library_impl(ctx):
|
|
return [SoongModuleInfo()]
|
|
|
|
foo_library = rule(
|
|
implementation = _foo_library_impl,
|
|
attrs = {
|
|
"module_name": attr.string(mandatory = True),
|
|
"module_variant": attr.string(),
|
|
"module_deps": attr.label_list(providers = [SoongModuleInfo]),
|
|
"bool_prop": attr.bool(),
|
|
"int64_prop": attr.int(),
|
|
"int_prop": attr.int(),
|
|
# "nested_prop__int_prop": attr.int(),
|
|
# "nested_prop__bool_prop": attr.bool(),
|
|
# "nested_prop__string_prop": attr.string(),
|
|
"string_list_prop": attr.string_list(),
|
|
"string_prop": attr.string(),
|
|
},
|
|
)
|
|
|
|
def _foo_test__impl(ctx):
|
|
return [SoongModuleInfo()]
|
|
|
|
foo_test_ = rule(
|
|
implementation = _foo_test__impl,
|
|
attrs = {
|
|
"module_name": attr.string(mandatory = True),
|
|
"module_variant": attr.string(),
|
|
"module_deps": attr.label_list(providers = [SoongModuleInfo]),
|
|
"bool_prop": attr.bool(),
|
|
"int64_prop": attr.int(),
|
|
"int_prop": attr.int(),
|
|
# "nested_prop__int_prop": attr.int(),
|
|
# "nested_prop__bool_prop": attr.bool(),
|
|
# "nested_prop__string_prop": attr.string(),
|
|
"string_list_prop": attr.string_list(),
|
|
"string_prop": attr.string(),
|
|
},
|
|
)
|
|
`
|
|
|
|
if fooRuleShim.content != expectedBzl {
|
|
t.Errorf(
|
|
"Expected the generated rule shim bzl to be:\n%s\nbut got:\n%s",
|
|
expectedBzl,
|
|
fooRuleShim.content)
|
|
}
|
|
}
|
|
|
|
func TestGenerateSoongModuleBzl(t *testing.T) {
|
|
ruleShims, err := createRuleShims(createPackageFixtures())
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
actualSoongModuleBzl := generateSoongModuleBzl(ruleShims)
|
|
|
|
expectedLoad := "load(\"//build/bazel/queryview_rules:foo.bzl\", \"foo_binary\", \"foo_library\", \"foo_test_\")"
|
|
expectedRuleMap := `soong_module_rule_map = {
|
|
"foo_binary": foo_binary,
|
|
"foo_library": foo_library,
|
|
"foo_test_": foo_test_,
|
|
}`
|
|
if !strings.Contains(actualSoongModuleBzl, expectedLoad) {
|
|
t.Errorf(
|
|
"Generated soong_module.bzl:\n\n%s\n\n"+
|
|
"Could not find the load statement in the generated soong_module.bzl:\n%s",
|
|
actualSoongModuleBzl,
|
|
expectedLoad)
|
|
}
|
|
|
|
if !strings.Contains(actualSoongModuleBzl, expectedRuleMap) {
|
|
t.Errorf(
|
|
"Generated soong_module.bzl:\n\n%s\n\n"+
|
|
"Could not find the module -> rule map in the generated soong_module.bzl:\n%s",
|
|
actualSoongModuleBzl,
|
|
expectedRuleMap)
|
|
}
|
|
}
|