OLD | NEW |
1 #!/usr/bin/python | 1 #!/usr/bin/python |
2 | 2 |
3 # Copyright (c) 2011 The Chromium Authors. All rights reserved. | 3 # Copyright (c) 2011 The Chromium Authors. All rights reserved. |
4 # Use of this source code is governed by a BSD-style license that can be | 4 # Use of this source code is governed by a BSD-style license that can be |
5 # found in the LICENSE file. | 5 # found in the LICENSE file. |
6 | 6 |
7 """Dart2js buildbot steps | 7 """ |
| 8 Dart2js buildbot steps |
8 | 9 |
9 Runs tests for the dart2js compiler. | 10 Runs tests for the dart2js compiler. |
10 """ | 11 """ |
11 | 12 |
12 import platform | 13 import platform |
13 import optparse | |
14 import os | 14 import os |
15 import re | 15 import re |
16 import shutil | 16 import shutil |
17 import subprocess | 17 import subprocess |
18 import sys | 18 import sys |
19 | 19 |
20 BUILDER_NAME = 'BUILDBOT_BUILDERNAME' | 20 import bot |
21 BUILDER_CLOBBER = 'BUILDBOT_CLOBBER' | |
22 | |
23 | |
24 DART_PATH = os.path.dirname( | |
25 os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) | |
26 | 21 |
27 DART2JS_BUILDER = ( | 22 DART2JS_BUILDER = ( |
28 r'dart2js-(linux|mac|windows)(-(jsshell))?-(debug|release)(-(checked|host-ch
ecked))?(-(host-checked))?-?(\d*)-?(\d*)') | 23 r'dart2js-(linux|mac|windows)(-(jsshell))?-(debug|release)(-(checked|host-ch
ecked))?(-(host-checked))?-?(\d*)-?(\d*)') |
29 WEB_BUILDER = ( | 24 WEB_BUILDER = ( |
30 r'dart2js-(ie9|ie10|ff|safari|chrome|opera)-(win7|win8|mac|linux)(-(all|html
))?') | 25 r'dart2js-(ie9|ie10|ff|safari|chrome|opera)-(win7|win8|mac|linux)(-(all|html
))?') |
31 | 26 |
32 NO_COLOR_ENV = dict(os.environ) | |
33 NO_COLOR_ENV['TERM'] = 'nocolor' | |
34 | 27 |
35 class BuildInfo(object): | 28 def GetBuildInfo(builder_name, is_buildbot): |
36 """ Encapsulation of build information. | |
37 - compiler: 'dart2js' or None when the builder has an incorrect name | |
38 - runtime: 'd8', 'ie', 'ff', 'safari', 'chrome', 'opera' | |
39 - mode: 'debug' or 'release' | |
40 - system: 'linux', 'mac', or 'win7' | |
41 - checked: True if we should run in checked mode, otherwise False | |
42 - host_checked: True if we should run in host checked mode, otherwise False | |
43 - shard_index: The shard we are running, None when not specified. | |
44 - total_shards: The total number of shards, None when not specified. | |
45 - is_buildbot: True if we are on a buildbot (or emulating it). | |
46 - test_set: Specification of a non standard test set, default None | |
47 """ | |
48 def __init__(self, compiler, runtime, mode, system, checked=False, | |
49 host_checked=False, shard_index=None, total_shards=None, | |
50 is_buildbot=False, test_set=None): | |
51 self.compiler = compiler | |
52 self.runtime = runtime | |
53 self.mode = mode | |
54 self.system = system | |
55 self.checked = checked | |
56 self.host_checked = host_checked | |
57 self.shard_index = shard_index | |
58 self.total_shards = total_shards | |
59 self.is_buildbot = is_buildbot | |
60 self.test_set = test_set | |
61 | |
62 def PrintBuildInfo(self): | |
63 shard_description = "" | |
64 if self.shard_index: | |
65 shard_description = " shard %s of %s" % (self.shard_index, | |
66 self.total_shards) | |
67 print ("compiler: %s, runtime: %s mode: %s, system: %s," | |
68 " checked: %s, host-checked: %s, test-set: %s%s" | |
69 ) % (self.compiler, self.runtime, self.mode, self.system, | |
70 self.checked, self.host_checked, self.test_set, | |
71 shard_description) | |
72 | |
73 | |
74 def GetBuildInfo(): | |
75 """Returns a BuildInfo object for the current buildbot based on the | 29 """Returns a BuildInfo object for the current buildbot based on the |
76 name of the builder. | 30 name of the builder. |
77 """ | 31 """ |
78 parser = optparse.OptionParser() | |
79 parser.add_option('-n', '--name', dest='name', help='The name of the build' | |
80 'bot you would like to emulate (ex: web-chrome-win7)', default=None) | |
81 args, _ = parser.parse_args() | |
82 | |
83 compiler = None | 32 compiler = None |
84 runtime = None | 33 runtime = None |
85 mode = None | 34 mode = None |
86 system = None | 35 system = None |
87 builder_name = os.environ.get(BUILDER_NAME) | |
88 checked = False | 36 checked = False |
89 host_checked = False | 37 host_checked = False |
90 shard_index = None | 38 shard_index = None |
91 total_shards = None | 39 total_shards = None |
92 is_buildbot = True | |
93 test_set = None | 40 test_set = None |
94 | 41 |
95 if not builder_name: | 42 dart2js_pattern = re.match(DART2JS_BUILDER, builder_name) |
96 # We are not running on a buildbot. | 43 web_pattern = re.match(WEB_BUILDER, builder_name) |
97 is_buildbot = False | |
98 if args.name: | |
99 builder_name = args.name | |
100 else: | |
101 print 'Use -n $BUILDBOT_NAME for the bot you would like to emulate.' | |
102 sys.exit(1) | |
103 | 44 |
104 if builder_name: | 45 if web_pattern: |
105 dart2js_pattern = re.match(DART2JS_BUILDER, builder_name) | 46 compiler = 'dart2js' |
106 web_pattern = re.match(WEB_BUILDER, builder_name) | 47 runtime = web_pattern.group(1) |
107 | 48 system = web_pattern.group(2) |
108 if web_pattern: | 49 mode = 'release' |
109 compiler = 'dart2js' | 50 test_set = web_pattern.group(4) |
110 runtime = web_pattern.group(1) | 51 elif dart2js_pattern: |
111 system = web_pattern.group(2) | 52 compiler = 'dart2js' |
112 mode = 'release' | 53 system = dart2js_pattern.group(1) |
113 test_set = web_pattern.group(4) | 54 runtime = 'd8' |
114 elif dart2js_pattern: | 55 if dart2js_pattern.group(3) == 'jsshell': |
115 compiler = 'dart2js' | 56 runtime = 'jsshell' |
116 system = dart2js_pattern.group(1) | 57 mode = dart2js_pattern.group(4) |
117 runtime = 'd8' | 58 # The valid naming parts for checked and host-checked are: |
118 if dart2js_pattern.group(3) == 'jsshell': | 59 # Empty: checked=False, host_checked=False |
119 runtime = 'jsshell' | 60 # -checked: checked=True, host_checked=False |
120 mode = dart2js_pattern.group(4) | 61 # -host-checked: checked=False, host_checked=True |
121 # The valid naming parts for checked and host-checked are: | 62 # -checked-host-checked: checked=True, host_checked=True |
122 # Empty: checked=False, host_checked=False | 63 if dart2js_pattern.group(6) == 'checked': |
123 # -checked: checked=True, host_checked=False | 64 checked = True |
124 # -host-checked: checked=False, host_checked=True | 65 if dart2js_pattern.group(6) == 'host-checked': |
125 # -checked-host-checked: checked=True, host_checked=True | 66 host_checked = True |
126 if dart2js_pattern.group(6) == 'checked': | 67 if dart2js_pattern.group(8) == 'host-checked': |
127 checked = True | 68 host_checked = True |
128 if dart2js_pattern.group(6) == 'host-checked': | 69 shard_index = dart2js_pattern.group(9) |
129 host_checked = True | 70 total_shards = dart2js_pattern.group(10) |
130 if dart2js_pattern.group(8) == 'host-checked': | 71 else : |
131 host_checked = True | 72 return None |
132 shard_index = dart2js_pattern.group(9) | |
133 total_shards = dart2js_pattern.group(10) | |
134 | 73 |
135 if system == 'windows': | 74 if system == 'windows': |
136 system = 'win7' | 75 system = 'win7' |
137 | 76 |
138 if (system == 'win7' and platform.system() != 'Windows') or ( | 77 if (system == 'win7' and platform.system() != 'Windows') or ( |
139 system == 'mac' and platform.system() != 'Darwin') or ( | 78 system == 'mac' and platform.system() != 'Darwin') or ( |
140 system == 'linux' and platform.system() != 'Linux'): | 79 system == 'linux' and platform.system() != 'Linux'): |
141 print ('Error: You cannot emulate a buildbot with a platform different ' | 80 print ('Error: You cannot emulate a buildbot with a platform different ' |
142 'from your own.') | 81 'from your own.') |
143 sys.exit(1) | 82 return None |
144 return BuildInfo(compiler, runtime, mode, system, checked, host_checked, | 83 |
| 84 return bot.BuildInfo(compiler, runtime, mode, system, checked, host_checked, |
145 shard_index, total_shards, is_buildbot, test_set) | 85 shard_index, total_shards, is_buildbot, test_set) |
146 | 86 |
147 | 87 |
148 def NeedsXterm(compiler, runtime): | 88 def NeedsXterm(compiler, runtime): |
149 return runtime in ['ie', 'chrome', 'safari', 'opera', 'ff', 'drt'] | 89 return runtime in ['ie', 'chrome', 'safari', 'opera', 'ff', 'drt'] |
150 | 90 |
151 | 91 |
152 def TestStepName(name, flags): | 92 def TestStepName(name, flags): |
153 # Filter out flags with '=' as this breaks the /stats feature of the | 93 # Filter out flags with '=' as this breaks the /stats feature of the |
154 # build bot. | 94 # build bot. |
155 flags = [x for x in flags if not '=' in x] | 95 flags = [x for x in flags if not '=' in x] |
156 return ('%s tests %s' % (name, ' '.join(flags))).strip() | 96 return ('%s tests %s' % (name, ' '.join(flags))).strip() |
157 | 97 |
158 | 98 |
159 def TestStep(name, mode, system, compiler, runtime, targets, flags): | 99 def TestStep(name, mode, system, compiler, runtime, targets, flags): |
160 step_name = TestStepName(name, flags) | 100 step_name = TestStepName(name, flags) |
161 print '@@@BUILD_STEP %s@@@' % step_name | 101 with bot.BuildStep(step_name, swallow_error=True): |
162 sys.stdout.flush() | 102 sys.stdout.flush() |
163 if NeedsXterm(compiler, runtime) and system == 'linux': | 103 if NeedsXterm(compiler, runtime) and system == 'linux': |
164 cmd = ['xvfb-run', '-a'] | 104 cmd = ['xvfb-run', '-a'] |
165 else: | 105 else: |
166 cmd = [] | 106 cmd = [] |
167 | 107 |
168 user_test = os.environ.get('USER_TEST', 'no') | 108 user_test = os.environ.get('USER_TEST', 'no') |
169 | 109 |
170 cmd.extend([sys.executable, | 110 cmd.extend([sys.executable, |
171 os.path.join(os.curdir, 'tools', 'test.py'), | 111 os.path.join(os.curdir, 'tools', 'test.py'), |
172 '--step_name=' + step_name, | 112 '--step_name=' + step_name, |
173 '--mode=' + mode, | 113 '--mode=' + mode, |
174 '--compiler=' + compiler, | 114 '--compiler=' + compiler, |
175 '--runtime=' + runtime, | 115 '--runtime=' + runtime, |
176 '--time', | 116 '--time', |
177 '--use-sdk', | 117 '--use-sdk', |
178 '--report']) | 118 '--report']) |
179 | 119 |
180 if user_test == 'yes': | 120 if user_test == 'yes': |
181 cmd.append('--progress=color') | 121 cmd.append('--progress=color') |
182 else: | 122 else: |
183 cmd.extend(['--progress=buildbot', '-v']) | 123 cmd.extend(['--progress=buildbot', '-v']) |
184 | 124 |
185 if flags: | 125 if flags: |
186 cmd.extend(flags) | 126 cmd.extend(flags) |
187 cmd.extend(targets) | 127 cmd.extend(targets) |
188 | 128 |
189 print 'running %s' % (' '.join(cmd)) | 129 print 'running %s' % (' '.join(cmd)) |
190 exit_code = subprocess.call(cmd, env=NO_COLOR_ENV) | 130 bot.RunProcess(cmd) |
191 if exit_code != 0: | |
192 print '@@@STEP_FAILURE@@@' | |
193 return exit_code | |
194 | |
195 | |
196 def BuildSDK(mode, system): | |
197 """ build the SDK. | |
198 Args: | |
199 - mode: either 'debug' or 'release' | |
200 - system: either 'linux', 'mac', or 'win7' | |
201 """ | |
202 os.chdir(DART_PATH) | |
203 | |
204 args = [sys.executable, './tools/build.py', '--mode=' + mode, 'create_sdk'] | |
205 print 'running %s' % (' '.join(args)) | |
206 return subprocess.call(args, env=NO_COLOR_ENV) | |
207 | 131 |
208 | 132 |
209 def TestCompiler(runtime, mode, system, flags, is_buildbot, test_set): | 133 def TestCompiler(runtime, mode, system, flags, is_buildbot, test_set): |
210 """ test the compiler. | 134 """ test the compiler. |
211 Args: | 135 Args: |
212 - runtime: either 'd8', 'jsshell', or one of the browsers, see GetBuildInfo | 136 - runtime: either 'd8', 'jsshell', or one of the browsers, see GetBuildInfo |
213 - mode: either 'debug' or 'release' | 137 - mode: either 'debug' or 'release' |
214 - system: either 'linux', 'mac', or 'win7' | 138 - system: either 'linux', 'mac', or 'win7' |
215 - flags: extra flags to pass to test.dart | 139 - flags: extra flags to pass to test.dart |
216 - is_buildbot: true if we are running on a real buildbot instead of | 140 - is_buildbot: true if we are running on a real buildbot instead of |
217 emulating one. | 141 emulating one. |
218 - test_set: Specification of a non standard test set, default None | 142 - test_set: Specification of a non standard test set, default None |
219 """ | 143 """ |
220 | 144 |
221 # Make sure we are in the dart directory | |
222 os.chdir(DART_PATH) | |
223 | |
224 if system.startswith('win') and runtime == 'ie': | 145 if system.startswith('win') and runtime == 'ie': |
225 # There should not be more than one InternetExplorerDriver instance | 146 # There should not be more than one InternetExplorerDriver instance |
226 # running at a time. For details, see | 147 # running at a time. For details, see |
227 # http://code.google.com/p/selenium/wiki/InternetExplorerDriver. | 148 # http://code.google.com/p/selenium/wiki/InternetExplorerDriver. |
228 flags += ['-j1'] | 149 flags += ['-j1'] |
229 | 150 |
230 def GetPath(runtime): | 151 def GetPath(runtime): |
231 """ Helper to get the path to the Chrome or Firefox executable for a | 152 """ Helper to get the path to the Chrome or Firefox executable for a |
232 particular platform on the buildbot. Throws a KeyError if runtime is not | 153 particular platform on the buildbot. Throws a KeyError if runtime is not |
233 either 'chrome' or 'ff'.""" | 154 either 'chrome' or 'ff'.""" |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
287 TestStep("dart2js", mode, system, 'dart2js', runtime, ['html'], flags) | 208 TestStep("dart2js", mode, system, 'dart2js', runtime, ['html'], flags) |
288 elif test_set == 'all': | 209 elif test_set == 'all': |
289 TestStep("dart2js", mode, system, 'dart2js', runtime, ['dartc', | 210 TestStep("dart2js", mode, system, 'dart2js', runtime, ['dartc', |
290 'samples', 'standalone', 'corelib', 'co19', 'language', 'isolate', | 211 'samples', 'standalone', 'corelib', 'co19', 'language', 'isolate', |
291 'vm', 'json', 'benchmark_smoke', 'dartdoc', 'utils', 'pub', 'lib'], | 212 'vm', 'json', 'benchmark_smoke', 'dartdoc', 'utils', 'pub', 'lib'], |
292 flags) | 213 flags) |
293 extras = ['dart2js_extra', 'dart2js_native', 'dart2js_foreign'] | 214 extras = ['dart2js_extra', 'dart2js_native', 'dart2js_foreign'] |
294 TestStep("dart2js_extra", mode, system, 'dart2js', runtime, extras, | 215 TestStep("dart2js_extra", mode, system, 'dart2js', runtime, extras, |
295 flags) | 216 flags) |
296 | 217 |
297 return 0 | |
298 | 218 |
299 def _DeleteTempWebdriverProfiles(directory): | 219 def _DeleteTempWebdriverProfiles(directory): |
300 """Find all the firefox profiles in a particular directory and delete them.""" | 220 """Find all the firefox profiles in a particular directory and delete them.""" |
301 for f in os.listdir(directory): | 221 for f in os.listdir(directory): |
302 item = os.path.join(directory, f) | 222 item = os.path.join(directory, f) |
303 if os.path.isdir(item) and (f.startswith('tmp') or f.startswith('opera')): | 223 if os.path.isdir(item) and (f.startswith('tmp') or f.startswith('opera')): |
304 subprocess.Popen('rm -rf %s' % item, shell=True) | 224 subprocess.Popen('rm -rf %s' % item, shell=True) |
305 | 225 |
| 226 |
306 def CleanUpTemporaryFiles(system, browser): | 227 def CleanUpTemporaryFiles(system, browser): |
307 """For some browser (selenium) tests, the browser creates a temporary profile | 228 """For some browser (selenium) tests, the browser creates a temporary profile |
308 on each browser session start. On Windows, generally these files are | 229 on each browser session start. On Windows, generally these files are |
309 automatically deleted when all python processes complete. However, since our | 230 automatically deleted when all python processes complete. However, since our |
310 buildbot slave script also runs on python, we never get the opportunity to | 231 buildbot slave script also runs on python, we never get the opportunity to |
311 clear out the temp files, so we do so explicitly here. Our batch browser | 232 clear out the temp files, so we do so explicitly here. Our batch browser |
312 testing will make this problem occur much less frequently, but will still | 233 testing will make this problem occur much less frequently, but will still |
313 happen eventually unless we do this. | 234 happen eventually unless we do this. |
314 | 235 |
315 This problem also occurs with batch tests in Firefox. For some reason selenium | 236 This problem also occurs with batch tests in Firefox. For some reason selenium |
316 automatically deletes the temporary profiles for Firefox for one browser, | 237 automatically deletes the temporary profiles for Firefox for one browser, |
317 but not multiple ones when we have many open batch tasks running. This | 238 but not multiple ones when we have many open batch tasks running. This |
318 behavior has not been reproduced outside of the buildbots. | 239 behavior has not been reproduced outside of the buildbots. |
319 | 240 |
320 Args: | 241 Args: |
321 - system: either 'linux', 'mac', or 'win7' | 242 - system: either 'linux', 'mac', or 'win7' |
322 - browser: one of the browsers, see GetBuildInfo | 243 - browser: one of the browsers, see GetBuildInfo |
323 """ | 244 """ |
324 if system == 'win7': | 245 if system == 'win7': |
325 shutil.rmtree('C:\\Users\\chrome-bot\\AppData\\Local\\Temp', | 246 shutil.rmtree('C:\\Users\\chrome-bot\\AppData\\Local\\Temp', |
326 ignore_errors=True) | 247 ignore_errors=True) |
327 elif browser == 'ff' or 'opera': | 248 elif browser == 'ff' or 'opera': |
328 # Note: the buildbots run as root, so we can do this without requiring a | 249 # Note: the buildbots run as root, so we can do this without requiring a |
329 # password. The command won't actually work on regular machines without | 250 # password. The command won't actually work on regular machines without |
330 # root permissions. | 251 # root permissions. |
331 _DeleteTempWebdriverProfiles('/tmp') | 252 _DeleteTempWebdriverProfiles('/tmp') |
332 _DeleteTempWebdriverProfiles('/var/tmp') | 253 _DeleteTempWebdriverProfiles('/var/tmp') |
333 | 254 |
334 def ClobberBuilder(mode): | |
335 """ Clobber the builder before we do the build. | |
336 Args: | |
337 - mode: either 'debug' or 'release' | |
338 """ | |
339 cmd = [sys.executable, | |
340 './tools/clean_output_directory.py', | |
341 '--mode=' + mode] | |
342 print 'Clobbering %s' % (' '.join(cmd)) | |
343 return subprocess.call(cmd, env=NO_COLOR_ENV) | |
344 | |
345 def GetShouldClobber(): | |
346 return os.environ.get(BUILDER_CLOBBER) == "1" | |
347 | 255 |
348 def GetHasHardCodedCheckedMode(build_info): | 256 def GetHasHardCodedCheckedMode(build_info): |
349 # TODO(ricow): We currently run checked mode tests on chrome on linux and | 257 # TODO(ricow): We currently run checked mode tests on chrome on linux and |
350 # on the slow (all) IE windows bots. This is a hack and we should use the | 258 # on the slow (all) IE windows bots. This is a hack and we should use the |
351 # normal sharding and checked splitting functionality when we get more | 259 # normal sharding and checked splitting functionality when we get more |
352 # vms for testing this. | 260 # vms for testing this. |
353 if (build_info.system == 'linux' and build_info.runtime == 'chrome'): | 261 if (build_info.system == 'linux' and build_info.runtime == 'chrome'): |
354 return True | 262 return True |
355 if (build_info.system == 'win7' and build_info.runtime == 'ie' and | 263 if (build_info.system == 'win7' and build_info.runtime == 'ie' and |
356 build_info.test_set == 'all'): | 264 build_info.test_set == 'all'): |
357 return True | 265 return True |
358 return False | 266 return False |
359 | 267 |
360 def main(): | |
361 if len(sys.argv) == 0: | |
362 print 'Script pathname not known, giving up.' | |
363 return 1 | |
364 | 268 |
365 build_info = GetBuildInfo() | 269 def RunCompilerTests(build_info): |
366 | |
367 # Print out the buildinfo for easy debugging. | |
368 build_info.PrintBuildInfo() | |
369 | |
370 if build_info.compiler is None: | |
371 return 1 | |
372 | |
373 if GetShouldClobber(): | |
374 print '@@@BUILD_STEP Clobber@@@' | |
375 status = ClobberBuilder(build_info.mode) | |
376 if status != 0: | |
377 print '@@@STEP_FAILURE@@@' | |
378 return status | |
379 | |
380 print '@@@BUILD_STEP build sdk@@@' | |
381 status = BuildSDK(build_info.mode, build_info.system) | |
382 if status != 0: | |
383 print '@@@STEP_FAILURE@@@' | |
384 return status | |
385 | |
386 test_flags = [] | 270 test_flags = [] |
387 if build_info.shard_index: | 271 if build_info.shard_index: |
388 test_flags = ['--shards=%s' % build_info.total_shards, | 272 test_flags = ['--shards=%s' % build_info.total_shards, |
389 '--shard=%s' % build_info.shard_index] | 273 '--shard=%s' % build_info.shard_index] |
390 | 274 |
391 if build_info.checked: test_flags += ['--checked'] | 275 if build_info.checked: test_flags += ['--checked'] |
392 | 276 |
393 if build_info.host_checked: test_flags += ['--host-checked'] | 277 if build_info.host_checked: test_flags += ['--host-checked'] |
394 | 278 |
395 status = TestCompiler(build_info.runtime, build_info.mode, | 279 TestCompiler(build_info.runtime, build_info.mode, build_info.system, |
396 build_info.system, list(test_flags), | 280 list(test_flags), build_info.is_buildbot, build_info.test_set) |
397 build_info.is_buildbot, build_info.test_set) | |
398 | 281 |
399 # See comment in GetHasHardCodedCheckedMode, this is a hack. | 282 # See comment in GetHasHardCodedCheckedMode, this is a hack. |
400 if (status == 0 and GetHasHardCodedCheckedMode(build_info)): | 283 if (GetHasHardCodedCheckedMode(build_info)): |
401 status = TestCompiler(build_info.runtime, build_info.mode, | 284 TestCompiler(build_info.runtime, build_info.mode, build_info.system, |
402 build_info.system, | 285 test_flags + ['--checked'], build_info.is_buildbot, |
403 test_flags + ['--checked'], | 286 build_info.test_set) |
404 build_info.is_buildbot, | |
405 build_info.test_set) | |
406 | 287 |
407 if build_info.runtime != 'd8': CleanUpTemporaryFiles(build_info.system, | 288 if build_info.runtime != 'd8': |
408 build_info.runtime) | 289 CleanUpTemporaryFiles(build_info.system, build_info.runtime) |
409 if status != 0: print '@@@STEP_FAILURE@@@' | 290 |
410 return status | |
411 | 291 |
412 if __name__ == '__main__': | 292 if __name__ == '__main__': |
413 sys.exit(main()) | 293 bot.RunBot(GetBuildInfo, RunCompilerTests) |
OLD | NEW |