Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/usr/bin/python | 1 #!/usr/bin/python |
| 2 | 2 |
| 3 # Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 3 # Copyright (c) 2011, 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 datetime | 7 import datetime |
| 8 import math | 8 import math |
| 9 try: | 9 try: |
| 10 from matplotlib.font_manager import FontProperties | 10 from matplotlib.font_manager import FontProperties |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 140 | 140 |
| 141 def ensure_output_directory(self, dir_name): | 141 def ensure_output_directory(self, dir_name): |
| 142 """Test that the listed directory name exists, and if not, create one for | 142 """Test that the listed directory name exists, and if not, create one for |
| 143 our output to be placed. | 143 our output to be placed. |
| 144 | 144 |
| 145 Args: | 145 Args: |
| 146 dir_name: the directory we will create if it does not exist.""" | 146 dir_name: the directory we will create if it does not exist.""" |
| 147 dir_path = os.path.join(DART_INSTALL_LOCATION, 'tools', | 147 dir_path = os.path.join(DART_INSTALL_LOCATION, 'tools', |
| 148 'testing', 'perf_testing', dir_name) | 148 'testing', 'perf_testing', dir_name) |
| 149 if not os.path.exists(dir_path): | 149 if not os.path.exists(dir_path): |
| 150 os.mkdir(dir_path) | 150 os.makedirs(dir_path) |
| 151 print 'Creating output directory ', dir_path | 151 print 'Creating output directory ', dir_path |
|
vsm
2012/05/08 03:30:58
Did you mean to create old/dir_name here as well i
Emily Fortuna
2012/05/08 16:35:07
I call this function twice, once for the regular d
| |
| 152 | 152 |
| 153 def has_new_code(self): | 153 def has_new_code(self): |
| 154 """Tests if there are any newer versions of files on the server.""" | 154 """Tests if there are any newer versions of files on the server.""" |
| 155 os.chdir(DART_INSTALL_LOCATION) | 155 os.chdir(DART_INSTALL_LOCATION) |
| 156 # Pass 'p' in if we have a new certificate for the svn server, we want to | 156 # Pass 'p' in if we have a new certificate for the svn server, we want to |
| 157 # (p)ermanently accept it. | 157 # (p)ermanently accept it. |
| 158 results = self.run_cmd(['svn', 'st', '-u'], std_in='p') | 158 results = self.run_cmd(['svn', 'st', '-u'], std_in='p\r\n') |
| 159 for line in results: | 159 for line in results: |
| 160 if '*' in line: | 160 if '*' in line: |
| 161 return True | 161 return True |
| 162 return False | 162 return False |
| 163 | 163 |
| 164 def get_os_directory(self): | 164 def get_os_directory(self): |
| 165 """Specifies the name of the directory for the testing build of dart, which | 165 """Specifies the name of the directory for the testing build of dart, which |
| 166 has yet a different naming convention from utils.getBuildRoot(...).""" | 166 has yet a different naming convention from utils.getBuildRoot(...).""" |
| 167 if platform.system() == 'Windows': | 167 if platform.system() == 'Windows': |
| 168 return 'windows' | 168 return 'windows' |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 339 | 339 |
| 340 def run(self): | 340 def run(self): |
| 341 """Run the benchmarks/tests from the command line and plot the | 341 """Run the benchmarks/tests from the command line and plot the |
| 342 results. | 342 results. |
| 343 """ | 343 """ |
| 344 for visitor in [self.tester, self.file_processor, self.grapher]: | 344 for visitor in [self.tester, self.file_processor, self.grapher]: |
| 345 visitor.prepare() | 345 visitor.prepare() |
| 346 | 346 |
| 347 os.chdir(DART_INSTALL_LOCATION) | 347 os.chdir(DART_INSTALL_LOCATION) |
| 348 self.test_runner.ensure_output_directory(self.result_folder_name) | 348 self.test_runner.ensure_output_directory(self.result_folder_name) |
| 349 self.test_runner.ensure_output_directory(os.path.join( | |
| 350 'old', self.result_folder_name)) | |
| 349 if not self.test_runner.no_test: | 351 if not self.test_runner.no_test: |
| 350 self.tester.run_tests() | 352 self.tester.run_tests() |
| 351 | 353 |
| 352 os.chdir(os.path.join('tools', 'testing', 'perf_testing')) | 354 os.chdir(os.path.join('tools', 'testing', 'perf_testing')) |
| 353 | 355 |
| 356 for afile in os.listdir(os.path.join('old', self.result_folder_name)): | |
| 357 if not afile.startswith('.'): | |
| 358 self.file_processor.process_file(afile, False) | |
| 359 | |
| 354 files = os.listdir(self.result_folder_name) | 360 files = os.listdir(self.result_folder_name) |
| 355 for afile in files: | 361 for afile in files: |
| 356 if not afile.startswith('.'): | 362 if not afile.startswith('.'): |
| 357 self.file_processor.process_file(afile) | 363 should_move_file = self.file_processor.process_file(afile, True) |
| 364 if should_move_file: | |
| 365 shutil.move(os.path.join(self.result_folder_name, afile), | |
| 366 os.path.join('old', self.result_folder_name, afile)) | |
| 358 | 367 |
| 359 if 'plt' in globals(): | 368 if 'plt' in globals(): |
| 360 # Only run Matplotlib if it is installed. | 369 # Only run Matplotlib if it is installed. |
| 361 self.grapher.plot_results('%s.png' % self.result_folder_name) | 370 self.grapher.plot_results('%s.png' % self.result_folder_name) |
| 362 | 371 |
| 363 | 372 |
| 364 class Tester(object): | 373 class Tester(object): |
| 365 """The base level visitor class that runs tests. It contains convenience | 374 """The base level visitor class that runs tests. It contains convenience |
| 366 methods that many Tester objects use. Any class that would like to be a | 375 methods that many Tester objects use. Any class that would like to be a |
| 367 TesterVisitor must implement the run_tests() method.""" | 376 TesterVisitor must implement the run_tests() method.""" |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 411 COMPILE_TIME = 'CompileTime' | 420 COMPILE_TIME = 'CompileTime' |
| 412 CODE_SIZE = 'CodeSize' | 421 CODE_SIZE = 'CodeSize' |
| 413 | 422 |
| 414 def __init__(self, test): | 423 def __init__(self, test): |
| 415 self.test = test | 424 self.test = test |
| 416 | 425 |
| 417 def prepare(self): | 426 def prepare(self): |
| 418 """Perform any initial setup required before the test is run.""" | 427 """Perform any initial setup required before the test is run.""" |
| 419 pass | 428 pass |
| 420 | 429 |
| 421 def should_report_results(self, afile): | |
| 422 """We store all trace files locally, but we don't want to post all of the | |
| 423 results every time, so we only attempt to post results for recent runs.""" | |
| 424 cur_time = time.time() | |
| 425 file_mod_time = os.path.getmtime(os.path.join( | |
| 426 self.test.result_folder_name, afile)) | |
| 427 return cur_time - file_mod_time < 1000 # Files modified in the last ~15 min. | |
| 428 | |
| 429 def report_results(self, benchmark_name, score, platform, variant, | 430 def report_results(self, benchmark_name, score, platform, variant, |
| 430 revision_number, metric): | 431 revision_number, metric): |
| 431 """Store the results of the benchmark run. | 432 """Store the results of the benchmark run. |
| 432 Args: | 433 Args: |
| 433 benchmark_name: The name of the individual benchmark. | 434 benchmark_name: The name of the individual benchmark. |
| 434 score: The numerical value of this benchmark. | 435 score: The numerical value of this benchmark. |
| 435 platform: The platform the test was run on (firefox, command line, etc). | 436 platform: The platform the test was run on (firefox, command line, etc). |
| 436 variant: Specifies whether the data was about generated Frog, js, a | 437 variant: Specifies whether the data was about generated Frog, js, a |
| 437 combination of both, or Dart depending on the test. | 438 combination of both, or Dart depending on the test. |
| 438 revision_number: The revision of the code (and sometimes the revision of | 439 revision_number: The revision of the code (and sometimes the revision of |
| (...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 674 file_path = os.path.join( | 675 file_path = os.path.join( |
| 675 os.getcwd(), 'internal', 'browserBenchmarks', | 676 os.getcwd(), 'internal', 'browserBenchmarks', |
| 676 'benchmark_page_%s.html' % version) | 677 'benchmark_page_%s.html' % version) |
| 677 self.test.test_runner.run_cmd( | 678 self.test.test_runner.run_cmd( |
| 678 ['python', os.path.join('tools', 'testing', 'run_selenium.py'), | 679 ['python', os.path.join('tools', 'testing', 'run_selenium.py'), |
| 679 '--out', file_path, '--browser', browser, | 680 '--out', file_path, '--browser', browser, |
| 680 '--timeout', '600', '--mode', 'perf'], self.test.trace_file, | 681 '--timeout', '600', '--mode', 'perf'], self.test.trace_file, |
| 681 append=True) | 682 append=True) |
| 682 | 683 |
| 683 class CommonBrowserFileProcessor(Processor): | 684 class CommonBrowserFileProcessor(Processor): |
| 684 def process_file(self, afile): | 685 def process_file(self, afile, should_post_file): |
| 685 """Comb through the html to find the performance results. | 686 """Comb through the html to find the performance results. |
| 686 Returns: True if we successfully posted our data to storage and/or we can | 687 Returns: True if we successfully posted our data to storage and/or we can |
| 687 delete the trace file.""" | 688 delete the trace file.""" |
| 688 os.chdir(os.path.join(DART_INSTALL_LOCATION, 'tools', | 689 os.chdir(os.path.join(DART_INSTALL_LOCATION, 'tools', |
| 689 'testing', 'perf_testing')) | 690 'testing', 'perf_testing')) |
| 690 parts = afile.split('-') | 691 parts = afile.split('-') |
| 691 browser = parts[2] | 692 browser = parts[2] |
| 692 version = parts[3] | 693 version = parts[3] |
| 693 f = open(os.path.join(self.test.result_folder_name, afile)) | 694 f = open(os.path.join(self.test.result_folder_name, afile)) |
| 694 lines = f.readlines() | 695 lines = f.readlines() |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 719 name_and_score = result.split(':') | 720 name_and_score = result.split(':') |
| 720 if len(name_and_score) < 2: | 721 if len(name_and_score) < 2: |
| 721 break | 722 break |
| 722 name = name_and_score[0].strip() | 723 name = name_and_score[0].strip() |
| 723 score = name_and_score[1].strip() | 724 score = name_and_score[1].strip() |
| 724 if version == 'js' or version == 'v8': | 725 if version == 'js' or version == 'v8': |
| 725 version = 'js' | 726 version = 'js' |
| 726 bench_dict = self.test.values_dict[browser][version] | 727 bench_dict = self.test.values_dict[browser][version] |
| 727 bench_dict[name] += [float(score)] | 728 bench_dict[name] += [float(score)] |
| 728 self.test.revision_dict[browser][version][name] += [revision_num] | 729 self.test.revision_dict[browser][version][name] += [revision_num] |
| 729 if self.should_report_results(afile) and \ | 730 if not self.test.test_runner.no_upload and should_post_file: |
| 730 not self.test.test_runner.no_upload: | |
| 731 upload_success = upload_success and self.report_results( | 731 upload_success = upload_success and self.report_results( |
| 732 name, score, browser, version, revision_num, self.SCORE) | 732 name, score, browser, version, revision_num, self.SCORE) |
| 733 else: | 733 else: |
| 734 upload_success = False | 734 upload_success = False |
| 735 | 735 |
| 736 f.close() | 736 f.close() |
| 737 self.calculate_geometric_mean(browser, version, revision_num) | 737 self.calculate_geometric_mean(browser, version, revision_num) |
| 738 return upload_success | 738 return upload_success |
| 739 | 739 |
| 740 | 740 |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 863 @staticmethod | 863 @staticmethod |
| 864 def get_dromaeo_url_query(browser, version): | 864 def get_dromaeo_url_query(browser, version): |
| 865 if browser == 'dartium': | 865 if browser == 'dartium': |
| 866 version = version.replace('frog', 'dart') | 866 version = version.replace('frog', 'dart') |
| 867 version = version.replace('_','&') | 867 version = version.replace('_','&') |
| 868 tags = DromaeoTester.get_valid_dromaeo_tags() | 868 tags = DromaeoTester.get_valid_dromaeo_tags() |
| 869 return '|'.join([ '%s&%s' % (version, tag) for tag in tags]) | 869 return '|'.join([ '%s&%s' % (version, tag) for tag in tags]) |
| 870 | 870 |
| 871 | 871 |
| 872 class DromaeoFileProcessor(Processor): | 872 class DromaeoFileProcessor(Processor): |
| 873 def process_file(self, afile): | 873 def process_file(self, afile, should_post_file): |
| 874 """Comb through the html to find the performance results. | 874 """Comb through the html to find the performance results. |
| 875 Returns: True if we successfully posted our data to storage.""" | 875 Returns: True if we successfully posted our data to storage.""" |
| 876 parts = afile.split('-') | 876 parts = afile.split('-') |
| 877 browser = parts[2] | 877 browser = parts[2] |
| 878 version = parts[3] | 878 version = parts[3] |
| 879 | 879 |
| 880 bench_dict = self.test.values_dict[browser][version] | 880 bench_dict = self.test.values_dict[browser][version] |
| 881 | 881 |
| 882 f = open(os.path.join(self.test.result_folder_name, afile)) | 882 f = open(os.path.join(self.test.result_folder_name, afile)) |
| 883 lines = f.readlines() | 883 lines = f.readlines() |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 899 for suite_result in suite_results: | 899 for suite_result in suite_results: |
| 900 results = re.findall(r'<li>(.*?)</li>', suite_result) | 900 results = re.findall(r'<li>(.*?)</li>', suite_result) |
| 901 if results: | 901 if results: |
| 902 for result in results: | 902 for result in results: |
| 903 r = re.match(result_pattern, result) | 903 r = re.match(result_pattern, result) |
| 904 name = DromaeoTester.legalize_filename(r.group(1).strip(':')) | 904 name = DromaeoTester.legalize_filename(r.group(1).strip(':')) |
| 905 score = float(r.group(2)) | 905 score = float(r.group(2)) |
| 906 bench_dict[name] += [float(score)] | 906 bench_dict[name] += [float(score)] |
| 907 self.test.revision_dict[browser][version][name] += \ | 907 self.test.revision_dict[browser][version][name] += \ |
| 908 [revision_num] | 908 [revision_num] |
| 909 if self.should_report_results(afile) and \ | 909 if not self.test.test_runner.no_upload and should_post_file: |
| 910 not self.test.test_runner.no_upload: | |
| 911 upload_success = upload_success and self.report_results( | 910 upload_success = upload_success and self.report_results( |
| 912 name, score, browser, version, revision_num, self.SCORE) | 911 name, score, browser, version, revision_num, self.SCORE) |
| 913 else: | 912 else: |
| 914 upload_success = False | 913 upload_success = False |
| 915 | 914 |
| 916 f.close() | 915 f.close() |
| 917 self.calculate_geometric_mean(browser, version, revision_num) | 916 self.calculate_geometric_mean(browser, version, revision_num) |
| 918 return upload_success | 917 return upload_success |
| 919 | 918 |
| 920 | 919 |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 993 self.test.extra_metrics[0])], | 992 self.test.extra_metrics[0])], |
| 994 self.test.trace_file, append=True) | 993 self.test.trace_file, append=True) |
| 995 for (variant, _) in variants: | 994 for (variant, _) in variants: |
| 996 self.test.test_runner.run_cmd( | 995 self.test.test_runner.run_cmd( |
| 997 ['echo', 'Size (%s, %s): %s' % (variant, self.test.extra_metrics[0], | 996 ['echo', 'Size (%s, %s): %s' % (variant, self.test.extra_metrics[0], |
| 998 total_size[variant])], | 997 total_size[variant])], |
| 999 self.test.trace_file, append=True) | 998 self.test.trace_file, append=True) |
| 1000 | 999 |
| 1001 | 1000 |
| 1002 class DromaeoSizeProcessor(Processor): | 1001 class DromaeoSizeProcessor(Processor): |
| 1003 def process_file(self, afile): | 1002 def process_file(self, afile, should_post_file): |
| 1004 """Pull all the relevant information out of a given tracefile. | 1003 """Pull all the relevant information out of a given tracefile. |
| 1005 | 1004 |
| 1006 Args: | 1005 Args: |
| 1007 afile: is the filename string we will be processing. | 1006 afile: is the filename string we will be processing. |
| 1008 Returns: True if we successfully posted our data to storage.""" | 1007 Returns: True if we successfully posted our data to storage.""" |
| 1009 os.chdir(os.path.join(DART_INSTALL_LOCATION, 'tools', | 1008 os.chdir(os.path.join(DART_INSTALL_LOCATION, 'tools', |
| 1010 'testing', 'perf_testing')) | 1009 'testing', 'perf_testing')) |
| 1011 f = open(os.path.join(self.test.result_folder_name, afile)) | 1010 f = open(os.path.join(self.test.result_folder_name, afile)) |
| 1012 tabulate_data = False | 1011 tabulate_data = False |
| 1013 revision_num = 0 | 1012 revision_num = 0 |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 1026 variant = result.group(1) | 1025 variant = result.group(1) |
| 1027 metric = result.group(2) | 1026 metric = result.group(2) |
| 1028 num = result.group(3) | 1027 num = result.group(3) |
| 1029 if num.find('.') == -1: | 1028 if num.find('.') == -1: |
| 1030 num = int(num) | 1029 num = int(num) |
| 1031 else: | 1030 else: |
| 1032 num = float(num) | 1031 num = float(num) |
| 1033 self.test.values_dict['commandline'][variant][metric] += [num] | 1032 self.test.values_dict['commandline'][variant][metric] += [num] |
| 1034 self.test.revision_dict['commandline'][variant][metric] += \ | 1033 self.test.revision_dict['commandline'][variant][metric] += \ |
| 1035 [revision_num] | 1034 [revision_num] |
| 1036 if self.should_report_results(afile) and \ | 1035 if not self.test.test_runner.no_upload and should_post_file: |
| 1037 not self.test.test_runner.no_upload: | |
| 1038 upload_success = upload_success and self.report_results( | 1036 upload_success = upload_success and self.report_results( |
| 1039 metric, num, 'commandline', variant, revision_num, | 1037 metric, num, 'commandline', variant, revision_num, |
| 1040 self.CODE_SIZE) | 1038 self.CODE_SIZE) |
| 1041 else: | 1039 else: |
| 1042 upload_success = False | 1040 upload_success = False |
| 1043 | 1041 |
| 1044 f.close() | 1042 f.close() |
| 1045 return upload_success | 1043 return upload_success |
| 1046 | 1044 |
| 1047 class DromaeoSizeGrapher(Grapher): | 1045 class DromaeoSizeGrapher(Grapher): |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1123 | 1121 |
| 1124 self.test.test_runner.run_cmd( | 1122 self.test.test_runner.run_cmd( |
| 1125 ['echo', '%d Generated checked total size' % total_size], | 1123 ['echo', '%d Generated checked total size' % total_size], |
| 1126 self.test.trace_file, append=True) | 1124 self.test.trace_file, append=True) |
| 1127 | 1125 |
| 1128 os.chdir('..') | 1126 os.chdir('..') |
| 1129 | 1127 |
| 1130 | 1128 |
| 1131 class CompileProcessor(Processor): | 1129 class CompileProcessor(Processor): |
| 1132 | 1130 |
| 1133 def process_file(self, afile): | 1131 def process_file(self, afile, should_post_file): |
| 1134 """Pull all the relevant information out of a given tracefile. | 1132 """Pull all the relevant information out of a given tracefile. |
| 1135 | 1133 |
| 1136 Args: | 1134 Args: |
| 1137 afile: is the filename string we will be processing. | 1135 afile: is the filename string we will be processing. |
| 1138 Returns: True if we successfully posted our data to storage.""" | 1136 Returns: True if we successfully posted our data to storage.""" |
| 1139 os.chdir(os.path.join(DART_INSTALL_LOCATION, 'tools', | 1137 os.chdir(os.path.join(DART_INSTALL_LOCATION, 'tools', |
| 1140 'testing', 'perf_testing')) | 1138 'testing', 'perf_testing')) |
| 1141 f = open(os.path.join(self.test.result_folder_name, afile)) | 1139 f = open(os.path.join(self.test.result_folder_name, afile)) |
| 1142 tabulate_data = False | 1140 tabulate_data = False |
| 1143 revision_num = 0 | 1141 revision_num = 0 |
| 1144 upload_success = True | 1142 upload_success = True |
| 1145 for line in f.readlines(): | 1143 for line in f.readlines(): |
| 1146 tokens = line.split() | 1144 tokens = line.split() |
| 1147 if 'Revision' in line: | 1145 if 'Revision' in line: |
| 1148 revision_num = int(line.split()[1]) | 1146 revision_num = int(line.split()[1]) |
| 1149 else: | 1147 else: |
| 1150 for metric in self.test.values_list: | 1148 for metric in self.test.values_list: |
| 1151 if metric in line: | 1149 if metric in line: |
| 1152 num = tokens[0] | 1150 num = tokens[0] |
| 1153 if num.find('.') == -1: | 1151 if num.find('.') == -1: |
| 1154 num = int(num) | 1152 num = int(num) |
| 1155 else: | 1153 else: |
| 1156 num = float(num) | 1154 num = float(num) |
| 1157 self.test.values_dict['commandline']['frog'][metric] += [num] | 1155 self.test.values_dict['commandline']['frog'][metric] += [num] |
| 1158 self.test.revision_dict['commandline']['frog'][metric] += \ | 1156 self.test.revision_dict['commandline']['frog'][metric] += \ |
| 1159 [revision_num] | 1157 [revision_num] |
| 1160 score_type = self.CODE_SIZE | 1158 score_type = self.CODE_SIZE |
| 1161 if 'Compiling' in metric or 'Bootstrapping' in metric: | 1159 if 'Compiling' in metric or 'Bootstrapping' in metric: |
| 1162 score_type = self.COMPILE_TIME | 1160 score_type = self.COMPILE_TIME |
| 1163 if self.should_report_results(afile) and \ | 1161 if not self.test.test_runner.no_upload and should_post_file: |
| 1164 not self.test.test_runner.no_upload: | |
| 1165 if num < self.test.failure_threshold[metric]: | 1162 if num < self.test.failure_threshold[metric]: |
| 1166 num = 0 | 1163 num = 0 |
| 1167 upload_success = upload_success and self.report_results( | 1164 upload_success = upload_success and self.report_results( |
| 1168 metric, num, 'commandline', 'frog', revision_num, | 1165 metric, num, 'commandline', 'frog', revision_num, |
| 1169 score_type) | 1166 score_type) |
| 1170 else: | 1167 else: |
| 1171 upload_success = False | 1168 upload_success = False |
| 1172 if revision_num != 0: | 1169 if revision_num != 0: |
| 1173 for metric in self.test.values_list: | 1170 for metric in self.test.values_list: |
| 1174 self.test.revision_dict['commandline']['frog'][metric].pop() | 1171 self.test.revision_dict['commandline']['frog'][metric].pop() |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1213 while True: | 1210 while True: |
| 1214 if runner.has_new_code(): | 1211 if runner.has_new_code(): |
| 1215 runner.run_test_sequence() | 1212 runner.run_test_sequence() |
| 1216 else: | 1213 else: |
| 1217 time.sleep(200) | 1214 time.sleep(200) |
| 1218 else: | 1215 else: |
| 1219 runner.run_test_sequence() | 1216 runner.run_test_sequence() |
| 1220 | 1217 |
| 1221 if __name__ == '__main__': | 1218 if __name__ == '__main__': |
| 1222 main() | 1219 main() |
| OLD | NEW |