blob: e293275720573d0c66c71690bfe3e65ad0223e62 [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"
Liz Kammerca9cb2e2021-07-14 15:29:57 -040031
Dan Willemsen4591b642021-05-24 14:24:12 -070032 "google.golang.org/protobuf/proto"
Dan Willemsen9b587492017-07-10 22:13:00 -070033)
34
35func testContext() Context {
36 return Context{&ContextImpl{
Dan Willemsenb82471a2018-05-17 16:37:09 -070037 Context: context.Background(),
38 Logger: logger.New(&bytes.Buffer{}),
Colin Cross097ed2a2019-06-08 21:48:58 -070039 Writer: &bytes.Buffer{},
Patrice Arruda219eef32020-06-01 17:29:30 +000040 Status: &status.Status{},
Dan Willemsen9b587492017-07-10 22:13:00 -070041 }}
42}
43
44func TestConfigParseArgsJK(t *testing.T) {
45 ctx := testContext()
46
47 testCases := []struct {
48 args []string
49
50 parallel int
51 keepGoing int
52 remaining []string
53 }{
54 {nil, -1, -1, nil},
55
56 {[]string{"-j"}, -1, -1, nil},
57 {[]string{"-j1"}, 1, -1, nil},
58 {[]string{"-j1234"}, 1234, -1, nil},
59
60 {[]string{"-j", "1"}, 1, -1, nil},
61 {[]string{"-j", "1234"}, 1234, -1, nil},
62 {[]string{"-j", "1234", "abc"}, 1234, -1, []string{"abc"}},
63 {[]string{"-j", "abc"}, -1, -1, []string{"abc"}},
64 {[]string{"-j", "1abc"}, -1, -1, []string{"1abc"}},
65
66 {[]string{"-k"}, -1, 0, nil},
67 {[]string{"-k0"}, -1, 0, nil},
68 {[]string{"-k1"}, -1, 1, nil},
69 {[]string{"-k1234"}, -1, 1234, nil},
70
71 {[]string{"-k", "0"}, -1, 0, nil},
72 {[]string{"-k", "1"}, -1, 1, nil},
73 {[]string{"-k", "1234"}, -1, 1234, nil},
74 {[]string{"-k", "1234", "abc"}, -1, 1234, []string{"abc"}},
75 {[]string{"-k", "abc"}, -1, 0, []string{"abc"}},
76 {[]string{"-k", "1abc"}, -1, 0, []string{"1abc"}},
77
78 // TODO: These are supported in Make, should we support them?
79 //{[]string{"-kj"}, -1, 0},
80 //{[]string{"-kj8"}, 8, 0},
81
82 // -jk is not valid in Make
83 }
84
85 for _, tc := range testCases {
86 t.Run(strings.Join(tc.args, " "), func(t *testing.T) {
87 defer logger.Recover(func(err error) {
88 t.Fatal(err)
89 })
90
91 c := &configImpl{
92 parallel: -1,
93 keepGoing: -1,
94 }
95 c.parseArgs(ctx, tc.args)
96
97 if c.parallel != tc.parallel {
98 t.Errorf("for %q, parallel:\nwant: %d\n got: %d\n",
99 strings.Join(tc.args, " "),
100 tc.parallel, c.parallel)
101 }
102 if c.keepGoing != tc.keepGoing {
103 t.Errorf("for %q, keep going:\nwant: %d\n got: %d\n",
104 strings.Join(tc.args, " "),
105 tc.keepGoing, c.keepGoing)
106 }
107 if !reflect.DeepEqual(c.arguments, tc.remaining) {
108 t.Errorf("for %q, remaining arguments:\nwant: %q\n got: %q\n",
109 strings.Join(tc.args, " "),
110 tc.remaining, c.arguments)
111 }
112 })
113 }
114}
Dan Willemsen091525e2017-07-11 14:17:50 -0700115
116func TestConfigParseArgsVars(t *testing.T) {
117 ctx := testContext()
118
119 testCases := []struct {
120 env []string
121 args []string
122
123 expectedEnv []string
124 remaining []string
125 }{
126 {},
127 {
128 env: []string{"A=bc"},
129
130 expectedEnv: []string{"A=bc"},
131 },
132 {
133 args: []string{"abc"},
134
135 remaining: []string{"abc"},
136 },
137
138 {
139 args: []string{"A=bc"},
140
141 expectedEnv: []string{"A=bc"},
142 },
143 {
144 env: []string{"A=a"},
145 args: []string{"A=bc"},
146
147 expectedEnv: []string{"A=bc"},
148 },
149
150 {
151 env: []string{"A=a"},
152 args: []string{"A=", "=b"},
153
154 expectedEnv: []string{"A="},
155 remaining: []string{"=b"},
156 },
157 }
158
159 for _, tc := range testCases {
160 t.Run(strings.Join(tc.args, " "), func(t *testing.T) {
161 defer logger.Recover(func(err error) {
162 t.Fatal(err)
163 })
164
165 e := Environment(tc.env)
166 c := &configImpl{
167 environ: &e,
168 }
169 c.parseArgs(ctx, tc.args)
170
171 if !reflect.DeepEqual([]string(*c.environ), tc.expectedEnv) {
172 t.Errorf("for env=%q args=%q, environment:\nwant: %q\n got: %q\n",
173 tc.env, tc.args,
174 tc.expectedEnv, []string(*c.environ))
175 }
176 if !reflect.DeepEqual(c.arguments, tc.remaining) {
177 t.Errorf("for env=%q args=%q, remaining arguments:\nwant: %q\n got: %q\n",
178 tc.env, tc.args,
179 tc.remaining, c.arguments)
180 }
181 })
182 }
183}
Patrice Arruda13848222019-04-22 17:12:02 -0700184
185func TestConfigCheckTopDir(t *testing.T) {
186 ctx := testContext()
187 buildRootDir := filepath.Dir(srcDirFileCheck)
188 expectedErrStr := fmt.Sprintf("Current working directory must be the source tree. %q not found.", srcDirFileCheck)
189
190 tests := []struct {
191 // ********* Setup *********
192 // Test description.
193 description string
194
195 // ********* Action *********
196 // If set to true, the build root file is created.
197 rootBuildFile bool
198
199 // The current path where Soong is being executed.
200 path string
201
202 // ********* Validation *********
203 // Expecting error and validate the error string against expectedErrStr.
204 wantErr bool
205 }{{
206 description: "current directory is the root source tree",
207 rootBuildFile: true,
208 path: ".",
209 wantErr: false,
210 }, {
211 description: "one level deep in the source tree",
212 rootBuildFile: true,
213 path: "1",
214 wantErr: true,
215 }, {
216 description: "very deep in the source tree",
217 rootBuildFile: true,
218 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",
219 wantErr: true,
220 }, {
221 description: "outside of source tree",
222 rootBuildFile: false,
223 path: "1/2/3/4/5",
224 wantErr: true,
225 }}
226
227 for _, tt := range tests {
228 t.Run(tt.description, func(t *testing.T) {
229 defer logger.Recover(func(err error) {
230 if !tt.wantErr {
231 t.Fatalf("Got unexpected error: %v", err)
232 }
233 if expectedErrStr != err.Error() {
234 t.Fatalf("expected %s, got %s", expectedErrStr, err.Error())
235 }
236 })
237
238 // Create the root source tree.
239 rootDir, err := ioutil.TempDir("", "")
240 if err != nil {
241 t.Fatal(err)
242 }
243 defer os.RemoveAll(rootDir)
244
245 // Create the build root file. This is to test if topDir returns an error if the build root
246 // file does not exist.
247 if tt.rootBuildFile {
248 dir := filepath.Join(rootDir, buildRootDir)
249 if err := os.MkdirAll(dir, 0755); err != nil {
250 t.Errorf("failed to create %s directory: %v", dir, err)
251 }
252 f := filepath.Join(rootDir, srcDirFileCheck)
253 if err := ioutil.WriteFile(f, []byte{}, 0644); err != nil {
254 t.Errorf("failed to create file %s: %v", f, err)
255 }
256 }
257
258 // Next block of code is to set the current directory.
259 dir := rootDir
260 if tt.path != "" {
261 dir = filepath.Join(dir, tt.path)
262 if err := os.MkdirAll(dir, 0755); err != nil {
263 t.Errorf("failed to create %s directory: %v", dir, err)
264 }
265 }
266 curDir, err := os.Getwd()
267 if err != nil {
268 t.Fatalf("failed to get the current directory: %v", err)
269 }
270 defer func() { os.Chdir(curDir) }()
271
272 if err := os.Chdir(dir); err != nil {
273 t.Fatalf("failed to change directory to %s: %v", dir, err)
274 }
275
276 checkTopDir(ctx)
277 })
278 }
279}
280
281func TestConfigConvertToTarget(t *testing.T) {
282 tests := []struct {
283 // ********* Setup *********
284 // Test description.
285 description string
286
287 // ********* Action *********
288 // The current directory where Soong is being executed.
289 dir string
290
291 // The current prefix string to be pre-appended to the target.
292 prefix string
293
294 // ********* Validation *********
295 // The expected target to be invoked in ninja.
296 expectedTarget string
297 }{{
298 description: "one level directory in source tree",
299 dir: "test1",
300 prefix: "MODULES-IN-",
301 expectedTarget: "MODULES-IN-test1",
302 }, {
303 description: "multiple level directories in source tree",
304 dir: "test1/test2/test3/test4",
305 prefix: "GET-INSTALL-PATH-IN-",
306 expectedTarget: "GET-INSTALL-PATH-IN-test1-test2-test3-test4",
307 }}
308 for _, tt := range tests {
309 t.Run(tt.description, func(t *testing.T) {
310 target := convertToTarget(tt.dir, tt.prefix)
311 if target != tt.expectedTarget {
312 t.Errorf("expected %s, got %s for target", tt.expectedTarget, target)
313 }
314 })
315 }
316}
317
318func setTop(t *testing.T, dir string) func() {
319 curDir, err := os.Getwd()
320 if err != nil {
321 t.Fatalf("failed to get current directory: %v", err)
322 }
323 if err := os.Chdir(dir); err != nil {
324 t.Fatalf("failed to change directory to top dir %s: %v", dir, err)
325 }
326 return func() { os.Chdir(curDir) }
327}
328
329func createBuildFiles(t *testing.T, topDir string, buildFiles []string) {
330 for _, buildFile := range buildFiles {
331 buildFile = filepath.Join(topDir, buildFile)
332 if err := ioutil.WriteFile(buildFile, []byte{}, 0644); err != nil {
333 t.Errorf("failed to create file %s: %v", buildFile, err)
334 }
335 }
336}
337
338func createDirectories(t *testing.T, topDir string, dirs []string) {
339 for _, dir := range dirs {
340 dir = filepath.Join(topDir, dir)
341 if err := os.MkdirAll(dir, 0755); err != nil {
342 t.Errorf("failed to create %s directory: %v", dir, err)
343 }
344 }
345}
346
347func TestConfigGetTargets(t *testing.T) {
348 ctx := testContext()
349 tests := []struct {
350 // ********* Setup *********
351 // Test description.
352 description string
353
354 // Directories that exist in the source tree.
355 dirsInTrees []string
356
357 // Build files that exists in the source tree.
358 buildFiles []string
359
360 // ********* Action *********
361 // Directories passed in to soong_ui.
362 dirs []string
363
364 // Current directory that the user executed the build action command.
365 curDir string
366
367 // ********* Validation *********
368 // Expected targets from the function.
369 expectedTargets []string
370
Patrice Arruda13848222019-04-22 17:12:02 -0700371 // Expecting error from running test case.
372 errStr string
373 }{{
Dan Willemsence41e942019-07-29 23:39:30 -0700374 description: "one target dir specified",
375 dirsInTrees: []string{"0/1/2/3"},
376 buildFiles: []string{"0/1/2/3/Android.bp"},
377 dirs: []string{"1/2/3"},
378 curDir: "0",
379 expectedTargets: []string{"MODULES-IN-0-1-2-3"},
Patrice Arruda13848222019-04-22 17:12:02 -0700380 }, {
381 description: "one target dir specified, build file does not exist",
382 dirsInTrees: []string{"0/1/2/3"},
383 buildFiles: []string{},
384 dirs: []string{"1/2/3"},
385 curDir: "0",
386 errStr: "Build file not found for 0/1/2/3 directory",
387 }, {
388 description: "one target dir specified, invalid targets specified",
389 dirsInTrees: []string{"0/1/2/3"},
390 buildFiles: []string{},
391 dirs: []string{"1/2/3:t1:t2"},
392 curDir: "0",
393 errStr: "1/2/3:t1:t2 not in proper directory:target1,target2,... format (\":\" was specified more than once)",
394 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700395 description: "one target dir specified, no targets specified but has colon",
396 dirsInTrees: []string{"0/1/2/3"},
397 buildFiles: []string{"0/1/2/3/Android.bp"},
398 dirs: []string{"1/2/3:"},
399 curDir: "0",
400 expectedTargets: []string{"MODULES-IN-0-1-2-3"},
Patrice Arruda13848222019-04-22 17:12:02 -0700401 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700402 description: "one target dir specified, two targets specified",
403 dirsInTrees: []string{"0/1/2/3"},
404 buildFiles: []string{"0/1/2/3/Android.bp"},
405 dirs: []string{"1/2/3:t1,t2"},
406 curDir: "0",
407 expectedTargets: []string{"t1", "t2"},
Patrice Arruda13848222019-04-22 17:12:02 -0700408 }, {
409 description: "one target dir specified, no targets and has a comma",
410 dirsInTrees: []string{"0/1/2/3"},
411 buildFiles: []string{"0/1/2/3/Android.bp"},
412 dirs: []string{"1/2/3:,"},
413 curDir: "0",
414 errStr: "0/1/2/3 not in proper directory:target1,target2,... format",
415 }, {
416 description: "one target dir specified, improper targets defined",
417 dirsInTrees: []string{"0/1/2/3"},
418 buildFiles: []string{"0/1/2/3/Android.bp"},
419 dirs: []string{"1/2/3:,t1"},
420 curDir: "0",
421 errStr: "0/1/2/3 not in proper directory:target1,target2,... format",
422 }, {
423 description: "one target dir specified, blank target",
424 dirsInTrees: []string{"0/1/2/3"},
425 buildFiles: []string{"0/1/2/3/Android.bp"},
426 dirs: []string{"1/2/3:t1,"},
427 curDir: "0",
428 errStr: "0/1/2/3 not in proper directory:target1,target2,... format",
429 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700430 description: "one target dir specified, many targets specified",
431 dirsInTrees: []string{"0/1/2/3"},
432 buildFiles: []string{"0/1/2/3/Android.bp"},
433 dirs: []string{"1/2/3:t1,t2,t3,t4,t5,t6,t7,t8,t9,t10"},
434 curDir: "0",
435 expectedTargets: []string{"t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9", "t10"},
Patrice Arruda13848222019-04-22 17:12:02 -0700436 }, {
437 description: "one target dir specified, one target specified, build file does not exist",
438 dirsInTrees: []string{"0/1/2/3"},
439 buildFiles: []string{},
440 dirs: []string{"1/2/3:t1"},
441 curDir: "0",
Patrice Arruda9450d0b2019-07-08 11:06:46 -0700442 errStr: "Couldn't locate a build file from 0/1/2/3 directory",
Patrice Arruda13848222019-04-22 17:12:02 -0700443 }, {
444 description: "one target dir specified, one target specified, build file not in target dir",
445 dirsInTrees: []string{"0/1/2/3"},
446 buildFiles: []string{"0/1/2/Android.mk"},
447 dirs: []string{"1/2/3:t1"},
448 curDir: "0",
449 errStr: "Couldn't locate a build file from 0/1/2/3 directory",
450 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700451 description: "one target dir specified, build file not in target dir",
452 dirsInTrees: []string{"0/1/2/3"},
453 buildFiles: []string{"0/1/2/Android.mk"},
454 dirs: []string{"1/2/3"},
455 curDir: "0",
456 expectedTargets: []string{"MODULES-IN-0-1-2"},
Patrice Arruda13848222019-04-22 17:12:02 -0700457 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700458 description: "multiple targets dir specified, targets specified",
459 dirsInTrees: []string{"0/1/2/3", "0/3/4"},
460 buildFiles: []string{"0/1/2/3/Android.bp", "0/3/4/Android.mk"},
461 dirs: []string{"1/2/3:t1,t2", "3/4:t3,t4,t5"},
462 curDir: "0",
463 expectedTargets: []string{"t1", "t2", "t3", "t4", "t5"},
Patrice Arruda13848222019-04-22 17:12:02 -0700464 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700465 description: "multiple targets dir specified, one directory has targets specified",
466 dirsInTrees: []string{"0/1/2/3", "0/3/4"},
467 buildFiles: []string{"0/1/2/3/Android.bp", "0/3/4/Android.mk"},
468 dirs: []string{"1/2/3:t1,t2", "3/4"},
469 curDir: "0",
470 expectedTargets: []string{"t1", "t2", "MODULES-IN-0-3-4"},
Patrice Arruda13848222019-04-22 17:12:02 -0700471 }, {
472 description: "two dirs specified, only one dir exist",
473 dirsInTrees: []string{"0/1/2/3"},
474 buildFiles: []string{"0/1/2/3/Android.mk"},
475 dirs: []string{"1/2/3:t1", "3/4"},
476 curDir: "0",
477 errStr: "couldn't find directory 0/3/4",
478 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700479 description: "multiple targets dirs specified at root source tree",
480 dirsInTrees: []string{"0/1/2/3", "0/3/4"},
481 buildFiles: []string{"0/1/2/3/Android.bp", "0/3/4/Android.mk"},
482 dirs: []string{"0/1/2/3:t1,t2", "0/3/4"},
483 curDir: ".",
484 expectedTargets: []string{"t1", "t2", "MODULES-IN-0-3-4"},
Patrice Arruda13848222019-04-22 17:12:02 -0700485 }, {
486 description: "no directories specified",
487 dirsInTrees: []string{"0/1/2/3", "0/3/4"},
488 buildFiles: []string{"0/1/2/3/Android.bp", "0/3/4/Android.mk"},
489 dirs: []string{},
490 curDir: ".",
491 }}
492 for _, tt := range tests {
493 t.Run(tt.description, func(t *testing.T) {
494 defer logger.Recover(func(err error) {
495 if tt.errStr == "" {
496 t.Fatalf("Got unexpected error: %v", err)
497 }
498 if tt.errStr != err.Error() {
499 t.Errorf("expected %s, got %s", tt.errStr, err.Error())
500 }
501 })
502
503 // Create the root source tree.
504 topDir, err := ioutil.TempDir("", "")
505 if err != nil {
506 t.Fatalf("failed to create temp dir: %v", err)
507 }
508 defer os.RemoveAll(topDir)
509
510 createDirectories(t, topDir, tt.dirsInTrees)
511 createBuildFiles(t, topDir, tt.buildFiles)
512 r := setTop(t, topDir)
513 defer r()
514
Dan Willemsence41e942019-07-29 23:39:30 -0700515 targets := getTargetsFromDirs(ctx, tt.curDir, tt.dirs, "MODULES-IN-")
Patrice Arruda13848222019-04-22 17:12:02 -0700516 if !reflect.DeepEqual(targets, tt.expectedTargets) {
517 t.Errorf("expected %v, got %v for targets", tt.expectedTargets, targets)
518 }
Patrice Arruda13848222019-04-22 17:12:02 -0700519
520 // If the execution reached here and there was an expected error code, the unit test case failed.
521 if tt.errStr != "" {
522 t.Errorf("expecting error %s", tt.errStr)
523 }
524 })
525 }
526}
527
528func TestConfigFindBuildFile(t *testing.T) {
529 ctx := testContext()
530
531 tests := []struct {
532 // ********* Setup *********
533 // Test description.
534 description string
535
536 // Array of build files to create in dir.
537 buildFiles []string
538
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700539 // Directories that exist in the source tree.
540 dirsInTrees []string
541
Patrice Arruda13848222019-04-22 17:12:02 -0700542 // ********* Action *********
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700543 // The base directory is where findBuildFile is invoked.
Patrice Arruda13848222019-04-22 17:12:02 -0700544 dir string
545
546 // ********* Validation *********
547 // Expected build file path to find.
548 expectedBuildFile string
549 }{{
550 description: "build file exists at leaf directory",
551 buildFiles: []string{"1/2/3/Android.bp"},
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700552 dirsInTrees: []string{"1/2/3"},
Patrice Arruda13848222019-04-22 17:12:02 -0700553 dir: "1/2/3",
554 expectedBuildFile: "1/2/3/Android.mk",
555 }, {
556 description: "build file exists in all directory paths",
557 buildFiles: []string{"1/Android.mk", "1/2/Android.mk", "1/2/3/Android.mk"},
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700558 dirsInTrees: []string{"1/2/3"},
Patrice Arruda13848222019-04-22 17:12:02 -0700559 dir: "1/2/3",
560 expectedBuildFile: "1/2/3/Android.mk",
561 }, {
562 description: "build file does not exist in all directory paths",
563 buildFiles: []string{},
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700564 dirsInTrees: []string{"1/2/3"},
Patrice Arruda13848222019-04-22 17:12:02 -0700565 dir: "1/2/3",
566 expectedBuildFile: "",
567 }, {
568 description: "build file exists only at top directory",
569 buildFiles: []string{"Android.bp"},
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700570 dirsInTrees: []string{"1/2/3"},
Patrice Arruda13848222019-04-22 17:12:02 -0700571 dir: "1/2/3",
572 expectedBuildFile: "",
573 }, {
574 description: "build file exist in a subdirectory",
575 buildFiles: []string{"1/2/Android.bp"},
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700576 dirsInTrees: []string{"1/2/3"},
Patrice Arruda13848222019-04-22 17:12:02 -0700577 dir: "1/2/3",
578 expectedBuildFile: "1/2/Android.mk",
579 }, {
580 description: "build file exists in a subdirectory",
581 buildFiles: []string{"1/Android.mk"},
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700582 dirsInTrees: []string{"1/2/3"},
Patrice Arruda13848222019-04-22 17:12:02 -0700583 dir: "1/2/3",
584 expectedBuildFile: "1/Android.mk",
585 }, {
586 description: "top directory",
587 buildFiles: []string{"Android.bp"},
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700588 dirsInTrees: []string{},
Patrice Arruda13848222019-04-22 17:12:02 -0700589 dir: ".",
590 expectedBuildFile: "",
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700591 }, {
592 description: "build file exists in subdirectory",
593 buildFiles: []string{"1/2/3/Android.bp", "1/2/4/Android.bp"},
594 dirsInTrees: []string{"1/2/3", "1/2/4"},
595 dir: "1/2",
596 expectedBuildFile: "1/2/Android.mk",
597 }, {
598 description: "build file exists in parent subdirectory",
599 buildFiles: []string{"1/5/Android.bp"},
600 dirsInTrees: []string{"1/2/3", "1/2/4", "1/5"},
601 dir: "1/2",
602 expectedBuildFile: "1/Android.mk",
603 }, {
604 description: "build file exists in deep parent's subdirectory.",
605 buildFiles: []string{"1/5/6/Android.bp"},
606 dirsInTrees: []string{"1/2/3", "1/2/4", "1/5/6", "1/5/7"},
607 dir: "1/2",
608 expectedBuildFile: "1/Android.mk",
Patrice Arruda13848222019-04-22 17:12:02 -0700609 }}
610
611 for _, tt := range tests {
612 t.Run(tt.description, func(t *testing.T) {
613 defer logger.Recover(func(err error) {
614 t.Fatalf("Got unexpected error: %v", err)
615 })
616
617 topDir, err := ioutil.TempDir("", "")
618 if err != nil {
619 t.Fatalf("failed to create temp dir: %v", err)
620 }
621 defer os.RemoveAll(topDir)
622
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700623 createDirectories(t, topDir, tt.dirsInTrees)
Patrice Arruda13848222019-04-22 17:12:02 -0700624 createBuildFiles(t, topDir, tt.buildFiles)
625
626 curDir, err := os.Getwd()
627 if err != nil {
628 t.Fatalf("Could not get working directory: %v", err)
629 }
630 defer func() { os.Chdir(curDir) }()
631 if err := os.Chdir(topDir); err != nil {
632 t.Fatalf("Could not change top dir to %s: %v", topDir, err)
633 }
634
635 buildFile := findBuildFile(ctx, tt.dir)
636 if buildFile != tt.expectedBuildFile {
637 t.Errorf("expected %q, got %q for build file", tt.expectedBuildFile, buildFile)
638 }
639 })
640 }
641}
642
643func TestConfigSplitArgs(t *testing.T) {
644 tests := []struct {
645 // ********* Setup *********
646 // Test description.
647 description string
648
649 // ********* Action *********
650 // Arguments passed in to soong_ui.
651 args []string
652
653 // ********* Validation *********
654 // Expected newArgs list after extracting the directories.
655 expectedNewArgs []string
656
657 // Expected directories
658 expectedDirs []string
659 }{{
660 description: "flags but no directories specified",
661 args: []string{"showcommands", "-j", "-k"},
662 expectedNewArgs: []string{"showcommands", "-j", "-k"},
663 expectedDirs: []string{},
664 }, {
665 description: "flags and one directory specified",
666 args: []string{"snod", "-j", "dir:target1,target2"},
667 expectedNewArgs: []string{"snod", "-j"},
668 expectedDirs: []string{"dir:target1,target2"},
669 }, {
670 description: "flags and directories specified",
671 args: []string{"dist", "-k", "dir1", "dir2:target1,target2"},
672 expectedNewArgs: []string{"dist", "-k"},
673 expectedDirs: []string{"dir1", "dir2:target1,target2"},
674 }, {
675 description: "only directories specified",
676 args: []string{"dir1", "dir2", "dir3:target1,target2"},
677 expectedNewArgs: []string{},
678 expectedDirs: []string{"dir1", "dir2", "dir3:target1,target2"},
679 }}
680 for _, tt := range tests {
681 t.Run(tt.description, func(t *testing.T) {
682 args, dirs := splitArgs(tt.args)
683 if !reflect.DeepEqual(tt.expectedNewArgs, args) {
684 t.Errorf("expected %v, got %v for arguments", tt.expectedNewArgs, args)
685 }
686 if !reflect.DeepEqual(tt.expectedDirs, dirs) {
687 t.Errorf("expected %v, got %v for directories", tt.expectedDirs, dirs)
688 }
689 })
690 }
691}
692
693type envVar struct {
694 name string
695 value string
696}
697
698type buildActionTestCase struct {
699 // ********* Setup *********
700 // Test description.
701 description string
702
703 // Directories that exist in the source tree.
704 dirsInTrees []string
705
706 // Build files that exists in the source tree.
707 buildFiles []string
708
Patrice Arrudababa9a92019-07-03 10:47:34 -0700709 // Create root symlink that points to topDir.
710 rootSymlink bool
711
Patrice Arruda13848222019-04-22 17:12:02 -0700712 // ********* Action *********
713 // Arguments passed in to soong_ui.
714 args []string
715
716 // Directory where the build action was invoked.
717 curDir string
718
719 // WITH_TIDY_ONLY environment variable specified.
720 tidyOnly string
721
722 // ********* Validation *********
723 // Expected arguments to be in Config instance.
724 expectedArgs []string
725
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700726 // Expecting error from running test case.
727 expectedErrStr string
Patrice Arruda13848222019-04-22 17:12:02 -0700728}
729
Dan Willemsence41e942019-07-29 23:39:30 -0700730func testGetConfigArgs(t *testing.T, tt buildActionTestCase, action BuildAction) {
Patrice Arruda13848222019-04-22 17:12:02 -0700731 ctx := testContext()
732
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700733 defer logger.Recover(func(err error) {
734 if tt.expectedErrStr == "" {
735 t.Fatalf("Got unexpected error: %v", err)
736 }
737 if tt.expectedErrStr != err.Error() {
738 t.Errorf("expected %s, got %s", tt.expectedErrStr, err.Error())
739 }
740 })
741
Patrice Arruda13848222019-04-22 17:12:02 -0700742 // Environment variables to set it to blank on every test case run.
743 resetEnvVars := []string{
Patrice Arruda13848222019-04-22 17:12:02 -0700744 "WITH_TIDY_ONLY",
745 }
746
747 for _, name := range resetEnvVars {
748 if err := os.Unsetenv(name); err != nil {
749 t.Fatalf("failed to unset environment variable %s: %v", name, err)
750 }
751 }
752 if tt.tidyOnly != "" {
753 if err := os.Setenv("WITH_TIDY_ONLY", tt.tidyOnly); err != nil {
754 t.Errorf("failed to set WITH_TIDY_ONLY to %s: %v", tt.tidyOnly, err)
755 }
756 }
757
758 // Create the root source tree.
759 topDir, err := ioutil.TempDir("", "")
760 if err != nil {
761 t.Fatalf("failed to create temp dir: %v", err)
762 }
763 defer os.RemoveAll(topDir)
764
765 createDirectories(t, topDir, tt.dirsInTrees)
766 createBuildFiles(t, topDir, tt.buildFiles)
767
Patrice Arrudababa9a92019-07-03 10:47:34 -0700768 if tt.rootSymlink {
769 // Create a secondary root source tree which points to the true root source tree.
770 symlinkTopDir, err := ioutil.TempDir("", "")
771 if err != nil {
772 t.Fatalf("failed to create symlink temp dir: %v", err)
773 }
774 defer os.RemoveAll(symlinkTopDir)
775
776 symlinkTopDir = filepath.Join(symlinkTopDir, "root")
777 err = os.Symlink(topDir, symlinkTopDir)
778 if err != nil {
779 t.Fatalf("failed to create symlink: %v", err)
780 }
781 topDir = symlinkTopDir
782 }
783
Patrice Arruda13848222019-04-22 17:12:02 -0700784 r := setTop(t, topDir)
785 defer r()
786
787 // The next block is to create the root build file.
788 rootBuildFileDir := filepath.Dir(srcDirFileCheck)
789 if err := os.MkdirAll(rootBuildFileDir, 0755); err != nil {
790 t.Fatalf("Failed to create %s directory: %v", rootBuildFileDir, err)
791 }
792
793 if err := ioutil.WriteFile(srcDirFileCheck, []byte{}, 0644); err != nil {
794 t.Fatalf("failed to create %s file: %v", srcDirFileCheck, err)
795 }
796
Dan Willemsence41e942019-07-29 23:39:30 -0700797 args := getConfigArgs(action, tt.curDir, ctx, tt.args)
Patrice Arruda13848222019-04-22 17:12:02 -0700798 if !reflect.DeepEqual(tt.expectedArgs, args) {
799 t.Fatalf("expected %v, got %v for config arguments", tt.expectedArgs, args)
800 }
801
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700802 // If the execution reached here and there was an expected error code, the unit test case failed.
803 if tt.expectedErrStr != "" {
804 t.Errorf("expecting error %s", tt.expectedErrStr)
805 }
Patrice Arruda13848222019-04-22 17:12:02 -0700806}
807
Patrice Arruda39282062019-06-20 16:35:12 -0700808func TestGetConfigArgsBuildModules(t *testing.T) {
809 tests := []buildActionTestCase{{
Dan Willemsence41e942019-07-29 23:39:30 -0700810 description: "normal execution from the root source tree directory",
811 dirsInTrees: []string{"0/1/2", "0/2", "0/3"},
812 buildFiles: []string{"0/1/2/Android.mk", "0/2/Android.bp", "0/3/Android.mk"},
813 args: []string{"-j", "fake_module", "fake_module2"},
814 curDir: ".",
815 tidyOnly: "",
816 expectedArgs: []string{"-j", "fake_module", "fake_module2"},
Patrice Arruda39282062019-06-20 16:35:12 -0700817 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700818 description: "normal execution in deep directory",
819 dirsInTrees: []string{"0/1/2", "0/2", "0/3", "1/2/3/4/5/6/7/8/9/1/2/3/4/5/6"},
820 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"},
821 args: []string{"-j", "fake_module", "fake_module2", "-k"},
822 curDir: "1/2/3/4/5/6/7/8/9",
823 tidyOnly: "",
824 expectedArgs: []string{"-j", "fake_module", "fake_module2", "-k"},
Patrice Arruda39282062019-06-20 16:35:12 -0700825 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700826 description: "normal execution in deep directory, no targets",
827 dirsInTrees: []string{"0/1/2", "0/2", "0/3", "1/2/3/4/5/6/7/8/9/1/2/3/4/5/6"},
828 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"},
829 args: []string{"-j", "-k"},
830 curDir: "1/2/3/4/5/6/7/8/9",
831 tidyOnly: "",
832 expectedArgs: []string{"-j", "-k"},
Patrice Arruda39282062019-06-20 16:35:12 -0700833 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700834 description: "normal execution in root source tree, no args",
835 dirsInTrees: []string{"0/1/2", "0/2", "0/3"},
836 buildFiles: []string{"0/1/2/Android.mk", "0/2/Android.bp"},
837 args: []string{},
838 curDir: "0/2",
839 tidyOnly: "",
840 expectedArgs: []string{},
Patrice Arrudababa9a92019-07-03 10:47:34 -0700841 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700842 description: "normal execution in symlink root source tree, no args",
843 dirsInTrees: []string{"0/1/2", "0/2", "0/3"},
844 buildFiles: []string{"0/1/2/Android.mk", "0/2/Android.bp"},
845 rootSymlink: true,
846 args: []string{},
847 curDir: "0/2",
848 tidyOnly: "",
849 expectedArgs: []string{},
Patrice Arruda39282062019-06-20 16:35:12 -0700850 }}
851 for _, tt := range tests {
852 t.Run("build action BUILD_MODULES with dependencies, "+tt.description, func(t *testing.T) {
Dan Willemsence41e942019-07-29 23:39:30 -0700853 testGetConfigArgs(t, tt, BUILD_MODULES)
Patrice Arruda13848222019-04-22 17:12:02 -0700854 })
855 }
856}
857
858func TestGetConfigArgsBuildModulesInDirectory(t *testing.T) {
859 tests := []buildActionTestCase{{
Dan Willemsence41e942019-07-29 23:39:30 -0700860 description: "normal execution in a directory",
861 dirsInTrees: []string{"0/1/2"},
862 buildFiles: []string{"0/1/2/Android.mk"},
863 args: []string{"fake-module"},
864 curDir: "0/1/2",
865 tidyOnly: "",
866 expectedArgs: []string{"fake-module", "MODULES-IN-0-1-2"},
Patrice Arruda13848222019-04-22 17:12:02 -0700867 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700868 description: "build file in parent directory",
869 dirsInTrees: []string{"0/1/2"},
870 buildFiles: []string{"0/1/Android.mk"},
871 args: []string{},
872 curDir: "0/1/2",
873 tidyOnly: "",
874 expectedArgs: []string{"MODULES-IN-0-1"},
Patrice Arruda13848222019-04-22 17:12:02 -0700875 },
876 {
Dan Willemsence41e942019-07-29 23:39:30 -0700877 description: "build file in parent directory, multiple module names passed in",
878 dirsInTrees: []string{"0/1/2"},
879 buildFiles: []string{"0/1/Android.mk"},
880 args: []string{"fake-module1", "fake-module2", "fake-module3"},
881 curDir: "0/1/2",
882 tidyOnly: "",
883 expectedArgs: []string{"fake-module1", "fake-module2", "fake-module3", "MODULES-IN-0-1"},
Patrice Arruda13848222019-04-22 17:12:02 -0700884 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700885 description: "build file in 2nd level parent directory",
886 dirsInTrees: []string{"0/1/2"},
887 buildFiles: []string{"0/Android.bp"},
888 args: []string{},
889 curDir: "0/1/2",
890 tidyOnly: "",
891 expectedArgs: []string{"MODULES-IN-0"},
Patrice Arruda13848222019-04-22 17:12:02 -0700892 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700893 description: "build action executed at root directory",
894 dirsInTrees: []string{},
895 buildFiles: []string{},
896 rootSymlink: false,
897 args: []string{},
898 curDir: ".",
899 tidyOnly: "",
900 expectedArgs: []string{},
Patrice Arrudababa9a92019-07-03 10:47:34 -0700901 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700902 description: "build action executed at root directory in symlink",
903 dirsInTrees: []string{},
904 buildFiles: []string{},
905 rootSymlink: true,
906 args: []string{},
907 curDir: ".",
908 tidyOnly: "",
909 expectedArgs: []string{},
Patrice Arruda13848222019-04-22 17:12:02 -0700910 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700911 description: "build file not found",
912 dirsInTrees: []string{"0/1/2"},
913 buildFiles: []string{},
914 args: []string{},
915 curDir: "0/1/2",
916 tidyOnly: "",
917 expectedArgs: []string{"MODULES-IN-0-1-2"},
918 expectedErrStr: "Build file not found for 0/1/2 directory",
Patrice Arruda13848222019-04-22 17:12:02 -0700919 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700920 description: "GET-INSTALL-PATH specified,",
921 dirsInTrees: []string{"0/1/2"},
922 buildFiles: []string{"0/1/Android.mk"},
923 args: []string{"GET-INSTALL-PATH", "-j", "-k", "GET-INSTALL-PATH"},
924 curDir: "0/1/2",
925 tidyOnly: "",
926 expectedArgs: []string{"-j", "-k", "GET-INSTALL-PATH-IN-0-1"},
Patrice Arruda13848222019-04-22 17:12:02 -0700927 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700928 description: "tidy only environment variable specified,",
929 dirsInTrees: []string{"0/1/2"},
930 buildFiles: []string{"0/1/Android.mk"},
931 args: []string{"GET-INSTALL-PATH"},
932 curDir: "0/1/2",
933 tidyOnly: "true",
934 expectedArgs: []string{"tidy_only"},
Patrice Arruda13848222019-04-22 17:12:02 -0700935 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700936 description: "normal execution in root directory with args",
937 dirsInTrees: []string{},
938 buildFiles: []string{},
939 args: []string{"-j", "-k", "fake_module"},
940 curDir: "",
941 tidyOnly: "",
942 expectedArgs: []string{"-j", "-k", "fake_module"},
Patrice Arruda13848222019-04-22 17:12:02 -0700943 }}
944 for _, tt := range tests {
945 t.Run("build action BUILD_MODULES_IN_DIR, "+tt.description, func(t *testing.T) {
Dan Willemsence41e942019-07-29 23:39:30 -0700946 testGetConfigArgs(t, tt, BUILD_MODULES_IN_A_DIRECTORY)
Patrice Arruda13848222019-04-22 17:12:02 -0700947 })
948 }
949}
950
951func TestGetConfigArgsBuildModulesInDirectories(t *testing.T) {
952 tests := []buildActionTestCase{{
953 description: "normal execution in a directory",
954 dirsInTrees: []string{"0/1/2/3.1", "0/1/2/3.2", "0/1/2/3.3"},
955 buildFiles: []string{"0/1/2/3.1/Android.bp", "0/1/2/3.2/Android.bp", "0/1/2/3.3/Android.bp"},
956 args: []string{"3.1/", "3.2/", "3.3/"},
957 curDir: "0/1/2",
958 tidyOnly: "",
959 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 -0700960 }, {
961 description: "GET-INSTALL-PATH specified",
962 dirsInTrees: []string{"0/1/2/3.1", "0/1/2/3.2", "0/1/3"},
963 buildFiles: []string{"0/1/2/3.1/Android.bp", "0/1/2/3.2/Android.bp", "0/1/Android.bp"},
964 args: []string{"GET-INSTALL-PATH", "2/3.1/", "2/3.2", "3"},
965 curDir: "0/1",
966 tidyOnly: "",
967 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 -0700968 }, {
969 description: "tidy only environment variable specified",
970 dirsInTrees: []string{"0/1/2/3.1", "0/1/2/3.2", "0/1/2/3.3"},
971 buildFiles: []string{"0/1/2/3.1/Android.bp", "0/1/2/3.2/Android.bp", "0/1/2/3.3/Android.bp"},
972 args: []string{"GET-INSTALL-PATH", "3.1/", "3.2/", "3.3"},
973 curDir: "0/1/2",
974 tidyOnly: "1",
975 expectedArgs: []string{"tidy_only"},
Patrice Arruda13848222019-04-22 17:12:02 -0700976 }, {
977 description: "normal execution from top dir directory",
978 dirsInTrees: []string{"0/1/2/3.1", "0/1/2/3.2", "0/1/3", "0/2"},
979 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 -0700980 rootSymlink: false,
981 args: []string{"0/1/2/3.1", "0/1/2/3.2", "0/1/3", "0/2"},
982 curDir: ".",
983 tidyOnly: "",
984 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 -0700985 }, {
986 description: "normal execution from top dir directory in symlink",
987 dirsInTrees: []string{"0/1/2/3.1", "0/1/2/3.2", "0/1/3", "0/2"},
988 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"},
989 rootSymlink: true,
Patrice Arruda13848222019-04-22 17:12:02 -0700990 args: []string{"0/1/2/3.1", "0/1/2/3.2", "0/1/3", "0/2"},
991 curDir: ".",
992 tidyOnly: "",
993 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 -0700994 }}
995 for _, tt := range tests {
996 t.Run("build action BUILD_MODULES_IN_DIRS, "+tt.description, func(t *testing.T) {
Dan Willemsence41e942019-07-29 23:39:30 -0700997 testGetConfigArgs(t, tt, BUILD_MODULES_IN_DIRECTORIES)
Patrice Arruda13848222019-04-22 17:12:02 -0700998 })
999 }
1000}
Liz Kammerca9cb2e2021-07-14 15:29:57 -04001001
1002func TestBuildConfig(t *testing.T) {
1003 tests := []struct {
1004 name string
1005 environ Environment
Yu Liue737a992021-10-04 13:21:41 -07001006 arguments []string
Liz Kammerca9cb2e2021-07-14 15:29:57 -04001007 useBazel bool
1008 expectedBuildConfig *smpb.BuildConfig
1009 }{
1010 {
1011 name: "none set",
1012 environ: Environment{},
1013 expectedBuildConfig: &smpb.BuildConfig{
1014 ForceUseGoma: proto.Bool(false),
1015 UseGoma: proto.Bool(false),
1016 UseRbe: proto.Bool(false),
1017 BazelAsNinja: proto.Bool(false),
1018 BazelMixedBuild: proto.Bool(false),
1019 },
1020 },
1021 {
1022 name: "force use goma",
1023 environ: Environment{"FORCE_USE_GOMA=1"},
1024 expectedBuildConfig: &smpb.BuildConfig{
1025 ForceUseGoma: proto.Bool(true),
1026 UseGoma: proto.Bool(false),
1027 UseRbe: proto.Bool(false),
1028 BazelAsNinja: proto.Bool(false),
1029 BazelMixedBuild: proto.Bool(false),
1030 },
1031 },
1032 {
1033 name: "use goma",
1034 environ: Environment{"USE_GOMA=1"},
1035 expectedBuildConfig: &smpb.BuildConfig{
1036 ForceUseGoma: proto.Bool(false),
1037 UseGoma: proto.Bool(true),
1038 UseRbe: proto.Bool(false),
1039 BazelAsNinja: proto.Bool(false),
1040 BazelMixedBuild: proto.Bool(false),
1041 },
1042 },
1043 {
1044 name: "use rbe",
1045 environ: Environment{"USE_RBE=1"},
1046 expectedBuildConfig: &smpb.BuildConfig{
1047 ForceUseGoma: proto.Bool(false),
1048 UseGoma: proto.Bool(false),
1049 UseRbe: proto.Bool(true),
1050 BazelAsNinja: proto.Bool(false),
1051 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),
1062 BazelAsNinja: proto.Bool(true),
1063 BazelMixedBuild: proto.Bool(false),
1064 },
1065 },
1066 {
1067 name: "bazel mixed build",
1068 environ: Environment{"USE_BAZEL_ANALYSIS=1"},
1069 expectedBuildConfig: &smpb.BuildConfig{
1070 ForceUseGoma: proto.Bool(false),
1071 UseGoma: proto.Bool(false),
1072 UseRbe: proto.Bool(false),
1073 BazelAsNinja: proto.Bool(false),
1074 BazelMixedBuild: proto.Bool(true),
1075 },
1076 },
1077 {
Yu Liue737a992021-10-04 13:21:41 -07001078 name: "specified targets",
1079 environ: Environment{},
1080 useBazel: true,
1081 arguments: []string{"droid", "dist"},
1082 expectedBuildConfig: &smpb.BuildConfig{
1083 ForceUseGoma: proto.Bool(false),
1084 UseGoma: proto.Bool(false),
1085 UseRbe: proto.Bool(false),
1086 BazelAsNinja: proto.Bool(true),
1087 BazelMixedBuild: proto.Bool(false),
1088 Targets: []string{"droid", "dist"},
1089 },
1090 },
1091 {
Liz Kammerca9cb2e2021-07-14 15:29:57 -04001092 name: "all set",
1093 environ: Environment{
1094 "FORCE_USE_GOMA=1",
1095 "USE_GOMA=1",
1096 "USE_RBE=1",
1097 "USE_BAZEL_ANALYSIS=1",
1098 },
1099 useBazel: true,
1100 expectedBuildConfig: &smpb.BuildConfig{
1101 ForceUseGoma: proto.Bool(true),
1102 UseGoma: proto.Bool(true),
1103 UseRbe: proto.Bool(true),
1104 BazelAsNinja: proto.Bool(true),
1105 BazelMixedBuild: proto.Bool(true),
1106 },
1107 },
1108 }
1109
1110 for _, tc := range tests {
1111 t.Run(tc.name, func(t *testing.T) {
1112 c := &configImpl{
Yu Liue737a992021-10-04 13:21:41 -07001113 environ: &tc.environ,
1114 useBazel: tc.useBazel,
1115 arguments: tc.arguments,
Liz Kammerca9cb2e2021-07-14 15:29:57 -04001116 }
1117 config := Config{c}
1118 actualBuildConfig := buildConfig(config)
1119 if expected := tc.expectedBuildConfig; !proto.Equal(expected, actualBuildConfig) {
1120 t.Errorf("Expected build config != actual build config: %#v != %#v", *expected, *actualBuildConfig)
1121 }
1122 })
1123 }
1124}
Yu Liu6e13b402021-07-27 14:29:06 -07001125
1126func TestGetMetricsUploaderApp(t *testing.T) {
1127
1128 metricsUploaderDir := "metrics_uploader_dir"
1129 metricsUploaderBinary := "metrics_uploader_binary"
1130 metricsUploaderPath := filepath.Join(metricsUploaderDir, metricsUploaderBinary)
1131 tests := []struct {
1132 description string
1133 environ Environment
1134 createFiles bool
1135 expected string
1136 }{{
1137 description: "Uploader binary exist",
1138 environ: Environment{"METRICS_UPLOADER=" + metricsUploaderPath},
1139 createFiles: true,
1140 expected: metricsUploaderPath,
1141 }, {
1142 description: "Uploader binary not exist",
1143 environ: Environment{"METRICS_UPLOADER=" + metricsUploaderPath},
1144 createFiles: false,
1145 expected: "",
1146 }, {
1147 description: "Uploader binary variable not set",
1148 createFiles: true,
1149 expected: "",
1150 }}
1151
1152 for _, tt := range tests {
1153 t.Run(tt.description, func(t *testing.T) {
1154 defer logger.Recover(func(err error) {
1155 t.Fatalf("got unexpected error: %v", err)
1156 })
1157
1158 // Create the root source tree.
1159 topDir, err := ioutil.TempDir("", "")
1160 if err != nil {
1161 t.Fatalf("failed to create temp dir: %v", err)
1162 }
1163 defer os.RemoveAll(topDir)
1164
1165 expected := tt.expected
1166 if len(expected) > 0 {
1167 expected = filepath.Join(topDir, expected)
1168 }
1169
1170 if tt.createFiles {
1171 if err := os.MkdirAll(filepath.Join(topDir, metricsUploaderDir), 0755); err != nil {
1172 t.Errorf("failed to create %s directory: %v", metricsUploaderDir, err)
1173 }
1174 if err := ioutil.WriteFile(filepath.Join(topDir, metricsUploaderPath), []byte{}, 0644); err != nil {
1175 t.Errorf("failed to create file %s: %v", expected, err)
1176 }
1177 }
1178
1179 actual := GetMetricsUploader(topDir, &tt.environ)
1180
1181 if actual != expected {
1182 t.Errorf("expecting: %s, actual: %s", expected, actual)
1183 }
1184 })
1185 }
1186}