blob: cbd27919cdb54c89391d2c380e0af8f08a26aa8e [file] [log] [blame]
Chris Parsons4f069892021-01-15 12:22:41 -05001// 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 bazel
16
17import (
Jason Wu118fd2b2022-10-27 18:41:15 +000018 "encoding/json"
Chris Parsons4f069892021-01-15 12:22:41 -050019 "fmt"
20 "reflect"
Usta Shrestha1c4a3ea2022-06-23 16:09:32 -040021 "sort"
Chris Parsons4f069892021-01-15 12:22:41 -050022 "testing"
Jason Wu118fd2b2022-10-27 18:41:15 +000023
Jason Wu118fd2b2022-10-27 18:41:15 +000024 analysis_v2_proto "prebuilts/bazel/common/proto/analysis_v2"
Liz Kammer690fbac2023-02-10 11:11:17 -050025
26 "github.com/google/blueprint/metrics"
27 "google.golang.org/protobuf/proto"
Chris Parsons4f069892021-01-15 12:22:41 -050028)
29
30func TestAqueryMultiArchGenrule(t *testing.T) {
31 // This input string is retrieved from a real build of bionic-related genrules.
32 const inputString = `
33{
Jason Wu118fd2b2022-10-27 18:41:15 +000034 "Artifacts": [
35 { "Id": 1, "path_fragment_id": 1 },
36 { "Id": 2, "path_fragment_id": 6 },
37 { "Id": 3, "path_fragment_id": 8 },
38 { "Id": 4, "path_fragment_id": 12 },
39 { "Id": 5, "path_fragment_id": 19 },
40 { "Id": 6, "path_fragment_id": 20 },
41 { "Id": 7, "path_fragment_id": 21 }],
42 "Actions": [{
43 "target_id": 1,
44 "action_key": "ab53f6ecbdc2ee8cb8812613b63205464f1f5083f6dca87081a0a398c0f1ecf7",
45 "Mnemonic": "Genrule",
46 "configuration_id": 1,
47 "Arguments": ["/bin/bash", "-c", "source ../bazel_tools/tools/genrule/genrule-setup.sh; ../sourceroot/bionic/libc/tools/gensyscalls.py arm ../sourceroot/bionic/libc/SYSCALLS.TXT \u003e bazel-out/sourceroot/k8-fastbuild/bin/bionic/libc/syscalls-arm.S"],
48 "environment_variables": [{
49 "Key": "PATH",
50 "Value": "/bin:/usr/bin:/usr/local/bin"
51 }],
52 "input_dep_set_ids": [1],
53 "output_ids": [4],
54 "primary_output_id": 4
55 }, {
56 "target_id": 2,
57 "action_key": "9f4309ce165dac458498cb92811c18b0b7919782cc37b82a42d2141b8cc90826",
58 "Mnemonic": "Genrule",
59 "configuration_id": 1,
60 "Arguments": ["/bin/bash", "-c", "source ../bazel_tools/tools/genrule/genrule-setup.sh; ../sourceroot/bionic/libc/tools/gensyscalls.py x86 ../sourceroot/bionic/libc/SYSCALLS.TXT \u003e bazel-out/sourceroot/k8-fastbuild/bin/bionic/libc/syscalls-x86.S"],
61 "environment_variables": [{
62 "Key": "PATH",
63 "Value": "/bin:/usr/bin:/usr/local/bin"
64 }],
65 "input_dep_set_ids": [2],
66 "output_ids": [5],
67 "primary_output_id": 5
68 }, {
69 "target_id": 3,
70 "action_key": "50d6c586103ebeed3a218195540bcc30d329464eae36377eb82f8ce7c36ac342",
71 "Mnemonic": "Genrule",
72 "configuration_id": 1,
73 "Arguments": ["/bin/bash", "-c", "source ../bazel_tools/tools/genrule/genrule-setup.sh; ../sourceroot/bionic/libc/tools/gensyscalls.py x86_64 ../sourceroot/bionic/libc/SYSCALLS.TXT \u003e bazel-out/sourceroot/k8-fastbuild/bin/bionic/libc/syscalls-x86_64.S"],
74 "environment_variables": [{
75 "Key": "PATH",
76 "Value": "/bin:/usr/bin:/usr/local/bin"
77 }],
78 "input_dep_set_ids": [3],
79 "output_ids": [6],
80 "primary_output_id": 6
81 }, {
82 "target_id": 4,
83 "action_key": "f30cbe442f5216f4223cf16a39112cad4ec56f31f49290d85cff587e48647ffa",
84 "Mnemonic": "Genrule",
85 "configuration_id": 1,
86 "Arguments": ["/bin/bash", "-c", "source ../bazel_tools/tools/genrule/genrule-setup.sh; ../sourceroot/bionic/libc/tools/gensyscalls.py arm64 ../sourceroot/bionic/libc/SYSCALLS.TXT \u003e bazel-out/sourceroot/k8-fastbuild/bin/bionic/libc/syscalls-arm64.S"],
87 "environment_variables": [{
88 "Key": "PATH",
89 "Value": "/bin:/usr/bin:/usr/local/bin"
90 }],
91 "input_dep_set_ids": [4],
92 "output_ids": [7],
93 "primary_output_id": 7
94 }],
95 "Targets": [
96 { "Id": 1, "Label": "@sourceroot//bionic/libc:syscalls-arm", "rule_class_id": 1 },
97 { "Id": 2, "Label": "@sourceroot//bionic/libc:syscalls-x86", "rule_class_id": 1 },
98 { "Id": 3, "Label": "@sourceroot//bionic/libc:syscalls-x86_64", "rule_class_id": 1 },
99 { "Id": 4, "Label": "@sourceroot//bionic/libc:syscalls-arm64", "rule_class_id": 1 }],
100 "dep_set_of_files": [
101 { "Id": 1, "direct_artifact_ids": [1, 2, 3] },
102 { "Id": 2, "direct_artifact_ids": [1, 2, 3] },
103 { "Id": 3, "direct_artifact_ids": [1, 2, 3] },
104 { "Id": 4, "direct_artifact_ids": [1, 2, 3] }],
105 "Configuration": [{
106 "Id": 1,
107 "Mnemonic": "k8-fastbuild",
108 "platform_name": "k8",
109 "Checksum": "485c362832c178e367d972177f68e69e0981e51e67ef1c160944473db53fe046"
110 }],
111 "rule_classes": [{ "Id": 1, "Name": "genrule"}],
112 "path_fragments": [
113 { "Id": 5, "Label": ".." },
114 { "Id": 4, "Label": "sourceroot", "parent_id": 5 },
115 { "Id": 3, "Label": "bionic", "parent_id": 4 },
116 { "Id": 2, "Label": "libc", "parent_id": 3 },
117 { "Id": 1, "Label": "SYSCALLS.TXT", "parent_id": 2 },
118 { "Id": 7, "Label": "tools", "parent_id": 2 },
119 { "Id": 6, "Label": "gensyscalls.py", "parent_id": 7 },
120 { "Id": 11, "Label": "bazel_tools", "parent_id": 5 },
121 { "Id": 10, "Label": "tools", "parent_id": 11 },
122 { "Id": 9, "Label": "genrule", "parent_id": 10 },
123 { "Id": 8, "Label": "genrule-setup.sh", "parent_id": 9 },
124 { "Id": 18, "Label": "bazel-out" },
125 { "Id": 17, "Label": "sourceroot", "parent_id": 18 },
126 { "Id": 16, "Label": "k8-fastbuild", "parent_id": 17 },
127 { "Id": 15, "Label": "bin", "parent_id": 16 },
128 { "Id": 14, "Label": "bionic", "parent_id": 15 },
129 { "Id": 13, "Label": "libc", "parent_id": 14 },
130 { "Id": 12, "Label": "syscalls-arm.S", "parent_id": 13 },
131 { "Id": 19, "Label": "syscalls-x86.S", "parent_id": 13 },
132 { "Id": 20, "Label": "syscalls-x86_64.S", "parent_id": 13 },
133 { "Id": 21, "Label": "syscalls-arm64.S", "parent_id": 13 }]
134}
135`
136 data, err := JsonToActionGraphContainer(inputString)
137 if err != nil {
138 t.Error(err)
139 return
140 }
Liz Kammer690fbac2023-02-10 11:11:17 -0500141 actualbuildStatements, actualDepsets, _ := AqueryBuildStatements(data, &metrics.EventHandler{})
Liz Kammera4655a92023-02-10 17:17:28 -0500142 var expectedBuildStatements []*BuildStatement
Chris Parsons4f069892021-01-15 12:22:41 -0500143 for _, arch := range []string{"arm", "arm64", "x86", "x86_64"} {
144 expectedBuildStatements = append(expectedBuildStatements,
Liz Kammera4655a92023-02-10 17:17:28 -0500145 &BuildStatement{
Chris Parsons4f069892021-01-15 12:22:41 -0500146 Command: fmt.Sprintf(
147 "/bin/bash -c 'source ../bazel_tools/tools/genrule/genrule-setup.sh; ../sourceroot/bionic/libc/tools/gensyscalls.py %s ../sourceroot/bionic/libc/SYSCALLS.TXT > bazel-out/sourceroot/k8-fastbuild/bin/bionic/libc/syscalls-%s.S'",
148 arch, arch),
149 OutputPaths: []string{
150 fmt.Sprintf("bazel-out/sourceroot/k8-fastbuild/bin/bionic/libc/syscalls-%s.S", arch),
151 },
Liz Kammer00629db2023-02-09 14:28:15 -0500152 Env: []*analysis_v2_proto.KeyValuePair{
Usta Shrestha16ac1352022-06-22 11:01:55 -0400153 {Key: "PATH", Value: "/bin:/usr/bin:/usr/local/bin"},
Chris Parsons4f069892021-01-15 12:22:41 -0500154 },
155 Mnemonic: "Genrule",
156 })
157 }
158 assertBuildStatements(t, expectedBuildStatements, actualbuildStatements)
Chris Parsons1a7aca02022-04-25 22:35:15 -0400159
160 expectedFlattenedInputs := []string{
161 "../sourceroot/bionic/libc/SYSCALLS.TXT",
162 "../sourceroot/bionic/libc/tools/gensyscalls.py",
Chris Parsons1a7aca02022-04-25 22:35:15 -0400163 }
Chris Parsons0bfb1c02022-05-12 16:43:01 -0400164 // In this example, each depset should have the same expected inputs.
165 for _, actualDepset := range actualDepsets {
166 actualFlattenedInputs := flattenDepsets([]string{actualDepset.ContentHash}, actualDepsets)
167 if !reflect.DeepEqual(actualFlattenedInputs, expectedFlattenedInputs) {
168 t.Errorf("Expected flattened inputs %v, but got %v", expectedFlattenedInputs, actualFlattenedInputs)
169 }
Chris Parsons1a7aca02022-04-25 22:35:15 -0400170 }
Chris Parsons4f069892021-01-15 12:22:41 -0500171}
172
173func TestInvalidOutputId(t *testing.T) {
174 const inputString = `
175{
Jason Wu118fd2b2022-10-27 18:41:15 +0000176 "artifacts": [
177 { "id": 1, "path_fragment_id": 1 },
178 { "id": 2, "path_fragment_id": 2 }],
179 "actions": [{
180 "target_id": 1,
ustac4547812023-09-25 17:34:15 -0400181 "action_key": "action_x",
182 "mnemonic": "X",
Jason Wu118fd2b2022-10-27 18:41:15 +0000183 "arguments": ["touch", "foo"],
184 "input_dep_set_ids": [1],
185 "output_ids": [3],
186 "primary_output_id": 3
187 }],
188 "dep_set_of_files": [
189 { "id": 1, "direct_artifact_ids": [1, 2] }],
190 "path_fragments": [
191 { "id": 1, "label": "one" },
192 { "id": 2, "label": "two" }]
Chris Parsons4f069892021-01-15 12:22:41 -0500193}`
194
Jason Wu118fd2b2022-10-27 18:41:15 +0000195 data, err := JsonToActionGraphContainer(inputString)
196 if err != nil {
197 t.Error(err)
198 return
199 }
Liz Kammer690fbac2023-02-10 11:11:17 -0500200 _, _, err = AqueryBuildStatements(data, &metrics.EventHandler{})
ustac4547812023-09-25 17:34:15 -0400201 assertError(t, err, "undefined outputId 3: [X] []")
Chris Parsons4f069892021-01-15 12:22:41 -0500202}
203
Chris Parsons1a7aca02022-04-25 22:35:15 -0400204func TestInvalidInputDepsetIdFromAction(t *testing.T) {
Chris Parsons4f069892021-01-15 12:22:41 -0500205 const inputString = `
206{
Jason Wu118fd2b2022-10-27 18:41:15 +0000207 "artifacts": [
208 { "id": 1, "path_fragment_id": 1 },
209 { "id": 2, "path_fragment_id": 2 }],
210 "actions": [{
211 "target_id": 1,
ustac4547812023-09-25 17:34:15 -0400212 "action_key": "action_x",
213 "mnemonic": "X",
Jason Wu118fd2b2022-10-27 18:41:15 +0000214 "arguments": ["touch", "foo"],
215 "input_dep_set_ids": [2],
216 "output_ids": [1],
217 "primary_output_id": 1
218 }],
ustac4547812023-09-25 17:34:15 -0400219 "targets": [{
220 "id": 1,
221 "label": "target_x"
222 }],
Jason Wu118fd2b2022-10-27 18:41:15 +0000223 "dep_set_of_files": [
224 { "id": 1, "direct_artifact_ids": [1, 2] }],
225 "path_fragments": [
226 { "id": 1, "label": "one" },
227 { "id": 2, "label": "two" }]
Chris Parsons4f069892021-01-15 12:22:41 -0500228}`
229
Jason Wu118fd2b2022-10-27 18:41:15 +0000230 data, err := JsonToActionGraphContainer(inputString)
231 if err != nil {
232 t.Error(err)
233 return
234 }
Liz Kammer690fbac2023-02-10 11:11:17 -0500235 _, _, err = AqueryBuildStatements(data, &metrics.EventHandler{})
ustac4547812023-09-25 17:34:15 -0400236 assertError(t, err, "undefined (not even empty) input depsetId 2: [X] [target_x]")
Chris Parsons4f069892021-01-15 12:22:41 -0500237}
238
Chris Parsons1a7aca02022-04-25 22:35:15 -0400239func TestInvalidInputDepsetIdFromDepset(t *testing.T) {
240 const inputString = `
241{
Jason Wu118fd2b2022-10-27 18:41:15 +0000242 "artifacts": [
243 { "id": 1, "path_fragment_id": 1 },
244 { "id": 2, "path_fragment_id": 2 }],
245 "actions": [{
246 "target_id": 1,
247 "action_key": "x",
248 "mnemonic": "x",
249 "arguments": ["touch", "foo"],
250 "input_dep_set_ids": [1],
251 "output_ids": [1],
252 "primary_output_id": 1
253 }],
254 "dep_set_of_files": [
255 { "id": 1, "direct_artifact_ids": [1, 2], "transitive_dep_set_ids": [42] }],
256 "path_fragments": [
257 { "id": 1, "label": "one"},
258 { "id": 2, "label": "two" }]
Chris Parsons1a7aca02022-04-25 22:35:15 -0400259}`
260
Jason Wu118fd2b2022-10-27 18:41:15 +0000261 data, err := JsonToActionGraphContainer(inputString)
262 if err != nil {
263 t.Error(err)
264 return
265 }
Liz Kammer690fbac2023-02-10 11:11:17 -0500266 _, _, err = AqueryBuildStatements(data, &metrics.EventHandler{})
Chris Parsons1a7aca02022-04-25 22:35:15 -0400267 assertError(t, err, "undefined input depsetId 42 (referenced by depsetId 1)")
268}
269
Chris Parsons4f069892021-01-15 12:22:41 -0500270func TestInvalidInputArtifactId(t *testing.T) {
271 const inputString = `
272{
Jason Wu118fd2b2022-10-27 18:41:15 +0000273 "artifacts": [
274 { "id": 1, "path_fragment_id": 1 },
275 { "id": 2, "path_fragment_id": 2 }],
276 "actions": [{
277 "target_id": 1,
278 "action_key": "x",
279 "mnemonic": "x",
280 "arguments": ["touch", "foo"],
281 "input_dep_set_ids": [1],
282 "output_ids": [1],
283 "primary_output_id": 1
284 }],
285 "dep_set_of_files": [
286 { "id": 1, "direct_artifact_ids": [1, 3] }],
287 "path_fragments": [
288 { "id": 1, "label": "one" },
289 { "id": 2, "label": "two" }]
Chris Parsons4f069892021-01-15 12:22:41 -0500290}`
291
Jason Wu118fd2b2022-10-27 18:41:15 +0000292 data, err := JsonToActionGraphContainer(inputString)
293 if err != nil {
294 t.Error(err)
295 return
296 }
Liz Kammer690fbac2023-02-10 11:11:17 -0500297 _, _, err = AqueryBuildStatements(data, &metrics.EventHandler{})
Chris Parsons4f069892021-01-15 12:22:41 -0500298 assertError(t, err, "undefined input artifactId 3")
299}
300
301func TestInvalidPathFragmentId(t *testing.T) {
302 const inputString = `
303{
Jason Wu118fd2b2022-10-27 18:41:15 +0000304 "artifacts": [
305 { "id": 1, "path_fragment_id": 1 },
306 { "id": 2, "path_fragment_id": 2 }],
307 "actions": [{
308 "target_id": 1,
309 "action_key": "x",
310 "mnemonic": "x",
311 "arguments": ["touch", "foo"],
312 "input_dep_set_ids": [1],
313 "output_ids": [1],
314 "primary_output_id": 1
315 }],
316 "dep_set_of_files": [
317 { "id": 1, "direct_artifact_ids": [1, 2] }],
318 "path_fragments": [
319 { "id": 1, "label": "one" },
320 { "id": 2, "label": "two", "parent_id": 3 }]
Chris Parsons4f069892021-01-15 12:22:41 -0500321}`
322
Jason Wu118fd2b2022-10-27 18:41:15 +0000323 data, err := JsonToActionGraphContainer(inputString)
324 if err != nil {
325 t.Error(err)
326 return
327 }
Liz Kammer690fbac2023-02-10 11:11:17 -0500328 _, _, err = AqueryBuildStatements(data, &metrics.EventHandler{})
Chris Parsons4f069892021-01-15 12:22:41 -0500329 assertError(t, err, "undefined path fragment id 3")
330}
331
Liz Kammerde116852021-03-25 16:42:37 -0400332func TestDepfiles(t *testing.T) {
333 const inputString = `
334{
Sasha Smundake3cf1ab2022-06-30 11:36:18 -0700335 "artifacts": [
Jason Wu118fd2b2022-10-27 18:41:15 +0000336 { "id": 1, "path_fragment_id": 1 },
337 { "id": 2, "path_fragment_id": 2 },
338 { "id": 3, "path_fragment_id": 3 }],
Liz Kammerde116852021-03-25 16:42:37 -0400339 "actions": [{
Jason Wu118fd2b2022-10-27 18:41:15 +0000340 "target_Id": 1,
341 "action_Key": "x",
Liz Kammerde116852021-03-25 16:42:37 -0400342 "mnemonic": "x",
343 "arguments": ["touch", "foo"],
Jason Wu118fd2b2022-10-27 18:41:15 +0000344 "input_dep_set_ids": [1],
345 "output_ids": [2, 3],
346 "primary_output_id": 2
Liz Kammerde116852021-03-25 16:42:37 -0400347 }],
Jason Wu118fd2b2022-10-27 18:41:15 +0000348 "dep_set_of_files": [
349 { "id": 1, "direct_Artifact_Ids": [1, 2, 3] }],
350 "path_fragments": [
Sasha Smundake3cf1ab2022-06-30 11:36:18 -0700351 { "id": 1, "label": "one" },
352 { "id": 2, "label": "two" },
353 { "id": 3, "label": "two.d" }]
Liz Kammerde116852021-03-25 16:42:37 -0400354}`
355
Jason Wu118fd2b2022-10-27 18:41:15 +0000356 data, err := JsonToActionGraphContainer(inputString)
357 if err != nil {
358 t.Error(err)
359 return
360 }
Liz Kammer690fbac2023-02-10 11:11:17 -0500361 actual, _, err := AqueryBuildStatements(data, &metrics.EventHandler{})
Liz Kammerde116852021-03-25 16:42:37 -0400362 if err != nil {
363 t.Errorf("Unexpected error %q", err)
Cole Faustbc65a3f2023-08-01 16:38:55 +0000364 return
Liz Kammerde116852021-03-25 16:42:37 -0400365 }
366 if expected := 1; len(actual) != expected {
367 t.Fatalf("Expected %d build statements, got %d", expected, len(actual))
Cole Faustbc65a3f2023-08-01 16:38:55 +0000368 return
Liz Kammerde116852021-03-25 16:42:37 -0400369 }
370
371 bs := actual[0]
372 expectedDepfile := "two.d"
373 if bs.Depfile == nil {
374 t.Errorf("Expected depfile %q, but there was none found", expectedDepfile)
375 } else if *bs.Depfile != expectedDepfile {
376 t.Errorf("Expected depfile %q, but got %q", expectedDepfile, *bs.Depfile)
377 }
378}
379
380func TestMultipleDepfiles(t *testing.T) {
381 const inputString = `
382{
Jason Wu118fd2b2022-10-27 18:41:15 +0000383 "artifacts": [
384 { "id": 1, "path_fragment_id": 1 },
385 { "id": 2, "path_fragment_id": 2 },
386 { "id": 3, "path_fragment_id": 3 },
387 { "id": 4, "path_fragment_id": 4 }],
388 "actions": [{
389 "target_id": 1,
ustac4547812023-09-25 17:34:15 -0400390 "action_key": "action_x",
391 "mnemonic": "X",
Jason Wu118fd2b2022-10-27 18:41:15 +0000392 "arguments": ["touch", "foo"],
393 "input_dep_set_ids": [1],
394 "output_ids": [2,3,4],
395 "primary_output_id": 2
396 }],
397 "dep_set_of_files": [{
398 "id": 1,
399 "direct_artifact_ids": [1, 2, 3, 4]
400 }],
401 "path_fragments": [
402 { "id": 1, "label": "one" },
403 { "id": 2, "label": "two" },
404 { "id": 3, "label": "two.d" },
405 { "id": 4, "label": "other.d" }]
Liz Kammerde116852021-03-25 16:42:37 -0400406}`
407
Jason Wu118fd2b2022-10-27 18:41:15 +0000408 data, err := JsonToActionGraphContainer(inputString)
409 if err != nil {
410 t.Error(err)
411 return
412 }
Liz Kammer690fbac2023-02-10 11:11:17 -0500413 _, _, err = AqueryBuildStatements(data, &metrics.EventHandler{})
ustac4547812023-09-25 17:34:15 -0400414 assertError(t, err, `found multiple potential depfiles "two.d", "other.d": [X] []`)
Liz Kammerde116852021-03-25 16:42:37 -0400415}
416
Chris Parsons943f2432021-01-19 11:36:50 -0500417func TestTransitiveInputDepsets(t *testing.T) {
418 // The input aquery for this test comes from a proof-of-concept starlark rule which registers
419 // a single action with many inputs given via a deep depset.
420 const inputString = `
421{
Jason Wu118fd2b2022-10-27 18:41:15 +0000422 "artifacts": [
423 { "id": 1, "path_fragment_id": 1 },
424 { "id": 2, "path_fragment_id": 7 },
425 { "id": 3, "path_fragment_id": 8 },
426 { "id": 4, "path_fragment_id": 9 },
427 { "id": 5, "path_fragment_id": 10 },
428 { "id": 6, "path_fragment_id": 11 },
429 { "id": 7, "path_fragment_id": 12 },
430 { "id": 8, "path_fragment_id": 13 },
431 { "id": 9, "path_fragment_id": 14 },
432 { "id": 10, "path_fragment_id": 15 },
433 { "id": 11, "path_fragment_id": 16 },
434 { "id": 12, "path_fragment_id": 17 },
435 { "id": 13, "path_fragment_id": 18 },
436 { "id": 14, "path_fragment_id": 19 },
437 { "id": 15, "path_fragment_id": 20 },
438 { "id": 16, "path_fragment_id": 21 },
439 { "id": 17, "path_fragment_id": 22 },
440 { "id": 18, "path_fragment_id": 23 },
441 { "id": 19, "path_fragment_id": 24 },
442 { "id": 20, "path_fragment_id": 25 },
443 { "id": 21, "path_fragment_id": 26 }],
444 "actions": [{
445 "target_id": 1,
446 "action_key": "3b826d17fadbbbcd8313e456b90ec47c078c438088891dd45b4adbcd8889dc50",
447 "mnemonic": "Action",
448 "configuration_id": 1,
449 "arguments": ["/bin/bash", "-c", "touch bazel-out/sourceroot/k8-fastbuild/bin/testpkg/test_out"],
450 "input_dep_set_ids": [1],
451 "output_ids": [21],
452 "primary_output_id": 21
453 }],
454 "dep_set_of_files": [
455 { "id": 3, "direct_artifact_ids": [1, 2, 3, 4, 5] },
456 { "id": 4, "direct_artifact_ids": [6, 7, 8, 9, 10] },
457 { "id": 2, "transitive_dep_set_ids": [3, 4], "direct_artifact_ids": [11, 12, 13, 14, 15] },
458 { "id": 5, "direct_artifact_ids": [16, 17, 18, 19] },
459 { "id": 1, "transitive_dep_set_ids": [2, 5], "direct_artifact_ids": [20] }],
460 "path_fragments": [
461 { "id": 6, "label": "bazel-out" },
462 { "id": 5, "label": "sourceroot", "parent_id": 6 },
463 { "id": 4, "label": "k8-fastbuild", "parent_id": 5 },
464 { "id": 3, "label": "bin", "parent_id": 4 },
465 { "id": 2, "label": "testpkg", "parent_id": 3 },
466 { "id": 1, "label": "test_1", "parent_id": 2 },
467 { "id": 7, "label": "test_2", "parent_id": 2 },
468 { "id": 8, "label": "test_3", "parent_id": 2 },
469 { "id": 9, "label": "test_4", "parent_id": 2 },
470 { "id": 10, "label": "test_5", "parent_id": 2 },
471 { "id": 11, "label": "test_6", "parent_id": 2 },
472 { "id": 12, "label": "test_7", "parent_id": 2 },
473 { "id": 13, "label": "test_8", "parent_id": 2 },
474 { "id": 14, "label": "test_9", "parent_id": 2 },
475 { "id": 15, "label": "test_10", "parent_id": 2 },
476 { "id": 16, "label": "test_11", "parent_id": 2 },
477 { "id": 17, "label": "test_12", "parent_id": 2 },
478 { "id": 18, "label": "test_13", "parent_id": 2 },
479 { "id": 19, "label": "test_14", "parent_id": 2 },
480 { "id": 20, "label": "test_15", "parent_id": 2 },
481 { "id": 21, "label": "test_16", "parent_id": 2 },
482 { "id": 22, "label": "test_17", "parent_id": 2 },
483 { "id": 23, "label": "test_18", "parent_id": 2 },
484 { "id": 24, "label": "test_19", "parent_id": 2 },
485 { "id": 25, "label": "test_root", "parent_id": 2 },
486 { "id": 26,"label": "test_out", "parent_id": 2 }]
Chris Parsons943f2432021-01-19 11:36:50 -0500487}`
488
Jason Wu118fd2b2022-10-27 18:41:15 +0000489 data, err := JsonToActionGraphContainer(inputString)
490 if err != nil {
491 t.Error(err)
492 return
493 }
Liz Kammer690fbac2023-02-10 11:11:17 -0500494 actualbuildStatements, actualDepsets, _ := AqueryBuildStatements(data, &metrics.EventHandler{})
Chris Parsons1a7aca02022-04-25 22:35:15 -0400495
Liz Kammera4655a92023-02-10 17:17:28 -0500496 expectedBuildStatements := []*BuildStatement{
497 &BuildStatement{
Liz Kammer00629db2023-02-09 14:28:15 -0500498 Command: "/bin/bash -c 'touch bazel-out/sourceroot/k8-fastbuild/bin/testpkg/test_out'",
499 OutputPaths: []string{"bazel-out/sourceroot/k8-fastbuild/bin/testpkg/test_out"},
500 Mnemonic: "Action",
501 SymlinkPaths: []string{},
Chris Parsons943f2432021-01-19 11:36:50 -0500502 },
503 }
504 assertBuildStatements(t, expectedBuildStatements, actualbuildStatements)
Chris Parsons1a7aca02022-04-25 22:35:15 -0400505
506 // Inputs for the action are test_{i} from 1 to 20, and test_root. These inputs
507 // are given via a deep depset, but the depset is flattened when returned as a
508 // BuildStatement slice.
Usta Shrestha16ac1352022-06-22 11:01:55 -0400509 var expectedFlattenedInputs []string
Chris Parsons1a7aca02022-04-25 22:35:15 -0400510 for i := 1; i < 20; i++ {
511 expectedFlattenedInputs = append(expectedFlattenedInputs, fmt.Sprintf("bazel-out/sourceroot/k8-fastbuild/bin/testpkg/test_%d", i))
512 }
513 expectedFlattenedInputs = append(expectedFlattenedInputs, "bazel-out/sourceroot/k8-fastbuild/bin/testpkg/test_root")
514
Chris Parsons0bfb1c02022-05-12 16:43:01 -0400515 actualDepsetHashes := actualbuildStatements[0].InputDepsetHashes
516 actualFlattenedInputs := flattenDepsets(actualDepsetHashes, actualDepsets)
Chris Parsons1a7aca02022-04-25 22:35:15 -0400517 if !reflect.DeepEqual(actualFlattenedInputs, expectedFlattenedInputs) {
518 t.Errorf("Expected flattened inputs %v, but got %v", expectedFlattenedInputs, actualFlattenedInputs)
519 }
Chris Parsons943f2432021-01-19 11:36:50 -0500520}
521
Sasha Smundakc180dbd2022-07-03 14:55:58 -0700522func TestSymlinkTree(t *testing.T) {
523 const inputString = `
524{
Jason Wu118fd2b2022-10-27 18:41:15 +0000525 "artifacts": [
526 { "id": 1, "path_fragment_id": 1 },
527 { "id": 2, "path_fragment_id": 2 }],
528 "actions": [{
529 "target_id": 1,
530 "action_key": "x",
531 "mnemonic": "SymlinkTree",
532 "configuration_id": 1,
533 "input_dep_set_ids": [1],
534 "output_ids": [2],
535 "primary_output_id": 2,
536 "execution_platform": "//build/bazel/platforms:linux_x86_64"
537 }],
538 "path_fragments": [
539 { "id": 1, "label": "foo.manifest" },
540 { "id": 2, "label": "foo.runfiles/MANIFEST" }],
541 "dep_set_of_files": [
542 { "id": 1, "direct_artifact_ids": [1] }]
Sasha Smundakc180dbd2022-07-03 14:55:58 -0700543}
544`
Jason Wu118fd2b2022-10-27 18:41:15 +0000545 data, err := JsonToActionGraphContainer(inputString)
546 if err != nil {
547 t.Error(err)
548 return
549 }
Liz Kammer690fbac2023-02-10 11:11:17 -0500550 actual, _, err := AqueryBuildStatements(data, &metrics.EventHandler{})
Sasha Smundakc180dbd2022-07-03 14:55:58 -0700551 if err != nil {
552 t.Errorf("Unexpected error %q", err)
Cole Faustbc65a3f2023-08-01 16:38:55 +0000553 return
Sasha Smundakc180dbd2022-07-03 14:55:58 -0700554 }
Liz Kammera4655a92023-02-10 17:17:28 -0500555 assertBuildStatements(t, []*BuildStatement{
556 &BuildStatement{
Liz Kammer00629db2023-02-09 14:28:15 -0500557 Command: "",
558 OutputPaths: []string{"foo.runfiles/MANIFEST"},
559 Mnemonic: "SymlinkTree",
560 InputPaths: []string{"foo.manifest"},
561 SymlinkPaths: []string{},
Sasha Smundakc180dbd2022-07-03 14:55:58 -0700562 },
563 }, actual)
564}
565
ustac4547812023-09-25 17:34:15 -0400566func TestBazelToolsRemovalFromInputDepsets(t *testing.T) {
Usta Shresthaef922252022-06-02 14:23:02 -0400567 const inputString = `{
Jason Wu118fd2b2022-10-27 18:41:15 +0000568 "artifacts": [
569 { "id": 1, "path_fragment_id": 10 },
570 { "id": 2, "path_fragment_id": 20 },
571 { "id": 3, "path_fragment_id": 30 },
572 { "id": 4, "path_fragment_id": 40 }],
573 "dep_set_of_files": [{
574 "id": 1111,
575 "direct_artifact_ids": [3 , 4]
576 }, {
577 "id": 2222,
578 "direct_artifact_ids": [3]
579 }],
580 "actions": [{
581 "target_id": 100,
582 "action_key": "x",
583 "input_dep_set_ids": [1111, 2222],
584 "mnemonic": "x",
585 "arguments": ["bogus", "command"],
586 "output_ids": [2],
587 "primary_output_id": 1
588 }],
589 "path_fragments": [
590 { "id": 10, "label": "input" },
591 { "id": 20, "label": "output" },
592 { "id": 30, "label": "dep1", "parent_id": 50 },
593 { "id": 40, "label": "dep2", "parent_id": 60 },
594 { "id": 50, "label": "bazel_tools", "parent_id": 60 },
595 { "id": 60, "label": ".."}
596 ]
Usta Shresthaef922252022-06-02 14:23:02 -0400597}`
Usta Shrestha13fd5ae2023-01-27 10:55:34 -0500598 /* depsets
599 1111 2222
600 / \ |
601 ../dep2 ../bazel_tools/dep1
602 */
Jason Wu118fd2b2022-10-27 18:41:15 +0000603 data, err := JsonToActionGraphContainer(inputString)
604 if err != nil {
605 t.Error(err)
606 return
607 }
Liz Kammer690fbac2023-02-10 11:11:17 -0500608 actualBuildStatements, actualDepsets, _ := AqueryBuildStatements(data, &metrics.EventHandler{})
Usta Shrestha13fd5ae2023-01-27 10:55:34 -0500609 if len(actualDepsets) != 1 {
Usta Shresthaef922252022-06-02 14:23:02 -0400610 t.Errorf("expected 1 depset but found %#v", actualDepsets)
611 return
612 }
613 dep2Found := false
614 for _, dep := range flattenDepsets([]string{actualDepsets[0].ContentHash}, actualDepsets) {
615 if dep == "../bazel_tools/dep1" {
616 t.Errorf("dependency %s expected to be removed but still exists", dep)
617 } else if dep == "../dep2" {
618 dep2Found = true
619 }
620 }
621 if !dep2Found {
622 t.Errorf("dependency ../dep2 expected but not found")
623 }
624
Liz Kammera4655a92023-02-10 17:17:28 -0500625 expectedBuildStatement := &BuildStatement{
Liz Kammer00629db2023-02-09 14:28:15 -0500626 Command: "bogus command",
627 OutputPaths: []string{"output"},
628 Mnemonic: "x",
629 SymlinkPaths: []string{},
Usta Shresthaef922252022-06-02 14:23:02 -0400630 }
631 buildStatementFound := false
632 for _, actualBuildStatement := range actualBuildStatements {
633 if buildStatementEquals(actualBuildStatement, expectedBuildStatement) == "" {
634 buildStatementFound = true
635 break
636 }
637 }
638 if !buildStatementFound {
639 t.Errorf("expected but missing %#v in %#v", expectedBuildStatement, actualBuildStatements)
640 return
641 }
642}
643
ustac4547812023-09-25 17:34:15 -0400644func TestBazelToolsRemovalFromTargets(t *testing.T) {
645 const inputString = `{
646 "artifacts": [{ "id": 1, "path_fragment_id": 10 }],
647 "targets": [
648 { "id": 100, "label": "targetX" },
649 { "id": 200, "label": "@bazel_tools//tool_y" }
650],
651 "actions": [{
652 "target_id": 100,
653 "action_key": "actionX",
654 "arguments": ["bogus", "command"],
655 "mnemonic" : "x",
656 "output_ids": [1]
657 }, {
658 "target_id": 200,
659 "action_key": "y"
660 }],
661 "path_fragments": [{ "id": 10, "label": "outputX"}]
662}`
663 data, err := JsonToActionGraphContainer(inputString)
664 if err != nil {
665 t.Error(err)
666 return
667 }
668 actualBuildStatements, actualDepsets, _ := AqueryBuildStatements(data, &metrics.EventHandler{})
669 if len(actualDepsets) != 0 {
670 t.Errorf("expected 0 depset but found %#v", actualDepsets)
671 return
672 }
673 expectedBuildStatement := &BuildStatement{
674 Command: "bogus command",
675 OutputPaths: []string{"outputX"},
676 Mnemonic: "x",
677 SymlinkPaths: []string{},
678 }
679 buildStatementFound := false
680 for _, actualBuildStatement := range actualBuildStatements {
681 if buildStatementEquals(actualBuildStatement, expectedBuildStatement) == "" {
682 buildStatementFound = true
683 break
684 }
685 }
686 if !buildStatementFound {
687 t.Errorf("expected but missing %#v in %#v build statements", expectedBuildStatement, len(actualBuildStatements))
688 return
689 }
690}
691
692func TestBazelToolsRemovalFromTransitiveInputDepsets(t *testing.T) {
Usta Shrestha13fd5ae2023-01-27 10:55:34 -0500693 const inputString = `{
694 "artifacts": [
695 { "id": 1, "path_fragment_id": 10 },
696 { "id": 2, "path_fragment_id": 20 },
697 { "id": 3, "path_fragment_id": 30 }],
698 "dep_set_of_files": [{
699 "id": 1111,
700 "transitive_dep_set_ids": [2222]
701 }, {
702 "id": 2222,
703 "direct_artifact_ids": [3]
704 }, {
705 "id": 3333,
706 "direct_artifact_ids": [3]
707 }, {
708 "id": 4444,
709 "transitive_dep_set_ids": [3333]
710 }],
711 "actions": [{
712 "target_id": 100,
713 "action_key": "x",
714 "input_dep_set_ids": [1111, 4444],
715 "mnemonic": "x",
716 "arguments": ["bogus", "command"],
717 "output_ids": [2],
718 "primary_output_id": 1
719 }],
720 "path_fragments": [
721 { "id": 10, "label": "input" },
722 { "id": 20, "label": "output" },
723 { "id": 30, "label": "dep", "parent_id": 50 },
724 { "id": 50, "label": "bazel_tools", "parent_id": 60 },
725 { "id": 60, "label": ".."}
726 ]
727}`
728 /* depsets
729 1111 4444
730 || ||
731 2222 3333
732 | |
733 ../bazel_tools/dep
734 Note: in dep_set_of_files:
735 1111 appears BEFORE its dependency,2222 while
736 4444 appears AFTER its dependency 3333
737 and this test shows that that order doesn't affect empty depset pruning
738 */
739 data, err := JsonToActionGraphContainer(inputString)
740 if err != nil {
741 t.Error(err)
742 return
743 }
Liz Kammer690fbac2023-02-10 11:11:17 -0500744 actualBuildStatements, actualDepsets, _ := AqueryBuildStatements(data, &metrics.EventHandler{})
Usta Shrestha13fd5ae2023-01-27 10:55:34 -0500745 if len(actualDepsets) != 0 {
746 t.Errorf("expected 0 depsets but found %#v", actualDepsets)
747 return
748 }
749
Liz Kammera4655a92023-02-10 17:17:28 -0500750 expectedBuildStatement := &BuildStatement{
Usta Shrestha13fd5ae2023-01-27 10:55:34 -0500751 Command: "bogus command",
752 OutputPaths: []string{"output"},
753 Mnemonic: "x",
754 }
755 buildStatementFound := false
756 for _, actualBuildStatement := range actualBuildStatements {
757 if buildStatementEquals(actualBuildStatement, expectedBuildStatement) == "" {
758 buildStatementFound = true
759 break
760 }
761 }
762 if !buildStatementFound {
763 t.Errorf("expected but missing %#v in %#v", expectedBuildStatement, actualBuildStatements)
764 return
765 }
766}
767
Chris Parsonsc4fb1332021-05-18 12:31:25 -0400768func TestMiddlemenAction(t *testing.T) {
769 const inputString = `
770{
Jason Wu118fd2b2022-10-27 18:41:15 +0000771 "artifacts": [
772 { "id": 1, "path_fragment_id": 1 },
773 { "id": 2, "path_fragment_id": 2 },
774 { "id": 3, "path_fragment_id": 3 },
775 { "id": 4, "path_fragment_id": 4 },
776 { "id": 5, "path_fragment_id": 5 },
777 { "id": 6, "path_fragment_id": 6 }],
778 "path_fragments": [
779 { "id": 1, "label": "middleinput_one" },
780 { "id": 2, "label": "middleinput_two" },
781 { "id": 3, "label": "middleman_artifact" },
782 { "id": 4, "label": "maininput_one" },
783 { "id": 5, "label": "maininput_two" },
784 { "id": 6, "label": "output" }],
785 "dep_set_of_files": [
786 { "id": 1, "direct_artifact_ids": [1, 2] },
787 { "id": 2, "direct_artifact_ids": [3, 4, 5] }],
788 "actions": [{
789 "target_id": 1,
790 "action_key": "x",
791 "mnemonic": "Middleman",
792 "arguments": ["touch", "foo"],
793 "input_dep_set_ids": [1],
794 "output_ids": [3],
795 "primary_output_id": 3
796 }, {
797 "target_id": 2,
798 "action_key": "y",
799 "mnemonic": "Main action",
800 "arguments": ["touch", "foo"],
801 "input_dep_set_ids": [2],
802 "output_ids": [6],
803 "primary_output_id": 6
804 }]
Chris Parsonsc4fb1332021-05-18 12:31:25 -0400805}`
Jason Wu118fd2b2022-10-27 18:41:15 +0000806 data, err := JsonToActionGraphContainer(inputString)
807 if err != nil {
808 t.Error(err)
809 return
810 }
Liz Kammer690fbac2023-02-10 11:11:17 -0500811 actualBuildStatements, actualDepsets, err := AqueryBuildStatements(data, &metrics.EventHandler{})
Chris Parsonsc4fb1332021-05-18 12:31:25 -0400812 if err != nil {
813 t.Errorf("Unexpected error %q", err)
Cole Faustbc65a3f2023-08-01 16:38:55 +0000814 return
Chris Parsonsc4fb1332021-05-18 12:31:25 -0400815 }
Liz Kammera4655a92023-02-10 17:17:28 -0500816 if expected := 2; len(actualBuildStatements) != expected {
817 t.Fatalf("Expected %d build statements, got %d %#v", expected, len(actualBuildStatements), actualBuildStatements)
Cole Faustbc65a3f2023-08-01 16:38:55 +0000818 return
Chris Parsonsc4fb1332021-05-18 12:31:25 -0400819 }
820
Chris Parsons0bfb1c02022-05-12 16:43:01 -0400821 expectedDepsetFiles := [][]string{
Usta Shrestha2ccdb422022-06-02 10:19:13 -0400822 {"middleinput_one", "middleinput_two", "maininput_one", "maininput_two"},
823 {"middleinput_one", "middleinput_two"},
Chris Parsons0bfb1c02022-05-12 16:43:01 -0400824 }
825 assertFlattenedDepsets(t, actualDepsets, expectedDepsetFiles)
826
Chris Parsons1a7aca02022-04-25 22:35:15 -0400827 bs := actualBuildStatements[0]
828 if len(bs.InputPaths) > 0 {
829 t.Errorf("Expected main action raw inputs to be empty, but got %q", bs.InputPaths)
830 }
831
Chris Parsonsc4fb1332021-05-18 12:31:25 -0400832 expectedOutputs := []string{"output"}
833 if !reflect.DeepEqual(bs.OutputPaths, expectedOutputs) {
834 t.Errorf("Expected main action outputs %q, but got %q", expectedOutputs, bs.OutputPaths)
835 }
Chris Parsons1a7aca02022-04-25 22:35:15 -0400836
Chris Parsons1a7aca02022-04-25 22:35:15 -0400837 expectedFlattenedInputs := []string{"middleinput_one", "middleinput_two", "maininput_one", "maininput_two"}
Chris Parsons0bfb1c02022-05-12 16:43:01 -0400838 actualFlattenedInputs := flattenDepsets(bs.InputDepsetHashes, actualDepsets)
Chris Parsons1a7aca02022-04-25 22:35:15 -0400839
840 if !reflect.DeepEqual(actualFlattenedInputs, expectedFlattenedInputs) {
841 t.Errorf("Expected flattened inputs %v, but got %v", expectedFlattenedInputs, actualFlattenedInputs)
842 }
Liz Kammera4655a92023-02-10 17:17:28 -0500843
844 bs = actualBuildStatements[1]
845 if bs != nil {
846 t.Errorf("Expected nil action for skipped")
847 }
Chris Parsons1a7aca02022-04-25 22:35:15 -0400848}
849
850// Returns the contents of given depsets in concatenated post order.
Chris Parsons0bfb1c02022-05-12 16:43:01 -0400851func flattenDepsets(depsetHashesToFlatten []string, allDepsets []AqueryDepset) []string {
852 depsetsByHash := map[string]AqueryDepset{}
Chris Parsons1a7aca02022-04-25 22:35:15 -0400853 for _, depset := range allDepsets {
Chris Parsons0bfb1c02022-05-12 16:43:01 -0400854 depsetsByHash[depset.ContentHash] = depset
Chris Parsons1a7aca02022-04-25 22:35:15 -0400855 }
Usta Shrestha16ac1352022-06-22 11:01:55 -0400856 var result []string
Chris Parsons0bfb1c02022-05-12 16:43:01 -0400857 for _, depsetId := range depsetHashesToFlatten {
858 result = append(result, flattenDepset(depsetId, depsetsByHash)...)
Chris Parsons1a7aca02022-04-25 22:35:15 -0400859 }
860 return result
861}
862
863// Returns the contents of a given depset in post order.
Chris Parsons0bfb1c02022-05-12 16:43:01 -0400864func flattenDepset(depsetHashToFlatten string, allDepsets map[string]AqueryDepset) []string {
865 depset := allDepsets[depsetHashToFlatten]
Usta Shrestha16ac1352022-06-22 11:01:55 -0400866 var result []string
Chris Parsons0bfb1c02022-05-12 16:43:01 -0400867 for _, depsetId := range depset.TransitiveDepSetHashes {
Chris Parsons1a7aca02022-04-25 22:35:15 -0400868 result = append(result, flattenDepset(depsetId, allDepsets)...)
869 }
870 result = append(result, depset.DirectArtifacts...)
871 return result
Chris Parsonsc4fb1332021-05-18 12:31:25 -0400872}
873
Chris Parsons0bfb1c02022-05-12 16:43:01 -0400874func assertFlattenedDepsets(t *testing.T, actualDepsets []AqueryDepset, expectedDepsetFiles [][]string) {
875 t.Helper()
876 if len(actualDepsets) != len(expectedDepsetFiles) {
Sasha Smundakf10c3ac2022-06-08 11:46:31 -0700877 t.Errorf("Expected %d depsets, but got %d depsets", len(expectedDepsetFiles), len(actualDepsets))
Chris Parsons0bfb1c02022-05-12 16:43:01 -0400878 }
879 for i, actualDepset := range actualDepsets {
880 actualFlattenedInputs := flattenDepsets([]string{actualDepset.ContentHash}, actualDepsets)
881 if !reflect.DeepEqual(actualFlattenedInputs, expectedDepsetFiles[i]) {
882 t.Errorf("Expected depset files: %v, but got %v", expectedDepsetFiles[i], actualFlattenedInputs)
883 }
884 }
885}
886
Liz Kammerc49e6822021-06-08 15:04:11 -0400887func TestSimpleSymlink(t *testing.T) {
888 const inputString = `
889{
Jason Wu118fd2b2022-10-27 18:41:15 +0000890 "artifacts": [
891 { "id": 1, "path_fragment_id": 3 },
892 { "id": 2, "path_fragment_id": 5 }],
893 "actions": [{
894 "target_id": 1,
895 "action_key": "x",
896 "mnemonic": "Symlink",
897 "input_dep_set_ids": [1],
898 "output_ids": [2],
899 "primary_output_id": 2
900 }],
901 "dep_set_of_files": [
902 { "id": 1, "direct_artifact_ids": [1] }],
903 "path_fragments": [
904 { "id": 1, "label": "one" },
905 { "id": 2, "label": "file_subdir", "parent_id": 1 },
906 { "id": 3, "label": "file", "parent_id": 2 },
907 { "id": 4, "label": "symlink_subdir", "parent_id": 1 },
908 { "id": 5, "label": "symlink", "parent_id": 4 }]
Liz Kammerc49e6822021-06-08 15:04:11 -0400909}`
Jason Wu118fd2b2022-10-27 18:41:15 +0000910 data, err := JsonToActionGraphContainer(inputString)
911 if err != nil {
912 t.Error(err)
913 return
914 }
Liz Kammer690fbac2023-02-10 11:11:17 -0500915 actual, _, err := AqueryBuildStatements(data, &metrics.EventHandler{})
Liz Kammerc49e6822021-06-08 15:04:11 -0400916
917 if err != nil {
918 t.Errorf("Unexpected error %q", err)
Cole Faustbc65a3f2023-08-01 16:38:55 +0000919 return
Liz Kammerc49e6822021-06-08 15:04:11 -0400920 }
921
Liz Kammera4655a92023-02-10 17:17:28 -0500922 expectedBuildStatements := []*BuildStatement{
923 &BuildStatement{
Liz Kammerc49e6822021-06-08 15:04:11 -0400924 Command: "mkdir -p one/symlink_subdir && " +
925 "rm -f one/symlink_subdir/symlink && " +
Liz Kammerc7737782021-11-04 10:56:13 -0400926 "ln -sf $PWD/one/file_subdir/file one/symlink_subdir/symlink",
Liz Kammerc49e6822021-06-08 15:04:11 -0400927 InputPaths: []string{"one/file_subdir/file"},
928 OutputPaths: []string{"one/symlink_subdir/symlink"},
929 SymlinkPaths: []string{"one/symlink_subdir/symlink"},
930 Mnemonic: "Symlink",
931 },
932 }
933 assertBuildStatements(t, actual, expectedBuildStatements)
934}
935
936func TestSymlinkQuotesPaths(t *testing.T) {
937 const inputString = `
938{
Jason Wu118fd2b2022-10-27 18:41:15 +0000939 "artifacts": [
940 { "id": 1, "path_fragment_id": 3 },
941 { "id": 2, "path_fragment_id": 5 }],
942 "actions": [{
943 "target_id": 1,
944 "action_key": "x",
945 "mnemonic": "SolibSymlink",
946 "input_dep_set_ids": [1],
947 "output_ids": [2],
948 "primary_output_id": 2
949 }],
950 "dep_set_of_files": [
951 { "id": 1, "direct_artifact_ids": [1] }],
952 "path_fragments": [
953 { "id": 1, "label": "one" },
954 { "id": 2, "label": "file subdir", "parent_id": 1 },
955 { "id": 3, "label": "file", "parent_id": 2 },
956 { "id": 4, "label": "symlink subdir", "parent_id": 1 },
957 { "id": 5, "label": "symlink", "parent_id": 4 }]
Liz Kammerc49e6822021-06-08 15:04:11 -0400958}`
959
Jason Wu118fd2b2022-10-27 18:41:15 +0000960 data, err := JsonToActionGraphContainer(inputString)
961 if err != nil {
962 t.Error(err)
963 return
964 }
Liz Kammer690fbac2023-02-10 11:11:17 -0500965 actual, _, err := AqueryBuildStatements(data, &metrics.EventHandler{})
Liz Kammerc49e6822021-06-08 15:04:11 -0400966 if err != nil {
967 t.Errorf("Unexpected error %q", err)
Cole Faustbc65a3f2023-08-01 16:38:55 +0000968 return
Liz Kammerc49e6822021-06-08 15:04:11 -0400969 }
970
Liz Kammera4655a92023-02-10 17:17:28 -0500971 expectedBuildStatements := []*BuildStatement{
972 &BuildStatement{
Liz Kammerc49e6822021-06-08 15:04:11 -0400973 Command: "mkdir -p 'one/symlink subdir' && " +
974 "rm -f 'one/symlink subdir/symlink' && " +
Liz Kammerc7737782021-11-04 10:56:13 -0400975 "ln -sf $PWD/'one/file subdir/file' 'one/symlink subdir/symlink'",
Liz Kammerc49e6822021-06-08 15:04:11 -0400976 InputPaths: []string{"one/file subdir/file"},
977 OutputPaths: []string{"one/symlink subdir/symlink"},
978 SymlinkPaths: []string{"one/symlink subdir/symlink"},
979 Mnemonic: "SolibSymlink",
980 },
981 }
Liz Kammerc7737782021-11-04 10:56:13 -0400982 assertBuildStatements(t, expectedBuildStatements, actual)
Liz Kammerc49e6822021-06-08 15:04:11 -0400983}
984
985func TestSymlinkMultipleInputs(t *testing.T) {
986 const inputString = `
987{
Jason Wu118fd2b2022-10-27 18:41:15 +0000988 "artifacts": [
989 { "id": 1, "path_fragment_id": 1 },
990 { "id": 2, "path_fragment_id": 2 },
991 { "id": 3, "path_fragment_id": 3 }],
992 "actions": [{
993 "target_id": 1,
ustac4547812023-09-25 17:34:15 -0400994 "action_key": "action_x",
Jason Wu118fd2b2022-10-27 18:41:15 +0000995 "mnemonic": "Symlink",
996 "input_dep_set_ids": [1],
997 "output_ids": [3],
998 "primary_output_id": 3
999 }],
1000 "dep_set_of_files": [{ "id": 1, "direct_artifact_ids": [1,2] }],
1001 "path_fragments": [
1002 { "id": 1, "label": "file" },
1003 { "id": 2, "label": "other_file" },
1004 { "id": 3, "label": "symlink" }]
Liz Kammerc49e6822021-06-08 15:04:11 -04001005}`
1006
Jason Wu118fd2b2022-10-27 18:41:15 +00001007 data, err := JsonToActionGraphContainer(inputString)
1008 if err != nil {
1009 t.Error(err)
1010 return
1011 }
Liz Kammer690fbac2023-02-10 11:11:17 -05001012 _, _, err = AqueryBuildStatements(data, &metrics.EventHandler{})
ustac4547812023-09-25 17:34:15 -04001013 assertError(t, err, `Expect 1 input and 1 output to symlink action, got: input ["file" "other_file"], output ["symlink"]: [Symlink] []`)
Liz Kammerc49e6822021-06-08 15:04:11 -04001014}
1015
1016func TestSymlinkMultipleOutputs(t *testing.T) {
1017 const inputString = `
1018{
Jason Wu118fd2b2022-10-27 18:41:15 +00001019 "artifacts": [
1020 { "id": 1, "path_fragment_id": 1 },
1021 { "id": 3, "path_fragment_id": 3 }],
1022 "actions": [{
1023 "target_id": 1,
1024 "action_key": "x",
1025 "mnemonic": "Symlink",
1026 "input_dep_set_ids": [1],
1027 "output_ids": [2,3],
1028 "primary_output_id": 2
1029 }],
1030 "dep_set_of_files": [
1031 { "id": 1, "direct_artifact_ids": [1] }],
1032 "path_fragments": [
1033 { "id": 1, "label": "file" },
1034 { "id": 2, "label": "symlink" },
1035 { "id": 3, "label": "other_symlink" }]
Liz Kammerc49e6822021-06-08 15:04:11 -04001036}`
1037
Jason Wu118fd2b2022-10-27 18:41:15 +00001038 data, err := JsonToActionGraphContainer(inputString)
1039 if err != nil {
1040 t.Error(err)
1041 return
1042 }
Liz Kammer690fbac2023-02-10 11:11:17 -05001043 _, _, err = AqueryBuildStatements(data, &metrics.EventHandler{})
ustac4547812023-09-25 17:34:15 -04001044 assertError(t, err, "undefined outputId 2: [Symlink] []")
Liz Kammerc49e6822021-06-08 15:04:11 -04001045}
1046
Wei Li455ba832021-11-04 22:58:12 +00001047func TestTemplateExpandActionSubstitutions(t *testing.T) {
1048 const inputString = `
1049{
Jason Wu118fd2b2022-10-27 18:41:15 +00001050 "artifacts": [{
1051 "id": 1,
1052 "path_fragment_id": 1
1053 }],
1054 "actions": [{
1055 "target_id": 1,
1056 "action_key": "x",
1057 "mnemonic": "TemplateExpand",
1058 "configuration_id": 1,
1059 "output_ids": [1],
1060 "primary_output_id": 1,
1061 "execution_platform": "//build/bazel/platforms:linux_x86_64",
1062 "template_content": "Test template substitutions: %token1%, %python_binary%",
1063 "substitutions": [
1064 { "key": "%token1%", "value": "abcd" },
1065 { "key": "%python_binary%", "value": "python3" }]
1066 }],
1067 "path_fragments": [
1068 { "id": 1, "label": "template_file" }]
Wei Li455ba832021-11-04 22:58:12 +00001069}`
1070
Jason Wu118fd2b2022-10-27 18:41:15 +00001071 data, err := JsonToActionGraphContainer(inputString)
1072 if err != nil {
1073 t.Error(err)
1074 return
1075 }
Liz Kammer690fbac2023-02-10 11:11:17 -05001076 actual, _, err := AqueryBuildStatements(data, &metrics.EventHandler{})
Wei Li455ba832021-11-04 22:58:12 +00001077 if err != nil {
1078 t.Errorf("Unexpected error %q", err)
Cole Faustbc65a3f2023-08-01 16:38:55 +00001079 return
Wei Li455ba832021-11-04 22:58:12 +00001080 }
1081
Liz Kammera4655a92023-02-10 17:17:28 -05001082 expectedBuildStatements := []*BuildStatement{
1083 &BuildStatement{
Wei Li455ba832021-11-04 22:58:12 +00001084 Command: "/bin/bash -c 'echo \"Test template substitutions: abcd, python3\" | sed \"s/\\\\\\\\n/\\\\n/g\" > template_file && " +
1085 "chmod a+x template_file'",
Liz Kammer00629db2023-02-09 14:28:15 -05001086 OutputPaths: []string{"template_file"},
1087 Mnemonic: "TemplateExpand",
1088 SymlinkPaths: []string{},
Wei Li455ba832021-11-04 22:58:12 +00001089 },
1090 }
1091 assertBuildStatements(t, expectedBuildStatements, actual)
1092}
1093
1094func TestTemplateExpandActionNoOutput(t *testing.T) {
1095 const inputString = `
1096{
Jason Wu118fd2b2022-10-27 18:41:15 +00001097 "artifacts": [
1098 { "id": 1, "path_fragment_id": 1 }],
1099 "actions": [{
1100 "target_id": 1,
1101 "action_key": "x",
1102 "mnemonic": "TemplateExpand",
1103 "configuration_id": 1,
1104 "primary_output_id": 1,
1105 "execution_platform": "//build/bazel/platforms:linux_x86_64",
1106 "templateContent": "Test template substitutions: %token1%, %python_binary%",
1107 "substitutions": [
1108 { "key": "%token1%", "value": "abcd" },
1109 { "key": "%python_binary%", "value": "python3" }]
1110 }],
1111 "path_fragments": [
1112 { "id": 1, "label": "template_file" }]
Wei Li455ba832021-11-04 22:58:12 +00001113}`
1114
Jason Wu118fd2b2022-10-27 18:41:15 +00001115 data, err := JsonToActionGraphContainer(inputString)
1116 if err != nil {
1117 t.Error(err)
1118 return
1119 }
Liz Kammer690fbac2023-02-10 11:11:17 -05001120 _, _, err = AqueryBuildStatements(data, &metrics.EventHandler{})
ustac4547812023-09-25 17:34:15 -04001121 assertError(t, err, `Expect 1 output to template expand action, got: output []: [TemplateExpand] []`)
Wei Li455ba832021-11-04 22:58:12 +00001122}
1123
Sasha Smundak1da064c2022-06-08 16:36:16 -07001124func TestFileWrite(t *testing.T) {
1125 const inputString = `
1126{
Jason Wu118fd2b2022-10-27 18:41:15 +00001127 "artifacts": [
1128 { "id": 1, "path_fragment_id": 1 }],
1129 "actions": [{
1130 "target_id": 1,
1131 "action_key": "x",
1132 "mnemonic": "FileWrite",
1133 "configuration_id": 1,
1134 "output_ids": [1],
1135 "primary_output_id": 1,
1136 "execution_platform": "//build/bazel/platforms:linux_x86_64",
1137 "file_contents": "file data\n"
1138 }],
1139 "path_fragments": [
1140 { "id": 1, "label": "foo.manifest" }]
Sasha Smundak1da064c2022-06-08 16:36:16 -07001141}
1142`
Jason Wu118fd2b2022-10-27 18:41:15 +00001143 data, err := JsonToActionGraphContainer(inputString)
1144 if err != nil {
1145 t.Error(err)
1146 return
1147 }
Liz Kammer690fbac2023-02-10 11:11:17 -05001148 actual, _, err := AqueryBuildStatements(data, &metrics.EventHandler{})
Sasha Smundak1da064c2022-06-08 16:36:16 -07001149 if err != nil {
1150 t.Errorf("Unexpected error %q", err)
Cole Faustbc65a3f2023-08-01 16:38:55 +00001151 return
Sasha Smundak1da064c2022-06-08 16:36:16 -07001152 }
Liz Kammera4655a92023-02-10 17:17:28 -05001153 assertBuildStatements(t, []*BuildStatement{
1154 &BuildStatement{
Sasha Smundak1da064c2022-06-08 16:36:16 -07001155 OutputPaths: []string{"foo.manifest"},
1156 Mnemonic: "FileWrite",
1157 FileContents: "file data\n",
Liz Kammer00629db2023-02-09 14:28:15 -05001158 SymlinkPaths: []string{},
Sasha Smundak1da064c2022-06-08 16:36:16 -07001159 },
1160 }, actual)
1161}
1162
1163func TestSourceSymlinkManifest(t *testing.T) {
1164 const inputString = `
1165{
Jason Wu118fd2b2022-10-27 18:41:15 +00001166 "artifacts": [
1167 { "id": 1, "path_fragment_id": 1 }],
1168 "actions": [{
1169 "target_id": 1,
1170 "action_key": "x",
1171 "mnemonic": "SourceSymlinkManifest",
1172 "configuration_id": 1,
1173 "output_ids": [1],
1174 "primary_output_id": 1,
1175 "execution_platform": "//build/bazel/platforms:linux_x86_64",
1176 "file_contents": "symlink target\n"
1177 }],
1178 "path_fragments": [
1179 { "id": 1, "label": "foo.manifest" }]
Sasha Smundak1da064c2022-06-08 16:36:16 -07001180}
1181`
Jason Wu118fd2b2022-10-27 18:41:15 +00001182 data, err := JsonToActionGraphContainer(inputString)
1183 if err != nil {
1184 t.Error(err)
1185 return
1186 }
Liz Kammer690fbac2023-02-10 11:11:17 -05001187 actual, _, err := AqueryBuildStatements(data, &metrics.EventHandler{})
Sasha Smundak1da064c2022-06-08 16:36:16 -07001188 if err != nil {
1189 t.Errorf("Unexpected error %q", err)
Cole Faustbc65a3f2023-08-01 16:38:55 +00001190 return
Sasha Smundak1da064c2022-06-08 16:36:16 -07001191 }
Liz Kammera4655a92023-02-10 17:17:28 -05001192 assertBuildStatements(t, []*BuildStatement{
1193 &BuildStatement{
Liz Kammer00629db2023-02-09 14:28:15 -05001194 OutputPaths: []string{"foo.manifest"},
1195 Mnemonic: "SourceSymlinkManifest",
1196 SymlinkPaths: []string{},
Sasha Smundak1da064c2022-06-08 16:36:16 -07001197 },
1198 }, actual)
1199}
1200
Cole Faustbc65a3f2023-08-01 16:38:55 +00001201func TestUnresolvedSymlink(t *testing.T) {
1202 const inputString = `
1203{
1204 "artifacts": [
1205 { "id": 1, "path_fragment_id": 1 }
1206 ],
1207 "actions": [{
1208 "target_id": 1,
1209 "action_key": "x",
1210 "mnemonic": "UnresolvedSymlink",
1211 "configuration_id": 1,
1212 "output_ids": [1],
1213 "primary_output_id": 1,
1214 "execution_platform": "//build/bazel/platforms:linux_x86_64",
1215 "unresolved_symlink_target": "symlink/target"
1216 }],
1217 "path_fragments": [
1218 { "id": 1, "label": "path/to/symlink" }
1219 ]
1220}
1221`
1222 data, err := JsonToActionGraphContainer(inputString)
1223 if err != nil {
1224 t.Error(err)
1225 return
1226 }
1227 actual, _, err := AqueryBuildStatements(data, &metrics.EventHandler{})
1228 if err != nil {
1229 t.Errorf("Unexpected error %q", err)
1230 return
1231 }
1232 assertBuildStatements(t, []*BuildStatement{{
1233 Command: "mkdir -p path/to && rm -f path/to/symlink && ln -sf symlink/target path/to/symlink",
1234 OutputPaths: []string{"path/to/symlink"},
1235 Mnemonic: "UnresolvedSymlink",
1236 SymlinkPaths: []string{"path/to/symlink"},
1237 }}, actual)
1238}
1239
1240func TestUnresolvedSymlinkBazelSandwich(t *testing.T) {
1241 const inputString = `
1242{
1243 "artifacts": [
1244 { "id": 1, "path_fragment_id": 1 }
1245 ],
1246 "actions": [{
1247 "target_id": 1,
1248 "action_key": "x",
1249 "mnemonic": "UnresolvedSymlink",
1250 "configuration_id": 1,
1251 "output_ids": [1],
1252 "primary_output_id": 1,
1253 "execution_platform": "//build/bazel/platforms:linux_x86_64",
1254 "unresolved_symlink_target": "bazel_sandwich:{\"target\":\"target/product/emulator_x86_64/system\"}"
1255 }],
1256 "path_fragments": [
1257 { "id": 1, "label": "path/to/symlink" }
1258 ]
1259}
1260`
1261 data, err := JsonToActionGraphContainer(inputString)
1262 if err != nil {
1263 t.Error(err)
1264 return
1265 }
1266 actual, _, err := AqueryBuildStatements(data, &metrics.EventHandler{})
1267 if err != nil {
1268 t.Errorf("Unexpected error %q", err)
1269 return
1270 }
1271 assertBuildStatements(t, []*BuildStatement{{
1272 Command: "mkdir -p path/to && rm -f path/to/symlink && ln -sf {DOTDOTS_TO_OUTPUT_ROOT}../../target/product/emulator_x86_64/system path/to/symlink",
1273 OutputPaths: []string{"path/to/symlink"},
1274 Mnemonic: "UnresolvedSymlink",
1275 SymlinkPaths: []string{"path/to/symlink"},
1276 ImplicitDeps: []string{"target/product/emulator_x86_64/system"},
1277 }}, actual)
1278}
1279
1280func TestUnresolvedSymlinkBazelSandwichWithAlternativeDeps(t *testing.T) {
1281 const inputString = `
1282{
1283 "artifacts": [
1284 { "id": 1, "path_fragment_id": 1 }
1285 ],
1286 "actions": [{
1287 "target_id": 1,
1288 "action_key": "x",
1289 "mnemonic": "UnresolvedSymlink",
1290 "configuration_id": 1,
1291 "output_ids": [1],
1292 "primary_output_id": 1,
1293 "execution_platform": "//build/bazel/platforms:linux_x86_64",
1294 "unresolved_symlink_target": "bazel_sandwich:{\"depend_on_target\":false,\"implicit_deps\":[\"target/product/emulator_x86_64/obj/PACKAGING/systemimage_intermediates/staging_dir.stamp\"],\"target\":\"target/product/emulator_x86_64/system\"}"
1295 }],
1296 "path_fragments": [
1297 { "id": 1, "label": "path/to/symlink" }
1298 ]
1299}
1300`
1301 data, err := JsonToActionGraphContainer(inputString)
1302 if err != nil {
1303 t.Error(err)
1304 return
1305 }
1306 actual, _, err := AqueryBuildStatements(data, &metrics.EventHandler{})
1307 if err != nil {
1308 t.Errorf("Unexpected error %q", err)
1309 return
1310 }
1311 assertBuildStatements(t, []*BuildStatement{{
1312 Command: "mkdir -p path/to && rm -f path/to/symlink && ln -sf {DOTDOTS_TO_OUTPUT_ROOT}../../target/product/emulator_x86_64/system path/to/symlink",
1313 OutputPaths: []string{"path/to/symlink"},
1314 Mnemonic: "UnresolvedSymlink",
1315 SymlinkPaths: []string{"path/to/symlink"},
1316 // Note that the target of the symlink, target/product/emulator_x86_64/system, is not listed here
1317 ImplicitDeps: []string{"target/product/emulator_x86_64/obj/PACKAGING/systemimage_intermediates/staging_dir.stamp"},
1318 }}, actual)
1319}
1320
Chris Parsons4f069892021-01-15 12:22:41 -05001321func assertError(t *testing.T, err error, expected string) {
Liz Kammerc49e6822021-06-08 15:04:11 -04001322 t.Helper()
Chris Parsons943f2432021-01-19 11:36:50 -05001323 if err == nil {
1324 t.Errorf("expected error '%s', but got no error", expected)
1325 } else if err.Error() != expected {
Liz Kammerc49e6822021-06-08 15:04:11 -04001326 t.Errorf("expected error:\n\t'%s', but got:\n\t'%s'", expected, err.Error())
Chris Parsons4f069892021-01-15 12:22:41 -05001327 }
1328}
1329
1330// Asserts that the given actual build statements match the given expected build statements.
1331// Build statement equivalence is determined using buildStatementEquals.
Liz Kammera4655a92023-02-10 17:17:28 -05001332func assertBuildStatements(t *testing.T, expected []*BuildStatement, actual []*BuildStatement) {
Liz Kammerc49e6822021-06-08 15:04:11 -04001333 t.Helper()
Chris Parsons4f069892021-01-15 12:22:41 -05001334 if len(expected) != len(actual) {
Liz Kammerc3192992021-11-16 17:01:11 -05001335 t.Errorf("expected %d build statements, but got %d,\n expected: %#v,\n actual: %#v",
Chris Parsons4f069892021-01-15 12:22:41 -05001336 len(expected), len(actual), expected, actual)
1337 return
1338 }
Usta Shrestha1c4a3ea2022-06-23 16:09:32 -04001339 type compareFn = func(i int, j int) bool
Liz Kammera4655a92023-02-10 17:17:28 -05001340 byCommand := func(slice []*BuildStatement) compareFn {
Usta Shrestha1c4a3ea2022-06-23 16:09:32 -04001341 return func(i int, j int) bool {
Liz Kammera4655a92023-02-10 17:17:28 -05001342 if slice[i] == nil {
1343 return false
1344 } else if slice[j] == nil {
1345 return false
1346 }
Usta Shrestha1c4a3ea2022-06-23 16:09:32 -04001347 return slice[i].Command < slice[j].Command
Chris Parsons4f069892021-01-15 12:22:41 -05001348 }
Usta Shrestha1c4a3ea2022-06-23 16:09:32 -04001349 }
1350 sort.SliceStable(expected, byCommand(expected))
1351 sort.SliceStable(actual, byCommand(actual))
1352 for i, actualStatement := range actual {
1353 expectedStatement := expected[i]
1354 if differingField := buildStatementEquals(actualStatement, expectedStatement); differingField != "" {
1355 t.Errorf("%s differs\nunexpected build statement %#v.\nexpected: %#v",
Usta Shresthaef922252022-06-02 14:23:02 -04001356 differingField, actualStatement, expectedStatement)
Usta Shrestha1c4a3ea2022-06-23 16:09:32 -04001357 return
1358 }
Chris Parsons4f069892021-01-15 12:22:41 -05001359 }
1360}
1361
Liz Kammera4655a92023-02-10 17:17:28 -05001362func buildStatementEquals(first *BuildStatement, second *BuildStatement) string {
1363 if (first == nil) != (second == nil) {
1364 return "Nil"
1365 }
Chris Parsons4f069892021-01-15 12:22:41 -05001366 if first.Mnemonic != second.Mnemonic {
Usta Shrestha1c4a3ea2022-06-23 16:09:32 -04001367 return "Mnemonic"
Chris Parsons4f069892021-01-15 12:22:41 -05001368 }
1369 if first.Command != second.Command {
Usta Shrestha1c4a3ea2022-06-23 16:09:32 -04001370 return "Command"
Chris Parsons4f069892021-01-15 12:22:41 -05001371 }
1372 // Ordering is significant for environment variables.
1373 if !reflect.DeepEqual(first.Env, second.Env) {
Usta Shrestha1c4a3ea2022-06-23 16:09:32 -04001374 return "Env"
Chris Parsons4f069892021-01-15 12:22:41 -05001375 }
1376 // Ordering is irrelevant for input and output paths, so compare sets.
Usta Shrestha1c4a3ea2022-06-23 16:09:32 -04001377 if !reflect.DeepEqual(sortedStrings(first.InputPaths), sortedStrings(second.InputPaths)) {
1378 return "InputPaths"
Chris Parsons4f069892021-01-15 12:22:41 -05001379 }
Usta Shrestha1c4a3ea2022-06-23 16:09:32 -04001380 if !reflect.DeepEqual(sortedStrings(first.OutputPaths), sortedStrings(second.OutputPaths)) {
1381 return "OutputPaths"
Chris Parsons4f069892021-01-15 12:22:41 -05001382 }
Usta Shrestha1c4a3ea2022-06-23 16:09:32 -04001383 if !reflect.DeepEqual(sortedStrings(first.SymlinkPaths), sortedStrings(second.SymlinkPaths)) {
1384 return "SymlinkPaths"
Liz Kammerc49e6822021-06-08 15:04:11 -04001385 }
Cole Faustbc65a3f2023-08-01 16:38:55 +00001386 if !reflect.DeepEqual(sortedStrings(first.ImplicitDeps), sortedStrings(second.ImplicitDeps)) {
1387 return "ImplicitDeps"
1388 }
Liz Kammerc49e6822021-06-08 15:04:11 -04001389 if first.Depfile != second.Depfile {
Usta Shrestha1c4a3ea2022-06-23 16:09:32 -04001390 return "Depfile"
Liz Kammerc49e6822021-06-08 15:04:11 -04001391 }
Usta Shrestha1c4a3ea2022-06-23 16:09:32 -04001392 return ""
Chris Parsons4f069892021-01-15 12:22:41 -05001393}
1394
Usta Shrestha1c4a3ea2022-06-23 16:09:32 -04001395func sortedStrings(stringSlice []string) []string {
1396 sorted := make([]string, len(stringSlice))
1397 copy(sorted, stringSlice)
1398 sort.Strings(sorted)
1399 return sorted
Chris Parsons4f069892021-01-15 12:22:41 -05001400}
Jason Wu118fd2b2022-10-27 18:41:15 +00001401
1402// Transform the json format to ActionGraphContainer
1403func JsonToActionGraphContainer(inputString string) ([]byte, error) {
1404 var aqueryProtoResult analysis_v2_proto.ActionGraphContainer
1405 err := json.Unmarshal([]byte(inputString), &aqueryProtoResult)
1406 if err != nil {
1407 return []byte(""), err
1408 }
1409 data, _ := proto.Marshal(&aqueryProtoResult)
1410 return data, err
1411}