OLD | NEW |
1 #!/usr/bin/python | 1 #!/usr/bin/python |
2 | 2 |
3 # Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 3 # Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
4 # for details. All rights reserved. Use of this source code is governed by a | 4 # for details. All rights reserved. Use of this source code is governed by a |
5 # BSD-style license that can be found in the LICENSE file. | 5 # BSD-style license that can be found in the LICENSE file. |
6 | 6 |
7 import imp | 7 import imp |
8 import os | 8 import os |
9 import re | 9 import re |
10 import shutil | 10 import shutil |
| 11 import shlex |
11 import subprocess | 12 import subprocess |
12 import sys | 13 import sys |
13 import tempfile | 14 import tempfile |
14 import zipfile | 15 import zipfile |
15 | 16 |
16 import config_parser | 17 import config_parser |
17 | 18 |
18 # We expect the tools directory from the dart repo to be checked out into: | 19 # We expect the tools directory from the dart repo to be checked out into: |
19 # ../../tools | 20 # ../../tools |
20 DART_DIR = os.path.abspath( | 21 DART_DIR = os.path.abspath( |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
74 builder_pattern.group(4), | 75 builder_pattern.group(4), |
75 is_repo, | 76 is_repo, |
76 is_sample) | 77 is_sample) |
77 | 78 |
78 class BuildStep(object): | 79 class BuildStep(object): |
79 """ | 80 """ |
80 A context manager for handling build steps. | 81 A context manager for handling build steps. |
81 | 82 |
82 When the context manager is entered, it prints the "@@@BUILD_STEP __@@@" | 83 When the context manager is entered, it prints the "@@@BUILD_STEP __@@@" |
83 message. If it exits from an error being raised it displays the | 84 message. If it exits from an error being raised it displays the |
84 "@@@STEP_FAILURE@@@" message. | 85 "@@@STEP_FAILURE __@@@" message. |
85 | 86 |
86 If swallow_error is True, then this will catch and discard any OSError that | 87 If swallow_error is True, then this will catch and discard any OSError that |
87 is thrown. This lets you run later BuildSteps if the current one fails. | 88 is thrown. This lets you run later BuildSteps if the current one fails. |
88 """ | 89 """ |
89 def __init__(self, name, swallow_error=False): | 90 def __init__(self, name, swallow_error=False): |
90 self.name = name | 91 self.name = name |
91 self.swallow_error = swallow_error | 92 self.swallow_error = swallow_error |
92 | 93 |
93 def __enter__(self): | 94 def __enter__(self): |
94 print '@@@BUILD_STEP %s@@@' % self.name | 95 print '@@@BUILD_STEP %s@@@' % self.name |
95 sys.stdout.flush() | 96 sys.stdout.flush() |
96 | 97 |
97 def __exit__(self, type, value, traceback): | 98 def __exit__(self, type, value, traceback): |
98 if value: | 99 if value: |
99 print '@@@STEP_FAILURE@@@' | 100 print '@@@STEP_FAILURE %s@@@' % self.name |
100 sys.stdout.flush() | 101 sys.stdout.flush() |
101 if self.swallow_error and isinstance(value, OSError): | 102 if self.swallow_error and isinstance(value, OSError): |
102 return True | 103 return True |
103 | 104 |
104 class TempDir(object): | 105 class TempDir(object): |
105 def __init__(self, prefix=''): | 106 def __init__(self, prefix=''): |
106 self._temp_dir = None | 107 self._temp_dir = None |
107 self._prefix = prefix | 108 self._prefix = prefix |
108 | 109 |
109 def __enter__(self): | 110 def __enter__(self): |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
151 args = [sys.executable, 'tools/build.py', | 152 args = [sys.executable, 'tools/build.py', |
152 '-mrelease,debug', '--arch=ia32', | 153 '-mrelease,debug', '--arch=ia32', |
153 'create_sdk'] | 154 'create_sdk'] |
154 RunProcess(args) | 155 RunProcess(args) |
155 | 156 |
156 def GetSDK(bot_info): | 157 def GetSDK(bot_info): |
157 with BuildStep('Get sdk'): | 158 with BuildStep('Get sdk'): |
158 namer = bot_utils.GCSNamer(channel=bot_utils.Channel.DEV) | 159 namer = bot_utils.GCSNamer(channel=bot_utils.Channel.DEV) |
159 # TODO(ricow): Be smarter here, only download if new. | 160 # TODO(ricow): Be smarter here, only download if new. |
160 build_root = GetBuildRoot(bot_info) | 161 build_root = GetBuildRoot(bot_info) |
161 SafeDelete(os.path.join(build_root, 'dart-sdk')) | 162 SafeDelete(os.path.join(build_root, 'dart-sdk'), bot_info) |
162 if not os.path.exists(build_root): | 163 if not os.path.exists(build_root): |
163 os.makedirs(build_root) | 164 os.makedirs(build_root) |
164 local_zip = os.path.join(build_root, 'sdk.zip') | 165 local_zip = os.path.join(build_root, 'sdk.zip') |
165 gsutils = bot_utils.GSUtil() | 166 gsutils = bot_utils.GSUtil() |
166 gsutils.execute(['cp', | 167 gsutils.execute(['cp', |
167 namer.sdk_zipfilepath('latest', bot_info.system, | 168 namer.sdk_zipfilepath('latest', bot_info.system, |
168 'ia32', 'release'), | 169 'ia32', 'release'), |
169 local_zip]) | 170 local_zip]) |
170 if bot_info.system == 'windows': | 171 if bot_info.system == 'windows': |
171 with zipfile.ZipFile(local_zip, 'r') as zip_file: | 172 with zipfile.ZipFile(local_zip, 'r') as zip_file: |
172 zip_file.extractall(path=build_root) | 173 zip_file.extractall(path=build_root) |
173 else: | 174 else: |
174 # We don't keep the execution bit if we use python's zipfile on possix. | 175 # We don't keep the execution bit if we use python's zipfile on possix. |
175 RunProcess(['unzip', local_zip, '-d', build_root]) | 176 RunProcess(['unzip', local_zip, '-d', build_root]) |
176 | 177 |
177 def GetPackagePath(bot_info): | 178 def GetPackagePath(bot_info): |
178 if bot_info.is_repo: | 179 if bot_info.is_repo: |
179 return os.path.join('pkg', bot_info.package_name) | 180 return os.path.join('pkg', bot_info.package_name) |
180 return os.path.join('third_party', 'pkg', bot_info.package_name) | 181 return os.path.join('third_party', 'pkg', bot_info.package_name) |
181 | 182 |
182 def GetBuildRoot(bot_info): | 183 def GetBuildRoot(bot_info): |
183 system = bot_info.system | 184 system = bot_info.system |
184 if system == 'windows': | 185 if system == 'windows': |
185 system = 'win32' | 186 system = 'win32' |
186 if system == 'mac': | 187 if system == 'mac': |
187 system = 'macos' | 188 system = 'macos' |
188 return utils.GetBuildRoot(system, mode='release', arch='ia32', | 189 return utils.GetBuildRoot(system, mode='release', arch='ia32', |
189 target_os=system) | 190 target_os=system) |
190 | 191 |
191 def SafeDelete(path): | 192 def SafeDelete(path, bot_info): |
192 if bot_info.system == 'windows': | 193 if bot_info.system == 'windows': |
193 if os.path.exists(path): | 194 if os.path.exists(path): |
194 args = ['cmd.exe', '/c', 'rmdir', '/q', '/s', path] | 195 args = ['cmd.exe', '/c', 'rmdir', '/q', '/s', path] |
195 RunProcess(args) | 196 RunProcess(args) |
196 else: | 197 else: |
197 shutil.rmtree(path, ignore_errors=True) | 198 shutil.rmtree(path, ignore_errors=True) |
198 | 199 |
199 | 200 |
200 def GetPackageCopy(bot_info): | 201 def GetPackageCopy(bot_info): |
201 build_root = GetBuildRoot(bot_info) | 202 build_root = GetBuildRoot(bot_info) |
202 package_copy = os.path.join(build_root, 'package_copy') | 203 package_copy = os.path.join(build_root, 'package_copy') |
203 package_path = GetPackagePath(bot_info) | 204 package_path = GetPackagePath(bot_info) |
204 copy_path = os.path.join(package_copy, bot_info.package_name) | 205 copy_path = os.path.join(package_copy, bot_info.package_name) |
205 SafeDelete(package_copy) | 206 SafeDelete(package_copy, bot_info) |
206 no_git = shutil.ignore_patterns('.git') | 207 no_git = shutil.ignore_patterns('.git') |
207 shutil.copytree(package_path, copy_path, symlinks=False, ignore=no_git) | 208 shutil.copytree(package_path, copy_path, symlinks=False, ignore=no_git) |
208 return copy_path | 209 return copy_path |
209 | 210 |
210 def GetSdkBin(): | 211 def GetSdkBin(bot_info): |
211 return os.path.join(os.getcwd(), GetBuildRoot(bot_info), | 212 return os.path.join(os.getcwd(), GetBuildRoot(bot_info), |
212 'dart-sdk', 'bin') | 213 'dart-sdk', 'bin') |
213 | 214 |
214 def GetVM(): | 215 def GetVM(bot_info): |
215 executable = 'dart.exe' if bot_info.system == 'windows' else 'dart' | 216 executable = 'dart.exe' if bot_info.system == 'windows' else 'dart' |
216 return os.path.join(GetSdkBin(), executable) | 217 return os.path.join(DART_DIR, |
| 218 'tools/testing/bin', |
| 219 bot_info.system, |
| 220 executable) |
217 | 221 |
218 def GetPub(bot_info): | 222 def GetPub(bot_info): |
219 executable = 'pub.bat' if bot_info.system == 'windows' else 'pub' | 223 executable = 'pub.bat' if bot_info.system == 'windows' else 'pub' |
220 return os.path.join(GetSdkBin(), executable) | 224 return os.path.join(GetSdkBin(bot_info), executable) |
221 | 225 |
222 def GetPubEnv(bot_info): | 226 def GetPubEnv(bot_info): |
223 return {'PUB_CACHE' : os.path.join(os.getcwd(), | 227 return {'PUB_CACHE' : os.path.join(os.getcwd(), |
224 GetBuildRoot(bot_info), 'pub_cache') } | 228 GetBuildRoot(bot_info), 'pub_cache') } |
225 | 229 |
226 # _RunPubCacheRepair and _CheckPubCacheCorruption are not used right now, but we | 230 # _RunPubCacheRepair and _CheckPubCacheCorruption are not used right now, but we |
227 # keep them around because they provide an easy way to diagnose and fix issues | 231 # keep them around because they provide an easy way to diagnose and fix issues |
228 # in the bots. | 232 # in the bots. |
229 def _RunPubCacheRepair(bot_info, path): | 233 def _RunPubCacheRepair(bot_info, path): |
230 pub = GetPub(bot_info) | 234 pub = GetPub(bot_info) |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
333 system = bot_info.system | 337 system = bot_info.system |
334 xvfb_command = ['xvfb-run', '-a', '--server-args=-screen 0 1024x768x24'] | 338 xvfb_command = ['xvfb-run', '-a', '--server-args=-screen 0 1024x768x24'] |
335 xvfb_args = xvfb_command if system == 'linux' else [] | 339 xvfb_args = xvfb_command if system == 'linux' else [] |
336 suffix = ' under build' if folder == 'build/test' else '' | 340 suffix = ' under build' if folder == 'build/test' else '' |
337 with BuildStep('Test vm release mode%s' % suffix, swallow_error=True): | 341 with BuildStep('Test vm release mode%s' % suffix, swallow_error=True): |
338 args = [sys.executable, 'tools/test.py', | 342 args = [sys.executable, 'tools/test.py', |
339 '-mrelease', '-rvm', '-cnone'] + standard_args | 343 '-mrelease', '-rvm', '-cnone'] + standard_args |
340 args.extend(LogsArgument()) | 344 args.extend(LogsArgument()) |
341 # For easy integration testing we give access to the sdk bin directory. | 345 # For easy integration testing we give access to the sdk bin directory. |
342 # This only makes sense on vm testing. | 346 # This only makes sense on vm testing. |
343 extra_env = { 'DART_SDK_BIN' : GetSdkBin() } | 347 extra_env = { 'DART_SDK_BIN' : GetSdkBin(bot_info) } |
344 RunProcess(args, extra_env=extra_env) | 348 RunProcess(args, extra_env=extra_env) |
345 with BuildStep('Test analyzer%s' % suffix, swallow_error=True): | 349 with BuildStep('Test analyzer%s' % suffix, swallow_error=True): |
346 args = [sys.executable, 'tools/test.py', | 350 args = [sys.executable, 'tools/test.py', |
347 '-mrelease', '-rnone', '-cdart2analyzer'] + standard_args | 351 '-mrelease', '-rnone', '-cdart2analyzer'] + standard_args |
348 args.extend(LogsArgument()) | 352 args.extend(LogsArgument()) |
349 RunProcess(args) | 353 RunProcess(args) |
350 if bot_info.system != 'windows': | 354 if bot_info.system != 'windows': |
351 with BuildStep('Test dartium%s' % suffix, swallow_error=True): | 355 with BuildStep('Test dartium%s' % suffix, swallow_error=True): |
352 test_args = [sys.executable, 'tools/test.py', | 356 test_args = [sys.executable, 'tools/test.py', |
353 '-mrelease', '-rdartium', '-cnone', '-j4'] | 357 '-mrelease', '-rdartium', '-cnone', '-j4'] |
354 args = xvfb_args + test_args + standard_args | 358 args = xvfb_args + test_args + standard_args |
355 args.extend(LogsArgument()) | 359 args.extend(LogsArgument()) |
356 RunProcess(args) | 360 RunProcess(args) |
357 | 361 |
358 for runtime in JS_RUNTIMES[system]: | 362 for runtime in JS_RUNTIMES[system]: |
359 with BuildStep('dart2js-%s%s' % (runtime, suffix), swallow_error=True): | 363 with BuildStep('dart2js-%s%s' % (runtime, suffix), swallow_error=True): |
360 test_args = [sys.executable, 'tools/test.py', | 364 test_args = [sys.executable, 'tools/test.py', |
361 '-mrelease', '-r%s' % runtime, '-cdart2js', '-j4', | 365 '-mrelease', '-r%s' % runtime, '-cdart2js', '-j4', |
362 '--dart2js-batch'] | 366 '--dart2js-batch'] |
363 args = xvfb_args + test_args + standard_args | 367 args = xvfb_args + test_args + standard_args |
364 args.extend(LogsArgument()) | 368 args.extend(LogsArgument()) |
365 RunProcess(args) | 369 RunProcess(args) |
366 | 370 |
| 371 def FillMagicMarkers(v, replacements): |
| 372 def replace(match): |
| 373 word = match.group(1) |
| 374 if not word in replacements: |
| 375 raise Exception("Unknown magic marker %s. Known mappings are: %s" % |
| 376 (word, replacements)) |
| 377 return replacements[word] |
| 378 return re.sub(r"\$(\w+)", replace, v) |
367 | 379 |
368 def RunHooks(hooks, section_name): | 380 # Runs the script given by test_config.get_config if it exists, does nothing |
| 381 # otherwise. |
| 382 # Returns `True` if the script was run. |
| 383 def RunCustomScript(test_config): |
| 384 custom_script = test_config.get_custom_script() |
| 385 if custom_script: |
| 386 command_string = FillMagicMarkers(custom_script, test_config.replacements) |
| 387 with BuildStep('Running custom script %s' % command_string, |
| 388 swallow_error=True): |
| 389 args = shlex.split(command_string, posix=True) |
| 390 sys.stdout.flush() |
| 391 exit_code = subprocess.call(args) |
| 392 if exit_code != 0: |
| 393 print "Custom script failed" |
| 394 return True |
| 395 else: |
| 396 return False |
| 397 |
| 398 |
| 399 def RunHooks(hooks, section_name, replacements): |
369 for name, command in hooks.iteritems(): | 400 for name, command in hooks.iteritems(): |
| 401 command = FillMagicMarkers(command, replacements) |
370 with BuildStep('%s: %s' % (section_name, name), swallow_error=True): | 402 with BuildStep('%s: %s' % (section_name, name), swallow_error=True): |
371 RunProcess(command, shell=True) | 403 RunProcess(command, shell=True) |
372 | 404 |
373 def RunPrePubUpgradeHooks(test_config): | 405 def RunPrePubUpgradeHooks(test_config): |
374 RunHooks(test_config.get_pre_pub_upgrade_hooks(), "Pre pub upgrade hooks") | 406 RunHooks(test_config.get_pre_pub_upgrade_hooks(), "Pre pub upgrade hooks", |
| 407 test_config.replacements) |
375 | 408 |
376 def RunPrePubBuildHooks(test_config): | 409 def RunPrePubBuildHooks(test_config): |
377 RunHooks(test_config.get_pre_pub_build_hooks(), "Pre pub build hooks") | 410 RunHooks(test_config.get_pre_pub_build_hooks(), "Pre pub build hooks", |
| 411 test_config.replacements) |
378 | 412 |
379 def RunPostPubBuildHooks(test_config): | 413 def RunPostPubBuildHooks(test_config): |
380 RunHooks(test_config.get_post_pub_build_hooks(), "Pre pub build hooks") | 414 RunHooks(test_config.get_post_pub_build_hooks(), "Pre pub build hooks", |
| 415 test_config.replacements) |
381 | 416 |
382 def RunPreTestHooks(test_config): | 417 def RunPreTestHooks(test_config): |
383 RunHooks(test_config.get_pre_test_hooks(), "Pre test hooks") | 418 RunHooks(test_config.get_pre_test_hooks(), "Pre test hooks", |
| 419 test_config.replacements) |
384 | 420 |
385 def RunPostTestHooks(test_config): | 421 def RunPostTestHooks(test_config): |
386 RunHooks(test_config.get_post_test_hooks(), "Post test hooks") | 422 RunHooks(test_config.get_post_test_hooks(), "Post test hooks", |
| 423 test_config.replacements) |
387 | 424 |
388 if __name__ == '__main__': | 425 def main(): |
389 bot_info = GetBotInfo() | 426 bot_info = GetBotInfo() |
| 427 |
390 print 'Bot info: %s' % bot_info | 428 print 'Bot info: %s' % bot_info |
391 copy_path = GetPackageCopy(bot_info) | 429 copy_path = GetPackageCopy(bot_info) |
392 config_file = os.path.join(copy_path, '.test_config') | 430 config_file = os.path.join(copy_path, '.test_config') |
393 test_config = config_parser.ConfigParser(config_file, | 431 test_config = config_parser.ConfigParser(config_file) |
394 GetVM(), | 432 test_config.replacements = { |
395 copy_path) | 433 'dart': GetVM(bot_info), |
396 GetSDK(bot_info) | 434 'project_root': copy_path, |
397 print 'Running testing in copy of package in %s' % copy_path | 435 'python': sys.executable |
398 RunPrePubUpgradeHooks(test_config) | 436 } |
399 RunPubUpgrade(bot_info, copy_path) | |
400 | 437 |
401 RunPrePubBuildHooks(test_config) | 438 if not RunCustomScript(test_config): |
402 RunPubBuild(bot_info, copy_path, 'web') | 439 print "No custom script found, running default steps." |
403 RunPubBuild(bot_info, copy_path, 'test', 'debug') | |
404 RunPostPubBuildHooks(test_config) | |
405 FixupTestControllerJS(copy_path) | |
406 | 440 |
407 RunPreTestHooks(test_config) | 441 GetSDK(bot_info) |
408 RunPackageTesting(bot_info, copy_path, 'test') | 442 print 'Running testing in copy of package in %s' % copy_path |
409 RunPackageTesting(bot_info, copy_path, 'build/test') | 443 RunPrePubUpgradeHooks(test_config) |
410 RunPostTestHooks(test_config) | 444 RunPubUpgrade(bot_info, copy_path) |
| 445 |
| 446 RunPrePubBuildHooks(test_config) |
| 447 RunPubBuild(bot_info, copy_path, 'web') |
| 448 RunPubBuild(bot_info, copy_path, 'test', 'debug') |
| 449 RunPostPubBuildHooks(test_config) |
| 450 FixupTestControllerJS(copy_path) |
| 451 |
| 452 RunPreTestHooks(test_config) |
| 453 RunPackageTesting(bot_info, copy_path, 'test') |
| 454 RunPackageTesting(bot_info, copy_path, 'build/test') |
| 455 RunPostTestHooks(test_config) |
| 456 |
| 457 if __name__ == '__main__': |
| 458 main() |
OLD | NEW |