Index: tools/testing/architecture.py |
diff --git a/tools/testing/architecture.py b/tools/testing/architecture.py |
deleted file mode 100755 |
index caf5c9acbac7d8f43ab775091bbb181b703c7bd8..0000000000000000000000000000000000000000 |
--- a/tools/testing/architecture.py |
+++ /dev/null |
@@ -1,605 +0,0 @@ |
-# Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
-# for details. All rights reserved. Use of this source code is governed by a |
-# BSD-style license that can be found in the LICENSE file. |
-# |
- |
-import os |
-import platform |
-import re |
-import shutil |
-import subprocess |
-import sys |
-import tempfile |
- |
-import utils |
- |
-OS_GUESS = utils.GuessOS() |
- |
-HTML_CONTENTS = """ |
-<html> |
-<head> |
- <title> Test %(title)s </title> |
- <style> |
- .unittest-table { font-family:monospace; border:1px; } |
- .unittest-pass { background: #6b3;} |
- .unittest-fail { background: #d55;} |
- .unittest-error { background: #a11;} |
- </style> |
-</head> |
-<body> |
- <h1> Running %(title)s </h1> |
- <script type="text/javascript" src="%(controller_script)s"></script> |
- <script type="text/javascript"> |
- // If nobody intercepts the error, finish the test. |
- onerror = function() { window.layoutTestController.notifyDone() }; |
- |
- document.onreadystatechange = function() { |
- if (document.readyState != "loaded") return; |
- // If 'startedDartTest' is not set, that means that the test did not have |
- // a chance to load. This will happen when a load error occurs in the VM. |
- // Give the machine time to start up. |
- setTimeout(function() { |
- // A window.postMessage might have been enqueued after this timeout. |
- // Just sleep another time to give the browser the time to process the |
- // posted message. |
- setTimeout(function() { |
- if (layoutTestController && !layoutTestController.startedDartTest) { |
- layoutTestController.notifyDone(); |
- } |
- }, 0); |
- }, 50); |
- }; |
- </script> |
- <script type="%(script_type)s" src="%(source_script)s"></script> |
-</body> |
-</html> |
-""" |
- |
-DART_TEST_AS_LIBRARY = """ |
-#library('test'); |
-#source('%(test)s'); |
-""" |
- |
-DART_CONTENTS = """ |
-#library('test'); |
- |
-#import('%(dom_library)s'); |
-#import('%(test_framework)s'); |
- |
-#import('%(library)s', prefix: "Test"); |
- |
-waitForDone() { |
- window.postMessage('unittest-suite-wait-for-done', '*'); |
-} |
- |
-pass() { |
- document.body.innerHTML = 'PASS'; |
- window.postMessage('unittest-suite-done', '*'); |
-} |
- |
-fail(e, trace) { |
- document.body.innerHTML = 'FAIL: $e, $trace'; |
- window.postMessage('unittest-suite-done', '*'); |
-} |
- |
-main() { |
- bool needsToWait = false; |
- bool mainIsFinished = false; |
- TestRunner.waitForDoneCallback = () { needsToWait = true; }; |
- TestRunner.doneCallback = () { |
- if (mainIsFinished) { |
- pass(); |
- } else { |
- needsToWait = false; |
- } |
- }; |
- try { |
- Test.main(); |
- if (needsToWait) { |
- waitForDone(); |
- } else { |
- pass(); |
- } |
- mainIsFinished = true; |
- } catch(var e, var trace) { |
- fail(e, trace); |
- } |
-} |
-""" |
- |
- |
-# Patterns for matching test options in .dart files. |
-DART_OPTIONS_PATTERN = re.compile(r'// DartOptions=(.*)') |
- |
-# Pattern for checking if the test is a web test. |
-DOM_IMPORT_PATTERN = re.compile(r'#import.*(dart:(dom|html)|html\.dart).*\);', |
- re.MULTILINE) |
- |
-# Pattern for matching the output of a browser test. |
-BROWSER_OUTPUT_PASS_PATTERN = re.compile(r'^Content-Type: text/plain\nPASS$', |
- re.MULTILINE) |
- |
-# Pattern for matching flaky errors of browser tests. xvfb-run by default uses |
-# DISPLAY=:99, we keep that in the error pattern to avoid matching real |
-# errors when DISPLAY is set incorrectly. |
-BROWSER_FLAKY_DISPLAY_ERR_PATTERN = re.compile( |
- r'Gtk-WARNING \*\*: cannot open display: :99', re.MULTILINE) |
- |
-# Pattern for checking if the test is a library in itself. |
-LIBRARY_DEFINITION_PATTERN = re.compile(r'^#library\(.*\);', |
- re.MULTILINE) |
-SOURCE_OR_IMPORT_PATTERN = re.compile(r'^#(source|import)\(.*\);', |
- re.MULTILINE) |
- |
- |
-class Error(Exception): |
- """Base class for exceptions in this module.""" |
- pass |
- |
- |
-def _IsWebTest(source): |
- """Returns True if the source includes a dart dom library #import.""" |
- return DOM_IMPORT_PATTERN.search(source) |
- |
- |
-def IsLibraryDefinition(test, source): |
- """Returns True if the source has a #library statement.""" |
- if LIBRARY_DEFINITION_PATTERN.search(source): |
- return True |
- if SOURCE_OR_IMPORT_PATTERN.search(source): |
- print ('WARNING for %s: Browser tests need a #library ' |
- 'for a file that #import or #source' % test) |
- return False |
- |
- |
-class Architecture(object): |
- """Definitions for different ways to test based on the component flag.""" |
- |
- def __init__(self, root_path, arch, mode, component, test): |
- self.root_path = root_path |
- self.arch = arch |
- self.mode = mode |
- self.component = component |
- self.test = test |
- self.build_root = utils.GetBuildRoot(OS_GUESS, self.mode, self.arch) |
- source = file(test).read() |
- self.vm_options = [] |
- self.dart_options = utils.ParseTestOptions(DART_OPTIONS_PATTERN, |
- source, |
- root_path) |
- self.is_web_test = _IsWebTest(source) |
- self.temp_dir = None |
- |
- def GetVMOption(self, option): |
- for flag in self.vm_options: |
- if flag.startswith('--%s=' % option): |
- return flag.split('=')[1] |
- return None |
- |
- def HasFatalTypeErrors(self): |
- """Returns True if this type of component supports --fatal-type-errors.""" |
- return False |
- |
- def GetTestFrameworkPath(self): |
- """Path to dart source (TestFramework.dart) for testing framework.""" |
- return os.path.join(self.root_path, 'tests', 'isolate', 'src', |
- 'TestFramework.dart') |
- |
- |
-class BrowserArchitecture(Architecture): |
- """Architecture that runs compiled dart->JS through a browser.""" |
- |
- def __init__(self, root_path, arch, mode, component, test): |
- super(BrowserArchitecture, self).__init__(root_path, arch, mode, component, |
- test) |
- self.temp_dir = tempfile.mkdtemp() |
- if not self.is_web_test: self.GenerateWebTestScript() |
- |
- def GetTestScriptFile(self): |
- """Returns the name of the .dart file to compile.""" |
- if self.is_web_test: return os.path.abspath(self.test) |
- return os.path.join(self.temp_dir, 'test.dart') |
- |
- def GetHtmlContents(self): |
- """Fills in the HTML_CONTENTS template with info for this architecture.""" |
- script_type = self.GetScriptType() |
- controller_path = os.path.join(self.root_path, 'client', 'testing', |
- 'unittest', 'test_controller.js') |
- return HTML_CONTENTS % { |
- 'title': self.test, |
- 'controller_script': controller_path, |
- 'script_type': script_type, |
- 'source_script': self.GetScriptPath() |
- } |
- |
- def GetHtmlPath(self): |
- """Creates a path for the generated .html file. |
- |
- Resources for web tests are relative to the 'html' file. We |
- output the 'html' file in the 'out' directory instead of the temporary |
- directory because we can easily go the the resources in 'client' through |
- 'out'. |
- |
- Returns: |
- Created path for the generated .html file. |
- """ |
- if self.is_web_test: |
- html_path = os.path.join(self.root_path, 'client', self.build_root) |
- if not os.path.exists(html_path): |
- os.makedirs(html_path) |
- return html_path |
- |
- return self.temp_dir |
- |
- def GetTestContents(self, library_file): |
- """Pastes a preamble on the front of the .dart file before testing.""" |
- unittest_path = os.path.join(self.root_path, 'client', 'testing', |
- 'unittest', 'unittest.dart') |
- |
- if self.component == 'chromium': |
- dom_path = os.path.join(self.root_path, 'client', 'testing', |
- 'unittest', 'dom_for_unittest.dart') |
- else: |
- dom_path = os.path.join('dart:dom') |
- |
- test_framework_path = self.GetTestFrameworkPath() |
- test_path = os.path.abspath(self.test) |
- |
- inputs = { |
- 'unittest': unittest_path, |
- 'test': test_path, |
- 'dom_library': dom_path, |
- 'test_framework': test_framework_path, |
- 'library': library_file |
- } |
- return DART_CONTENTS % inputs |
- |
- def GenerateWebTestScript(self): |
- """Creates a .dart file to run in the test.""" |
- if IsLibraryDefinition(self.test, file(self.test).read()): |
- library_file = os.path.abspath(self.test) |
- else: |
- library_file = 'test_as_library.dart' |
- test_as_library = DART_TEST_AS_LIBRARY % { |
- 'test': os.path.abspath(self.test) |
- } |
- test_as_library_file = os.path.join(self.temp_dir, library_file) |
- f = open(test_as_library_file, 'w') |
- f.write(test_as_library) |
- f.close() |
- |
- app_output_file = self.GetTestScriptFile() |
- f = open(app_output_file, 'w') |
- f.write(self.GetTestContents(library_file)) |
- f.close() |
- |
- def GetRunCommand(self, fatal_static_type_errors=False): |
- """Returns a command line to execute for the test.""" |
- fatal_static_type_errors = fatal_static_type_errors # shutup lint! |
- # Find DRT |
- # For some reason, DRT needs to be called via an absolute path |
- drt_location = self.GetVMOption('browser') |
- if drt_location is not None: |
- drt_location = os.path.abspath(drt_location) |
- else: |
- drt_location = os.path.join(self.root_path, 'client', 'tests', 'drt', |
- 'DumpRenderTree') |
- |
- # On Mac DumpRenderTree is a .app folder |
- if platform.system() == 'Darwin': |
- drt_location += '.app/Contents/MacOS/DumpRenderTree' |
- |
- drt_flags = ['--no-timeout'] |
- if len(self.vm_options) > 0: |
- dart_flags = '--dart-flags=' |
- dart_flags += ' '.join(self.vm_options) |
- drt_flags.append(dart_flags) |
- |
- html_output_file = os.path.join(self.GetHtmlPath(), self.GetHtmlName()) |
- f = open(html_output_file, 'w') |
- f.write(self.GetHtmlContents()) |
- f.close() |
- |
- drt_flags.append(html_output_file) |
- |
- return [drt_location] + drt_flags |
- |
- def HasFailed(self, output): |
- """Return True if the 'PASS' result string isn't in the output.""" |
- return not BROWSER_OUTPUT_PASS_PATTERN.search(output) |
- |
- def WasFlakyDrt(self, error): |
- """Return whether the error indicates a flaky error from running. |
- DumpRenderTree within xvfb-run. |
- """ |
- return BROWSER_FLAKY_DISPLAY_ERR_PATTERN.search(error) |
- |
- def RunTest(self, verbose): |
- """Calls GetRunCommand() and executes the returned commandline. |
- |
- Args: |
- verbose: if True, print additional diagnostics to stdout. |
- |
- Returns: |
- Return code from executable. 0 == PASS, 253 = CRASH, anything |
- else is treated as FAIL |
- """ |
- retcode = self.Compile() |
- if retcode != 0: return 1 |
- |
- command = self.GetRunCommand() |
- |
- unused_status, output, err = ExecutePipedCommand(command, verbose) |
- if not self.HasFailed(output): |
- return 0 |
- |
- # TODO(sigmund): print better error message, including how to run test |
- # locally, and translate error traces using source map info. |
- print '(FAIL) test page:\033[31m %s \033[0m' % command[2] |
- if verbose: |
- print 'Additional info: ' |
- print output |
- print err |
- return 1 |
- |
- def Cleanup(self): |
- """Removes temporary files created for the test.""" |
- if self.temp_dir: |
- shutil.rmtree(self.temp_dir) |
- self.temp_dir = None |
- |
- |
-class ChromiumArchitecture(BrowserArchitecture): |
- """Architecture that runs compiled dart->JS through a chromium DRT.""" |
- |
- def __init__(self, root_path, arch, mode, component, test): |
- super(ChromiumArchitecture, self).__init__(root_path, arch, mode, component, test) |
- |
- def GetScriptType(self): |
- return 'text/javascript' |
- |
- def GetScriptPath(self): |
- """Returns the name of the output .js file to create.""" |
- path = self.GetTestScriptFile() |
- return os.path.abspath(os.path.join(self.temp_dir, |
- os.path.basename(path) + '.js')) |
- |
- def GetHtmlName(self): |
- """Returns the name of the output .html file to create.""" |
- relpath = os.path.relpath(self.test, self.root_path) |
- return relpath.replace(os.sep, '_') + '.html' |
- |
- def Compile(self): |
- return ExecuteCommand(self.GetCompileCommand()) |
- |
-class DartcChromiumArchitecture(ChromiumArchitecture): |
- """ChromiumArchitecture that compiles code using dartc.""" |
- |
- def __init__(self, root_path, arch, mode, component, test): |
- super(DartcChromiumArchitecture, self).__init__( |
- root_path, arch, mode, component, test) |
- |
- def GetCompileCommand(self, fatal_static_type_errors=False): |
- """Returns cmdline as an array to invoke the compiler on this test.""" |
- |
- # We need an absolute path because the compilation will run |
- # in a temporary directory. |
- build_root = utils.GetBuildRoot(OS_GUESS, self.mode, 'ia32') |
- dartc = os.path.abspath(os.path.join(build_root, 'compiler', 'bin', |
- 'dartc')) |
- if utils.IsWindows(): dartc += '.exe' |
- cmd = [dartc, '--work', self.temp_dir] |
- if self.mode == 'release': |
- cmd += ['--optimize'] |
- cmd += self.vm_options |
- cmd += ['--out', self.GetScriptPath()] |
- if fatal_static_type_errors: |
- # TODO(zundel): update to --fatal_type_errors for both VM and Compiler |
- cmd.append('-fatal-type-errors') |
- cmd.append(self.GetTestScriptFile()) |
- return cmd |
- |
- |
-class FrogChromiumArchitecture(ChromiumArchitecture): |
- """ChromiumArchitecture that compiles code using frog.""" |
- |
- def __init__(self, root_path, arch, mode, component, test): |
- super(FrogChromiumArchitecture, self).__init__( |
- root_path, arch, mode, component, test) |
- |
- def GetCompileCommand(self, fatal_static_type_errors=False): |
- """Returns cmdline as an array to invoke the compiler on this test.""" |
- |
- # Get a frog executable from the command line. Default to frogsh. |
- # We need an absolute path because the compilation will run |
- # in a temporary directory. |
- frog = self.GetVMOption('frog') |
- if frog is not None: |
- frog = os.path.abspath(frog) |
- else: |
- frog = os.path.abspath(utils.GetDartRunner(self.mode, self.arch, 'frogsh')) |
- frog_libdir = self.GetVMOption('froglib') |
- if frog_libdir is not None: |
- frog_libdir = os.path.abspath(frog_libdir) |
- else: |
- frog_libdir = os.path.abspath(os.path.join(self.root_path, 'frog', 'lib')) |
- cmd = [frog, |
- '--libdir=%s' % frog_libdir, |
- '--compile-only', |
- '--out=%s' % self.GetScriptPath()] |
- cmd.extend(self.vm_options) |
- cmd.append(self.GetTestScriptFile()) |
- return cmd |
- |
- |
-class DartiumArchitecture(BrowserArchitecture): |
- """Architecture that runs dart in an VM embedded in DumpRenderTree.""" |
- |
- def __init__(self, root_path, arch, mode, component, test): |
- super(DartiumArchitecture, self).__init__(root_path, arch, mode, component, test) |
- |
- def GetScriptType(self): |
- return 'application/dart' |
- |
- def GetScriptPath(self): |
- return 'file:///' + self.GetTestScriptFile() |
- |
- def GetHtmlName(self): |
- path = os.path.relpath(self.test, self.root_path).replace(os.sep, '_') |
- return path + '.dartium.html' |
- |
- def GetCompileCommand(self, fatal_static_type_errors=False): |
- fatal_static_type_errors = fatal_static_type_errors # shutup lint! |
- return None |
- |
- def Compile(self): |
- return 0 |
- |
- |
-class WebDriverArchitecture(FrogChromiumArchitecture): |
- """Architecture that runs compiled dart->JS (via frog) through a variety of |
- real browsers using WebDriver.""" |
- |
- def __init__(self, root_path, arch, mode, component, test): |
- super(WebDriverArchitecture, self).__init__(root_path, arch, mode, |
- component, test) |
- |
- def GetRunCommand(self, fatal_static_type_errors=False): |
- """Returns a command line to execute for the test.""" |
- flags = self.vm_options |
- browser_flag = 'chrome' |
- if 'ff' in flags or 'firefox' in flags: |
- browser_flag = 'ff' |
- elif 'ie' in flags or 'explorer' in flags or 'internet-explorer' in flags: |
- browser_flag = 'ie' |
- elif 'safari' in flags: |
- browser_flag = 'safari' |
- |
- selenium_location = os.path.join(self.root_path, 'tools', 'testing', |
- 'run_selenium.py') |
- |
- html_output_file = os.path.join(self.GetHtmlPath(), self.GetHtmlName()) |
- f = open(html_output_file, 'w') |
- f.write(self.GetHtmlContents()) |
- f.close() |
- return [selenium_location, '--out', html_output_file, '--browser', |
- browser_flag] |
- |
- |
-class StandaloneArchitecture(Architecture): |
- """Base class for architectures that run tests without a browser.""" |
- |
- def __init__(self, root_path, arch, mode, component, test): |
- super(StandaloneArchitecture, self).__init__(root_path, arch, mode, component, |
- test) |
- |
- def GetExecutable(self): |
- """Returns the path to the Dart test runner (executes the .dart file).""" |
- return utils.GetDartRunner(self.mode, self.arch, self.component) |
- |
- |
- def GetCompileCommand(self, fatal_static_type_errors=False): |
- fatal_static_type_errors = fatal_static_type_errors # shutup lint! |
- return None |
- |
- def GetOptions(self): |
- return [] |
- |
- def GetRunCommand(self, fatal_static_type_errors=False): |
- """Returns a command line to execute for the test.""" |
- dart = self.GetExecutable() |
- command = [dart] + self.GetOptions() + self.vm_options |
- if fatal_static_type_errors: |
- command += self.GetFatalTypeErrorsFlags() |
- |
- if self.dart_options: |
- command += self.dart_options |
- else: |
- command += [self.test] |
- |
- return command |
- |
- def GetFatalTypeErrorsFlags(self): |
- return [] |
- |
- def RunTest(self, verbose): |
- command = self.GetRunCommand() |
- return ExecuteCommand(command, verbose) |
- |
- def Cleanup(self): |
- return |
- |
- |
-class LegArchitecture(StandaloneArchitecture): |
- |
- def __init__(self, root_path, arch, mode, component, test): |
- super(LegArchitecture, self).__init__(root_path, arch, mode, component, |
- test) |
- def GetOptions(self): |
- return ['--leg_only'] |
- |
- def GetExecutable(self): |
- """Returns the path to the Dart test runner (executes the .dart file).""" |
- return utils.GetDartRunner(self.mode, self.arch, 'frog') |
- |
- |
-# Long term, we should do the running machinery that is currently in |
-# DartRunner.java |
-class DartcArchitecture(StandaloneArchitecture): |
- """Runs the Dart ->JS compiler then runs the result in a standalone JS VM.""" |
- |
- def __init__(self, root_path, arch, mode, component, test): |
- super(DartcArchitecture, self).__init__(root_path, arch, mode, component, test) |
- |
- def GetOptions(self): |
- if self.mode == 'release': return ['--optimize'] |
- return [] |
- |
- def GetFatalTypeErrorsFlags(self): |
- return ['--fatal-type-errors'] |
- |
- def HasFatalTypeErrors(self): |
- return True |
- |
- |
-def ExecutePipedCommand(cmd, verbose): |
- """Execute a command in a subprocess.""" |
- if verbose: |
- print 'Executing: ' + ' '.join(cmd) |
- pipe = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) |
- (output, err) = pipe.communicate() |
- if pipe.returncode != 0 and verbose: |
- print 'Execution failed: ' + output + '\n' + err |
- print output |
- print err |
- return pipe.returncode, output, err |
- |
- |
-def ExecuteCommand(cmd, verbose=False): |
- """Execute a command in a subprocess.""" |
- if verbose: print 'Executing: ' + ' '.join(cmd) |
- return subprocess.call(cmd) |
- |
- |
-def GetArchitecture(arch, mode, component, test): |
- root_path = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), '..')) |
- if component == 'chromium': |
- return DartcChromiumArchitecture(root_path, arch, mode, component, test) |
- |
- elif component == 'dartium': |
- return DartiumArchitecture(root_path, arch, mode, component, test) |
- |
- elif component == 'frogium': |
- return FrogChromiumArchitecture(root_path, arch, mode, component, test) |
- |
- elif component == 'webdriver': |
- return WebDriverArchitecture(root_path, arch, mode, component, test) |
- |
- elif component in ['vm', 'frog', 'frogsh']: |
- return StandaloneArchitecture(root_path, arch, mode, component, test) |
- |
- elif component == 'leg': |
- return LegArchitecture(root_path, arch, mode, component, test) |
- |
- elif component == 'dartc': |
- return DartcArchitecture(root_path, arch, mode, component, test) |