1// Copyright 2020 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package bp2build
16
17import (
18	"android/soong/android"
19	"io/ioutil"
20	"os"
21	"strings"
22	"testing"
23)
24
25var buildDir string
26
27func setUp() {
28	var err error
29	buildDir, err = ioutil.TempDir("", "bazel_queryview_test")
30	if err != nil {
31		panic(err)
32	}
33}
34
35func tearDown() {
36	os.RemoveAll(buildDir)
37}
38
39func TestMain(m *testing.M) {
40	run := func() int {
41		setUp()
42		defer tearDown()
43
44		return m.Run()
45	}
46
47	os.Exit(run())
48}
49
50func TestGenerateModuleRuleShims(t *testing.T) {
51	moduleTypeFactories := map[string]android.ModuleFactory{
52		"custom":          customModuleFactoryBase,
53		"custom_test":     customTestModuleFactoryBase,
54		"custom_defaults": customDefaultsModuleFactoryBasic,
55	}
56	ruleShims := CreateRuleShims(moduleTypeFactories)
57
58	if len(ruleShims) != 1 {
59		t.Errorf("Expected to generate 1 rule shim, but got %d", len(ruleShims))
60	}
61
62	ruleShim := ruleShims["bp2build"]
63	expectedRules := []string{
64		"custom",
65		"custom_defaults",
66		"custom_test_",
67	}
68
69	if len(ruleShim.rules) != len(expectedRules) {
70		t.Errorf("Expected %d rules, but got %d", len(expectedRules), len(ruleShim.rules))
71	}
72
73	for i, rule := range ruleShim.rules {
74		if rule != expectedRules[i] {
75			t.Errorf("Expected rule shim to contain %s, but got %s", expectedRules[i], rule)
76		}
77	}
78	expectedBzl := `load("//build/bazel/queryview_rules:providers.bzl", "SoongModuleInfo")
79
80def _custom_impl(ctx):
81    return [SoongModuleInfo()]
82
83custom = rule(
84    implementation = _custom_impl,
85    attrs = {
86        "soong_module_name": attr.string(mandatory = True),
87        "soong_module_variant": attr.string(),
88        "soong_module_deps": attr.label_list(providers = [SoongModuleInfo]),
89        "arch_paths": attr.string_list(),
90        # bazel_module start
91#         "label": attr.string(),
92#         "bp2build_available": attr.bool(),
93        # bazel_module end
94        "bool_prop": attr.bool(),
95        "bool_ptr_prop": attr.bool(),
96        "int64_ptr_prop": attr.int(),
97        # nested_props start
98#         "nested_prop": attr.string(),
99        # nested_props end
100        # nested_props_ptr start
101#         "nested_prop": attr.string(),
102        # nested_props_ptr end
103        "string_list_prop": attr.string_list(),
104        "string_prop": attr.string(),
105        "string_ptr_prop": attr.string(),
106    },
107)
108
109def _custom_defaults_impl(ctx):
110    return [SoongModuleInfo()]
111
112custom_defaults = rule(
113    implementation = _custom_defaults_impl,
114    attrs = {
115        "soong_module_name": attr.string(mandatory = True),
116        "soong_module_variant": attr.string(),
117        "soong_module_deps": attr.label_list(providers = [SoongModuleInfo]),
118        "arch_paths": attr.string_list(),
119        "bool_prop": attr.bool(),
120        "bool_ptr_prop": attr.bool(),
121        "int64_ptr_prop": attr.int(),
122        # nested_props start
123#         "nested_prop": attr.string(),
124        # nested_props end
125        # nested_props_ptr start
126#         "nested_prop": attr.string(),
127        # nested_props_ptr end
128        "string_list_prop": attr.string_list(),
129        "string_prop": attr.string(),
130        "string_ptr_prop": attr.string(),
131    },
132)
133
134def _custom_test__impl(ctx):
135    return [SoongModuleInfo()]
136
137custom_test_ = rule(
138    implementation = _custom_test__impl,
139    attrs = {
140        "soong_module_name": attr.string(mandatory = True),
141        "soong_module_variant": attr.string(),
142        "soong_module_deps": attr.label_list(providers = [SoongModuleInfo]),
143        "arch_paths": attr.string_list(),
144        "bool_prop": attr.bool(),
145        "bool_ptr_prop": attr.bool(),
146        "int64_ptr_prop": attr.int(),
147        # nested_props start
148#         "nested_prop": attr.string(),
149        # nested_props end
150        # nested_props_ptr start
151#         "nested_prop": attr.string(),
152        # nested_props_ptr end
153        "string_list_prop": attr.string_list(),
154        "string_prop": attr.string(),
155        "string_ptr_prop": attr.string(),
156        # test_prop start
157#         "test_string_prop": attr.string(),
158        # test_prop end
159    },
160)
161`
162
163	if ruleShim.content != expectedBzl {
164		t.Errorf(
165			"Expected the generated rule shim bzl to be:\n%s\nbut got:\n%s",
166			expectedBzl,
167			ruleShim.content)
168	}
169}
170
171func TestGenerateSoongModuleBzl(t *testing.T) {
172	ruleShims := map[string]RuleShim{
173		"file1": RuleShim{
174			rules:   []string{"a", "b"},
175			content: "irrelevant",
176		},
177		"file2": RuleShim{
178			rules:   []string{"c", "d"},
179			content: "irrelevant",
180		},
181	}
182	files := CreateBazelFiles(ruleShims, make(map[string]BazelTargets), QueryView)
183
184	var actualSoongModuleBzl BazelFile
185	for _, f := range files {
186		if f.Basename == "soong_module.bzl" {
187			actualSoongModuleBzl = f
188		}
189	}
190
191	expectedLoad := `load("//build/bazel/queryview_rules:file1.bzl", "a", "b")
192load("//build/bazel/queryview_rules:file2.bzl", "c", "d")
193`
194	expectedRuleMap := `soong_module_rule_map = {
195    "a": a,
196    "b": b,
197    "c": c,
198    "d": d,
199}`
200	if !strings.Contains(actualSoongModuleBzl.Contents, expectedLoad) {
201		t.Errorf(
202			"Generated soong_module.bzl:\n\n%s\n\n"+
203				"Could not find the load statement in the generated soong_module.bzl:\n%s",
204			actualSoongModuleBzl.Contents,
205			expectedLoad)
206	}
207
208	if !strings.Contains(actualSoongModuleBzl.Contents, expectedRuleMap) {
209		t.Errorf(
210			"Generated soong_module.bzl:\n\n%s\n\n"+
211				"Could not find the module -> rule map in the generated soong_module.bzl:\n%s",
212			actualSoongModuleBzl.Contents,
213			expectedRuleMap)
214	}
215}
216