| 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)
|
|
|