blob: 10de1ad9631c2e29c132d1b0b537349490c67683 [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
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
Chris Parsonsb6e96902022-10-31 20:08:45 -040092 env := Environment([]string{})
Dan Willemsen9b587492017-07-10 22:13:00 -070093 c := &configImpl{
Chris Parsonsb6e96902022-10-31 20:08:45 -040094 environ: &env,
Dan Willemsen9b587492017-07-10 22:13:00 -070095 parallel: -1,
96 keepGoing: -1,
97 }
98 c.parseArgs(ctx, tc.args)
99
100 if c.parallel != tc.parallel {
101 t.Errorf("for %q, parallel:\nwant: %d\n got: %d\n",
102 strings.Join(tc.args, " "),
103 tc.parallel, c.parallel)
104 }
105 if c.keepGoing != tc.keepGoing {
106 t.Errorf("for %q, keep going:\nwant: %d\n got: %d\n",
107 strings.Join(tc.args, " "),
108 tc.keepGoing, c.keepGoing)
109 }
110 if !reflect.DeepEqual(c.arguments, tc.remaining) {
111 t.Errorf("for %q, remaining arguments:\nwant: %q\n got: %q\n",
112 strings.Join(tc.args, " "),
113 tc.remaining, c.arguments)
114 }
115 })
116 }
117}
Dan Willemsen091525e2017-07-11 14:17:50 -0700118
119func TestConfigParseArgsVars(t *testing.T) {
120 ctx := testContext()
121
122 testCases := []struct {
123 env []string
124 args []string
125
126 expectedEnv []string
127 remaining []string
128 }{
129 {},
130 {
131 env: []string{"A=bc"},
132
133 expectedEnv: []string{"A=bc"},
134 },
135 {
136 args: []string{"abc"},
137
138 remaining: []string{"abc"},
139 },
140
141 {
142 args: []string{"A=bc"},
143
144 expectedEnv: []string{"A=bc"},
145 },
146 {
147 env: []string{"A=a"},
148 args: []string{"A=bc"},
149
150 expectedEnv: []string{"A=bc"},
151 },
152
153 {
154 env: []string{"A=a"},
155 args: []string{"A=", "=b"},
156
157 expectedEnv: []string{"A="},
158 remaining: []string{"=b"},
159 },
160 }
161
162 for _, tc := range testCases {
163 t.Run(strings.Join(tc.args, " "), func(t *testing.T) {
164 defer logger.Recover(func(err error) {
165 t.Fatal(err)
166 })
167
168 e := Environment(tc.env)
169 c := &configImpl{
170 environ: &e,
171 }
172 c.parseArgs(ctx, tc.args)
173
174 if !reflect.DeepEqual([]string(*c.environ), tc.expectedEnv) {
175 t.Errorf("for env=%q args=%q, environment:\nwant: %q\n got: %q\n",
176 tc.env, tc.args,
177 tc.expectedEnv, []string(*c.environ))
178 }
179 if !reflect.DeepEqual(c.arguments, tc.remaining) {
180 t.Errorf("for env=%q args=%q, remaining arguments:\nwant: %q\n got: %q\n",
181 tc.env, tc.args,
182 tc.remaining, c.arguments)
183 }
184 })
185 }
186}
Patrice Arruda13848222019-04-22 17:12:02 -0700187
188func TestConfigCheckTopDir(t *testing.T) {
189 ctx := testContext()
190 buildRootDir := filepath.Dir(srcDirFileCheck)
191 expectedErrStr := fmt.Sprintf("Current working directory must be the source tree. %q not found.", srcDirFileCheck)
192
193 tests := []struct {
194 // ********* Setup *********
195 // Test description.
196 description string
197
198 // ********* Action *********
199 // If set to true, the build root file is created.
200 rootBuildFile bool
201
202 // The current path where Soong is being executed.
203 path string
204
205 // ********* Validation *********
206 // Expecting error and validate the error string against expectedErrStr.
207 wantErr bool
208 }{{
209 description: "current directory is the root source tree",
210 rootBuildFile: true,
211 path: ".",
212 wantErr: false,
213 }, {
214 description: "one level deep in the source tree",
215 rootBuildFile: true,
216 path: "1",
217 wantErr: true,
218 }, {
219 description: "very deep in the source tree",
220 rootBuildFile: true,
221 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",
222 wantErr: true,
223 }, {
224 description: "outside of source tree",
225 rootBuildFile: false,
226 path: "1/2/3/4/5",
227 wantErr: true,
228 }}
229
230 for _, tt := range tests {
231 t.Run(tt.description, func(t *testing.T) {
232 defer logger.Recover(func(err error) {
233 if !tt.wantErr {
234 t.Fatalf("Got unexpected error: %v", err)
235 }
236 if expectedErrStr != err.Error() {
237 t.Fatalf("expected %s, got %s", expectedErrStr, err.Error())
238 }
239 })
240
241 // Create the root source tree.
242 rootDir, err := ioutil.TempDir("", "")
243 if err != nil {
244 t.Fatal(err)
245 }
246 defer os.RemoveAll(rootDir)
247
248 // Create the build root file. This is to test if topDir returns an error if the build root
249 // file does not exist.
250 if tt.rootBuildFile {
251 dir := filepath.Join(rootDir, buildRootDir)
252 if err := os.MkdirAll(dir, 0755); err != nil {
253 t.Errorf("failed to create %s directory: %v", dir, err)
254 }
255 f := filepath.Join(rootDir, srcDirFileCheck)
256 if err := ioutil.WriteFile(f, []byte{}, 0644); err != nil {
257 t.Errorf("failed to create file %s: %v", f, err)
258 }
259 }
260
261 // Next block of code is to set the current directory.
262 dir := rootDir
263 if tt.path != "" {
264 dir = filepath.Join(dir, tt.path)
265 if err := os.MkdirAll(dir, 0755); err != nil {
266 t.Errorf("failed to create %s directory: %v", dir, err)
267 }
268 }
269 curDir, err := os.Getwd()
270 if err != nil {
271 t.Fatalf("failed to get the current directory: %v", err)
272 }
273 defer func() { os.Chdir(curDir) }()
274
275 if err := os.Chdir(dir); err != nil {
276 t.Fatalf("failed to change directory to %s: %v", dir, err)
277 }
278
279 checkTopDir(ctx)
280 })
281 }
282}
283
284func TestConfigConvertToTarget(t *testing.T) {
285 tests := []struct {
286 // ********* Setup *********
287 // Test description.
288 description string
289
290 // ********* Action *********
291 // The current directory where Soong is being executed.
292 dir string
293
294 // The current prefix string to be pre-appended to the target.
295 prefix string
296
297 // ********* Validation *********
298 // The expected target to be invoked in ninja.
299 expectedTarget string
300 }{{
301 description: "one level directory in source tree",
302 dir: "test1",
303 prefix: "MODULES-IN-",
304 expectedTarget: "MODULES-IN-test1",
305 }, {
306 description: "multiple level directories in source tree",
307 dir: "test1/test2/test3/test4",
308 prefix: "GET-INSTALL-PATH-IN-",
309 expectedTarget: "GET-INSTALL-PATH-IN-test1-test2-test3-test4",
310 }}
311 for _, tt := range tests {
312 t.Run(tt.description, func(t *testing.T) {
313 target := convertToTarget(tt.dir, tt.prefix)
314 if target != tt.expectedTarget {
315 t.Errorf("expected %s, got %s for target", tt.expectedTarget, target)
316 }
317 })
318 }
319}
320
321func setTop(t *testing.T, dir string) func() {
322 curDir, err := os.Getwd()
323 if err != nil {
324 t.Fatalf("failed to get current directory: %v", err)
325 }
326 if err := os.Chdir(dir); err != nil {
327 t.Fatalf("failed to change directory to top dir %s: %v", dir, err)
328 }
329 return func() { os.Chdir(curDir) }
330}
331
332func createBuildFiles(t *testing.T, topDir string, buildFiles []string) {
333 for _, buildFile := range buildFiles {
334 buildFile = filepath.Join(topDir, buildFile)
335 if err := ioutil.WriteFile(buildFile, []byte{}, 0644); err != nil {
336 t.Errorf("failed to create file %s: %v", buildFile, err)
337 }
338 }
339}
340
341func createDirectories(t *testing.T, topDir string, dirs []string) {
342 for _, dir := range dirs {
343 dir = filepath.Join(topDir, dir)
344 if err := os.MkdirAll(dir, 0755); err != nil {
345 t.Errorf("failed to create %s directory: %v", dir, err)
346 }
347 }
348}
349
350func TestConfigGetTargets(t *testing.T) {
351 ctx := testContext()
352 tests := []struct {
353 // ********* Setup *********
354 // Test description.
355 description string
356
357 // Directories that exist in the source tree.
358 dirsInTrees []string
359
360 // Build files that exists in the source tree.
361 buildFiles []string
362
363 // ********* Action *********
364 // Directories passed in to soong_ui.
365 dirs []string
366
367 // Current directory that the user executed the build action command.
368 curDir string
369
370 // ********* Validation *********
371 // Expected targets from the function.
372 expectedTargets []string
373
Patrice Arruda13848222019-04-22 17:12:02 -0700374 // Expecting error from running test case.
375 errStr string
376 }{{
Dan Willemsence41e942019-07-29 23:39:30 -0700377 description: "one target dir specified",
378 dirsInTrees: []string{"0/1/2/3"},
379 buildFiles: []string{"0/1/2/3/Android.bp"},
380 dirs: []string{"1/2/3"},
381 curDir: "0",
382 expectedTargets: []string{"MODULES-IN-0-1-2-3"},
Patrice Arruda13848222019-04-22 17:12:02 -0700383 }, {
384 description: "one target dir specified, build file does not exist",
385 dirsInTrees: []string{"0/1/2/3"},
386 buildFiles: []string{},
387 dirs: []string{"1/2/3"},
388 curDir: "0",
389 errStr: "Build file not found for 0/1/2/3 directory",
390 }, {
391 description: "one target dir specified, invalid targets specified",
392 dirsInTrees: []string{"0/1/2/3"},
393 buildFiles: []string{},
394 dirs: []string{"1/2/3:t1:t2"},
395 curDir: "0",
396 errStr: "1/2/3:t1:t2 not in proper directory:target1,target2,... format (\":\" was specified more than once)",
397 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700398 description: "one target dir specified, no targets specified but has colon",
399 dirsInTrees: []string{"0/1/2/3"},
400 buildFiles: []string{"0/1/2/3/Android.bp"},
401 dirs: []string{"1/2/3:"},
402 curDir: "0",
403 expectedTargets: []string{"MODULES-IN-0-1-2-3"},
Patrice Arruda13848222019-04-22 17:12:02 -0700404 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700405 description: "one target dir specified, two targets specified",
406 dirsInTrees: []string{"0/1/2/3"},
407 buildFiles: []string{"0/1/2/3/Android.bp"},
408 dirs: []string{"1/2/3:t1,t2"},
409 curDir: "0",
410 expectedTargets: []string{"t1", "t2"},
Patrice Arruda13848222019-04-22 17:12:02 -0700411 }, {
412 description: "one target dir specified, no targets and has a comma",
413 dirsInTrees: []string{"0/1/2/3"},
414 buildFiles: []string{"0/1/2/3/Android.bp"},
415 dirs: []string{"1/2/3:,"},
416 curDir: "0",
417 errStr: "0/1/2/3 not in proper directory:target1,target2,... format",
418 }, {
419 description: "one target dir specified, improper targets defined",
420 dirsInTrees: []string{"0/1/2/3"},
421 buildFiles: []string{"0/1/2/3/Android.bp"},
422 dirs: []string{"1/2/3:,t1"},
423 curDir: "0",
424 errStr: "0/1/2/3 not in proper directory:target1,target2,... format",
425 }, {
426 description: "one target dir specified, blank target",
427 dirsInTrees: []string{"0/1/2/3"},
428 buildFiles: []string{"0/1/2/3/Android.bp"},
429 dirs: []string{"1/2/3:t1,"},
430 curDir: "0",
431 errStr: "0/1/2/3 not in proper directory:target1,target2,... format",
432 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700433 description: "one target dir specified, many targets specified",
434 dirsInTrees: []string{"0/1/2/3"},
435 buildFiles: []string{"0/1/2/3/Android.bp"},
436 dirs: []string{"1/2/3:t1,t2,t3,t4,t5,t6,t7,t8,t9,t10"},
437 curDir: "0",
438 expectedTargets: []string{"t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9", "t10"},
Patrice Arruda13848222019-04-22 17:12:02 -0700439 }, {
440 description: "one target dir specified, one target specified, build file does not exist",
441 dirsInTrees: []string{"0/1/2/3"},
442 buildFiles: []string{},
443 dirs: []string{"1/2/3:t1"},
444 curDir: "0",
Patrice Arruda9450d0b2019-07-08 11:06:46 -0700445 errStr: "Couldn't locate a build file from 0/1/2/3 directory",
Patrice Arruda13848222019-04-22 17:12:02 -0700446 }, {
447 description: "one target dir specified, one target specified, build file not in target dir",
448 dirsInTrees: []string{"0/1/2/3"},
449 buildFiles: []string{"0/1/2/Android.mk"},
450 dirs: []string{"1/2/3:t1"},
451 curDir: "0",
452 errStr: "Couldn't locate a build file from 0/1/2/3 directory",
453 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700454 description: "one target dir specified, build file not in target dir",
455 dirsInTrees: []string{"0/1/2/3"},
456 buildFiles: []string{"0/1/2/Android.mk"},
457 dirs: []string{"1/2/3"},
458 curDir: "0",
459 expectedTargets: []string{"MODULES-IN-0-1-2"},
Patrice Arruda13848222019-04-22 17:12:02 -0700460 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700461 description: "multiple targets dir specified, targets specified",
462 dirsInTrees: []string{"0/1/2/3", "0/3/4"},
463 buildFiles: []string{"0/1/2/3/Android.bp", "0/3/4/Android.mk"},
464 dirs: []string{"1/2/3:t1,t2", "3/4:t3,t4,t5"},
465 curDir: "0",
466 expectedTargets: []string{"t1", "t2", "t3", "t4", "t5"},
Patrice Arruda13848222019-04-22 17:12:02 -0700467 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700468 description: "multiple targets dir specified, one directory has targets specified",
469 dirsInTrees: []string{"0/1/2/3", "0/3/4"},
470 buildFiles: []string{"0/1/2/3/Android.bp", "0/3/4/Android.mk"},
471 dirs: []string{"1/2/3:t1,t2", "3/4"},
472 curDir: "0",
473 expectedTargets: []string{"t1", "t2", "MODULES-IN-0-3-4"},
Patrice Arruda13848222019-04-22 17:12:02 -0700474 }, {
475 description: "two dirs specified, only one dir exist",
476 dirsInTrees: []string{"0/1/2/3"},
477 buildFiles: []string{"0/1/2/3/Android.mk"},
478 dirs: []string{"1/2/3:t1", "3/4"},
479 curDir: "0",
480 errStr: "couldn't find directory 0/3/4",
481 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700482 description: "multiple targets dirs specified at root source tree",
483 dirsInTrees: []string{"0/1/2/3", "0/3/4"},
484 buildFiles: []string{"0/1/2/3/Android.bp", "0/3/4/Android.mk"},
485 dirs: []string{"0/1/2/3:t1,t2", "0/3/4"},
486 curDir: ".",
487 expectedTargets: []string{"t1", "t2", "MODULES-IN-0-3-4"},
Patrice Arruda13848222019-04-22 17:12:02 -0700488 }, {
489 description: "no directories specified",
490 dirsInTrees: []string{"0/1/2/3", "0/3/4"},
491 buildFiles: []string{"0/1/2/3/Android.bp", "0/3/4/Android.mk"},
492 dirs: []string{},
493 curDir: ".",
494 }}
495 for _, tt := range tests {
496 t.Run(tt.description, func(t *testing.T) {
497 defer logger.Recover(func(err error) {
498 if tt.errStr == "" {
499 t.Fatalf("Got unexpected error: %v", err)
500 }
501 if tt.errStr != err.Error() {
502 t.Errorf("expected %s, got %s", tt.errStr, err.Error())
503 }
504 })
505
506 // Create the root source tree.
507 topDir, err := ioutil.TempDir("", "")
508 if err != nil {
509 t.Fatalf("failed to create temp dir: %v", err)
510 }
511 defer os.RemoveAll(topDir)
512
513 createDirectories(t, topDir, tt.dirsInTrees)
514 createBuildFiles(t, topDir, tt.buildFiles)
515 r := setTop(t, topDir)
516 defer r()
517
Dan Willemsence41e942019-07-29 23:39:30 -0700518 targets := getTargetsFromDirs(ctx, tt.curDir, tt.dirs, "MODULES-IN-")
Patrice Arruda13848222019-04-22 17:12:02 -0700519 if !reflect.DeepEqual(targets, tt.expectedTargets) {
520 t.Errorf("expected %v, got %v for targets", tt.expectedTargets, targets)
521 }
Patrice Arruda13848222019-04-22 17:12:02 -0700522
523 // If the execution reached here and there was an expected error code, the unit test case failed.
524 if tt.errStr != "" {
525 t.Errorf("expecting error %s", tt.errStr)
526 }
527 })
528 }
529}
530
531func TestConfigFindBuildFile(t *testing.T) {
532 ctx := testContext()
533
534 tests := []struct {
535 // ********* Setup *********
536 // Test description.
537 description string
538
539 // Array of build files to create in dir.
540 buildFiles []string
541
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700542 // Directories that exist in the source tree.
543 dirsInTrees []string
544
Patrice Arruda13848222019-04-22 17:12:02 -0700545 // ********* Action *********
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700546 // The base directory is where findBuildFile is invoked.
Patrice Arruda13848222019-04-22 17:12:02 -0700547 dir string
548
549 // ********* Validation *********
550 // Expected build file path to find.
551 expectedBuildFile string
552 }{{
553 description: "build file exists at leaf directory",
554 buildFiles: []string{"1/2/3/Android.bp"},
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700555 dirsInTrees: []string{"1/2/3"},
Patrice Arruda13848222019-04-22 17:12:02 -0700556 dir: "1/2/3",
557 expectedBuildFile: "1/2/3/Android.mk",
558 }, {
559 description: "build file exists in all directory paths",
560 buildFiles: []string{"1/Android.mk", "1/2/Android.mk", "1/2/3/Android.mk"},
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700561 dirsInTrees: []string{"1/2/3"},
Patrice Arruda13848222019-04-22 17:12:02 -0700562 dir: "1/2/3",
563 expectedBuildFile: "1/2/3/Android.mk",
564 }, {
565 description: "build file does not exist in all directory paths",
566 buildFiles: []string{},
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700567 dirsInTrees: []string{"1/2/3"},
Patrice Arruda13848222019-04-22 17:12:02 -0700568 dir: "1/2/3",
569 expectedBuildFile: "",
570 }, {
571 description: "build file exists only at top directory",
572 buildFiles: []string{"Android.bp"},
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700573 dirsInTrees: []string{"1/2/3"},
Patrice Arruda13848222019-04-22 17:12:02 -0700574 dir: "1/2/3",
575 expectedBuildFile: "",
576 }, {
577 description: "build file exist in a subdirectory",
578 buildFiles: []string{"1/2/Android.bp"},
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700579 dirsInTrees: []string{"1/2/3"},
Patrice Arruda13848222019-04-22 17:12:02 -0700580 dir: "1/2/3",
581 expectedBuildFile: "1/2/Android.mk",
582 }, {
583 description: "build file exists in a subdirectory",
584 buildFiles: []string{"1/Android.mk"},
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700585 dirsInTrees: []string{"1/2/3"},
Patrice Arruda13848222019-04-22 17:12:02 -0700586 dir: "1/2/3",
587 expectedBuildFile: "1/Android.mk",
588 }, {
589 description: "top directory",
590 buildFiles: []string{"Android.bp"},
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700591 dirsInTrees: []string{},
Patrice Arruda13848222019-04-22 17:12:02 -0700592 dir: ".",
593 expectedBuildFile: "",
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700594 }, {
595 description: "build file exists in subdirectory",
596 buildFiles: []string{"1/2/3/Android.bp", "1/2/4/Android.bp"},
597 dirsInTrees: []string{"1/2/3", "1/2/4"},
598 dir: "1/2",
599 expectedBuildFile: "1/2/Android.mk",
600 }, {
601 description: "build file exists in parent subdirectory",
602 buildFiles: []string{"1/5/Android.bp"},
603 dirsInTrees: []string{"1/2/3", "1/2/4", "1/5"},
604 dir: "1/2",
605 expectedBuildFile: "1/Android.mk",
606 }, {
607 description: "build file exists in deep parent's subdirectory.",
608 buildFiles: []string{"1/5/6/Android.bp"},
609 dirsInTrees: []string{"1/2/3", "1/2/4", "1/5/6", "1/5/7"},
610 dir: "1/2",
611 expectedBuildFile: "1/Android.mk",
Patrice Arruda13848222019-04-22 17:12:02 -0700612 }}
613
614 for _, tt := range tests {
615 t.Run(tt.description, func(t *testing.T) {
616 defer logger.Recover(func(err error) {
617 t.Fatalf("Got unexpected error: %v", err)
618 })
619
620 topDir, err := ioutil.TempDir("", "")
621 if err != nil {
622 t.Fatalf("failed to create temp dir: %v", err)
623 }
624 defer os.RemoveAll(topDir)
625
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700626 createDirectories(t, topDir, tt.dirsInTrees)
Patrice Arruda13848222019-04-22 17:12:02 -0700627 createBuildFiles(t, topDir, tt.buildFiles)
628
629 curDir, err := os.Getwd()
630 if err != nil {
631 t.Fatalf("Could not get working directory: %v", err)
632 }
633 defer func() { os.Chdir(curDir) }()
634 if err := os.Chdir(topDir); err != nil {
635 t.Fatalf("Could not change top dir to %s: %v", topDir, err)
636 }
637
638 buildFile := findBuildFile(ctx, tt.dir)
639 if buildFile != tt.expectedBuildFile {
640 t.Errorf("expected %q, got %q for build file", tt.expectedBuildFile, buildFile)
641 }
642 })
643 }
644}
645
646func TestConfigSplitArgs(t *testing.T) {
647 tests := []struct {
648 // ********* Setup *********
649 // Test description.
650 description string
651
652 // ********* Action *********
653 // Arguments passed in to soong_ui.
654 args []string
655
656 // ********* Validation *********
657 // Expected newArgs list after extracting the directories.
658 expectedNewArgs []string
659
660 // Expected directories
661 expectedDirs []string
662 }{{
663 description: "flags but no directories specified",
664 args: []string{"showcommands", "-j", "-k"},
665 expectedNewArgs: []string{"showcommands", "-j", "-k"},
666 expectedDirs: []string{},
667 }, {
668 description: "flags and one directory specified",
669 args: []string{"snod", "-j", "dir:target1,target2"},
670 expectedNewArgs: []string{"snod", "-j"},
671 expectedDirs: []string{"dir:target1,target2"},
672 }, {
673 description: "flags and directories specified",
674 args: []string{"dist", "-k", "dir1", "dir2:target1,target2"},
675 expectedNewArgs: []string{"dist", "-k"},
676 expectedDirs: []string{"dir1", "dir2:target1,target2"},
677 }, {
678 description: "only directories specified",
679 args: []string{"dir1", "dir2", "dir3:target1,target2"},
680 expectedNewArgs: []string{},
681 expectedDirs: []string{"dir1", "dir2", "dir3:target1,target2"},
682 }}
683 for _, tt := range tests {
684 t.Run(tt.description, func(t *testing.T) {
685 args, dirs := splitArgs(tt.args)
686 if !reflect.DeepEqual(tt.expectedNewArgs, args) {
687 t.Errorf("expected %v, got %v for arguments", tt.expectedNewArgs, args)
688 }
689 if !reflect.DeepEqual(tt.expectedDirs, dirs) {
690 t.Errorf("expected %v, got %v for directories", tt.expectedDirs, dirs)
691 }
692 })
693 }
694}
695
696type envVar struct {
697 name string
698 value string
699}
700
701type buildActionTestCase struct {
702 // ********* Setup *********
703 // Test description.
704 description string
705
706 // Directories that exist in the source tree.
707 dirsInTrees []string
708
709 // Build files that exists in the source tree.
710 buildFiles []string
711
Patrice Arrudababa9a92019-07-03 10:47:34 -0700712 // Create root symlink that points to topDir.
713 rootSymlink bool
714
Patrice Arruda13848222019-04-22 17:12:02 -0700715 // ********* Action *********
716 // Arguments passed in to soong_ui.
717 args []string
718
719 // Directory where the build action was invoked.
720 curDir string
721
722 // WITH_TIDY_ONLY environment variable specified.
723 tidyOnly string
724
725 // ********* Validation *********
726 // Expected arguments to be in Config instance.
727 expectedArgs []string
728
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700729 // Expecting error from running test case.
730 expectedErrStr string
Patrice Arruda13848222019-04-22 17:12:02 -0700731}
732
Dan Willemsence41e942019-07-29 23:39:30 -0700733func testGetConfigArgs(t *testing.T, tt buildActionTestCase, action BuildAction) {
Patrice Arruda13848222019-04-22 17:12:02 -0700734 ctx := testContext()
735
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700736 defer logger.Recover(func(err error) {
737 if tt.expectedErrStr == "" {
738 t.Fatalf("Got unexpected error: %v", err)
739 }
740 if tt.expectedErrStr != err.Error() {
741 t.Errorf("expected %s, got %s", tt.expectedErrStr, err.Error())
742 }
743 })
744
Patrice Arruda13848222019-04-22 17:12:02 -0700745 // Environment variables to set it to blank on every test case run.
746 resetEnvVars := []string{
Patrice Arruda13848222019-04-22 17:12:02 -0700747 "WITH_TIDY_ONLY",
748 }
749
750 for _, name := range resetEnvVars {
751 if err := os.Unsetenv(name); err != nil {
752 t.Fatalf("failed to unset environment variable %s: %v", name, err)
753 }
754 }
755 if tt.tidyOnly != "" {
756 if err := os.Setenv("WITH_TIDY_ONLY", tt.tidyOnly); err != nil {
757 t.Errorf("failed to set WITH_TIDY_ONLY to %s: %v", tt.tidyOnly, err)
758 }
759 }
760
761 // Create the root source tree.
762 topDir, err := ioutil.TempDir("", "")
763 if err != nil {
764 t.Fatalf("failed to create temp dir: %v", err)
765 }
766 defer os.RemoveAll(topDir)
767
768 createDirectories(t, topDir, tt.dirsInTrees)
769 createBuildFiles(t, topDir, tt.buildFiles)
770
Patrice Arrudababa9a92019-07-03 10:47:34 -0700771 if tt.rootSymlink {
772 // Create a secondary root source tree which points to the true root source tree.
773 symlinkTopDir, err := ioutil.TempDir("", "")
774 if err != nil {
775 t.Fatalf("failed to create symlink temp dir: %v", err)
776 }
777 defer os.RemoveAll(symlinkTopDir)
778
779 symlinkTopDir = filepath.Join(symlinkTopDir, "root")
780 err = os.Symlink(topDir, symlinkTopDir)
781 if err != nil {
782 t.Fatalf("failed to create symlink: %v", err)
783 }
784 topDir = symlinkTopDir
785 }
786
Patrice Arruda13848222019-04-22 17:12:02 -0700787 r := setTop(t, topDir)
788 defer r()
789
790 // The next block is to create the root build file.
791 rootBuildFileDir := filepath.Dir(srcDirFileCheck)
792 if err := os.MkdirAll(rootBuildFileDir, 0755); err != nil {
793 t.Fatalf("Failed to create %s directory: %v", rootBuildFileDir, err)
794 }
795
796 if err := ioutil.WriteFile(srcDirFileCheck, []byte{}, 0644); err != nil {
797 t.Fatalf("failed to create %s file: %v", srcDirFileCheck, err)
798 }
799
Dan Willemsence41e942019-07-29 23:39:30 -0700800 args := getConfigArgs(action, tt.curDir, ctx, tt.args)
Patrice Arruda13848222019-04-22 17:12:02 -0700801 if !reflect.DeepEqual(tt.expectedArgs, args) {
802 t.Fatalf("expected %v, got %v for config arguments", tt.expectedArgs, args)
803 }
804
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700805 // If the execution reached here and there was an expected error code, the unit test case failed.
806 if tt.expectedErrStr != "" {
807 t.Errorf("expecting error %s", tt.expectedErrStr)
808 }
Patrice Arruda13848222019-04-22 17:12:02 -0700809}
810
Patrice Arruda39282062019-06-20 16:35:12 -0700811func TestGetConfigArgsBuildModules(t *testing.T) {
812 tests := []buildActionTestCase{{
Dan Willemsence41e942019-07-29 23:39:30 -0700813 description: "normal execution from the root source tree directory",
814 dirsInTrees: []string{"0/1/2", "0/2", "0/3"},
815 buildFiles: []string{"0/1/2/Android.mk", "0/2/Android.bp", "0/3/Android.mk"},
816 args: []string{"-j", "fake_module", "fake_module2"},
817 curDir: ".",
818 tidyOnly: "",
819 expectedArgs: []string{"-j", "fake_module", "fake_module2"},
Patrice Arruda39282062019-06-20 16:35:12 -0700820 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700821 description: "normal execution in deep directory",
822 dirsInTrees: []string{"0/1/2", "0/2", "0/3", "1/2/3/4/5/6/7/8/9/1/2/3/4/5/6"},
823 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"},
824 args: []string{"-j", "fake_module", "fake_module2", "-k"},
825 curDir: "1/2/3/4/5/6/7/8/9",
826 tidyOnly: "",
827 expectedArgs: []string{"-j", "fake_module", "fake_module2", "-k"},
Patrice Arruda39282062019-06-20 16:35:12 -0700828 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700829 description: "normal execution in deep directory, no targets",
830 dirsInTrees: []string{"0/1/2", "0/2", "0/3", "1/2/3/4/5/6/7/8/9/1/2/3/4/5/6"},
831 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"},
832 args: []string{"-j", "-k"},
833 curDir: "1/2/3/4/5/6/7/8/9",
834 tidyOnly: "",
835 expectedArgs: []string{"-j", "-k"},
Patrice Arruda39282062019-06-20 16:35:12 -0700836 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700837 description: "normal execution in root source tree, no args",
838 dirsInTrees: []string{"0/1/2", "0/2", "0/3"},
839 buildFiles: []string{"0/1/2/Android.mk", "0/2/Android.bp"},
840 args: []string{},
841 curDir: "0/2",
842 tidyOnly: "",
843 expectedArgs: []string{},
Patrice Arrudababa9a92019-07-03 10:47:34 -0700844 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700845 description: "normal execution in symlink root source tree, no args",
846 dirsInTrees: []string{"0/1/2", "0/2", "0/3"},
847 buildFiles: []string{"0/1/2/Android.mk", "0/2/Android.bp"},
848 rootSymlink: true,
849 args: []string{},
850 curDir: "0/2",
851 tidyOnly: "",
852 expectedArgs: []string{},
Patrice Arruda39282062019-06-20 16:35:12 -0700853 }}
854 for _, tt := range tests {
855 t.Run("build action BUILD_MODULES with dependencies, "+tt.description, func(t *testing.T) {
Dan Willemsence41e942019-07-29 23:39:30 -0700856 testGetConfigArgs(t, tt, BUILD_MODULES)
Patrice Arruda13848222019-04-22 17:12:02 -0700857 })
858 }
859}
860
861func TestGetConfigArgsBuildModulesInDirectory(t *testing.T) {
Cole Faust331b27f2024-02-28 15:35:49 -0800862 tests := []buildActionTestCase{
863 {
864 description: "normal execution in a directory",
865 dirsInTrees: []string{"0/1/2"},
866 buildFiles: []string{"0/1/2/Android.mk"},
867 args: []string{"fake-module"},
868 curDir: "0/1/2",
869 tidyOnly: "",
870 expectedArgs: []string{"fake-module", "MODULES-IN-0-1-2"},
871 }, {
872 description: "build file in parent directory",
873 dirsInTrees: []string{"0/1/2"},
874 buildFiles: []string{"0/1/Android.mk"},
875 args: []string{},
876 curDir: "0/1/2",
877 tidyOnly: "",
878 expectedArgs: []string{"MODULES-IN-0-1"},
879 },
Patrice Arruda13848222019-04-22 17:12:02 -0700880 {
Dan Willemsence41e942019-07-29 23:39:30 -0700881 description: "build file in parent directory, multiple module names passed in",
882 dirsInTrees: []string{"0/1/2"},
883 buildFiles: []string{"0/1/Android.mk"},
884 args: []string{"fake-module1", "fake-module2", "fake-module3"},
885 curDir: "0/1/2",
886 tidyOnly: "",
887 expectedArgs: []string{"fake-module1", "fake-module2", "fake-module3", "MODULES-IN-0-1"},
Patrice Arruda13848222019-04-22 17:12:02 -0700888 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700889 description: "build file in 2nd level parent directory",
890 dirsInTrees: []string{"0/1/2"},
891 buildFiles: []string{"0/Android.bp"},
892 args: []string{},
893 curDir: "0/1/2",
894 tidyOnly: "",
895 expectedArgs: []string{"MODULES-IN-0"},
Patrice Arruda13848222019-04-22 17:12:02 -0700896 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700897 description: "build action executed at root directory",
898 dirsInTrees: []string{},
899 buildFiles: []string{},
900 rootSymlink: false,
901 args: []string{},
902 curDir: ".",
903 tidyOnly: "",
904 expectedArgs: []string{},
Patrice Arrudababa9a92019-07-03 10:47:34 -0700905 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700906 description: "build action executed at root directory in symlink",
907 dirsInTrees: []string{},
908 buildFiles: []string{},
909 rootSymlink: true,
910 args: []string{},
911 curDir: ".",
912 tidyOnly: "",
913 expectedArgs: []string{},
Patrice Arruda13848222019-04-22 17:12:02 -0700914 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700915 description: "build file not found",
916 dirsInTrees: []string{"0/1/2"},
917 buildFiles: []string{},
918 args: []string{},
919 curDir: "0/1/2",
920 tidyOnly: "",
921 expectedArgs: []string{"MODULES-IN-0-1-2"},
922 expectedErrStr: "Build file not found for 0/1/2 directory",
Patrice Arruda13848222019-04-22 17:12:02 -0700923 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700924 description: "GET-INSTALL-PATH specified,",
925 dirsInTrees: []string{"0/1/2"},
926 buildFiles: []string{"0/1/Android.mk"},
927 args: []string{"GET-INSTALL-PATH", "-j", "-k", "GET-INSTALL-PATH"},
928 curDir: "0/1/2",
929 tidyOnly: "",
930 expectedArgs: []string{"-j", "-k", "GET-INSTALL-PATH-IN-0-1"},
Patrice Arruda13848222019-04-22 17:12:02 -0700931 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700932 description: "tidy only environment variable specified,",
933 dirsInTrees: []string{"0/1/2"},
934 buildFiles: []string{"0/1/Android.mk"},
935 args: []string{"GET-INSTALL-PATH"},
936 curDir: "0/1/2",
937 tidyOnly: "true",
938 expectedArgs: []string{"tidy_only"},
Patrice Arruda13848222019-04-22 17:12:02 -0700939 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700940 description: "normal execution in root directory with args",
941 dirsInTrees: []string{},
942 buildFiles: []string{},
943 args: []string{"-j", "-k", "fake_module"},
944 curDir: "",
945 tidyOnly: "",
946 expectedArgs: []string{"-j", "-k", "fake_module"},
Cole Faust331b27f2024-02-28 15:35:49 -0800947 },
948 }
Patrice Arruda13848222019-04-22 17:12:02 -0700949 for _, tt := range tests {
950 t.Run("build action BUILD_MODULES_IN_DIR, "+tt.description, func(t *testing.T) {
Dan Willemsence41e942019-07-29 23:39:30 -0700951 testGetConfigArgs(t, tt, BUILD_MODULES_IN_A_DIRECTORY)
Patrice Arruda13848222019-04-22 17:12:02 -0700952 })
953 }
954}
955
956func TestGetConfigArgsBuildModulesInDirectories(t *testing.T) {
957 tests := []buildActionTestCase{{
958 description: "normal execution in a directory",
959 dirsInTrees: []string{"0/1/2/3.1", "0/1/2/3.2", "0/1/2/3.3"},
960 buildFiles: []string{"0/1/2/3.1/Android.bp", "0/1/2/3.2/Android.bp", "0/1/2/3.3/Android.bp"},
961 args: []string{"3.1/", "3.2/", "3.3/"},
962 curDir: "0/1/2",
963 tidyOnly: "",
964 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 -0700965 }, {
966 description: "GET-INSTALL-PATH specified",
967 dirsInTrees: []string{"0/1/2/3.1", "0/1/2/3.2", "0/1/3"},
968 buildFiles: []string{"0/1/2/3.1/Android.bp", "0/1/2/3.2/Android.bp", "0/1/Android.bp"},
969 args: []string{"GET-INSTALL-PATH", "2/3.1/", "2/3.2", "3"},
970 curDir: "0/1",
971 tidyOnly: "",
972 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 -0700973 }, {
974 description: "tidy only environment variable specified",
975 dirsInTrees: []string{"0/1/2/3.1", "0/1/2/3.2", "0/1/2/3.3"},
976 buildFiles: []string{"0/1/2/3.1/Android.bp", "0/1/2/3.2/Android.bp", "0/1/2/3.3/Android.bp"},
977 args: []string{"GET-INSTALL-PATH", "3.1/", "3.2/", "3.3"},
978 curDir: "0/1/2",
979 tidyOnly: "1",
980 expectedArgs: []string{"tidy_only"},
Patrice Arruda13848222019-04-22 17:12:02 -0700981 }, {
982 description: "normal execution from top dir directory",
983 dirsInTrees: []string{"0/1/2/3.1", "0/1/2/3.2", "0/1/3", "0/2"},
984 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 -0700985 rootSymlink: false,
986 args: []string{"0/1/2/3.1", "0/1/2/3.2", "0/1/3", "0/2"},
987 curDir: ".",
988 tidyOnly: "",
989 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 -0700990 }, {
991 description: "normal execution from top dir directory in symlink",
992 dirsInTrees: []string{"0/1/2/3.1", "0/1/2/3.2", "0/1/3", "0/2"},
993 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"},
994 rootSymlink: true,
Patrice Arruda13848222019-04-22 17:12:02 -0700995 args: []string{"0/1/2/3.1", "0/1/2/3.2", "0/1/3", "0/2"},
996 curDir: ".",
997 tidyOnly: "",
998 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 -0700999 }}
1000 for _, tt := range tests {
1001 t.Run("build action BUILD_MODULES_IN_DIRS, "+tt.description, func(t *testing.T) {
Dan Willemsence41e942019-07-29 23:39:30 -07001002 testGetConfigArgs(t, tt, BUILD_MODULES_IN_DIRECTORIES)
Patrice Arruda13848222019-04-22 17:12:02 -07001003 })
1004 }
1005}
Liz Kammerca9cb2e2021-07-14 15:29:57 -04001006
Joe Onoratoe84ec902025-01-29 17:56:57 -08001007func assertEquals[T ~bool | ~int32](t *testing.T, name string, expected, actual T) {
1008 if expected != actual {
1009 t.Errorf("Expected %s: %#v\nActual %s: %#v", name, expected, name, actual)
1010 }
1011}
1012
Liz Kammerca9cb2e2021-07-14 15:29:57 -04001013func TestBuildConfig(t *testing.T) {
1014 tests := []struct {
1015 name string
1016 environ Environment
Yu Liue737a992021-10-04 13:21:41 -07001017 arguments []string
Liz Kammerca9cb2e2021-07-14 15:29:57 -04001018 expectedBuildConfig *smpb.BuildConfig
1019 }{
1020 {
1021 name: "none set",
1022 environ: Environment{},
1023 expectedBuildConfig: &smpb.BuildConfig{
Colin Cross8d411ff2023-12-07 10:31:24 -08001024 ForceUseGoma: proto.Bool(false),
1025 UseGoma: proto.Bool(false),
1026 UseRbe: proto.Bool(false),
1027 NinjaWeightListSource: smpb.BuildConfig_NOT_USED.Enum(),
Liz Kammerca9cb2e2021-07-14 15:29:57 -04001028 },
1029 },
1030 {
1031 name: "force use goma",
1032 environ: Environment{"FORCE_USE_GOMA=1"},
1033 expectedBuildConfig: &smpb.BuildConfig{
Colin Cross8d411ff2023-12-07 10:31:24 -08001034 ForceUseGoma: proto.Bool(true),
1035 UseGoma: proto.Bool(false),
1036 UseRbe: proto.Bool(false),
1037 NinjaWeightListSource: smpb.BuildConfig_NOT_USED.Enum(),
Liz Kammerca9cb2e2021-07-14 15:29:57 -04001038 },
1039 },
1040 {
1041 name: "use goma",
1042 environ: Environment{"USE_GOMA=1"},
1043 expectedBuildConfig: &smpb.BuildConfig{
Colin Cross8d411ff2023-12-07 10:31:24 -08001044 ForceUseGoma: proto.Bool(false),
1045 UseGoma: proto.Bool(true),
1046 UseRbe: proto.Bool(false),
1047 NinjaWeightListSource: smpb.BuildConfig_NOT_USED.Enum(),
Liz Kammerca9cb2e2021-07-14 15:29:57 -04001048 },
1049 },
1050 {
Christopher Ferris1db36e32024-07-25 12:42:47 -07001051 // RBE is only supported on linux.
Liz Kammerca9cb2e2021-07-14 15:29:57 -04001052 name: "use rbe",
1053 environ: Environment{"USE_RBE=1"},
1054 expectedBuildConfig: &smpb.BuildConfig{
Colin Cross8d411ff2023-12-07 10:31:24 -08001055 ForceUseGoma: proto.Bool(false),
1056 UseGoma: proto.Bool(false),
Christopher Ferris1db36e32024-07-25 12:42:47 -07001057 UseRbe: proto.Bool(runtime.GOOS == "linux"),
Colin Cross8d411ff2023-12-07 10:31:24 -08001058 NinjaWeightListSource: smpb.BuildConfig_NOT_USED.Enum(),
Liz Kammerca9cb2e2021-07-14 15:29:57 -04001059 },
1060 },
1061 }
1062
1063 for _, tc := range tests {
1064 t.Run(tc.name, func(t *testing.T) {
1065 c := &configImpl{
Colin Cross8d411ff2023-12-07 10:31:24 -08001066 environ: &tc.environ,
1067 arguments: tc.arguments,
Liz Kammerca9cb2e2021-07-14 15:29:57 -04001068 }
1069 config := Config{c}
Joe Onoratoe84ec902025-01-29 17:56:57 -08001070 actual := buildConfig(config)
1071 assertEquals(t, "ForceUseGoma", *tc.expectedBuildConfig.ForceUseGoma, *actual.ForceUseGoma)
1072 assertEquals(t, "UseGoma", *tc.expectedBuildConfig.UseGoma, *actual.UseGoma)
1073 assertEquals(t, "UseRbe", *tc.expectedBuildConfig.UseRbe, *actual.UseRbe)
1074 assertEquals(t, "NinjaWeightListSource", *tc.expectedBuildConfig.NinjaWeightListSource, *actual.NinjaWeightListSource)
Liz Kammerca9cb2e2021-07-14 15:29:57 -04001075 })
1076 }
1077}
Yu Liu6e13b402021-07-27 14:29:06 -07001078
1079func TestGetMetricsUploaderApp(t *testing.T) {
1080
1081 metricsUploaderDir := "metrics_uploader_dir"
1082 metricsUploaderBinary := "metrics_uploader_binary"
1083 metricsUploaderPath := filepath.Join(metricsUploaderDir, metricsUploaderBinary)
1084 tests := []struct {
1085 description string
1086 environ Environment
1087 createFiles bool
1088 expected string
1089 }{{
1090 description: "Uploader binary exist",
1091 environ: Environment{"METRICS_UPLOADER=" + metricsUploaderPath},
1092 createFiles: true,
1093 expected: metricsUploaderPath,
1094 }, {
1095 description: "Uploader binary not exist",
1096 environ: Environment{"METRICS_UPLOADER=" + metricsUploaderPath},
1097 createFiles: false,
1098 expected: "",
1099 }, {
1100 description: "Uploader binary variable not set",
1101 createFiles: true,
1102 expected: "",
1103 }}
1104
1105 for _, tt := range tests {
1106 t.Run(tt.description, func(t *testing.T) {
1107 defer logger.Recover(func(err error) {
1108 t.Fatalf("got unexpected error: %v", err)
1109 })
1110
1111 // Create the root source tree.
1112 topDir, err := ioutil.TempDir("", "")
1113 if err != nil {
1114 t.Fatalf("failed to create temp dir: %v", err)
1115 }
1116 defer os.RemoveAll(topDir)
1117
1118 expected := tt.expected
1119 if len(expected) > 0 {
1120 expected = filepath.Join(topDir, expected)
1121 }
1122
1123 if tt.createFiles {
1124 if err := os.MkdirAll(filepath.Join(topDir, metricsUploaderDir), 0755); err != nil {
1125 t.Errorf("failed to create %s directory: %v", metricsUploaderDir, err)
1126 }
1127 if err := ioutil.WriteFile(filepath.Join(topDir, metricsUploaderPath), []byte{}, 0644); err != nil {
1128 t.Errorf("failed to create file %s: %v", expected, err)
1129 }
1130 }
1131
1132 actual := GetMetricsUploader(topDir, &tt.environ)
1133
1134 if actual != expected {
1135 t.Errorf("expecting: %s, actual: %s", expected, actual)
1136 }
1137 })
1138 }
1139}