blob: 9ea51101f3a231359a3753ac04277c052a4326ef [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"
Chris Parsonsef615e52022-08-18 22:04:11 -040031 "google.golang.org/protobuf/encoding/prototext"
Liz Kammerca9cb2e2021-07-14 15:29:57 -040032
Dan Willemsen4591b642021-05-24 14:24:12 -070033 "google.golang.org/protobuf/proto"
Dan Willemsen9b587492017-07-10 22:13:00 -070034)
35
36func testContext() Context {
37 return Context{&ContextImpl{
Dan Willemsenb82471a2018-05-17 16:37:09 -070038 Context: context.Background(),
39 Logger: logger.New(&bytes.Buffer{}),
Colin Cross097ed2a2019-06-08 21:48:58 -070040 Writer: &bytes.Buffer{},
Patrice Arruda219eef32020-06-01 17:29:30 +000041 Status: &status.Status{},
Dan Willemsen9b587492017-07-10 22:13:00 -070042 }}
43}
44
45func TestConfigParseArgsJK(t *testing.T) {
46 ctx := testContext()
47
48 testCases := []struct {
49 args []string
50
51 parallel int
52 keepGoing int
53 remaining []string
54 }{
55 {nil, -1, -1, nil},
56
57 {[]string{"-j"}, -1, -1, nil},
58 {[]string{"-j1"}, 1, -1, nil},
59 {[]string{"-j1234"}, 1234, -1, nil},
60
61 {[]string{"-j", "1"}, 1, -1, nil},
62 {[]string{"-j", "1234"}, 1234, -1, nil},
63 {[]string{"-j", "1234", "abc"}, 1234, -1, []string{"abc"}},
64 {[]string{"-j", "abc"}, -1, -1, []string{"abc"}},
65 {[]string{"-j", "1abc"}, -1, -1, []string{"1abc"}},
66
67 {[]string{"-k"}, -1, 0, nil},
68 {[]string{"-k0"}, -1, 0, nil},
69 {[]string{"-k1"}, -1, 1, nil},
70 {[]string{"-k1234"}, -1, 1234, nil},
71
72 {[]string{"-k", "0"}, -1, 0, nil},
73 {[]string{"-k", "1"}, -1, 1, nil},
74 {[]string{"-k", "1234"}, -1, 1234, nil},
75 {[]string{"-k", "1234", "abc"}, -1, 1234, []string{"abc"}},
76 {[]string{"-k", "abc"}, -1, 0, []string{"abc"}},
77 {[]string{"-k", "1abc"}, -1, 0, []string{"1abc"}},
78
79 // TODO: These are supported in Make, should we support them?
80 //{[]string{"-kj"}, -1, 0},
81 //{[]string{"-kj8"}, 8, 0},
82
83 // -jk is not valid in Make
84 }
85
86 for _, tc := range testCases {
87 t.Run(strings.Join(tc.args, " "), func(t *testing.T) {
88 defer logger.Recover(func(err error) {
89 t.Fatal(err)
90 })
91
92 c := &configImpl{
93 parallel: -1,
94 keepGoing: -1,
95 }
96 c.parseArgs(ctx, tc.args)
97
98 if c.parallel != tc.parallel {
99 t.Errorf("for %q, parallel:\nwant: %d\n got: %d\n",
100 strings.Join(tc.args, " "),
101 tc.parallel, c.parallel)
102 }
103 if c.keepGoing != tc.keepGoing {
104 t.Errorf("for %q, keep going:\nwant: %d\n got: %d\n",
105 strings.Join(tc.args, " "),
106 tc.keepGoing, c.keepGoing)
107 }
108 if !reflect.DeepEqual(c.arguments, tc.remaining) {
109 t.Errorf("for %q, remaining arguments:\nwant: %q\n got: %q\n",
110 strings.Join(tc.args, " "),
111 tc.remaining, c.arguments)
112 }
113 })
114 }
115}
Dan Willemsen091525e2017-07-11 14:17:50 -0700116
117func TestConfigParseArgsVars(t *testing.T) {
118 ctx := testContext()
119
120 testCases := []struct {
121 env []string
122 args []string
123
124 expectedEnv []string
125 remaining []string
126 }{
127 {},
128 {
129 env: []string{"A=bc"},
130
131 expectedEnv: []string{"A=bc"},
132 },
133 {
134 args: []string{"abc"},
135
136 remaining: []string{"abc"},
137 },
138
139 {
140 args: []string{"A=bc"},
141
142 expectedEnv: []string{"A=bc"},
143 },
144 {
145 env: []string{"A=a"},
146 args: []string{"A=bc"},
147
148 expectedEnv: []string{"A=bc"},
149 },
150
151 {
152 env: []string{"A=a"},
153 args: []string{"A=", "=b"},
154
155 expectedEnv: []string{"A="},
156 remaining: []string{"=b"},
157 },
158 }
159
160 for _, tc := range testCases {
161 t.Run(strings.Join(tc.args, " "), func(t *testing.T) {
162 defer logger.Recover(func(err error) {
163 t.Fatal(err)
164 })
165
166 e := Environment(tc.env)
167 c := &configImpl{
168 environ: &e,
169 }
170 c.parseArgs(ctx, tc.args)
171
172 if !reflect.DeepEqual([]string(*c.environ), tc.expectedEnv) {
173 t.Errorf("for env=%q args=%q, environment:\nwant: %q\n got: %q\n",
174 tc.env, tc.args,
175 tc.expectedEnv, []string(*c.environ))
176 }
177 if !reflect.DeepEqual(c.arguments, tc.remaining) {
178 t.Errorf("for env=%q args=%q, remaining arguments:\nwant: %q\n got: %q\n",
179 tc.env, tc.args,
180 tc.remaining, c.arguments)
181 }
182 })
183 }
184}
Patrice Arruda13848222019-04-22 17:12:02 -0700185
186func TestConfigCheckTopDir(t *testing.T) {
187 ctx := testContext()
188 buildRootDir := filepath.Dir(srcDirFileCheck)
189 expectedErrStr := fmt.Sprintf("Current working directory must be the source tree. %q not found.", srcDirFileCheck)
190
191 tests := []struct {
192 // ********* Setup *********
193 // Test description.
194 description string
195
196 // ********* Action *********
197 // If set to true, the build root file is created.
198 rootBuildFile bool
199
200 // The current path where Soong is being executed.
201 path string
202
203 // ********* Validation *********
204 // Expecting error and validate the error string against expectedErrStr.
205 wantErr bool
206 }{{
207 description: "current directory is the root source tree",
208 rootBuildFile: true,
209 path: ".",
210 wantErr: false,
211 }, {
212 description: "one level deep in the source tree",
213 rootBuildFile: true,
214 path: "1",
215 wantErr: true,
216 }, {
217 description: "very deep in the source tree",
218 rootBuildFile: true,
219 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",
220 wantErr: true,
221 }, {
222 description: "outside of source tree",
223 rootBuildFile: false,
224 path: "1/2/3/4/5",
225 wantErr: true,
226 }}
227
228 for _, tt := range tests {
229 t.Run(tt.description, func(t *testing.T) {
230 defer logger.Recover(func(err error) {
231 if !tt.wantErr {
232 t.Fatalf("Got unexpected error: %v", err)
233 }
234 if expectedErrStr != err.Error() {
235 t.Fatalf("expected %s, got %s", expectedErrStr, err.Error())
236 }
237 })
238
239 // Create the root source tree.
240 rootDir, err := ioutil.TempDir("", "")
241 if err != nil {
242 t.Fatal(err)
243 }
244 defer os.RemoveAll(rootDir)
245
246 // Create the build root file. This is to test if topDir returns an error if the build root
247 // file does not exist.
248 if tt.rootBuildFile {
249 dir := filepath.Join(rootDir, buildRootDir)
250 if err := os.MkdirAll(dir, 0755); err != nil {
251 t.Errorf("failed to create %s directory: %v", dir, err)
252 }
253 f := filepath.Join(rootDir, srcDirFileCheck)
254 if err := ioutil.WriteFile(f, []byte{}, 0644); err != nil {
255 t.Errorf("failed to create file %s: %v", f, err)
256 }
257 }
258
259 // Next block of code is to set the current directory.
260 dir := rootDir
261 if tt.path != "" {
262 dir = filepath.Join(dir, tt.path)
263 if err := os.MkdirAll(dir, 0755); err != nil {
264 t.Errorf("failed to create %s directory: %v", dir, err)
265 }
266 }
267 curDir, err := os.Getwd()
268 if err != nil {
269 t.Fatalf("failed to get the current directory: %v", err)
270 }
271 defer func() { os.Chdir(curDir) }()
272
273 if err := os.Chdir(dir); err != nil {
274 t.Fatalf("failed to change directory to %s: %v", dir, err)
275 }
276
277 checkTopDir(ctx)
278 })
279 }
280}
281
282func TestConfigConvertToTarget(t *testing.T) {
283 tests := []struct {
284 // ********* Setup *********
285 // Test description.
286 description string
287
288 // ********* Action *********
289 // The current directory where Soong is being executed.
290 dir string
291
292 // The current prefix string to be pre-appended to the target.
293 prefix string
294
295 // ********* Validation *********
296 // The expected target to be invoked in ninja.
297 expectedTarget string
298 }{{
299 description: "one level directory in source tree",
300 dir: "test1",
301 prefix: "MODULES-IN-",
302 expectedTarget: "MODULES-IN-test1",
303 }, {
304 description: "multiple level directories in source tree",
305 dir: "test1/test2/test3/test4",
306 prefix: "GET-INSTALL-PATH-IN-",
307 expectedTarget: "GET-INSTALL-PATH-IN-test1-test2-test3-test4",
308 }}
309 for _, tt := range tests {
310 t.Run(tt.description, func(t *testing.T) {
311 target := convertToTarget(tt.dir, tt.prefix)
312 if target != tt.expectedTarget {
313 t.Errorf("expected %s, got %s for target", tt.expectedTarget, target)
314 }
315 })
316 }
317}
318
319func setTop(t *testing.T, dir string) func() {
320 curDir, err := os.Getwd()
321 if err != nil {
322 t.Fatalf("failed to get current directory: %v", err)
323 }
324 if err := os.Chdir(dir); err != nil {
325 t.Fatalf("failed to change directory to top dir %s: %v", dir, err)
326 }
327 return func() { os.Chdir(curDir) }
328}
329
330func createBuildFiles(t *testing.T, topDir string, buildFiles []string) {
331 for _, buildFile := range buildFiles {
332 buildFile = filepath.Join(topDir, buildFile)
333 if err := ioutil.WriteFile(buildFile, []byte{}, 0644); err != nil {
334 t.Errorf("failed to create file %s: %v", buildFile, err)
335 }
336 }
337}
338
339func createDirectories(t *testing.T, topDir string, dirs []string) {
340 for _, dir := range dirs {
341 dir = filepath.Join(topDir, dir)
342 if err := os.MkdirAll(dir, 0755); err != nil {
343 t.Errorf("failed to create %s directory: %v", dir, err)
344 }
345 }
346}
347
348func TestConfigGetTargets(t *testing.T) {
349 ctx := testContext()
350 tests := []struct {
351 // ********* Setup *********
352 // Test description.
353 description string
354
355 // Directories that exist in the source tree.
356 dirsInTrees []string
357
358 // Build files that exists in the source tree.
359 buildFiles []string
360
361 // ********* Action *********
362 // Directories passed in to soong_ui.
363 dirs []string
364
365 // Current directory that the user executed the build action command.
366 curDir string
367
368 // ********* Validation *********
369 // Expected targets from the function.
370 expectedTargets []string
371
Patrice Arruda13848222019-04-22 17:12:02 -0700372 // Expecting error from running test case.
373 errStr string
374 }{{
Dan Willemsence41e942019-07-29 23:39:30 -0700375 description: "one target dir specified",
376 dirsInTrees: []string{"0/1/2/3"},
377 buildFiles: []string{"0/1/2/3/Android.bp"},
378 dirs: []string{"1/2/3"},
379 curDir: "0",
380 expectedTargets: []string{"MODULES-IN-0-1-2-3"},
Patrice Arruda13848222019-04-22 17:12:02 -0700381 }, {
382 description: "one target dir specified, build file does not exist",
383 dirsInTrees: []string{"0/1/2/3"},
384 buildFiles: []string{},
385 dirs: []string{"1/2/3"},
386 curDir: "0",
387 errStr: "Build file not found for 0/1/2/3 directory",
388 }, {
389 description: "one target dir specified, invalid targets specified",
390 dirsInTrees: []string{"0/1/2/3"},
391 buildFiles: []string{},
392 dirs: []string{"1/2/3:t1:t2"},
393 curDir: "0",
394 errStr: "1/2/3:t1:t2 not in proper directory:target1,target2,... format (\":\" was specified more than once)",
395 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700396 description: "one target dir specified, no targets specified but has colon",
397 dirsInTrees: []string{"0/1/2/3"},
398 buildFiles: []string{"0/1/2/3/Android.bp"},
399 dirs: []string{"1/2/3:"},
400 curDir: "0",
401 expectedTargets: []string{"MODULES-IN-0-1-2-3"},
Patrice Arruda13848222019-04-22 17:12:02 -0700402 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700403 description: "one target dir specified, two targets specified",
404 dirsInTrees: []string{"0/1/2/3"},
405 buildFiles: []string{"0/1/2/3/Android.bp"},
406 dirs: []string{"1/2/3:t1,t2"},
407 curDir: "0",
408 expectedTargets: []string{"t1", "t2"},
Patrice Arruda13848222019-04-22 17:12:02 -0700409 }, {
410 description: "one target dir specified, no targets and has a comma",
411 dirsInTrees: []string{"0/1/2/3"},
412 buildFiles: []string{"0/1/2/3/Android.bp"},
413 dirs: []string{"1/2/3:,"},
414 curDir: "0",
415 errStr: "0/1/2/3 not in proper directory:target1,target2,... format",
416 }, {
417 description: "one target dir specified, improper targets defined",
418 dirsInTrees: []string{"0/1/2/3"},
419 buildFiles: []string{"0/1/2/3/Android.bp"},
420 dirs: []string{"1/2/3:,t1"},
421 curDir: "0",
422 errStr: "0/1/2/3 not in proper directory:target1,target2,... format",
423 }, {
424 description: "one target dir specified, blank target",
425 dirsInTrees: []string{"0/1/2/3"},
426 buildFiles: []string{"0/1/2/3/Android.bp"},
427 dirs: []string{"1/2/3:t1,"},
428 curDir: "0",
429 errStr: "0/1/2/3 not in proper directory:target1,target2,... format",
430 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700431 description: "one target dir specified, many targets specified",
432 dirsInTrees: []string{"0/1/2/3"},
433 buildFiles: []string{"0/1/2/3/Android.bp"},
434 dirs: []string{"1/2/3:t1,t2,t3,t4,t5,t6,t7,t8,t9,t10"},
435 curDir: "0",
436 expectedTargets: []string{"t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9", "t10"},
Patrice Arruda13848222019-04-22 17:12:02 -0700437 }, {
438 description: "one target dir specified, one target specified, build file does not exist",
439 dirsInTrees: []string{"0/1/2/3"},
440 buildFiles: []string{},
441 dirs: []string{"1/2/3:t1"},
442 curDir: "0",
Patrice Arruda9450d0b2019-07-08 11:06:46 -0700443 errStr: "Couldn't locate a build file from 0/1/2/3 directory",
Patrice Arruda13848222019-04-22 17:12:02 -0700444 }, {
445 description: "one target dir specified, one target specified, build file not in target dir",
446 dirsInTrees: []string{"0/1/2/3"},
447 buildFiles: []string{"0/1/2/Android.mk"},
448 dirs: []string{"1/2/3:t1"},
449 curDir: "0",
450 errStr: "Couldn't locate a build file from 0/1/2/3 directory",
451 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700452 description: "one target dir specified, build file not in target dir",
453 dirsInTrees: []string{"0/1/2/3"},
454 buildFiles: []string{"0/1/2/Android.mk"},
455 dirs: []string{"1/2/3"},
456 curDir: "0",
457 expectedTargets: []string{"MODULES-IN-0-1-2"},
Patrice Arruda13848222019-04-22 17:12:02 -0700458 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700459 description: "multiple targets dir specified, targets specified",
460 dirsInTrees: []string{"0/1/2/3", "0/3/4"},
461 buildFiles: []string{"0/1/2/3/Android.bp", "0/3/4/Android.mk"},
462 dirs: []string{"1/2/3:t1,t2", "3/4:t3,t4,t5"},
463 curDir: "0",
464 expectedTargets: []string{"t1", "t2", "t3", "t4", "t5"},
Patrice Arruda13848222019-04-22 17:12:02 -0700465 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700466 description: "multiple targets dir specified, one directory has targets specified",
467 dirsInTrees: []string{"0/1/2/3", "0/3/4"},
468 buildFiles: []string{"0/1/2/3/Android.bp", "0/3/4/Android.mk"},
469 dirs: []string{"1/2/3:t1,t2", "3/4"},
470 curDir: "0",
471 expectedTargets: []string{"t1", "t2", "MODULES-IN-0-3-4"},
Patrice Arruda13848222019-04-22 17:12:02 -0700472 }, {
473 description: "two dirs specified, only one dir exist",
474 dirsInTrees: []string{"0/1/2/3"},
475 buildFiles: []string{"0/1/2/3/Android.mk"},
476 dirs: []string{"1/2/3:t1", "3/4"},
477 curDir: "0",
478 errStr: "couldn't find directory 0/3/4",
479 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700480 description: "multiple targets dirs specified at root source tree",
481 dirsInTrees: []string{"0/1/2/3", "0/3/4"},
482 buildFiles: []string{"0/1/2/3/Android.bp", "0/3/4/Android.mk"},
483 dirs: []string{"0/1/2/3:t1,t2", "0/3/4"},
484 curDir: ".",
485 expectedTargets: []string{"t1", "t2", "MODULES-IN-0-3-4"},
Patrice Arruda13848222019-04-22 17:12:02 -0700486 }, {
487 description: "no directories specified",
488 dirsInTrees: []string{"0/1/2/3", "0/3/4"},
489 buildFiles: []string{"0/1/2/3/Android.bp", "0/3/4/Android.mk"},
490 dirs: []string{},
491 curDir: ".",
492 }}
493 for _, tt := range tests {
494 t.Run(tt.description, func(t *testing.T) {
495 defer logger.Recover(func(err error) {
496 if tt.errStr == "" {
497 t.Fatalf("Got unexpected error: %v", err)
498 }
499 if tt.errStr != err.Error() {
500 t.Errorf("expected %s, got %s", tt.errStr, err.Error())
501 }
502 })
503
504 // Create the root source tree.
505 topDir, err := ioutil.TempDir("", "")
506 if err != nil {
507 t.Fatalf("failed to create temp dir: %v", err)
508 }
509 defer os.RemoveAll(topDir)
510
511 createDirectories(t, topDir, tt.dirsInTrees)
512 createBuildFiles(t, topDir, tt.buildFiles)
513 r := setTop(t, topDir)
514 defer r()
515
Dan Willemsence41e942019-07-29 23:39:30 -0700516 targets := getTargetsFromDirs(ctx, tt.curDir, tt.dirs, "MODULES-IN-")
Patrice Arruda13848222019-04-22 17:12:02 -0700517 if !reflect.DeepEqual(targets, tt.expectedTargets) {
518 t.Errorf("expected %v, got %v for targets", tt.expectedTargets, targets)
519 }
Patrice Arruda13848222019-04-22 17:12:02 -0700520
521 // If the execution reached here and there was an expected error code, the unit test case failed.
522 if tt.errStr != "" {
523 t.Errorf("expecting error %s", tt.errStr)
524 }
525 })
526 }
527}
528
529func TestConfigFindBuildFile(t *testing.T) {
530 ctx := testContext()
531
532 tests := []struct {
533 // ********* Setup *********
534 // Test description.
535 description string
536
537 // Array of build files to create in dir.
538 buildFiles []string
539
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700540 // Directories that exist in the source tree.
541 dirsInTrees []string
542
Patrice Arruda13848222019-04-22 17:12:02 -0700543 // ********* Action *********
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700544 // The base directory is where findBuildFile is invoked.
Patrice Arruda13848222019-04-22 17:12:02 -0700545 dir string
546
547 // ********* Validation *********
548 // Expected build file path to find.
549 expectedBuildFile string
550 }{{
551 description: "build file exists at leaf directory",
552 buildFiles: []string{"1/2/3/Android.bp"},
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700553 dirsInTrees: []string{"1/2/3"},
Patrice Arruda13848222019-04-22 17:12:02 -0700554 dir: "1/2/3",
555 expectedBuildFile: "1/2/3/Android.mk",
556 }, {
557 description: "build file exists in all directory paths",
558 buildFiles: []string{"1/Android.mk", "1/2/Android.mk", "1/2/3/Android.mk"},
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700559 dirsInTrees: []string{"1/2/3"},
Patrice Arruda13848222019-04-22 17:12:02 -0700560 dir: "1/2/3",
561 expectedBuildFile: "1/2/3/Android.mk",
562 }, {
563 description: "build file does not exist in all directory paths",
564 buildFiles: []string{},
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700565 dirsInTrees: []string{"1/2/3"},
Patrice Arruda13848222019-04-22 17:12:02 -0700566 dir: "1/2/3",
567 expectedBuildFile: "",
568 }, {
569 description: "build file exists only at top directory",
570 buildFiles: []string{"Android.bp"},
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700571 dirsInTrees: []string{"1/2/3"},
Patrice Arruda13848222019-04-22 17:12:02 -0700572 dir: "1/2/3",
573 expectedBuildFile: "",
574 }, {
575 description: "build file exist in a subdirectory",
576 buildFiles: []string{"1/2/Android.bp"},
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700577 dirsInTrees: []string{"1/2/3"},
Patrice Arruda13848222019-04-22 17:12:02 -0700578 dir: "1/2/3",
579 expectedBuildFile: "1/2/Android.mk",
580 }, {
581 description: "build file exists in a subdirectory",
582 buildFiles: []string{"1/Android.mk"},
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700583 dirsInTrees: []string{"1/2/3"},
Patrice Arruda13848222019-04-22 17:12:02 -0700584 dir: "1/2/3",
585 expectedBuildFile: "1/Android.mk",
586 }, {
587 description: "top directory",
588 buildFiles: []string{"Android.bp"},
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700589 dirsInTrees: []string{},
Patrice Arruda13848222019-04-22 17:12:02 -0700590 dir: ".",
591 expectedBuildFile: "",
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700592 }, {
593 description: "build file exists in subdirectory",
594 buildFiles: []string{"1/2/3/Android.bp", "1/2/4/Android.bp"},
595 dirsInTrees: []string{"1/2/3", "1/2/4"},
596 dir: "1/2",
597 expectedBuildFile: "1/2/Android.mk",
598 }, {
599 description: "build file exists in parent subdirectory",
600 buildFiles: []string{"1/5/Android.bp"},
601 dirsInTrees: []string{"1/2/3", "1/2/4", "1/5"},
602 dir: "1/2",
603 expectedBuildFile: "1/Android.mk",
604 }, {
605 description: "build file exists in deep parent's subdirectory.",
606 buildFiles: []string{"1/5/6/Android.bp"},
607 dirsInTrees: []string{"1/2/3", "1/2/4", "1/5/6", "1/5/7"},
608 dir: "1/2",
609 expectedBuildFile: "1/Android.mk",
Patrice Arruda13848222019-04-22 17:12:02 -0700610 }}
611
612 for _, tt := range tests {
613 t.Run(tt.description, func(t *testing.T) {
614 defer logger.Recover(func(err error) {
615 t.Fatalf("Got unexpected error: %v", err)
616 })
617
618 topDir, err := ioutil.TempDir("", "")
619 if err != nil {
620 t.Fatalf("failed to create temp dir: %v", err)
621 }
622 defer os.RemoveAll(topDir)
623
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700624 createDirectories(t, topDir, tt.dirsInTrees)
Patrice Arruda13848222019-04-22 17:12:02 -0700625 createBuildFiles(t, topDir, tt.buildFiles)
626
627 curDir, err := os.Getwd()
628 if err != nil {
629 t.Fatalf("Could not get working directory: %v", err)
630 }
631 defer func() { os.Chdir(curDir) }()
632 if err := os.Chdir(topDir); err != nil {
633 t.Fatalf("Could not change top dir to %s: %v", topDir, err)
634 }
635
636 buildFile := findBuildFile(ctx, tt.dir)
637 if buildFile != tt.expectedBuildFile {
638 t.Errorf("expected %q, got %q for build file", tt.expectedBuildFile, buildFile)
639 }
640 })
641 }
642}
643
644func TestConfigSplitArgs(t *testing.T) {
645 tests := []struct {
646 // ********* Setup *********
647 // Test description.
648 description string
649
650 // ********* Action *********
651 // Arguments passed in to soong_ui.
652 args []string
653
654 // ********* Validation *********
655 // Expected newArgs list after extracting the directories.
656 expectedNewArgs []string
657
658 // Expected directories
659 expectedDirs []string
660 }{{
661 description: "flags but no directories specified",
662 args: []string{"showcommands", "-j", "-k"},
663 expectedNewArgs: []string{"showcommands", "-j", "-k"},
664 expectedDirs: []string{},
665 }, {
666 description: "flags and one directory specified",
667 args: []string{"snod", "-j", "dir:target1,target2"},
668 expectedNewArgs: []string{"snod", "-j"},
669 expectedDirs: []string{"dir:target1,target2"},
670 }, {
671 description: "flags and directories specified",
672 args: []string{"dist", "-k", "dir1", "dir2:target1,target2"},
673 expectedNewArgs: []string{"dist", "-k"},
674 expectedDirs: []string{"dir1", "dir2:target1,target2"},
675 }, {
676 description: "only directories specified",
677 args: []string{"dir1", "dir2", "dir3:target1,target2"},
678 expectedNewArgs: []string{},
679 expectedDirs: []string{"dir1", "dir2", "dir3:target1,target2"},
680 }}
681 for _, tt := range tests {
682 t.Run(tt.description, func(t *testing.T) {
683 args, dirs := splitArgs(tt.args)
684 if !reflect.DeepEqual(tt.expectedNewArgs, args) {
685 t.Errorf("expected %v, got %v for arguments", tt.expectedNewArgs, args)
686 }
687 if !reflect.DeepEqual(tt.expectedDirs, dirs) {
688 t.Errorf("expected %v, got %v for directories", tt.expectedDirs, dirs)
689 }
690 })
691 }
692}
693
694type envVar struct {
695 name string
696 value string
697}
698
699type buildActionTestCase struct {
700 // ********* Setup *********
701 // Test description.
702 description string
703
704 // Directories that exist in the source tree.
705 dirsInTrees []string
706
707 // Build files that exists in the source tree.
708 buildFiles []string
709
Patrice Arrudababa9a92019-07-03 10:47:34 -0700710 // Create root symlink that points to topDir.
711 rootSymlink bool
712
Patrice Arruda13848222019-04-22 17:12:02 -0700713 // ********* Action *********
714 // Arguments passed in to soong_ui.
715 args []string
716
717 // Directory where the build action was invoked.
718 curDir string
719
720 // WITH_TIDY_ONLY environment variable specified.
721 tidyOnly string
722
723 // ********* Validation *********
724 // Expected arguments to be in Config instance.
725 expectedArgs []string
726
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700727 // Expecting error from running test case.
728 expectedErrStr string
Patrice Arruda13848222019-04-22 17:12:02 -0700729}
730
Dan Willemsence41e942019-07-29 23:39:30 -0700731func testGetConfigArgs(t *testing.T, tt buildActionTestCase, action BuildAction) {
Patrice Arruda13848222019-04-22 17:12:02 -0700732 ctx := testContext()
733
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700734 defer logger.Recover(func(err error) {
735 if tt.expectedErrStr == "" {
736 t.Fatalf("Got unexpected error: %v", err)
737 }
738 if tt.expectedErrStr != err.Error() {
739 t.Errorf("expected %s, got %s", tt.expectedErrStr, err.Error())
740 }
741 })
742
Patrice Arruda13848222019-04-22 17:12:02 -0700743 // Environment variables to set it to blank on every test case run.
744 resetEnvVars := []string{
Patrice Arruda13848222019-04-22 17:12:02 -0700745 "WITH_TIDY_ONLY",
746 }
747
748 for _, name := range resetEnvVars {
749 if err := os.Unsetenv(name); err != nil {
750 t.Fatalf("failed to unset environment variable %s: %v", name, err)
751 }
752 }
753 if tt.tidyOnly != "" {
754 if err := os.Setenv("WITH_TIDY_ONLY", tt.tidyOnly); err != nil {
755 t.Errorf("failed to set WITH_TIDY_ONLY to %s: %v", tt.tidyOnly, err)
756 }
757 }
758
759 // Create the root source tree.
760 topDir, err := ioutil.TempDir("", "")
761 if err != nil {
762 t.Fatalf("failed to create temp dir: %v", err)
763 }
764 defer os.RemoveAll(topDir)
765
766 createDirectories(t, topDir, tt.dirsInTrees)
767 createBuildFiles(t, topDir, tt.buildFiles)
768
Patrice Arrudababa9a92019-07-03 10:47:34 -0700769 if tt.rootSymlink {
770 // Create a secondary root source tree which points to the true root source tree.
771 symlinkTopDir, err := ioutil.TempDir("", "")
772 if err != nil {
773 t.Fatalf("failed to create symlink temp dir: %v", err)
774 }
775 defer os.RemoveAll(symlinkTopDir)
776
777 symlinkTopDir = filepath.Join(symlinkTopDir, "root")
778 err = os.Symlink(topDir, symlinkTopDir)
779 if err != nil {
780 t.Fatalf("failed to create symlink: %v", err)
781 }
782 topDir = symlinkTopDir
783 }
784
Patrice Arruda13848222019-04-22 17:12:02 -0700785 r := setTop(t, topDir)
786 defer r()
787
788 // The next block is to create the root build file.
789 rootBuildFileDir := filepath.Dir(srcDirFileCheck)
790 if err := os.MkdirAll(rootBuildFileDir, 0755); err != nil {
791 t.Fatalf("Failed to create %s directory: %v", rootBuildFileDir, err)
792 }
793
794 if err := ioutil.WriteFile(srcDirFileCheck, []byte{}, 0644); err != nil {
795 t.Fatalf("failed to create %s file: %v", srcDirFileCheck, err)
796 }
797
Dan Willemsence41e942019-07-29 23:39:30 -0700798 args := getConfigArgs(action, tt.curDir, ctx, tt.args)
Patrice Arruda13848222019-04-22 17:12:02 -0700799 if !reflect.DeepEqual(tt.expectedArgs, args) {
800 t.Fatalf("expected %v, got %v for config arguments", tt.expectedArgs, args)
801 }
802
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700803 // If the execution reached here and there was an expected error code, the unit test case failed.
804 if tt.expectedErrStr != "" {
805 t.Errorf("expecting error %s", tt.expectedErrStr)
806 }
Patrice Arruda13848222019-04-22 17:12:02 -0700807}
808
Patrice Arruda39282062019-06-20 16:35:12 -0700809func TestGetConfigArgsBuildModules(t *testing.T) {
810 tests := []buildActionTestCase{{
Dan Willemsence41e942019-07-29 23:39:30 -0700811 description: "normal execution from the root source tree directory",
812 dirsInTrees: []string{"0/1/2", "0/2", "0/3"},
813 buildFiles: []string{"0/1/2/Android.mk", "0/2/Android.bp", "0/3/Android.mk"},
814 args: []string{"-j", "fake_module", "fake_module2"},
815 curDir: ".",
816 tidyOnly: "",
817 expectedArgs: []string{"-j", "fake_module", "fake_module2"},
Patrice Arruda39282062019-06-20 16:35:12 -0700818 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700819 description: "normal execution in deep directory",
820 dirsInTrees: []string{"0/1/2", "0/2", "0/3", "1/2/3/4/5/6/7/8/9/1/2/3/4/5/6"},
821 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"},
822 args: []string{"-j", "fake_module", "fake_module2", "-k"},
823 curDir: "1/2/3/4/5/6/7/8/9",
824 tidyOnly: "",
825 expectedArgs: []string{"-j", "fake_module", "fake_module2", "-k"},
Patrice Arruda39282062019-06-20 16:35:12 -0700826 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700827 description: "normal execution in deep directory, no targets",
828 dirsInTrees: []string{"0/1/2", "0/2", "0/3", "1/2/3/4/5/6/7/8/9/1/2/3/4/5/6"},
829 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"},
830 args: []string{"-j", "-k"},
831 curDir: "1/2/3/4/5/6/7/8/9",
832 tidyOnly: "",
833 expectedArgs: []string{"-j", "-k"},
Patrice Arruda39282062019-06-20 16:35:12 -0700834 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700835 description: "normal execution in root source tree, no args",
836 dirsInTrees: []string{"0/1/2", "0/2", "0/3"},
837 buildFiles: []string{"0/1/2/Android.mk", "0/2/Android.bp"},
838 args: []string{},
839 curDir: "0/2",
840 tidyOnly: "",
841 expectedArgs: []string{},
Patrice Arrudababa9a92019-07-03 10:47:34 -0700842 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700843 description: "normal execution in symlink root source tree, no args",
844 dirsInTrees: []string{"0/1/2", "0/2", "0/3"},
845 buildFiles: []string{"0/1/2/Android.mk", "0/2/Android.bp"},
846 rootSymlink: true,
847 args: []string{},
848 curDir: "0/2",
849 tidyOnly: "",
850 expectedArgs: []string{},
Patrice Arruda39282062019-06-20 16:35:12 -0700851 }}
852 for _, tt := range tests {
853 t.Run("build action BUILD_MODULES with dependencies, "+tt.description, func(t *testing.T) {
Dan Willemsence41e942019-07-29 23:39:30 -0700854 testGetConfigArgs(t, tt, BUILD_MODULES)
Patrice Arruda13848222019-04-22 17:12:02 -0700855 })
856 }
857}
858
859func TestGetConfigArgsBuildModulesInDirectory(t *testing.T) {
860 tests := []buildActionTestCase{{
Dan Willemsence41e942019-07-29 23:39:30 -0700861 description: "normal execution in a directory",
862 dirsInTrees: []string{"0/1/2"},
863 buildFiles: []string{"0/1/2/Android.mk"},
864 args: []string{"fake-module"},
865 curDir: "0/1/2",
866 tidyOnly: "",
867 expectedArgs: []string{"fake-module", "MODULES-IN-0-1-2"},
Patrice Arruda13848222019-04-22 17:12:02 -0700868 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700869 description: "build file in parent directory",
870 dirsInTrees: []string{"0/1/2"},
871 buildFiles: []string{"0/1/Android.mk"},
872 args: []string{},
873 curDir: "0/1/2",
874 tidyOnly: "",
875 expectedArgs: []string{"MODULES-IN-0-1"},
Patrice Arruda13848222019-04-22 17:12:02 -0700876 },
877 {
Dan Willemsence41e942019-07-29 23:39:30 -0700878 description: "build file in parent directory, multiple module names passed in",
879 dirsInTrees: []string{"0/1/2"},
880 buildFiles: []string{"0/1/Android.mk"},
881 args: []string{"fake-module1", "fake-module2", "fake-module3"},
882 curDir: "0/1/2",
883 tidyOnly: "",
884 expectedArgs: []string{"fake-module1", "fake-module2", "fake-module3", "MODULES-IN-0-1"},
Patrice Arruda13848222019-04-22 17:12:02 -0700885 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700886 description: "build file in 2nd level parent directory",
887 dirsInTrees: []string{"0/1/2"},
888 buildFiles: []string{"0/Android.bp"},
889 args: []string{},
890 curDir: "0/1/2",
891 tidyOnly: "",
892 expectedArgs: []string{"MODULES-IN-0"},
Patrice Arruda13848222019-04-22 17:12:02 -0700893 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700894 description: "build action executed at root directory",
895 dirsInTrees: []string{},
896 buildFiles: []string{},
897 rootSymlink: false,
898 args: []string{},
899 curDir: ".",
900 tidyOnly: "",
901 expectedArgs: []string{},
Patrice Arrudababa9a92019-07-03 10:47:34 -0700902 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700903 description: "build action executed at root directory in symlink",
904 dirsInTrees: []string{},
905 buildFiles: []string{},
906 rootSymlink: true,
907 args: []string{},
908 curDir: ".",
909 tidyOnly: "",
910 expectedArgs: []string{},
Patrice Arruda13848222019-04-22 17:12:02 -0700911 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700912 description: "build file not found",
913 dirsInTrees: []string{"0/1/2"},
914 buildFiles: []string{},
915 args: []string{},
916 curDir: "0/1/2",
917 tidyOnly: "",
918 expectedArgs: []string{"MODULES-IN-0-1-2"},
919 expectedErrStr: "Build file not found for 0/1/2 directory",
Patrice Arruda13848222019-04-22 17:12:02 -0700920 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700921 description: "GET-INSTALL-PATH specified,",
922 dirsInTrees: []string{"0/1/2"},
923 buildFiles: []string{"0/1/Android.mk"},
924 args: []string{"GET-INSTALL-PATH", "-j", "-k", "GET-INSTALL-PATH"},
925 curDir: "0/1/2",
926 tidyOnly: "",
927 expectedArgs: []string{"-j", "-k", "GET-INSTALL-PATH-IN-0-1"},
Patrice Arruda13848222019-04-22 17:12:02 -0700928 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700929 description: "tidy only environment variable specified,",
930 dirsInTrees: []string{"0/1/2"},
931 buildFiles: []string{"0/1/Android.mk"},
932 args: []string{"GET-INSTALL-PATH"},
933 curDir: "0/1/2",
934 tidyOnly: "true",
935 expectedArgs: []string{"tidy_only"},
Patrice Arruda13848222019-04-22 17:12:02 -0700936 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700937 description: "normal execution in root directory with args",
938 dirsInTrees: []string{},
939 buildFiles: []string{},
940 args: []string{"-j", "-k", "fake_module"},
941 curDir: "",
942 tidyOnly: "",
943 expectedArgs: []string{"-j", "-k", "fake_module"},
Patrice Arruda13848222019-04-22 17:12:02 -0700944 }}
945 for _, tt := range tests {
946 t.Run("build action BUILD_MODULES_IN_DIR, "+tt.description, func(t *testing.T) {
Dan Willemsence41e942019-07-29 23:39:30 -0700947 testGetConfigArgs(t, tt, BUILD_MODULES_IN_A_DIRECTORY)
Patrice Arruda13848222019-04-22 17:12:02 -0700948 })
949 }
950}
951
952func TestGetConfigArgsBuildModulesInDirectories(t *testing.T) {
953 tests := []buildActionTestCase{{
954 description: "normal execution in a directory",
955 dirsInTrees: []string{"0/1/2/3.1", "0/1/2/3.2", "0/1/2/3.3"},
956 buildFiles: []string{"0/1/2/3.1/Android.bp", "0/1/2/3.2/Android.bp", "0/1/2/3.3/Android.bp"},
957 args: []string{"3.1/", "3.2/", "3.3/"},
958 curDir: "0/1/2",
959 tidyOnly: "",
960 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 -0700961 }, {
962 description: "GET-INSTALL-PATH specified",
963 dirsInTrees: []string{"0/1/2/3.1", "0/1/2/3.2", "0/1/3"},
964 buildFiles: []string{"0/1/2/3.1/Android.bp", "0/1/2/3.2/Android.bp", "0/1/Android.bp"},
965 args: []string{"GET-INSTALL-PATH", "2/3.1/", "2/3.2", "3"},
966 curDir: "0/1",
967 tidyOnly: "",
968 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 -0700969 }, {
970 description: "tidy only environment variable specified",
971 dirsInTrees: []string{"0/1/2/3.1", "0/1/2/3.2", "0/1/2/3.3"},
972 buildFiles: []string{"0/1/2/3.1/Android.bp", "0/1/2/3.2/Android.bp", "0/1/2/3.3/Android.bp"},
973 args: []string{"GET-INSTALL-PATH", "3.1/", "3.2/", "3.3"},
974 curDir: "0/1/2",
975 tidyOnly: "1",
976 expectedArgs: []string{"tidy_only"},
Patrice Arruda13848222019-04-22 17:12:02 -0700977 }, {
978 description: "normal execution from top dir directory",
979 dirsInTrees: []string{"0/1/2/3.1", "0/1/2/3.2", "0/1/3", "0/2"},
980 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 -0700981 rootSymlink: false,
982 args: []string{"0/1/2/3.1", "0/1/2/3.2", "0/1/3", "0/2"},
983 curDir: ".",
984 tidyOnly: "",
985 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 -0700986 }, {
987 description: "normal execution from top dir directory in symlink",
988 dirsInTrees: []string{"0/1/2/3.1", "0/1/2/3.2", "0/1/3", "0/2"},
989 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"},
990 rootSymlink: true,
Patrice Arruda13848222019-04-22 17:12:02 -0700991 args: []string{"0/1/2/3.1", "0/1/2/3.2", "0/1/3", "0/2"},
992 curDir: ".",
993 tidyOnly: "",
994 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 -0700995 }}
996 for _, tt := range tests {
997 t.Run("build action BUILD_MODULES_IN_DIRS, "+tt.description, func(t *testing.T) {
Dan Willemsence41e942019-07-29 23:39:30 -0700998 testGetConfigArgs(t, tt, BUILD_MODULES_IN_DIRECTORIES)
Patrice Arruda13848222019-04-22 17:12:02 -0700999 })
1000 }
1001}
Liz Kammerca9cb2e2021-07-14 15:29:57 -04001002
1003func TestBuildConfig(t *testing.T) {
1004 tests := []struct {
1005 name string
1006 environ Environment
Yu Liue737a992021-10-04 13:21:41 -07001007 arguments []string
Liz Kammerca9cb2e2021-07-14 15:29:57 -04001008 useBazel bool
Chris Parsonsef615e52022-08-18 22:04:11 -04001009 bazelDevMode bool
1010 bazelProdMode bool
MarkDacekb78465d2022-10-18 20:10:16 +00001011 bazelStagingMode bool
Liz Kammerca9cb2e2021-07-14 15:29:57 -04001012 expectedBuildConfig *smpb.BuildConfig
1013 }{
1014 {
1015 name: "none set",
1016 environ: Environment{},
1017 expectedBuildConfig: &smpb.BuildConfig{
1018 ForceUseGoma: proto.Bool(false),
1019 UseGoma: proto.Bool(false),
1020 UseRbe: proto.Bool(false),
Liz Kammerca9cb2e2021-07-14 15:29:57 -04001021 BazelMixedBuild: proto.Bool(false),
1022 },
1023 },
1024 {
1025 name: "force use goma",
1026 environ: Environment{"FORCE_USE_GOMA=1"},
1027 expectedBuildConfig: &smpb.BuildConfig{
1028 ForceUseGoma: proto.Bool(true),
1029 UseGoma: proto.Bool(false),
1030 UseRbe: proto.Bool(false),
Liz Kammerca9cb2e2021-07-14 15:29:57 -04001031 BazelMixedBuild: proto.Bool(false),
1032 },
1033 },
1034 {
1035 name: "use goma",
1036 environ: Environment{"USE_GOMA=1"},
1037 expectedBuildConfig: &smpb.BuildConfig{
1038 ForceUseGoma: proto.Bool(false),
1039 UseGoma: proto.Bool(true),
1040 UseRbe: proto.Bool(false),
Liz Kammerca9cb2e2021-07-14 15:29:57 -04001041 BazelMixedBuild: proto.Bool(false),
1042 },
1043 },
1044 {
1045 name: "use rbe",
1046 environ: Environment{"USE_RBE=1"},
1047 expectedBuildConfig: &smpb.BuildConfig{
1048 ForceUseGoma: proto.Bool(false),
1049 UseGoma: proto.Bool(false),
1050 UseRbe: proto.Bool(true),
Liz Kammerca9cb2e2021-07-14 15:29:57 -04001051 BazelMixedBuild: proto.Bool(false),
1052 },
1053 },
1054 {
1055 name: "use bazel as ninja",
1056 environ: Environment{},
1057 useBazel: true,
1058 expectedBuildConfig: &smpb.BuildConfig{
1059 ForceUseGoma: proto.Bool(false),
1060 UseGoma: proto.Bool(false),
1061 UseRbe: proto.Bool(false),
Liz Kammerca9cb2e2021-07-14 15:29:57 -04001062 BazelMixedBuild: proto.Bool(false),
1063 },
1064 },
1065 {
Chris Parsonsef615e52022-08-18 22:04:11 -04001066 name: "bazel mixed build from dev mode",
1067 environ: Environment{},
1068 bazelDevMode: true,
1069 expectedBuildConfig: &smpb.BuildConfig{
1070 ForceUseGoma: proto.Bool(false),
1071 UseGoma: proto.Bool(false),
1072 UseRbe: proto.Bool(false),
Chris Parsonsef615e52022-08-18 22:04:11 -04001073 BazelMixedBuild: proto.Bool(true),
1074 },
1075 },
1076 {
1077 name: "bazel mixed build from prod mode",
1078 environ: Environment{},
1079 bazelProdMode: true,
1080 expectedBuildConfig: &smpb.BuildConfig{
1081 ForceUseGoma: proto.Bool(false),
1082 UseGoma: proto.Bool(false),
1083 UseRbe: proto.Bool(false),
Chris Parsonsef615e52022-08-18 22:04:11 -04001084 BazelMixedBuild: proto.Bool(true),
1085 },
1086 },
1087 {
MarkDacekb78465d2022-10-18 20:10:16 +00001088 name: "bazel mixed build from staging mode",
1089 environ: Environment{},
1090 bazelStagingMode: true,
1091 expectedBuildConfig: &smpb.BuildConfig{
1092 ForceUseGoma: proto.Bool(false),
1093 UseGoma: proto.Bool(false),
1094 UseRbe: proto.Bool(false),
1095 BazelMixedBuild: proto.Bool(true),
1096 },
1097 },
1098 {
Yu Liue737a992021-10-04 13:21:41 -07001099 name: "specified targets",
1100 environ: Environment{},
1101 useBazel: true,
1102 arguments: []string{"droid", "dist"},
1103 expectedBuildConfig: &smpb.BuildConfig{
1104 ForceUseGoma: proto.Bool(false),
1105 UseGoma: proto.Bool(false),
1106 UseRbe: proto.Bool(false),
Yu Liue737a992021-10-04 13:21:41 -07001107 BazelMixedBuild: proto.Bool(false),
1108 Targets: []string{"droid", "dist"},
1109 },
1110 },
1111 {
Liz Kammerca9cb2e2021-07-14 15:29:57 -04001112 name: "all set",
1113 environ: Environment{
1114 "FORCE_USE_GOMA=1",
1115 "USE_GOMA=1",
1116 "USE_RBE=1",
Liz Kammerca9cb2e2021-07-14 15:29:57 -04001117 },
Chris Parsonsef615e52022-08-18 22:04:11 -04001118 useBazel: true,
1119 bazelDevMode: true,
Liz Kammerca9cb2e2021-07-14 15:29:57 -04001120 expectedBuildConfig: &smpb.BuildConfig{
1121 ForceUseGoma: proto.Bool(true),
1122 UseGoma: proto.Bool(true),
1123 UseRbe: proto.Bool(true),
Liz Kammerca9cb2e2021-07-14 15:29:57 -04001124 BazelMixedBuild: proto.Bool(true),
1125 },
1126 },
1127 }
1128
Chris Parsonsef615e52022-08-18 22:04:11 -04001129 ctx := testContext()
Liz Kammerca9cb2e2021-07-14 15:29:57 -04001130 for _, tc := range tests {
1131 t.Run(tc.name, func(t *testing.T) {
1132 c := &configImpl{
MarkDacekb78465d2022-10-18 20:10:16 +00001133 environ: &tc.environ,
1134 bazelDevMode: tc.bazelDevMode,
1135 bazelProdMode: tc.bazelProdMode,
1136 bazelStagingMode: tc.bazelStagingMode,
1137 arguments: tc.arguments,
Liz Kammerca9cb2e2021-07-14 15:29:57 -04001138 }
1139 config := Config{c}
Chris Parsonsef615e52022-08-18 22:04:11 -04001140 checkBazelMode(ctx, config)
Liz Kammerca9cb2e2021-07-14 15:29:57 -04001141 actualBuildConfig := buildConfig(config)
1142 if expected := tc.expectedBuildConfig; !proto.Equal(expected, actualBuildConfig) {
Chris Parsonsef615e52022-08-18 22:04:11 -04001143 t.Errorf("Build config mismatch.\n"+
1144 "Expected build config: %#v\n"+
1145 "Actual build config: %#v", prototext.Format(expected), prototext.Format(actualBuildConfig))
Liz Kammerca9cb2e2021-07-14 15:29:57 -04001146 }
1147 })
1148 }
1149}
Yu Liu6e13b402021-07-27 14:29:06 -07001150
1151func TestGetMetricsUploaderApp(t *testing.T) {
1152
1153 metricsUploaderDir := "metrics_uploader_dir"
1154 metricsUploaderBinary := "metrics_uploader_binary"
1155 metricsUploaderPath := filepath.Join(metricsUploaderDir, metricsUploaderBinary)
1156 tests := []struct {
1157 description string
1158 environ Environment
1159 createFiles bool
1160 expected string
1161 }{{
1162 description: "Uploader binary exist",
1163 environ: Environment{"METRICS_UPLOADER=" + metricsUploaderPath},
1164 createFiles: true,
1165 expected: metricsUploaderPath,
1166 }, {
1167 description: "Uploader binary not exist",
1168 environ: Environment{"METRICS_UPLOADER=" + metricsUploaderPath},
1169 createFiles: false,
1170 expected: "",
1171 }, {
1172 description: "Uploader binary variable not set",
1173 createFiles: true,
1174 expected: "",
1175 }}
1176
1177 for _, tt := range tests {
1178 t.Run(tt.description, func(t *testing.T) {
1179 defer logger.Recover(func(err error) {
1180 t.Fatalf("got unexpected error: %v", err)
1181 })
1182
1183 // Create the root source tree.
1184 topDir, err := ioutil.TempDir("", "")
1185 if err != nil {
1186 t.Fatalf("failed to create temp dir: %v", err)
1187 }
1188 defer os.RemoveAll(topDir)
1189
1190 expected := tt.expected
1191 if len(expected) > 0 {
1192 expected = filepath.Join(topDir, expected)
1193 }
1194
1195 if tt.createFiles {
1196 if err := os.MkdirAll(filepath.Join(topDir, metricsUploaderDir), 0755); err != nil {
1197 t.Errorf("failed to create %s directory: %v", metricsUploaderDir, err)
1198 }
1199 if err := ioutil.WriteFile(filepath.Join(topDir, metricsUploaderPath), []byte{}, 0644); err != nil {
1200 t.Errorf("failed to create file %s: %v", expected, err)
1201 }
1202 }
1203
1204 actual := GetMetricsUploader(topDir, &tt.environ)
1205
1206 if actual != expected {
1207 t.Errorf("expecting: %s, actual: %s", expected, actual)
1208 }
1209 })
1210 }
1211}