blob: 968544be7426be1fadaef6b9229b09c2a1c47bfd [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
93 c := &configImpl{
94 parallel: -1,
95 keepGoing: -1,
96 }
97 c.parseArgs(ctx, tc.args)
98
99 if c.parallel != tc.parallel {
100 t.Errorf("for %q, parallel:\nwant: %d\n got: %d\n",
101 strings.Join(tc.args, " "),
102 tc.parallel, c.parallel)
103 }
104 if c.keepGoing != tc.keepGoing {
105 t.Errorf("for %q, keep going:\nwant: %d\n got: %d\n",
106 strings.Join(tc.args, " "),
107 tc.keepGoing, c.keepGoing)
108 }
109 if !reflect.DeepEqual(c.arguments, tc.remaining) {
110 t.Errorf("for %q, remaining arguments:\nwant: %q\n got: %q\n",
111 strings.Join(tc.args, " "),
112 tc.remaining, c.arguments)
113 }
114 })
115 }
116}
Dan Willemsen091525e2017-07-11 14:17:50 -0700117
118func TestConfigParseArgsVars(t *testing.T) {
119 ctx := testContext()
120
121 testCases := []struct {
122 env []string
123 args []string
124
125 expectedEnv []string
126 remaining []string
127 }{
128 {},
129 {
130 env: []string{"A=bc"},
131
132 expectedEnv: []string{"A=bc"},
133 },
134 {
135 args: []string{"abc"},
136
137 remaining: []string{"abc"},
138 },
139
140 {
141 args: []string{"A=bc"},
142
143 expectedEnv: []string{"A=bc"},
144 },
145 {
146 env: []string{"A=a"},
147 args: []string{"A=bc"},
148
149 expectedEnv: []string{"A=bc"},
150 },
151
152 {
153 env: []string{"A=a"},
154 args: []string{"A=", "=b"},
155
156 expectedEnv: []string{"A="},
157 remaining: []string{"=b"},
158 },
159 }
160
161 for _, tc := range testCases {
162 t.Run(strings.Join(tc.args, " "), func(t *testing.T) {
163 defer logger.Recover(func(err error) {
164 t.Fatal(err)
165 })
166
167 e := Environment(tc.env)
168 c := &configImpl{
169 environ: &e,
170 }
171 c.parseArgs(ctx, tc.args)
172
173 if !reflect.DeepEqual([]string(*c.environ), tc.expectedEnv) {
174 t.Errorf("for env=%q args=%q, environment:\nwant: %q\n got: %q\n",
175 tc.env, tc.args,
176 tc.expectedEnv, []string(*c.environ))
177 }
178 if !reflect.DeepEqual(c.arguments, tc.remaining) {
179 t.Errorf("for env=%q args=%q, remaining arguments:\nwant: %q\n got: %q\n",
180 tc.env, tc.args,
181 tc.remaining, c.arguments)
182 }
183 })
184 }
185}
Patrice Arruda13848222019-04-22 17:12:02 -0700186
187func TestConfigCheckTopDir(t *testing.T) {
188 ctx := testContext()
189 buildRootDir := filepath.Dir(srcDirFileCheck)
190 expectedErrStr := fmt.Sprintf("Current working directory must be the source tree. %q not found.", srcDirFileCheck)
191
192 tests := []struct {
193 // ********* Setup *********
194 // Test description.
195 description string
196
197 // ********* Action *********
198 // If set to true, the build root file is created.
199 rootBuildFile bool
200
201 // The current path where Soong is being executed.
202 path string
203
204 // ********* Validation *********
205 // Expecting error and validate the error string against expectedErrStr.
206 wantErr bool
207 }{{
208 description: "current directory is the root source tree",
209 rootBuildFile: true,
210 path: ".",
211 wantErr: false,
212 }, {
213 description: "one level deep in the source tree",
214 rootBuildFile: true,
215 path: "1",
216 wantErr: true,
217 }, {
218 description: "very deep in the source tree",
219 rootBuildFile: true,
220 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",
221 wantErr: true,
222 }, {
223 description: "outside of source tree",
224 rootBuildFile: false,
225 path: "1/2/3/4/5",
226 wantErr: true,
227 }}
228
229 for _, tt := range tests {
230 t.Run(tt.description, func(t *testing.T) {
231 defer logger.Recover(func(err error) {
232 if !tt.wantErr {
233 t.Fatalf("Got unexpected error: %v", err)
234 }
235 if expectedErrStr != err.Error() {
236 t.Fatalf("expected %s, got %s", expectedErrStr, err.Error())
237 }
238 })
239
240 // Create the root source tree.
241 rootDir, err := ioutil.TempDir("", "")
242 if err != nil {
243 t.Fatal(err)
244 }
245 defer os.RemoveAll(rootDir)
246
247 // Create the build root file. This is to test if topDir returns an error if the build root
248 // file does not exist.
249 if tt.rootBuildFile {
250 dir := filepath.Join(rootDir, buildRootDir)
251 if err := os.MkdirAll(dir, 0755); err != nil {
252 t.Errorf("failed to create %s directory: %v", dir, err)
253 }
254 f := filepath.Join(rootDir, srcDirFileCheck)
255 if err := ioutil.WriteFile(f, []byte{}, 0644); err != nil {
256 t.Errorf("failed to create file %s: %v", f, err)
257 }
258 }
259
260 // Next block of code is to set the current directory.
261 dir := rootDir
262 if tt.path != "" {
263 dir = filepath.Join(dir, tt.path)
264 if err := os.MkdirAll(dir, 0755); err != nil {
265 t.Errorf("failed to create %s directory: %v", dir, err)
266 }
267 }
268 curDir, err := os.Getwd()
269 if err != nil {
270 t.Fatalf("failed to get the current directory: %v", err)
271 }
272 defer func() { os.Chdir(curDir) }()
273
274 if err := os.Chdir(dir); err != nil {
275 t.Fatalf("failed to change directory to %s: %v", dir, err)
276 }
277
278 checkTopDir(ctx)
279 })
280 }
281}
282
283func TestConfigConvertToTarget(t *testing.T) {
284 tests := []struct {
285 // ********* Setup *********
286 // Test description.
287 description string
288
289 // ********* Action *********
290 // The current directory where Soong is being executed.
291 dir string
292
293 // The current prefix string to be pre-appended to the target.
294 prefix string
295
296 // ********* Validation *********
297 // The expected target to be invoked in ninja.
298 expectedTarget string
299 }{{
300 description: "one level directory in source tree",
301 dir: "test1",
302 prefix: "MODULES-IN-",
303 expectedTarget: "MODULES-IN-test1",
304 }, {
305 description: "multiple level directories in source tree",
306 dir: "test1/test2/test3/test4",
307 prefix: "GET-INSTALL-PATH-IN-",
308 expectedTarget: "GET-INSTALL-PATH-IN-test1-test2-test3-test4",
309 }}
310 for _, tt := range tests {
311 t.Run(tt.description, func(t *testing.T) {
312 target := convertToTarget(tt.dir, tt.prefix)
313 if target != tt.expectedTarget {
314 t.Errorf("expected %s, got %s for target", tt.expectedTarget, target)
315 }
316 })
317 }
318}
319
320func setTop(t *testing.T, dir string) func() {
321 curDir, err := os.Getwd()
322 if err != nil {
323 t.Fatalf("failed to get current directory: %v", err)
324 }
325 if err := os.Chdir(dir); err != nil {
326 t.Fatalf("failed to change directory to top dir %s: %v", dir, err)
327 }
328 return func() { os.Chdir(curDir) }
329}
330
331func createBuildFiles(t *testing.T, topDir string, buildFiles []string) {
332 for _, buildFile := range buildFiles {
333 buildFile = filepath.Join(topDir, buildFile)
334 if err := ioutil.WriteFile(buildFile, []byte{}, 0644); err != nil {
335 t.Errorf("failed to create file %s: %v", buildFile, err)
336 }
337 }
338}
339
340func createDirectories(t *testing.T, topDir string, dirs []string) {
341 for _, dir := range dirs {
342 dir = filepath.Join(topDir, dir)
343 if err := os.MkdirAll(dir, 0755); err != nil {
344 t.Errorf("failed to create %s directory: %v", dir, err)
345 }
346 }
347}
348
349func TestConfigGetTargets(t *testing.T) {
350 ctx := testContext()
351 tests := []struct {
352 // ********* Setup *********
353 // Test description.
354 description string
355
356 // Directories that exist in the source tree.
357 dirsInTrees []string
358
359 // Build files that exists in the source tree.
360 buildFiles []string
361
362 // ********* Action *********
363 // Directories passed in to soong_ui.
364 dirs []string
365
366 // Current directory that the user executed the build action command.
367 curDir string
368
369 // ********* Validation *********
370 // Expected targets from the function.
371 expectedTargets []string
372
Patrice Arruda13848222019-04-22 17:12:02 -0700373 // Expecting error from running test case.
374 errStr string
375 }{{
Dan Willemsence41e942019-07-29 23:39:30 -0700376 description: "one target dir specified",
377 dirsInTrees: []string{"0/1/2/3"},
378 buildFiles: []string{"0/1/2/3/Android.bp"},
379 dirs: []string{"1/2/3"},
380 curDir: "0",
381 expectedTargets: []string{"MODULES-IN-0-1-2-3"},
Patrice Arruda13848222019-04-22 17:12:02 -0700382 }, {
383 description: "one target dir specified, build file does not exist",
384 dirsInTrees: []string{"0/1/2/3"},
385 buildFiles: []string{},
386 dirs: []string{"1/2/3"},
387 curDir: "0",
388 errStr: "Build file not found for 0/1/2/3 directory",
389 }, {
390 description: "one target dir specified, invalid targets specified",
391 dirsInTrees: []string{"0/1/2/3"},
392 buildFiles: []string{},
393 dirs: []string{"1/2/3:t1:t2"},
394 curDir: "0",
395 errStr: "1/2/3:t1:t2 not in proper directory:target1,target2,... format (\":\" was specified more than once)",
396 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700397 description: "one target dir specified, no targets specified but has colon",
398 dirsInTrees: []string{"0/1/2/3"},
399 buildFiles: []string{"0/1/2/3/Android.bp"},
400 dirs: []string{"1/2/3:"},
401 curDir: "0",
402 expectedTargets: []string{"MODULES-IN-0-1-2-3"},
Patrice Arruda13848222019-04-22 17:12:02 -0700403 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700404 description: "one target dir specified, two targets specified",
405 dirsInTrees: []string{"0/1/2/3"},
406 buildFiles: []string{"0/1/2/3/Android.bp"},
407 dirs: []string{"1/2/3:t1,t2"},
408 curDir: "0",
409 expectedTargets: []string{"t1", "t2"},
Patrice Arruda13848222019-04-22 17:12:02 -0700410 }, {
411 description: "one target dir specified, no targets and has a comma",
412 dirsInTrees: []string{"0/1/2/3"},
413 buildFiles: []string{"0/1/2/3/Android.bp"},
414 dirs: []string{"1/2/3:,"},
415 curDir: "0",
416 errStr: "0/1/2/3 not in proper directory:target1,target2,... format",
417 }, {
418 description: "one target dir specified, improper targets defined",
419 dirsInTrees: []string{"0/1/2/3"},
420 buildFiles: []string{"0/1/2/3/Android.bp"},
421 dirs: []string{"1/2/3:,t1"},
422 curDir: "0",
423 errStr: "0/1/2/3 not in proper directory:target1,target2,... format",
424 }, {
425 description: "one target dir specified, blank target",
426 dirsInTrees: []string{"0/1/2/3"},
427 buildFiles: []string{"0/1/2/3/Android.bp"},
428 dirs: []string{"1/2/3:t1,"},
429 curDir: "0",
430 errStr: "0/1/2/3 not in proper directory:target1,target2,... format",
431 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700432 description: "one target dir specified, many targets specified",
433 dirsInTrees: []string{"0/1/2/3"},
434 buildFiles: []string{"0/1/2/3/Android.bp"},
435 dirs: []string{"1/2/3:t1,t2,t3,t4,t5,t6,t7,t8,t9,t10"},
436 curDir: "0",
437 expectedTargets: []string{"t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9", "t10"},
Patrice Arruda13848222019-04-22 17:12:02 -0700438 }, {
439 description: "one target dir specified, one target specified, build file does not exist",
440 dirsInTrees: []string{"0/1/2/3"},
441 buildFiles: []string{},
442 dirs: []string{"1/2/3:t1"},
443 curDir: "0",
Patrice Arruda9450d0b2019-07-08 11:06:46 -0700444 errStr: "Couldn't locate a build file from 0/1/2/3 directory",
Patrice Arruda13848222019-04-22 17:12:02 -0700445 }, {
446 description: "one target dir specified, one target specified, build file not in target dir",
447 dirsInTrees: []string{"0/1/2/3"},
448 buildFiles: []string{"0/1/2/Android.mk"},
449 dirs: []string{"1/2/3:t1"},
450 curDir: "0",
451 errStr: "Couldn't locate a build file from 0/1/2/3 directory",
452 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700453 description: "one target dir specified, build file not in target dir",
454 dirsInTrees: []string{"0/1/2/3"},
455 buildFiles: []string{"0/1/2/Android.mk"},
456 dirs: []string{"1/2/3"},
457 curDir: "0",
458 expectedTargets: []string{"MODULES-IN-0-1-2"},
Patrice Arruda13848222019-04-22 17:12:02 -0700459 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700460 description: "multiple targets dir specified, targets specified",
461 dirsInTrees: []string{"0/1/2/3", "0/3/4"},
462 buildFiles: []string{"0/1/2/3/Android.bp", "0/3/4/Android.mk"},
463 dirs: []string{"1/2/3:t1,t2", "3/4:t3,t4,t5"},
464 curDir: "0",
465 expectedTargets: []string{"t1", "t2", "t3", "t4", "t5"},
Patrice Arruda13848222019-04-22 17:12:02 -0700466 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700467 description: "multiple targets dir specified, one directory has targets specified",
468 dirsInTrees: []string{"0/1/2/3", "0/3/4"},
469 buildFiles: []string{"0/1/2/3/Android.bp", "0/3/4/Android.mk"},
470 dirs: []string{"1/2/3:t1,t2", "3/4"},
471 curDir: "0",
472 expectedTargets: []string{"t1", "t2", "MODULES-IN-0-3-4"},
Patrice Arruda13848222019-04-22 17:12:02 -0700473 }, {
474 description: "two dirs specified, only one dir exist",
475 dirsInTrees: []string{"0/1/2/3"},
476 buildFiles: []string{"0/1/2/3/Android.mk"},
477 dirs: []string{"1/2/3:t1", "3/4"},
478 curDir: "0",
479 errStr: "couldn't find directory 0/3/4",
480 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700481 description: "multiple targets dirs specified at root source tree",
482 dirsInTrees: []string{"0/1/2/3", "0/3/4"},
483 buildFiles: []string{"0/1/2/3/Android.bp", "0/3/4/Android.mk"},
484 dirs: []string{"0/1/2/3:t1,t2", "0/3/4"},
485 curDir: ".",
486 expectedTargets: []string{"t1", "t2", "MODULES-IN-0-3-4"},
Patrice Arruda13848222019-04-22 17:12:02 -0700487 }, {
488 description: "no directories specified",
489 dirsInTrees: []string{"0/1/2/3", "0/3/4"},
490 buildFiles: []string{"0/1/2/3/Android.bp", "0/3/4/Android.mk"},
491 dirs: []string{},
492 curDir: ".",
493 }}
494 for _, tt := range tests {
495 t.Run(tt.description, func(t *testing.T) {
496 defer logger.Recover(func(err error) {
497 if tt.errStr == "" {
498 t.Fatalf("Got unexpected error: %v", err)
499 }
500 if tt.errStr != err.Error() {
501 t.Errorf("expected %s, got %s", tt.errStr, err.Error())
502 }
503 })
504
505 // Create the root source tree.
506 topDir, err := ioutil.TempDir("", "")
507 if err != nil {
508 t.Fatalf("failed to create temp dir: %v", err)
509 }
510 defer os.RemoveAll(topDir)
511
512 createDirectories(t, topDir, tt.dirsInTrees)
513 createBuildFiles(t, topDir, tt.buildFiles)
514 r := setTop(t, topDir)
515 defer r()
516
Dan Willemsence41e942019-07-29 23:39:30 -0700517 targets := getTargetsFromDirs(ctx, tt.curDir, tt.dirs, "MODULES-IN-")
Patrice Arruda13848222019-04-22 17:12:02 -0700518 if !reflect.DeepEqual(targets, tt.expectedTargets) {
519 t.Errorf("expected %v, got %v for targets", tt.expectedTargets, targets)
520 }
Patrice Arruda13848222019-04-22 17:12:02 -0700521
522 // If the execution reached here and there was an expected error code, the unit test case failed.
523 if tt.errStr != "" {
524 t.Errorf("expecting error %s", tt.errStr)
525 }
526 })
527 }
528}
529
530func TestConfigFindBuildFile(t *testing.T) {
531 ctx := testContext()
532
533 tests := []struct {
534 // ********* Setup *********
535 // Test description.
536 description string
537
538 // Array of build files to create in dir.
539 buildFiles []string
540
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700541 // Directories that exist in the source tree.
542 dirsInTrees []string
543
Patrice Arruda13848222019-04-22 17:12:02 -0700544 // ********* Action *********
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700545 // The base directory is where findBuildFile is invoked.
Patrice Arruda13848222019-04-22 17:12:02 -0700546 dir string
547
548 // ********* Validation *********
549 // Expected build file path to find.
550 expectedBuildFile string
551 }{{
552 description: "build file exists at leaf directory",
553 buildFiles: []string{"1/2/3/Android.bp"},
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700554 dirsInTrees: []string{"1/2/3"},
Patrice Arruda13848222019-04-22 17:12:02 -0700555 dir: "1/2/3",
556 expectedBuildFile: "1/2/3/Android.mk",
557 }, {
558 description: "build file exists in all directory paths",
559 buildFiles: []string{"1/Android.mk", "1/2/Android.mk", "1/2/3/Android.mk"},
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700560 dirsInTrees: []string{"1/2/3"},
Patrice Arruda13848222019-04-22 17:12:02 -0700561 dir: "1/2/3",
562 expectedBuildFile: "1/2/3/Android.mk",
563 }, {
564 description: "build file does not exist in all directory paths",
565 buildFiles: []string{},
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700566 dirsInTrees: []string{"1/2/3"},
Patrice Arruda13848222019-04-22 17:12:02 -0700567 dir: "1/2/3",
568 expectedBuildFile: "",
569 }, {
570 description: "build file exists only at top directory",
571 buildFiles: []string{"Android.bp"},
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700572 dirsInTrees: []string{"1/2/3"},
Patrice Arruda13848222019-04-22 17:12:02 -0700573 dir: "1/2/3",
574 expectedBuildFile: "",
575 }, {
576 description: "build file exist in a subdirectory",
577 buildFiles: []string{"1/2/Android.bp"},
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700578 dirsInTrees: []string{"1/2/3"},
Patrice Arruda13848222019-04-22 17:12:02 -0700579 dir: "1/2/3",
580 expectedBuildFile: "1/2/Android.mk",
581 }, {
582 description: "build file exists in a subdirectory",
583 buildFiles: []string{"1/Android.mk"},
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700584 dirsInTrees: []string{"1/2/3"},
Patrice Arruda13848222019-04-22 17:12:02 -0700585 dir: "1/2/3",
586 expectedBuildFile: "1/Android.mk",
587 }, {
588 description: "top directory",
589 buildFiles: []string{"Android.bp"},
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700590 dirsInTrees: []string{},
Patrice Arruda13848222019-04-22 17:12:02 -0700591 dir: ".",
592 expectedBuildFile: "",
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700593 }, {
594 description: "build file exists in subdirectory",
595 buildFiles: []string{"1/2/3/Android.bp", "1/2/4/Android.bp"},
596 dirsInTrees: []string{"1/2/3", "1/2/4"},
597 dir: "1/2",
598 expectedBuildFile: "1/2/Android.mk",
599 }, {
600 description: "build file exists in parent subdirectory",
601 buildFiles: []string{"1/5/Android.bp"},
602 dirsInTrees: []string{"1/2/3", "1/2/4", "1/5"},
603 dir: "1/2",
604 expectedBuildFile: "1/Android.mk",
605 }, {
606 description: "build file exists in deep parent's subdirectory.",
607 buildFiles: []string{"1/5/6/Android.bp"},
608 dirsInTrees: []string{"1/2/3", "1/2/4", "1/5/6", "1/5/7"},
609 dir: "1/2",
610 expectedBuildFile: "1/Android.mk",
Patrice Arruda13848222019-04-22 17:12:02 -0700611 }}
612
613 for _, tt := range tests {
614 t.Run(tt.description, func(t *testing.T) {
615 defer logger.Recover(func(err error) {
616 t.Fatalf("Got unexpected error: %v", err)
617 })
618
619 topDir, err := ioutil.TempDir("", "")
620 if err != nil {
621 t.Fatalf("failed to create temp dir: %v", err)
622 }
623 defer os.RemoveAll(topDir)
624
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700625 createDirectories(t, topDir, tt.dirsInTrees)
Patrice Arruda13848222019-04-22 17:12:02 -0700626 createBuildFiles(t, topDir, tt.buildFiles)
627
628 curDir, err := os.Getwd()
629 if err != nil {
630 t.Fatalf("Could not get working directory: %v", err)
631 }
632 defer func() { os.Chdir(curDir) }()
633 if err := os.Chdir(topDir); err != nil {
634 t.Fatalf("Could not change top dir to %s: %v", topDir, err)
635 }
636
637 buildFile := findBuildFile(ctx, tt.dir)
638 if buildFile != tt.expectedBuildFile {
639 t.Errorf("expected %q, got %q for build file", tt.expectedBuildFile, buildFile)
640 }
641 })
642 }
643}
644
645func TestConfigSplitArgs(t *testing.T) {
646 tests := []struct {
647 // ********* Setup *********
648 // Test description.
649 description string
650
651 // ********* Action *********
652 // Arguments passed in to soong_ui.
653 args []string
654
655 // ********* Validation *********
656 // Expected newArgs list after extracting the directories.
657 expectedNewArgs []string
658
659 // Expected directories
660 expectedDirs []string
661 }{{
662 description: "flags but no directories specified",
663 args: []string{"showcommands", "-j", "-k"},
664 expectedNewArgs: []string{"showcommands", "-j", "-k"},
665 expectedDirs: []string{},
666 }, {
667 description: "flags and one directory specified",
668 args: []string{"snod", "-j", "dir:target1,target2"},
669 expectedNewArgs: []string{"snod", "-j"},
670 expectedDirs: []string{"dir:target1,target2"},
671 }, {
672 description: "flags and directories specified",
673 args: []string{"dist", "-k", "dir1", "dir2:target1,target2"},
674 expectedNewArgs: []string{"dist", "-k"},
675 expectedDirs: []string{"dir1", "dir2:target1,target2"},
676 }, {
677 description: "only directories specified",
678 args: []string{"dir1", "dir2", "dir3:target1,target2"},
679 expectedNewArgs: []string{},
680 expectedDirs: []string{"dir1", "dir2", "dir3:target1,target2"},
681 }}
682 for _, tt := range tests {
683 t.Run(tt.description, func(t *testing.T) {
684 args, dirs := splitArgs(tt.args)
685 if !reflect.DeepEqual(tt.expectedNewArgs, args) {
686 t.Errorf("expected %v, got %v for arguments", tt.expectedNewArgs, args)
687 }
688 if !reflect.DeepEqual(tt.expectedDirs, dirs) {
689 t.Errorf("expected %v, got %v for directories", tt.expectedDirs, dirs)
690 }
691 })
692 }
693}
694
695type envVar struct {
696 name string
697 value string
698}
699
700type buildActionTestCase struct {
701 // ********* Setup *********
702 // Test description.
703 description string
704
705 // Directories that exist in the source tree.
706 dirsInTrees []string
707
708 // Build files that exists in the source tree.
709 buildFiles []string
710
Patrice Arrudababa9a92019-07-03 10:47:34 -0700711 // Create root symlink that points to topDir.
712 rootSymlink bool
713
Patrice Arruda13848222019-04-22 17:12:02 -0700714 // ********* Action *********
715 // Arguments passed in to soong_ui.
716 args []string
717
718 // Directory where the build action was invoked.
719 curDir string
720
721 // WITH_TIDY_ONLY environment variable specified.
722 tidyOnly string
723
724 // ********* Validation *********
725 // Expected arguments to be in Config instance.
726 expectedArgs []string
727
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700728 // Expecting error from running test case.
729 expectedErrStr string
Patrice Arruda13848222019-04-22 17:12:02 -0700730}
731
Dan Willemsence41e942019-07-29 23:39:30 -0700732func testGetConfigArgs(t *testing.T, tt buildActionTestCase, action BuildAction) {
Patrice Arruda13848222019-04-22 17:12:02 -0700733 ctx := testContext()
734
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700735 defer logger.Recover(func(err error) {
736 if tt.expectedErrStr == "" {
737 t.Fatalf("Got unexpected error: %v", err)
738 }
739 if tt.expectedErrStr != err.Error() {
740 t.Errorf("expected %s, got %s", tt.expectedErrStr, err.Error())
741 }
742 })
743
Patrice Arruda13848222019-04-22 17:12:02 -0700744 // Environment variables to set it to blank on every test case run.
745 resetEnvVars := []string{
Patrice Arruda13848222019-04-22 17:12:02 -0700746 "WITH_TIDY_ONLY",
747 }
748
749 for _, name := range resetEnvVars {
750 if err := os.Unsetenv(name); err != nil {
751 t.Fatalf("failed to unset environment variable %s: %v", name, err)
752 }
753 }
754 if tt.tidyOnly != "" {
755 if err := os.Setenv("WITH_TIDY_ONLY", tt.tidyOnly); err != nil {
756 t.Errorf("failed to set WITH_TIDY_ONLY to %s: %v", tt.tidyOnly, err)
757 }
758 }
759
760 // Create the root source tree.
761 topDir, err := ioutil.TempDir("", "")
762 if err != nil {
763 t.Fatalf("failed to create temp dir: %v", err)
764 }
765 defer os.RemoveAll(topDir)
766
767 createDirectories(t, topDir, tt.dirsInTrees)
768 createBuildFiles(t, topDir, tt.buildFiles)
769
Patrice Arrudababa9a92019-07-03 10:47:34 -0700770 if tt.rootSymlink {
771 // Create a secondary root source tree which points to the true root source tree.
772 symlinkTopDir, err := ioutil.TempDir("", "")
773 if err != nil {
774 t.Fatalf("failed to create symlink temp dir: %v", err)
775 }
776 defer os.RemoveAll(symlinkTopDir)
777
778 symlinkTopDir = filepath.Join(symlinkTopDir, "root")
779 err = os.Symlink(topDir, symlinkTopDir)
780 if err != nil {
781 t.Fatalf("failed to create symlink: %v", err)
782 }
783 topDir = symlinkTopDir
784 }
785
Patrice Arruda13848222019-04-22 17:12:02 -0700786 r := setTop(t, topDir)
787 defer r()
788
789 // The next block is to create the root build file.
790 rootBuildFileDir := filepath.Dir(srcDirFileCheck)
791 if err := os.MkdirAll(rootBuildFileDir, 0755); err != nil {
792 t.Fatalf("Failed to create %s directory: %v", rootBuildFileDir, err)
793 }
794
795 if err := ioutil.WriteFile(srcDirFileCheck, []byte{}, 0644); err != nil {
796 t.Fatalf("failed to create %s file: %v", srcDirFileCheck, err)
797 }
798
Dan Willemsence41e942019-07-29 23:39:30 -0700799 args := getConfigArgs(action, tt.curDir, ctx, tt.args)
Patrice Arruda13848222019-04-22 17:12:02 -0700800 if !reflect.DeepEqual(tt.expectedArgs, args) {
801 t.Fatalf("expected %v, got %v for config arguments", tt.expectedArgs, args)
802 }
803
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700804 // If the execution reached here and there was an expected error code, the unit test case failed.
805 if tt.expectedErrStr != "" {
806 t.Errorf("expecting error %s", tt.expectedErrStr)
807 }
Patrice Arruda13848222019-04-22 17:12:02 -0700808}
809
Patrice Arruda39282062019-06-20 16:35:12 -0700810func TestGetConfigArgsBuildModules(t *testing.T) {
811 tests := []buildActionTestCase{{
Dan Willemsence41e942019-07-29 23:39:30 -0700812 description: "normal execution from the root source tree directory",
813 dirsInTrees: []string{"0/1/2", "0/2", "0/3"},
814 buildFiles: []string{"0/1/2/Android.mk", "0/2/Android.bp", "0/3/Android.mk"},
815 args: []string{"-j", "fake_module", "fake_module2"},
816 curDir: ".",
817 tidyOnly: "",
818 expectedArgs: []string{"-j", "fake_module", "fake_module2"},
Patrice Arruda39282062019-06-20 16:35:12 -0700819 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700820 description: "normal execution in deep directory",
821 dirsInTrees: []string{"0/1/2", "0/2", "0/3", "1/2/3/4/5/6/7/8/9/1/2/3/4/5/6"},
822 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"},
823 args: []string{"-j", "fake_module", "fake_module2", "-k"},
824 curDir: "1/2/3/4/5/6/7/8/9",
825 tidyOnly: "",
826 expectedArgs: []string{"-j", "fake_module", "fake_module2", "-k"},
Patrice Arruda39282062019-06-20 16:35:12 -0700827 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700828 description: "normal execution in deep directory, no targets",
829 dirsInTrees: []string{"0/1/2", "0/2", "0/3", "1/2/3/4/5/6/7/8/9/1/2/3/4/5/6"},
830 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"},
831 args: []string{"-j", "-k"},
832 curDir: "1/2/3/4/5/6/7/8/9",
833 tidyOnly: "",
834 expectedArgs: []string{"-j", "-k"},
Patrice Arruda39282062019-06-20 16:35:12 -0700835 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700836 description: "normal execution in root source tree, no args",
837 dirsInTrees: []string{"0/1/2", "0/2", "0/3"},
838 buildFiles: []string{"0/1/2/Android.mk", "0/2/Android.bp"},
839 args: []string{},
840 curDir: "0/2",
841 tidyOnly: "",
842 expectedArgs: []string{},
Patrice Arrudababa9a92019-07-03 10:47:34 -0700843 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700844 description: "normal execution in symlink root source tree, no args",
845 dirsInTrees: []string{"0/1/2", "0/2", "0/3"},
846 buildFiles: []string{"0/1/2/Android.mk", "0/2/Android.bp"},
847 rootSymlink: true,
848 args: []string{},
849 curDir: "0/2",
850 tidyOnly: "",
851 expectedArgs: []string{},
Patrice Arruda39282062019-06-20 16:35:12 -0700852 }}
853 for _, tt := range tests {
854 t.Run("build action BUILD_MODULES with dependencies, "+tt.description, func(t *testing.T) {
Dan Willemsence41e942019-07-29 23:39:30 -0700855 testGetConfigArgs(t, tt, BUILD_MODULES)
Patrice Arruda13848222019-04-22 17:12:02 -0700856 })
857 }
858}
859
860func TestGetConfigArgsBuildModulesInDirectory(t *testing.T) {
861 tests := []buildActionTestCase{{
Dan Willemsence41e942019-07-29 23:39:30 -0700862 description: "normal execution in a directory",
863 dirsInTrees: []string{"0/1/2"},
864 buildFiles: []string{"0/1/2/Android.mk"},
865 args: []string{"fake-module"},
866 curDir: "0/1/2",
867 tidyOnly: "",
868 expectedArgs: []string{"fake-module", "MODULES-IN-0-1-2"},
Patrice Arruda13848222019-04-22 17:12:02 -0700869 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700870 description: "build file in parent directory",
871 dirsInTrees: []string{"0/1/2"},
872 buildFiles: []string{"0/1/Android.mk"},
873 args: []string{},
874 curDir: "0/1/2",
875 tidyOnly: "",
876 expectedArgs: []string{"MODULES-IN-0-1"},
Patrice Arruda13848222019-04-22 17:12:02 -0700877 },
878 {
Dan Willemsence41e942019-07-29 23:39:30 -0700879 description: "build file in parent directory, multiple module names passed in",
880 dirsInTrees: []string{"0/1/2"},
881 buildFiles: []string{"0/1/Android.mk"},
882 args: []string{"fake-module1", "fake-module2", "fake-module3"},
883 curDir: "0/1/2",
884 tidyOnly: "",
885 expectedArgs: []string{"fake-module1", "fake-module2", "fake-module3", "MODULES-IN-0-1"},
Patrice Arruda13848222019-04-22 17:12:02 -0700886 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700887 description: "build file in 2nd level parent directory",
888 dirsInTrees: []string{"0/1/2"},
889 buildFiles: []string{"0/Android.bp"},
890 args: []string{},
891 curDir: "0/1/2",
892 tidyOnly: "",
893 expectedArgs: []string{"MODULES-IN-0"},
Patrice Arruda13848222019-04-22 17:12:02 -0700894 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700895 description: "build action executed at root directory",
896 dirsInTrees: []string{},
897 buildFiles: []string{},
898 rootSymlink: false,
899 args: []string{},
900 curDir: ".",
901 tidyOnly: "",
902 expectedArgs: []string{},
Patrice Arrudababa9a92019-07-03 10:47:34 -0700903 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700904 description: "build action executed at root directory in symlink",
905 dirsInTrees: []string{},
906 buildFiles: []string{},
907 rootSymlink: true,
908 args: []string{},
909 curDir: ".",
910 tidyOnly: "",
911 expectedArgs: []string{},
Patrice Arruda13848222019-04-22 17:12:02 -0700912 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700913 description: "build file not found",
914 dirsInTrees: []string{"0/1/2"},
915 buildFiles: []string{},
916 args: []string{},
917 curDir: "0/1/2",
918 tidyOnly: "",
919 expectedArgs: []string{"MODULES-IN-0-1-2"},
920 expectedErrStr: "Build file not found for 0/1/2 directory",
Patrice Arruda13848222019-04-22 17:12:02 -0700921 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700922 description: "GET-INSTALL-PATH specified,",
923 dirsInTrees: []string{"0/1/2"},
924 buildFiles: []string{"0/1/Android.mk"},
925 args: []string{"GET-INSTALL-PATH", "-j", "-k", "GET-INSTALL-PATH"},
926 curDir: "0/1/2",
927 tidyOnly: "",
928 expectedArgs: []string{"-j", "-k", "GET-INSTALL-PATH-IN-0-1"},
Patrice Arruda13848222019-04-22 17:12:02 -0700929 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700930 description: "tidy only environment variable specified,",
931 dirsInTrees: []string{"0/1/2"},
932 buildFiles: []string{"0/1/Android.mk"},
933 args: []string{"GET-INSTALL-PATH"},
934 curDir: "0/1/2",
935 tidyOnly: "true",
936 expectedArgs: []string{"tidy_only"},
Patrice Arruda13848222019-04-22 17:12:02 -0700937 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700938 description: "normal execution in root directory with args",
939 dirsInTrees: []string{},
940 buildFiles: []string{},
941 args: []string{"-j", "-k", "fake_module"},
942 curDir: "",
943 tidyOnly: "",
944 expectedArgs: []string{"-j", "-k", "fake_module"},
Patrice Arruda13848222019-04-22 17:12:02 -0700945 }}
946 for _, tt := range tests {
947 t.Run("build action BUILD_MODULES_IN_DIR, "+tt.description, func(t *testing.T) {
Dan Willemsence41e942019-07-29 23:39:30 -0700948 testGetConfigArgs(t, tt, BUILD_MODULES_IN_A_DIRECTORY)
Patrice Arruda13848222019-04-22 17:12:02 -0700949 })
950 }
951}
952
953func TestGetConfigArgsBuildModulesInDirectories(t *testing.T) {
954 tests := []buildActionTestCase{{
955 description: "normal execution in a directory",
956 dirsInTrees: []string{"0/1/2/3.1", "0/1/2/3.2", "0/1/2/3.3"},
957 buildFiles: []string{"0/1/2/3.1/Android.bp", "0/1/2/3.2/Android.bp", "0/1/2/3.3/Android.bp"},
958 args: []string{"3.1/", "3.2/", "3.3/"},
959 curDir: "0/1/2",
960 tidyOnly: "",
961 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 -0700962 }, {
963 description: "GET-INSTALL-PATH specified",
964 dirsInTrees: []string{"0/1/2/3.1", "0/1/2/3.2", "0/1/3"},
965 buildFiles: []string{"0/1/2/3.1/Android.bp", "0/1/2/3.2/Android.bp", "0/1/Android.bp"},
966 args: []string{"GET-INSTALL-PATH", "2/3.1/", "2/3.2", "3"},
967 curDir: "0/1",
968 tidyOnly: "",
969 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 -0700970 }, {
971 description: "tidy only environment variable specified",
972 dirsInTrees: []string{"0/1/2/3.1", "0/1/2/3.2", "0/1/2/3.3"},
973 buildFiles: []string{"0/1/2/3.1/Android.bp", "0/1/2/3.2/Android.bp", "0/1/2/3.3/Android.bp"},
974 args: []string{"GET-INSTALL-PATH", "3.1/", "3.2/", "3.3"},
975 curDir: "0/1/2",
976 tidyOnly: "1",
977 expectedArgs: []string{"tidy_only"},
Patrice Arruda13848222019-04-22 17:12:02 -0700978 }, {
979 description: "normal execution from top dir directory",
980 dirsInTrees: []string{"0/1/2/3.1", "0/1/2/3.2", "0/1/3", "0/2"},
981 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 -0700982 rootSymlink: false,
983 args: []string{"0/1/2/3.1", "0/1/2/3.2", "0/1/3", "0/2"},
984 curDir: ".",
985 tidyOnly: "",
986 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 -0700987 }, {
988 description: "normal execution from top dir directory in symlink",
989 dirsInTrees: []string{"0/1/2/3.1", "0/1/2/3.2", "0/1/3", "0/2"},
990 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"},
991 rootSymlink: true,
Patrice Arruda13848222019-04-22 17:12:02 -0700992 args: []string{"0/1/2/3.1", "0/1/2/3.2", "0/1/3", "0/2"},
993 curDir: ".",
994 tidyOnly: "",
995 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 -0700996 }}
997 for _, tt := range tests {
998 t.Run("build action BUILD_MODULES_IN_DIRS, "+tt.description, func(t *testing.T) {
Dan Willemsence41e942019-07-29 23:39:30 -0700999 testGetConfigArgs(t, tt, BUILD_MODULES_IN_DIRECTORIES)
Patrice Arruda13848222019-04-22 17:12:02 -07001000 })
1001 }
1002}
Liz Kammerca9cb2e2021-07-14 15:29:57 -04001003
1004func TestBuildConfig(t *testing.T) {
1005 tests := []struct {
1006 name string
1007 environ Environment
Yu Liue737a992021-10-04 13:21:41 -07001008 arguments []string
Liz Kammerca9cb2e2021-07-14 15:29:57 -04001009 useBazel bool
Chris Parsonsef615e52022-08-18 22:04:11 -04001010 bazelDevMode bool
1011 bazelProdMode bool
MarkDacekb78465d2022-10-18 20:10:16 +00001012 bazelStagingMode bool
Liz Kammerca9cb2e2021-07-14 15:29:57 -04001013 expectedBuildConfig *smpb.BuildConfig
1014 }{
1015 {
1016 name: "none set",
1017 environ: Environment{},
1018 expectedBuildConfig: &smpb.BuildConfig{
Romain Jobredeaux0a7529b2022-10-26 12:56:41 -04001019 ForceUseGoma: proto.Bool(false),
1020 UseGoma: proto.Bool(false),
1021 UseRbe: proto.Bool(false),
1022 BazelMixedBuild: proto.Bool(false),
1023 ForceDisableBazelMixedBuild: proto.Bool(false),
Liz Kammerca9cb2e2021-07-14 15:29:57 -04001024 },
1025 },
1026 {
1027 name: "force use goma",
1028 environ: Environment{"FORCE_USE_GOMA=1"},
1029 expectedBuildConfig: &smpb.BuildConfig{
Romain Jobredeaux0a7529b2022-10-26 12:56:41 -04001030 ForceUseGoma: proto.Bool(true),
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: "use goma",
1039 environ: Environment{"USE_GOMA=1"},
1040 expectedBuildConfig: &smpb.BuildConfig{
Romain Jobredeaux0a7529b2022-10-26 12:56:41 -04001041 ForceUseGoma: proto.Bool(false),
1042 UseGoma: proto.Bool(true),
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 rbe",
1050 environ: Environment{"USE_RBE=1"},
1051 expectedBuildConfig: &smpb.BuildConfig{
Romain Jobredeaux0a7529b2022-10-26 12:56:41 -04001052 ForceUseGoma: proto.Bool(false),
1053 UseGoma: proto.Bool(false),
1054 UseRbe: proto.Bool(true),
1055 BazelMixedBuild: proto.Bool(false),
1056 ForceDisableBazelMixedBuild: proto.Bool(false),
1057 },
1058 },
1059 {
1060 name: "disable mixed builds",
1061 environ: Environment{"BUILD_BROKEN_DISABLE_BAZEL=1"},
1062 expectedBuildConfig: &smpb.BuildConfig{
1063 ForceUseGoma: proto.Bool(false),
1064 UseGoma: proto.Bool(false),
1065 UseRbe: proto.Bool(false),
1066 BazelMixedBuild: proto.Bool(false),
1067 ForceDisableBazelMixedBuild: proto.Bool(true),
Liz Kammerca9cb2e2021-07-14 15:29:57 -04001068 },
1069 },
1070 {
1071 name: "use bazel as ninja",
1072 environ: Environment{},
1073 useBazel: true,
1074 expectedBuildConfig: &smpb.BuildConfig{
Romain Jobredeaux0a7529b2022-10-26 12:56:41 -04001075 ForceUseGoma: proto.Bool(false),
1076 UseGoma: proto.Bool(false),
1077 UseRbe: proto.Bool(false),
1078 BazelMixedBuild: proto.Bool(false),
1079 ForceDisableBazelMixedBuild: proto.Bool(false),
Liz Kammerca9cb2e2021-07-14 15:29:57 -04001080 },
1081 },
1082 {
Chris Parsonsef615e52022-08-18 22:04:11 -04001083 name: "bazel mixed build from dev mode",
1084 environ: Environment{},
1085 bazelDevMode: true,
1086 expectedBuildConfig: &smpb.BuildConfig{
Romain Jobredeaux0a7529b2022-10-26 12:56:41 -04001087 ForceUseGoma: proto.Bool(false),
1088 UseGoma: proto.Bool(false),
1089 UseRbe: proto.Bool(false),
1090 BazelMixedBuild: proto.Bool(true),
1091 ForceDisableBazelMixedBuild: proto.Bool(false),
Chris Parsonsef615e52022-08-18 22:04:11 -04001092 },
1093 },
1094 {
1095 name: "bazel mixed build from prod mode",
1096 environ: Environment{},
1097 bazelProdMode: true,
1098 expectedBuildConfig: &smpb.BuildConfig{
Romain Jobredeaux0a7529b2022-10-26 12:56:41 -04001099 ForceUseGoma: proto.Bool(false),
1100 UseGoma: proto.Bool(false),
1101 UseRbe: proto.Bool(false),
1102 BazelMixedBuild: proto.Bool(true),
1103 ForceDisableBazelMixedBuild: proto.Bool(false),
Chris Parsonsef615e52022-08-18 22:04:11 -04001104 },
1105 },
1106 {
MarkDacekb78465d2022-10-18 20:10:16 +00001107 name: "bazel mixed build from staging mode",
1108 environ: Environment{},
1109 bazelStagingMode: true,
1110 expectedBuildConfig: &smpb.BuildConfig{
Romain Jobredeaux0a7529b2022-10-26 12:56:41 -04001111 ForceUseGoma: proto.Bool(false),
1112 UseGoma: proto.Bool(false),
1113 UseRbe: proto.Bool(false),
1114 BazelMixedBuild: proto.Bool(true),
1115 ForceDisableBazelMixedBuild: proto.Bool(false),
MarkDacekb78465d2022-10-18 20:10:16 +00001116 },
1117 },
1118 {
Yu Liue737a992021-10-04 13:21:41 -07001119 name: "specified targets",
1120 environ: Environment{},
1121 useBazel: true,
1122 arguments: []string{"droid", "dist"},
1123 expectedBuildConfig: &smpb.BuildConfig{
Romain Jobredeaux0a7529b2022-10-26 12:56:41 -04001124 ForceUseGoma: proto.Bool(false),
1125 UseGoma: proto.Bool(false),
1126 UseRbe: proto.Bool(false),
1127 BazelMixedBuild: proto.Bool(false),
1128 Targets: []string{"droid", "dist"},
1129 ForceDisableBazelMixedBuild: proto.Bool(false),
Yu Liue737a992021-10-04 13:21:41 -07001130 },
1131 },
1132 {
Liz Kammerca9cb2e2021-07-14 15:29:57 -04001133 name: "all set",
1134 environ: Environment{
1135 "FORCE_USE_GOMA=1",
1136 "USE_GOMA=1",
1137 "USE_RBE=1",
Romain Jobredeaux0a7529b2022-10-26 12:56:41 -04001138 "BUILD_BROKEN_DISABLE_BAZEL=1",
Liz Kammerca9cb2e2021-07-14 15:29:57 -04001139 },
Chris Parsonsef615e52022-08-18 22:04:11 -04001140 useBazel: true,
1141 bazelDevMode: true,
Liz Kammerca9cb2e2021-07-14 15:29:57 -04001142 expectedBuildConfig: &smpb.BuildConfig{
Romain Jobredeaux0a7529b2022-10-26 12:56:41 -04001143 ForceUseGoma: proto.Bool(true),
1144 UseGoma: proto.Bool(true),
1145 UseRbe: proto.Bool(true),
1146 BazelMixedBuild: proto.Bool(true),
1147 ForceDisableBazelMixedBuild: proto.Bool(true),
Liz Kammerca9cb2e2021-07-14 15:29:57 -04001148 },
1149 },
1150 }
1151
Chris Parsonsef615e52022-08-18 22:04:11 -04001152 ctx := testContext()
Liz Kammerca9cb2e2021-07-14 15:29:57 -04001153 for _, tc := range tests {
1154 t.Run(tc.name, func(t *testing.T) {
1155 c := &configImpl{
MarkDacekb78465d2022-10-18 20:10:16 +00001156 environ: &tc.environ,
1157 bazelDevMode: tc.bazelDevMode,
1158 bazelProdMode: tc.bazelProdMode,
1159 bazelStagingMode: tc.bazelStagingMode,
1160 arguments: tc.arguments,
Liz Kammerca9cb2e2021-07-14 15:29:57 -04001161 }
1162 config := Config{c}
Chris Parsonsef615e52022-08-18 22:04:11 -04001163 checkBazelMode(ctx, config)
Liz Kammerca9cb2e2021-07-14 15:29:57 -04001164 actualBuildConfig := buildConfig(config)
1165 if expected := tc.expectedBuildConfig; !proto.Equal(expected, actualBuildConfig) {
Chris Parsonsef615e52022-08-18 22:04:11 -04001166 t.Errorf("Build config mismatch.\n"+
1167 "Expected build config: %#v\n"+
1168 "Actual build config: %#v", prototext.Format(expected), prototext.Format(actualBuildConfig))
Liz Kammerca9cb2e2021-07-14 15:29:57 -04001169 }
1170 })
1171 }
1172}
Yu Liu6e13b402021-07-27 14:29:06 -07001173
1174func TestGetMetricsUploaderApp(t *testing.T) {
1175
1176 metricsUploaderDir := "metrics_uploader_dir"
1177 metricsUploaderBinary := "metrics_uploader_binary"
1178 metricsUploaderPath := filepath.Join(metricsUploaderDir, metricsUploaderBinary)
1179 tests := []struct {
1180 description string
1181 environ Environment
1182 createFiles bool
1183 expected string
1184 }{{
1185 description: "Uploader binary exist",
1186 environ: Environment{"METRICS_UPLOADER=" + metricsUploaderPath},
1187 createFiles: true,
1188 expected: metricsUploaderPath,
1189 }, {
1190 description: "Uploader binary not exist",
1191 environ: Environment{"METRICS_UPLOADER=" + metricsUploaderPath},
1192 createFiles: false,
1193 expected: "",
1194 }, {
1195 description: "Uploader binary variable not set",
1196 createFiles: true,
1197 expected: "",
1198 }}
1199
1200 for _, tt := range tests {
1201 t.Run(tt.description, func(t *testing.T) {
1202 defer logger.Recover(func(err error) {
1203 t.Fatalf("got unexpected error: %v", err)
1204 })
1205
1206 // Create the root source tree.
1207 topDir, err := ioutil.TempDir("", "")
1208 if err != nil {
1209 t.Fatalf("failed to create temp dir: %v", err)
1210 }
1211 defer os.RemoveAll(topDir)
1212
1213 expected := tt.expected
1214 if len(expected) > 0 {
1215 expected = filepath.Join(topDir, expected)
1216 }
1217
1218 if tt.createFiles {
1219 if err := os.MkdirAll(filepath.Join(topDir, metricsUploaderDir), 0755); err != nil {
1220 t.Errorf("failed to create %s directory: %v", metricsUploaderDir, err)
1221 }
1222 if err := ioutil.WriteFile(filepath.Join(topDir, metricsUploaderPath), []byte{}, 0644); err != nil {
1223 t.Errorf("failed to create file %s: %v", expected, err)
1224 }
1225 }
1226
1227 actual := GetMetricsUploader(topDir, &tt.environ)
1228
1229 if actual != expected {
1230 t.Errorf("expecting: %s, actual: %s", expected, actual)
1231 }
1232 })
1233 }
1234}