xref: /aosp_15_r20/build/soong/ui/build/config_test.go (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
1*333d2b36SAndroid Build Coastguard Worker// Copyright 2017 Google Inc. All rights reserved.
2*333d2b36SAndroid Build Coastguard Worker//
3*333d2b36SAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License");
4*333d2b36SAndroid Build Coastguard Worker// you may not use this file except in compliance with the License.
5*333d2b36SAndroid Build Coastguard Worker// You may obtain a copy of the License at
6*333d2b36SAndroid Build Coastguard Worker//
7*333d2b36SAndroid Build Coastguard Worker//     http://www.apache.org/licenses/LICENSE-2.0
8*333d2b36SAndroid Build Coastguard Worker//
9*333d2b36SAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software
10*333d2b36SAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS,
11*333d2b36SAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*333d2b36SAndroid Build Coastguard Worker// See the License for the specific language governing permissions and
13*333d2b36SAndroid Build Coastguard Worker// limitations under the License.
14*333d2b36SAndroid Build Coastguard Worker
15*333d2b36SAndroid Build Coastguard Workerpackage build
16*333d2b36SAndroid Build Coastguard Worker
17*333d2b36SAndroid Build Coastguard Workerimport (
18*333d2b36SAndroid Build Coastguard Worker	"bytes"
19*333d2b36SAndroid Build Coastguard Worker	"context"
20*333d2b36SAndroid Build Coastguard Worker	"fmt"
21*333d2b36SAndroid Build Coastguard Worker	"io/ioutil"
22*333d2b36SAndroid Build Coastguard Worker	"os"
23*333d2b36SAndroid Build Coastguard Worker	"path/filepath"
24*333d2b36SAndroid Build Coastguard Worker	"reflect"
25*333d2b36SAndroid Build Coastguard Worker	"runtime"
26*333d2b36SAndroid Build Coastguard Worker	"strings"
27*333d2b36SAndroid Build Coastguard Worker	"testing"
28*333d2b36SAndroid Build Coastguard Worker
29*333d2b36SAndroid Build Coastguard Worker	"android/soong/ui/logger"
30*333d2b36SAndroid Build Coastguard Worker	smpb "android/soong/ui/metrics/metrics_proto"
31*333d2b36SAndroid Build Coastguard Worker	"android/soong/ui/status"
32*333d2b36SAndroid Build Coastguard Worker
33*333d2b36SAndroid Build Coastguard Worker	"google.golang.org/protobuf/encoding/prototext"
34*333d2b36SAndroid Build Coastguard Worker
35*333d2b36SAndroid Build Coastguard Worker	"google.golang.org/protobuf/proto"
36*333d2b36SAndroid Build Coastguard Worker)
37*333d2b36SAndroid Build Coastguard Worker
38*333d2b36SAndroid Build Coastguard Workerfunc testContext() Context {
39*333d2b36SAndroid Build Coastguard Worker	return Context{&ContextImpl{
40*333d2b36SAndroid Build Coastguard Worker		Context: context.Background(),
41*333d2b36SAndroid Build Coastguard Worker		Logger:  logger.New(&bytes.Buffer{}),
42*333d2b36SAndroid Build Coastguard Worker		Writer:  &bytes.Buffer{},
43*333d2b36SAndroid Build Coastguard Worker		Status:  &status.Status{},
44*333d2b36SAndroid Build Coastguard Worker	}}
45*333d2b36SAndroid Build Coastguard Worker}
46*333d2b36SAndroid Build Coastguard Worker
47*333d2b36SAndroid Build Coastguard Workerfunc TestConfigParseArgsJK(t *testing.T) {
48*333d2b36SAndroid Build Coastguard Worker	ctx := testContext()
49*333d2b36SAndroid Build Coastguard Worker
50*333d2b36SAndroid Build Coastguard Worker	testCases := []struct {
51*333d2b36SAndroid Build Coastguard Worker		args []string
52*333d2b36SAndroid Build Coastguard Worker
53*333d2b36SAndroid Build Coastguard Worker		parallel  int
54*333d2b36SAndroid Build Coastguard Worker		keepGoing int
55*333d2b36SAndroid Build Coastguard Worker		remaining []string
56*333d2b36SAndroid Build Coastguard Worker	}{
57*333d2b36SAndroid Build Coastguard Worker		{nil, -1, -1, nil},
58*333d2b36SAndroid Build Coastguard Worker
59*333d2b36SAndroid Build Coastguard Worker		{[]string{"-j"}, -1, -1, nil},
60*333d2b36SAndroid Build Coastguard Worker		{[]string{"-j1"}, 1, -1, nil},
61*333d2b36SAndroid Build Coastguard Worker		{[]string{"-j1234"}, 1234, -1, nil},
62*333d2b36SAndroid Build Coastguard Worker
63*333d2b36SAndroid Build Coastguard Worker		{[]string{"-j", "1"}, 1, -1, nil},
64*333d2b36SAndroid Build Coastguard Worker		{[]string{"-j", "1234"}, 1234, -1, nil},
65*333d2b36SAndroid Build Coastguard Worker		{[]string{"-j", "1234", "abc"}, 1234, -1, []string{"abc"}},
66*333d2b36SAndroid Build Coastguard Worker		{[]string{"-j", "abc"}, -1, -1, []string{"abc"}},
67*333d2b36SAndroid Build Coastguard Worker		{[]string{"-j", "1abc"}, -1, -1, []string{"1abc"}},
68*333d2b36SAndroid Build Coastguard Worker
69*333d2b36SAndroid Build Coastguard Worker		{[]string{"-k"}, -1, 0, nil},
70*333d2b36SAndroid Build Coastguard Worker		{[]string{"-k0"}, -1, 0, nil},
71*333d2b36SAndroid Build Coastguard Worker		{[]string{"-k1"}, -1, 1, nil},
72*333d2b36SAndroid Build Coastguard Worker		{[]string{"-k1234"}, -1, 1234, nil},
73*333d2b36SAndroid Build Coastguard Worker
74*333d2b36SAndroid Build Coastguard Worker		{[]string{"-k", "0"}, -1, 0, nil},
75*333d2b36SAndroid Build Coastguard Worker		{[]string{"-k", "1"}, -1, 1, nil},
76*333d2b36SAndroid Build Coastguard Worker		{[]string{"-k", "1234"}, -1, 1234, nil},
77*333d2b36SAndroid Build Coastguard Worker		{[]string{"-k", "1234", "abc"}, -1, 1234, []string{"abc"}},
78*333d2b36SAndroid Build Coastguard Worker		{[]string{"-k", "abc"}, -1, 0, []string{"abc"}},
79*333d2b36SAndroid Build Coastguard Worker		{[]string{"-k", "1abc"}, -1, 0, []string{"1abc"}},
80*333d2b36SAndroid Build Coastguard Worker
81*333d2b36SAndroid Build Coastguard Worker		// TODO: These are supported in Make, should we support them?
82*333d2b36SAndroid Build Coastguard Worker		//{[]string{"-kj"}, -1, 0},
83*333d2b36SAndroid Build Coastguard Worker		//{[]string{"-kj8"}, 8, 0},
84*333d2b36SAndroid Build Coastguard Worker
85*333d2b36SAndroid Build Coastguard Worker		// -jk is not valid in Make
86*333d2b36SAndroid Build Coastguard Worker	}
87*333d2b36SAndroid Build Coastguard Worker
88*333d2b36SAndroid Build Coastguard Worker	for _, tc := range testCases {
89*333d2b36SAndroid Build Coastguard Worker		t.Run(strings.Join(tc.args, " "), func(t *testing.T) {
90*333d2b36SAndroid Build Coastguard Worker			defer logger.Recover(func(err error) {
91*333d2b36SAndroid Build Coastguard Worker				t.Fatal(err)
92*333d2b36SAndroid Build Coastguard Worker			})
93*333d2b36SAndroid Build Coastguard Worker
94*333d2b36SAndroid Build Coastguard Worker			env := Environment([]string{})
95*333d2b36SAndroid Build Coastguard Worker			c := &configImpl{
96*333d2b36SAndroid Build Coastguard Worker				environ:   &env,
97*333d2b36SAndroid Build Coastguard Worker				parallel:  -1,
98*333d2b36SAndroid Build Coastguard Worker				keepGoing: -1,
99*333d2b36SAndroid Build Coastguard Worker			}
100*333d2b36SAndroid Build Coastguard Worker			c.parseArgs(ctx, tc.args)
101*333d2b36SAndroid Build Coastguard Worker
102*333d2b36SAndroid Build Coastguard Worker			if c.parallel != tc.parallel {
103*333d2b36SAndroid Build Coastguard Worker				t.Errorf("for %q, parallel:\nwant: %d\n got: %d\n",
104*333d2b36SAndroid Build Coastguard Worker					strings.Join(tc.args, " "),
105*333d2b36SAndroid Build Coastguard Worker					tc.parallel, c.parallel)
106*333d2b36SAndroid Build Coastguard Worker			}
107*333d2b36SAndroid Build Coastguard Worker			if c.keepGoing != tc.keepGoing {
108*333d2b36SAndroid Build Coastguard Worker				t.Errorf("for %q, keep going:\nwant: %d\n got: %d\n",
109*333d2b36SAndroid Build Coastguard Worker					strings.Join(tc.args, " "),
110*333d2b36SAndroid Build Coastguard Worker					tc.keepGoing, c.keepGoing)
111*333d2b36SAndroid Build Coastguard Worker			}
112*333d2b36SAndroid Build Coastguard Worker			if !reflect.DeepEqual(c.arguments, tc.remaining) {
113*333d2b36SAndroid Build Coastguard Worker				t.Errorf("for %q, remaining arguments:\nwant: %q\n got: %q\n",
114*333d2b36SAndroid Build Coastguard Worker					strings.Join(tc.args, " "),
115*333d2b36SAndroid Build Coastguard Worker					tc.remaining, c.arguments)
116*333d2b36SAndroid Build Coastguard Worker			}
117*333d2b36SAndroid Build Coastguard Worker		})
118*333d2b36SAndroid Build Coastguard Worker	}
119*333d2b36SAndroid Build Coastguard Worker}
120*333d2b36SAndroid Build Coastguard Worker
121*333d2b36SAndroid Build Coastguard Workerfunc TestConfigParseArgsVars(t *testing.T) {
122*333d2b36SAndroid Build Coastguard Worker	ctx := testContext()
123*333d2b36SAndroid Build Coastguard Worker
124*333d2b36SAndroid Build Coastguard Worker	testCases := []struct {
125*333d2b36SAndroid Build Coastguard Worker		env  []string
126*333d2b36SAndroid Build Coastguard Worker		args []string
127*333d2b36SAndroid Build Coastguard Worker
128*333d2b36SAndroid Build Coastguard Worker		expectedEnv []string
129*333d2b36SAndroid Build Coastguard Worker		remaining   []string
130*333d2b36SAndroid Build Coastguard Worker	}{
131*333d2b36SAndroid Build Coastguard Worker		{},
132*333d2b36SAndroid Build Coastguard Worker		{
133*333d2b36SAndroid Build Coastguard Worker			env: []string{"A=bc"},
134*333d2b36SAndroid Build Coastguard Worker
135*333d2b36SAndroid Build Coastguard Worker			expectedEnv: []string{"A=bc"},
136*333d2b36SAndroid Build Coastguard Worker		},
137*333d2b36SAndroid Build Coastguard Worker		{
138*333d2b36SAndroid Build Coastguard Worker			args: []string{"abc"},
139*333d2b36SAndroid Build Coastguard Worker
140*333d2b36SAndroid Build Coastguard Worker			remaining: []string{"abc"},
141*333d2b36SAndroid Build Coastguard Worker		},
142*333d2b36SAndroid Build Coastguard Worker
143*333d2b36SAndroid Build Coastguard Worker		{
144*333d2b36SAndroid Build Coastguard Worker			args: []string{"A=bc"},
145*333d2b36SAndroid Build Coastguard Worker
146*333d2b36SAndroid Build Coastguard Worker			expectedEnv: []string{"A=bc"},
147*333d2b36SAndroid Build Coastguard Worker		},
148*333d2b36SAndroid Build Coastguard Worker		{
149*333d2b36SAndroid Build Coastguard Worker			env:  []string{"A=a"},
150*333d2b36SAndroid Build Coastguard Worker			args: []string{"A=bc"},
151*333d2b36SAndroid Build Coastguard Worker
152*333d2b36SAndroid Build Coastguard Worker			expectedEnv: []string{"A=bc"},
153*333d2b36SAndroid Build Coastguard Worker		},
154*333d2b36SAndroid Build Coastguard Worker
155*333d2b36SAndroid Build Coastguard Worker		{
156*333d2b36SAndroid Build Coastguard Worker			env:  []string{"A=a"},
157*333d2b36SAndroid Build Coastguard Worker			args: []string{"A=", "=b"},
158*333d2b36SAndroid Build Coastguard Worker
159*333d2b36SAndroid Build Coastguard Worker			expectedEnv: []string{"A="},
160*333d2b36SAndroid Build Coastguard Worker			remaining:   []string{"=b"},
161*333d2b36SAndroid Build Coastguard Worker		},
162*333d2b36SAndroid Build Coastguard Worker	}
163*333d2b36SAndroid Build Coastguard Worker
164*333d2b36SAndroid Build Coastguard Worker	for _, tc := range testCases {
165*333d2b36SAndroid Build Coastguard Worker		t.Run(strings.Join(tc.args, " "), func(t *testing.T) {
166*333d2b36SAndroid Build Coastguard Worker			defer logger.Recover(func(err error) {
167*333d2b36SAndroid Build Coastguard Worker				t.Fatal(err)
168*333d2b36SAndroid Build Coastguard Worker			})
169*333d2b36SAndroid Build Coastguard Worker
170*333d2b36SAndroid Build Coastguard Worker			e := Environment(tc.env)
171*333d2b36SAndroid Build Coastguard Worker			c := &configImpl{
172*333d2b36SAndroid Build Coastguard Worker				environ: &e,
173*333d2b36SAndroid Build Coastguard Worker			}
174*333d2b36SAndroid Build Coastguard Worker			c.parseArgs(ctx, tc.args)
175*333d2b36SAndroid Build Coastguard Worker
176*333d2b36SAndroid Build Coastguard Worker			if !reflect.DeepEqual([]string(*c.environ), tc.expectedEnv) {
177*333d2b36SAndroid Build Coastguard Worker				t.Errorf("for env=%q args=%q, environment:\nwant: %q\n got: %q\n",
178*333d2b36SAndroid Build Coastguard Worker					tc.env, tc.args,
179*333d2b36SAndroid Build Coastguard Worker					tc.expectedEnv, []string(*c.environ))
180*333d2b36SAndroid Build Coastguard Worker			}
181*333d2b36SAndroid Build Coastguard Worker			if !reflect.DeepEqual(c.arguments, tc.remaining) {
182*333d2b36SAndroid Build Coastguard Worker				t.Errorf("for env=%q args=%q, remaining arguments:\nwant: %q\n got: %q\n",
183*333d2b36SAndroid Build Coastguard Worker					tc.env, tc.args,
184*333d2b36SAndroid Build Coastguard Worker					tc.remaining, c.arguments)
185*333d2b36SAndroid Build Coastguard Worker			}
186*333d2b36SAndroid Build Coastguard Worker		})
187*333d2b36SAndroid Build Coastguard Worker	}
188*333d2b36SAndroid Build Coastguard Worker}
189*333d2b36SAndroid Build Coastguard Worker
190*333d2b36SAndroid Build Coastguard Workerfunc TestConfigCheckTopDir(t *testing.T) {
191*333d2b36SAndroid Build Coastguard Worker	ctx := testContext()
192*333d2b36SAndroid Build Coastguard Worker	buildRootDir := filepath.Dir(srcDirFileCheck)
193*333d2b36SAndroid Build Coastguard Worker	expectedErrStr := fmt.Sprintf("Current working directory must be the source tree. %q not found.", srcDirFileCheck)
194*333d2b36SAndroid Build Coastguard Worker
195*333d2b36SAndroid Build Coastguard Worker	tests := []struct {
196*333d2b36SAndroid Build Coastguard Worker		// ********* Setup *********
197*333d2b36SAndroid Build Coastguard Worker		// Test description.
198*333d2b36SAndroid Build Coastguard Worker		description string
199*333d2b36SAndroid Build Coastguard Worker
200*333d2b36SAndroid Build Coastguard Worker		// ********* Action *********
201*333d2b36SAndroid Build Coastguard Worker		// If set to true, the build root file is created.
202*333d2b36SAndroid Build Coastguard Worker		rootBuildFile bool
203*333d2b36SAndroid Build Coastguard Worker
204*333d2b36SAndroid Build Coastguard Worker		// The current path where Soong is being executed.
205*333d2b36SAndroid Build Coastguard Worker		path string
206*333d2b36SAndroid Build Coastguard Worker
207*333d2b36SAndroid Build Coastguard Worker		// ********* Validation *********
208*333d2b36SAndroid Build Coastguard Worker		// Expecting error and validate the error string against expectedErrStr.
209*333d2b36SAndroid Build Coastguard Worker		wantErr bool
210*333d2b36SAndroid Build Coastguard Worker	}{{
211*333d2b36SAndroid Build Coastguard Worker		description:   "current directory is the root source tree",
212*333d2b36SAndroid Build Coastguard Worker		rootBuildFile: true,
213*333d2b36SAndroid Build Coastguard Worker		path:          ".",
214*333d2b36SAndroid Build Coastguard Worker		wantErr:       false,
215*333d2b36SAndroid Build Coastguard Worker	}, {
216*333d2b36SAndroid Build Coastguard Worker		description:   "one level deep in the source tree",
217*333d2b36SAndroid Build Coastguard Worker		rootBuildFile: true,
218*333d2b36SAndroid Build Coastguard Worker		path:          "1",
219*333d2b36SAndroid Build Coastguard Worker		wantErr:       true,
220*333d2b36SAndroid Build Coastguard Worker	}, {
221*333d2b36SAndroid Build Coastguard Worker		description:   "very deep in the source tree",
222*333d2b36SAndroid Build Coastguard Worker		rootBuildFile: true,
223*333d2b36SAndroid Build Coastguard Worker		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*333d2b36SAndroid Build Coastguard Worker		wantErr:       true,
225*333d2b36SAndroid Build Coastguard Worker	}, {
226*333d2b36SAndroid Build Coastguard Worker		description:   "outside of source tree",
227*333d2b36SAndroid Build Coastguard Worker		rootBuildFile: false,
228*333d2b36SAndroid Build Coastguard Worker		path:          "1/2/3/4/5",
229*333d2b36SAndroid Build Coastguard Worker		wantErr:       true,
230*333d2b36SAndroid Build Coastguard Worker	}}
231*333d2b36SAndroid Build Coastguard Worker
232*333d2b36SAndroid Build Coastguard Worker	for _, tt := range tests {
233*333d2b36SAndroid Build Coastguard Worker		t.Run(tt.description, func(t *testing.T) {
234*333d2b36SAndroid Build Coastguard Worker			defer logger.Recover(func(err error) {
235*333d2b36SAndroid Build Coastguard Worker				if !tt.wantErr {
236*333d2b36SAndroid Build Coastguard Worker					t.Fatalf("Got unexpected error: %v", err)
237*333d2b36SAndroid Build Coastguard Worker				}
238*333d2b36SAndroid Build Coastguard Worker				if expectedErrStr != err.Error() {
239*333d2b36SAndroid Build Coastguard Worker					t.Fatalf("expected %s, got %s", expectedErrStr, err.Error())
240*333d2b36SAndroid Build Coastguard Worker				}
241*333d2b36SAndroid Build Coastguard Worker			})
242*333d2b36SAndroid Build Coastguard Worker
243*333d2b36SAndroid Build Coastguard Worker			// Create the root source tree.
244*333d2b36SAndroid Build Coastguard Worker			rootDir, err := ioutil.TempDir("", "")
245*333d2b36SAndroid Build Coastguard Worker			if err != nil {
246*333d2b36SAndroid Build Coastguard Worker				t.Fatal(err)
247*333d2b36SAndroid Build Coastguard Worker			}
248*333d2b36SAndroid Build Coastguard Worker			defer os.RemoveAll(rootDir)
249*333d2b36SAndroid Build Coastguard Worker
250*333d2b36SAndroid Build Coastguard Worker			// Create the build root file. This is to test if topDir returns an error if the build root
251*333d2b36SAndroid Build Coastguard Worker			// file does not exist.
252*333d2b36SAndroid Build Coastguard Worker			if tt.rootBuildFile {
253*333d2b36SAndroid Build Coastguard Worker				dir := filepath.Join(rootDir, buildRootDir)
254*333d2b36SAndroid Build Coastguard Worker				if err := os.MkdirAll(dir, 0755); err != nil {
255*333d2b36SAndroid Build Coastguard Worker					t.Errorf("failed to create %s directory: %v", dir, err)
256*333d2b36SAndroid Build Coastguard Worker				}
257*333d2b36SAndroid Build Coastguard Worker				f := filepath.Join(rootDir, srcDirFileCheck)
258*333d2b36SAndroid Build Coastguard Worker				if err := ioutil.WriteFile(f, []byte{}, 0644); err != nil {
259*333d2b36SAndroid Build Coastguard Worker					t.Errorf("failed to create file %s: %v", f, err)
260*333d2b36SAndroid Build Coastguard Worker				}
261*333d2b36SAndroid Build Coastguard Worker			}
262*333d2b36SAndroid Build Coastguard Worker
263*333d2b36SAndroid Build Coastguard Worker			// Next block of code is to set the current directory.
264*333d2b36SAndroid Build Coastguard Worker			dir := rootDir
265*333d2b36SAndroid Build Coastguard Worker			if tt.path != "" {
266*333d2b36SAndroid Build Coastguard Worker				dir = filepath.Join(dir, tt.path)
267*333d2b36SAndroid Build Coastguard Worker				if err := os.MkdirAll(dir, 0755); err != nil {
268*333d2b36SAndroid Build Coastguard Worker					t.Errorf("failed to create %s directory: %v", dir, err)
269*333d2b36SAndroid Build Coastguard Worker				}
270*333d2b36SAndroid Build Coastguard Worker			}
271*333d2b36SAndroid Build Coastguard Worker			curDir, err := os.Getwd()
272*333d2b36SAndroid Build Coastguard Worker			if err != nil {
273*333d2b36SAndroid Build Coastguard Worker				t.Fatalf("failed to get the current directory: %v", err)
274*333d2b36SAndroid Build Coastguard Worker			}
275*333d2b36SAndroid Build Coastguard Worker			defer func() { os.Chdir(curDir) }()
276*333d2b36SAndroid Build Coastguard Worker
277*333d2b36SAndroid Build Coastguard Worker			if err := os.Chdir(dir); err != nil {
278*333d2b36SAndroid Build Coastguard Worker				t.Fatalf("failed to change directory to %s: %v", dir, err)
279*333d2b36SAndroid Build Coastguard Worker			}
280*333d2b36SAndroid Build Coastguard Worker
281*333d2b36SAndroid Build Coastguard Worker			checkTopDir(ctx)
282*333d2b36SAndroid Build Coastguard Worker		})
283*333d2b36SAndroid Build Coastguard Worker	}
284*333d2b36SAndroid Build Coastguard Worker}
285*333d2b36SAndroid Build Coastguard Worker
286*333d2b36SAndroid Build Coastguard Workerfunc TestConfigConvertToTarget(t *testing.T) {
287*333d2b36SAndroid Build Coastguard Worker	tests := []struct {
288*333d2b36SAndroid Build Coastguard Worker		// ********* Setup *********
289*333d2b36SAndroid Build Coastguard Worker		// Test description.
290*333d2b36SAndroid Build Coastguard Worker		description string
291*333d2b36SAndroid Build Coastguard Worker
292*333d2b36SAndroid Build Coastguard Worker		// ********* Action *********
293*333d2b36SAndroid Build Coastguard Worker		// The current directory where Soong is being executed.
294*333d2b36SAndroid Build Coastguard Worker		dir string
295*333d2b36SAndroid Build Coastguard Worker
296*333d2b36SAndroid Build Coastguard Worker		// The current prefix string to be pre-appended to the target.
297*333d2b36SAndroid Build Coastguard Worker		prefix string
298*333d2b36SAndroid Build Coastguard Worker
299*333d2b36SAndroid Build Coastguard Worker		// ********* Validation *********
300*333d2b36SAndroid Build Coastguard Worker		// The expected target to be invoked in ninja.
301*333d2b36SAndroid Build Coastguard Worker		expectedTarget string
302*333d2b36SAndroid Build Coastguard Worker	}{{
303*333d2b36SAndroid Build Coastguard Worker		description:    "one level directory in source tree",
304*333d2b36SAndroid Build Coastguard Worker		dir:            "test1",
305*333d2b36SAndroid Build Coastguard Worker		prefix:         "MODULES-IN-",
306*333d2b36SAndroid Build Coastguard Worker		expectedTarget: "MODULES-IN-test1",
307*333d2b36SAndroid Build Coastguard Worker	}, {
308*333d2b36SAndroid Build Coastguard Worker		description:    "multiple level directories in source tree",
309*333d2b36SAndroid Build Coastguard Worker		dir:            "test1/test2/test3/test4",
310*333d2b36SAndroid Build Coastguard Worker		prefix:         "GET-INSTALL-PATH-IN-",
311*333d2b36SAndroid Build Coastguard Worker		expectedTarget: "GET-INSTALL-PATH-IN-test1-test2-test3-test4",
312*333d2b36SAndroid Build Coastguard Worker	}}
313*333d2b36SAndroid Build Coastguard Worker	for _, tt := range tests {
314*333d2b36SAndroid Build Coastguard Worker		t.Run(tt.description, func(t *testing.T) {
315*333d2b36SAndroid Build Coastguard Worker			target := convertToTarget(tt.dir, tt.prefix)
316*333d2b36SAndroid Build Coastguard Worker			if target != tt.expectedTarget {
317*333d2b36SAndroid Build Coastguard Worker				t.Errorf("expected %s, got %s for target", tt.expectedTarget, target)
318*333d2b36SAndroid Build Coastguard Worker			}
319*333d2b36SAndroid Build Coastguard Worker		})
320*333d2b36SAndroid Build Coastguard Worker	}
321*333d2b36SAndroid Build Coastguard Worker}
322*333d2b36SAndroid Build Coastguard Worker
323*333d2b36SAndroid Build Coastguard Workerfunc setTop(t *testing.T, dir string) func() {
324*333d2b36SAndroid Build Coastguard Worker	curDir, err := os.Getwd()
325*333d2b36SAndroid Build Coastguard Worker	if err != nil {
326*333d2b36SAndroid Build Coastguard Worker		t.Fatalf("failed to get current directory: %v", err)
327*333d2b36SAndroid Build Coastguard Worker	}
328*333d2b36SAndroid Build Coastguard Worker	if err := os.Chdir(dir); err != nil {
329*333d2b36SAndroid Build Coastguard Worker		t.Fatalf("failed to change directory to top dir %s: %v", dir, err)
330*333d2b36SAndroid Build Coastguard Worker	}
331*333d2b36SAndroid Build Coastguard Worker	return func() { os.Chdir(curDir) }
332*333d2b36SAndroid Build Coastguard Worker}
333*333d2b36SAndroid Build Coastguard Worker
334*333d2b36SAndroid Build Coastguard Workerfunc createBuildFiles(t *testing.T, topDir string, buildFiles []string) {
335*333d2b36SAndroid Build Coastguard Worker	for _, buildFile := range buildFiles {
336*333d2b36SAndroid Build Coastguard Worker		buildFile = filepath.Join(topDir, buildFile)
337*333d2b36SAndroid Build Coastguard Worker		if err := ioutil.WriteFile(buildFile, []byte{}, 0644); err != nil {
338*333d2b36SAndroid Build Coastguard Worker			t.Errorf("failed to create file %s: %v", buildFile, err)
339*333d2b36SAndroid Build Coastguard Worker		}
340*333d2b36SAndroid Build Coastguard Worker	}
341*333d2b36SAndroid Build Coastguard Worker}
342*333d2b36SAndroid Build Coastguard Worker
343*333d2b36SAndroid Build Coastguard Workerfunc createDirectories(t *testing.T, topDir string, dirs []string) {
344*333d2b36SAndroid Build Coastguard Worker	for _, dir := range dirs {
345*333d2b36SAndroid Build Coastguard Worker		dir = filepath.Join(topDir, dir)
346*333d2b36SAndroid Build Coastguard Worker		if err := os.MkdirAll(dir, 0755); err != nil {
347*333d2b36SAndroid Build Coastguard Worker			t.Errorf("failed to create %s directory: %v", dir, err)
348*333d2b36SAndroid Build Coastguard Worker		}
349*333d2b36SAndroid Build Coastguard Worker	}
350*333d2b36SAndroid Build Coastguard Worker}
351*333d2b36SAndroid Build Coastguard Worker
352*333d2b36SAndroid Build Coastguard Workerfunc TestConfigGetTargets(t *testing.T) {
353*333d2b36SAndroid Build Coastguard Worker	ctx := testContext()
354*333d2b36SAndroid Build Coastguard Worker	tests := []struct {
355*333d2b36SAndroid Build Coastguard Worker		// ********* Setup *********
356*333d2b36SAndroid Build Coastguard Worker		// Test description.
357*333d2b36SAndroid Build Coastguard Worker		description string
358*333d2b36SAndroid Build Coastguard Worker
359*333d2b36SAndroid Build Coastguard Worker		// Directories that exist in the source tree.
360*333d2b36SAndroid Build Coastguard Worker		dirsInTrees []string
361*333d2b36SAndroid Build Coastguard Worker
362*333d2b36SAndroid Build Coastguard Worker		// Build files that exists in the source tree.
363*333d2b36SAndroid Build Coastguard Worker		buildFiles []string
364*333d2b36SAndroid Build Coastguard Worker
365*333d2b36SAndroid Build Coastguard Worker		// ********* Action *********
366*333d2b36SAndroid Build Coastguard Worker		// Directories passed in to soong_ui.
367*333d2b36SAndroid Build Coastguard Worker		dirs []string
368*333d2b36SAndroid Build Coastguard Worker
369*333d2b36SAndroid Build Coastguard Worker		// Current directory that the user executed the build action command.
370*333d2b36SAndroid Build Coastguard Worker		curDir string
371*333d2b36SAndroid Build Coastguard Worker
372*333d2b36SAndroid Build Coastguard Worker		// ********* Validation *********
373*333d2b36SAndroid Build Coastguard Worker		// Expected targets from the function.
374*333d2b36SAndroid Build Coastguard Worker		expectedTargets []string
375*333d2b36SAndroid Build Coastguard Worker
376*333d2b36SAndroid Build Coastguard Worker		// Expecting error from running test case.
377*333d2b36SAndroid Build Coastguard Worker		errStr string
378*333d2b36SAndroid Build Coastguard Worker	}{{
379*333d2b36SAndroid Build Coastguard Worker		description:     "one target dir specified",
380*333d2b36SAndroid Build Coastguard Worker		dirsInTrees:     []string{"0/1/2/3"},
381*333d2b36SAndroid Build Coastguard Worker		buildFiles:      []string{"0/1/2/3/Android.bp"},
382*333d2b36SAndroid Build Coastguard Worker		dirs:            []string{"1/2/3"},
383*333d2b36SAndroid Build Coastguard Worker		curDir:          "0",
384*333d2b36SAndroid Build Coastguard Worker		expectedTargets: []string{"MODULES-IN-0-1-2-3"},
385*333d2b36SAndroid Build Coastguard Worker	}, {
386*333d2b36SAndroid Build Coastguard Worker		description: "one target dir specified, build file does not exist",
387*333d2b36SAndroid Build Coastguard Worker		dirsInTrees: []string{"0/1/2/3"},
388*333d2b36SAndroid Build Coastguard Worker		buildFiles:  []string{},
389*333d2b36SAndroid Build Coastguard Worker		dirs:        []string{"1/2/3"},
390*333d2b36SAndroid Build Coastguard Worker		curDir:      "0",
391*333d2b36SAndroid Build Coastguard Worker		errStr:      "Build file not found for 0/1/2/3 directory",
392*333d2b36SAndroid Build Coastguard Worker	}, {
393*333d2b36SAndroid Build Coastguard Worker		description: "one target dir specified, invalid targets specified",
394*333d2b36SAndroid Build Coastguard Worker		dirsInTrees: []string{"0/1/2/3"},
395*333d2b36SAndroid Build Coastguard Worker		buildFiles:  []string{},
396*333d2b36SAndroid Build Coastguard Worker		dirs:        []string{"1/2/3:t1:t2"},
397*333d2b36SAndroid Build Coastguard Worker		curDir:      "0",
398*333d2b36SAndroid Build Coastguard Worker		errStr:      "1/2/3:t1:t2 not in proper directory:target1,target2,... format (\":\" was specified more than once)",
399*333d2b36SAndroid Build Coastguard Worker	}, {
400*333d2b36SAndroid Build Coastguard Worker		description:     "one target dir specified, no targets specified but has colon",
401*333d2b36SAndroid Build Coastguard Worker		dirsInTrees:     []string{"0/1/2/3"},
402*333d2b36SAndroid Build Coastguard Worker		buildFiles:      []string{"0/1/2/3/Android.bp"},
403*333d2b36SAndroid Build Coastguard Worker		dirs:            []string{"1/2/3:"},
404*333d2b36SAndroid Build Coastguard Worker		curDir:          "0",
405*333d2b36SAndroid Build Coastguard Worker		expectedTargets: []string{"MODULES-IN-0-1-2-3"},
406*333d2b36SAndroid Build Coastguard Worker	}, {
407*333d2b36SAndroid Build Coastguard Worker		description:     "one target dir specified, two targets specified",
408*333d2b36SAndroid Build Coastguard Worker		dirsInTrees:     []string{"0/1/2/3"},
409*333d2b36SAndroid Build Coastguard Worker		buildFiles:      []string{"0/1/2/3/Android.bp"},
410*333d2b36SAndroid Build Coastguard Worker		dirs:            []string{"1/2/3:t1,t2"},
411*333d2b36SAndroid Build Coastguard Worker		curDir:          "0",
412*333d2b36SAndroid Build Coastguard Worker		expectedTargets: []string{"t1", "t2"},
413*333d2b36SAndroid Build Coastguard Worker	}, {
414*333d2b36SAndroid Build Coastguard Worker		description: "one target dir specified, no targets and has a comma",
415*333d2b36SAndroid Build Coastguard Worker		dirsInTrees: []string{"0/1/2/3"},
416*333d2b36SAndroid Build Coastguard Worker		buildFiles:  []string{"0/1/2/3/Android.bp"},
417*333d2b36SAndroid Build Coastguard Worker		dirs:        []string{"1/2/3:,"},
418*333d2b36SAndroid Build Coastguard Worker		curDir:      "0",
419*333d2b36SAndroid Build Coastguard Worker		errStr:      "0/1/2/3 not in proper directory:target1,target2,... format",
420*333d2b36SAndroid Build Coastguard Worker	}, {
421*333d2b36SAndroid Build Coastguard Worker		description: "one target dir specified, improper targets defined",
422*333d2b36SAndroid Build Coastguard Worker		dirsInTrees: []string{"0/1/2/3"},
423*333d2b36SAndroid Build Coastguard Worker		buildFiles:  []string{"0/1/2/3/Android.bp"},
424*333d2b36SAndroid Build Coastguard Worker		dirs:        []string{"1/2/3:,t1"},
425*333d2b36SAndroid Build Coastguard Worker		curDir:      "0",
426*333d2b36SAndroid Build Coastguard Worker		errStr:      "0/1/2/3 not in proper directory:target1,target2,... format",
427*333d2b36SAndroid Build Coastguard Worker	}, {
428*333d2b36SAndroid Build Coastguard Worker		description: "one target dir specified, blank target",
429*333d2b36SAndroid Build Coastguard Worker		dirsInTrees: []string{"0/1/2/3"},
430*333d2b36SAndroid Build Coastguard Worker		buildFiles:  []string{"0/1/2/3/Android.bp"},
431*333d2b36SAndroid Build Coastguard Worker		dirs:        []string{"1/2/3:t1,"},
432*333d2b36SAndroid Build Coastguard Worker		curDir:      "0",
433*333d2b36SAndroid Build Coastguard Worker		errStr:      "0/1/2/3 not in proper directory:target1,target2,... format",
434*333d2b36SAndroid Build Coastguard Worker	}, {
435*333d2b36SAndroid Build Coastguard Worker		description:     "one target dir specified, many targets specified",
436*333d2b36SAndroid Build Coastguard Worker		dirsInTrees:     []string{"0/1/2/3"},
437*333d2b36SAndroid Build Coastguard Worker		buildFiles:      []string{"0/1/2/3/Android.bp"},
438*333d2b36SAndroid Build Coastguard Worker		dirs:            []string{"1/2/3:t1,t2,t3,t4,t5,t6,t7,t8,t9,t10"},
439*333d2b36SAndroid Build Coastguard Worker		curDir:          "0",
440*333d2b36SAndroid Build Coastguard Worker		expectedTargets: []string{"t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9", "t10"},
441*333d2b36SAndroid Build Coastguard Worker	}, {
442*333d2b36SAndroid Build Coastguard Worker		description: "one target dir specified, one target specified, build file does not exist",
443*333d2b36SAndroid Build Coastguard Worker		dirsInTrees: []string{"0/1/2/3"},
444*333d2b36SAndroid Build Coastguard Worker		buildFiles:  []string{},
445*333d2b36SAndroid Build Coastguard Worker		dirs:        []string{"1/2/3:t1"},
446*333d2b36SAndroid Build Coastguard Worker		curDir:      "0",
447*333d2b36SAndroid Build Coastguard Worker		errStr:      "Couldn't locate a build file from 0/1/2/3 directory",
448*333d2b36SAndroid Build Coastguard Worker	}, {
449*333d2b36SAndroid Build Coastguard Worker		description: "one target dir specified, one target specified, build file not in target dir",
450*333d2b36SAndroid Build Coastguard Worker		dirsInTrees: []string{"0/1/2/3"},
451*333d2b36SAndroid Build Coastguard Worker		buildFiles:  []string{"0/1/2/Android.mk"},
452*333d2b36SAndroid Build Coastguard Worker		dirs:        []string{"1/2/3:t1"},
453*333d2b36SAndroid Build Coastguard Worker		curDir:      "0",
454*333d2b36SAndroid Build Coastguard Worker		errStr:      "Couldn't locate a build file from 0/1/2/3 directory",
455*333d2b36SAndroid Build Coastguard Worker	}, {
456*333d2b36SAndroid Build Coastguard Worker		description:     "one target dir specified, build file not in target dir",
457*333d2b36SAndroid Build Coastguard Worker		dirsInTrees:     []string{"0/1/2/3"},
458*333d2b36SAndroid Build Coastguard Worker		buildFiles:      []string{"0/1/2/Android.mk"},
459*333d2b36SAndroid Build Coastguard Worker		dirs:            []string{"1/2/3"},
460*333d2b36SAndroid Build Coastguard Worker		curDir:          "0",
461*333d2b36SAndroid Build Coastguard Worker		expectedTargets: []string{"MODULES-IN-0-1-2"},
462*333d2b36SAndroid Build Coastguard Worker	}, {
463*333d2b36SAndroid Build Coastguard Worker		description:     "multiple targets dir specified, targets specified",
464*333d2b36SAndroid Build Coastguard Worker		dirsInTrees:     []string{"0/1/2/3", "0/3/4"},
465*333d2b36SAndroid Build Coastguard Worker		buildFiles:      []string{"0/1/2/3/Android.bp", "0/3/4/Android.mk"},
466*333d2b36SAndroid Build Coastguard Worker		dirs:            []string{"1/2/3:t1,t2", "3/4:t3,t4,t5"},
467*333d2b36SAndroid Build Coastguard Worker		curDir:          "0",
468*333d2b36SAndroid Build Coastguard Worker		expectedTargets: []string{"t1", "t2", "t3", "t4", "t5"},
469*333d2b36SAndroid Build Coastguard Worker	}, {
470*333d2b36SAndroid Build Coastguard Worker		description:     "multiple targets dir specified, one directory has targets specified",
471*333d2b36SAndroid Build Coastguard Worker		dirsInTrees:     []string{"0/1/2/3", "0/3/4"},
472*333d2b36SAndroid Build Coastguard Worker		buildFiles:      []string{"0/1/2/3/Android.bp", "0/3/4/Android.mk"},
473*333d2b36SAndroid Build Coastguard Worker		dirs:            []string{"1/2/3:t1,t2", "3/4"},
474*333d2b36SAndroid Build Coastguard Worker		curDir:          "0",
475*333d2b36SAndroid Build Coastguard Worker		expectedTargets: []string{"t1", "t2", "MODULES-IN-0-3-4"},
476*333d2b36SAndroid Build Coastguard Worker	}, {
477*333d2b36SAndroid Build Coastguard Worker		description: "two dirs specified, only one dir exist",
478*333d2b36SAndroid Build Coastguard Worker		dirsInTrees: []string{"0/1/2/3"},
479*333d2b36SAndroid Build Coastguard Worker		buildFiles:  []string{"0/1/2/3/Android.mk"},
480*333d2b36SAndroid Build Coastguard Worker		dirs:        []string{"1/2/3:t1", "3/4"},
481*333d2b36SAndroid Build Coastguard Worker		curDir:      "0",
482*333d2b36SAndroid Build Coastguard Worker		errStr:      "couldn't find directory 0/3/4",
483*333d2b36SAndroid Build Coastguard Worker	}, {
484*333d2b36SAndroid Build Coastguard Worker		description:     "multiple targets dirs specified at root source tree",
485*333d2b36SAndroid Build Coastguard Worker		dirsInTrees:     []string{"0/1/2/3", "0/3/4"},
486*333d2b36SAndroid Build Coastguard Worker		buildFiles:      []string{"0/1/2/3/Android.bp", "0/3/4/Android.mk"},
487*333d2b36SAndroid Build Coastguard Worker		dirs:            []string{"0/1/2/3:t1,t2", "0/3/4"},
488*333d2b36SAndroid Build Coastguard Worker		curDir:          ".",
489*333d2b36SAndroid Build Coastguard Worker		expectedTargets: []string{"t1", "t2", "MODULES-IN-0-3-4"},
490*333d2b36SAndroid Build Coastguard Worker	}, {
491*333d2b36SAndroid Build Coastguard Worker		description: "no directories specified",
492*333d2b36SAndroid Build Coastguard Worker		dirsInTrees: []string{"0/1/2/3", "0/3/4"},
493*333d2b36SAndroid Build Coastguard Worker		buildFiles:  []string{"0/1/2/3/Android.bp", "0/3/4/Android.mk"},
494*333d2b36SAndroid Build Coastguard Worker		dirs:        []string{},
495*333d2b36SAndroid Build Coastguard Worker		curDir:      ".",
496*333d2b36SAndroid Build Coastguard Worker	}}
497*333d2b36SAndroid Build Coastguard Worker	for _, tt := range tests {
498*333d2b36SAndroid Build Coastguard Worker		t.Run(tt.description, func(t *testing.T) {
499*333d2b36SAndroid Build Coastguard Worker			defer logger.Recover(func(err error) {
500*333d2b36SAndroid Build Coastguard Worker				if tt.errStr == "" {
501*333d2b36SAndroid Build Coastguard Worker					t.Fatalf("Got unexpected error: %v", err)
502*333d2b36SAndroid Build Coastguard Worker				}
503*333d2b36SAndroid Build Coastguard Worker				if tt.errStr != err.Error() {
504*333d2b36SAndroid Build Coastguard Worker					t.Errorf("expected %s, got %s", tt.errStr, err.Error())
505*333d2b36SAndroid Build Coastguard Worker				}
506*333d2b36SAndroid Build Coastguard Worker			})
507*333d2b36SAndroid Build Coastguard Worker
508*333d2b36SAndroid Build Coastguard Worker			// Create the root source tree.
509*333d2b36SAndroid Build Coastguard Worker			topDir, err := ioutil.TempDir("", "")
510*333d2b36SAndroid Build Coastguard Worker			if err != nil {
511*333d2b36SAndroid Build Coastguard Worker				t.Fatalf("failed to create temp dir: %v", err)
512*333d2b36SAndroid Build Coastguard Worker			}
513*333d2b36SAndroid Build Coastguard Worker			defer os.RemoveAll(topDir)
514*333d2b36SAndroid Build Coastguard Worker
515*333d2b36SAndroid Build Coastguard Worker			createDirectories(t, topDir, tt.dirsInTrees)
516*333d2b36SAndroid Build Coastguard Worker			createBuildFiles(t, topDir, tt.buildFiles)
517*333d2b36SAndroid Build Coastguard Worker			r := setTop(t, topDir)
518*333d2b36SAndroid Build Coastguard Worker			defer r()
519*333d2b36SAndroid Build Coastguard Worker
520*333d2b36SAndroid Build Coastguard Worker			targets := getTargetsFromDirs(ctx, tt.curDir, tt.dirs, "MODULES-IN-")
521*333d2b36SAndroid Build Coastguard Worker			if !reflect.DeepEqual(targets, tt.expectedTargets) {
522*333d2b36SAndroid Build Coastguard Worker				t.Errorf("expected %v, got %v for targets", tt.expectedTargets, targets)
523*333d2b36SAndroid Build Coastguard Worker			}
524*333d2b36SAndroid Build Coastguard Worker
525*333d2b36SAndroid Build Coastguard Worker			// If the execution reached here and there was an expected error code, the unit test case failed.
526*333d2b36SAndroid Build Coastguard Worker			if tt.errStr != "" {
527*333d2b36SAndroid Build Coastguard Worker				t.Errorf("expecting error %s", tt.errStr)
528*333d2b36SAndroid Build Coastguard Worker			}
529*333d2b36SAndroid Build Coastguard Worker		})
530*333d2b36SAndroid Build Coastguard Worker	}
531*333d2b36SAndroid Build Coastguard Worker}
532*333d2b36SAndroid Build Coastguard Worker
533*333d2b36SAndroid Build Coastguard Workerfunc TestConfigFindBuildFile(t *testing.T) {
534*333d2b36SAndroid Build Coastguard Worker	ctx := testContext()
535*333d2b36SAndroid Build Coastguard Worker
536*333d2b36SAndroid Build Coastguard Worker	tests := []struct {
537*333d2b36SAndroid Build Coastguard Worker		// ********* Setup *********
538*333d2b36SAndroid Build Coastguard Worker		// Test description.
539*333d2b36SAndroid Build Coastguard Worker		description string
540*333d2b36SAndroid Build Coastguard Worker
541*333d2b36SAndroid Build Coastguard Worker		// Array of build files to create in dir.
542*333d2b36SAndroid Build Coastguard Worker		buildFiles []string
543*333d2b36SAndroid Build Coastguard Worker
544*333d2b36SAndroid Build Coastguard Worker		// Directories that exist in the source tree.
545*333d2b36SAndroid Build Coastguard Worker		dirsInTrees []string
546*333d2b36SAndroid Build Coastguard Worker
547*333d2b36SAndroid Build Coastguard Worker		// ********* Action *********
548*333d2b36SAndroid Build Coastguard Worker		// The base directory is where findBuildFile is invoked.
549*333d2b36SAndroid Build Coastguard Worker		dir string
550*333d2b36SAndroid Build Coastguard Worker
551*333d2b36SAndroid Build Coastguard Worker		// ********* Validation *********
552*333d2b36SAndroid Build Coastguard Worker		// Expected build file path to find.
553*333d2b36SAndroid Build Coastguard Worker		expectedBuildFile string
554*333d2b36SAndroid Build Coastguard Worker	}{{
555*333d2b36SAndroid Build Coastguard Worker		description:       "build file exists at leaf directory",
556*333d2b36SAndroid Build Coastguard Worker		buildFiles:        []string{"1/2/3/Android.bp"},
557*333d2b36SAndroid Build Coastguard Worker		dirsInTrees:       []string{"1/2/3"},
558*333d2b36SAndroid Build Coastguard Worker		dir:               "1/2/3",
559*333d2b36SAndroid Build Coastguard Worker		expectedBuildFile: "1/2/3/Android.mk",
560*333d2b36SAndroid Build Coastguard Worker	}, {
561*333d2b36SAndroid Build Coastguard Worker		description:       "build file exists in all directory paths",
562*333d2b36SAndroid Build Coastguard Worker		buildFiles:        []string{"1/Android.mk", "1/2/Android.mk", "1/2/3/Android.mk"},
563*333d2b36SAndroid Build Coastguard Worker		dirsInTrees:       []string{"1/2/3"},
564*333d2b36SAndroid Build Coastguard Worker		dir:               "1/2/3",
565*333d2b36SAndroid Build Coastguard Worker		expectedBuildFile: "1/2/3/Android.mk",
566*333d2b36SAndroid Build Coastguard Worker	}, {
567*333d2b36SAndroid Build Coastguard Worker		description:       "build file does not exist in all directory paths",
568*333d2b36SAndroid Build Coastguard Worker		buildFiles:        []string{},
569*333d2b36SAndroid Build Coastguard Worker		dirsInTrees:       []string{"1/2/3"},
570*333d2b36SAndroid Build Coastguard Worker		dir:               "1/2/3",
571*333d2b36SAndroid Build Coastguard Worker		expectedBuildFile: "",
572*333d2b36SAndroid Build Coastguard Worker	}, {
573*333d2b36SAndroid Build Coastguard Worker		description:       "build file exists only at top directory",
574*333d2b36SAndroid Build Coastguard Worker		buildFiles:        []string{"Android.bp"},
575*333d2b36SAndroid Build Coastguard Worker		dirsInTrees:       []string{"1/2/3"},
576*333d2b36SAndroid Build Coastguard Worker		dir:               "1/2/3",
577*333d2b36SAndroid Build Coastguard Worker		expectedBuildFile: "",
578*333d2b36SAndroid Build Coastguard Worker	}, {
579*333d2b36SAndroid Build Coastguard Worker		description:       "build file exist in a subdirectory",
580*333d2b36SAndroid Build Coastguard Worker		buildFiles:        []string{"1/2/Android.bp"},
581*333d2b36SAndroid Build Coastguard Worker		dirsInTrees:       []string{"1/2/3"},
582*333d2b36SAndroid Build Coastguard Worker		dir:               "1/2/3",
583*333d2b36SAndroid Build Coastguard Worker		expectedBuildFile: "1/2/Android.mk",
584*333d2b36SAndroid Build Coastguard Worker	}, {
585*333d2b36SAndroid Build Coastguard Worker		description:       "build file exists in a subdirectory",
586*333d2b36SAndroid Build Coastguard Worker		buildFiles:        []string{"1/Android.mk"},
587*333d2b36SAndroid Build Coastguard Worker		dirsInTrees:       []string{"1/2/3"},
588*333d2b36SAndroid Build Coastguard Worker		dir:               "1/2/3",
589*333d2b36SAndroid Build Coastguard Worker		expectedBuildFile: "1/Android.mk",
590*333d2b36SAndroid Build Coastguard Worker	}, {
591*333d2b36SAndroid Build Coastguard Worker		description:       "top directory",
592*333d2b36SAndroid Build Coastguard Worker		buildFiles:        []string{"Android.bp"},
593*333d2b36SAndroid Build Coastguard Worker		dirsInTrees:       []string{},
594*333d2b36SAndroid Build Coastguard Worker		dir:               ".",
595*333d2b36SAndroid Build Coastguard Worker		expectedBuildFile: "",
596*333d2b36SAndroid Build Coastguard Worker	}, {
597*333d2b36SAndroid Build Coastguard Worker		description:       "build file exists in subdirectory",
598*333d2b36SAndroid Build Coastguard Worker		buildFiles:        []string{"1/2/3/Android.bp", "1/2/4/Android.bp"},
599*333d2b36SAndroid Build Coastguard Worker		dirsInTrees:       []string{"1/2/3", "1/2/4"},
600*333d2b36SAndroid Build Coastguard Worker		dir:               "1/2",
601*333d2b36SAndroid Build Coastguard Worker		expectedBuildFile: "1/2/Android.mk",
602*333d2b36SAndroid Build Coastguard Worker	}, {
603*333d2b36SAndroid Build Coastguard Worker		description:       "build file exists in parent subdirectory",
604*333d2b36SAndroid Build Coastguard Worker		buildFiles:        []string{"1/5/Android.bp"},
605*333d2b36SAndroid Build Coastguard Worker		dirsInTrees:       []string{"1/2/3", "1/2/4", "1/5"},
606*333d2b36SAndroid Build Coastguard Worker		dir:               "1/2",
607*333d2b36SAndroid Build Coastguard Worker		expectedBuildFile: "1/Android.mk",
608*333d2b36SAndroid Build Coastguard Worker	}, {
609*333d2b36SAndroid Build Coastguard Worker		description:       "build file exists in deep parent's subdirectory.",
610*333d2b36SAndroid Build Coastguard Worker		buildFiles:        []string{"1/5/6/Android.bp"},
611*333d2b36SAndroid Build Coastguard Worker		dirsInTrees:       []string{"1/2/3", "1/2/4", "1/5/6", "1/5/7"},
612*333d2b36SAndroid Build Coastguard Worker		dir:               "1/2",
613*333d2b36SAndroid Build Coastguard Worker		expectedBuildFile: "1/Android.mk",
614*333d2b36SAndroid Build Coastguard Worker	}}
615*333d2b36SAndroid Build Coastguard Worker
616*333d2b36SAndroid Build Coastguard Worker	for _, tt := range tests {
617*333d2b36SAndroid Build Coastguard Worker		t.Run(tt.description, func(t *testing.T) {
618*333d2b36SAndroid Build Coastguard Worker			defer logger.Recover(func(err error) {
619*333d2b36SAndroid Build Coastguard Worker				t.Fatalf("Got unexpected error: %v", err)
620*333d2b36SAndroid Build Coastguard Worker			})
621*333d2b36SAndroid Build Coastguard Worker
622*333d2b36SAndroid Build Coastguard Worker			topDir, err := ioutil.TempDir("", "")
623*333d2b36SAndroid Build Coastguard Worker			if err != nil {
624*333d2b36SAndroid Build Coastguard Worker				t.Fatalf("failed to create temp dir: %v", err)
625*333d2b36SAndroid Build Coastguard Worker			}
626*333d2b36SAndroid Build Coastguard Worker			defer os.RemoveAll(topDir)
627*333d2b36SAndroid Build Coastguard Worker
628*333d2b36SAndroid Build Coastguard Worker			createDirectories(t, topDir, tt.dirsInTrees)
629*333d2b36SAndroid Build Coastguard Worker			createBuildFiles(t, topDir, tt.buildFiles)
630*333d2b36SAndroid Build Coastguard Worker
631*333d2b36SAndroid Build Coastguard Worker			curDir, err := os.Getwd()
632*333d2b36SAndroid Build Coastguard Worker			if err != nil {
633*333d2b36SAndroid Build Coastguard Worker				t.Fatalf("Could not get working directory: %v", err)
634*333d2b36SAndroid Build Coastguard Worker			}
635*333d2b36SAndroid Build Coastguard Worker			defer func() { os.Chdir(curDir) }()
636*333d2b36SAndroid Build Coastguard Worker			if err := os.Chdir(topDir); err != nil {
637*333d2b36SAndroid Build Coastguard Worker				t.Fatalf("Could not change top dir to %s: %v", topDir, err)
638*333d2b36SAndroid Build Coastguard Worker			}
639*333d2b36SAndroid Build Coastguard Worker
640*333d2b36SAndroid Build Coastguard Worker			buildFile := findBuildFile(ctx, tt.dir)
641*333d2b36SAndroid Build Coastguard Worker			if buildFile != tt.expectedBuildFile {
642*333d2b36SAndroid Build Coastguard Worker				t.Errorf("expected %q, got %q for build file", tt.expectedBuildFile, buildFile)
643*333d2b36SAndroid Build Coastguard Worker			}
644*333d2b36SAndroid Build Coastguard Worker		})
645*333d2b36SAndroid Build Coastguard Worker	}
646*333d2b36SAndroid Build Coastguard Worker}
647*333d2b36SAndroid Build Coastguard Worker
648*333d2b36SAndroid Build Coastguard Workerfunc TestConfigSplitArgs(t *testing.T) {
649*333d2b36SAndroid Build Coastguard Worker	tests := []struct {
650*333d2b36SAndroid Build Coastguard Worker		// ********* Setup *********
651*333d2b36SAndroid Build Coastguard Worker		// Test description.
652*333d2b36SAndroid Build Coastguard Worker		description string
653*333d2b36SAndroid Build Coastguard Worker
654*333d2b36SAndroid Build Coastguard Worker		// ********* Action *********
655*333d2b36SAndroid Build Coastguard Worker		// Arguments passed in to soong_ui.
656*333d2b36SAndroid Build Coastguard Worker		args []string
657*333d2b36SAndroid Build Coastguard Worker
658*333d2b36SAndroid Build Coastguard Worker		// ********* Validation *********
659*333d2b36SAndroid Build Coastguard Worker		// Expected newArgs list after extracting the directories.
660*333d2b36SAndroid Build Coastguard Worker		expectedNewArgs []string
661*333d2b36SAndroid Build Coastguard Worker
662*333d2b36SAndroid Build Coastguard Worker		// Expected directories
663*333d2b36SAndroid Build Coastguard Worker		expectedDirs []string
664*333d2b36SAndroid Build Coastguard Worker	}{{
665*333d2b36SAndroid Build Coastguard Worker		description:     "flags but no directories specified",
666*333d2b36SAndroid Build Coastguard Worker		args:            []string{"showcommands", "-j", "-k"},
667*333d2b36SAndroid Build Coastguard Worker		expectedNewArgs: []string{"showcommands", "-j", "-k"},
668*333d2b36SAndroid Build Coastguard Worker		expectedDirs:    []string{},
669*333d2b36SAndroid Build Coastguard Worker	}, {
670*333d2b36SAndroid Build Coastguard Worker		description:     "flags and one directory specified",
671*333d2b36SAndroid Build Coastguard Worker		args:            []string{"snod", "-j", "dir:target1,target2"},
672*333d2b36SAndroid Build Coastguard Worker		expectedNewArgs: []string{"snod", "-j"},
673*333d2b36SAndroid Build Coastguard Worker		expectedDirs:    []string{"dir:target1,target2"},
674*333d2b36SAndroid Build Coastguard Worker	}, {
675*333d2b36SAndroid Build Coastguard Worker		description:     "flags and directories specified",
676*333d2b36SAndroid Build Coastguard Worker		args:            []string{"dist", "-k", "dir1", "dir2:target1,target2"},
677*333d2b36SAndroid Build Coastguard Worker		expectedNewArgs: []string{"dist", "-k"},
678*333d2b36SAndroid Build Coastguard Worker		expectedDirs:    []string{"dir1", "dir2:target1,target2"},
679*333d2b36SAndroid Build Coastguard Worker	}, {
680*333d2b36SAndroid Build Coastguard Worker		description:     "only directories specified",
681*333d2b36SAndroid Build Coastguard Worker		args:            []string{"dir1", "dir2", "dir3:target1,target2"},
682*333d2b36SAndroid Build Coastguard Worker		expectedNewArgs: []string{},
683*333d2b36SAndroid Build Coastguard Worker		expectedDirs:    []string{"dir1", "dir2", "dir3:target1,target2"},
684*333d2b36SAndroid Build Coastguard Worker	}}
685*333d2b36SAndroid Build Coastguard Worker	for _, tt := range tests {
686*333d2b36SAndroid Build Coastguard Worker		t.Run(tt.description, func(t *testing.T) {
687*333d2b36SAndroid Build Coastguard Worker			args, dirs := splitArgs(tt.args)
688*333d2b36SAndroid Build Coastguard Worker			if !reflect.DeepEqual(tt.expectedNewArgs, args) {
689*333d2b36SAndroid Build Coastguard Worker				t.Errorf("expected %v, got %v for arguments", tt.expectedNewArgs, args)
690*333d2b36SAndroid Build Coastguard Worker			}
691*333d2b36SAndroid Build Coastguard Worker			if !reflect.DeepEqual(tt.expectedDirs, dirs) {
692*333d2b36SAndroid Build Coastguard Worker				t.Errorf("expected %v, got %v for directories", tt.expectedDirs, dirs)
693*333d2b36SAndroid Build Coastguard Worker			}
694*333d2b36SAndroid Build Coastguard Worker		})
695*333d2b36SAndroid Build Coastguard Worker	}
696*333d2b36SAndroid Build Coastguard Worker}
697*333d2b36SAndroid Build Coastguard Worker
698*333d2b36SAndroid Build Coastguard Workertype envVar struct {
699*333d2b36SAndroid Build Coastguard Worker	name  string
700*333d2b36SAndroid Build Coastguard Worker	value string
701*333d2b36SAndroid Build Coastguard Worker}
702*333d2b36SAndroid Build Coastguard Worker
703*333d2b36SAndroid Build Coastguard Workertype buildActionTestCase struct {
704*333d2b36SAndroid Build Coastguard Worker	// ********* Setup *********
705*333d2b36SAndroid Build Coastguard Worker	// Test description.
706*333d2b36SAndroid Build Coastguard Worker	description string
707*333d2b36SAndroid Build Coastguard Worker
708*333d2b36SAndroid Build Coastguard Worker	// Directories that exist in the source tree.
709*333d2b36SAndroid Build Coastguard Worker	dirsInTrees []string
710*333d2b36SAndroid Build Coastguard Worker
711*333d2b36SAndroid Build Coastguard Worker	// Build files that exists in the source tree.
712*333d2b36SAndroid Build Coastguard Worker	buildFiles []string
713*333d2b36SAndroid Build Coastguard Worker
714*333d2b36SAndroid Build Coastguard Worker	// Create root symlink that points to topDir.
715*333d2b36SAndroid Build Coastguard Worker	rootSymlink bool
716*333d2b36SAndroid Build Coastguard Worker
717*333d2b36SAndroid Build Coastguard Worker	// ********* Action *********
718*333d2b36SAndroid Build Coastguard Worker	// Arguments passed in to soong_ui.
719*333d2b36SAndroid Build Coastguard Worker	args []string
720*333d2b36SAndroid Build Coastguard Worker
721*333d2b36SAndroid Build Coastguard Worker	// Directory where the build action was invoked.
722*333d2b36SAndroid Build Coastguard Worker	curDir string
723*333d2b36SAndroid Build Coastguard Worker
724*333d2b36SAndroid Build Coastguard Worker	// WITH_TIDY_ONLY environment variable specified.
725*333d2b36SAndroid Build Coastguard Worker	tidyOnly string
726*333d2b36SAndroid Build Coastguard Worker
727*333d2b36SAndroid Build Coastguard Worker	// ********* Validation *********
728*333d2b36SAndroid Build Coastguard Worker	// Expected arguments to be in Config instance.
729*333d2b36SAndroid Build Coastguard Worker	expectedArgs []string
730*333d2b36SAndroid Build Coastguard Worker
731*333d2b36SAndroid Build Coastguard Worker	// Expecting error from running test case.
732*333d2b36SAndroid Build Coastguard Worker	expectedErrStr string
733*333d2b36SAndroid Build Coastguard Worker}
734*333d2b36SAndroid Build Coastguard Worker
735*333d2b36SAndroid Build Coastguard Workerfunc testGetConfigArgs(t *testing.T, tt buildActionTestCase, action BuildAction) {
736*333d2b36SAndroid Build Coastguard Worker	ctx := testContext()
737*333d2b36SAndroid Build Coastguard Worker
738*333d2b36SAndroid Build Coastguard Worker	defer logger.Recover(func(err error) {
739*333d2b36SAndroid Build Coastguard Worker		if tt.expectedErrStr == "" {
740*333d2b36SAndroid Build Coastguard Worker			t.Fatalf("Got unexpected error: %v", err)
741*333d2b36SAndroid Build Coastguard Worker		}
742*333d2b36SAndroid Build Coastguard Worker		if tt.expectedErrStr != err.Error() {
743*333d2b36SAndroid Build Coastguard Worker			t.Errorf("expected %s, got %s", tt.expectedErrStr, err.Error())
744*333d2b36SAndroid Build Coastguard Worker		}
745*333d2b36SAndroid Build Coastguard Worker	})
746*333d2b36SAndroid Build Coastguard Worker
747*333d2b36SAndroid Build Coastguard Worker	// Environment variables to set it to blank on every test case run.
748*333d2b36SAndroid Build Coastguard Worker	resetEnvVars := []string{
749*333d2b36SAndroid Build Coastguard Worker		"WITH_TIDY_ONLY",
750*333d2b36SAndroid Build Coastguard Worker	}
751*333d2b36SAndroid Build Coastguard Worker
752*333d2b36SAndroid Build Coastguard Worker	for _, name := range resetEnvVars {
753*333d2b36SAndroid Build Coastguard Worker		if err := os.Unsetenv(name); err != nil {
754*333d2b36SAndroid Build Coastguard Worker			t.Fatalf("failed to unset environment variable %s: %v", name, err)
755*333d2b36SAndroid Build Coastguard Worker		}
756*333d2b36SAndroid Build Coastguard Worker	}
757*333d2b36SAndroid Build Coastguard Worker	if tt.tidyOnly != "" {
758*333d2b36SAndroid Build Coastguard Worker		if err := os.Setenv("WITH_TIDY_ONLY", tt.tidyOnly); err != nil {
759*333d2b36SAndroid Build Coastguard Worker			t.Errorf("failed to set WITH_TIDY_ONLY to %s: %v", tt.tidyOnly, err)
760*333d2b36SAndroid Build Coastguard Worker		}
761*333d2b36SAndroid Build Coastguard Worker	}
762*333d2b36SAndroid Build Coastguard Worker
763*333d2b36SAndroid Build Coastguard Worker	// Create the root source tree.
764*333d2b36SAndroid Build Coastguard Worker	topDir, err := ioutil.TempDir("", "")
765*333d2b36SAndroid Build Coastguard Worker	if err != nil {
766*333d2b36SAndroid Build Coastguard Worker		t.Fatalf("failed to create temp dir: %v", err)
767*333d2b36SAndroid Build Coastguard Worker	}
768*333d2b36SAndroid Build Coastguard Worker	defer os.RemoveAll(topDir)
769*333d2b36SAndroid Build Coastguard Worker
770*333d2b36SAndroid Build Coastguard Worker	createDirectories(t, topDir, tt.dirsInTrees)
771*333d2b36SAndroid Build Coastguard Worker	createBuildFiles(t, topDir, tt.buildFiles)
772*333d2b36SAndroid Build Coastguard Worker
773*333d2b36SAndroid Build Coastguard Worker	if tt.rootSymlink {
774*333d2b36SAndroid Build Coastguard Worker		// Create a secondary root source tree which points to the true root source tree.
775*333d2b36SAndroid Build Coastguard Worker		symlinkTopDir, err := ioutil.TempDir("", "")
776*333d2b36SAndroid Build Coastguard Worker		if err != nil {
777*333d2b36SAndroid Build Coastguard Worker			t.Fatalf("failed to create symlink temp dir: %v", err)
778*333d2b36SAndroid Build Coastguard Worker		}
779*333d2b36SAndroid Build Coastguard Worker		defer os.RemoveAll(symlinkTopDir)
780*333d2b36SAndroid Build Coastguard Worker
781*333d2b36SAndroid Build Coastguard Worker		symlinkTopDir = filepath.Join(symlinkTopDir, "root")
782*333d2b36SAndroid Build Coastguard Worker		err = os.Symlink(topDir, symlinkTopDir)
783*333d2b36SAndroid Build Coastguard Worker		if err != nil {
784*333d2b36SAndroid Build Coastguard Worker			t.Fatalf("failed to create symlink: %v", err)
785*333d2b36SAndroid Build Coastguard Worker		}
786*333d2b36SAndroid Build Coastguard Worker		topDir = symlinkTopDir
787*333d2b36SAndroid Build Coastguard Worker	}
788*333d2b36SAndroid Build Coastguard Worker
789*333d2b36SAndroid Build Coastguard Worker	r := setTop(t, topDir)
790*333d2b36SAndroid Build Coastguard Worker	defer r()
791*333d2b36SAndroid Build Coastguard Worker
792*333d2b36SAndroid Build Coastguard Worker	// The next block is to create the root build file.
793*333d2b36SAndroid Build Coastguard Worker	rootBuildFileDir := filepath.Dir(srcDirFileCheck)
794*333d2b36SAndroid Build Coastguard Worker	if err := os.MkdirAll(rootBuildFileDir, 0755); err != nil {
795*333d2b36SAndroid Build Coastguard Worker		t.Fatalf("Failed to create %s directory: %v", rootBuildFileDir, err)
796*333d2b36SAndroid Build Coastguard Worker	}
797*333d2b36SAndroid Build Coastguard Worker
798*333d2b36SAndroid Build Coastguard Worker	if err := ioutil.WriteFile(srcDirFileCheck, []byte{}, 0644); err != nil {
799*333d2b36SAndroid Build Coastguard Worker		t.Fatalf("failed to create %s file: %v", srcDirFileCheck, err)
800*333d2b36SAndroid Build Coastguard Worker	}
801*333d2b36SAndroid Build Coastguard Worker
802*333d2b36SAndroid Build Coastguard Worker	args := getConfigArgs(action, tt.curDir, ctx, tt.args)
803*333d2b36SAndroid Build Coastguard Worker	if !reflect.DeepEqual(tt.expectedArgs, args) {
804*333d2b36SAndroid Build Coastguard Worker		t.Fatalf("expected %v, got %v for config arguments", tt.expectedArgs, args)
805*333d2b36SAndroid Build Coastguard Worker	}
806*333d2b36SAndroid Build Coastguard Worker
807*333d2b36SAndroid Build Coastguard Worker	// If the execution reached here and there was an expected error code, the unit test case failed.
808*333d2b36SAndroid Build Coastguard Worker	if tt.expectedErrStr != "" {
809*333d2b36SAndroid Build Coastguard Worker		t.Errorf("expecting error %s", tt.expectedErrStr)
810*333d2b36SAndroid Build Coastguard Worker	}
811*333d2b36SAndroid Build Coastguard Worker}
812*333d2b36SAndroid Build Coastguard Worker
813*333d2b36SAndroid Build Coastguard Workerfunc TestGetConfigArgsBuildModules(t *testing.T) {
814*333d2b36SAndroid Build Coastguard Worker	tests := []buildActionTestCase{{
815*333d2b36SAndroid Build Coastguard Worker		description:  "normal execution from the root source tree directory",
816*333d2b36SAndroid Build Coastguard Worker		dirsInTrees:  []string{"0/1/2", "0/2", "0/3"},
817*333d2b36SAndroid Build Coastguard Worker		buildFiles:   []string{"0/1/2/Android.mk", "0/2/Android.bp", "0/3/Android.mk"},
818*333d2b36SAndroid Build Coastguard Worker		args:         []string{"-j", "fake_module", "fake_module2"},
819*333d2b36SAndroid Build Coastguard Worker		curDir:       ".",
820*333d2b36SAndroid Build Coastguard Worker		tidyOnly:     "",
821*333d2b36SAndroid Build Coastguard Worker		expectedArgs: []string{"-j", "fake_module", "fake_module2"},
822*333d2b36SAndroid Build Coastguard Worker	}, {
823*333d2b36SAndroid Build Coastguard Worker		description:  "normal execution in deep directory",
824*333d2b36SAndroid Build Coastguard Worker		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*333d2b36SAndroid Build Coastguard Worker		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*333d2b36SAndroid Build Coastguard Worker		args:         []string{"-j", "fake_module", "fake_module2", "-k"},
827*333d2b36SAndroid Build Coastguard Worker		curDir:       "1/2/3/4/5/6/7/8/9",
828*333d2b36SAndroid Build Coastguard Worker		tidyOnly:     "",
829*333d2b36SAndroid Build Coastguard Worker		expectedArgs: []string{"-j", "fake_module", "fake_module2", "-k"},
830*333d2b36SAndroid Build Coastguard Worker	}, {
831*333d2b36SAndroid Build Coastguard Worker		description:  "normal execution in deep directory, no targets",
832*333d2b36SAndroid Build Coastguard Worker		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*333d2b36SAndroid Build Coastguard Worker		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*333d2b36SAndroid Build Coastguard Worker		args:         []string{"-j", "-k"},
835*333d2b36SAndroid Build Coastguard Worker		curDir:       "1/2/3/4/5/6/7/8/9",
836*333d2b36SAndroid Build Coastguard Worker		tidyOnly:     "",
837*333d2b36SAndroid Build Coastguard Worker		expectedArgs: []string{"-j", "-k"},
838*333d2b36SAndroid Build Coastguard Worker	}, {
839*333d2b36SAndroid Build Coastguard Worker		description:  "normal execution in root source tree, no args",
840*333d2b36SAndroid Build Coastguard Worker		dirsInTrees:  []string{"0/1/2", "0/2", "0/3"},
841*333d2b36SAndroid Build Coastguard Worker		buildFiles:   []string{"0/1/2/Android.mk", "0/2/Android.bp"},
842*333d2b36SAndroid Build Coastguard Worker		args:         []string{},
843*333d2b36SAndroid Build Coastguard Worker		curDir:       "0/2",
844*333d2b36SAndroid Build Coastguard Worker		tidyOnly:     "",
845*333d2b36SAndroid Build Coastguard Worker		expectedArgs: []string{},
846*333d2b36SAndroid Build Coastguard Worker	}, {
847*333d2b36SAndroid Build Coastguard Worker		description:  "normal execution in symlink root source tree, no args",
848*333d2b36SAndroid Build Coastguard Worker		dirsInTrees:  []string{"0/1/2", "0/2", "0/3"},
849*333d2b36SAndroid Build Coastguard Worker		buildFiles:   []string{"0/1/2/Android.mk", "0/2/Android.bp"},
850*333d2b36SAndroid Build Coastguard Worker		rootSymlink:  true,
851*333d2b36SAndroid Build Coastguard Worker		args:         []string{},
852*333d2b36SAndroid Build Coastguard Worker		curDir:       "0/2",
853*333d2b36SAndroid Build Coastguard Worker		tidyOnly:     "",
854*333d2b36SAndroid Build Coastguard Worker		expectedArgs: []string{},
855*333d2b36SAndroid Build Coastguard Worker	}}
856*333d2b36SAndroid Build Coastguard Worker	for _, tt := range tests {
857*333d2b36SAndroid Build Coastguard Worker		t.Run("build action BUILD_MODULES with dependencies, "+tt.description, func(t *testing.T) {
858*333d2b36SAndroid Build Coastguard Worker			testGetConfigArgs(t, tt, BUILD_MODULES)
859*333d2b36SAndroid Build Coastguard Worker		})
860*333d2b36SAndroid Build Coastguard Worker	}
861*333d2b36SAndroid Build Coastguard Worker}
862*333d2b36SAndroid Build Coastguard Worker
863*333d2b36SAndroid Build Coastguard Workerfunc TestGetConfigArgsBuildModulesInDirectory(t *testing.T) {
864*333d2b36SAndroid Build Coastguard Worker	tests := []buildActionTestCase{
865*333d2b36SAndroid Build Coastguard Worker		{
866*333d2b36SAndroid Build Coastguard Worker			description:  "normal execution in a directory",
867*333d2b36SAndroid Build Coastguard Worker			dirsInTrees:  []string{"0/1/2"},
868*333d2b36SAndroid Build Coastguard Worker			buildFiles:   []string{"0/1/2/Android.mk"},
869*333d2b36SAndroid Build Coastguard Worker			args:         []string{"fake-module"},
870*333d2b36SAndroid Build Coastguard Worker			curDir:       "0/1/2",
871*333d2b36SAndroid Build Coastguard Worker			tidyOnly:     "",
872*333d2b36SAndroid Build Coastguard Worker			expectedArgs: []string{"fake-module", "MODULES-IN-0-1-2"},
873*333d2b36SAndroid Build Coastguard Worker		}, {
874*333d2b36SAndroid Build Coastguard Worker			description:  "build file in parent directory",
875*333d2b36SAndroid Build Coastguard Worker			dirsInTrees:  []string{"0/1/2"},
876*333d2b36SAndroid Build Coastguard Worker			buildFiles:   []string{"0/1/Android.mk"},
877*333d2b36SAndroid Build Coastguard Worker			args:         []string{},
878*333d2b36SAndroid Build Coastguard Worker			curDir:       "0/1/2",
879*333d2b36SAndroid Build Coastguard Worker			tidyOnly:     "",
880*333d2b36SAndroid Build Coastguard Worker			expectedArgs: []string{"MODULES-IN-0-1"},
881*333d2b36SAndroid Build Coastguard Worker		},
882*333d2b36SAndroid Build Coastguard Worker		{
883*333d2b36SAndroid Build Coastguard Worker			description:  "build file in parent directory, multiple module names passed in",
884*333d2b36SAndroid Build Coastguard Worker			dirsInTrees:  []string{"0/1/2"},
885*333d2b36SAndroid Build Coastguard Worker			buildFiles:   []string{"0/1/Android.mk"},
886*333d2b36SAndroid Build Coastguard Worker			args:         []string{"fake-module1", "fake-module2", "fake-module3"},
887*333d2b36SAndroid Build Coastguard Worker			curDir:       "0/1/2",
888*333d2b36SAndroid Build Coastguard Worker			tidyOnly:     "",
889*333d2b36SAndroid Build Coastguard Worker			expectedArgs: []string{"fake-module1", "fake-module2", "fake-module3", "MODULES-IN-0-1"},
890*333d2b36SAndroid Build Coastguard Worker		}, {
891*333d2b36SAndroid Build Coastguard Worker			description:  "build file in 2nd level parent directory",
892*333d2b36SAndroid Build Coastguard Worker			dirsInTrees:  []string{"0/1/2"},
893*333d2b36SAndroid Build Coastguard Worker			buildFiles:   []string{"0/Android.bp"},
894*333d2b36SAndroid Build Coastguard Worker			args:         []string{},
895*333d2b36SAndroid Build Coastguard Worker			curDir:       "0/1/2",
896*333d2b36SAndroid Build Coastguard Worker			tidyOnly:     "",
897*333d2b36SAndroid Build Coastguard Worker			expectedArgs: []string{"MODULES-IN-0"},
898*333d2b36SAndroid Build Coastguard Worker		}, {
899*333d2b36SAndroid Build Coastguard Worker			description:  "build action executed at root directory",
900*333d2b36SAndroid Build Coastguard Worker			dirsInTrees:  []string{},
901*333d2b36SAndroid Build Coastguard Worker			buildFiles:   []string{},
902*333d2b36SAndroid Build Coastguard Worker			rootSymlink:  false,
903*333d2b36SAndroid Build Coastguard Worker			args:         []string{},
904*333d2b36SAndroid Build Coastguard Worker			curDir:       ".",
905*333d2b36SAndroid Build Coastguard Worker			tidyOnly:     "",
906*333d2b36SAndroid Build Coastguard Worker			expectedArgs: []string{},
907*333d2b36SAndroid Build Coastguard Worker		}, {
908*333d2b36SAndroid Build Coastguard Worker			description:  "build action executed at root directory in symlink",
909*333d2b36SAndroid Build Coastguard Worker			dirsInTrees:  []string{},
910*333d2b36SAndroid Build Coastguard Worker			buildFiles:   []string{},
911*333d2b36SAndroid Build Coastguard Worker			rootSymlink:  true,
912*333d2b36SAndroid Build Coastguard Worker			args:         []string{},
913*333d2b36SAndroid Build Coastguard Worker			curDir:       ".",
914*333d2b36SAndroid Build Coastguard Worker			tidyOnly:     "",
915*333d2b36SAndroid Build Coastguard Worker			expectedArgs: []string{},
916*333d2b36SAndroid Build Coastguard Worker		}, {
917*333d2b36SAndroid Build Coastguard Worker			description:    "build file not found",
918*333d2b36SAndroid Build Coastguard Worker			dirsInTrees:    []string{"0/1/2"},
919*333d2b36SAndroid Build Coastguard Worker			buildFiles:     []string{},
920*333d2b36SAndroid Build Coastguard Worker			args:           []string{},
921*333d2b36SAndroid Build Coastguard Worker			curDir:         "0/1/2",
922*333d2b36SAndroid Build Coastguard Worker			tidyOnly:       "",
923*333d2b36SAndroid Build Coastguard Worker			expectedArgs:   []string{"MODULES-IN-0-1-2"},
924*333d2b36SAndroid Build Coastguard Worker			expectedErrStr: "Build file not found for 0/1/2 directory",
925*333d2b36SAndroid Build Coastguard Worker		}, {
926*333d2b36SAndroid Build Coastguard Worker			description:  "GET-INSTALL-PATH specified,",
927*333d2b36SAndroid Build Coastguard Worker			dirsInTrees:  []string{"0/1/2"},
928*333d2b36SAndroid Build Coastguard Worker			buildFiles:   []string{"0/1/Android.mk"},
929*333d2b36SAndroid Build Coastguard Worker			args:         []string{"GET-INSTALL-PATH", "-j", "-k", "GET-INSTALL-PATH"},
930*333d2b36SAndroid Build Coastguard Worker			curDir:       "0/1/2",
931*333d2b36SAndroid Build Coastguard Worker			tidyOnly:     "",
932*333d2b36SAndroid Build Coastguard Worker			expectedArgs: []string{"-j", "-k", "GET-INSTALL-PATH-IN-0-1"},
933*333d2b36SAndroid Build Coastguard Worker		}, {
934*333d2b36SAndroid Build Coastguard Worker			description:  "tidy only environment variable specified,",
935*333d2b36SAndroid Build Coastguard Worker			dirsInTrees:  []string{"0/1/2"},
936*333d2b36SAndroid Build Coastguard Worker			buildFiles:   []string{"0/1/Android.mk"},
937*333d2b36SAndroid Build Coastguard Worker			args:         []string{"GET-INSTALL-PATH"},
938*333d2b36SAndroid Build Coastguard Worker			curDir:       "0/1/2",
939*333d2b36SAndroid Build Coastguard Worker			tidyOnly:     "true",
940*333d2b36SAndroid Build Coastguard Worker			expectedArgs: []string{"tidy_only"},
941*333d2b36SAndroid Build Coastguard Worker		}, {
942*333d2b36SAndroid Build Coastguard Worker			description:  "normal execution in root directory with args",
943*333d2b36SAndroid Build Coastguard Worker			dirsInTrees:  []string{},
944*333d2b36SAndroid Build Coastguard Worker			buildFiles:   []string{},
945*333d2b36SAndroid Build Coastguard Worker			args:         []string{"-j", "-k", "fake_module"},
946*333d2b36SAndroid Build Coastguard Worker			curDir:       "",
947*333d2b36SAndroid Build Coastguard Worker			tidyOnly:     "",
948*333d2b36SAndroid Build Coastguard Worker			expectedArgs: []string{"-j", "-k", "fake_module"},
949*333d2b36SAndroid Build Coastguard Worker		},
950*333d2b36SAndroid Build Coastguard Worker	}
951*333d2b36SAndroid Build Coastguard Worker	for _, tt := range tests {
952*333d2b36SAndroid Build Coastguard Worker		t.Run("build action BUILD_MODULES_IN_DIR, "+tt.description, func(t *testing.T) {
953*333d2b36SAndroid Build Coastguard Worker			testGetConfigArgs(t, tt, BUILD_MODULES_IN_A_DIRECTORY)
954*333d2b36SAndroid Build Coastguard Worker		})
955*333d2b36SAndroid Build Coastguard Worker	}
956*333d2b36SAndroid Build Coastguard Worker}
957*333d2b36SAndroid Build Coastguard Worker
958*333d2b36SAndroid Build Coastguard Workerfunc TestGetConfigArgsBuildModulesInDirectories(t *testing.T) {
959*333d2b36SAndroid Build Coastguard Worker	tests := []buildActionTestCase{{
960*333d2b36SAndroid Build Coastguard Worker		description:  "normal execution in a directory",
961*333d2b36SAndroid Build Coastguard Worker		dirsInTrees:  []string{"0/1/2/3.1", "0/1/2/3.2", "0/1/2/3.3"},
962*333d2b36SAndroid Build Coastguard Worker		buildFiles:   []string{"0/1/2/3.1/Android.bp", "0/1/2/3.2/Android.bp", "0/1/2/3.3/Android.bp"},
963*333d2b36SAndroid Build Coastguard Worker		args:         []string{"3.1/", "3.2/", "3.3/"},
964*333d2b36SAndroid Build Coastguard Worker		curDir:       "0/1/2",
965*333d2b36SAndroid Build Coastguard Worker		tidyOnly:     "",
966*333d2b36SAndroid Build Coastguard Worker		expectedArgs: []string{"MODULES-IN-0-1-2-3.1", "MODULES-IN-0-1-2-3.2", "MODULES-IN-0-1-2-3.3"},
967*333d2b36SAndroid Build Coastguard Worker	}, {
968*333d2b36SAndroid Build Coastguard Worker		description:  "GET-INSTALL-PATH specified",
969*333d2b36SAndroid Build Coastguard Worker		dirsInTrees:  []string{"0/1/2/3.1", "0/1/2/3.2", "0/1/3"},
970*333d2b36SAndroid Build Coastguard Worker		buildFiles:   []string{"0/1/2/3.1/Android.bp", "0/1/2/3.2/Android.bp", "0/1/Android.bp"},
971*333d2b36SAndroid Build Coastguard Worker		args:         []string{"GET-INSTALL-PATH", "2/3.1/", "2/3.2", "3"},
972*333d2b36SAndroid Build Coastguard Worker		curDir:       "0/1",
973*333d2b36SAndroid Build Coastguard Worker		tidyOnly:     "",
974*333d2b36SAndroid Build Coastguard Worker		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"},
975*333d2b36SAndroid Build Coastguard Worker	}, {
976*333d2b36SAndroid Build Coastguard Worker		description:  "tidy only environment variable specified",
977*333d2b36SAndroid Build Coastguard Worker		dirsInTrees:  []string{"0/1/2/3.1", "0/1/2/3.2", "0/1/2/3.3"},
978*333d2b36SAndroid Build Coastguard Worker		buildFiles:   []string{"0/1/2/3.1/Android.bp", "0/1/2/3.2/Android.bp", "0/1/2/3.3/Android.bp"},
979*333d2b36SAndroid Build Coastguard Worker		args:         []string{"GET-INSTALL-PATH", "3.1/", "3.2/", "3.3"},
980*333d2b36SAndroid Build Coastguard Worker		curDir:       "0/1/2",
981*333d2b36SAndroid Build Coastguard Worker		tidyOnly:     "1",
982*333d2b36SAndroid Build Coastguard Worker		expectedArgs: []string{"tidy_only"},
983*333d2b36SAndroid Build Coastguard Worker	}, {
984*333d2b36SAndroid Build Coastguard Worker		description:  "normal execution from top dir directory",
985*333d2b36SAndroid Build Coastguard Worker		dirsInTrees:  []string{"0/1/2/3.1", "0/1/2/3.2", "0/1/3", "0/2"},
986*333d2b36SAndroid Build Coastguard Worker		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"},
987*333d2b36SAndroid Build Coastguard Worker		rootSymlink:  false,
988*333d2b36SAndroid Build Coastguard Worker		args:         []string{"0/1/2/3.1", "0/1/2/3.2", "0/1/3", "0/2"},
989*333d2b36SAndroid Build Coastguard Worker		curDir:       ".",
990*333d2b36SAndroid Build Coastguard Worker		tidyOnly:     "",
991*333d2b36SAndroid Build Coastguard Worker		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"},
992*333d2b36SAndroid Build Coastguard Worker	}, {
993*333d2b36SAndroid Build Coastguard Worker		description:  "normal execution from top dir directory in symlink",
994*333d2b36SAndroid Build Coastguard Worker		dirsInTrees:  []string{"0/1/2/3.1", "0/1/2/3.2", "0/1/3", "0/2"},
995*333d2b36SAndroid Build Coastguard Worker		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*333d2b36SAndroid Build Coastguard Worker		rootSymlink:  true,
997*333d2b36SAndroid Build Coastguard Worker		args:         []string{"0/1/2/3.1", "0/1/2/3.2", "0/1/3", "0/2"},
998*333d2b36SAndroid Build Coastguard Worker		curDir:       ".",
999*333d2b36SAndroid Build Coastguard Worker		tidyOnly:     "",
1000*333d2b36SAndroid Build Coastguard Worker		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"},
1001*333d2b36SAndroid Build Coastguard Worker	}}
1002*333d2b36SAndroid Build Coastguard Worker	for _, tt := range tests {
1003*333d2b36SAndroid Build Coastguard Worker		t.Run("build action BUILD_MODULES_IN_DIRS, "+tt.description, func(t *testing.T) {
1004*333d2b36SAndroid Build Coastguard Worker			testGetConfigArgs(t, tt, BUILD_MODULES_IN_DIRECTORIES)
1005*333d2b36SAndroid Build Coastguard Worker		})
1006*333d2b36SAndroid Build Coastguard Worker	}
1007*333d2b36SAndroid Build Coastguard Worker}
1008*333d2b36SAndroid Build Coastguard Worker
1009*333d2b36SAndroid Build Coastguard Workerfunc TestBuildConfig(t *testing.T) {
1010*333d2b36SAndroid Build Coastguard Worker	tests := []struct {
1011*333d2b36SAndroid Build Coastguard Worker		name                string
1012*333d2b36SAndroid Build Coastguard Worker		environ             Environment
1013*333d2b36SAndroid Build Coastguard Worker		arguments           []string
1014*333d2b36SAndroid Build Coastguard Worker		expectedBuildConfig *smpb.BuildConfig
1015*333d2b36SAndroid Build Coastguard Worker	}{
1016*333d2b36SAndroid Build Coastguard Worker		{
1017*333d2b36SAndroid Build Coastguard Worker			name:    "none set",
1018*333d2b36SAndroid Build Coastguard Worker			environ: Environment{},
1019*333d2b36SAndroid Build Coastguard Worker			expectedBuildConfig: &smpb.BuildConfig{
1020*333d2b36SAndroid Build Coastguard Worker				ForceUseGoma:          proto.Bool(false),
1021*333d2b36SAndroid Build Coastguard Worker				UseGoma:               proto.Bool(false),
1022*333d2b36SAndroid Build Coastguard Worker				UseRbe:                proto.Bool(false),
1023*333d2b36SAndroid Build Coastguard Worker				NinjaWeightListSource: smpb.BuildConfig_NOT_USED.Enum(),
1024*333d2b36SAndroid Build Coastguard Worker			},
1025*333d2b36SAndroid Build Coastguard Worker		},
1026*333d2b36SAndroid Build Coastguard Worker		{
1027*333d2b36SAndroid Build Coastguard Worker			name:    "force use goma",
1028*333d2b36SAndroid Build Coastguard Worker			environ: Environment{"FORCE_USE_GOMA=1"},
1029*333d2b36SAndroid Build Coastguard Worker			expectedBuildConfig: &smpb.BuildConfig{
1030*333d2b36SAndroid Build Coastguard Worker				ForceUseGoma:          proto.Bool(true),
1031*333d2b36SAndroid Build Coastguard Worker				UseGoma:               proto.Bool(false),
1032*333d2b36SAndroid Build Coastguard Worker				UseRbe:                proto.Bool(false),
1033*333d2b36SAndroid Build Coastguard Worker				NinjaWeightListSource: smpb.BuildConfig_NOT_USED.Enum(),
1034*333d2b36SAndroid Build Coastguard Worker			},
1035*333d2b36SAndroid Build Coastguard Worker		},
1036*333d2b36SAndroid Build Coastguard Worker		{
1037*333d2b36SAndroid Build Coastguard Worker			name:    "use goma",
1038*333d2b36SAndroid Build Coastguard Worker			environ: Environment{"USE_GOMA=1"},
1039*333d2b36SAndroid Build Coastguard Worker			expectedBuildConfig: &smpb.BuildConfig{
1040*333d2b36SAndroid Build Coastguard Worker				ForceUseGoma:          proto.Bool(false),
1041*333d2b36SAndroid Build Coastguard Worker				UseGoma:               proto.Bool(true),
1042*333d2b36SAndroid Build Coastguard Worker				UseRbe:                proto.Bool(false),
1043*333d2b36SAndroid Build Coastguard Worker				NinjaWeightListSource: smpb.BuildConfig_NOT_USED.Enum(),
1044*333d2b36SAndroid Build Coastguard Worker			},
1045*333d2b36SAndroid Build Coastguard Worker		},
1046*333d2b36SAndroid Build Coastguard Worker		{
1047*333d2b36SAndroid Build Coastguard Worker			// RBE is only supported on linux.
1048*333d2b36SAndroid Build Coastguard Worker			name:    "use rbe",
1049*333d2b36SAndroid Build Coastguard Worker			environ: Environment{"USE_RBE=1"},
1050*333d2b36SAndroid Build Coastguard Worker			expectedBuildConfig: &smpb.BuildConfig{
1051*333d2b36SAndroid Build Coastguard Worker				ForceUseGoma:          proto.Bool(false),
1052*333d2b36SAndroid Build Coastguard Worker				UseGoma:               proto.Bool(false),
1053*333d2b36SAndroid Build Coastguard Worker				UseRbe:                proto.Bool(runtime.GOOS == "linux"),
1054*333d2b36SAndroid Build Coastguard Worker				NinjaWeightListSource: smpb.BuildConfig_NOT_USED.Enum(),
1055*333d2b36SAndroid Build Coastguard Worker			},
1056*333d2b36SAndroid Build Coastguard Worker		},
1057*333d2b36SAndroid Build Coastguard Worker	}
1058*333d2b36SAndroid Build Coastguard Worker
1059*333d2b36SAndroid Build Coastguard Worker	for _, tc := range tests {
1060*333d2b36SAndroid Build Coastguard Worker		t.Run(tc.name, func(t *testing.T) {
1061*333d2b36SAndroid Build Coastguard Worker			c := &configImpl{
1062*333d2b36SAndroid Build Coastguard Worker				environ:   &tc.environ,
1063*333d2b36SAndroid Build Coastguard Worker				arguments: tc.arguments,
1064*333d2b36SAndroid Build Coastguard Worker			}
1065*333d2b36SAndroid Build Coastguard Worker			config := Config{c}
1066*333d2b36SAndroid Build Coastguard Worker			actualBuildConfig := buildConfig(config)
1067*333d2b36SAndroid Build Coastguard Worker			if expected := tc.expectedBuildConfig; !proto.Equal(expected, actualBuildConfig) {
1068*333d2b36SAndroid Build Coastguard Worker				t.Errorf("Build config mismatch.\n"+
1069*333d2b36SAndroid Build Coastguard Worker					"Expected build config: %#v\n"+
1070*333d2b36SAndroid Build Coastguard Worker					"Actual build config: %#v", prototext.Format(expected), prototext.Format(actualBuildConfig))
1071*333d2b36SAndroid Build Coastguard Worker			}
1072*333d2b36SAndroid Build Coastguard Worker		})
1073*333d2b36SAndroid Build Coastguard Worker	}
1074*333d2b36SAndroid Build Coastguard Worker}
1075*333d2b36SAndroid Build Coastguard Worker
1076*333d2b36SAndroid Build Coastguard Workerfunc TestGetMetricsUploaderApp(t *testing.T) {
1077*333d2b36SAndroid Build Coastguard Worker
1078*333d2b36SAndroid Build Coastguard Worker	metricsUploaderDir := "metrics_uploader_dir"
1079*333d2b36SAndroid Build Coastguard Worker	metricsUploaderBinary := "metrics_uploader_binary"
1080*333d2b36SAndroid Build Coastguard Worker	metricsUploaderPath := filepath.Join(metricsUploaderDir, metricsUploaderBinary)
1081*333d2b36SAndroid Build Coastguard Worker	tests := []struct {
1082*333d2b36SAndroid Build Coastguard Worker		description string
1083*333d2b36SAndroid Build Coastguard Worker		environ     Environment
1084*333d2b36SAndroid Build Coastguard Worker		createFiles bool
1085*333d2b36SAndroid Build Coastguard Worker		expected    string
1086*333d2b36SAndroid Build Coastguard Worker	}{{
1087*333d2b36SAndroid Build Coastguard Worker		description: "Uploader binary exist",
1088*333d2b36SAndroid Build Coastguard Worker		environ:     Environment{"METRICS_UPLOADER=" + metricsUploaderPath},
1089*333d2b36SAndroid Build Coastguard Worker		createFiles: true,
1090*333d2b36SAndroid Build Coastguard Worker		expected:    metricsUploaderPath,
1091*333d2b36SAndroid Build Coastguard Worker	}, {
1092*333d2b36SAndroid Build Coastguard Worker		description: "Uploader binary not exist",
1093*333d2b36SAndroid Build Coastguard Worker		environ:     Environment{"METRICS_UPLOADER=" + metricsUploaderPath},
1094*333d2b36SAndroid Build Coastguard Worker		createFiles: false,
1095*333d2b36SAndroid Build Coastguard Worker		expected:    "",
1096*333d2b36SAndroid Build Coastguard Worker	}, {
1097*333d2b36SAndroid Build Coastguard Worker		description: "Uploader binary variable not set",
1098*333d2b36SAndroid Build Coastguard Worker		createFiles: true,
1099*333d2b36SAndroid Build Coastguard Worker		expected:    "",
1100*333d2b36SAndroid Build Coastguard Worker	}}
1101*333d2b36SAndroid Build Coastguard Worker
1102*333d2b36SAndroid Build Coastguard Worker	for _, tt := range tests {
1103*333d2b36SAndroid Build Coastguard Worker		t.Run(tt.description, func(t *testing.T) {
1104*333d2b36SAndroid Build Coastguard Worker			defer logger.Recover(func(err error) {
1105*333d2b36SAndroid Build Coastguard Worker				t.Fatalf("got unexpected error: %v", err)
1106*333d2b36SAndroid Build Coastguard Worker			})
1107*333d2b36SAndroid Build Coastguard Worker
1108*333d2b36SAndroid Build Coastguard Worker			// Create the root source tree.
1109*333d2b36SAndroid Build Coastguard Worker			topDir, err := ioutil.TempDir("", "")
1110*333d2b36SAndroid Build Coastguard Worker			if err != nil {
1111*333d2b36SAndroid Build Coastguard Worker				t.Fatalf("failed to create temp dir: %v", err)
1112*333d2b36SAndroid Build Coastguard Worker			}
1113*333d2b36SAndroid Build Coastguard Worker			defer os.RemoveAll(topDir)
1114*333d2b36SAndroid Build Coastguard Worker
1115*333d2b36SAndroid Build Coastguard Worker			expected := tt.expected
1116*333d2b36SAndroid Build Coastguard Worker			if len(expected) > 0 {
1117*333d2b36SAndroid Build Coastguard Worker				expected = filepath.Join(topDir, expected)
1118*333d2b36SAndroid Build Coastguard Worker			}
1119*333d2b36SAndroid Build Coastguard Worker
1120*333d2b36SAndroid Build Coastguard Worker			if tt.createFiles {
1121*333d2b36SAndroid Build Coastguard Worker				if err := os.MkdirAll(filepath.Join(topDir, metricsUploaderDir), 0755); err != nil {
1122*333d2b36SAndroid Build Coastguard Worker					t.Errorf("failed to create %s directory: %v", metricsUploaderDir, err)
1123*333d2b36SAndroid Build Coastguard Worker				}
1124*333d2b36SAndroid Build Coastguard Worker				if err := ioutil.WriteFile(filepath.Join(topDir, metricsUploaderPath), []byte{}, 0644); err != nil {
1125*333d2b36SAndroid Build Coastguard Worker					t.Errorf("failed to create file %s: %v", expected, err)
1126*333d2b36SAndroid Build Coastguard Worker				}
1127*333d2b36SAndroid Build Coastguard Worker			}
1128*333d2b36SAndroid Build Coastguard Worker
1129*333d2b36SAndroid Build Coastguard Worker			actual := GetMetricsUploader(topDir, &tt.environ)
1130*333d2b36SAndroid Build Coastguard Worker
1131*333d2b36SAndroid Build Coastguard Worker			if actual != expected {
1132*333d2b36SAndroid Build Coastguard Worker				t.Errorf("expecting: %s, actual: %s", expected, actual)
1133*333d2b36SAndroid Build Coastguard Worker			}
1134*333d2b36SAndroid Build Coastguard Worker		})
1135*333d2b36SAndroid Build Coastguard Worker	}
1136*333d2b36SAndroid Build Coastguard Worker}
1137