blob: c67d7fb66a932cd1c8a61c86b9ee60629684ff57 [file] [log] [blame]
Liz Kammer8d62a4f2021-04-08 09:47:28 -04001package android
2
3import (
Jason Wu118fd2b2022-10-27 18:41:15 +00004 "encoding/json"
Liz Kammer8d62a4f2021-04-08 09:47:28 -04005 "os"
6 "path/filepath"
7 "reflect"
Yu Liu8d82ac52022-05-17 15:13:28 -07008 "strings"
Liz Kammer8d62a4f2021-04-08 09:47:28 -04009 "testing"
Chris Parsonsf874e462022-05-10 13:50:12 -040010
11 "android/soong/bazel/cquery"
Jason Wu118fd2b2022-10-27 18:41:15 +000012 analysis_v2_proto "prebuilts/bazel/common/proto/analysis_v2"
Jingwen Chenf3b1ec32022-11-07 15:02:48 +000013
Liz Kammer690fbac2023-02-10 11:11:17 -050014 "github.com/google/blueprint/metrics"
Jingwen Chenf3b1ec32022-11-07 15:02:48 +000015 "google.golang.org/protobuf/proto"
Liz Kammer8d62a4f2021-04-08 09:47:28 -040016)
17
Yu Liu8d82ac52022-05-17 15:13:28 -070018var testConfig = TestConfig("out", nil, "", nil)
19
Liz Kammer690fbac2023-02-10 11:11:17 -050020type testInvokeBazelContext struct{}
21
22func (t *testInvokeBazelContext) GetEventHandler() *metrics.EventHandler {
23 return &metrics.EventHandler{}
24}
25
Liz Kammer8d62a4f2021-04-08 09:47:28 -040026func TestRequestResultsAfterInvokeBazel(t *testing.T) {
Yu Liue4312402023-01-18 09:15:31 -080027 label_foo := "@//foo:foo"
28 label_bar := "@//foo:bar"
29 apexKey := ApexConfigKey{
30 WithinApex: true,
31 ApexSdkVersion: "29",
32 }
33 cfg_foo := configKey{"arm64_armv8-a", Android, apexKey}
34 cfg_bar := configKey{arch: "arm64_armv8-a", osType: Android}
35 cmd_results := []string{
36 `@//foo:foo|arm64_armv8-a|android|within_apex|29>>out/foo/foo.txt`,
37 `@//foo:bar|arm64_armv8-a|android>>out/foo/bar.txt`,
38 }
Liz Kammer8d62a4f2021-04-08 09:47:28 -040039 bazelContext, _ := testBazelContext(t, map[bazelCommand]string{
Yu Liue4312402023-01-18 09:15:31 -080040 bazelCommand{command: "cquery", expression: "deps(@soong_injection//mixed_builds:buildroot, 2)"}: strings.Join(cmd_results, "\n"),
Liz Kammer8d62a4f2021-04-08 09:47:28 -040041 })
Yu Liue4312402023-01-18 09:15:31 -080042
43 bazelContext.QueueBazelRequest(label_foo, cquery.GetOutputFiles, cfg_foo)
44 bazelContext.QueueBazelRequest(label_bar, cquery.GetOutputFiles, cfg_bar)
Liz Kammer690fbac2023-02-10 11:11:17 -050045 err := bazelContext.InvokeBazel(testConfig, &testInvokeBazelContext{})
Liz Kammer8d62a4f2021-04-08 09:47:28 -040046 if err != nil {
47 t.Fatalf("Did not expect error invoking Bazel, but got %s", err)
48 }
Yu Liue4312402023-01-18 09:15:31 -080049 verifyCqueryResult(t, bazelContext, label_foo, cfg_foo, "out/foo/foo.txt")
50 verifyCqueryResult(t, bazelContext, label_bar, cfg_bar, "out/foo/bar.txt")
51}
52
53func verifyCqueryResult(t *testing.T, ctx *mixedBuildBazelContext, label string, cfg configKey, result string) {
54 g, err := ctx.GetOutputFiles(label, cfg)
Chris Parsonsf874e462022-05-10 13:50:12 -040055 if err != nil {
56 t.Errorf("Expected cquery results after running InvokeBazel(), but got err %v", err)
Yu Liue4312402023-01-18 09:15:31 -080057 } else if w := []string{result}; !reflect.DeepEqual(w, g) {
Liz Kammer8d62a4f2021-04-08 09:47:28 -040058 t.Errorf("Expected output %s, got %s", w, g)
59 }
60}
61
62func TestInvokeBazelWritesBazelFiles(t *testing.T) {
63 bazelContext, baseDir := testBazelContext(t, map[bazelCommand]string{})
Liz Kammer690fbac2023-02-10 11:11:17 -050064 err := bazelContext.InvokeBazel(testConfig, &testInvokeBazelContext{})
Liz Kammer8d62a4f2021-04-08 09:47:28 -040065 if err != nil {
66 t.Fatalf("Did not expect error invoking Bazel, but got %s", err)
67 }
Lukacs T. Berki3069dd92021-05-11 16:54:29 +020068 if _, err := os.Stat(filepath.Join(baseDir, "soong_injection", "mixed_builds", "main.bzl")); os.IsNotExist(err) {
Liz Kammer8d62a4f2021-04-08 09:47:28 -040069 t.Errorf("Expected main.bzl to exist, but it does not")
70 } else if err != nil {
71 t.Errorf("Unexpected error stating main.bzl %s", err)
72 }
73
Lukacs T. Berki3069dd92021-05-11 16:54:29 +020074 if _, err := os.Stat(filepath.Join(baseDir, "soong_injection", "mixed_builds", "BUILD.bazel")); os.IsNotExist(err) {
Liz Kammer8d62a4f2021-04-08 09:47:28 -040075 t.Errorf("Expected BUILD.bazel to exist, but it does not")
76 } else if err != nil {
77 t.Errorf("Unexpected error stating BUILD.bazel %s", err)
78 }
79
Liz Kammer286c9fa2021-04-21 08:46:34 -040080 if _, err := os.Stat(filepath.Join(baseDir, "soong_injection", "WORKSPACE.bazel")); os.IsNotExist(err) {
Liz Kammer8d62a4f2021-04-08 09:47:28 -040081 t.Errorf("Expected WORKSPACE.bazel to exist, but it does not")
82 } else if err != nil {
83 t.Errorf("Unexpected error stating WORKSPACE.bazel %s", err)
84 }
85}
86
87func TestInvokeBazelPopulatesBuildStatements(t *testing.T) {
Usta Shresthaacd5a0c2022-06-22 11:20:50 -040088 type testCase struct {
89 input string
90 command string
91 }
92
93 var testCases = []testCase{
94 {`
Liz Kammer8d62a4f2021-04-08 09:47:28 -040095{
Jason Wu118fd2b2022-10-27 18:41:15 +000096 "artifacts": [
97 { "id": 1, "path_fragment_id": 1 },
98 { "id": 2, "path_fragment_id": 2 }],
99 "actions": [{
100 "target_Id": 1,
101 "action_Key": "x",
102 "mnemonic": "x",
103 "arguments": ["touch", "foo"],
104 "input_dep_set_ids": [1],
105 "output_Ids": [1],
106 "primary_output_id": 1
107 }],
108 "dep_set_of_files": [
109 { "id": 1, "direct_artifact_ids": [1, 2] }],
110 "path_fragments": [
111 { "id": 1, "label": "one" },
112 { "id": 2, "label": "two" }]
Liz Kammer8d62a4f2021-04-08 09:47:28 -0400113}`,
Jingwen Chenf3b1ec32022-11-07 15:02:48 +0000114 "cd 'test/exec_root' && rm -rf 'one' && touch foo",
Usta Shresthaacd5a0c2022-06-22 11:20:50 -0400115 }, {`
116{
Jason Wu118fd2b2022-10-27 18:41:15 +0000117 "artifacts": [
118 { "id": 1, "path_fragment_id": 10 },
119 { "id": 2, "path_fragment_id": 20 }],
120 "actions": [{
121 "target_Id": 100,
122 "action_Key": "x",
123 "mnemonic": "x",
124 "arguments": ["bogus", "command"],
125 "output_Ids": [1, 2],
126 "primary_output_id": 1
127 }],
128 "path_fragments": [
129 { "id": 10, "label": "one", "parent_id": 30 },
130 { "id": 20, "label": "one.d", "parent_id": 30 },
131 { "id": 30, "label": "parent" }]
Usta Shresthaacd5a0c2022-06-22 11:20:50 -0400132}`,
Jingwen Chenf3b1ec32022-11-07 15:02:48 +0000133 `cd 'test/exec_root' && rm -rf 'parent/one' && bogus command && sed -i'' -E 's@(^|\s|")bazel-out/@\1test/bazel_out/@g' 'parent/one.d'`,
Usta Shresthaacd5a0c2022-06-22 11:20:50 -0400134 },
Liz Kammer8d62a4f2021-04-08 09:47:28 -0400135 }
136
Usta Shresthaef922252022-06-02 14:23:02 -0400137 for i, testCase := range testCases {
Jason Wu118fd2b2022-10-27 18:41:15 +0000138 data, err := JsonToActionGraphContainer(testCase.input)
139 if err != nil {
140 t.Error(err)
141 }
Usta Shresthaacd5a0c2022-06-22 11:20:50 -0400142 bazelContext, _ := testBazelContext(t, map[bazelCommand]string{
Jason Wu118fd2b2022-10-27 18:41:15 +0000143 bazelCommand{command: "aquery", expression: "deps(@soong_injection//mixed_builds:buildroot)"}: string(data)})
Usta Shresthaacd5a0c2022-06-22 11:20:50 -0400144
Liz Kammer690fbac2023-02-10 11:11:17 -0500145 err = bazelContext.InvokeBazel(testConfig, &testInvokeBazelContext{})
Usta Shresthaacd5a0c2022-06-22 11:20:50 -0400146 if err != nil {
Usta Shresthaef922252022-06-02 14:23:02 -0400147 t.Fatalf("testCase #%d: did not expect error invoking Bazel, but got %s", i+1, err)
Usta Shresthaacd5a0c2022-06-22 11:20:50 -0400148 }
149
150 got := bazelContext.BuildStatementsToRegister()
151 if want := 1; len(got) != want {
Sasha Smundake3cf1ab2022-06-30 11:36:18 -0700152 t.Fatalf("expected %d registered build statements, but got %#v", want, got)
Usta Shresthaacd5a0c2022-06-22 11:20:50 -0400153 }
154
155 cmd := RuleBuilderCommand{}
Colin Crossd5c7ddb2022-12-06 16:27:17 -0800156 ctx := builderContextForTests{PathContextForTesting(TestConfig("out", nil, "", nil))}
157 createCommand(&cmd, got[0], "test/exec_root", "test/bazel_out", ctx)
Usta Shresthaef922252022-06-02 14:23:02 -0400158 if actual, expected := cmd.buf.String(), testCase.command; expected != actual {
159 t.Errorf("expected: [%s], actual: [%s]", expected, actual)
Usta Shresthaacd5a0c2022-06-22 11:20:50 -0400160 }
Liz Kammer8d62a4f2021-04-08 09:47:28 -0400161 }
162}
163
Yu Liu8d82ac52022-05-17 15:13:28 -0700164func TestCoverageFlagsAfterInvokeBazel(t *testing.T) {
165 testConfig.productVariables.ClangCoverage = boolPtr(true)
166
167 testConfig.productVariables.NativeCoveragePaths = []string{"foo1", "foo2"}
168 testConfig.productVariables.NativeCoverageExcludePaths = []string{"bar1", "bar2"}
169 verifyExtraFlags(t, testConfig, `--collect_code_coverage --instrumentation_filter=+foo1,+foo2,-bar1,-bar2`)
170
171 testConfig.productVariables.NativeCoveragePaths = []string{"foo1"}
172 testConfig.productVariables.NativeCoverageExcludePaths = []string{"bar1"}
173 verifyExtraFlags(t, testConfig, `--collect_code_coverage --instrumentation_filter=+foo1,-bar1`)
174
175 testConfig.productVariables.NativeCoveragePaths = []string{"foo1"}
176 testConfig.productVariables.NativeCoverageExcludePaths = nil
177 verifyExtraFlags(t, testConfig, `--collect_code_coverage --instrumentation_filter=+foo1`)
178
179 testConfig.productVariables.NativeCoveragePaths = nil
180 testConfig.productVariables.NativeCoverageExcludePaths = []string{"bar1"}
181 verifyExtraFlags(t, testConfig, `--collect_code_coverage --instrumentation_filter=-bar1`)
182
Wei Licbd181c2022-11-16 08:59:23 -0800183 testConfig.productVariables.NativeCoveragePaths = []string{"*"}
184 testConfig.productVariables.NativeCoverageExcludePaths = nil
185 verifyExtraFlags(t, testConfig, `--collect_code_coverage --instrumentation_filter=+.*`)
186
Yu Liu8d82ac52022-05-17 15:13:28 -0700187 testConfig.productVariables.ClangCoverage = boolPtr(false)
188 actual := verifyExtraFlags(t, testConfig, ``)
189 if strings.Contains(actual, "--collect_code_coverage") ||
190 strings.Contains(actual, "--instrumentation_filter=") {
191 t.Errorf("Expected code coverage disabled, but got %#v", actual)
192 }
193}
194
Chris Parsons3a8d0fb2023-02-02 18:16:29 -0500195func TestBazelRequestsSorted(t *testing.T) {
196 bazelContext, _ := testBazelContext(t, map[bazelCommand]string{})
197
Yu Liue4312402023-01-18 09:15:31 -0800198 cfgKeyArm64Android := configKey{arch: "arm64_armv8-a", osType: Android}
199 cfgKeyArm64Linux := configKey{arch: "arm64_armv8-a", osType: Linux}
200 cfgKeyOtherAndroid := configKey{arch: "otherarch", osType: Android}
201
202 bazelContext.QueueBazelRequest("zzz", cquery.GetOutputFiles, cfgKeyArm64Android)
203 bazelContext.QueueBazelRequest("ccc", cquery.GetApexInfo, cfgKeyArm64Android)
204 bazelContext.QueueBazelRequest("duplicate", cquery.GetOutputFiles, cfgKeyArm64Android)
205 bazelContext.QueueBazelRequest("duplicate", cquery.GetOutputFiles, cfgKeyArm64Android)
206 bazelContext.QueueBazelRequest("xxx", cquery.GetOutputFiles, cfgKeyArm64Linux)
207 bazelContext.QueueBazelRequest("aaa", cquery.GetOutputFiles, cfgKeyArm64Android)
208 bazelContext.QueueBazelRequest("aaa", cquery.GetOutputFiles, cfgKeyOtherAndroid)
209 bazelContext.QueueBazelRequest("bbb", cquery.GetOutputFiles, cfgKeyOtherAndroid)
Chris Parsons3a8d0fb2023-02-02 18:16:29 -0500210
211 if len(bazelContext.requests) != 7 {
212 t.Error("Expected 7 request elements, but got", len(bazelContext.requests))
213 }
214
215 lastString := ""
216 for _, val := range bazelContext.requests {
217 thisString := val.String()
218 if thisString <= lastString {
219 t.Errorf("Requests are not ordered correctly. '%s' came before '%s'", lastString, thisString)
220 }
221 lastString = thisString
222 }
223}
224
Yu Liue4312402023-01-18 09:15:31 -0800225func TestIsModuleNameAllowed(t *testing.T) {
226 libDisabled := "lib_disabled"
227 libEnabled := "lib_enabled"
228 libDclaWithinApex := "lib_dcla_within_apex"
229 libDclaNonApex := "lib_dcla_non_apex"
230 libNotConverted := "lib_not_converted"
231
232 disabledModules := map[string]bool{
233 libDisabled: true,
234 }
235 enabledModules := map[string]bool{
236 libEnabled: true,
237 }
238 dclaEnabledModules := map[string]bool{
239 libDclaWithinApex: true,
240 libDclaNonApex: true,
241 }
242
243 bazelContext := &mixedBuildBazelContext{
244 modulesDefaultToBazel: false,
245 bazelEnabledModules: enabledModules,
246 bazelDisabledModules: disabledModules,
247 bazelDclaEnabledModules: dclaEnabledModules,
248 }
249
250 if bazelContext.IsModuleNameAllowed(libDisabled, true) {
251 t.Fatalf("%s shouldn't be allowed for mixed build", libDisabled)
252 }
253
254 if !bazelContext.IsModuleNameAllowed(libEnabled, true) {
255 t.Fatalf("%s should be allowed for mixed build", libEnabled)
256 }
257
258 if !bazelContext.IsModuleNameAllowed(libDclaWithinApex, true) {
259 t.Fatalf("%s should be allowed for mixed build", libDclaWithinApex)
260 }
261
262 if bazelContext.IsModuleNameAllowed(libDclaNonApex, false) {
263 t.Fatalf("%s shouldn't be allowed for mixed build", libDclaNonApex)
264 }
265
266 if bazelContext.IsModuleNameAllowed(libNotConverted, true) {
267 t.Fatalf("%s shouldn't be allowed for mixed build", libNotConverted)
268 }
269}
270
Yu Liu8d82ac52022-05-17 15:13:28 -0700271func verifyExtraFlags(t *testing.T, config Config, expected string) string {
272 bazelContext, _ := testBazelContext(t, map[bazelCommand]string{})
273
Liz Kammer690fbac2023-02-10 11:11:17 -0500274 err := bazelContext.InvokeBazel(config, &testInvokeBazelContext{})
Yu Liu8d82ac52022-05-17 15:13:28 -0700275 if err != nil {
276 t.Fatalf("Did not expect error invoking Bazel, but got %s", err)
277 }
278
279 flags := bazelContext.bazelRunner.(*mockBazelRunner).extraFlags
280 if expected := 3; len(flags) != expected {
281 t.Errorf("Expected %d extra flags got %#v", expected, flags)
282 }
283
284 actual := flags[1]
285 if !strings.Contains(actual, expected) {
286 t.Errorf("Expected %#v got %#v", expected, actual)
287 }
288
289 return actual
290}
291
Sasha Smundak39a301c2022-12-29 17:11:49 -0800292func testBazelContext(t *testing.T, bazelCommandResults map[bazelCommand]string) (*mixedBuildBazelContext, string) {
Liz Kammer8d62a4f2021-04-08 09:47:28 -0400293 t.Helper()
294 p := bazelPaths{
Lukacs T. Berki9f6c24a2021-08-26 15:07:24 +0200295 soongOutDir: t.TempDir(),
Liz Kammer8d62a4f2021-04-08 09:47:28 -0400296 outputBase: "outputbase",
297 workspaceDir: "workspace_dir",
298 }
Lukacs T. Berki3069dd92021-05-11 16:54:29 +0200299 aqueryCommand := bazelCommand{command: "aquery", expression: "deps(@soong_injection//mixed_builds:buildroot)"}
Liz Kammer8d62a4f2021-04-08 09:47:28 -0400300 if _, exists := bazelCommandResults[aqueryCommand]; !exists {
Sasha Smundak4975c822022-11-16 15:28:18 -0800301 bazelCommandResults[aqueryCommand] = ""
Liz Kammer8d62a4f2021-04-08 09:47:28 -0400302 }
303 runner := &mockBazelRunner{bazelCommandResults: bazelCommandResults}
Sasha Smundak39a301c2022-12-29 17:11:49 -0800304 return &mixedBuildBazelContext{
Liz Kammer8d62a4f2021-04-08 09:47:28 -0400305 bazelRunner: runner,
306 paths: &p,
Lukacs T. Berki9f6c24a2021-08-26 15:07:24 +0200307 }, p.soongOutDir
Liz Kammer8d62a4f2021-04-08 09:47:28 -0400308}
Jason Wu118fd2b2022-10-27 18:41:15 +0000309
310// Transform the json format to ActionGraphContainer
311func JsonToActionGraphContainer(inputString string) ([]byte, error) {
312 var aqueryProtoResult analysis_v2_proto.ActionGraphContainer
313 err := json.Unmarshal([]byte(inputString), &aqueryProtoResult)
314 if err != nil {
315 return []byte(""), err
316 }
317 data, _ := proto.Marshal(&aqueryProtoResult)
318 return data, err
319}