blob: 4a4ecb57fe9e4add1a6c70ac9b55c77219c5bb04 [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) {
Chris Parsons86dc2c22022-09-28 14:58:41 -040027 label := "@//foo:bar"
Liz Kammer0940b892022-03-18 15:55:04 -040028 cfg := configKey{"arm64_armv8-a", Android}
Liz Kammer8d62a4f2021-04-08 09:47:28 -040029 bazelContext, _ := testBazelContext(t, map[bazelCommand]string{
Chris Parsons86dc2c22022-09-28 14:58:41 -040030 bazelCommand{command: "cquery", expression: "deps(@soong_injection//mixed_builds:buildroot, 2)"}: `@//foo:bar|arm64_armv8-a|android>>out/foo/bar.txt`,
Liz Kammer8d62a4f2021-04-08 09:47:28 -040031 })
Chris Parsonsf874e462022-05-10 13:50:12 -040032 bazelContext.QueueBazelRequest(label, cquery.GetOutputFiles, cfg)
Liz Kammer690fbac2023-02-10 11:11:17 -050033 err := bazelContext.InvokeBazel(testConfig, &testInvokeBazelContext{})
Liz Kammer8d62a4f2021-04-08 09:47:28 -040034 if err != nil {
35 t.Fatalf("Did not expect error invoking Bazel, but got %s", err)
36 }
Chris Parsonsf874e462022-05-10 13:50:12 -040037 g, err := bazelContext.GetOutputFiles(label, cfg)
38 if err != nil {
39 t.Errorf("Expected cquery results after running InvokeBazel(), but got err %v", err)
Liz Kammer8d62a4f2021-04-08 09:47:28 -040040 } else if w := []string{"out/foo/bar.txt"}; !reflect.DeepEqual(w, g) {
41 t.Errorf("Expected output %s, got %s", w, g)
42 }
43}
44
45func TestInvokeBazelWritesBazelFiles(t *testing.T) {
46 bazelContext, baseDir := testBazelContext(t, map[bazelCommand]string{})
Liz Kammer690fbac2023-02-10 11:11:17 -050047 err := bazelContext.InvokeBazel(testConfig, &testInvokeBazelContext{})
Liz Kammer8d62a4f2021-04-08 09:47:28 -040048 if err != nil {
49 t.Fatalf("Did not expect error invoking Bazel, but got %s", err)
50 }
Lukacs T. Berki3069dd92021-05-11 16:54:29 +020051 if _, err := os.Stat(filepath.Join(baseDir, "soong_injection", "mixed_builds", "main.bzl")); os.IsNotExist(err) {
Liz Kammer8d62a4f2021-04-08 09:47:28 -040052 t.Errorf("Expected main.bzl to exist, but it does not")
53 } else if err != nil {
54 t.Errorf("Unexpected error stating main.bzl %s", err)
55 }
56
Lukacs T. Berki3069dd92021-05-11 16:54:29 +020057 if _, err := os.Stat(filepath.Join(baseDir, "soong_injection", "mixed_builds", "BUILD.bazel")); os.IsNotExist(err) {
Liz Kammer8d62a4f2021-04-08 09:47:28 -040058 t.Errorf("Expected BUILD.bazel to exist, but it does not")
59 } else if err != nil {
60 t.Errorf("Unexpected error stating BUILD.bazel %s", err)
61 }
62
Liz Kammer286c9fa2021-04-21 08:46:34 -040063 if _, err := os.Stat(filepath.Join(baseDir, "soong_injection", "WORKSPACE.bazel")); os.IsNotExist(err) {
Liz Kammer8d62a4f2021-04-08 09:47:28 -040064 t.Errorf("Expected WORKSPACE.bazel to exist, but it does not")
65 } else if err != nil {
66 t.Errorf("Unexpected error stating WORKSPACE.bazel %s", err)
67 }
68}
69
70func TestInvokeBazelPopulatesBuildStatements(t *testing.T) {
Usta Shresthaacd5a0c2022-06-22 11:20:50 -040071 type testCase struct {
72 input string
73 command string
74 }
75
76 var testCases = []testCase{
77 {`
Liz Kammer8d62a4f2021-04-08 09:47:28 -040078{
Jason Wu118fd2b2022-10-27 18:41:15 +000079 "artifacts": [
80 { "id": 1, "path_fragment_id": 1 },
81 { "id": 2, "path_fragment_id": 2 }],
82 "actions": [{
83 "target_Id": 1,
84 "action_Key": "x",
85 "mnemonic": "x",
86 "arguments": ["touch", "foo"],
87 "input_dep_set_ids": [1],
88 "output_Ids": [1],
89 "primary_output_id": 1
90 }],
91 "dep_set_of_files": [
92 { "id": 1, "direct_artifact_ids": [1, 2] }],
93 "path_fragments": [
94 { "id": 1, "label": "one" },
95 { "id": 2, "label": "two" }]
Liz Kammer8d62a4f2021-04-08 09:47:28 -040096}`,
Jingwen Chenf3b1ec32022-11-07 15:02:48 +000097 "cd 'test/exec_root' && rm -rf 'one' && touch foo",
Usta Shresthaacd5a0c2022-06-22 11:20:50 -040098 }, {`
99{
Jason Wu118fd2b2022-10-27 18:41:15 +0000100 "artifacts": [
101 { "id": 1, "path_fragment_id": 10 },
102 { "id": 2, "path_fragment_id": 20 }],
103 "actions": [{
104 "target_Id": 100,
105 "action_Key": "x",
106 "mnemonic": "x",
107 "arguments": ["bogus", "command"],
108 "output_Ids": [1, 2],
109 "primary_output_id": 1
110 }],
111 "path_fragments": [
112 { "id": 10, "label": "one", "parent_id": 30 },
113 { "id": 20, "label": "one.d", "parent_id": 30 },
114 { "id": 30, "label": "parent" }]
Usta Shresthaacd5a0c2022-06-22 11:20:50 -0400115}`,
Jingwen Chenf3b1ec32022-11-07 15:02:48 +0000116 `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 -0400117 },
Liz Kammer8d62a4f2021-04-08 09:47:28 -0400118 }
119
Usta Shresthaef922252022-06-02 14:23:02 -0400120 for i, testCase := range testCases {
Jason Wu118fd2b2022-10-27 18:41:15 +0000121 data, err := JsonToActionGraphContainer(testCase.input)
122 if err != nil {
123 t.Error(err)
124 }
Usta Shresthaacd5a0c2022-06-22 11:20:50 -0400125 bazelContext, _ := testBazelContext(t, map[bazelCommand]string{
Jason Wu118fd2b2022-10-27 18:41:15 +0000126 bazelCommand{command: "aquery", expression: "deps(@soong_injection//mixed_builds:buildroot)"}: string(data)})
Usta Shresthaacd5a0c2022-06-22 11:20:50 -0400127
Liz Kammer690fbac2023-02-10 11:11:17 -0500128 err = bazelContext.InvokeBazel(testConfig, &testInvokeBazelContext{})
Usta Shresthaacd5a0c2022-06-22 11:20:50 -0400129 if err != nil {
Usta Shresthaef922252022-06-02 14:23:02 -0400130 t.Fatalf("testCase #%d: did not expect error invoking Bazel, but got %s", i+1, err)
Usta Shresthaacd5a0c2022-06-22 11:20:50 -0400131 }
132
133 got := bazelContext.BuildStatementsToRegister()
134 if want := 1; len(got) != want {
Sasha Smundake3cf1ab2022-06-30 11:36:18 -0700135 t.Fatalf("expected %d registered build statements, but got %#v", want, got)
Usta Shresthaacd5a0c2022-06-22 11:20:50 -0400136 }
137
138 cmd := RuleBuilderCommand{}
Colin Crossd5c7ddb2022-12-06 16:27:17 -0800139 ctx := builderContextForTests{PathContextForTesting(TestConfig("out", nil, "", nil))}
140 createCommand(&cmd, got[0], "test/exec_root", "test/bazel_out", ctx)
Usta Shresthaef922252022-06-02 14:23:02 -0400141 if actual, expected := cmd.buf.String(), testCase.command; expected != actual {
142 t.Errorf("expected: [%s], actual: [%s]", expected, actual)
Usta Shresthaacd5a0c2022-06-22 11:20:50 -0400143 }
Liz Kammer8d62a4f2021-04-08 09:47:28 -0400144 }
145}
146
Yu Liu8d82ac52022-05-17 15:13:28 -0700147func TestCoverageFlagsAfterInvokeBazel(t *testing.T) {
148 testConfig.productVariables.ClangCoverage = boolPtr(true)
149
150 testConfig.productVariables.NativeCoveragePaths = []string{"foo1", "foo2"}
151 testConfig.productVariables.NativeCoverageExcludePaths = []string{"bar1", "bar2"}
152 verifyExtraFlags(t, testConfig, `--collect_code_coverage --instrumentation_filter=+foo1,+foo2,-bar1,-bar2`)
153
154 testConfig.productVariables.NativeCoveragePaths = []string{"foo1"}
155 testConfig.productVariables.NativeCoverageExcludePaths = []string{"bar1"}
156 verifyExtraFlags(t, testConfig, `--collect_code_coverage --instrumentation_filter=+foo1,-bar1`)
157
158 testConfig.productVariables.NativeCoveragePaths = []string{"foo1"}
159 testConfig.productVariables.NativeCoverageExcludePaths = nil
160 verifyExtraFlags(t, testConfig, `--collect_code_coverage --instrumentation_filter=+foo1`)
161
162 testConfig.productVariables.NativeCoveragePaths = nil
163 testConfig.productVariables.NativeCoverageExcludePaths = []string{"bar1"}
164 verifyExtraFlags(t, testConfig, `--collect_code_coverage --instrumentation_filter=-bar1`)
165
Wei Licbd181c2022-11-16 08:59:23 -0800166 testConfig.productVariables.NativeCoveragePaths = []string{"*"}
167 testConfig.productVariables.NativeCoverageExcludePaths = nil
168 verifyExtraFlags(t, testConfig, `--collect_code_coverage --instrumentation_filter=+.*`)
169
Yu Liu8d82ac52022-05-17 15:13:28 -0700170 testConfig.productVariables.ClangCoverage = boolPtr(false)
171 actual := verifyExtraFlags(t, testConfig, ``)
172 if strings.Contains(actual, "--collect_code_coverage") ||
173 strings.Contains(actual, "--instrumentation_filter=") {
174 t.Errorf("Expected code coverage disabled, but got %#v", actual)
175 }
176}
177
Chris Parsons3a8d0fb2023-02-02 18:16:29 -0500178func TestBazelRequestsSorted(t *testing.T) {
179 bazelContext, _ := testBazelContext(t, map[bazelCommand]string{})
180
181 bazelContext.QueueBazelRequest("zzz", cquery.GetOutputFiles, configKey{"arm64_armv8-a", Android})
182 bazelContext.QueueBazelRequest("ccc", cquery.GetApexInfo, configKey{"arm64_armv8-a", Android})
183 bazelContext.QueueBazelRequest("duplicate", cquery.GetOutputFiles, configKey{"arm64_armv8-a", Android})
184 bazelContext.QueueBazelRequest("duplicate", cquery.GetOutputFiles, configKey{"arm64_armv8-a", Android})
185 bazelContext.QueueBazelRequest("xxx", cquery.GetOutputFiles, configKey{"arm64_armv8-a", Linux})
186 bazelContext.QueueBazelRequest("aaa", cquery.GetOutputFiles, configKey{"arm64_armv8-a", Android})
187 bazelContext.QueueBazelRequest("aaa", cquery.GetOutputFiles, configKey{"otherarch", Android})
188 bazelContext.QueueBazelRequest("bbb", cquery.GetOutputFiles, configKey{"otherarch", Android})
189
190 if len(bazelContext.requests) != 7 {
191 t.Error("Expected 7 request elements, but got", len(bazelContext.requests))
192 }
193
194 lastString := ""
195 for _, val := range bazelContext.requests {
196 thisString := val.String()
197 if thisString <= lastString {
198 t.Errorf("Requests are not ordered correctly. '%s' came before '%s'", lastString, thisString)
199 }
200 lastString = thisString
201 }
202}
203
Yu Liu8d82ac52022-05-17 15:13:28 -0700204func verifyExtraFlags(t *testing.T, config Config, expected string) string {
205 bazelContext, _ := testBazelContext(t, map[bazelCommand]string{})
206
Liz Kammer690fbac2023-02-10 11:11:17 -0500207 err := bazelContext.InvokeBazel(config, &testInvokeBazelContext{})
Yu Liu8d82ac52022-05-17 15:13:28 -0700208 if err != nil {
209 t.Fatalf("Did not expect error invoking Bazel, but got %s", err)
210 }
211
212 flags := bazelContext.bazelRunner.(*mockBazelRunner).extraFlags
213 if expected := 3; len(flags) != expected {
214 t.Errorf("Expected %d extra flags got %#v", expected, flags)
215 }
216
217 actual := flags[1]
218 if !strings.Contains(actual, expected) {
219 t.Errorf("Expected %#v got %#v", expected, actual)
220 }
221
222 return actual
223}
224
Sasha Smundak39a301c2022-12-29 17:11:49 -0800225func testBazelContext(t *testing.T, bazelCommandResults map[bazelCommand]string) (*mixedBuildBazelContext, string) {
Liz Kammer8d62a4f2021-04-08 09:47:28 -0400226 t.Helper()
227 p := bazelPaths{
Lukacs T. Berki9f6c24a2021-08-26 15:07:24 +0200228 soongOutDir: t.TempDir(),
Liz Kammer8d62a4f2021-04-08 09:47:28 -0400229 outputBase: "outputbase",
230 workspaceDir: "workspace_dir",
231 }
Lukacs T. Berki3069dd92021-05-11 16:54:29 +0200232 aqueryCommand := bazelCommand{command: "aquery", expression: "deps(@soong_injection//mixed_builds:buildroot)"}
Liz Kammer8d62a4f2021-04-08 09:47:28 -0400233 if _, exists := bazelCommandResults[aqueryCommand]; !exists {
Sasha Smundak4975c822022-11-16 15:28:18 -0800234 bazelCommandResults[aqueryCommand] = ""
Liz Kammer8d62a4f2021-04-08 09:47:28 -0400235 }
236 runner := &mockBazelRunner{bazelCommandResults: bazelCommandResults}
Sasha Smundak39a301c2022-12-29 17:11:49 -0800237 return &mixedBuildBazelContext{
Liz Kammer8d62a4f2021-04-08 09:47:28 -0400238 bazelRunner: runner,
239 paths: &p,
Lukacs T. Berki9f6c24a2021-08-26 15:07:24 +0200240 }, p.soongOutDir
Liz Kammer8d62a4f2021-04-08 09:47:28 -0400241}
Jason Wu118fd2b2022-10-27 18:41:15 +0000242
243// Transform the json format to ActionGraphContainer
244func JsonToActionGraphContainer(inputString string) ([]byte, error) {
245 var aqueryProtoResult analysis_v2_proto.ActionGraphContainer
246 err := json.Unmarshal([]byte(inputString), &aqueryProtoResult)
247 if err != nil {
248 return []byte(""), err
249 }
250 data, _ := proto.Marshal(&aqueryProtoResult)
251 return data, err
252}