2 # Copyright 2015 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
17 class FakeMBW(mb
.MetaBuildWrapper
):
19 super(FakeMBW
, self
).__init
__()
21 # Override vars for test portability.
22 self
.chromium_src_dir
= '/fake_src'
23 self
.default_config
= '/fake_src/tools/mb/mb_config.pyl'
24 self
.executable
= 'python'
25 self
.platform
= 'linux2'
31 self
.cross_compile
= None
36 def ExpandUser(self
, path
):
37 return '$HOME/%s' % path
39 def Exists(self
, path
):
40 return self
.files
.get(path
) is not None
42 def MaybeMakeDirectory(self
, path
):
43 self
.files
[path
] = True
45 def PathJoin(self
, *comps
):
46 return self
.sep
.join(comps
)
48 def ReadFile(self
, path
):
49 return self
.files
[path
]
51 def WriteFile(self
, path
, contents
, force_verbose
=False):
52 self
.files
[path
] = contents
54 def Call(self
, cmd
, env
=None):
56 self
.cross_compile
= env
.get('GYP_CROSSCOMPILE')
57 self
.calls
.append(cmd
)
59 return self
.cmds
.pop(0)
62 def Print(self
, *args
, **kwargs
):
63 sep
= kwargs
.get('sep', ' ')
64 end
= kwargs
.get('end', '\n')
65 f
= kwargs
.get('file', sys
.stdout
)
67 self
.err
+= sep
.join(args
) + end
69 self
.out
+= sep
.join(args
) + end
71 def TempFile(self
, mode
='w'):
72 return FakeFile(self
.files
)
74 def RemoveFile(self
, path
):
77 def RemoveDirectory(self
, path
):
78 self
.rmdirs
.append(path
)
79 files_to_delete
= [f
for f
in self
.files
if f
.startswith(path
)]
80 for f
in files_to_delete
:
84 class FakeFile(object):
85 def __init__(self
, files
):
86 self
.name
= '/tmp/file'
90 def write(self
, contents
):
94 self
.files
[self
.name
] = self
.buf
99 'common_dev_configs': ['gn_debug'],
101 'gyp_rel_bot': ['gyp', 'rel', 'goma'],
102 'gn_debug': ['gn', 'debug'],
103 'gyp_debug': ['gyp', 'debug'],
104 'gn_rel_bot': ['gn', 'rel', 'goma'],
105 'private': ['gyp', 'rel', 'fake_feature1'],
106 'unsupported': ['gn', 'fake_feature2'],
110 'fake_builder': 'gyp_rel_bot',
111 'fake_gn_builder': 'gn_rel_bot',
112 'fake_gyp_builder': 'gyp_debug',
117 'gn_args': 'enable_doom_melon=true',
118 'gyp_crosscompile': True,
119 'gyp_defines': 'doom_melon=1',
122 'gn_args': 'enable_doom_melon=false',
123 'gyp_defaults': 'doom_melon=0',
125 'gyp': {'type': 'gyp'},
126 'gn': {'type': 'gn'},
128 'gn_args': 'use_goma=true goma_dir="$(goma_dir)"',
129 'gyp_defines': 'goma=1 gomadir="$(goma_dir)"',
132 'gn_args': 'is_debug=false',
135 'gn_args': 'is_debug=true',
138 'private_configs': ['private'],
139 'unsupported_configs': ['unsupported'],
144 class UnitTest(unittest
.TestCase
):
145 def fake_mbw(self
, files
=None):
147 mbw
.files
.setdefault(mbw
.default_config
, TEST_CONFIG
)
149 for path
, contents
in files
.items():
150 mbw
.files
[path
] = contents
153 def check(self
, args
, mbw
=None, files
=None, out
=None, err
=None, ret
=None):
155 mbw
= self
.fake_mbw(files
)
157 actual_ret
= mbw
.args
.func()
159 self
.assertEqual(actual_ret
, ret
)
161 self
.assertEqual(mbw
.out
, out
)
163 self
.assertEqual(mbw
.err
, err
)
166 def test_clobber(self
):
168 '/fake_src/out/Debug': None,
169 '/fake_src/out/Debug/mb_type': None,
171 mbw
= self
.fake_mbw(files
)
173 # The first time we run this, the build dir doesn't exist, so no clobber.
174 self
.check(['gen', '-c', 'gn_debug', '//out/Debug'], mbw
=mbw
, ret
=0)
175 self
.assertEqual(mbw
.rmdirs
, [])
176 self
.assertEqual(mbw
.files
['/fake_src/out/Debug/mb_type'], 'gn')
178 # The second time we run this, the build dir exists and matches, so no
180 self
.check(['gen', '-c', 'gn_debug', '//out/Debug'], mbw
=mbw
, ret
=0)
181 self
.assertEqual(mbw
.rmdirs
, [])
182 self
.assertEqual(mbw
.files
['/fake_src/out/Debug/mb_type'], 'gn')
184 # Now we switch build types; this should result in a clobber.
185 self
.check(['gen', '-c', 'gyp_debug', '//out/Debug'], mbw
=mbw
, ret
=0)
186 self
.assertEqual(mbw
.rmdirs
, ['/fake_src/out/Debug'])
187 self
.assertEqual(mbw
.files
['/fake_src/out/Debug/mb_type'], 'gyp')
189 # Now we delete mb_type; this checks the case where the build dir
190 # exists but wasn't populated by mb; this should also result in a clobber.
191 del mbw
.files
['/fake_src/out/Debug/mb_type']
192 self
.check(['gen', '-c', 'gyp_debug', '//out/Debug'], mbw
=mbw
, ret
=0)
193 self
.assertEqual(mbw
.rmdirs
,
194 ['/fake_src/out/Debug', '/fake_src/out/Debug'])
195 self
.assertEqual(mbw
.files
['/fake_src/out/Debug/mb_type'], 'gyp')
197 def test_gn_analyze(self
):
198 files
= {'/tmp/in.json': """{\
199 "files": ["foo/foo_unittest.cc"],
200 "targets": ["foo_unittests", "bar_unittests"]
203 mbw
= self
.fake_mbw(files
)
204 mbw
.Call
= lambda cmd
, env
=None: (0, 'out/Default/foo_unittests\n', '')
206 self
.check(['analyze', '-c', 'gn_debug', '//out/Default',
207 '/tmp/in.json', '/tmp/out.json'], mbw
=mbw
, ret
=0)
208 out
= json
.loads(mbw
.files
['/tmp/out.json'])
209 self
.assertEqual(out
, {
210 'status': 'Found dependency',
211 'targets': ['foo_unittests'],
212 'build_targets': ['foo_unittests']
215 def test_gn_analyze_all(self
):
216 files
= {'/tmp/in.json': """{\
217 "files": ["foo/foo_unittest.cc"],
218 "targets": ["all", "bar_unittests"]
220 mbw
= self
.fake_mbw(files
)
221 mbw
.Call
= lambda cmd
, env
=None: (0, 'out/Default/foo_unittests\n', '')
222 self
.check(['analyze', '-c', 'gn_debug', '//out/Default',
223 '/tmp/in.json', '/tmp/out.json'], mbw
=mbw
, ret
=0)
224 out
= json
.loads(mbw
.files
['/tmp/out.json'])
225 self
.assertEqual(out
, {
226 'status': 'Found dependency (all)',
229 def test_gn_analyze_missing_file(self
):
230 files
= {'/tmp/in.json': """{\
231 "files": ["foo/foo_unittest.cc"],
232 "targets": ["bar_unittests"]
234 mbw
= self
.fake_mbw(files
)
237 (1, 'The input matches no targets, configs, or files\n', ''),
238 (1, 'The input matches no targets, configs, or files\n', ''),
241 self
.check(['analyze', '-c', 'gn_debug', '//out/Default',
242 '/tmp/in.json', '/tmp/out.json'], mbw
=mbw
, ret
=0)
243 out
= json
.loads(mbw
.files
['/tmp/out.json'])
244 self
.assertEqual(out
, {
247 'status': 'No dependency',
250 def test_gn_gen(self
):
251 self
.check(['gen', '-c', 'gn_debug', '//out/Default'], ret
=0)
252 self
.check(['gen', '-c', 'gyp_rel_bot', '//out/Release'], ret
=0)
254 def test_gn_gen_fails(self
):
255 mbw
= self
.fake_mbw()
256 mbw
.Call
= lambda cmd
, env
=None: (1, '', '')
257 self
.check(['gen', '-c', 'gn_debug', '//out/Default'], mbw
=mbw
, ret
=1)
259 def test_gn_gen_swarming(self
):
261 '/tmp/swarming_targets': 'base_unittests\n',
262 '/fake_src/testing/buildbot/gn_isolate_map.pyl': (
263 "{'base_unittests': {"
264 " 'label': '//base:base_unittests',"
269 '/fake_src/out/Default/base_unittests.runtime_deps': (
273 mbw
= self
.fake_mbw(files
)
276 '--swarming-targets-file', '/tmp/swarming_targets',
277 '//out/Default'], mbw
=mbw
, ret
=0)
278 self
.assertIn('/fake_src/out/Default/base_unittests.isolate',
280 self
.assertIn('/fake_src/out/Default/base_unittests.isolated.gen.json',
283 def test_gn_lookup(self
):
284 self
.check(['lookup', '-c', 'gn_debug'], ret
=0)
286 def test_gn_lookup_goma_dir_expansion(self
):
287 self
.check(['lookup', '-c', 'gn_rel_bot', '-g', '/foo'], ret
=0,
288 out
=("/fake_src/buildtools/linux64/gn gen '<path>' "
289 "'--args=is_debug=false use_goma=true "
290 "goma_dir=\"/foo\"'\n" ))
292 def test_gyp_analyze(self
):
293 mbw
= self
.check(['analyze', '-c', 'gyp_rel_bot', '//out/Release',
294 '/tmp/in.json', '/tmp/out.json'],
296 self
.assertIn('analyzer', mbw
.calls
[0])
298 def test_gyp_crosscompile(self
):
299 mbw
= self
.fake_mbw()
300 self
.check(['gen', '-c', 'private', '//out/Release'], mbw
=mbw
)
301 self
.assertTrue(mbw
.cross_compile
)
303 def test_gyp_gen(self
):
304 self
.check(['gen', '-c', 'gyp_rel_bot', '-g', '/goma', '//out/Release'],
306 out
=("python build/gyp_chromium -G output_dir=out "
307 "-D goma=1 -D gomadir=/goma\n"))
310 mbw
= self
.fake_mbw()
312 self
.check(['gen', '-c', 'gyp_rel_bot', '-g', 'c:\\goma', '//out/Release'],
314 out
=("python 'build\\gyp_chromium' -G output_dir=out "
315 "-D goma=1 -D 'gomadir=c:\\goma'\n"))
317 def test_gyp_gen_fails(self
):
318 mbw
= self
.fake_mbw()
319 mbw
.Call
= lambda cmd
, env
=None: (1, '', '')
320 self
.check(['gen', '-c', 'gyp_rel_bot', '//out/Release'], mbw
=mbw
, ret
=1)
322 def test_gyp_lookup_goma_dir_expansion(self
):
323 self
.check(['lookup', '-c', 'gyp_rel_bot', '-g', '/foo'], ret
=0,
324 out
=("python build/gyp_chromium -G 'output_dir=<path>' "
325 "-D goma=1 -D gomadir=/foo\n"))
328 orig_stdout
= sys
.stdout
330 sys
.stdout
= StringIO
.StringIO()
331 self
.assertRaises(SystemExit, self
.check
, ['-h'])
332 self
.assertRaises(SystemExit, self
.check
, ['help'])
333 self
.assertRaises(SystemExit, self
.check
, ['help', 'gen'])
335 sys
.stdout
= orig_stdout
338 def test_validate(self
):
339 self
.check(['validate'], ret
=0)
342 if __name__
== '__main__':