blob: b42edb0c686eb30f71b903d7baaa1f6ab6299553 [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"
Christopher Ferris1db36e32024-07-25 12:42:47 -070025 "runtime"
Dan Willemsen9b587492017-07-10 22:13:00 -070026 "strings"
27 "testing"
28
29 "android/soong/ui/logger"
Liz Kammerca9cb2e2021-07-14 15:29:57 -040030 smpb "android/soong/ui/metrics/metrics_proto"
Patrice Arruda219eef32020-06-01 17:29:30 +000031 "android/soong/ui/status"
Romain Jobredeaux0a7529b2022-10-26 12:56:41 -040032
Chris Parsonsef615e52022-08-18 22:04:11 -040033 "google.golang.org/protobuf/encoding/prototext"
Liz Kammerca9cb2e2021-07-14 15:29:57 -040034
Dan Willemsen4591b642021-05-24 14:24:12 -070035 "google.golang.org/protobuf/proto"
Dan Willemsen9b587492017-07-10 22:13:00 -070036)
37
38func testContext() Context {
39 return Context{&ContextImpl{
Dan Willemsenb82471a2018-05-17 16:37:09 -070040 Context: context.Background(),
41 Logger: logger.New(&bytes.Buffer{}),
Colin Cross097ed2a2019-06-08 21:48:58 -070042 Writer: &bytes.Buffer{},
Patrice Arruda219eef32020-06-01 17:29:30 +000043 Status: &status.Status{},
Dan Willemsen9b587492017-07-10 22:13:00 -070044 }}
45}
46
47func TestConfigParseArgsJK(t *testing.T) {
48 ctx := testContext()
49
50 testCases := []struct {
51 args []string
52
53 parallel int
54 keepGoing int
55 remaining []string
56 }{
57 {nil, -1, -1, nil},
58
59 {[]string{"-j"}, -1, -1, nil},
60 {[]string{"-j1"}, 1, -1, nil},
61 {[]string{"-j1234"}, 1234, -1, nil},
62
63 {[]string{"-j", "1"}, 1, -1, nil},
64 {[]string{"-j", "1234"}, 1234, -1, nil},
65 {[]string{"-j", "1234", "abc"}, 1234, -1, []string{"abc"}},
66 {[]string{"-j", "abc"}, -1, -1, []string{"abc"}},
67 {[]string{"-j", "1abc"}, -1, -1, []string{"1abc"}},
68
69 {[]string{"-k"}, -1, 0, nil},
70 {[]string{"-k0"}, -1, 0, nil},
71 {[]string{"-k1"}, -1, 1, nil},
72 {[]string{"-k1234"}, -1, 1234, nil},
73
74 {[]string{"-k", "0"}, -1, 0, nil},
75 {[]string{"-k", "1"}, -1, 1, nil},
76 {[]string{"-k", "1234"}, -1, 1234, nil},
77 {[]string{"-k", "1234", "abc"}, -1, 1234, []string{"abc"}},
78 {[]string{"-k", "abc"}, -1, 0, []string{"abc"}},
79 {[]string{"-k", "1abc"}, -1, 0, []string{"1abc"}},
80
81 // TODO: These are supported in Make, should we support them?
82 //{[]string{"-kj"}, -1, 0},
83 //{[]string{"-kj8"}, 8, 0},
84
85 // -jk is not valid in Make
86 }
87
88 for _, tc := range testCases {
89 t.Run(strings.Join(tc.args, " "), func(t *testing.T) {
90 defer logger.Recover(func(err error) {
91 t.Fatal(err)
92 })
93
Chris Parsonsb6e96902022-10-31 20:08:45 -040094 env := Environment([]string{})
Dan Willemsen9b587492017-07-10 22:13:00 -070095 c := &configImpl{
Chris Parsonsb6e96902022-10-31 20:08:45 -040096 environ: &env,
Dan Willemsen9b587492017-07-10 22:13:00 -070097 parallel: -1,
98 keepGoing: -1,
99 }
100 c.parseArgs(ctx, tc.args)
101
102 if c.parallel != tc.parallel {
103 t.Errorf("for %q, parallel:\nwant: %d\n got: %d\n",
104 strings.Join(tc.args, " "),
105 tc.parallel, c.parallel)
106 }
107 if c.keepGoing != tc.keepGoing {
108 t.Errorf("for %q, keep going:\nwant: %d\n got: %d\n",
109 strings.Join(tc.args, " "),
110 tc.keepGoing, c.keepGoing)
111 }
112 if !reflect.DeepEqual(c.arguments, tc.remaining) {
113 t.Errorf("for %q, remaining arguments:\nwant: %q\n got: %q\n",
114 strings.Join(tc.args, " "),
115 tc.remaining, c.arguments)
116 }
117 })
118 }
119}
Dan Willemsen091525e2017-07-11 14:17:50 -0700120
121func TestConfigParseArgsVars(t *testing.T) {
122 ctx := testContext()
123
124 testCases := []struct {
125 env []string
126 args []string
127
128 expectedEnv []string
129 remaining []string
130 }{
131 {},
132 {
133 env: []string{"A=bc"},
134
135 expectedEnv: []string{"A=bc"},
136 },
137 {
138 args: []string{"abc"},
139
140 remaining: []string{"abc"},
141 },
142
143 {
144 args: []string{"A=bc"},
145
146 expectedEnv: []string{"A=bc"},
147 },
148 {
149 env: []string{"A=a"},
150 args: []string{"A=bc"},
151
152 expectedEnv: []string{"A=bc"},
153 },
154
155 {
156 env: []string{"A=a"},
157 args: []string{"A=", "=b"},
158
159 expectedEnv: []string{"A="},
160 remaining: []string{"=b"},
161 },
162 }
163
164 for _, tc := range testCases {
165 t.Run(strings.Join(tc.args, " "), func(t *testing.T) {
166 defer logger.Recover(func(err error) {
167 t.Fatal(err)
168 })
169
170 e := Environment(tc.env)
171 c := &configImpl{
172 environ: &e,
173 }
174 c.parseArgs(ctx, tc.args)
175
176 if !reflect.DeepEqual([]string(*c.environ), tc.expectedEnv) {
177 t.Errorf("for env=%q args=%q, environment:\nwant: %q\n got: %q\n",
178 tc.env, tc.args,
179 tc.expectedEnv, []string(*c.environ))
180 }
181 if !reflect.DeepEqual(c.arguments, tc.remaining) {
182 t.Errorf("for env=%q args=%q, remaining arguments:\nwant: %q\n got: %q\n",
183 tc.env, tc.args,
184 tc.remaining, c.arguments)
185 }
186 })
187 }
188}
Patrice Arruda13848222019-04-22 17:12:02 -0700189
190func TestConfigCheckTopDir(t *testing.T) {
191 ctx := testContext()
192 buildRootDir := filepath.Dir(srcDirFileCheck)
193 expectedErrStr := fmt.Sprintf("Current working directory must be the source tree. %q not found.", srcDirFileCheck)
194
195 tests := []struct {
196 // ********* Setup *********
197 // Test description.
198 description string
199
200 // ********* Action *********
201 // If set to true, the build root file is created.
202 rootBuildFile bool
203
204 // The current path where Soong is being executed.
205 path string
206
207 // ********* Validation *********
208 // Expecting error and validate the error string against expectedErrStr.
209 wantErr bool
210 }{{
211 description: "current directory is the root source tree",
212 rootBuildFile: true,
213 path: ".",
214 wantErr: false,
215 }, {
216 description: "one level deep in the source tree",
217 rootBuildFile: true,
218 path: "1",
219 wantErr: true,
220 }, {
221 description: "very deep in the source tree",
222 rootBuildFile: true,
223 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",
224 wantErr: true,
225 }, {
226 description: "outside of source tree",
227 rootBuildFile: false,
228 path: "1/2/3/4/5",
229 wantErr: true,
230 }}
231
232 for _, tt := range tests {
233 t.Run(tt.description, func(t *testing.T) {
234 defer logger.Recover(func(err error) {
235 if !tt.wantErr {
236 t.Fatalf("Got unexpected error: %v", err)
237 }
238 if expectedErrStr != err.Error() {
239 t.Fatalf("expected %s, got %s", expectedErrStr, err.Error())
240 }
241 })
242
243 // Create the root source tree.
244 rootDir, err := ioutil.TempDir("", "")
245 if err != nil {
246 t.Fatal(err)
247 }
248 defer os.RemoveAll(rootDir)
249
250 // Create the build root file. This is to test if topDir returns an error if the build root
251 // file does not exist.
252 if tt.rootBuildFile {
253 dir := filepath.Join(rootDir, buildRootDir)
254 if err := os.MkdirAll(dir, 0755); err != nil {
255 t.Errorf("failed to create %s directory: %v", dir, err)
256 }
257 f := filepath.Join(rootDir, srcDirFileCheck)
258 if err := ioutil.WriteFile(f, []byte{}, 0644); err != nil {
259 t.Errorf("failed to create file %s: %v", f, err)
260 }
261 }
262
263 // Next block of code is to set the current directory.
264 dir := rootDir
265 if tt.path != "" {
266 dir = filepath.Join(dir, tt.path)
267 if err := os.MkdirAll(dir, 0755); err != nil {
268 t.Errorf("failed to create %s directory: %v", dir, err)
269 }
270 }
271 curDir, err := os.Getwd()
272 if err != nil {
273 t.Fatalf("failed to get the current directory: %v", err)
274 }
275 defer func() { os.Chdir(curDir) }()
276
277 if err := os.Chdir(dir); err != nil {
278 t.Fatalf("failed to change directory to %s: %v", dir, err)
279 }
280
281 checkTopDir(ctx)
282 })
283 }
284}
285
286func TestConfigConvertToTarget(t *testing.T) {
287 tests := []struct {
288 // ********* Setup *********
289 // Test description.
290 description string
291
292 // ********* Action *********
293 // The current directory where Soong is being executed.
294 dir string
295
296 // The current prefix string to be pre-appended to the target.
297 prefix string
298
299 // ********* Validation *********
300 // The expected target to be invoked in ninja.
301 expectedTarget string
302 }{{
303 description: "one level directory in source tree",
304 dir: "test1",
305 prefix: "MODULES-IN-",
306 expectedTarget: "MODULES-IN-test1",
307 }, {
308 description: "multiple level directories in source tree",
309 dir: "test1/test2/test3/test4",
310 prefix: "GET-INSTALL-PATH-IN-",
311 expectedTarget: "GET-INSTALL-PATH-IN-test1-test2-test3-test4",
312 }}
313 for _, tt := range tests {
314 t.Run(tt.description, func(t *testing.T) {
315 target := convertToTarget(tt.dir, tt.prefix)
316 if target != tt.expectedTarget {
317 t.Errorf("expected %s, got %s for target", tt.expectedTarget, target)
318 }
319 })
320 }
321}
322
323func setTop(t *testing.T, dir string) func() {
324 curDir, err := os.Getwd()
325 if err != nil {
326 t.Fatalf("failed to get current directory: %v", err)
327 }
328 if err := os.Chdir(dir); err != nil {
329 t.Fatalf("failed to change directory to top dir %s: %v", dir, err)
330 }
331 return func() { os.Chdir(curDir) }
332}
333
334func createBuildFiles(t *testing.T, topDir string, buildFiles []string) {
335 for _, buildFile := range buildFiles {
336 buildFile = filepath.Join(topDir, buildFile)
337 if err := ioutil.WriteFile(buildFile, []byte{}, 0644); err != nil {
338 t.Errorf("failed to create file %s: %v", buildFile, err)
339 }
340 }
341}
342
343func createDirectories(t *testing.T, topDir string, dirs []string) {
344 for _, dir := range dirs {
345 dir = filepath.Join(topDir, dir)
346 if err := os.MkdirAll(dir, 0755); err != nil {
347 t.Errorf("failed to create %s directory: %v", dir, err)
348 }
349 }
350}
351
352func TestConfigGetTargets(t *testing.T) {
353 ctx := testContext()
354 tests := []struct {
355 // ********* Setup *********
356 // Test description.
357 description string
358
359 // Directories that exist in the source tree.
360 dirsInTrees []string
361
362 // Build files that exists in the source tree.
363 buildFiles []string
364
365 // ********* Action *********
366 // Directories passed in to soong_ui.
367 dirs []string
368
369 // Current directory that the user executed the build action command.
370 curDir string
371
372 // ********* Validation *********
373 // Expected targets from the function.
374 expectedTargets []string
375
Patrice Arruda13848222019-04-22 17:12:02 -0700376 // Expecting error from running test case.
377 errStr string
378 }{{
Dan Willemsence41e942019-07-29 23:39:30 -0700379 description: "one target dir specified",
380 dirsInTrees: []string{"0/1/2/3"},
381 buildFiles: []string{"0/1/2/3/Android.bp"},
382 dirs: []string{"1/2/3"},
383 curDir: "0",
384 expectedTargets: []string{"MODULES-IN-0-1-2-3"},
Patrice Arruda13848222019-04-22 17:12:02 -0700385 }, {
386 description: "one target dir specified, build file does not exist",
387 dirsInTrees: []string{"0/1/2/3"},
388 buildFiles: []string{},
389 dirs: []string{"1/2/3"},
390 curDir: "0",
391 errStr: "Build file not found for 0/1/2/3 directory",
392 }, {
393 description: "one target dir specified, invalid targets specified",
394 dirsInTrees: []string{"0/1/2/3"},
395 buildFiles: []string{},
396 dirs: []string{"1/2/3:t1:t2"},
397 curDir: "0",
398 errStr: "1/2/3:t1:t2 not in proper directory:target1,target2,... format (\":\" was specified more than once)",
399 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700400 description: "one target dir specified, no targets specified but has colon",
401 dirsInTrees: []string{"0/1/2/3"},
402 buildFiles: []string{"0/1/2/3/Android.bp"},
403 dirs: []string{"1/2/3:"},
404 curDir: "0",
405 expectedTargets: []string{"MODULES-IN-0-1-2-3"},
Patrice Arruda13848222019-04-22 17:12:02 -0700406 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700407 description: "one target dir specified, two targets specified",
408 dirsInTrees: []string{"0/1/2/3"},
409 buildFiles: []string{"0/1/2/3/Android.bp"},
410 dirs: []string{"1/2/3:t1,t2"},
411 curDir: "0",
412 expectedTargets: []string{"t1", "t2"},
Patrice Arruda13848222019-04-22 17:12:02 -0700413 }, {
414 description: "one target dir specified, no targets and has a comma",
415 dirsInTrees: []string{"0/1/2/3"},
416 buildFiles: []string{"0/1/2/3/Android.bp"},
417 dirs: []string{"1/2/3:,"},
418 curDir: "0",
419 errStr: "0/1/2/3 not in proper directory:target1,target2,... format",
420 }, {
421 description: "one target dir specified, improper targets defined",
422 dirsInTrees: []string{"0/1/2/3"},
423 buildFiles: []string{"0/1/2/3/Android.bp"},
424 dirs: []string{"1/2/3:,t1"},
425 curDir: "0",
426 errStr: "0/1/2/3 not in proper directory:target1,target2,... format",
427 }, {
428 description: "one target dir specified, blank target",
429 dirsInTrees: []string{"0/1/2/3"},
430 buildFiles: []string{"0/1/2/3/Android.bp"},
431 dirs: []string{"1/2/3:t1,"},
432 curDir: "0",
433 errStr: "0/1/2/3 not in proper directory:target1,target2,... format",
434 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700435 description: "one target dir specified, many targets specified",
436 dirsInTrees: []string{"0/1/2/3"},
437 buildFiles: []string{"0/1/2/3/Android.bp"},
438 dirs: []string{"1/2/3:t1,t2,t3,t4,t5,t6,t7,t8,t9,t10"},
439 curDir: "0",
440 expectedTargets: []string{"t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9", "t10"},
Patrice Arruda13848222019-04-22 17:12:02 -0700441 }, {
442 description: "one target dir specified, one target specified, build file does not exist",
443 dirsInTrees: []string{"0/1/2/3"},
444 buildFiles: []string{},
445 dirs: []string{"1/2/3:t1"},
446 curDir: "0",
Patrice Arruda9450d0b2019-07-08 11:06:46 -0700447 errStr: "Couldn't locate a build file from 0/1/2/3 directory",
Patrice Arruda13848222019-04-22 17:12:02 -0700448 }, {
449 description: "one target dir specified, one target specified, build file not in target dir",
450 dirsInTrees: []string{"0/1/2/3"},
451 buildFiles: []string{"0/1/2/Android.mk"},
452 dirs: []string{"1/2/3:t1"},
453 curDir: "0",
454 errStr: "Couldn't locate a build file from 0/1/2/3 directory",
455 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700456 description: "one target dir specified, build file not in target dir",
457 dirsInTrees: []string{"0/1/2/3"},
458 buildFiles: []string{"0/1/2/Android.mk"},
459 dirs: []string{"1/2/3"},
460 curDir: "0",
461 expectedTargets: []string{"MODULES-IN-0-1-2"},
Patrice Arruda13848222019-04-22 17:12:02 -0700462 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700463 description: "multiple targets dir specified, targets specified",
464 dirsInTrees: []string{"0/1/2/3", "0/3/4"},
465 buildFiles: []string{"0/1/2/3/Android.bp", "0/3/4/Android.mk"},
466 dirs: []string{"1/2/3:t1,t2", "3/4:t3,t4,t5"},
467 curDir: "0",
468 expectedTargets: []string{"t1", "t2", "t3", "t4", "t5"},
Patrice Arruda13848222019-04-22 17:12:02 -0700469 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700470 description: "multiple targets dir specified, one directory has targets specified",
471 dirsInTrees: []string{"0/1/2/3", "0/3/4"},
472 buildFiles: []string{"0/1/2/3/Android.bp", "0/3/4/Android.mk"},
473 dirs: []string{"1/2/3:t1,t2", "3/4"},
474 curDir: "0",
475 expectedTargets: []string{"t1", "t2", "MODULES-IN-0-3-4"},
Patrice Arruda13848222019-04-22 17:12:02 -0700476 }, {
477 description: "two dirs specified, only one dir exist",
478 dirsInTrees: []string{"0/1/2/3"},
479 buildFiles: []string{"0/1/2/3/Android.mk"},
480 dirs: []string{"1/2/3:t1", "3/4"},
481 curDir: "0",
482 errStr: "couldn't find directory 0/3/4",
483 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700484 description: "multiple targets dirs specified at root source tree",
485 dirsInTrees: []string{"0/1/2/3", "0/3/4"},
486 buildFiles: []string{"0/1/2/3/Android.bp", "0/3/4/Android.mk"},
487 dirs: []string{"0/1/2/3:t1,t2", "0/3/4"},
488 curDir: ".",
489 expectedTargets: []string{"t1", "t2", "MODULES-IN-0-3-4"},
Patrice Arruda13848222019-04-22 17:12:02 -0700490 }, {
491 description: "no directories specified",
492 dirsInTrees: []string{"0/1/2/3", "0/3/4"},
493 buildFiles: []string{"0/1/2/3/Android.bp", "0/3/4/Android.mk"},
494 dirs: []string{},
495 curDir: ".",
496 }}
497 for _, tt := range tests {
498 t.Run(tt.description, func(t *testing.T) {
499 defer logger.Recover(func(err error) {
500 if tt.errStr == "" {
501 t.Fatalf("Got unexpected error: %v", err)
502 }
503 if tt.errStr != err.Error() {
504 t.Errorf("expected %s, got %s", tt.errStr, err.Error())
505 }
506 })
507
508 // Create the root source tree.
509 topDir, err := ioutil.TempDir("", "")
510 if err != nil {
511 t.Fatalf("failed to create temp dir: %v", err)
512 }
513 defer os.RemoveAll(topDir)
514
515 createDirectories(t, topDir, tt.dirsInTrees)
516 createBuildFiles(t, topDir, tt.buildFiles)
517 r := setTop(t, topDir)
518 defer r()
519
Dan Willemsence41e942019-07-29 23:39:30 -0700520 targets := getTargetsFromDirs(ctx, tt.curDir, tt.dirs, "MODULES-IN-")
Patrice Arruda13848222019-04-22 17:12:02 -0700521 if !reflect.DeepEqual(targets, tt.expectedTargets) {
522 t.Errorf("expected %v, got %v for targets", tt.expectedTargets, targets)
523 }
Patrice Arruda13848222019-04-22 17:12:02 -0700524
525 // If the execution reached here and there was an expected error code, the unit test case failed.
526 if tt.errStr != "" {
527 t.Errorf("expecting error %s", tt.errStr)
528 }
529 })
530 }
531}
532
533func TestConfigFindBuildFile(t *testing.T) {
534 ctx := testContext()
535
536 tests := []struct {
537 // ********* Setup *********
538 // Test description.
539 description string
540
541 // Array of build files to create in dir.
542 buildFiles []string
543
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700544 // Directories that exist in the source tree.
545 dirsInTrees []string
546
Patrice Arruda13848222019-04-22 17:12:02 -0700547 // ********* Action *********
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700548 // The base directory is where findBuildFile is invoked.
Patrice Arruda13848222019-04-22 17:12:02 -0700549 dir string
550
551 // ********* Validation *********
552 // Expected build file path to find.
553 expectedBuildFile string
554 }{{
555 description: "build file exists at leaf directory",
556 buildFiles: []string{"1/2/3/Android.bp"},
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700557 dirsInTrees: []string{"1/2/3"},
Patrice Arruda13848222019-04-22 17:12:02 -0700558 dir: "1/2/3",
559 expectedBuildFile: "1/2/3/Android.mk",
560 }, {
561 description: "build file exists in all directory paths",
562 buildFiles: []string{"1/Android.mk", "1/2/Android.mk", "1/2/3/Android.mk"},
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700563 dirsInTrees: []string{"1/2/3"},
Patrice Arruda13848222019-04-22 17:12:02 -0700564 dir: "1/2/3",
565 expectedBuildFile: "1/2/3/Android.mk",
566 }, {
567 description: "build file does not exist in all directory paths",
568 buildFiles: []string{},
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700569 dirsInTrees: []string{"1/2/3"},
Patrice Arruda13848222019-04-22 17:12:02 -0700570 dir: "1/2/3",
571 expectedBuildFile: "",
572 }, {
573 description: "build file exists only at top directory",
574 buildFiles: []string{"Android.bp"},
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700575 dirsInTrees: []string{"1/2/3"},
Patrice Arruda13848222019-04-22 17:12:02 -0700576 dir: "1/2/3",
577 expectedBuildFile: "",
578 }, {
579 description: "build file exist in a subdirectory",
580 buildFiles: []string{"1/2/Android.bp"},
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700581 dirsInTrees: []string{"1/2/3"},
Patrice Arruda13848222019-04-22 17:12:02 -0700582 dir: "1/2/3",
583 expectedBuildFile: "1/2/Android.mk",
584 }, {
585 description: "build file exists in a subdirectory",
586 buildFiles: []string{"1/Android.mk"},
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700587 dirsInTrees: []string{"1/2/3"},
Patrice Arruda13848222019-04-22 17:12:02 -0700588 dir: "1/2/3",
589 expectedBuildFile: "1/Android.mk",
590 }, {
591 description: "top directory",
592 buildFiles: []string{"Android.bp"},
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700593 dirsInTrees: []string{},
Patrice Arruda13848222019-04-22 17:12:02 -0700594 dir: ".",
595 expectedBuildFile: "",
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700596 }, {
597 description: "build file exists in subdirectory",
598 buildFiles: []string{"1/2/3/Android.bp", "1/2/4/Android.bp"},
599 dirsInTrees: []string{"1/2/3", "1/2/4"},
600 dir: "1/2",
601 expectedBuildFile: "1/2/Android.mk",
602 }, {
603 description: "build file exists in parent subdirectory",
604 buildFiles: []string{"1/5/Android.bp"},
605 dirsInTrees: []string{"1/2/3", "1/2/4", "1/5"},
606 dir: "1/2",
607 expectedBuildFile: "1/Android.mk",
608 }, {
609 description: "build file exists in deep parent's subdirectory.",
610 buildFiles: []string{"1/5/6/Android.bp"},
611 dirsInTrees: []string{"1/2/3", "1/2/4", "1/5/6", "1/5/7"},
612 dir: "1/2",
613 expectedBuildFile: "1/Android.mk",
Patrice Arruda13848222019-04-22 17:12:02 -0700614 }}
615
616 for _, tt := range tests {
617 t.Run(tt.description, func(t *testing.T) {
618 defer logger.Recover(func(err error) {
619 t.Fatalf("Got unexpected error: %v", err)
620 })
621
622 topDir, err := ioutil.TempDir("", "")
623 if err != nil {
624 t.Fatalf("failed to create temp dir: %v", err)
625 }
626 defer os.RemoveAll(topDir)
627
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700628 createDirectories(t, topDir, tt.dirsInTrees)
Patrice Arruda13848222019-04-22 17:12:02 -0700629 createBuildFiles(t, topDir, tt.buildFiles)
630
631 curDir, err := os.Getwd()
632 if err != nil {
633 t.Fatalf("Could not get working directory: %v", err)
634 }
635 defer func() { os.Chdir(curDir) }()
636 if err := os.Chdir(topDir); err != nil {
637 t.Fatalf("Could not change top dir to %s: %v", topDir, err)
638 }
639
640 buildFile := findBuildFile(ctx, tt.dir)
641 if buildFile != tt.expectedBuildFile {
642 t.Errorf("expected %q, got %q for build file", tt.expectedBuildFile, buildFile)
643 }
644 })
645 }
646}
647
648func TestConfigSplitArgs(t *testing.T) {
649 tests := []struct {
650 // ********* Setup *********
651 // Test description.
652 description string
653
654 // ********* Action *********
655 // Arguments passed in to soong_ui.
656 args []string
657
658 // ********* Validation *********
659 // Expected newArgs list after extracting the directories.
660 expectedNewArgs []string
661
662 // Expected directories
663 expectedDirs []string
664 }{{
665 description: "flags but no directories specified",
666 args: []string{"showcommands", "-j", "-k"},
667 expectedNewArgs: []string{"showcommands", "-j", "-k"},
668 expectedDirs: []string{},
669 }, {
670 description: "flags and one directory specified",
671 args: []string{"snod", "-j", "dir:target1,target2"},
672 expectedNewArgs: []string{"snod", "-j"},
673 expectedDirs: []string{"dir:target1,target2"},
674 }, {
675 description: "flags and directories specified",
676 args: []string{"dist", "-k", "dir1", "dir2:target1,target2"},
677 expectedNewArgs: []string{"dist", "-k"},
678 expectedDirs: []string{"dir1", "dir2:target1,target2"},
679 }, {
680 description: "only directories specified",
681 args: []string{"dir1", "dir2", "dir3:target1,target2"},
682 expectedNewArgs: []string{},
683 expectedDirs: []string{"dir1", "dir2", "dir3:target1,target2"},
684 }}
685 for _, tt := range tests {
686 t.Run(tt.description, func(t *testing.T) {
687 args, dirs := splitArgs(tt.args)
688 if !reflect.DeepEqual(tt.expectedNewArgs, args) {
689 t.Errorf("expected %v, got %v for arguments", tt.expectedNewArgs, args)
690 }
691 if !reflect.DeepEqual(tt.expectedDirs, dirs) {
692 t.Errorf("expected %v, got %v for directories", tt.expectedDirs, dirs)
693 }
694 })
695 }
696}
697
698type envVar struct {
699 name string
700 value string
701}
702
703type buildActionTestCase struct {
704 // ********* Setup *********
705 // Test description.
706 description string
707
708 // Directories that exist in the source tree.
709 dirsInTrees []string
710
711 // Build files that exists in the source tree.
712 buildFiles []string
713
Patrice Arrudababa9a92019-07-03 10:47:34 -0700714 // Create root symlink that points to topDir.
715 rootSymlink bool
716
Patrice Arruda13848222019-04-22 17:12:02 -0700717 // ********* Action *********
718 // Arguments passed in to soong_ui.
719 args []string
720
721 // Directory where the build action was invoked.
722 curDir string
723
724 // WITH_TIDY_ONLY environment variable specified.
725 tidyOnly string
726
727 // ********* Validation *********
728 // Expected arguments to be in Config instance.
729 expectedArgs []string
730
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700731 // Expecting error from running test case.
732 expectedErrStr string
Patrice Arruda13848222019-04-22 17:12:02 -0700733}
734
Dan Willemsence41e942019-07-29 23:39:30 -0700735func testGetConfigArgs(t *testing.T, tt buildActionTestCase, action BuildAction) {
Patrice Arruda13848222019-04-22 17:12:02 -0700736 ctx := testContext()
737
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700738 defer logger.Recover(func(err error) {
739 if tt.expectedErrStr == "" {
740 t.Fatalf("Got unexpected error: %v", err)
741 }
742 if tt.expectedErrStr != err.Error() {
743 t.Errorf("expected %s, got %s", tt.expectedErrStr, err.Error())
744 }
745 })
746
Patrice Arruda13848222019-04-22 17:12:02 -0700747 // Environment variables to set it to blank on every test case run.
748 resetEnvVars := []string{
Patrice Arruda13848222019-04-22 17:12:02 -0700749 "WITH_TIDY_ONLY",
750 }
751
752 for _, name := range resetEnvVars {
753 if err := os.Unsetenv(name); err != nil {
754 t.Fatalf("failed to unset environment variable %s: %v", name, err)
755 }
756 }
757 if tt.tidyOnly != "" {
758 if err := os.Setenv("WITH_TIDY_ONLY", tt.tidyOnly); err != nil {
759 t.Errorf("failed to set WITH_TIDY_ONLY to %s: %v", tt.tidyOnly, err)
760 }
761 }
762
763 // Create the root source tree.
764 topDir, err := ioutil.TempDir("", "")
765 if err != nil {
766 t.Fatalf("failed to create temp dir: %v", err)
767 }
768 defer os.RemoveAll(topDir)
769
770 createDirectories(t, topDir, tt.dirsInTrees)
771 createBuildFiles(t, topDir, tt.buildFiles)
772
Patrice Arrudababa9a92019-07-03 10:47:34 -0700773 if tt.rootSymlink {
774 // Create a secondary root source tree which points to the true root source tree.
775 symlinkTopDir, err := ioutil.TempDir("", "")
776 if err != nil {
777 t.Fatalf("failed to create symlink temp dir: %v", err)
778 }
779 defer os.RemoveAll(symlinkTopDir)
780
781 symlinkTopDir = filepath.Join(symlinkTopDir, "root")
782 err = os.Symlink(topDir, symlinkTopDir)
783 if err != nil {
784 t.Fatalf("failed to create symlink: %v", err)
785 }
786 topDir = symlinkTopDir
787 }
788
Patrice Arruda13848222019-04-22 17:12:02 -0700789 r := setTop(t, topDir)
790 defer r()
791
792 // The next block is to create the root build file.
793 rootBuildFileDir := filepath.Dir(srcDirFileCheck)
794 if err := os.MkdirAll(rootBuildFileDir, 0755); err != nil {
795 t.Fatalf("Failed to create %s directory: %v", rootBuildFileDir, err)
796 }
797
798 if err := ioutil.WriteFile(srcDirFileCheck, []byte{}, 0644); err != nil {
799 t.Fatalf("failed to create %s file: %v", srcDirFileCheck, err)
800 }
801
Dan Willemsence41e942019-07-29 23:39:30 -0700802 args := getConfigArgs(action, tt.curDir, ctx, tt.args)
Patrice Arruda13848222019-04-22 17:12:02 -0700803 if !reflect.DeepEqual(tt.expectedArgs, args) {
804 t.Fatalf("expected %v, got %v for config arguments", tt.expectedArgs, args)
805 }
806
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700807 // If the execution reached here and there was an expected error code, the unit test case failed.
808 if tt.expectedErrStr != "" {
809 t.Errorf("expecting error %s", tt.expectedErrStr)
810 }
Patrice Arruda13848222019-04-22 17:12:02 -0700811}
812
Patrice Arruda39282062019-06-20 16:35:12 -0700813func TestGetConfigArgsBuildModules(t *testing.T) {
814 tests := []buildActionTestCase{{
Dan Willemsence41e942019-07-29 23:39:30 -0700815 description: "normal execution from the root source tree directory",
816 dirsInTrees: []string{"0/1/2", "0/2", "0/3"},
817 buildFiles: []string{"0/1/2/Android.mk", "0/2/Android.bp", "0/3/Android.mk"},
818 args: []string{"-j", "fake_module", "fake_module2"},
819 curDir: ".",
820 tidyOnly: "",
821 expectedArgs: []string{"-j", "fake_module", "fake_module2"},
Patrice Arruda39282062019-06-20 16:35:12 -0700822 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700823 description: "normal execution in deep directory",
824 dirsInTrees: []string{"0/1/2", "0/2", "0/3", "1/2/3/4/5/6/7/8/9/1/2/3/4/5/6"},
825 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"},
826 args: []string{"-j", "fake_module", "fake_module2", "-k"},
827 curDir: "1/2/3/4/5/6/7/8/9",
828 tidyOnly: "",
829 expectedArgs: []string{"-j", "fake_module", "fake_module2", "-k"},
Patrice Arruda39282062019-06-20 16:35:12 -0700830 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700831 description: "normal execution in deep directory, no targets",
832 dirsInTrees: []string{"0/1/2", "0/2", "0/3", "1/2/3/4/5/6/7/8/9/1/2/3/4/5/6"},
833 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"},
834 args: []string{"-j", "-k"},
835 curDir: "1/2/3/4/5/6/7/8/9",
836 tidyOnly: "",
837 expectedArgs: []string{"-j", "-k"},
Patrice Arruda39282062019-06-20 16:35:12 -0700838 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700839 description: "normal execution in root source tree, no args",
840 dirsInTrees: []string{"0/1/2", "0/2", "0/3"},
841 buildFiles: []string{"0/1/2/Android.mk", "0/2/Android.bp"},
842 args: []string{},
843 curDir: "0/2",
844 tidyOnly: "",
845 expectedArgs: []string{},
Patrice Arrudababa9a92019-07-03 10:47:34 -0700846 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700847 description: "normal execution in symlink root source tree, no args",
848 dirsInTrees: []string{"0/1/2", "0/2", "0/3"},
849 buildFiles: []string{"0/1/2/Android.mk", "0/2/Android.bp"},
850 rootSymlink: true,
851 args: []string{},
852 curDir: "0/2",
853 tidyOnly: "",
854 expectedArgs: []string{},
Patrice Arruda39282062019-06-20 16:35:12 -0700855 }}
856 for _, tt := range tests {
857 t.Run("build action BUILD_MODULES with dependencies, "+tt.description, func(t *testing.T) {
Dan Willemsence41e942019-07-29 23:39:30 -0700858 testGetConfigArgs(t, tt, BUILD_MODULES)
Patrice Arruda13848222019-04-22 17:12:02 -0700859 })
860 }
861}
862
863func TestGetConfigArgsBuildModulesInDirectory(t *testing.T) {
Cole Faust331b27f2024-02-28 15:35:49 -0800864 tests := []buildActionTestCase{
865 {
866 description: "normal execution in a directory",
867 dirsInTrees: []string{"0/1/2"},
868 buildFiles: []string{"0/1/2/Android.mk"},
869 args: []string{"fake-module"},
870 curDir: "0/1/2",
871 tidyOnly: "",
872 expectedArgs: []string{"fake-module", "MODULES-IN-0-1-2"},
873 }, {
874 description: "build file in parent directory",
875 dirsInTrees: []string{"0/1/2"},
876 buildFiles: []string{"0/1/Android.mk"},
877 args: []string{},
878 curDir: "0/1/2",
879 tidyOnly: "",
880 expectedArgs: []string{"MODULES-IN-0-1"},
881 },
Patrice Arruda13848222019-04-22 17:12:02 -0700882 {
Dan Willemsence41e942019-07-29 23:39:30 -0700883 description: "build file in parent directory, multiple module names passed in",
884 dirsInTrees: []string{"0/1/2"},
885 buildFiles: []string{"0/1/Android.mk"},
886 args: []string{"fake-module1", "fake-module2", "fake-module3"},
887 curDir: "0/1/2",
888 tidyOnly: "",
889 expectedArgs: []string{"fake-module1", "fake-module2", "fake-module3", "MODULES-IN-0-1"},
Patrice Arruda13848222019-04-22 17:12:02 -0700890 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700891 description: "build file in 2nd level parent directory",
892 dirsInTrees: []string{"0/1/2"},
893 buildFiles: []string{"0/Android.bp"},
894 args: []string{},
895 curDir: "0/1/2",
896 tidyOnly: "",
897 expectedArgs: []string{"MODULES-IN-0"},
Patrice Arruda13848222019-04-22 17:12:02 -0700898 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700899 description: "build action executed at root directory",
900 dirsInTrees: []string{},
901 buildFiles: []string{},
902 rootSymlink: false,
903 args: []string{},
904 curDir: ".",
905 tidyOnly: "",
906 expectedArgs: []string{},
Patrice Arrudababa9a92019-07-03 10:47:34 -0700907 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700908 description: "build action executed at root directory in symlink",
909 dirsInTrees: []string{},
910 buildFiles: []string{},
911 rootSymlink: true,
912 args: []string{},
913 curDir: ".",
914 tidyOnly: "",
915 expectedArgs: []string{},
Patrice Arruda13848222019-04-22 17:12:02 -0700916 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700917 description: "build file not found",
918 dirsInTrees: []string{"0/1/2"},
919 buildFiles: []string{},
920 args: []string{},
921 curDir: "0/1/2",
922 tidyOnly: "",
923 expectedArgs: []string{"MODULES-IN-0-1-2"},
924 expectedErrStr: "Build file not found for 0/1/2 directory",
Patrice Arruda13848222019-04-22 17:12:02 -0700925 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700926 description: "GET-INSTALL-PATH specified,",
927 dirsInTrees: []string{"0/1/2"},
928 buildFiles: []string{"0/1/Android.mk"},
929 args: []string{"GET-INSTALL-PATH", "-j", "-k", "GET-INSTALL-PATH"},
930 curDir: "0/1/2",
931 tidyOnly: "",
932 expectedArgs: []string{"-j", "-k", "GET-INSTALL-PATH-IN-0-1"},
Patrice Arruda13848222019-04-22 17:12:02 -0700933 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700934 description: "tidy only environment variable specified,",
935 dirsInTrees: []string{"0/1/2"},
936 buildFiles: []string{"0/1/Android.mk"},
937 args: []string{"GET-INSTALL-PATH"},
938 curDir: "0/1/2",
939 tidyOnly: "true",
940 expectedArgs: []string{"tidy_only"},
Patrice Arruda13848222019-04-22 17:12:02 -0700941 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700942 description: "normal execution in root directory with args",
943 dirsInTrees: []string{},
944 buildFiles: []string{},
945 args: []string{"-j", "-k", "fake_module"},
946 curDir: "",
947 tidyOnly: "",
948 expectedArgs: []string{"-j", "-k", "fake_module"},
Cole Faust331b27f2024-02-28 15:35:49 -0800949 },
950 }
Patrice Arruda13848222019-04-22 17:12:02 -0700951 for _, tt := range tests {
952 t.Run("build action BUILD_MODULES_IN_DIR, "+tt.description, func(t *testing.T) {
Dan Willemsence41e942019-07-29 23:39:30 -0700953 testGetConfigArgs(t, tt, BUILD_MODULES_IN_A_DIRECTORY)
Patrice Arruda13848222019-04-22 17:12:02 -0700954 })
955 }
956}
957
958func TestGetConfigArgsBuildModulesInDirectories(t *testing.T) {
959 tests := []buildActionTestCase{{
960 description: "normal execution in a directory",
961 dirsInTrees: []string{"0/1/2/3.1", "0/1/2/3.2", "0/1/2/3.3"},
962 buildFiles: []string{"0/1/2/3.1/Android.bp", "0/1/2/3.2/Android.bp", "0/1/2/3.3/Android.bp"},
963 args: []string{"3.1/", "3.2/", "3.3/"},
964 curDir: "0/1/2",
965 tidyOnly: "",
966 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 -0700967 }, {
968 description: "GET-INSTALL-PATH specified",
969 dirsInTrees: []string{"0/1/2/3.1", "0/1/2/3.2", "0/1/3"},
970 buildFiles: []string{"0/1/2/3.1/Android.bp", "0/1/2/3.2/Android.bp", "0/1/Android.bp"},
971 args: []string{"GET-INSTALL-PATH", "2/3.1/", "2/3.2", "3"},
972 curDir: "0/1",
973 tidyOnly: "",
974 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 -0700975 }, {
976 description: "tidy only environment variable specified",
977 dirsInTrees: []string{"0/1/2/3.1", "0/1/2/3.2", "0/1/2/3.3"},
978 buildFiles: []string{"0/1/2/3.1/Android.bp", "0/1/2/3.2/Android.bp", "0/1/2/3.3/Android.bp"},
979 args: []string{"GET-INSTALL-PATH", "3.1/", "3.2/", "3.3"},
980 curDir: "0/1/2",
981 tidyOnly: "1",
982 expectedArgs: []string{"tidy_only"},
Patrice Arruda13848222019-04-22 17:12:02 -0700983 }, {
984 description: "normal execution from top dir directory",
985 dirsInTrees: []string{"0/1/2/3.1", "0/1/2/3.2", "0/1/3", "0/2"},
986 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 -0700987 rootSymlink: false,
988 args: []string{"0/1/2/3.1", "0/1/2/3.2", "0/1/3", "0/2"},
989 curDir: ".",
990 tidyOnly: "",
991 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 -0700992 }, {
993 description: "normal execution from top dir directory in symlink",
994 dirsInTrees: []string{"0/1/2/3.1", "0/1/2/3.2", "0/1/3", "0/2"},
995 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"},
996 rootSymlink: true,
Patrice Arruda13848222019-04-22 17:12:02 -0700997 args: []string{"0/1/2/3.1", "0/1/2/3.2", "0/1/3", "0/2"},
998 curDir: ".",
999 tidyOnly: "",
1000 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 -07001001 }}
1002 for _, tt := range tests {
1003 t.Run("build action BUILD_MODULES_IN_DIRS, "+tt.description, func(t *testing.T) {
Dan Willemsence41e942019-07-29 23:39:30 -07001004 testGetConfigArgs(t, tt, BUILD_MODULES_IN_DIRECTORIES)
Patrice Arruda13848222019-04-22 17:12:02 -07001005 })
1006 }
1007}
Liz Kammerca9cb2e2021-07-14 15:29:57 -04001008
1009func TestBuildConfig(t *testing.T) {
1010 tests := []struct {
1011 name string
1012 environ Environment
Yu Liue737a992021-10-04 13:21:41 -07001013 arguments []string
Liz Kammerca9cb2e2021-07-14 15:29:57 -04001014 expectedBuildConfig *smpb.BuildConfig
1015 }{
1016 {
1017 name: "none set",
1018 environ: Environment{},
1019 expectedBuildConfig: &smpb.BuildConfig{
Colin Cross8d411ff2023-12-07 10:31:24 -08001020 ForceUseGoma: proto.Bool(false),
1021 UseGoma: proto.Bool(false),
1022 UseRbe: proto.Bool(false),
1023 NinjaWeightListSource: smpb.BuildConfig_NOT_USED.Enum(),
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{
Colin Cross8d411ff2023-12-07 10:31:24 -08001030 ForceUseGoma: proto.Bool(true),
1031 UseGoma: proto.Bool(false),
1032 UseRbe: proto.Bool(false),
1033 NinjaWeightListSource: smpb.BuildConfig_NOT_USED.Enum(),
Liz Kammerca9cb2e2021-07-14 15:29:57 -04001034 },
1035 },
1036 {
1037 name: "use goma",
1038 environ: Environment{"USE_GOMA=1"},
1039 expectedBuildConfig: &smpb.BuildConfig{
Colin Cross8d411ff2023-12-07 10:31:24 -08001040 ForceUseGoma: proto.Bool(false),
1041 UseGoma: proto.Bool(true),
1042 UseRbe: proto.Bool(false),
1043 NinjaWeightListSource: smpb.BuildConfig_NOT_USED.Enum(),
Liz Kammerca9cb2e2021-07-14 15:29:57 -04001044 },
1045 },
1046 {
Christopher Ferris1db36e32024-07-25 12:42:47 -07001047 // RBE is only supported on linux.
Liz Kammerca9cb2e2021-07-14 15:29:57 -04001048 name: "use rbe",
1049 environ: Environment{"USE_RBE=1"},
1050 expectedBuildConfig: &smpb.BuildConfig{
Colin Cross8d411ff2023-12-07 10:31:24 -08001051 ForceUseGoma: proto.Bool(false),
1052 UseGoma: proto.Bool(false),
Christopher Ferris1db36e32024-07-25 12:42:47 -07001053 UseRbe: proto.Bool(runtime.GOOS == "linux"),
Colin Cross8d411ff2023-12-07 10:31:24 -08001054 NinjaWeightListSource: smpb.BuildConfig_NOT_USED.Enum(),
Liz Kammerca9cb2e2021-07-14 15:29:57 -04001055 },
1056 },
1057 }
1058
1059 for _, tc := range tests {
1060 t.Run(tc.name, func(t *testing.T) {
1061 c := &configImpl{
Colin Cross8d411ff2023-12-07 10:31:24 -08001062 environ: &tc.environ,
1063 arguments: tc.arguments,
Liz Kammerca9cb2e2021-07-14 15:29:57 -04001064 }
1065 config := Config{c}
1066 actualBuildConfig := buildConfig(config)
1067 if expected := tc.expectedBuildConfig; !proto.Equal(expected, actualBuildConfig) {
Chris Parsonsef615e52022-08-18 22:04:11 -04001068 t.Errorf("Build config mismatch.\n"+
1069 "Expected build config: %#v\n"+
1070 "Actual build config: %#v", prototext.Format(expected), prototext.Format(actualBuildConfig))
Liz Kammerca9cb2e2021-07-14 15:29:57 -04001071 }
1072 })
1073 }
1074}
Yu Liu6e13b402021-07-27 14:29:06 -07001075
1076func TestGetMetricsUploaderApp(t *testing.T) {
1077
1078 metricsUploaderDir := "metrics_uploader_dir"
1079 metricsUploaderBinary := "metrics_uploader_binary"
1080 metricsUploaderPath := filepath.Join(metricsUploaderDir, metricsUploaderBinary)
1081 tests := []struct {
1082 description string
1083 environ Environment
1084 createFiles bool
1085 expected string
1086 }{{
1087 description: "Uploader binary exist",
1088 environ: Environment{"METRICS_UPLOADER=" + metricsUploaderPath},
1089 createFiles: true,
1090 expected: metricsUploaderPath,
1091 }, {
1092 description: "Uploader binary not exist",
1093 environ: Environment{"METRICS_UPLOADER=" + metricsUploaderPath},
1094 createFiles: false,
1095 expected: "",
1096 }, {
1097 description: "Uploader binary variable not set",
1098 createFiles: true,
1099 expected: "",
1100 }}
1101
1102 for _, tt := range tests {
1103 t.Run(tt.description, func(t *testing.T) {
1104 defer logger.Recover(func(err error) {
1105 t.Fatalf("got unexpected error: %v", err)
1106 })
1107
1108 // Create the root source tree.
1109 topDir, err := ioutil.TempDir("", "")
1110 if err != nil {
1111 t.Fatalf("failed to create temp dir: %v", err)
1112 }
1113 defer os.RemoveAll(topDir)
1114
1115 expected := tt.expected
1116 if len(expected) > 0 {
1117 expected = filepath.Join(topDir, expected)
1118 }
1119
1120 if tt.createFiles {
1121 if err := os.MkdirAll(filepath.Join(topDir, metricsUploaderDir), 0755); err != nil {
1122 t.Errorf("failed to create %s directory: %v", metricsUploaderDir, err)
1123 }
1124 if err := ioutil.WriteFile(filepath.Join(topDir, metricsUploaderPath), []byte{}, 0644); err != nil {
1125 t.Errorf("failed to create file %s: %v", expected, err)
1126 }
1127 }
1128
1129 actual := GetMetricsUploader(topDir, &tt.environ)
1130
1131 if actual != expected {
1132 t.Errorf("expecting: %s, actual: %s", expected, actual)
1133 }
1134 })
1135 }
1136}