Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(202)

Side by Side Diff: tools/mb/mb_unittest.py

Issue 1366093004: Merge latest MB from trunk back to M46. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@branch_2490
Patch Set: Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « tools/mb/mb_config.pyl ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/python 1 #!/usr/bin/python
2 # Copyright 2015 The Chromium Authors. All rights reserved. 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 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 5
6 """Tests for mb.py.""" 6 """Tests for mb.py."""
7 7
8 import json 8 import json
9 import StringIO 9 import StringIO
10 import os
10 import sys 11 import sys
11 import unittest 12 import unittest
12 13
13 import mb 14 import mb
14 15
15 16
16 class FakeMBW(mb.MetaBuildWrapper): 17 class FakeMBW(mb.MetaBuildWrapper):
17 def __init__(self): 18 def __init__(self, win32=False):
18 super(FakeMBW, self).__init__() 19 super(FakeMBW, self).__init__()
20
21 # Override vars for test portability.
22 if win32:
23 self.chromium_src_dir = 'c:\\fake_src'
24 self.default_config = 'c:\\fake_src\\tools\\mb\\mb_config.pyl'
25 self.platform = 'win32'
26 self.executable = 'c:\\python\\python.exe'
27 self.sep = '\\'
28 else:
29 self.chromium_src_dir = '/fake_src'
30 self.default_config = '/fake_src/tools/mb/mb_config.pyl'
31 self.executable = '/usr/bin/python'
32 self.platform = 'linux2'
33 self.sep = '/'
34
19 self.files = {} 35 self.files = {}
20 self.calls = [] 36 self.calls = []
21 self.cmds = [] 37 self.cmds = []
22 self.cross_compile = None 38 self.cross_compile = None
23 self.out = '' 39 self.out = ''
24 self.err = '' 40 self.err = ''
25 self.platform = 'linux2' 41 self.rmdirs = []
26 self.chromium_src_dir = '/fake_src'
27 self.default_config = '/fake_src/tools/mb/mb_config.pyl'
28 42
29 def ExpandUser(self, path): 43 def ExpandUser(self, path):
30 return '$HOME/%s' % path 44 return '$HOME/%s' % path
31 45
32 def Exists(self, path): 46 def Exists(self, path):
33 return self.files.get(path) is not None 47 return self.files.get(path) is not None
34 48
35 def MaybeMakeDirectory(self, path): 49 def MaybeMakeDirectory(self, path):
36 pass 50 self.files[path] = True
51
52 def PathJoin(self, *comps):
53 return self.sep.join(comps)
37 54
38 def ReadFile(self, path): 55 def ReadFile(self, path):
39 return self.files[path] 56 return self.files[path]
40 57
41 def WriteFile(self, path, contents): 58 def WriteFile(self, path, contents, force_verbose=False):
42 self.files[path] = contents 59 self.files[path] = contents
43 60
44 def Call(self, cmd, env=None): 61 def Call(self, cmd, env=None):
45 if env: 62 if env:
46 self.cross_compile = env.get('GYP_CROSSCOMPILE') 63 self.cross_compile = env.get('GYP_CROSSCOMPILE')
47 self.calls.append(cmd) 64 self.calls.append(cmd)
48 if self.cmds: 65 if self.cmds:
49 return self.cmds.pop(0) 66 return self.cmds.pop(0)
50 return 0, '', '' 67 return 0, '', ''
51 68
52 def Print(self, *args, **kwargs): 69 def Print(self, *args, **kwargs):
53 sep = kwargs.get('sep', ' ') 70 sep = kwargs.get('sep', ' ')
54 end = kwargs.get('end', '\n') 71 end = kwargs.get('end', '\n')
55 f = kwargs.get('file', sys.stdout) 72 f = kwargs.get('file', sys.stdout)
56 if f == sys.stderr: 73 if f == sys.stderr:
57 self.err += sep.join(args) + end 74 self.err += sep.join(args) + end
58 else: 75 else:
59 self.out += sep.join(args) + end 76 self.out += sep.join(args) + end
60 77
61 def TempFile(self, mode='w'): 78 def TempFile(self, mode='w'):
62 return FakeFile(self.files) 79 return FakeFile(self.files)
63 80
64 def RemoveFile(self, path): 81 def RemoveFile(self, path):
65 del self.files[path] 82 del self.files[path]
66 83
84 def RemoveDirectory(self, path):
85 self.rmdirs.append(path)
86 files_to_delete = [f for f in self.files if f.startswith(path)]
87 for f in files_to_delete:
88 self.files[f] = None
89
67 90
68 class FakeFile(object): 91 class FakeFile(object):
69 def __init__(self, files): 92 def __init__(self, files):
70 self.name = '/tmp/file' 93 self.name = '/tmp/file'
71 self.buf = '' 94 self.buf = ''
72 self.files = files 95 self.files = files
73 96
74 def write(self, contents): 97 def write(self, contents):
75 self.buf += contents 98 self.buf += contents
76 99
77 def close(self): 100 def close(self):
78 self.files[self.name] = self.buf 101 self.files[self.name] = self.buf
79 102
80 103
81 TEST_CONFIG = """\ 104 TEST_CONFIG = """\
82 { 105 {
83 'common_dev_configs': ['gn_debug'], 106 'common_dev_configs': ['gn_debug'],
84 'configs': { 107 'configs': {
85 'gyp_rel_bot': ['gyp', 'rel', 'goma'], 108 'gyp_rel_bot': ['gyp', 'rel', 'goma'],
86 'gn_debug': ['gn', 'debug'], 109 'gn_debug': ['gn', 'debug', 'goma'],
110 'gyp_debug': ['gyp', 'debug'],
87 'gn_rel_bot': ['gn', 'rel', 'goma'], 111 'gn_rel_bot': ['gn', 'rel', 'goma'],
88 'private': ['gyp', 'rel', 'fake_feature1'], 112 'private': ['gyp', 'rel', 'fake_feature1'],
89 'unsupported': ['gn', 'fake_feature2'], 113 'unsupported': ['gn', 'fake_feature2'],
90 }, 114 },
91 'masters': { 115 'masters': {
92 'fake_master': { 116 'fake_master': {
93 'fake_builder': 'gyp_rel_bot', 117 'fake_builder': 'gyp_rel_bot',
94 'fake_gn_builder': 'gn_rel_bot', 118 'fake_gn_builder': 'gn_rel_bot',
119 'fake_gyp_builder': 'gyp_debug',
95 }, 120 },
96 }, 121 },
97 'mixins': { 122 'mixins': {
98 'fake_feature1': { 123 'fake_feature1': {
99 'gn_args': 'enable_doom_melon=true', 124 'gn_args': 'enable_doom_melon=true',
100 'gyp_crosscompile': True, 125 'gyp_crosscompile': True,
101 'gyp_defines': 'doom_melon=1', 126 'gyp_defines': 'doom_melon=1',
102 }, 127 },
103 'fake_feature2': { 128 'fake_feature2': {
104 'gn_args': 'enable_doom_melon=false', 129 'gn_args': 'enable_doom_melon=false',
105 'gyp_defaults': 'doom_melon=0', 130 'gyp_defaults': 'doom_melon=0',
106 }, 131 },
107 'gyp': {'type': 'gyp'}, 132 'gyp': {'type': 'gyp'},
108 'gn': {'type': 'gn'}, 133 'gn': {'type': 'gn'},
109 'goma': { 134 'goma': {
110 'gn_args': 'use_goma=true goma_dir="$(goma_dir)"', 135 'gn_args': 'use_goma=true goma_dir="$(goma_dir)"',
111 'gyp_defines': 'goma=1 gomadir="$(goma_dir)"', 136 'gyp_defines': 'goma=1 gomadir=$(goma_dir)',
112 }, 137 },
113 'rel': { 138 'rel': {
114 'gn_args': 'is_debug=false', 139 'gn_args': 'is_debug=false',
115 'gyp_config': 'Release',
116 }, 140 },
117 'debug': { 141 'debug': {
118 'gn_args': 'is_debug=true', 142 'gn_args': 'is_debug=true',
119 }, 143 },
120 }, 144 },
121 'private_configs': ['private'], 145 'private_configs': ['private'],
122 'unsupported_configs': ['unsupported'], 146 'unsupported_configs': ['unsupported'],
123 } 147 }
124 """ 148 """
125 149
126 150
127 class UnitTest(unittest.TestCase): 151 class UnitTest(unittest.TestCase):
128 def fake_mbw(self, files=None): 152 def fake_mbw(self, files=None, win32=False):
129 mbw = FakeMBW() 153 mbw = FakeMBW(win32=win32)
130 mbw.files.setdefault(mbw.default_config, TEST_CONFIG) 154 mbw.files.setdefault(mbw.default_config, TEST_CONFIG)
131 if files: 155 if files:
132 for path, contents in files.items(): 156 for path, contents in files.items():
133 mbw.files[path] = contents 157 mbw.files[path] = contents
134 return mbw 158 return mbw
135 159
136 def check(self, args, mbw=None, files=None, out=None, err=None, ret=None): 160 def check(self, args, mbw=None, files=None, out=None, err=None, ret=None):
137 if not mbw: 161 if not mbw:
138 mbw = self.fake_mbw(files) 162 mbw = self.fake_mbw(files)
139 mbw.ParseArgs(args) 163 mbw.ParseArgs(args)
140 actual_ret = mbw.args.func() 164 actual_ret = mbw.args.func()
141 if ret is not None: 165 if ret is not None:
142 self.assertEqual(actual_ret, ret) 166 self.assertEqual(actual_ret, ret)
143 if out is not None: 167 if out is not None:
144 self.assertEqual(mbw.out, out) 168 self.assertEqual(mbw.out, out)
145 if err is not None: 169 if err is not None:
146 self.assertEqual(mbw.err, err) 170 self.assertEqual(mbw.err, err)
147 return mbw 171 return mbw
148 172
173 def test_clobber(self):
174 files = {
175 '/fake_src/out/Debug': None,
176 '/fake_src/out/Debug/mb_type': None,
177 }
178 mbw = self.fake_mbw(files)
179
180 # The first time we run this, the build dir doesn't exist, so no clobber.
181 self.check(['gen', '-c', 'gn_debug', '//out/Debug'], mbw=mbw, ret=0)
182 self.assertEqual(mbw.rmdirs, [])
183 self.assertEqual(mbw.files['/fake_src/out/Debug/mb_type'], 'gn')
184
185 # The second time we run this, the build dir exists and matches, so no
186 # clobber.
187 self.check(['gen', '-c', 'gn_debug', '//out/Debug'], mbw=mbw, ret=0)
188 self.assertEqual(mbw.rmdirs, [])
189 self.assertEqual(mbw.files['/fake_src/out/Debug/mb_type'], 'gn')
190
191 # Now we switch build types; this should result in a clobber.
192 self.check(['gen', '-c', 'gyp_debug', '//out/Debug'], mbw=mbw, ret=0)
193 self.assertEqual(mbw.rmdirs, ['/fake_src/out/Debug'])
194 self.assertEqual(mbw.files['/fake_src/out/Debug/mb_type'], 'gyp')
195
196 # Now we delete mb_type; this checks the case where the build dir
197 # exists but wasn't populated by mb; this should also result in a clobber.
198 del mbw.files['/fake_src/out/Debug/mb_type']
199 self.check(['gen', '-c', 'gyp_debug', '//out/Debug'], mbw=mbw, ret=0)
200 self.assertEqual(mbw.rmdirs,
201 ['/fake_src/out/Debug', '/fake_src/out/Debug'])
202 self.assertEqual(mbw.files['/fake_src/out/Debug/mb_type'], 'gyp')
203
149 def test_gn_analyze(self): 204 def test_gn_analyze(self):
150 files = {'/tmp/in.json': """{\ 205 files = {'/tmp/in.json': """{\
151 "files": ["foo/foo_unittest.cc"], 206 "files": ["foo/foo_unittest.cc"],
152 "targets": ["foo_unittests", "bar_unittests"] 207 "targets": ["foo_unittests", "bar_unittests"]
153 }"""} 208 }"""}
154 209
155 mbw = self.fake_mbw(files) 210 mbw = self.fake_mbw(files)
156 mbw.Call = lambda cmd, env=None: (0, 'out/Default/foo_unittests\n', '') 211 mbw.Call = lambda cmd, env=None: (0, 'out/Default/foo_unittests\n', '')
157 212
158 self.check(['analyze', '-c', 'gn_debug', '//out/Default', 213 self.check(['analyze', '-c', 'gn_debug', '//out/Default',
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
193 self.check(['analyze', '-c', 'gn_debug', '//out/Default', 248 self.check(['analyze', '-c', 'gn_debug', '//out/Default',
194 '/tmp/in.json', '/tmp/out.json'], mbw=mbw, ret=0) 249 '/tmp/in.json', '/tmp/out.json'], mbw=mbw, ret=0)
195 out = json.loads(mbw.files['/tmp/out.json']) 250 out = json.loads(mbw.files['/tmp/out.json'])
196 self.assertEqual(out, { 251 self.assertEqual(out, {
197 'build_targets': [], 252 'build_targets': [],
198 'targets': [], 253 'targets': [],
199 'status': 'No dependency', 254 'status': 'No dependency',
200 }) 255 })
201 256
202 def test_gn_gen(self): 257 def test_gn_gen(self):
203 self.check(['gen', '-c', 'gn_debug', '//out/Default'], ret=0) 258 self.check(['gen', '-c', 'gn_debug', '//out/Default', '-g', '/goma'],
204 self.check(['gen', '-c', 'gyp_rel_bot', '//out/Release'], ret=0) 259 ret=0,
260 out=('/fake_src/buildtools/linux64/gn gen //out/Default '
261 '\'--args=is_debug=true use_goma=true goma_dir="/goma"\' '
262 '--check\n'))
263
264 mbw = self.fake_mbw(win32=True)
265 self.check(['gen', '-c', 'gn_debug', '-g', 'c:\\goma', '//out/Debug'],
266 mbw=mbw, ret=0,
267 out=('c:\\fake_src\\buildtools\\win\\gn gen //out/Debug '
268 '"--args=is_debug=true use_goma=true goma_dir=\\"'
269 'c:\\goma\\"" --check\n'))
270
205 271
206 def test_gn_gen_fails(self): 272 def test_gn_gen_fails(self):
207 mbw = self.fake_mbw() 273 mbw = self.fake_mbw()
208 mbw.Call = lambda cmd, env=None: (1, '', '') 274 mbw.Call = lambda cmd, env=None: (1, '', '')
209 self.check(['gen', '-c', 'gn_debug', '//out/Default'], mbw=mbw, ret=1) 275 self.check(['gen', '-c', 'gn_debug', '//out/Default'], mbw=mbw, ret=1)
210 276
211 def test_gn_gen_swarming(self): 277 def test_gn_gen_swarming(self):
212 files = { 278 files = {
213 '/tmp/swarming_targets': 'base_unittests\n', 279 '/tmp/swarming_targets': 'base_unittests\n',
214 '/fake_src/testing/buildbot/gn_isolate_map.pyl': ( 280 '/fake_src/testing/buildbot/gn_isolate_map.pyl': (
(...skipping 15 matching lines...) Expand all
230 self.assertIn('/fake_src/out/Default/base_unittests.isolate', 296 self.assertIn('/fake_src/out/Default/base_unittests.isolate',
231 mbw.files) 297 mbw.files)
232 self.assertIn('/fake_src/out/Default/base_unittests.isolated.gen.json', 298 self.assertIn('/fake_src/out/Default/base_unittests.isolated.gen.json',
233 mbw.files) 299 mbw.files)
234 300
235 def test_gn_lookup(self): 301 def test_gn_lookup(self):
236 self.check(['lookup', '-c', 'gn_debug'], ret=0) 302 self.check(['lookup', '-c', 'gn_debug'], ret=0)
237 303
238 def test_gn_lookup_goma_dir_expansion(self): 304 def test_gn_lookup_goma_dir_expansion(self):
239 self.check(['lookup', '-c', 'gn_rel_bot', '-g', '/foo'], ret=0, 305 self.check(['lookup', '-c', 'gn_rel_bot', '-g', '/foo'], ret=0,
240 out=("/fake_src/buildtools/linux64/gn gen '<path>' " 306 out=("/fake_src/buildtools/linux64/gn gen _path_ "
241 "'--args=is_debug=false use_goma=true " 307 "'--args=is_debug=false use_goma=true "
242 "goma_dir=\"/foo\"'\n" )) 308 "goma_dir=\"/foo\"'\n" ))
243 309
244 def test_gyp_analyze(self): 310 def test_gyp_analyze(self):
245 mbw = self.check(['analyze', '-c', 'gyp_rel_bot', '//out/Release', 311 mbw = self.check(['analyze', '-c', 'gyp_rel_bot', '//out/Release',
246 '/tmp/in.json', '/tmp/out.json'], 312 '/tmp/in.json', '/tmp/out.json'],
247 ret=0) 313 ret=0)
248 self.assertIn('analyzer', mbw.calls[0]) 314 self.assertIn('analyzer', mbw.calls[0])
249 315
250 def test_gyp_crosscompile(self): 316 def test_gyp_crosscompile(self):
251 mbw = self.fake_mbw() 317 mbw = self.fake_mbw()
252 self.check(['gen', '-c', 'private', '//out/Release'], mbw=mbw) 318 self.check(['gen', '-c', 'private', '//out/Release'], mbw=mbw)
253 self.assertTrue(mbw.cross_compile) 319 self.assertTrue(mbw.cross_compile)
254 320
255 def test_gyp_gen(self): 321 def test_gyp_gen(self):
256 self.check(['gen', '-c', 'gyp_rel_bot', '//out/Release'], ret=0) 322 self.check(['gen', '-c', 'gyp_rel_bot', '-g', '/goma', '//out/Release'],
323 ret=0,
324 out=("GYP_DEFINES='goma=1 gomadir=/goma'\n"
325 "python build/gyp_chromium -G output_dir=out\n"))
326
327 mbw = self.fake_mbw(win32=True)
328 self.check(['gen', '-c', 'gyp_rel_bot', '-g', 'c:\\goma', '//out/Release'],
329 mbw=mbw, ret=0,
330 out=("set GYP_DEFINES=goma=1 gomadir='c:\\goma'\n"
331 "python build\\gyp_chromium -G output_dir=out\n"))
257 332
258 def test_gyp_gen_fails(self): 333 def test_gyp_gen_fails(self):
259 mbw = self.fake_mbw() 334 mbw = self.fake_mbw()
260 mbw.Call = lambda cmd, env=None: (1, '', '') 335 mbw.Call = lambda cmd, env=None: (1, '', '')
261 self.check(['gen', '-c', 'gyp_rel_bot', '//out/Release'], mbw=mbw, ret=1) 336 self.check(['gen', '-c', 'gyp_rel_bot', '//out/Release'], mbw=mbw, ret=1)
262 337
263 def test_gyp_lookup_goma_dir_expansion(self): 338 def test_gyp_lookup_goma_dir_expansion(self):
264 self.check(['lookup', '-c', 'gyp_rel_bot', '-g', '/foo'], ret=0, 339 self.check(['lookup', '-c', 'gyp_rel_bot', '-g', '/foo'], ret=0,
265 out=("python build/gyp_chromium -G 'output_dir=<path>' " 340 out=("GYP_DEFINES='goma=1 gomadir=/foo'\n"
266 "-G config=Release -D goma=1 -D gomadir=/foo\n")) 341 "python build/gyp_chromium -G output_dir=_path_\n"))
267 342
268 def test_help(self): 343 def test_help(self):
269 orig_stdout = sys.stdout 344 orig_stdout = sys.stdout
270 try: 345 try:
271 sys.stdout = StringIO.StringIO() 346 sys.stdout = StringIO.StringIO()
272 self.assertRaises(SystemExit, self.check, ['-h']) 347 self.assertRaises(SystemExit, self.check, ['-h'])
273 self.assertRaises(SystemExit, self.check, ['help']) 348 self.assertRaises(SystemExit, self.check, ['help'])
274 self.assertRaises(SystemExit, self.check, ['help', 'gen']) 349 self.assertRaises(SystemExit, self.check, ['help', 'gen'])
275 finally: 350 finally:
276 sys.stdout = orig_stdout 351 sys.stdout = orig_stdout
277 352
278 353
279 def test_validate(self): 354 def test_validate(self):
280 self.check(['validate'], ret=0) 355 self.check(['validate'], ret=0)
281 356
282 357
283 if __name__ == '__main__': 358 if __name__ == '__main__':
284 unittest.main() 359 unittest.main()
OLDNEW
« no previous file with comments | « tools/mb/mb_config.pyl ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698