| OLD | NEW |
| 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 sys | 10 import sys |
| 11 import unittest | 11 import unittest |
| 12 | 12 |
| 13 import mb | 13 import mb |
| 14 | 14 |
| 15 | 15 |
| 16 class FakeMBW(mb.MetaBuildWrapper): | 16 class FakeMBW(mb.MetaBuildWrapper): |
| 17 def __init__(self): | 17 def __init__(self): |
| 18 super(FakeMBW, self).__init__() | 18 super(FakeMBW, self).__init__() |
| 19 self.files = {} | 19 self.files = {} |
| 20 self.calls = [] | 20 self.calls = [] |
| 21 self.cmds = [] | 21 self.cmds = [] |
| 22 self.cross_compile = None | 22 self.cross_compile = None |
| 23 self.out = '' | 23 self.out = '' |
| 24 self.err = '' | 24 self.err = '' |
| 25 self.platform = 'linux2' | 25 self.platform = 'linux2' |
| 26 self.chromium_src_dir = '/fake_src' | 26 self.chromium_src_dir = '/fake_src' |
| 27 self.default_config = '/fake_src/tools/mb/mb_config.pyl' | 27 self.default_config = '/fake_src/tools/mb/mb_config.pyl' |
| 28 self.rmdirs = [] |
| 28 | 29 |
| 29 def ExpandUser(self, path): | 30 def ExpandUser(self, path): |
| 30 return '$HOME/%s' % path | 31 return '$HOME/%s' % path |
| 31 | 32 |
| 32 def Exists(self, path): | 33 def Exists(self, path): |
| 33 return self.files.get(path) is not None | 34 return self.files.get(path) is not None |
| 34 | 35 |
| 35 def MaybeMakeDirectory(self, path): | 36 def MaybeMakeDirectory(self, path): |
| 36 pass | 37 self.files[path] = True |
| 37 | 38 |
| 38 def ReadFile(self, path): | 39 def ReadFile(self, path): |
| 39 return self.files[path] | 40 return self.files[path] |
| 40 | 41 |
| 41 def WriteFile(self, path, contents): | 42 def WriteFile(self, path, contents): |
| 42 self.files[path] = contents | 43 self.files[path] = contents |
| 43 | 44 |
| 44 def Call(self, cmd, env=None): | 45 def Call(self, cmd, env=None): |
| 45 if env: | 46 if env: |
| 46 self.cross_compile = env.get('GYP_CROSSCOMPILE') | 47 self.cross_compile = env.get('GYP_CROSSCOMPILE') |
| (...skipping 10 matching lines...) Expand all Loading... |
| 57 self.err += sep.join(args) + end | 58 self.err += sep.join(args) + end |
| 58 else: | 59 else: |
| 59 self.out += sep.join(args) + end | 60 self.out += sep.join(args) + end |
| 60 | 61 |
| 61 def TempFile(self, mode='w'): | 62 def TempFile(self, mode='w'): |
| 62 return FakeFile(self.files) | 63 return FakeFile(self.files) |
| 63 | 64 |
| 64 def RemoveFile(self, path): | 65 def RemoveFile(self, path): |
| 65 del self.files[path] | 66 del self.files[path] |
| 66 | 67 |
| 68 def RemoveDirectory(self, path): |
| 69 self.rmdirs.append(path) |
| 70 files_to_delete = [f for f in self.files if f.startswith(path)] |
| 71 for f in files_to_delete: |
| 72 self.files[f] = None |
| 73 |
| 67 | 74 |
| 68 class FakeFile(object): | 75 class FakeFile(object): |
| 69 def __init__(self, files): | 76 def __init__(self, files): |
| 70 self.name = '/tmp/file' | 77 self.name = '/tmp/file' |
| 71 self.buf = '' | 78 self.buf = '' |
| 72 self.files = files | 79 self.files = files |
| 73 | 80 |
| 74 def write(self, contents): | 81 def write(self, contents): |
| 75 self.buf += contents | 82 self.buf += contents |
| 76 | 83 |
| 77 def close(self): | 84 def close(self): |
| 78 self.files[self.name] = self.buf | 85 self.files[self.name] = self.buf |
| 79 | 86 |
| 80 | 87 |
| 81 TEST_CONFIG = """\ | 88 TEST_CONFIG = """\ |
| 82 { | 89 { |
| 83 'common_dev_configs': ['gn_debug'], | 90 'common_dev_configs': ['gn_debug'], |
| 84 'configs': { | 91 'configs': { |
| 85 'gyp_rel_bot': ['gyp', 'rel', 'goma'], | 92 'gyp_rel_bot': ['gyp', 'rel', 'goma'], |
| 86 'gn_debug': ['gn', 'debug'], | 93 'gn_debug': ['gn', 'debug'], |
| 94 'gyp_debug': ['gyp', 'debug'], |
| 87 'gn_rel_bot': ['gn', 'rel', 'goma'], | 95 'gn_rel_bot': ['gn', 'rel', 'goma'], |
| 88 'private': ['gyp', 'rel', 'fake_feature1'], | 96 'private': ['gyp', 'rel', 'fake_feature1'], |
| 89 'unsupported': ['gn', 'fake_feature2'], | 97 'unsupported': ['gn', 'fake_feature2'], |
| 90 }, | 98 }, |
| 91 'masters': { | 99 'masters': { |
| 92 'fake_master': { | 100 'fake_master': { |
| 93 'fake_builder': 'gyp_rel_bot', | 101 'fake_builder': 'gyp_rel_bot', |
| 94 'fake_gn_builder': 'gn_rel_bot', | 102 'fake_gn_builder': 'gn_rel_bot', |
| 103 'fake_gyp_builder': 'gyp_debug', |
| 95 }, | 104 }, |
| 96 }, | 105 }, |
| 97 'mixins': { | 106 'mixins': { |
| 98 'fake_feature1': { | 107 'fake_feature1': { |
| 99 'gn_args': 'enable_doom_melon=true', | 108 'gn_args': 'enable_doom_melon=true', |
| 100 'gyp_crosscompile': True, | 109 'gyp_crosscompile': True, |
| 101 'gyp_defines': 'doom_melon=1', | 110 'gyp_defines': 'doom_melon=1', |
| 102 }, | 111 }, |
| 103 'fake_feature2': { | 112 'fake_feature2': { |
| 104 'gn_args': 'enable_doom_melon=false', | 113 'gn_args': 'enable_doom_melon=false', |
| 105 'gyp_defaults': 'doom_melon=0', | 114 'gyp_defaults': 'doom_melon=0', |
| 106 }, | 115 }, |
| 107 'gyp': {'type': 'gyp'}, | 116 'gyp': {'type': 'gyp'}, |
| 108 'gn': {'type': 'gn'}, | 117 'gn': {'type': 'gn'}, |
| 109 'goma': { | 118 'goma': { |
| 110 'gn_args': 'use_goma=true goma_dir="$(goma_dir)"', | 119 'gn_args': 'use_goma=true goma_dir="$(goma_dir)"', |
| 111 'gyp_defines': 'goma=1 gomadir="$(goma_dir)"', | 120 'gyp_defines': 'goma=1 gomadir="$(goma_dir)"', |
| 112 }, | 121 }, |
| 113 'rel': { | 122 'rel': { |
| 114 'gn_args': 'is_debug=false', | 123 'gn_args': 'is_debug=false', |
| 115 'gyp_config': 'Release', | 124 'gyp_config': 'Release', |
| 116 }, | 125 }, |
| 117 'debug': { | 126 'debug': { |
| 118 'gn_args': 'is_debug=true', | 127 'gn_args': 'is_debug=true', |
| 128 'gyp_config': 'Debug', |
| 119 }, | 129 }, |
| 120 }, | 130 }, |
| 121 'private_configs': ['private'], | 131 'private_configs': ['private'], |
| 122 'unsupported_configs': ['unsupported'], | 132 'unsupported_configs': ['unsupported'], |
| 123 } | 133 } |
| 124 """ | 134 """ |
| 125 | 135 |
| 126 | 136 |
| 127 class UnitTest(unittest.TestCase): | 137 class UnitTest(unittest.TestCase): |
| 128 def fake_mbw(self, files=None): | 138 def fake_mbw(self, files=None): |
| (...skipping 10 matching lines...) Expand all Loading... |
| 139 mbw.ParseArgs(args) | 149 mbw.ParseArgs(args) |
| 140 actual_ret = mbw.args.func() | 150 actual_ret = mbw.args.func() |
| 141 if ret is not None: | 151 if ret is not None: |
| 142 self.assertEqual(actual_ret, ret) | 152 self.assertEqual(actual_ret, ret) |
| 143 if out is not None: | 153 if out is not None: |
| 144 self.assertEqual(mbw.out, out) | 154 self.assertEqual(mbw.out, out) |
| 145 if err is not None: | 155 if err is not None: |
| 146 self.assertEqual(mbw.err, err) | 156 self.assertEqual(mbw.err, err) |
| 147 return mbw | 157 return mbw |
| 148 | 158 |
| 159 def test_clobber(self): |
| 160 files = { |
| 161 '/fake_src/out/Debug': None, |
| 162 '/fake_src/out/Debug/mb_type': None, |
| 163 } |
| 164 mbw = self.fake_mbw(files) |
| 165 |
| 166 # The first time we run this, the build dir doesn't exist, so no clobber. |
| 167 self.check(['gen', '-c', 'gn_debug', '//out/Debug'], mbw=mbw, ret=0) |
| 168 self.assertEqual(mbw.rmdirs, []) |
| 169 self.assertTrue(mbw.files['/fake_src/out/Debug/mb_type'], 'gn') |
| 170 |
| 171 # The second time we run this, the build dir exists and matches, so no |
| 172 # clobber. |
| 173 self.check(['gen', '-c', 'gn_debug', '//out/Debug'], mbw=mbw, ret=0) |
| 174 self.assertEqual(mbw.rmdirs, []) |
| 175 self.assertEqual(mbw.files['/fake_src/out/Debug/mb_type'], 'gn') |
| 176 |
| 177 # Now we switch build types; this should result in a clobber. |
| 178 self.check(['gen', '-c', 'gyp_debug', '//out/Debug'], mbw=mbw, ret=0) |
| 179 self.assertEqual(mbw.rmdirs, ['/fake_src/out/Debug']) |
| 180 self.assertEqual(mbw.files['/fake_src/out/Debug/mb_type'], 'gyp') |
| 181 |
| 182 # Now we delete mb_type; this checks the case where the build dir |
| 183 # exists but wasn't populated by mb; this should also result in a clobber. |
| 184 del mbw.files['/fake_src/out/Debug/mb_type'] |
| 185 self.check(['gen', '-c', 'gyp_debug', '//out/Debug'], mbw=mbw, ret=0) |
| 186 self.assertEqual(mbw.rmdirs, |
| 187 ['/fake_src/out/Debug', '/fake_src/out/Debug']) |
| 188 self.assertEqual(mbw.files['/fake_src/out/Debug/mb_type'], 'gyp') |
| 189 |
| 149 def test_gn_analyze(self): | 190 def test_gn_analyze(self): |
| 150 files = {'/tmp/in.json': """{\ | 191 files = {'/tmp/in.json': """{\ |
| 151 "files": ["foo/foo_unittest.cc"], | 192 "files": ["foo/foo_unittest.cc"], |
| 152 "targets": ["foo_unittests", "bar_unittests"] | 193 "targets": ["foo_unittests", "bar_unittests"] |
| 153 }"""} | 194 }"""} |
| 154 | 195 |
| 155 mbw = self.fake_mbw(files) | 196 mbw = self.fake_mbw(files) |
| 156 mbw.Call = lambda cmd, env=None: (0, 'out/Default/foo_unittests\n', '') | 197 mbw.Call = lambda cmd, env=None: (0, 'out/Default/foo_unittests\n', '') |
| 157 | 198 |
| 158 self.check(['analyze', '-c', 'gn_debug', '//out/Default', | 199 self.check(['analyze', '-c', 'gn_debug', '//out/Default', |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 275 finally: | 316 finally: |
| 276 sys.stdout = orig_stdout | 317 sys.stdout = orig_stdout |
| 277 | 318 |
| 278 | 319 |
| 279 def test_validate(self): | 320 def test_validate(self): |
| 280 self.check(['validate'], ret=0) | 321 self.check(['validate'], ret=0) |
| 281 | 322 |
| 282 | 323 |
| 283 if __name__ == '__main__': | 324 if __name__ == '__main__': |
| 284 unittest.main() | 325 unittest.main() |
| OLD | NEW |