// 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 ( "io/ioutil" "os" "strings" "testing" "android/soong/android" ) 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()) } func TestGenerateModuleRuleShims(t *testing.T) { moduleTypeFactories := map[string]android.ModuleFactory{ "custom": customModuleFactoryBase, "custom_test": customTestModuleFactoryBase, "custom_defaults": customDefaultsModuleFactoryBasic, } ruleShims := CreateRuleShims(moduleTypeFactories) if len(ruleShims) != 1 { t.Errorf("Expected to generate 1 rule shim, but got %d", len(ruleShims)) } ruleShim := ruleShims["bp2build"] expectedRules := []string{ "custom", "custom_defaults", "custom_test_", } if len(ruleShim.rules) != len(expectedRules) { t.Errorf("Expected %d rules, but got %d", len(expectedRules), len(ruleShim.rules)) } for i, rule := range ruleShim.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 _custom_impl(ctx): return [SoongModuleInfo()] custom = rule( implementation = _custom_impl, attrs = { "soong_module_name": attr.string(mandatory = True), "soong_module_variant": attr.string(), "soong_module_deps": attr.label_list(providers = [SoongModuleInfo]), "api": attr.string(), "arch_paths": attr.string_list(), "arch_paths_exclude": attr.string_list(), # bazel_module start # "label": attr.string(), # "bp2build_available": attr.bool(), # bazel_module end "bool_prop": attr.bool(), "bool_ptr_prop": attr.bool(), "dir": attr.string(), "embedded_prop": attr.string(), "int64_ptr_prop": attr.int(), # nested_props start # "nested_prop": attr.string(), # nested_props end # nested_props_ptr start # "nested_prop": attr.string(), # nested_props_ptr end "one_to_many_prop": attr.bool(), "other_embedded_prop": attr.string(), "string_list_prop": attr.string_list(), "string_literal_prop": attr.string(), "string_prop": attr.string(), "string_ptr_prop": attr.string(), "test_config_setting": attr.bool(), }, ) def _custom_defaults_impl(ctx): return [SoongModuleInfo()] custom_defaults = rule( implementation = _custom_defaults_impl, attrs = { "soong_module_name": attr.string(mandatory = True), "soong_module_variant": attr.string(), "soong_module_deps": attr.label_list(providers = [SoongModuleInfo]), "api": attr.string(), "arch_paths": attr.string_list(), "arch_paths_exclude": attr.string_list(), "bool_prop": attr.bool(), "bool_ptr_prop": attr.bool(), "dir": attr.string(), "embedded_prop": attr.string(), "int64_ptr_prop": attr.int(), # nested_props start # "nested_prop": attr.string(), # nested_props end # nested_props_ptr start # "nested_prop": attr.string(), # nested_props_ptr end "one_to_many_prop": attr.bool(), "other_embedded_prop": attr.string(), "string_list_prop": attr.string_list(), "string_literal_prop": attr.string(), "string_prop": attr.string(), "string_ptr_prop": attr.string(), "test_config_setting": attr.bool(), }, ) def _custom_test__impl(ctx): return [SoongModuleInfo()] custom_test_ = rule( implementation = _custom_test__impl, attrs = { "soong_module_name": attr.string(mandatory = True), "soong_module_variant": attr.string(), "soong_module_deps": attr.label_list(providers = [SoongModuleInfo]), "api": attr.string(), "arch_paths": attr.string_list(), "arch_paths_exclude": attr.string_list(), "bool_prop": attr.bool(), "bool_ptr_prop": attr.bool(), "dir": attr.string(), "embedded_prop": attr.string(), "int64_ptr_prop": attr.int(), # nested_props start # "nested_prop": attr.string(), # nested_props end # nested_props_ptr start # "nested_prop": attr.string(), # nested_props_ptr end "one_to_many_prop": attr.bool(), "other_embedded_prop": attr.string(), "string_list_prop": attr.string_list(), "string_literal_prop": attr.string(), "string_prop": attr.string(), "string_ptr_prop": attr.string(), "test_config_setting": attr.bool(), # test_prop start # "test_string_prop": attr.string(), # test_prop end }, ) ` if ruleShim.content != expectedBzl { t.Errorf( "Expected the generated rule shim bzl to be:\n%s\nbut got:\n%s", expectedBzl, ruleShim.content) } } func TestGenerateSoongModuleBzl(t *testing.T) { ruleShims := map[string]RuleShim{ "file1": RuleShim{ rules: []string{"a", "b"}, content: "irrelevant", }, "file2": RuleShim{ rules: []string{"c", "d"}, content: "irrelevant", }, } files := CreateBazelFiles(ruleShims, make(map[string]BazelTargets), QueryView) var actualSoongModuleBzl BazelFile for _, f := range files { if f.Basename == "soong_module.bzl" { actualSoongModuleBzl = f } } expectedLoad := `load("//build/bazel/queryview_rules:file1.bzl", "a", "b") load("//build/bazel/queryview_rules:file2.bzl", "c", "d") ` expectedRuleMap := `soong_module_rule_map = { "a": a, "b": b, "c": c, "d": d, }` if !strings.Contains(actualSoongModuleBzl.Contents, 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.Contents, expectedLoad) } if !strings.Contains(actualSoongModuleBzl.Contents, 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.Contents, expectedRuleMap) } }