Index: tools/testing/test_configuration.py |
diff --git a/tools/testing/test_configuration.py b/tools/testing/test_configuration.py |
index 75f3b54b094b2b5798ec30c5cd80b11fd789a8f1..f41b4832ead455ec0d4202dfcc61b30c4c2c722b 100644 |
--- a/tools/testing/test_configuration.py |
+++ b/tools/testing/test_configuration.py |
@@ -2,23 +2,19 @@ |
# 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. |
+"""Common Testconfiguration subclasses used to define a class of tests.""" |
+ |
import atexit |
import fileinput |
import os |
-import test |
-import platform |
import re |
import shutil |
-import sys |
-import tempfile |
-from testing import test_case |
+ |
import test |
+from testing import test_case |
import utils |
-from os.path import join, exists, basename |
- |
-import utils |
# Patterns for matching test options in .dart files. |
VM_OPTIONS_PATTERN = re.compile(r"// VMOptions=(.*)") |
@@ -26,10 +22,13 @@ VM_OPTIONS_PATTERN = re.compile(r"// VMOptions=(.*)") |
class Error(Exception): |
pass |
+ |
class TestConfigurationError(Error): |
pass |
+ |
class StandardTestConfiguration(test.TestConfiguration): |
+ """Configuration that looks for .dart files in the tests/*/src dirs.""" |
LEGAL_KINDS = set(['compile-time error', |
'runtime error', |
'static type error', |
@@ -38,24 +37,27 @@ class StandardTestConfiguration(test.TestConfiguration): |
def __init__(self, context, root): |
super(StandardTestConfiguration, self).__init__(context, root) |
- def _cleanup(self, tests): |
- if self.context.keep_temporary_files: return |
+ def _Cleanup(self, tests): |
+ """Remove any temporary files created by running the test.""" |
+ if self.context.keep_temporary_files: |
+ return |
dirs = [] |
for t in tests: |
- if t.run_arch != None: |
+ if t.run_arch: |
temp_dir = t.run_arch.temp_dir |
- if temp_dir != None: dirs.append(temp_dir) |
- |
- if len(dirs) == 0: return |
- if not utils.Daemonize(): return |
- |
+ if temp_dir: |
+ dirs.append(temp_dir) |
+ if not dirs: |
+ return |
+ if not utils.Daemonize(): |
+ return |
os.execlp('rm', *(['rm', '-rf'] + dirs)) |
- |
def CreateTestCases(self, test_path, path, filename, mode, arch): |
+ """Given a .dart filename, create a StandardTestCase from it.""" |
tags = {} |
- if filename.endswith(".dart"): |
+ if filename.endswith('.dart'): |
tags = self.SplitMultiTest(test_path, filename) |
if arch in ['dartium', 'chromium']: |
if tags: |
@@ -71,7 +73,10 @@ class StandardTestConfiguration(test.TestConfiguration): |
if not self.Contains(path, test_path + [tag]): |
continue |
tests.append(test_case.MultiTestCase(self.context, |
- test_path + [tag], test_source, kind, mode, arch)) |
+ test_path + [tag], |
+ test_source, |
+ kind, |
+ mode, arch)) |
else: |
# Look for VM specified as comments in the source file. If |
# several sets of VM options are specified create a separate |
@@ -90,29 +95,36 @@ class StandardTestConfiguration(test.TestConfiguration): |
return tests |
def ListTests(self, current_path, path, mode, arch): |
+ """Searches for *Test.dart files and returns list of TestCases.""" |
tests = [] |
- for root, dirs, files in os.walk(join(self.root, 'src')): |
+ for root, unused_dirs, files in os.walk(os.path.join(self.root, 'src')): |
for f in [x for x in files if self.IsTest(x)]: |
- if f.endswith(".dart"): |
- test_path = current_path + [ f[:-5] ] # Remove .dart suffix. |
- elif f.endswith(".app"): |
- test_path = current_path + [ f[:-4] ] # Remove .app suffix. |
+ if f.endswith('.dart'): |
+ test_path = current_path + [f[:-5]] # Remove .dart suffix. |
+ elif f.endswith('.app'): |
+ # TODO(zundel): .app files are used only the dromaeo test |
+ # and should be removed. |
+ test_path = current_path + [f[:-4]] # Remove .app suffix. |
if not self.Contains(path, test_path): |
continue |
- tests.extend(self.CreateTestCases(test_path, path, join(root, f), |
+ tests.extend(self.CreateTestCases(test_path, path, |
+ os.path.join(root, f), |
mode, arch)) |
- atexit.register(lambda: self._cleanup(tests)) |
+ atexit.register(lambda: self._Cleanup(tests)) |
return tests |
def IsTest(self, name): |
- return name.endswith('Test.dart') or name.endswith("Test.app") |
+ """Returns True if the file name is a test file.""" |
+ return name.endswith('Test.dart') or name.endswith('Test.app') |
def GetTestStatus(self, sections, defs): |
- status = join(self.root, basename(self.root) + '.status') |
- if exists(status): |
+ """Reads the .status file of the TestSuite.""" |
+ status = os.path.join(self.root, os.path.basename(self.root) + '.status') |
+ if os.path.exists(status): |
test.ReadConfigurationInto(status, sections, defs) |
def FindReferencedFiles(self, lines): |
+ """Scours the lines containing source code for include directives.""" |
referenced_files = [] |
for line in lines: |
m = re.match("#(source|import)\(['\"](.*)['\"]\);", line) |
@@ -121,19 +133,34 @@ class StandardTestConfiguration(test.TestConfiguration): |
return referenced_files |
def SplitMultiTest(self, test_path, filename): |
+ """Takes a file with multiple test case defined. |
+ |
+ Splits the file into multiple TestCase instances. |
+ |
+ Args: |
+ test_path: temporary dir to write split test case data. |
+ filename: name of the file to split. |
+ |
+ Returns: |
+ sequence of test cases split from file. |
+ |
+ Raises: |
+ TestConfigurationError: when a problem with the multi-test-case |
+ syntax is encountered. |
+ """ |
(name, extension) = os.path.splitext(os.path.basename(filename)) |
with open(filename, 'r') as s: |
source = s.read() |
lines = source.splitlines() |
tags = {} |
for line in lines: |
- (code, sep, info) = line.partition(' /// ') |
+ (unused_code, sep, info) = line.partition(' /// ') |
if sep: |
(tag, sep, kind) = info.partition(': ') |
- if tags.has_key(tag): |
- raise utils.Error('duplicated tag %s' % tag) |
+ if tag in tags: |
+ raise TestConfigurationError('duplicated tag %s' % tag) |
if kind not in StandardTestConfiguration.LEGAL_KINDS: |
- raise utils.Error('unrecognized kind %s' % kind) |
+ raise TestConfigurationError('unrecognized kind %s' % kind) |
tags[tag] = kind |
if not tags: |
return {} |
@@ -176,65 +203,29 @@ class StandardTestConfiguration(test.TestConfiguration): |
tests['none'] = ('', test_filename) |
return tests |
-class BrowserTestCase(test_case.StandardTestCase): |
- def __init__(self, context, path, filename, |
- fatal_static_type_errors, mode, arch): |
- super(test_case.BrowserTestCase, self).__init__(context, path, filename, mode, arch) |
- self.fatal_static_type_errors = fatal_static_type_errors |
- |
- def IsBatchable(self): |
- return True |
- |
- def Run(self): |
- command = self.run_arch.GetCompileCommand(self.fatal_static_type_errors) |
- if command != None: |
- # We change the directory where dartc will be launched because |
- # it is not predictable on the location of the compiled file. In |
- # case the test is a web test, we make sure the app file is not |
- # in a subdirectory. |
- cwd = None |
- if self.run_arch.is_web_test: cwd = self.run_arch.temp_dir |
- command = command[:1] + self.context.flags + command[1:] |
- test_output = self.RunCommand(command, cwd=cwd) |
- |
- # If errors were found, fail fast and show compile errors: |
- if test_output.output.exit_code != 0: |
- if not self.context.keep_temporary_files: |
- self.run_arch.Cleanup() |
- return test_output |
- |
- command = self.run_arch.GetRunCommand(); |
- test_output = self.RunCommand(command) |
- # The return value of DumpRenderedTree does not indicate test failing, but |
- # the output does. |
- if self.run_arch.HasFailed(test_output.output.stdout): |
- test_output.output.exit_code = 1 |
- |
- # TODO(ngeoffray): We run out of space on the build bots for these tests if |
- # the temp directories are not removed right after running the test. |
- if not self.context.keep_temporary_files: |
- self.run_arch.Cleanup() |
- |
- return test_output |
- |
class BrowserTestConfiguration(StandardTestConfiguration): |
+ """A configuration used to run tests inside a browser.""" |
+ |
def __init__(self, context, root, fatal_static_type_errors=False): |
super(BrowserTestConfiguration, self).__init__(context, root) |
self.fatal_static_type_errors = fatal_static_type_errors |
def ListTests(self, current_path, path, mode, arch): |
+ """Searches for *Test .dart files and returns list of TestCases.""" |
tests = [] |
- for root, dirs, files in os.walk(self.root): |
+ for root, unused_dirs, files in os.walk(self.root): |
for f in [x for x in files if self.IsTest(x)]: |
relative = os.path.relpath(root, self.root).split(os.path.sep) |
test_path = current_path + relative + [os.path.splitext(f)[0]] |
if not self.Contains(path, test_path): |
continue |
tests.append(test_case.BrowserTestCase(self.context, |
- test_path, join(root, f), self.fatal_static_type_errors, mode, |
- arch)) |
- atexit.register(lambda: self._cleanup(tests)) |
+ test_path, |
+ os.path.join(root, f), |
+ self.fatal_static_type_errors, |
+ mode, arch)) |
+ atexit.register(lambda: self._Cleanup(tests)) |
return tests |
def IsTest(self, name): |
@@ -242,14 +233,16 @@ class BrowserTestConfiguration(StandardTestConfiguration): |
class CompilationTestConfiguration(test.TestConfiguration): |
- """ Configuration that searches specific directories for apps to compile |
+ """Configuration that searches specific directories for apps to compile. |
- Expects a status file named dartc.status |
+ Expects a status file named dartc.status |
""" |
+ |
def __init__(self, context, root): |
super(CompilationTestConfiguration, self).__init__(context, root) |
def ListTests(self, current_path, path, mode, arch): |
+ """Searches for *Test.dart files and returns list of TestCases.""" |
tests = [] |
client_path = os.path.normpath(os.path.join(self.root, '..', '..')) |
@@ -261,32 +254,33 @@ class CompilationTestConfiguration(test.TestConfiguration): |
for f in files: |
filename = [os.path.basename(client_path)] |
filename.extend(root[len(client_path) + 1:].split(os.path.sep)) |
- filename.append(f) # Remove .lib or .app suffix. |
+ filename.append(f) # Remove .lib or .app suffix. |
test_path = current_path + filename |
test_dart_file = os.path.join(root, f) |
- if ((not self.Contains(path, test_path)) |
- or (not self.IsTest(test_dart_file))): |
+ if (not self.Contains(path, test_path) |
+ or not self.IsTest(test_dart_file)): |
continue |
tests.append(test_case.CompilationTestCase(test_path, |
- self.context, |
- test_dart_file, |
- mode, |
- arch)) |
- atexit.register(lambda: self._cleanup(tests)) |
+ self.context, |
+ test_dart_file, |
+ mode, |
+ arch)) |
+ atexit.register(lambda: self._Cleanup(tests)) |
return tests |
def SourceDirs(self): |
- """ Returns a list of directories to scan for files to compile """ |
+ """Returns a list of directories to scan for files to compile.""" |
raise TestConfigurationError( |
- "Subclasses must implement SourceDirs()") |
+ 'Subclasses must implement SourceDirs()') |
def IsTest(self, name): |
- if (not name.endswith('.dart')): |
+ """Returns True if name is a test case to be compiled.""" |
+ if not name.endswith('.dart'): |
return False |
- if (os.path.exists(name)): |
+ if os.path.exists(name): |
# TODO(dgrove): can we end reading the input early? |
for line in fileinput.input(name): |
- if (re.match('#', line)): |
+ if re.match('#', line): |
fileinput.close() |
return True |
fileinput.close() |
@@ -298,7 +292,7 @@ class CompilationTestConfiguration(test.TestConfiguration): |
if os.path.exists(status): |
test.ReadConfigurationInto(status, sections, defs) |
- def _cleanup(self, tests): |
+ def _Cleanup(self, tests): |
if not utils.Daemonize(): return |
os.execlp('rm', *(['rm', '-rf'] + [t.temp_dir for t in tests])) |
raise |