blob: 6e3acd5f7b8a16823f678640b45c75a8279756a6 [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
14 "google.golang.org/protobuf/proto"
Liz Kammer8d62a4f2021-04-08 09:47:28 -040015)
16
Yu Liu8d82ac52022-05-17 15:13:28 -070017var testConfig = TestConfig("out", nil, "", nil)
18
Liz Kammer8d62a4f2021-04-08 09:47:28 -040019func TestRequestResultsAfterInvokeBazel(t *testing.T) {
Chris Parsons86dc2c22022-09-28 14:58:41 -040020 label := "@//foo:bar"
Liz Kammer0940b892022-03-18 15:55:04 -040021 cfg := configKey{"arm64_armv8-a", Android}
Liz Kammer8d62a4f2021-04-08 09:47:28 -040022 bazelContext, _ := testBazelContext(t, map[bazelCommand]string{
Chris Parsons86dc2c22022-09-28 14:58:41 -040023 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 -040024 })
Chris Parsonsf874e462022-05-10 13:50:12 -040025 bazelContext.QueueBazelRequest(label, cquery.GetOutputFiles, cfg)
Yu Liu8d82ac52022-05-17 15:13:28 -070026 err := bazelContext.InvokeBazel(testConfig)
Liz Kammer8d62a4f2021-04-08 09:47:28 -040027 if err != nil {
28 t.Fatalf("Did not expect error invoking Bazel, but got %s", err)
29 }
Chris Parsonsf874e462022-05-10 13:50:12 -040030 g, err := bazelContext.GetOutputFiles(label, cfg)
31 if err != nil {
32 t.Errorf("Expected cquery results after running InvokeBazel(), but got err %v", err)
Liz Kammer8d62a4f2021-04-08 09:47:28 -040033 } else if w := []string{"out/foo/bar.txt"}; !reflect.DeepEqual(w, g) {
34 t.Errorf("Expected output %s, got %s", w, g)
35 }
36}
37
38func TestInvokeBazelWritesBazelFiles(t *testing.T) {
39 bazelContext, baseDir := testBazelContext(t, map[bazelCommand]string{})
Yu Liu8d82ac52022-05-17 15:13:28 -070040 err := bazelContext.InvokeBazel(testConfig)
Liz Kammer8d62a4f2021-04-08 09:47:28 -040041 if err != nil {
42 t.Fatalf("Did not expect error invoking Bazel, but got %s", err)
43 }
Lukacs T. Berki3069dd92021-05-11 16:54:29 +020044 if _, err := os.Stat(filepath.Join(baseDir, "soong_injection", "mixed_builds", "main.bzl")); os.IsNotExist(err) {
Liz Kammer8d62a4f2021-04-08 09:47:28 -040045 t.Errorf("Expected main.bzl to exist, but it does not")
46 } else if err != nil {
47 t.Errorf("Unexpected error stating main.bzl %s", err)
48 }
49
Lukacs T. Berki3069dd92021-05-11 16:54:29 +020050 if _, err := os.Stat(filepath.Join(baseDir, "soong_injection", "mixed_builds", "BUILD.bazel")); os.IsNotExist(err) {
Liz Kammer8d62a4f2021-04-08 09:47:28 -040051 t.Errorf("Expected BUILD.bazel to exist, but it does not")
52 } else if err != nil {
53 t.Errorf("Unexpected error stating BUILD.bazel %s", err)
54 }
55
Liz Kammer286c9fa2021-04-21 08:46:34 -040056 if _, err := os.Stat(filepath.Join(baseDir, "soong_injection", "WORKSPACE.bazel")); os.IsNotExist(err) {
Liz Kammer8d62a4f2021-04-08 09:47:28 -040057 t.Errorf("Expected WORKSPACE.bazel to exist, but it does not")
58 } else if err != nil {
59 t.Errorf("Unexpected error stating WORKSPACE.bazel %s", err)
60 }
61}
62
63func TestInvokeBazelPopulatesBuildStatements(t *testing.T) {
Usta Shresthaacd5a0c2022-06-22 11:20:50 -040064 type testCase struct {
65 input string
66 command string
67 }
68
69 var testCases = []testCase{
70 {`
Liz Kammer8d62a4f2021-04-08 09:47:28 -040071{
Jason Wu118fd2b2022-10-27 18:41:15 +000072 "artifacts": [
73 { "id": 1, "path_fragment_id": 1 },
74 { "id": 2, "path_fragment_id": 2 }],
75 "actions": [{
76 "target_Id": 1,
77 "action_Key": "x",
78 "mnemonic": "x",
79 "arguments": ["touch", "foo"],
80 "input_dep_set_ids": [1],
81 "output_Ids": [1],
82 "primary_output_id": 1
83 }],
84 "dep_set_of_files": [
85 { "id": 1, "direct_artifact_ids": [1, 2] }],
86 "path_fragments": [
87 { "id": 1, "label": "one" },
88 { "id": 2, "label": "two" }]
Liz Kammer8d62a4f2021-04-08 09:47:28 -040089}`,
Jingwen Chenf3b1ec32022-11-07 15:02:48 +000090 "cd 'test/exec_root' && rm -rf 'one' && touch foo",
Usta Shresthaacd5a0c2022-06-22 11:20:50 -040091 }, {`
92{
Jason Wu118fd2b2022-10-27 18:41:15 +000093 "artifacts": [
94 { "id": 1, "path_fragment_id": 10 },
95 { "id": 2, "path_fragment_id": 20 }],
96 "actions": [{
97 "target_Id": 100,
98 "action_Key": "x",
99 "mnemonic": "x",
100 "arguments": ["bogus", "command"],
101 "output_Ids": [1, 2],
102 "primary_output_id": 1
103 }],
104 "path_fragments": [
105 { "id": 10, "label": "one", "parent_id": 30 },
106 { "id": 20, "label": "one.d", "parent_id": 30 },
107 { "id": 30, "label": "parent" }]
Usta Shresthaacd5a0c2022-06-22 11:20:50 -0400108}`,
Jingwen Chenf3b1ec32022-11-07 15:02:48 +0000109 `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 -0400110 },
Liz Kammer8d62a4f2021-04-08 09:47:28 -0400111 }
112
Usta Shresthaef922252022-06-02 14:23:02 -0400113 for i, testCase := range testCases {
Jason Wu118fd2b2022-10-27 18:41:15 +0000114 data, err := JsonToActionGraphContainer(testCase.input)
115 if err != nil {
116 t.Error(err)
117 }
Usta Shresthaacd5a0c2022-06-22 11:20:50 -0400118 bazelContext, _ := testBazelContext(t, map[bazelCommand]string{
Jason Wu118fd2b2022-10-27 18:41:15 +0000119 bazelCommand{command: "aquery", expression: "deps(@soong_injection//mixed_builds:buildroot)"}: string(data)})
Usta Shresthaacd5a0c2022-06-22 11:20:50 -0400120
Jason Wu118fd2b2022-10-27 18:41:15 +0000121 err = bazelContext.InvokeBazel(testConfig)
Usta Shresthaacd5a0c2022-06-22 11:20:50 -0400122 if err != nil {
Usta Shresthaef922252022-06-02 14:23:02 -0400123 t.Fatalf("testCase #%d: did not expect error invoking Bazel, but got %s", i+1, err)
Usta Shresthaacd5a0c2022-06-22 11:20:50 -0400124 }
125
126 got := bazelContext.BuildStatementsToRegister()
127 if want := 1; len(got) != want {
Sasha Smundake3cf1ab2022-06-30 11:36:18 -0700128 t.Fatalf("expected %d registered build statements, but got %#v", want, got)
Usta Shresthaacd5a0c2022-06-22 11:20:50 -0400129 }
130
131 cmd := RuleBuilderCommand{}
Usta Shresthaef922252022-06-02 14:23:02 -0400132 createCommand(&cmd, got[0], "test/exec_root", "test/bazel_out", PathContextForTesting(TestConfig("out", nil, "", nil)))
133 if actual, expected := cmd.buf.String(), testCase.command; expected != actual {
134 t.Errorf("expected: [%s], actual: [%s]", expected, actual)
Usta Shresthaacd5a0c2022-06-22 11:20:50 -0400135 }
Liz Kammer8d62a4f2021-04-08 09:47:28 -0400136 }
137}
138
Yu Liu8d82ac52022-05-17 15:13:28 -0700139func TestCoverageFlagsAfterInvokeBazel(t *testing.T) {
140 testConfig.productVariables.ClangCoverage = boolPtr(true)
141
142 testConfig.productVariables.NativeCoveragePaths = []string{"foo1", "foo2"}
143 testConfig.productVariables.NativeCoverageExcludePaths = []string{"bar1", "bar2"}
144 verifyExtraFlags(t, testConfig, `--collect_code_coverage --instrumentation_filter=+foo1,+foo2,-bar1,-bar2`)
145
146 testConfig.productVariables.NativeCoveragePaths = []string{"foo1"}
147 testConfig.productVariables.NativeCoverageExcludePaths = []string{"bar1"}
148 verifyExtraFlags(t, testConfig, `--collect_code_coverage --instrumentation_filter=+foo1,-bar1`)
149
150 testConfig.productVariables.NativeCoveragePaths = []string{"foo1"}
151 testConfig.productVariables.NativeCoverageExcludePaths = nil
152 verifyExtraFlags(t, testConfig, `--collect_code_coverage --instrumentation_filter=+foo1`)
153
154 testConfig.productVariables.NativeCoveragePaths = nil
155 testConfig.productVariables.NativeCoverageExcludePaths = []string{"bar1"}
156 verifyExtraFlags(t, testConfig, `--collect_code_coverage --instrumentation_filter=-bar1`)
157
158 testConfig.productVariables.ClangCoverage = boolPtr(false)
159 actual := verifyExtraFlags(t, testConfig, ``)
160 if strings.Contains(actual, "--collect_code_coverage") ||
161 strings.Contains(actual, "--instrumentation_filter=") {
162 t.Errorf("Expected code coverage disabled, but got %#v", actual)
163 }
164}
165
166func verifyExtraFlags(t *testing.T, config Config, expected string) string {
167 bazelContext, _ := testBazelContext(t, map[bazelCommand]string{})
168
169 err := bazelContext.InvokeBazel(config)
170 if err != nil {
171 t.Fatalf("Did not expect error invoking Bazel, but got %s", err)
172 }
173
174 flags := bazelContext.bazelRunner.(*mockBazelRunner).extraFlags
175 if expected := 3; len(flags) != expected {
176 t.Errorf("Expected %d extra flags got %#v", expected, flags)
177 }
178
179 actual := flags[1]
180 if !strings.Contains(actual, expected) {
181 t.Errorf("Expected %#v got %#v", expected, actual)
182 }
183
184 return actual
185}
186
Liz Kammer8d62a4f2021-04-08 09:47:28 -0400187func testBazelContext(t *testing.T, bazelCommandResults map[bazelCommand]string) (*bazelContext, string) {
188 t.Helper()
189 p := bazelPaths{
Lukacs T. Berki9f6c24a2021-08-26 15:07:24 +0200190 soongOutDir: t.TempDir(),
Liz Kammer8d62a4f2021-04-08 09:47:28 -0400191 outputBase: "outputbase",
192 workspaceDir: "workspace_dir",
193 }
Lukacs T. Berki3069dd92021-05-11 16:54:29 +0200194 aqueryCommand := bazelCommand{command: "aquery", expression: "deps(@soong_injection//mixed_builds:buildroot)"}
Liz Kammer8d62a4f2021-04-08 09:47:28 -0400195 if _, exists := bazelCommandResults[aqueryCommand]; !exists {
196 bazelCommandResults[aqueryCommand] = "{}\n"
197 }
198 runner := &mockBazelRunner{bazelCommandResults: bazelCommandResults}
199 return &bazelContext{
200 bazelRunner: runner,
201 paths: &p,
202 requests: map[cqueryKey]bool{},
Lukacs T. Berki9f6c24a2021-08-26 15:07:24 +0200203 }, p.soongOutDir
Liz Kammer8d62a4f2021-04-08 09:47:28 -0400204}
Jason Wu118fd2b2022-10-27 18:41:15 +0000205
206// Transform the json format to ActionGraphContainer
207func JsonToActionGraphContainer(inputString string) ([]byte, error) {
208 var aqueryProtoResult analysis_v2_proto.ActionGraphContainer
209 err := json.Unmarshal([]byte(inputString), &aqueryProtoResult)
210 if err != nil {
211 return []byte(""), err
212 }
213 data, _ := proto.Marshal(&aqueryProtoResult)
214 return data, err
215}