| 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 | 7 |
| 8 """Script to actually open a browser and perform the test, and reports back with | 8 """Script to actually open a browser and perform the test, and reports back with |
| 9 the result. It uses Selenium WebDriver when possible for running the tests. It | 9 the result. It uses Selenium WebDriver when possible for running the tests. It |
| 10 uses Selenium RC for Safari. | 10 uses Selenium RC for Safari. |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 64 source = source[index + len(string):end_index] | 64 source = source[index + len(string):end_index] |
| 65 return '0:00' in source | 65 return '0:00' in source |
| 66 | 66 |
| 67 # TODO(vsm): Ideally, this wouldn't live in this file. | 67 # TODO(vsm): Ideally, this wouldn't live in this file. |
| 68 CONFIGURATIONS = { | 68 CONFIGURATIONS = { |
| 69 'correctness': correctness_test_done, | 69 'correctness': correctness_test_done, |
| 70 'perf': perf_test_done, | 70 'perf': perf_test_done, |
| 71 'dromaeo': dromaeo_test_done | 71 'dromaeo': dromaeo_test_done |
| 72 } | 72 } |
| 73 | 73 |
| 74 def run_test_in_browser(browser, html_out, timeout, config): | 74 def run_test_in_browser(browser, html_out, timeout, mode): |
| 75 """Run the desired test in the browser using Selenium 2.0 WebDriver syntax, | 75 """Run the desired test in the browser using Selenium 2.0 WebDriver syntax, |
| 76 and wait for the test to complete. This is the newer syntax, that currently | 76 and wait for the test to complete. This is the newer syntax, that currently |
| 77 supports Firefox, Chrome, IE, Opera (and some mobile browsers).""" | 77 supports Firefox, Chrome, IE, Opera (and some mobile browsers).""" |
| 78 if isinstance(browser, selenium.selenium): | 78 if isinstance(browser, selenium.selenium): |
| 79 return run_test_in_browser_selenium_rc(browser, html_out, timeout, config) | 79 return run_test_in_browser_selenium_rc(browser, html_out, timeout, mode) |
| 80 | 80 |
| 81 browser.get("file://" + html_out) | 81 browser.get("file://" + html_out) |
| 82 source = '' | 82 source = '' |
| 83 try: | 83 try: |
| 84 test_done = CONFIGURATIONS[config] | 84 test_done = CONFIGURATIONS[mode] |
| 85 element = WebDriverWait(browser, float(timeout)).until( | 85 element = WebDriverWait(browser, float(timeout)).until( |
| 86 lambda driver: test_done(driver.page_source)) | 86 lambda driver: test_done(driver.page_source)) |
| 87 source = browser.page_source | 87 source = browser.page_source |
| 88 except selenium.common.exceptions.TimeoutException: | 88 except selenium.common.exceptions.TimeoutException: |
| 89 source = TIMEOUT_ERROR_MSG | 89 source = TIMEOUT_ERROR_MSG |
| 90 return source | 90 return source |
| 91 | 91 |
| 92 def run_test_in_browser_selenium_rc(sel, html_out, timeout, config): | 92 def run_test_in_browser_selenium_rc(sel, html_out, timeout, mode): |
| 93 """ Run the desired test in the browser using Selenium 1.0 syntax, and wait | 93 """ Run the desired test in the browser using Selenium 1.0 syntax, and wait |
| 94 for the test to complete. This is used for Safari, since it is not currently | 94 for the test to complete. This is used for Safari, since it is not currently |
| 95 supported on Selenium 2.0.""" | 95 supported on Selenium 2.0.""" |
| 96 sel.open('file://' + html_out) | 96 sel.open('file://' + html_out) |
| 97 source = sel.get_html_source() | 97 source = sel.get_html_source() |
| 98 end_condition = CONFIGURATIONS[config] | 98 end_condition = CONFIGURATIONS[mode] |
| 99 | 99 |
| 100 elapsed = 0 | 100 elapsed = 0 |
| 101 while (not end_condition(source)) and elapsed <= timeout: | 101 while (not end_condition(source)) and elapsed <= timeout: |
| 102 sec = .25 | 102 sec = .25 |
| 103 time.sleep(sec) | 103 time.sleep(sec) |
| 104 elapsed += sec | 104 elapsed += sec |
| 105 source = sel.get_html_source() | 105 source = sel.get_html_source() |
| 106 return source | 106 return source |
| 107 | 107 |
| 108 def parse_args(args=None): | 108 def parse_args(args=None): |
| 109 parser = optparse.OptionParser() | 109 parser = optparse.OptionParser() |
| 110 parser.add_option('--out', dest='out', | 110 parser.add_option('--out', dest='out', |
| 111 help = 'The path for html output file that we will running our test from', | 111 help = 'The path for html output file that we will running our test from', |
| 112 action = 'store', default = '') | 112 action = 'store', default = '') |
| 113 parser.add_option('--browser', dest='browser', | 113 parser.add_option('--browser', dest='browser', |
| 114 help = 'The browser type (default = chrome)', | 114 help = 'The browser type (default = chrome)', |
| 115 action = 'store', default = 'chrome') | 115 action = 'store', default = 'chrome') |
| 116 # TODO(efortuna): Put this back up to be more than the default timeout in | 116 # TODO(efortuna): Put this back up to be more than the default timeout in |
| 117 # test.dart. Right now it needs to be less than 60 so that when test.dart | 117 # test.dart. Right now it needs to be less than 60 so that when test.dart |
| 118 # times out, this script also closes the browser windows. | 118 # times out, this script also closes the browser windows. |
| 119 parser.add_option('--timeout', dest = 'timeout', | 119 parser.add_option('--timeout', dest = 'timeout', |
| 120 help = 'Amount of time (seconds) to wait before timeout', type = 'int', | 120 help = 'Amount of time (seconds) to wait before timeout', type = 'int', |
| 121 action = 'store', default=58) | 121 action = 'store', default=58) |
| 122 parser.add_option('--perf', dest = 'is_perf', | 122 parser.add_option('--mode', dest = 'mode', |
| 123 help = 'Add this flag if we are running a browser performance test', | 123 help = 'The type of test we are running', |
| 124 action = 'store_true', default=False) | 124 action = 'store', default='correctness') |
| 125 # TODO(vsm): Abstract this out better. | |
| 126 parser.add_option('--dromaeo', dest = 'is_dromaeo', | |
| 127 help = 'Add this flag if we are running a browser performance test', | |
| 128 action = 'store_true', default=False) | |
| 129 args, ignored = parser.parse_args(args=args) | 125 args, ignored = parser.parse_args(args=args) |
| 130 if args.is_perf: | 126 return args.out, args.browser, args.timeout, args.mode |
| 131 config = 'perf' | |
| 132 elif args.is_dromaeo: | |
| 133 config = 'dromaeo' | |
| 134 else: | |
| 135 config = 'correctness' | |
| 136 return args.out, args.browser, args.timeout, config | |
| 137 | 127 |
| 138 def start_browser(browser, html_out): | 128 def start_browser(browser, html_out): |
| 139 if browser == 'chrome': | 129 if browser == 'chrome': |
| 140 # Note: you need ChromeDriver *in your path* to run Chrome, in addition to | 130 # Note: you need ChromeDriver *in your path* to run Chrome, in addition to |
| 141 # installing Chrome. Also note that the build bot runs have a different path | 131 # installing Chrome. Also note that the build bot runs have a different path |
| 142 # from a normal user -- check the build logs. | 132 # from a normal user -- check the build logs. |
| 143 return selenium.webdriver.Chrome() | 133 return selenium.webdriver.Chrome() |
| 144 elif browser == 'ff': | 134 elif browser == 'ff': |
| 145 profile = selenium.webdriver.firefox.firefox_profile.FirefoxProfile() | 135 profile = selenium.webdriver.firefox.firefox_profile.FirefoxProfile() |
| 146 profile.set_preference('dom.max_script_run_time', 0) | 136 profile.set_preference('dom.max_script_run_time', 0) |
| (...skipping 30 matching lines...) Expand all Loading... |
| 177 | 167 |
| 178 # A timeout exception is thrown if nothing happens within the time limit. | 168 # A timeout exception is thrown if nothing happens within the time limit. |
| 179 if browser != 'chrome': | 169 if browser != 'chrome': |
| 180 browser.close() | 170 browser.close() |
| 181 try: | 171 try: |
| 182 browser.quit() | 172 browser.quit() |
| 183 except selenium.common.exceptions.WebDriverException: | 173 except selenium.common.exceptions.WebDriverException: |
| 184 # TODO(efortuna): Figure out why this crashes.... and avoid? | 174 # TODO(efortuna): Figure out why this crashes.... and avoid? |
| 185 pass | 175 pass |
| 186 | 176 |
| 187 def report_results(config, source): | 177 def report_results(mode, source): |
| 188 # TODO(vsm): Add a failure check for Dromaeo. | 178 # TODO(vsm): Add a failure check for Dromaeo. |
| 189 if config != 'correctness': | 179 if mode != 'correctness': |
| 190 # We're running a performance test. | 180 # We're running a performance test. |
| 191 print source.encode('utf8') | 181 print source.encode('utf8') |
| 192 sys.stdout.flush() | 182 sys.stdout.flush() |
| 193 if 'NaN' in source: | 183 if 'NaN' in source: |
| 194 return 1 | 184 return 1 |
| 195 else: | 185 else: |
| 196 return 0 | 186 return 0 |
| 197 else: | 187 else: |
| 198 # We're running a correctness test. Mark test as passing if all individual | 188 # We're running a correctness test. Mark test as passing if all individual |
| 199 # test cases pass. | 189 # test cases pass. |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 238 # TODO(jmesserly): It'd be nice to shutdown gracefully in the event of a | 228 # TODO(jmesserly): It'd be nice to shutdown gracefully in the event of a |
| 239 # SIGTERM. Unfortunately dart:io cannot send SIGTERM, see dartbug.com/1756. | 229 # SIGTERM. Unfortunately dart:io cannot send SIGTERM, see dartbug.com/1756. |
| 240 signal.signal(signal.SIGTERM, lambda number, frame: close_browser(browser)) | 230 signal.signal(signal.SIGTERM, lambda number, frame: close_browser(browser)) |
| 241 | 231 |
| 242 try: | 232 try: |
| 243 while True: | 233 while True: |
| 244 line = sys.stdin.readline() | 234 line = sys.stdin.readline() |
| 245 if line == '--terminate\n': | 235 if line == '--terminate\n': |
| 246 break | 236 break |
| 247 | 237 |
| 248 html_out, browser_name, timeout, config = parse_args(line.split()) | 238 html_out, browser_name, timeout, mode = parse_args(line.split()) |
| 249 | 239 |
| 250 # Sanity checks that test.dart is passing flags we can handle. | 240 # Sanity checks that test.dart is passing flags we can handle. |
| 251 if config != 'correctness': | 241 if mode != 'correctness': |
| 252 print 'Batch test runner not compatible with perf testing' | 242 print 'Batch test runner not compatible with perf testing' |
| 253 return 1 | 243 return 1 |
| 254 if browser and current_browser_name != browser_name: | 244 if browser and current_browser_name != browser_name: |
| 255 print('Batch test runner got multiple browsers: %s and %s' | 245 print('Batch test runner got multiple browsers: %s and %s' |
| 256 % (current_browser_name, browser_name)) | 246 % (current_browser_name, browser_name)) |
| 257 return 1 | 247 return 1 |
| 258 | 248 |
| 259 # Start the browser on the first run | 249 # Start the browser on the first run |
| 260 if browser is None: | 250 if browser is None: |
| 261 current_browser_name = browser_name | 251 current_browser_name = browser_name |
| 262 browser = start_browser(browser_name, html_out) | 252 browser = start_browser(browser_name, html_out) |
| 263 | 253 |
| 264 source = run_test_in_browser(browser, html_out, timeout, config) | 254 source = run_test_in_browser(browser, html_out, timeout, mode) |
| 265 | 255 |
| 266 # Test is done. Write end token to stderr and flush. | 256 # Test is done. Write end token to stderr and flush. |
| 267 sys.stderr.write('>>> EOF STDERR\n') | 257 sys.stderr.write('>>> EOF STDERR\n') |
| 268 sys.stderr.flush() | 258 sys.stderr.flush() |
| 269 | 259 |
| 270 # print one of: | 260 # print one of: |
| 271 # >>> TEST {PASS, FAIL, OK, CRASH, FAIL, TIMEOUT} | 261 # >>> TEST {PASS, FAIL, OK, CRASH, FAIL, TIMEOUT} |
| 272 status = report_results(config, source) | 262 status = report_results(mode, source) |
| 273 if status == 0: | 263 if status == 0: |
| 274 print '>>> TEST PASS' | 264 print '>>> TEST PASS' |
| 275 elif source == TIMEOUT_ERROR_MSG: | 265 elif source == TIMEOUT_ERROR_MSG: |
| 276 print '>>> TEST TIMEOUT' | 266 print '>>> TEST TIMEOUT' |
| 277 else: | 267 else: |
| 278 print '>>> TEST FAIL' | 268 print '>>> TEST FAIL' |
| 279 sys.stdout.flush() | 269 sys.stdout.flush() |
| 280 finally: | 270 finally: |
| 281 close_browser(browser) | 271 close_browser(browser) |
| 282 | 272 |
| 283 | 273 |
| 284 def main(args): | 274 def main(args): |
| 285 # Run in batch mode if the --batch flag is passed. | 275 # Run in batch mode if the --batch flag is passed. |
| 286 # TODO(jmesserly): reconcile with the existing args parsing | 276 # TODO(jmesserly): reconcile with the existing args parsing |
| 287 if '--batch' in args: | 277 if '--batch' in args: |
| 288 return run_batch_tests() | 278 return run_batch_tests() |
| 289 | 279 |
| 290 # Run a single test | 280 # Run a single test |
| 291 html_out, browser_name, timeout, config = parse_args() | 281 html_out, browser_name, timeout, mode = parse_args() |
| 292 browser = start_browser(browser_name, html_out) | 282 browser = start_browser(browser_name, html_out) |
| 293 | 283 |
| 294 try: | 284 try: |
| 295 output = run_test_in_browser(browser, html_out, timeout, config) | 285 output = run_test_in_browser(browser, html_out, timeout, mode) |
| 296 return report_results(config, output) | 286 return report_results(mode, output) |
| 297 finally: | 287 finally: |
| 298 close_browser(browser) | 288 close_browser(browser) |
| 299 | 289 |
| 300 if __name__ == "__main__": | 290 if __name__ == "__main__": |
| 301 sys.exit(main(sys.argv)) | 291 sys.exit(main(sys.argv)) |
| OLD | NEW |