blob: c8572721712e91a32f8bea43bd2a99e6597e64e6 [file] [log] [blame]
Liz Kammer8d62a4f2021-04-08 09:47:28 -04001package android
2
3import (
Jason Wu6fe87212022-10-21 02:57:41 -04004 "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 Wu6fe87212022-10-21 02:57:41 -040012 "google.golang.org/protobuf/proto"
13 analysis_v2_proto "prebuilts/bazel/common/proto/analysis_v2"
Liz Kammer8d62a4f2021-04-08 09:47:28 -040014)
15
Yu Liu8d82ac52022-05-17 15:13:28 -070016var testConfig = TestConfig("out", nil, "", nil)
17
Liz Kammer8d62a4f2021-04-08 09:47:28 -040018func TestRequestResultsAfterInvokeBazel(t *testing.T) {
Chris Parsons86dc2c22022-09-28 14:58:41 -040019 label := "@//foo:bar"
Liz Kammer0940b892022-03-18 15:55:04 -040020 cfg := configKey{"arm64_armv8-a", Android}
Liz Kammer8d62a4f2021-04-08 09:47:28 -040021 bazelContext, _ := testBazelContext(t, map[bazelCommand]string{
Chris Parsons86dc2c22022-09-28 14:58:41 -040022 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 -040023 })
Chris Parsonsf874e462022-05-10 13:50:12 -040024 bazelContext.QueueBazelRequest(label, cquery.GetOutputFiles, cfg)
Yu Liu8d82ac52022-05-17 15:13:28 -070025 err := bazelContext.InvokeBazel(testConfig)
Liz Kammer8d62a4f2021-04-08 09:47:28 -040026 if err != nil {
27 t.Fatalf("Did not expect error invoking Bazel, but got %s", err)
28 }
Chris Parsonsf874e462022-05-10 13:50:12 -040029 g, err := bazelContext.GetOutputFiles(label, cfg)
30 if err != nil {
31 t.Errorf("Expected cquery results after running InvokeBazel(), but got err %v", err)
Liz Kammer8d62a4f2021-04-08 09:47:28 -040032 } else if w := []string{"out/foo/bar.txt"}; !reflect.DeepEqual(w, g) {
33 t.Errorf("Expected output %s, got %s", w, g)
34 }
35}
36
37func TestInvokeBazelWritesBazelFiles(t *testing.T) {
38 bazelContext, baseDir := testBazelContext(t, map[bazelCommand]string{})
Yu Liu8d82ac52022-05-17 15:13:28 -070039 err := bazelContext.InvokeBazel(testConfig)
Liz Kammer8d62a4f2021-04-08 09:47:28 -040040 if err != nil {
41 t.Fatalf("Did not expect error invoking Bazel, but got %s", err)
42 }
Lukacs T. Berki3069dd92021-05-11 16:54:29 +020043 if _, err := os.Stat(filepath.Join(baseDir, "soong_injection", "mixed_builds", "main.bzl")); os.IsNotExist(err) {
Liz Kammer8d62a4f2021-04-08 09:47:28 -040044 t.Errorf("Expected main.bzl to exist, but it does not")
45 } else if err != nil {
46 t.Errorf("Unexpected error stating main.bzl %s", err)
47 }
48
Lukacs T. Berki3069dd92021-05-11 16:54:29 +020049 if _, err := os.Stat(filepath.Join(baseDir, "soong_injection", "mixed_builds", "BUILD.bazel")); os.IsNotExist(err) {
Liz Kammer8d62a4f2021-04-08 09:47:28 -040050 t.Errorf("Expected BUILD.bazel to exist, but it does not")
51 } else if err != nil {
52 t.Errorf("Unexpected error stating BUILD.bazel %s", err)
53 }
54
Liz Kammer286c9fa2021-04-21 08:46:34 -040055 if _, err := os.Stat(filepath.Join(baseDir, "soong_injection", "WORKSPACE.bazel")); os.IsNotExist(err) {
Liz Kammer8d62a4f2021-04-08 09:47:28 -040056 t.Errorf("Expected WORKSPACE.bazel to exist, but it does not")
57 } else if err != nil {
58 t.Errorf("Unexpected error stating WORKSPACE.bazel %s", err)
59 }
60}
61
62func TestInvokeBazelPopulatesBuildStatements(t *testing.T) {
Usta Shresthaacd5a0c2022-06-22 11:20:50 -040063 type testCase struct {
64 input string
65 command string
66 }
67
68 var testCases = []testCase{
69 {`
Liz Kammer8d62a4f2021-04-08 09:47:28 -040070{
Jason Wu6fe87212022-10-21 02:57:41 -040071 "artifacts": [
72 { "id": 1, "path_fragment_id": 1 },
73 { "id": 2, "path_fragment_id": 2 }],
74 "actions": [{
75 "target_Id": 1,
76 "action_Key": "x",
77 "mnemonic": "x",
78 "arguments": ["touch", "foo"],
79 "input_dep_set_ids": [1],
80 "output_Ids": [1],
81 "primary_output_id": 1
82 }],
83 "dep_set_of_files": [
84 { "id": 1, "direct_artifact_ids": [1, 2] }],
85 "path_fragments": [
86 { "id": 1, "label": "one" },
87 { "id": 2, "label": "two" }]
Liz Kammer8d62a4f2021-04-08 09:47:28 -040088}`,
Usta Shresthaef922252022-06-02 14:23:02 -040089 "cd 'test/exec_root' && rm -f 'one' && touch foo",
Usta Shresthaacd5a0c2022-06-22 11:20:50 -040090 }, {`
91{
Jason Wu6fe87212022-10-21 02:57:41 -040092 "artifacts": [
93 { "id": 1, "path_fragment_id": 10 },
94 { "id": 2, "path_fragment_id": 20 }],
95 "actions": [{
96 "target_Id": 100,
97 "action_Key": "x",
98 "mnemonic": "x",
99 "arguments": ["bogus", "command"],
100 "output_Ids": [1, 2],
101 "primary_output_id": 1
102 }],
103 "path_fragments": [
104 { "id": 10, "label": "one", "parent_id": 30 },
105 { "id": 20, "label": "one.d", "parent_id": 30 },
106 { "id": 30, "label": "parent" }]
Usta Shresthaacd5a0c2022-06-22 11:20:50 -0400107}`,
Usta Shresthaef922252022-06-02 14:23:02 -0400108 `cd 'test/exec_root' && rm -f '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 -0400109 },
Liz Kammer8d62a4f2021-04-08 09:47:28 -0400110 }
111
Usta Shresthaef922252022-06-02 14:23:02 -0400112 for i, testCase := range testCases {
Jason Wu6fe87212022-10-21 02:57:41 -0400113 data, err := JsonToActionGraphContainer(testCase.input)
114 if err != nil {
115 t.Error(err)
116 }
Usta Shresthaacd5a0c2022-06-22 11:20:50 -0400117 bazelContext, _ := testBazelContext(t, map[bazelCommand]string{
Jason Wu6fe87212022-10-21 02:57:41 -0400118 bazelCommand{command: "aquery", expression: "deps(@soong_injection//mixed_builds:buildroot)"}: string(data)})
Usta Shresthaacd5a0c2022-06-22 11:20:50 -0400119
Jason Wu6fe87212022-10-21 02:57:41 -0400120 err = bazelContext.InvokeBazel(testConfig)
Usta Shresthaacd5a0c2022-06-22 11:20:50 -0400121 if err != nil {
Usta Shresthaef922252022-06-02 14:23:02 -0400122 t.Fatalf("testCase #%d: did not expect error invoking Bazel, but got %s", i+1, err)
Usta Shresthaacd5a0c2022-06-22 11:20:50 -0400123 }
124
125 got := bazelContext.BuildStatementsToRegister()
126 if want := 1; len(got) != want {
Sasha Smundake3cf1ab2022-06-30 11:36:18 -0700127 t.Fatalf("expected %d registered build statements, but got %#v", want, got)
Usta Shresthaacd5a0c2022-06-22 11:20:50 -0400128 }
129
130 cmd := RuleBuilderCommand{}
Usta Shresthaef922252022-06-02 14:23:02 -0400131 createCommand(&cmd, got[0], "test/exec_root", "test/bazel_out", PathContextForTesting(TestConfig("out", nil, "", nil)))
132 if actual, expected := cmd.buf.String(), testCase.command; expected != actual {
133 t.Errorf("expected: [%s], actual: [%s]", expected, actual)
Usta Shresthaacd5a0c2022-06-22 11:20:50 -0400134 }
Liz Kammer8d62a4f2021-04-08 09:47:28 -0400135 }
136}
137
Yu Liu8d82ac52022-05-17 15:13:28 -0700138func TestCoverageFlagsAfterInvokeBazel(t *testing.T) {
139 testConfig.productVariables.ClangCoverage = boolPtr(true)
140
141 testConfig.productVariables.NativeCoveragePaths = []string{"foo1", "foo2"}
142 testConfig.productVariables.NativeCoverageExcludePaths = []string{"bar1", "bar2"}
143 verifyExtraFlags(t, testConfig, `--collect_code_coverage --instrumentation_filter=+foo1,+foo2,-bar1,-bar2`)
144
145 testConfig.productVariables.NativeCoveragePaths = []string{"foo1"}
146 testConfig.productVariables.NativeCoverageExcludePaths = []string{"bar1"}
147 verifyExtraFlags(t, testConfig, `--collect_code_coverage --instrumentation_filter=+foo1,-bar1`)
148
149 testConfig.productVariables.NativeCoveragePaths = []string{"foo1"}
150 testConfig.productVariables.NativeCoverageExcludePaths = nil
151 verifyExtraFlags(t, testConfig, `--collect_code_coverage --instrumentation_filter=+foo1`)
152
153 testConfig.productVariables.NativeCoveragePaths = nil
154 testConfig.productVariables.NativeCoverageExcludePaths = []string{"bar1"}
155 verifyExtraFlags(t, testConfig, `--collect_code_coverage --instrumentation_filter=-bar1`)
156
157 testConfig.productVariables.ClangCoverage = boolPtr(false)
158 actual := verifyExtraFlags(t, testConfig, ``)
159 if strings.Contains(actual, "--collect_code_coverage") ||
160 strings.Contains(actual, "--instrumentation_filter=") {
161 t.Errorf("Expected code coverage disabled, but got %#v", actual)
162 }
163}
164
165func verifyExtraFlags(t *testing.T, config Config, expected string) string {
166 bazelContext, _ := testBazelContext(t, map[bazelCommand]string{})
167
168 err := bazelContext.InvokeBazel(config)
169 if err != nil {
170 t.Fatalf("Did not expect error invoking Bazel, but got %s", err)
171 }
172
173 flags := bazelContext.bazelRunner.(*mockBazelRunner).extraFlags
174 if expected := 3; len(flags) != expected {
175 t.Errorf("Expected %d extra flags got %#v", expected, flags)
176 }
177
178 actual := flags[1]
179 if !strings.Contains(actual, expected) {
180 t.Errorf("Expected %#v got %#v", expected, actual)
181 }
182
183 return actual
184}
185
Liz Kammer8d62a4f2021-04-08 09:47:28 -0400186func testBazelContext(t *testing.T, bazelCommandResults map[bazelCommand]string) (*bazelContext, string) {
187 t.Helper()
188 p := bazelPaths{
Lukacs T. Berki9f6c24a2021-08-26 15:07:24 +0200189 soongOutDir: t.TempDir(),
Liz Kammer8d62a4f2021-04-08 09:47:28 -0400190 outputBase: "outputbase",
191 workspaceDir: "workspace_dir",
192 }
Lukacs T. Berki3069dd92021-05-11 16:54:29 +0200193 aqueryCommand := bazelCommand{command: "aquery", expression: "deps(@soong_injection//mixed_builds:buildroot)"}
Liz Kammer8d62a4f2021-04-08 09:47:28 -0400194 if _, exists := bazelCommandResults[aqueryCommand]; !exists {
195 bazelCommandResults[aqueryCommand] = "{}\n"
196 }
197 runner := &mockBazelRunner{bazelCommandResults: bazelCommandResults}
198 return &bazelContext{
199 bazelRunner: runner,
200 paths: &p,
201 requests: map[cqueryKey]bool{},
Lukacs T. Berki9f6c24a2021-08-26 15:07:24 +0200202 }, p.soongOutDir
Liz Kammer8d62a4f2021-04-08 09:47:28 -0400203}
Jason Wu6fe87212022-10-21 02:57:41 -0400204
205// Transform the json format to ActionGraphContainer
206func JsonToActionGraphContainer(inputString string) ([]byte, error) {
207 var aqueryProtoResult analysis_v2_proto.ActionGraphContainer
208 err := json.Unmarshal([]byte(inputString), &aqueryProtoResult)
209 if err != nil {
210 return []byte(""), err
211 }
212 data, _ := proto.Marshal(&aqueryProtoResult)
213 return data, err
214}