blob: 1749cd47a5d628c0020a9925a3e9fb4ccc023319 [file] [log] [blame]
Dan Willemsen9b587492017-07-10 22:13:00 -07001// Copyright 2017 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 build
16
17import (
18 "bytes"
19 "context"
Patrice Arruda13848222019-04-22 17:12:02 -070020 "fmt"
21 "io/ioutil"
22 "os"
23 "path/filepath"
Dan Willemsen9b587492017-07-10 22:13:00 -070024 "reflect"
25 "strings"
26 "testing"
27
28 "android/soong/ui/logger"
Liz Kammerca9cb2e2021-07-14 15:29:57 -040029 smpb "android/soong/ui/metrics/metrics_proto"
Patrice Arruda219eef32020-06-01 17:29:30 +000030 "android/soong/ui/status"
Romain Jobredeaux0a7529b2022-10-26 12:56:41 -040031
Chris Parsonsef615e52022-08-18 22:04:11 -040032 "google.golang.org/protobuf/encoding/prototext"
Liz Kammerca9cb2e2021-07-14 15:29:57 -040033
Dan Willemsen4591b642021-05-24 14:24:12 -070034 "google.golang.org/protobuf/proto"
Dan Willemsen9b587492017-07-10 22:13:00 -070035)
36
37func testContext() Context {
38 return Context{&ContextImpl{
Dan Willemsenb82471a2018-05-17 16:37:09 -070039 Context: context.Background(),
40 Logger: logger.New(&bytes.Buffer{}),
Colin Cross097ed2a2019-06-08 21:48:58 -070041 Writer: &bytes.Buffer{},
Patrice Arruda219eef32020-06-01 17:29:30 +000042 Status: &status.Status{},
Dan Willemsen9b587492017-07-10 22:13:00 -070043 }}
44}
45
46func TestConfigParseArgsJK(t *testing.T) {
47 ctx := testContext()
48
49 testCases := []struct {
50 args []string
51
52 parallel int
53 keepGoing int
54 remaining []string
55 }{
56 {nil, -1, -1, nil},
57
58 {[]string{"-j"}, -1, -1, nil},
59 {[]string{"-j1"}, 1, -1, nil},
60 {[]string{"-j1234"}, 1234, -1, nil},
61
62 {[]string{"-j", "1"}, 1, -1, nil},
63 {[]string{"-j", "1234"}, 1234, -1, nil},
64 {[]string{"-j", "1234", "abc"}, 1234, -1, []string{"abc"}},
65 {[]string{"-j", "abc"}, -1, -1, []string{"abc"}},
66 {[]string{"-j", "1abc"}, -1, -1, []string{"1abc"}},
67
68 {[]string{"-k"}, -1, 0, nil},
69 {[]string{"-k0"}, -1, 0, nil},
70 {[]string{"-k1"}, -1, 1, nil},
71 {[]string{"-k1234"}, -1, 1234, nil},
72
73 {[]string{"-k", "0"}, -1, 0, nil},
74 {[]string{"-k", "1"}, -1, 1, nil},
75 {[]string{"-k", "1234"}, -1, 1234, nil},
76 {[]string{"-k", "1234", "abc"}, -1, 1234, []string{"abc"}},
77 {[]string{"-k", "abc"}, -1, 0, []string{"abc"}},
78 {[]string{"-k", "1abc"}, -1, 0, []string{"1abc"}},
79
80 // TODO: These are supported in Make, should we support them?
81 //{[]string{"-kj"}, -1, 0},
82 //{[]string{"-kj8"}, 8, 0},
83
84 // -jk is not valid in Make
85 }
86
87 for _, tc := range testCases {
88 t.Run(strings.Join(tc.args, " "), func(t *testing.T) {
89 defer logger.Recover(func(err error) {
90 t.Fatal(err)
91 })
92
Chris Parsonsb6e96902022-10-31 20:08:45 -040093 env := Environment([]string{})
Dan Willemsen9b587492017-07-10 22:13:00 -070094 c := &configImpl{
Chris Parsonsb6e96902022-10-31 20:08:45 -040095 environ: &env,
Dan Willemsen9b587492017-07-10 22:13:00 -070096 parallel: -1,
97 keepGoing: -1,
98 }
99 c.parseArgs(ctx, tc.args)
100
101 if c.parallel != tc.parallel {
102 t.Errorf("for %q, parallel:\nwant: %d\n got: %d\n",
103 strings.Join(tc.args, " "),
104 tc.parallel, c.parallel)
105 }
106 if c.keepGoing != tc.keepGoing {
107 t.Errorf("for %q, keep going:\nwant: %d\n got: %d\n",
108 strings.Join(tc.args, " "),
109 tc.keepGoing, c.keepGoing)
110 }
111 if !reflect.DeepEqual(c.arguments, tc.remaining) {
112 t.Errorf("for %q, remaining arguments:\nwant: %q\n got: %q\n",
113 strings.Join(tc.args, " "),
114 tc.remaining, c.arguments)
115 }
116 })
117 }
118}
Dan Willemsen091525e2017-07-11 14:17:50 -0700119
120func TestConfigParseArgsVars(t *testing.T) {
121 ctx := testContext()
122
123 testCases := []struct {
124 env []string
125 args []string
126
127 expectedEnv []string
128 remaining []string
129 }{
130 {},
131 {
132 env: []string{"A=bc"},
133
134 expectedEnv: []string{"A=bc"},
135 },
136 {
137 args: []string{"abc"},
138
139 remaining: []string{"abc"},
140 },
141
142 {
143 args: []string{"A=bc"},
144
145 expectedEnv: []string{"A=bc"},
146 },
147 {
148 env: []string{"A=a"},
149 args: []string{"A=bc"},
150
151 expectedEnv: []string{"A=bc"},
152 },
153
154 {
155 env: []string{"A=a"},
156 args: []string{"A=", "=b"},
157
158 expectedEnv: []string{"A="},
159 remaining: []string{"=b"},
160 },
161 }
162
163 for _, tc := range testCases {
164 t.Run(strings.Join(tc.args, " "), func(t *testing.T) {
165 defer logger.Recover(func(err error) {
166 t.Fatal(err)
167 })
168
169 e := Environment(tc.env)
170 c := &configImpl{
171 environ: &e,
172 }
173 c.parseArgs(ctx, tc.args)
174
175 if !reflect.DeepEqual([]string(*c.environ), tc.expectedEnv) {
176 t.Errorf("for env=%q args=%q, environment:\nwant: %q\n got: %q\n",
177 tc.env, tc.args,
178 tc.expectedEnv, []string(*c.environ))
179 }
180 if !reflect.DeepEqual(c.arguments, tc.remaining) {
181 t.Errorf("for env=%q args=%q, remaining arguments:\nwant: %q\n got: %q\n",
182 tc.env, tc.args,
183 tc.remaining, c.arguments)
184 }
185 })
186 }
187}
Patrice Arruda13848222019-04-22 17:12:02 -0700188
189func TestConfigCheckTopDir(t *testing.T) {
190 ctx := testContext()
191 buildRootDir := filepath.Dir(srcDirFileCheck)
192 expectedErrStr := fmt.Sprintf("Current working directory must be the source tree. %q not found.", srcDirFileCheck)
193
194 tests := []struct {
195 // ********* Setup *********
196 // Test description.
197 description string
198
199 // ********* Action *********
200 // If set to true, the build root file is created.
201 rootBuildFile bool
202
203 // The current path where Soong is being executed.
204 path string
205
206 // ********* Validation *********
207 // Expecting error and validate the error string against expectedErrStr.
208 wantErr bool
209 }{{
210 description: "current directory is the root source tree",
211 rootBuildFile: true,
212 path: ".",
213 wantErr: false,
214 }, {
215 description: "one level deep in the source tree",
216 rootBuildFile: true,
217 path: "1",
218 wantErr: true,
219 }, {
220 description: "very deep in the source tree",
221 rootBuildFile: true,
222 path: "1/2/3/4/5/6/7/8/9/1/2/3/4/5/6/7/8/9/1/2/3/4/5/6/7/8/9/1/2/3/4/5/6/7",
223 wantErr: true,
224 }, {
225 description: "outside of source tree",
226 rootBuildFile: false,
227 path: "1/2/3/4/5",
228 wantErr: true,
229 }}
230
231 for _, tt := range tests {
232 t.Run(tt.description, func(t *testing.T) {
233 defer logger.Recover(func(err error) {
234 if !tt.wantErr {
235 t.Fatalf("Got unexpected error: %v", err)
236 }
237 if expectedErrStr != err.Error() {
238 t.Fatalf("expected %s, got %s", expectedErrStr, err.Error())
239 }
240 })
241
242 // Create the root source tree.
243 rootDir, err := ioutil.TempDir("", "")
244 if err != nil {
245 t.Fatal(err)
246 }
247 defer os.RemoveAll(rootDir)
248
249 // Create the build root file. This is to test if topDir returns an error if the build root
250 // file does not exist.
251 if tt.rootBuildFile {
252 dir := filepath.Join(rootDir, buildRootDir)
253 if err := os.MkdirAll(dir, 0755); err != nil {
254 t.Errorf("failed to create %s directory: %v", dir, err)
255 }
256 f := filepath.Join(rootDir, srcDirFileCheck)
257 if err := ioutil.WriteFile(f, []byte{}, 0644); err != nil {
258 t.Errorf("failed to create file %s: %v", f, err)
259 }
260 }
261
262 // Next block of code is to set the current directory.
263 dir := rootDir
264 if tt.path != "" {
265 dir = filepath.Join(dir, tt.path)
266 if err := os.MkdirAll(dir, 0755); err != nil {
267 t.Errorf("failed to create %s directory: %v", dir, err)
268 }
269 }
270 curDir, err := os.Getwd()
271 if err != nil {
272 t.Fatalf("failed to get the current directory: %v", err)
273 }
274 defer func() { os.Chdir(curDir) }()
275
276 if err := os.Chdir(dir); err != nil {
277 t.Fatalf("failed to change directory to %s: %v", dir, err)
278 }
279
280 checkTopDir(ctx)
281 })
282 }
283}
284
285func TestConfigConvertToTarget(t *testing.T) {
286 tests := []struct {
287 // ********* Setup *********
288 // Test description.
289 description string
290
291 // ********* Action *********
292 // The current directory where Soong is being executed.
293 dir string
294
295 // The current prefix string to be pre-appended to the target.
296 prefix string
297
298 // ********* Validation *********
299 // The expected target to be invoked in ninja.
300 expectedTarget string
301 }{{
302 description: "one level directory in source tree",
303 dir: "test1",
304 prefix: "MODULES-IN-",
305 expectedTarget: "MODULES-IN-test1",
306 }, {
307 description: "multiple level directories in source tree",
308 dir: "test1/test2/test3/test4",
309 prefix: "GET-INSTALL-PATH-IN-",
310 expectedTarget: "GET-INSTALL-PATH-IN-test1-test2-test3-test4",
311 }}
312 for _, tt := range tests {
313 t.Run(tt.description, func(t *testing.T) {
314 target := convertToTarget(tt.dir, tt.prefix)
315 if target != tt.expectedTarget {
316 t.Errorf("expected %s, got %s for target", tt.expectedTarget, target)
317 }
318 })
319 }
320}
321
322func setTop(t *testing.T, dir string) func() {
323 curDir, err := os.Getwd()
324 if err != nil {
325 t.Fatalf("failed to get current directory: %v", err)
326 }
327 if err := os.Chdir(dir); err != nil {
328 t.Fatalf("failed to change directory to top dir %s: %v", dir, err)
329 }
330 return func() { os.Chdir(curDir) }
331}
332
333func createBuildFiles(t *testing.T, topDir string, buildFiles []string) {
334 for _, buildFile := range buildFiles {
335 buildFile = filepath.Join(topDir, buildFile)
336 if err := ioutil.WriteFile(buildFile, []byte{}, 0644); err != nil {
337 t.Errorf("failed to create file %s: %v", buildFile, err)
338 }
339 }
340}
341
342func createDirectories(t *testing.T, topDir string, dirs []string) {
343 for _, dir := range dirs {
344 dir = filepath.Join(topDir, dir)
345 if err := os.MkdirAll(dir, 0755); err != nil {
346 t.Errorf("failed to create %s directory: %v", dir, err)
347 }
348 }
349}
350
351func TestConfigGetTargets(t *testing.T) {
352 ctx := testContext()
353 tests := []struct {
354 // ********* Setup *********
355 // Test description.
356 description string
357
358 // Directories that exist in the source tree.
359 dirsInTrees []string
360
361 // Build files that exists in the source tree.
362 buildFiles []string
363
364 // ********* Action *********
365 // Directories passed in to soong_ui.
366 dirs []string
367
368 // Current directory that the user executed the build action command.
369 curDir string
370
371 // ********* Validation *********
372 // Expected targets from the function.
373 expectedTargets []string
374
Patrice Arruda13848222019-04-22 17:12:02 -0700375 // Expecting error from running test case.
376 errStr string
377 }{{
Dan Willemsence41e942019-07-29 23:39:30 -0700378 description: "one target dir specified",
379 dirsInTrees: []string{"0/1/2/3"},
380 buildFiles: []string{"0/1/2/3/Android.bp"},
381 dirs: []string{"1/2/3"},
382 curDir: "0",
383 expectedTargets: []string{"MODULES-IN-0-1-2-3"},
Patrice Arruda13848222019-04-22 17:12:02 -0700384 }, {
385 description: "one target dir specified, build file does not exist",
386 dirsInTrees: []string{"0/1/2/3"},
387 buildFiles: []string{},
388 dirs: []string{"1/2/3"},
389 curDir: "0",
390 errStr: "Build file not found for 0/1/2/3 directory",
391 }, {
392 description: "one target dir specified, invalid targets specified",
393 dirsInTrees: []string{"0/1/2/3"},
394 buildFiles: []string{},
395 dirs: []string{"1/2/3:t1:t2"},
396 curDir: "0",
397 errStr: "1/2/3:t1:t2 not in proper directory:target1,target2,... format (\":\" was specified more than once)",
398 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700399 description: "one target dir specified, no targets specified but has colon",
400 dirsInTrees: []string{"0/1/2/3"},
401 buildFiles: []string{"0/1/2/3/Android.bp"},
402 dirs: []string{"1/2/3:"},
403 curDir: "0",
404 expectedTargets: []string{"MODULES-IN-0-1-2-3"},
Patrice Arruda13848222019-04-22 17:12:02 -0700405 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700406 description: "one target dir specified, two targets specified",
407 dirsInTrees: []string{"0/1/2/3"},
408 buildFiles: []string{"0/1/2/3/Android.bp"},
409 dirs: []string{"1/2/3:t1,t2"},
410 curDir: "0",
411 expectedTargets: []string{"t1", "t2"},
Patrice Arruda13848222019-04-22 17:12:02 -0700412 }, {
413 description: "one target dir specified, no targets and has a comma",
414 dirsInTrees: []string{"0/1/2/3"},
415 buildFiles: []string{"0/1/2/3/Android.bp"},
416 dirs: []string{"1/2/3:,"},
417 curDir: "0",
418 errStr: "0/1/2/3 not in proper directory:target1,target2,... format",
419 }, {
420 description: "one target dir specified, improper targets defined",
421 dirsInTrees: []string{"0/1/2/3"},
422 buildFiles: []string{"0/1/2/3/Android.bp"},
423 dirs: []string{"1/2/3:,t1"},
424 curDir: "0",
425 errStr: "0/1/2/3 not in proper directory:target1,target2,... format",
426 }, {
427 description: "one target dir specified, blank target",
428 dirsInTrees: []string{"0/1/2/3"},
429 buildFiles: []string{"0/1/2/3/Android.bp"},
430 dirs: []string{"1/2/3:t1,"},
431 curDir: "0",
432 errStr: "0/1/2/3 not in proper directory:target1,target2,... format",
433 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700434 description: "one target dir specified, many targets specified",
435 dirsInTrees: []string{"0/1/2/3"},
436 buildFiles: []string{"0/1/2/3/Android.bp"},
437 dirs: []string{"1/2/3:t1,t2,t3,t4,t5,t6,t7,t8,t9,t10"},
438 curDir: "0",
439 expectedTargets: []string{"t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9", "t10"},
Patrice Arruda13848222019-04-22 17:12:02 -0700440 }, {
441 description: "one target dir specified, one target specified, build file does not exist",
442 dirsInTrees: []string{"0/1/2/3"},
443 buildFiles: []string{},
444 dirs: []string{"1/2/3:t1"},
445 curDir: "0",
Patrice Arruda9450d0b2019-07-08 11:06:46 -0700446 errStr: "Couldn't locate a build file from 0/1/2/3 directory",
Patrice Arruda13848222019-04-22 17:12:02 -0700447 }, {
448 description: "one target dir specified, one target specified, build file not in target dir",
449 dirsInTrees: []string{"0/1/2/3"},
450 buildFiles: []string{"0/1/2/Android.mk"},
451 dirs: []string{"1/2/3:t1"},
452 curDir: "0",
453 errStr: "Couldn't locate a build file from 0/1/2/3 directory",
454 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700455 description: "one target dir specified, build file not in target dir",
456 dirsInTrees: []string{"0/1/2/3"},
457 buildFiles: []string{"0/1/2/Android.mk"},
458 dirs: []string{"1/2/3"},
459 curDir: "0",
460 expectedTargets: []string{"MODULES-IN-0-1-2"},
Patrice Arruda13848222019-04-22 17:12:02 -0700461 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700462 description: "multiple targets dir specified, targets specified",
463 dirsInTrees: []string{"0/1/2/3", "0/3/4"},
464 buildFiles: []string{"0/1/2/3/Android.bp", "0/3/4/Android.mk"},
465 dirs: []string{"1/2/3:t1,t2", "3/4:t3,t4,t5"},
466 curDir: "0",
467 expectedTargets: []string{"t1", "t2", "t3", "t4", "t5"},
Patrice Arruda13848222019-04-22 17:12:02 -0700468 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700469 description: "multiple targets dir specified, one directory has targets specified",
470 dirsInTrees: []string{"0/1/2/3", "0/3/4"},
471 buildFiles: []string{"0/1/2/3/Android.bp", "0/3/4/Android.mk"},
472 dirs: []string{"1/2/3:t1,t2", "3/4"},
473 curDir: "0",
474 expectedTargets: []string{"t1", "t2", "MODULES-IN-0-3-4"},
Patrice Arruda13848222019-04-22 17:12:02 -0700475 }, {
476 description: "two dirs specified, only one dir exist",
477 dirsInTrees: []string{"0/1/2/3"},
478 buildFiles: []string{"0/1/2/3/Android.mk"},
479 dirs: []string{"1/2/3:t1", "3/4"},
480 curDir: "0",
481 errStr: "couldn't find directory 0/3/4",
482 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700483 description: "multiple targets dirs specified at root source tree",
484 dirsInTrees: []string{"0/1/2/3", "0/3/4"},
485 buildFiles: []string{"0/1/2/3/Android.bp", "0/3/4/Android.mk"},
486 dirs: []string{"0/1/2/3:t1,t2", "0/3/4"},
487 curDir: ".",
488 expectedTargets: []string{"t1", "t2", "MODULES-IN-0-3-4"},
Patrice Arruda13848222019-04-22 17:12:02 -0700489 }, {
490 description: "no directories specified",
491 dirsInTrees: []string{"0/1/2/3", "0/3/4"},
492 buildFiles: []string{"0/1/2/3/Android.bp", "0/3/4/Android.mk"},
493 dirs: []string{},
494 curDir: ".",
495 }}
496 for _, tt := range tests {
497 t.Run(tt.description, func(t *testing.T) {
498 defer logger.Recover(func(err error) {
499 if tt.errStr == "" {
500 t.Fatalf("Got unexpected error: %v", err)
501 }
502 if tt.errStr != err.Error() {
503 t.Errorf("expected %s, got %s", tt.errStr, err.Error())
504 }
505 })
506
507 // Create the root source tree.
508 topDir, err := ioutil.TempDir("", "")
509 if err != nil {
510 t.Fatalf("failed to create temp dir: %v", err)
511 }
512 defer os.RemoveAll(topDir)
513
514 createDirectories(t, topDir, tt.dirsInTrees)
515 createBuildFiles(t, topDir, tt.buildFiles)
516 r := setTop(t, topDir)
517 defer r()
518
Dan Willemsence41e942019-07-29 23:39:30 -0700519 targets := getTargetsFromDirs(ctx, tt.curDir, tt.dirs, "MODULES-IN-")
Patrice Arruda13848222019-04-22 17:12:02 -0700520 if !reflect.DeepEqual(targets, tt.expectedTargets) {
521 t.Errorf("expected %v, got %v for targets", tt.expectedTargets, targets)
522 }
Patrice Arruda13848222019-04-22 17:12:02 -0700523
524 // If the execution reached here and there was an expected error code, the unit test case failed.
525 if tt.errStr != "" {
526 t.Errorf("expecting error %s", tt.errStr)
527 }
528 })
529 }
530}
531
532func TestConfigFindBuildFile(t *testing.T) {
533 ctx := testContext()
534
535 tests := []struct {
536 // ********* Setup *********
537 // Test description.
538 description string
539
540 // Array of build files to create in dir.
541 buildFiles []string
542
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700543 // Directories that exist in the source tree.
544 dirsInTrees []string
545
Patrice Arruda13848222019-04-22 17:12:02 -0700546 // ********* Action *********
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700547 // The base directory is where findBuildFile is invoked.
Patrice Arruda13848222019-04-22 17:12:02 -0700548 dir string
549
550 // ********* Validation *********
551 // Expected build file path to find.
552 expectedBuildFile string
553 }{{
554 description: "build file exists at leaf directory",
555 buildFiles: []string{"1/2/3/Android.bp"},
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700556 dirsInTrees: []string{"1/2/3"},
Patrice Arruda13848222019-04-22 17:12:02 -0700557 dir: "1/2/3",
558 expectedBuildFile: "1/2/3/Android.mk",
559 }, {
560 description: "build file exists in all directory paths",
561 buildFiles: []string{"1/Android.mk", "1/2/Android.mk", "1/2/3/Android.mk"},
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700562 dirsInTrees: []string{"1/2/3"},
Patrice Arruda13848222019-04-22 17:12:02 -0700563 dir: "1/2/3",
564 expectedBuildFile: "1/2/3/Android.mk",
565 }, {
566 description: "build file does not exist in all directory paths",
567 buildFiles: []string{},
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700568 dirsInTrees: []string{"1/2/3"},
Patrice Arruda13848222019-04-22 17:12:02 -0700569 dir: "1/2/3",
570 expectedBuildFile: "",
571 }, {
572 description: "build file exists only at top directory",
573 buildFiles: []string{"Android.bp"},
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700574 dirsInTrees: []string{"1/2/3"},
Patrice Arruda13848222019-04-22 17:12:02 -0700575 dir: "1/2/3",
576 expectedBuildFile: "",
577 }, {
578 description: "build file exist in a subdirectory",
579 buildFiles: []string{"1/2/Android.bp"},
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700580 dirsInTrees: []string{"1/2/3"},
Patrice Arruda13848222019-04-22 17:12:02 -0700581 dir: "1/2/3",
582 expectedBuildFile: "1/2/Android.mk",
583 }, {
584 description: "build file exists in a subdirectory",
585 buildFiles: []string{"1/Android.mk"},
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700586 dirsInTrees: []string{"1/2/3"},
Patrice Arruda13848222019-04-22 17:12:02 -0700587 dir: "1/2/3",
588 expectedBuildFile: "1/Android.mk",
589 }, {
590 description: "top directory",
591 buildFiles: []string{"Android.bp"},
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700592 dirsInTrees: []string{},
Patrice Arruda13848222019-04-22 17:12:02 -0700593 dir: ".",
594 expectedBuildFile: "",
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700595 }, {
596 description: "build file exists in subdirectory",
597 buildFiles: []string{"1/2/3/Android.bp", "1/2/4/Android.bp"},
598 dirsInTrees: []string{"1/2/3", "1/2/4"},
599 dir: "1/2",
600 expectedBuildFile: "1/2/Android.mk",
601 }, {
602 description: "build file exists in parent subdirectory",
603 buildFiles: []string{"1/5/Android.bp"},
604 dirsInTrees: []string{"1/2/3", "1/2/4", "1/5"},
605 dir: "1/2",
606 expectedBuildFile: "1/Android.mk",
607 }, {
608 description: "build file exists in deep parent's subdirectory.",
609 buildFiles: []string{"1/5/6/Android.bp"},
610 dirsInTrees: []string{"1/2/3", "1/2/4", "1/5/6", "1/5/7"},
611 dir: "1/2",
612 expectedBuildFile: "1/Android.mk",
Patrice Arruda13848222019-04-22 17:12:02 -0700613 }}
614
615 for _, tt := range tests {
616 t.Run(tt.description, func(t *testing.T) {
617 defer logger.Recover(func(err error) {
618 t.Fatalf("Got unexpected error: %v", err)
619 })
620
621 topDir, err := ioutil.TempDir("", "")
622 if err != nil {
623 t.Fatalf("failed to create temp dir: %v", err)
624 }
625 defer os.RemoveAll(topDir)
626
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700627 createDirectories(t, topDir, tt.dirsInTrees)
Patrice Arruda13848222019-04-22 17:12:02 -0700628 createBuildFiles(t, topDir, tt.buildFiles)
629
630 curDir, err := os.Getwd()
631 if err != nil {
632 t.Fatalf("Could not get working directory: %v", err)
633 }
634 defer func() { os.Chdir(curDir) }()
635 if err := os.Chdir(topDir); err != nil {
636 t.Fatalf("Could not change top dir to %s: %v", topDir, err)
637 }
638
639 buildFile := findBuildFile(ctx, tt.dir)
640 if buildFile != tt.expectedBuildFile {
641 t.Errorf("expected %q, got %q for build file", tt.expectedBuildFile, buildFile)
642 }
643 })
644 }
645}
646
647func TestConfigSplitArgs(t *testing.T) {
648 tests := []struct {
649 // ********* Setup *********
650 // Test description.
651 description string
652
653 // ********* Action *********
654 // Arguments passed in to soong_ui.
655 args []string
656
657 // ********* Validation *********
658 // Expected newArgs list after extracting the directories.
659 expectedNewArgs []string
660
661 // Expected directories
662 expectedDirs []string
663 }{{
664 description: "flags but no directories specified",
665 args: []string{"showcommands", "-j", "-k"},
666 expectedNewArgs: []string{"showcommands", "-j", "-k"},
667 expectedDirs: []string{},
668 }, {
669 description: "flags and one directory specified",
670 args: []string{"snod", "-j", "dir:target1,target2"},
671 expectedNewArgs: []string{"snod", "-j"},
672 expectedDirs: []string{"dir:target1,target2"},
673 }, {
674 description: "flags and directories specified",
675 args: []string{"dist", "-k", "dir1", "dir2:target1,target2"},
676 expectedNewArgs: []string{"dist", "-k"},
677 expectedDirs: []string{"dir1", "dir2:target1,target2"},
678 }, {
679 description: "only directories specified",
680 args: []string{"dir1", "dir2", "dir3:target1,target2"},
681 expectedNewArgs: []string{},
682 expectedDirs: []string{"dir1", "dir2", "dir3:target1,target2"},
683 }}
684 for _, tt := range tests {
685 t.Run(tt.description, func(t *testing.T) {
686 args, dirs := splitArgs(tt.args)
687 if !reflect.DeepEqual(tt.expectedNewArgs, args) {
688 t.Errorf("expected %v, got %v for arguments", tt.expectedNewArgs, args)
689 }
690 if !reflect.DeepEqual(tt.expectedDirs, dirs) {
691 t.Errorf("expected %v, got %v for directories", tt.expectedDirs, dirs)
692 }
693 })
694 }
695}
696
697type envVar struct {
698 name string
699 value string
700}
701
702type buildActionTestCase struct {
703 // ********* Setup *********
704 // Test description.
705 description string
706
707 // Directories that exist in the source tree.
708 dirsInTrees []string
709
710 // Build files that exists in the source tree.
711 buildFiles []string
712
Patrice Arrudababa9a92019-07-03 10:47:34 -0700713 // Create root symlink that points to topDir.
714 rootSymlink bool
715
Patrice Arruda13848222019-04-22 17:12:02 -0700716 // ********* Action *********
717 // Arguments passed in to soong_ui.
718 args []string
719
720 // Directory where the build action was invoked.
721 curDir string
722
723 // WITH_TIDY_ONLY environment variable specified.
724 tidyOnly string
725
726 // ********* Validation *********
727 // Expected arguments to be in Config instance.
728 expectedArgs []string
729
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700730 // Expecting error from running test case.
731 expectedErrStr string
Patrice Arruda13848222019-04-22 17:12:02 -0700732}
733
Dan Willemsence41e942019-07-29 23:39:30 -0700734func testGetConfigArgs(t *testing.T, tt buildActionTestCase, action BuildAction) {
Patrice Arruda13848222019-04-22 17:12:02 -0700735 ctx := testContext()
736
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700737 defer logger.Recover(func(err error) {
738 if tt.expectedErrStr == "" {
739 t.Fatalf("Got unexpected error: %v", err)
740 }
741 if tt.expectedErrStr != err.Error() {
742 t.Errorf("expected %s, got %s", tt.expectedErrStr, err.Error())
743 }
744 })
745
Patrice Arruda13848222019-04-22 17:12:02 -0700746 // Environment variables to set it to blank on every test case run.
747 resetEnvVars := []string{
Patrice Arruda13848222019-04-22 17:12:02 -0700748 "WITH_TIDY_ONLY",
749 }
750
751 for _, name := range resetEnvVars {
752 if err := os.Unsetenv(name); err != nil {
753 t.Fatalf("failed to unset environment variable %s: %v", name, err)
754 }
755 }
756 if tt.tidyOnly != "" {
757 if err := os.Setenv("WITH_TIDY_ONLY", tt.tidyOnly); err != nil {
758 t.Errorf("failed to set WITH_TIDY_ONLY to %s: %v", tt.tidyOnly, err)
759 }
760 }
761
762 // Create the root source tree.
763 topDir, err := ioutil.TempDir("", "")
764 if err != nil {
765 t.Fatalf("failed to create temp dir: %v", err)
766 }
767 defer os.RemoveAll(topDir)
768
769 createDirectories(t, topDir, tt.dirsInTrees)
770 createBuildFiles(t, topDir, tt.buildFiles)
771
Patrice Arrudababa9a92019-07-03 10:47:34 -0700772 if tt.rootSymlink {
773 // Create a secondary root source tree which points to the true root source tree.
774 symlinkTopDir, err := ioutil.TempDir("", "")
775 if err != nil {
776 t.Fatalf("failed to create symlink temp dir: %v", err)
777 }
778 defer os.RemoveAll(symlinkTopDir)
779
780 symlinkTopDir = filepath.Join(symlinkTopDir, "root")
781 err = os.Symlink(topDir, symlinkTopDir)
782 if err != nil {
783 t.Fatalf("failed to create symlink: %v", err)
784 }
785 topDir = symlinkTopDir
786 }
787
Patrice Arruda13848222019-04-22 17:12:02 -0700788 r := setTop(t, topDir)
789 defer r()
790
791 // The next block is to create the root build file.
792 rootBuildFileDir := filepath.Dir(srcDirFileCheck)
793 if err := os.MkdirAll(rootBuildFileDir, 0755); err != nil {
794 t.Fatalf("Failed to create %s directory: %v", rootBuildFileDir, err)
795 }
796
797 if err := ioutil.WriteFile(srcDirFileCheck, []byte{}, 0644); err != nil {
798 t.Fatalf("failed to create %s file: %v", srcDirFileCheck, err)
799 }
800
Dan Willemsence41e942019-07-29 23:39:30 -0700801 args := getConfigArgs(action, tt.curDir, ctx, tt.args)
Patrice Arruda13848222019-04-22 17:12:02 -0700802 if !reflect.DeepEqual(tt.expectedArgs, args) {
803 t.Fatalf("expected %v, got %v for config arguments", tt.expectedArgs, args)
804 }
805
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700806 // If the execution reached here and there was an expected error code, the unit test case failed.
807 if tt.expectedErrStr != "" {
808 t.Errorf("expecting error %s", tt.expectedErrStr)
809 }
Patrice Arruda13848222019-04-22 17:12:02 -0700810}
811
Patrice Arruda39282062019-06-20 16:35:12 -0700812func TestGetConfigArgsBuildModules(t *testing.T) {
813 tests := []buildActionTestCase{{
Dan Willemsence41e942019-07-29 23:39:30 -0700814 description: "normal execution from the root source tree directory",
815 dirsInTrees: []string{"0/1/2", "0/2", "0/3"},
816 buildFiles: []string{"0/1/2/Android.mk", "0/2/Android.bp", "0/3/Android.mk"},
817 args: []string{"-j", "fake_module", "fake_module2"},
818 curDir: ".",
819 tidyOnly: "",
820 expectedArgs: []string{"-j", "fake_module", "fake_module2"},
Patrice Arruda39282062019-06-20 16:35:12 -0700821 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700822 description: "normal execution in deep directory",
823 dirsInTrees: []string{"0/1/2", "0/2", "0/3", "1/2/3/4/5/6/7/8/9/1/2/3/4/5/6"},
824 buildFiles: []string{"0/1/2/Android.mk", "0/2/Android.bp", "1/2/3/4/5/6/7/8/9/1/2/3/4/5/6/Android.mk"},
825 args: []string{"-j", "fake_module", "fake_module2", "-k"},
826 curDir: "1/2/3/4/5/6/7/8/9",
827 tidyOnly: "",
828 expectedArgs: []string{"-j", "fake_module", "fake_module2", "-k"},
Patrice Arruda39282062019-06-20 16:35:12 -0700829 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700830 description: "normal execution in deep directory, no targets",
831 dirsInTrees: []string{"0/1/2", "0/2", "0/3", "1/2/3/4/5/6/7/8/9/1/2/3/4/5/6"},
832 buildFiles: []string{"0/1/2/Android.mk", "0/2/Android.bp", "1/2/3/4/5/6/7/8/9/1/2/3/4/5/6/Android.mk"},
833 args: []string{"-j", "-k"},
834 curDir: "1/2/3/4/5/6/7/8/9",
835 tidyOnly: "",
836 expectedArgs: []string{"-j", "-k"},
Patrice Arruda39282062019-06-20 16:35:12 -0700837 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700838 description: "normal execution in root source tree, no args",
839 dirsInTrees: []string{"0/1/2", "0/2", "0/3"},
840 buildFiles: []string{"0/1/2/Android.mk", "0/2/Android.bp"},
841 args: []string{},
842 curDir: "0/2",
843 tidyOnly: "",
844 expectedArgs: []string{},
Patrice Arrudababa9a92019-07-03 10:47:34 -0700845 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700846 description: "normal execution in symlink root source tree, no args",
847 dirsInTrees: []string{"0/1/2", "0/2", "0/3"},
848 buildFiles: []string{"0/1/2/Android.mk", "0/2/Android.bp"},
849 rootSymlink: true,
850 args: []string{},
851 curDir: "0/2",
852 tidyOnly: "",
853 expectedArgs: []string{},
Patrice Arruda39282062019-06-20 16:35:12 -0700854 }}
855 for _, tt := range tests {
856 t.Run("build action BUILD_MODULES with dependencies, "+tt.description, func(t *testing.T) {
Dan Willemsence41e942019-07-29 23:39:30 -0700857 testGetConfigArgs(t, tt, BUILD_MODULES)
Patrice Arruda13848222019-04-22 17:12:02 -0700858 })
859 }
860}
861
862func TestGetConfigArgsBuildModulesInDirectory(t *testing.T) {
863 tests := []buildActionTestCase{{
Dan Willemsence41e942019-07-29 23:39:30 -0700864 description: "normal execution in a directory",
865 dirsInTrees: []string{"0/1/2"},
866 buildFiles: []string{"0/1/2/Android.mk"},
867 args: []string{"fake-module"},
868 curDir: "0/1/2",
869 tidyOnly: "",
870 expectedArgs: []string{"fake-module", "MODULES-IN-0-1-2"},
Patrice Arruda13848222019-04-22 17:12:02 -0700871 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700872 description: "build file in parent directory",
873 dirsInTrees: []string{"0/1/2"},
874 buildFiles: []string{"0/1/Android.mk"},
875 args: []string{},
876 curDir: "0/1/2",
877 tidyOnly: "",
878 expectedArgs: []string{"MODULES-IN-0-1"},
Patrice Arruda13848222019-04-22 17:12:02 -0700879 },
880 {
Dan Willemsence41e942019-07-29 23:39:30 -0700881 description: "build file in parent directory, multiple module names passed in",
882 dirsInTrees: []string{"0/1/2"},
883 buildFiles: []string{"0/1/Android.mk"},
884 args: []string{"fake-module1", "fake-module2", "fake-module3"},
885 curDir: "0/1/2",
886 tidyOnly: "",
887 expectedArgs: []string{"fake-module1", "fake-module2", "fake-module3", "MODULES-IN-0-1"},
Patrice Arruda13848222019-04-22 17:12:02 -0700888 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700889 description: "build file in 2nd level parent directory",
890 dirsInTrees: []string{"0/1/2"},
891 buildFiles: []string{"0/Android.bp"},
892 args: []string{},
893 curDir: "0/1/2",
894 tidyOnly: "",
895 expectedArgs: []string{"MODULES-IN-0"},
Patrice Arruda13848222019-04-22 17:12:02 -0700896 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700897 description: "build action executed at root directory",
898 dirsInTrees: []string{},
899 buildFiles: []string{},
900 rootSymlink: false,
901 args: []string{},
902 curDir: ".",
903 tidyOnly: "",
904 expectedArgs: []string{},
Patrice Arrudababa9a92019-07-03 10:47:34 -0700905 }, {
LaMont Jones52a72432023-03-09 18:19:35 +0000906 description: "multitree build action executed at root directory",
907 dirsInTrees: []string{},
908 buildFiles: []string{},
909 rootSymlink: false,
910 args: []string{"--multitree-build"},
911 curDir: ".",
912 tidyOnly: "",
913 expectedArgs: []string{"--multitree-build"},
914 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700915 description: "build action executed at root directory in symlink",
916 dirsInTrees: []string{},
917 buildFiles: []string{},
918 rootSymlink: true,
919 args: []string{},
920 curDir: ".",
921 tidyOnly: "",
922 expectedArgs: []string{},
Patrice Arruda13848222019-04-22 17:12:02 -0700923 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700924 description: "build file not found",
925 dirsInTrees: []string{"0/1/2"},
926 buildFiles: []string{},
927 args: []string{},
928 curDir: "0/1/2",
929 tidyOnly: "",
930 expectedArgs: []string{"MODULES-IN-0-1-2"},
931 expectedErrStr: "Build file not found for 0/1/2 directory",
Patrice Arruda13848222019-04-22 17:12:02 -0700932 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700933 description: "GET-INSTALL-PATH specified,",
934 dirsInTrees: []string{"0/1/2"},
935 buildFiles: []string{"0/1/Android.mk"},
936 args: []string{"GET-INSTALL-PATH", "-j", "-k", "GET-INSTALL-PATH"},
937 curDir: "0/1/2",
938 tidyOnly: "",
939 expectedArgs: []string{"-j", "-k", "GET-INSTALL-PATH-IN-0-1"},
Patrice Arruda13848222019-04-22 17:12:02 -0700940 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700941 description: "tidy only environment variable specified,",
942 dirsInTrees: []string{"0/1/2"},
943 buildFiles: []string{"0/1/Android.mk"},
944 args: []string{"GET-INSTALL-PATH"},
945 curDir: "0/1/2",
946 tidyOnly: "true",
947 expectedArgs: []string{"tidy_only"},
Patrice Arruda13848222019-04-22 17:12:02 -0700948 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700949 description: "normal execution in root directory with args",
950 dirsInTrees: []string{},
951 buildFiles: []string{},
952 args: []string{"-j", "-k", "fake_module"},
953 curDir: "",
954 tidyOnly: "",
955 expectedArgs: []string{"-j", "-k", "fake_module"},
Patrice Arruda13848222019-04-22 17:12:02 -0700956 }}
957 for _, tt := range tests {
958 t.Run("build action BUILD_MODULES_IN_DIR, "+tt.description, func(t *testing.T) {
Dan Willemsence41e942019-07-29 23:39:30 -0700959 testGetConfigArgs(t, tt, BUILD_MODULES_IN_A_DIRECTORY)
Patrice Arruda13848222019-04-22 17:12:02 -0700960 })
961 }
962}
963
964func TestGetConfigArgsBuildModulesInDirectories(t *testing.T) {
965 tests := []buildActionTestCase{{
966 description: "normal execution in a directory",
967 dirsInTrees: []string{"0/1/2/3.1", "0/1/2/3.2", "0/1/2/3.3"},
968 buildFiles: []string{"0/1/2/3.1/Android.bp", "0/1/2/3.2/Android.bp", "0/1/2/3.3/Android.bp"},
969 args: []string{"3.1/", "3.2/", "3.3/"},
970 curDir: "0/1/2",
971 tidyOnly: "",
972 expectedArgs: []string{"MODULES-IN-0-1-2-3.1", "MODULES-IN-0-1-2-3.2", "MODULES-IN-0-1-2-3.3"},
Patrice Arruda13848222019-04-22 17:12:02 -0700973 }, {
974 description: "GET-INSTALL-PATH specified",
975 dirsInTrees: []string{"0/1/2/3.1", "0/1/2/3.2", "0/1/3"},
976 buildFiles: []string{"0/1/2/3.1/Android.bp", "0/1/2/3.2/Android.bp", "0/1/Android.bp"},
977 args: []string{"GET-INSTALL-PATH", "2/3.1/", "2/3.2", "3"},
978 curDir: "0/1",
979 tidyOnly: "",
980 expectedArgs: []string{"GET-INSTALL-PATH-IN-0-1-2-3.1", "GET-INSTALL-PATH-IN-0-1-2-3.2", "GET-INSTALL-PATH-IN-0-1"},
Patrice Arruda13848222019-04-22 17:12:02 -0700981 }, {
982 description: "tidy only environment variable specified",
983 dirsInTrees: []string{"0/1/2/3.1", "0/1/2/3.2", "0/1/2/3.3"},
984 buildFiles: []string{"0/1/2/3.1/Android.bp", "0/1/2/3.2/Android.bp", "0/1/2/3.3/Android.bp"},
985 args: []string{"GET-INSTALL-PATH", "3.1/", "3.2/", "3.3"},
986 curDir: "0/1/2",
987 tidyOnly: "1",
988 expectedArgs: []string{"tidy_only"},
Patrice Arruda13848222019-04-22 17:12:02 -0700989 }, {
990 description: "normal execution from top dir directory",
991 dirsInTrees: []string{"0/1/2/3.1", "0/1/2/3.2", "0/1/3", "0/2"},
992 buildFiles: []string{"0/1/2/3.1/Android.bp", "0/1/2/3.2/Android.bp", "0/1/3/Android.bp", "0/2/Android.bp"},
Patrice Arrudababa9a92019-07-03 10:47:34 -0700993 rootSymlink: false,
994 args: []string{"0/1/2/3.1", "0/1/2/3.2", "0/1/3", "0/2"},
995 curDir: ".",
996 tidyOnly: "",
997 expectedArgs: []string{"MODULES-IN-0-1-2-3.1", "MODULES-IN-0-1-2-3.2", "MODULES-IN-0-1-3", "MODULES-IN-0-2"},
Patrice Arrudababa9a92019-07-03 10:47:34 -0700998 }, {
999 description: "normal execution from top dir directory in symlink",
1000 dirsInTrees: []string{"0/1/2/3.1", "0/1/2/3.2", "0/1/3", "0/2"},
1001 buildFiles: []string{"0/1/2/3.1/Android.bp", "0/1/2/3.2/Android.bp", "0/1/3/Android.bp", "0/2/Android.bp"},
1002 rootSymlink: true,
Patrice Arruda13848222019-04-22 17:12:02 -07001003 args: []string{"0/1/2/3.1", "0/1/2/3.2", "0/1/3", "0/2"},
1004 curDir: ".",
1005 tidyOnly: "",
1006 expectedArgs: []string{"MODULES-IN-0-1-2-3.1", "MODULES-IN-0-1-2-3.2", "MODULES-IN-0-1-3", "MODULES-IN-0-2"},
Patrice Arruda13848222019-04-22 17:12:02 -07001007 }}
1008 for _, tt := range tests {
1009 t.Run("build action BUILD_MODULES_IN_DIRS, "+tt.description, func(t *testing.T) {
Dan Willemsence41e942019-07-29 23:39:30 -07001010 testGetConfigArgs(t, tt, BUILD_MODULES_IN_DIRECTORIES)
Patrice Arruda13848222019-04-22 17:12:02 -07001011 })
1012 }
1013}
Liz Kammerca9cb2e2021-07-14 15:29:57 -04001014
1015func TestBuildConfig(t *testing.T) {
1016 tests := []struct {
1017 name string
1018 environ Environment
Yu Liue737a992021-10-04 13:21:41 -07001019 arguments []string
Liz Kammerca9cb2e2021-07-14 15:29:57 -04001020 useBazel bool
Chris Parsonsef615e52022-08-18 22:04:11 -04001021 bazelDevMode bool
1022 bazelProdMode bool
MarkDacekb78465d2022-10-18 20:10:16 +00001023 bazelStagingMode bool
Liz Kammerca9cb2e2021-07-14 15:29:57 -04001024 expectedBuildConfig *smpb.BuildConfig
1025 }{
1026 {
1027 name: "none set",
1028 environ: Environment{},
1029 expectedBuildConfig: &smpb.BuildConfig{
Romain Jobredeaux0a7529b2022-10-26 12:56:41 -04001030 ForceUseGoma: proto.Bool(false),
1031 UseGoma: proto.Bool(false),
1032 UseRbe: proto.Bool(false),
1033 BazelMixedBuild: proto.Bool(false),
1034 ForceDisableBazelMixedBuild: proto.Bool(false),
Liz Kammerca9cb2e2021-07-14 15:29:57 -04001035 },
1036 },
1037 {
1038 name: "force use goma",
1039 environ: Environment{"FORCE_USE_GOMA=1"},
1040 expectedBuildConfig: &smpb.BuildConfig{
Romain Jobredeaux0a7529b2022-10-26 12:56:41 -04001041 ForceUseGoma: proto.Bool(true),
1042 UseGoma: proto.Bool(false),
1043 UseRbe: proto.Bool(false),
1044 BazelMixedBuild: proto.Bool(false),
1045 ForceDisableBazelMixedBuild: proto.Bool(false),
Liz Kammerca9cb2e2021-07-14 15:29:57 -04001046 },
1047 },
1048 {
1049 name: "use goma",
1050 environ: Environment{"USE_GOMA=1"},
1051 expectedBuildConfig: &smpb.BuildConfig{
Romain Jobredeaux0a7529b2022-10-26 12:56:41 -04001052 ForceUseGoma: proto.Bool(false),
1053 UseGoma: proto.Bool(true),
1054 UseRbe: proto.Bool(false),
1055 BazelMixedBuild: proto.Bool(false),
1056 ForceDisableBazelMixedBuild: proto.Bool(false),
Liz Kammerca9cb2e2021-07-14 15:29:57 -04001057 },
1058 },
1059 {
1060 name: "use rbe",
1061 environ: Environment{"USE_RBE=1"},
1062 expectedBuildConfig: &smpb.BuildConfig{
Romain Jobredeaux0a7529b2022-10-26 12:56:41 -04001063 ForceUseGoma: proto.Bool(false),
1064 UseGoma: proto.Bool(false),
1065 UseRbe: proto.Bool(true),
1066 BazelMixedBuild: proto.Bool(false),
1067 ForceDisableBazelMixedBuild: proto.Bool(false),
1068 },
1069 },
1070 {
1071 name: "disable mixed builds",
1072 environ: Environment{"BUILD_BROKEN_DISABLE_BAZEL=1"},
1073 expectedBuildConfig: &smpb.BuildConfig{
1074 ForceUseGoma: proto.Bool(false),
1075 UseGoma: proto.Bool(false),
1076 UseRbe: proto.Bool(false),
1077 BazelMixedBuild: proto.Bool(false),
1078 ForceDisableBazelMixedBuild: proto.Bool(true),
Liz Kammerca9cb2e2021-07-14 15:29:57 -04001079 },
1080 },
1081 {
1082 name: "use bazel as ninja",
1083 environ: Environment{},
1084 useBazel: true,
1085 expectedBuildConfig: &smpb.BuildConfig{
Romain Jobredeaux0a7529b2022-10-26 12:56:41 -04001086 ForceUseGoma: proto.Bool(false),
1087 UseGoma: proto.Bool(false),
1088 UseRbe: proto.Bool(false),
1089 BazelMixedBuild: proto.Bool(false),
1090 ForceDisableBazelMixedBuild: proto.Bool(false),
Liz Kammerca9cb2e2021-07-14 15:29:57 -04001091 },
1092 },
1093 {
Chris Parsonsef615e52022-08-18 22:04:11 -04001094 name: "bazel mixed build from dev mode",
1095 environ: Environment{},
1096 bazelDevMode: true,
1097 expectedBuildConfig: &smpb.BuildConfig{
Romain Jobredeaux0a7529b2022-10-26 12:56:41 -04001098 ForceUseGoma: proto.Bool(false),
1099 UseGoma: proto.Bool(false),
1100 UseRbe: proto.Bool(false),
1101 BazelMixedBuild: proto.Bool(true),
1102 ForceDisableBazelMixedBuild: proto.Bool(false),
Chris Parsonsef615e52022-08-18 22:04:11 -04001103 },
1104 },
1105 {
1106 name: "bazel mixed build from prod mode",
1107 environ: Environment{},
1108 bazelProdMode: true,
1109 expectedBuildConfig: &smpb.BuildConfig{
Romain Jobredeaux0a7529b2022-10-26 12:56:41 -04001110 ForceUseGoma: proto.Bool(false),
1111 UseGoma: proto.Bool(false),
1112 UseRbe: proto.Bool(false),
1113 BazelMixedBuild: proto.Bool(true),
1114 ForceDisableBazelMixedBuild: proto.Bool(false),
Chris Parsonsef615e52022-08-18 22:04:11 -04001115 },
1116 },
1117 {
MarkDacekb78465d2022-10-18 20:10:16 +00001118 name: "bazel mixed build from staging mode",
1119 environ: Environment{},
1120 bazelStagingMode: true,
1121 expectedBuildConfig: &smpb.BuildConfig{
Romain Jobredeaux0a7529b2022-10-26 12:56:41 -04001122 ForceUseGoma: proto.Bool(false),
1123 UseGoma: proto.Bool(false),
1124 UseRbe: proto.Bool(false),
1125 BazelMixedBuild: proto.Bool(true),
1126 ForceDisableBazelMixedBuild: proto.Bool(false),
MarkDacekb78465d2022-10-18 20:10:16 +00001127 },
1128 },
1129 {
Yu Liue737a992021-10-04 13:21:41 -07001130 name: "specified targets",
1131 environ: Environment{},
1132 useBazel: true,
1133 arguments: []string{"droid", "dist"},
1134 expectedBuildConfig: &smpb.BuildConfig{
Romain Jobredeaux0a7529b2022-10-26 12:56:41 -04001135 ForceUseGoma: proto.Bool(false),
1136 UseGoma: proto.Bool(false),
1137 UseRbe: proto.Bool(false),
1138 BazelMixedBuild: proto.Bool(false),
1139 Targets: []string{"droid", "dist"},
1140 ForceDisableBazelMixedBuild: proto.Bool(false),
Yu Liue737a992021-10-04 13:21:41 -07001141 },
1142 },
1143 {
Liz Kammerca9cb2e2021-07-14 15:29:57 -04001144 name: "all set",
1145 environ: Environment{
1146 "FORCE_USE_GOMA=1",
1147 "USE_GOMA=1",
1148 "USE_RBE=1",
Romain Jobredeaux0a7529b2022-10-26 12:56:41 -04001149 "BUILD_BROKEN_DISABLE_BAZEL=1",
Liz Kammerca9cb2e2021-07-14 15:29:57 -04001150 },
Chris Parsonsef615e52022-08-18 22:04:11 -04001151 useBazel: true,
1152 bazelDevMode: true,
Liz Kammerca9cb2e2021-07-14 15:29:57 -04001153 expectedBuildConfig: &smpb.BuildConfig{
Romain Jobredeaux0a7529b2022-10-26 12:56:41 -04001154 ForceUseGoma: proto.Bool(true),
1155 UseGoma: proto.Bool(true),
1156 UseRbe: proto.Bool(true),
1157 BazelMixedBuild: proto.Bool(true),
1158 ForceDisableBazelMixedBuild: proto.Bool(true),
Liz Kammerca9cb2e2021-07-14 15:29:57 -04001159 },
1160 },
1161 }
1162
Chris Parsonsef615e52022-08-18 22:04:11 -04001163 ctx := testContext()
Liz Kammerca9cb2e2021-07-14 15:29:57 -04001164 for _, tc := range tests {
1165 t.Run(tc.name, func(t *testing.T) {
1166 c := &configImpl{
MarkDacekb78465d2022-10-18 20:10:16 +00001167 environ: &tc.environ,
1168 bazelDevMode: tc.bazelDevMode,
1169 bazelProdMode: tc.bazelProdMode,
1170 bazelStagingMode: tc.bazelStagingMode,
1171 arguments: tc.arguments,
Liz Kammerca9cb2e2021-07-14 15:29:57 -04001172 }
1173 config := Config{c}
Chris Parsonsef615e52022-08-18 22:04:11 -04001174 checkBazelMode(ctx, config)
Liz Kammerca9cb2e2021-07-14 15:29:57 -04001175 actualBuildConfig := buildConfig(config)
1176 if expected := tc.expectedBuildConfig; !proto.Equal(expected, actualBuildConfig) {
Chris Parsonsef615e52022-08-18 22:04:11 -04001177 t.Errorf("Build config mismatch.\n"+
1178 "Expected build config: %#v\n"+
1179 "Actual build config: %#v", prototext.Format(expected), prototext.Format(actualBuildConfig))
Liz Kammerca9cb2e2021-07-14 15:29:57 -04001180 }
1181 })
1182 }
1183}
Yu Liu6e13b402021-07-27 14:29:06 -07001184
1185func TestGetMetricsUploaderApp(t *testing.T) {
1186
1187 metricsUploaderDir := "metrics_uploader_dir"
1188 metricsUploaderBinary := "metrics_uploader_binary"
1189 metricsUploaderPath := filepath.Join(metricsUploaderDir, metricsUploaderBinary)
1190 tests := []struct {
1191 description string
1192 environ Environment
1193 createFiles bool
1194 expected string
1195 }{{
1196 description: "Uploader binary exist",
1197 environ: Environment{"METRICS_UPLOADER=" + metricsUploaderPath},
1198 createFiles: true,
1199 expected: metricsUploaderPath,
1200 }, {
1201 description: "Uploader binary not exist",
1202 environ: Environment{"METRICS_UPLOADER=" + metricsUploaderPath},
1203 createFiles: false,
1204 expected: "",
1205 }, {
1206 description: "Uploader binary variable not set",
1207 createFiles: true,
1208 expected: "",
1209 }}
1210
1211 for _, tt := range tests {
1212 t.Run(tt.description, func(t *testing.T) {
1213 defer logger.Recover(func(err error) {
1214 t.Fatalf("got unexpected error: %v", err)
1215 })
1216
1217 // Create the root source tree.
1218 topDir, err := ioutil.TempDir("", "")
1219 if err != nil {
1220 t.Fatalf("failed to create temp dir: %v", err)
1221 }
1222 defer os.RemoveAll(topDir)
1223
1224 expected := tt.expected
1225 if len(expected) > 0 {
1226 expected = filepath.Join(topDir, expected)
1227 }
1228
1229 if tt.createFiles {
1230 if err := os.MkdirAll(filepath.Join(topDir, metricsUploaderDir), 0755); err != nil {
1231 t.Errorf("failed to create %s directory: %v", metricsUploaderDir, err)
1232 }
1233 if err := ioutil.WriteFile(filepath.Join(topDir, metricsUploaderPath), []byte{}, 0644); err != nil {
1234 t.Errorf("failed to create file %s: %v", expected, err)
1235 }
1236 }
1237
1238 actual := GetMetricsUploader(topDir, &tt.environ)
1239
1240 if actual != expected {
1241 t.Errorf("expecting: %s, actual: %s", expected, actual)
1242 }
1243 })
1244 }
1245}