summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/__init__.py1
-rw-r--r--test/backtest.py33
-rw-r--r--test/backunittest.py93
-rw-r--r--test/coverage_coverage.py113
-rw-r--r--test/coveragetest.py304
-rw-r--r--test/farm/annotate/run_multi.py2
-rw-r--r--test/farm/html/gold_a/a.html91
-rw-r--r--test/farm/html/gold_a/index.html82
-rw-r--r--test/farm/html/gold_a/jquery-1.3.2.min.js19
-rw-r--r--test/farm/html/gold_a/style.css182
-rw-r--r--test/farm/html/gold_b_branch/b.html113
-rw-r--r--test/farm/html/gold_b_branch/index.html81
-rw-r--r--test/farm/html/gold_omit_1/index.html99
-rw-r--r--test/farm/html/gold_omit_1/m1.html59
-rw-r--r--test/farm/html/gold_omit_1/m2.html59
-rw-r--r--test/farm/html/gold_omit_1/m3.html59
-rw-r--r--test/farm/html/gold_omit_1/main.html75
-rw-r--r--test/farm/html/gold_omit_2/index.html90
-rw-r--r--test/farm/html/gold_omit_2/m2.html59
-rw-r--r--test/farm/html/gold_omit_2/m3.html59
-rw-r--r--test/farm/html/gold_omit_2/main.html75
-rw-r--r--test/farm/html/gold_omit_3/index.html81
-rw-r--r--test/farm/html/gold_omit_3/m3.html59
-rw-r--r--test/farm/html/gold_omit_3/main.html75
-rw-r--r--test/farm/html/gold_omit_4/index.html90
-rw-r--r--test/farm/html/gold_omit_4/m1.html59
-rw-r--r--test/farm/html/gold_omit_4/m3.html59
-rw-r--r--test/farm/html/gold_omit_4/main.html75
-rw-r--r--test/farm/html/gold_omit_5/index.html81
-rw-r--r--test/farm/html/gold_omit_5/m1.html59
-rw-r--r--test/farm/html/gold_omit_5/main.html75
-rw-r--r--test/farm/html/gold_other/blah_blah_other.html81
-rw-r--r--test/farm/html/gold_other/here.html95
-rw-r--r--test/farm/html/gold_other/index.html100
-rw-r--r--test/farm/html/gold_other/jquery-1.3.2.min.js19
-rw-r--r--test/farm/html/gold_other/style.css195
-rw-r--r--test/farm/html/gold_x_xml/coverage.xml2
-rw-r--r--test/farm/html/gold_y_xml_branch/coverage.xml22
-rw-r--r--test/farm/html/run_a.py10
-rw-r--r--test/farm/html/run_a_xml_1.py (renamed from test/farm/html/run_x_xml.py)14
-rw-r--r--test/farm/html/run_a_xml_2.py20
-rw-r--r--test/farm/html/run_b_branch.py28
-rw-r--r--test/farm/html/run_omit_1.py12
-rw-r--r--test/farm/html/run_omit_2.py12
-rw-r--r--test/farm/html/run_omit_3.py12
-rw-r--r--test/farm/html/run_omit_4.py12
-rw-r--r--test/farm/html/run_omit_5.py12
-rw-r--r--test/farm/html/run_other.py12
-rw-r--r--test/farm/html/run_tabbed.py10
-rw-r--r--test/farm/html/run_y_xml_branch.py20
-rw-r--r--test/farm/html/src/b.py28
-rw-r--r--test/farm/html/src/coverage.xml20
-rw-r--r--test/farm/html/src/m1.py2
-rw-r--r--test/farm/html/src/m2.py2
-rw-r--r--test/farm/html/src/m3.py2
-rw-r--r--test/farm/html/src/main.py10
-rw-r--r--test/farm/html/src/omit4.ini2
-rw-r--r--test/farm/html/src/omit5.ini8
-rw-r--r--test/farm/html/src/run_a_xml_2.ini3
-rw-r--r--test/farm/html/src/tabbed.py2
-rw-r--r--test/farm/html/src/x.py7
-rw-r--r--test/farm/html/src/y.py9
-rw-r--r--test/farm/run/run_xxx.py2
-rw-r--r--test/modules/aa/afile.odd.py1
-rw-r--r--test/modules/aa/bb.odd/bfile.py1
-rw-r--r--test/modules/aa/bb/bfile.odd.py1
-rw-r--r--test/osinfo.py69
-rw-r--r--test/stress_phystoken.tok (renamed from test/stress_phystoken.txt)21
-rw-r--r--test/stress_phystoken_dos.tok52
-rw-r--r--test/test_api.py192
-rw-r--r--test/test_arcs.py78
-rw-r--r--test/test_cmdline.py333
-rw-r--r--test/test_codeunit.py25
-rw-r--r--test/test_config.py147
-rw-r--r--test/test_coverage.py601
-rw-r--r--test/test_data.py44
-rw-r--r--test/test_execfile.py18
-rw-r--r--test/test_farm.py128
-rw-r--r--test/test_files.py35
-rw-r--r--test/test_oddball.py284
-rw-r--r--test/test_parser.py49
-rw-r--r--test/test_phystokens.py12
-rw-r--r--test/test_process.py245
-rw-r--r--test/test_results.py4
-rw-r--r--test/test_summary.py62
-rw-r--r--test/test_templite.py28
-rw-r--r--test/test_testing.py103
87 files changed, 4279 insertions, 1500 deletions
diff --git a/test/__init__.py b/test/__init__.py
index e69de29b..5a0e30f4 100644
--- a/test/__init__.py
+++ b/test/__init__.py
@@ -0,0 +1 @@
+"""Automated tests. Run with nosetests."""
diff --git a/test/backtest.py b/test/backtest.py
index 21a14d6d..05a1e142 100644
--- a/test/backtest.py
+++ b/test/backtest.py
@@ -4,46 +4,41 @@
# (Redefining built-in blah)
# The whole point of this file is to redefine built-ins, so shut up about it.
-import os, sys
+import os
# Py2k and 3k don't agree on how to run commands in a subprocess.
try:
import subprocess
except ImportError:
- def run_command(cmd):
+ def run_command(cmd, status=0):
"""Run a command in a subprocess.
-
- Returns the exit code and the combined stdout and stderr.
-
+
+ Returns the exit status code and the combined stdout and stderr.
+
"""
_, stdouterr = os.popen4(cmd)
- return 0, stdouterr.read()
+ return status, stdouterr.read()
else:
- def run_command(cmd):
+ def run_command(cmd, status=0):
"""Run a command in a subprocess.
-
- Returns the exit code and the combined stdout and stderr.
-
- """
- if sys.hexversion > 0x03000000 and cmd.startswith("coverage "):
- # We don't have a coverage command on 3.x, so fix it up to call the
- # script. Eventually we won't need this.
- cmd = "python " + sys.prefix + os.sep + "Scripts" + os.sep + cmd
+ Returns the exit status code and the combined stdout and stderr.
+
+ """
proc = subprocess.Popen(cmd, shell=True,
stdin=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.STDOUT
)
- retcode = proc.wait()
-
+ status = proc.wait()
+
# Get the output, and canonicalize it to strings with newlines.
output = proc.stdout.read()
if not isinstance(output, str):
output = output.decode('utf-8')
output = output.replace('\r', '')
-
- return retcode, output
+
+ return status, output
# No more execfile in Py3k
try:
diff --git a/test/backunittest.py b/test/backunittest.py
new file mode 100644
index 00000000..f606185f
--- /dev/null
+++ b/test/backunittest.py
@@ -0,0 +1,93 @@
+"""Implementations of unittest features from the future."""
+
+import difflib, re, sys, unittest
+
+from coverage.backward import set # pylint: disable-msg=W0622
+
+
+def _need(method):
+ """Do we need to define our own `method` method?"""
+ return not hasattr(unittest.TestCase, method)
+
+
+class TestCase(unittest.TestCase):
+ """Just like unittest.TestCase, but with assert methods added.
+
+ Designed to be compatible with 3.1 unittest. Methods are only defined if
+ the builtin `unittest` doesn't have them.
+
+ """
+ if _need('assertTrue'):
+ def assertTrue(self, exp, msg=None):
+ """Assert that `exp` is true."""
+ if not exp:
+ self.fail(msg)
+
+ if _need('assertFalse'):
+ def assertFalse(self, exp, msg=None):
+ """Assert that `exp` is false."""
+ if exp:
+ self.fail(msg)
+
+ if _need('assertRaisesRegexp'):
+ def assertRaisesRegexp(self, excClass, regexp, callobj, *args, **kw):
+ """ Just like unittest.TestCase.assertRaises,
+ but checks that the message is right too.
+ """
+ try:
+ callobj(*args, **kw)
+ except excClass:
+ _, exc, _ = sys.exc_info()
+ excMsg = str(exc)
+ if re.search(regexp, excMsg):
+ # Message provided, and we got the right one: it passes.
+ return
+ else:
+ # Message provided, and it didn't match: fail!
+ raise self.failureException(
+ "Right exception, wrong message: "
+ "'%s' doesn't match '%s'" % (excMsg, regexp)
+ )
+ # No need to catch other exceptions: They'll fail the test all by
+ # themselves!
+ else:
+ if hasattr(excClass, '__name__'):
+ excName = excClass.__name__
+ else:
+ excName = str(excClass)
+ raise self.failureException(
+ "Expected to raise %s, didn't get an exception at all" %
+ excName
+ )
+
+ if _need('assertSameElements'):
+ def assertSameElements(self, s1, s2):
+ """Assert that the two arguments are equal as sets."""
+ self.assertEqual(set(s1), set(s2))
+
+ if _need('assertRegexpMatches'):
+ def assertRegexpMatches(self, s, regex):
+ """Assert that `s` matches `regex`."""
+ m = re.search(regex, s)
+ if not m:
+ raise self.failureException("%r doesn't match %r" % (s, regex))
+
+ if _need('assertMultiLineEqual'):
+ def assertMultiLineEqual(self, first, second, msg=None):
+ """Assert that two multi-line strings are equal.
+
+ If they aren't, show a nice diff.
+
+ """
+ # Adapted from Py3.1 unittest.
+ self.assertTrue(isinstance(first, str),
+ 'First argument is not a string')
+ self.assertTrue(isinstance(second, str),
+ 'Second argument is not a string')
+
+ if first != second:
+ message = ''.join(difflib.ndiff(first.splitlines(True),
+ second.splitlines(True)))
+ if msg:
+ message += " : " + msg
+ self.fail("Multi-line strings are unequal:\n" + message)
diff --git a/test/coverage_coverage.py b/test/coverage_coverage.py
index 1a5cc9c4..1e1cba02 100644
--- a/test/coverage_coverage.py
+++ b/test/coverage_coverage.py
@@ -1,44 +1,85 @@
-"""Coverage-test Coverage itself."""
+"""Coverage-test Coverage.py itself.
+
+Run as:
+
+ $ python test/coverage_coverage.py run [NOSE_ARGS]
+
+to run and collect coverage, then:
+
+ $ python test/coverage_coverage.py report
+
+to put the HTML report into the htmlcov directory.
+
+"""
-import coverage
import os, shutil, sys
+import nose
HTML_DIR = "htmlcov"
-if os.path.exists(HTML_DIR):
- shutil.rmtree(HTML_DIR)
-
-cov = coverage.coverage()
-# Cheap trick: the coverage code itself is excluded from measurement, but if
-# we clobber the cover_prefix in the coverage object, we can defeat the
-# self-detection.
-cov.cover_prefix = "Please measure coverage.py!"
-cov.erase()
-cov.start()
-
-# Re-import coverage to get it coverage tested! I don't understand all the
-# mechanics here, but if I don't carry over the imported modules (in covmods),
-# then things go haywire (os == None eventually).
-covmods = {}
-covdir = os.path.split(coverage.__file__)
-for name, mod in sys.modules.items():
- if name.startswith('coverage'):
- if hasattr(mod, '__file__') and mod.__file__.startswith(covdir):
- covmods[name] = mod
- del sys.modules[name]
-import coverage # don't warn about re-import: pylint: disable-msg=W0404
-sys.modules.update(covmods)
-
-# Run nosetests, with the arguments from our command line.
-import nose
-nose.run(sys.argv[1:])
+def run_tests_with_coverage():
+ """Run the test suite with coverage measuring itself."""
+ import coverage
+
+ tracer = os.environ.get('COVERAGE_TEST_TRACER', 'c')
+ version = "%s%s" % sys.version_info[:2]
+ suffix = "%s_%s" % (version, tracer)
+
+ cov = coverage.coverage(config_file="covcov.ini", data_suffix=suffix)
+ # Cheap trick: the coverage code itself is excluded from measurement, but
+ # if we clobber the cover_prefix in the coverage object, we can defeat the
+ # self-detection.
+ cov.cover_prefix = "Please measure coverage.py!"
+ cov.erase()
+ cov.start()
+
+ # Re-import coverage to get it coverage tested! I don't understand all the
+ # mechanics here, but if I don't carry over the imported modules (in
+ # covmods), then things go haywire (os == None, eventually).
+ covmods = {}
+ covdir = os.path.split(coverage.__file__)[0]
+ # We have to make a list since we'll be deleting in the loop.
+ modules = list(sys.modules.items())
+ for name, mod in modules:
+ if name.startswith('coverage'):
+ if hasattr(mod, '__file__') and mod.__file__.startswith(covdir):
+ covmods[name] = mod
+ del sys.modules[name]
+ import coverage # don't warn about re-import: pylint: disable-msg=W0404
+ sys.modules.update(covmods)
+
+ # Run nosetests, with the arguments from our command line.
+ print(":: Running nosetests %s" % " ".join(sys.argv[1:]))
+ nose.run()
+
+ cov.stop()
+ print(":: Saving .coverage%s" % suffix)
+ cov.save()
+
+def report_on_combined_files():
+ """Combine all the .coverage files and make an HTML report."""
+ if os.path.exists(HTML_DIR):
+ shutil.rmtree(HTML_DIR)
+
+ print(":: Writing HTML report to %s/index.html" % HTML_DIR)
+ import coverage
+ cov = coverage.coverage(config_file="covcov.ini")
+ cov.combine()
+ cov.save()
+ cov.html_report(directory=HTML_DIR)
-cov.stop()
-cov.save()
-cov.clear_exclude()
-cov.exclude("#pragma: no cover")
-cov.exclude("def __repr__")
-cov.exclude("if __name__ == .__main__.:")
+try:
+ cmd = sys.argv[1]
+except IndexError:
+ cmd = ''
-cov.html_report(directory=HTML_DIR, ignore_errors=True)
+if cmd == 'run':
+ # Ugly hack: nose.run reads sys.argv directly, so here I delete my command
+ # argument so that sys.argv is left as just nose arguments.
+ del sys.argv[1]
+ run_tests_with_coverage()
+elif cmd == 'report':
+ report_on_combined_files()
+else:
+ print("Need 'run' or 'report'")
diff --git a/test/coveragetest.py b/test/coveragetest.py
index d1631a3d..9b85b034 100644
--- a/test/coveragetest.py
+++ b/test/coveragetest.py
@@ -1,11 +1,11 @@
"""Base test case class for coverage testing."""
-import imp, os, random, re, shutil, sys, tempfile, textwrap, unittest
+import imp, os, random, shlex, shutil, sys, tempfile, textwrap
import coverage
-from coverage.backward import set, sorted, StringIO # pylint: disable-msg=W0622
+from coverage.backward import sorted, StringIO # pylint: disable-msg=W0622
from backtest import run_command
-
+from backunittest import TestCase
class Tee(object):
"""A file-like that writes to all the file-likes it has."""
@@ -13,18 +13,21 @@ class Tee(object):
def __init__(self, *files):
"""Make a Tee that writes to all the files in `files.`"""
self.files = files
-
+
def write(self, data):
"""Write `data` to all the files."""
for f in self.files:
f.write(data)
-class CoverageTest(unittest.TestCase):
+# Status returns for the command line.
+OK, ERR = 0, 1
+
+class CoverageTest(TestCase):
"""A base class for Coverage test cases."""
run_in_temp_dir = True
-
+
def setUp(self):
if self.run_in_temp_dir:
# Create a temporary directory.
@@ -34,49 +37,106 @@ class CoverageTest(unittest.TestCase):
os.makedirs(self.temp_dir)
self.old_dir = os.getcwd()
os.chdir(self.temp_dir)
-
- # Preserve changes to PYTHONPATH.
- self.old_pypath = os.environ.get('PYTHONPATH', '')
-
+
+
# Modules should be importable from this temp directory.
self.old_syspath = sys.path[:]
sys.path.insert(0, '')
-
+
# Keep a counter to make every call to check_coverage unique.
self.n = 0
- # Use a Tee to capture stdout.
+ # Record environment variables that we changed with set_environ.
+ self.environ_undos = {}
+
+ # Capture stdout and stderr so we can examine them in tests.
+ # nose keeps stdout from littering the screen, so we can safely Tee it,
+ # but it doesn't capture stderr, so we don't want to Tee stderr to the
+ # real stderr, since it will interfere with our nice field of dots.
self.old_stdout = sys.stdout
self.captured_stdout = StringIO()
sys.stdout = Tee(sys.stdout, self.captured_stdout)
-
+ self.old_stderr = sys.stderr
+ self.captured_stderr = StringIO()
+ sys.stderr = self.captured_stderr
+
+ # Record sys.modules here so we can restore it in tearDown.
+ self.old_modules = dict(sys.modules)
+
def tearDown(self):
if self.run_in_temp_dir:
- # Restore the original sys.path and PYTHONPATH
+ # Restore the original sys.path.
sys.path = self.old_syspath
- os.environ['PYTHONPATH'] = self.old_pypath
-
+
# Get rid of the temporary directory.
os.chdir(self.old_dir)
shutil.rmtree(self.temp_root)
-
- # Restore stdout.
+
+ # Restore the environment.
+ self.undo_environ()
+
+ # Restore stdout and stderr
sys.stdout = self.old_stdout
+ sys.stderr = self.old_stderr
+
+ # Remove any new modules imported during the test run. This lets us
+ # import the same source files for more than one test.
+ for m in [m for m in sys.modules if m not in self.old_modules]:
+ del sys.modules[m]
+
+ def set_environ(self, name, value):
+ """Set an environment variable `name` to be `value`.
+
+ The environment variable is set, and record is kept that it was set,
+ so that `tearDown` can restore its original value.
+
+ """
+ if name not in self.environ_undos:
+ self.environ_undos[name] = os.environ.get(name)
+ os.environ[name] = value
+
+ def original_environ(self, name, if_missing=None):
+ """The environment variable `name` from when the test started."""
+ if name in self.environ_undos:
+ ret = self.environ_undos[name]
+ else:
+ ret = os.environ.get(name)
+ if ret is None:
+ ret = if_missing
+ return ret
+
+ def undo_environ(self):
+ """Undo all the changes made by `set_environ`."""
+ for name, value in self.environ_undos.items():
+ if value is None:
+ del os.environ[name]
+ else:
+ os.environ[name] = value
def stdout(self):
"""Return the data written to stdout during the test."""
return self.captured_stdout.getvalue()
+ def stderr(self):
+ """Return the data written to stderr during the test."""
+ return self.captured_stderr.getvalue()
+
def make_file(self, filename, text):
"""Create a temp file.
-
- `filename` is the file name, and `text` is the content.
-
+
+ `filename` is the path to the file, including directories if desired,
+ and `text` is the content.
+
"""
# Tests that call `make_file` should be run in a temp environment.
assert self.run_in_temp_dir
text = textwrap.dedent(text)
-
+
+ # Make sure the directories are available.
+ dirs, _ = os.path.split(filename)
+ if dirs and not os.path.exists(dirs):
+ os.makedirs(dirs)
+
# Create the file.
f = open(filename, 'w')
f.write(text)
@@ -86,7 +146,7 @@ class CoverageTest(unittest.TestCase):
"""Import the module named modname, and return the module object."""
modfile = modname + '.py'
f = open(modfile, 'r')
-
+
for suff in imp.get_suffixes():
if suff[0] == '.py':
break
@@ -107,49 +167,73 @@ class CoverageTest(unittest.TestCase):
modname = 'coverage_test_' + self.noise + str(self.n)
self.n += 1
return modname
-
+
# Map chars to numbers for arcz_to_arcs
_arcz_map = {'.': -1}
_arcz_map.update(dict([(c, ord(c)-ord('0')) for c in '123456789']))
_arcz_map.update(dict(
[(c, 10+ord(c)-ord('A')) for c in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ']
))
-
+
def arcz_to_arcs(self, arcz):
"""Convert a compact textual representation of arcs to a list of pairs.
-
+
The text has space-separated pairs of letters. Period is -1, 1-9 are
1-9, A-Z are 10 through 36. The resulting list is sorted regardless of
the order of the input pairs.
-
+
".1 12 2." --> [(-1,1), (1,2), (2,-1)]
-
+
+ Minus signs can be included in the pairs:
+
+ "-11, 12, 2-5" --> [(-1,1), (1,2), (2,-5)]
+
"""
arcs = []
- for a,b in arcz.split():
- arcs.append((self._arcz_map[a], self._arcz_map[b]))
+ for pair in arcz.split():
+ asgn = bsgn = 1
+ if len(pair) == 2:
+ a,b = pair
+ else:
+ assert len(pair) == 3
+ if pair[0] == '-':
+ _,a,b = pair
+ asgn = -1
+ else:
+ assert pair[1] == '-'
+ a,_,b = pair
+ bsgn = -1
+ arcs.append((asgn*self._arcz_map[a], bsgn*self._arcz_map[b]))
return sorted(arcs)
+ def assertEqualArcs(self, a1, a2, msg=None):
+ """Assert that the arc lists `a1` and `a2` are equal."""
+ # Make them into multi-line strings so we can see what's going wrong.
+ s1 = "\n".join([repr(a) for a in a1]) + "\n"
+ s2 = "\n".join([repr(a) for a in a2]) + "\n"
+ self.assertMultiLineEqual(s1, s2, msg)
+
def check_coverage(self, text, lines=None, missing="", excludes=None,
report="", arcz=None, arcz_missing="", arcz_unpredicted=""):
"""Check the coverage measurement of `text`.
-
+
The source `text` is run and measured. `lines` are the line numbers
- that are executable, `missing` are the lines not executed, `excludes`
- are regexes to match against for excluding lines, and `report` is
- the text of the measurement report.
-
+ that are executable, or a list of possible line numbers, any of which
+ could match. `missing` are the lines not executed, `excludes` are
+ regexes to match against for excluding lines, and `report` is the text
+ of the measurement report.
+
For arc measurement, `arcz` is a string that can be decoded into arcs
in the code (see `arcz_to_arcs` for the encoding scheme),
`arcz_missing` are the arcs that are not executed, and
`arcs_unpredicted` are the arcs executed in the code, but not deducible
from the code.
-
+
"""
# We write the code into a file so that we can import it.
# Coverage wants to deal with things as modules with file names.
modname = self.get_module_name()
-
+
self.make_file(modname+".py", text)
arcs = arcs_missing = arcs_unpredicted = None
@@ -157,7 +241,7 @@ class CoverageTest(unittest.TestCase):
arcs = self.arcz_to_arcs(arcz)
arcs_missing = self.arcz_to_arcs(arcz_missing or "")
arcs_unpredicted = self.arcz_to_arcs(arcz_unpredicted or "")
-
+
# Start up Coverage.
cov = coverage.coverage(branch=(arcs_missing is not None))
cov.erase()
@@ -165,11 +249,12 @@ class CoverageTest(unittest.TestCase):
cov.exclude(exc)
cov.start()
- # Import the python file, executing it.
- mod = self.import_module(modname)
-
- # Stop Coverage.
- cov.stop()
+ try: # pragma: recursive coverage
+ # Import the python file, executing it.
+ mod = self.import_module(modname)
+ finally: # pragma: recursive coverage
+ # Stop Coverage.
+ cov.stop()
# Clean up our side effects
del sys.modules[modname]
@@ -178,8 +263,12 @@ class CoverageTest(unittest.TestCase):
analysis = cov._analyze(mod)
if lines is not None:
if type(lines[0]) == type(1):
+ # lines is just a list of numbers, it must match the statements
+ # found in the code.
self.assertEqual(analysis.statements, lines)
else:
+ # lines is a list of possible line number lists, one of them
+ # must match.
for line_list in lines:
if analysis.statements == line_list:
break
@@ -188,26 +277,33 @@ class CoverageTest(unittest.TestCase):
analysis.statements
)
- if missing is not None:
- if type(missing) == type(""):
- self.assertEqual(analysis.missing_formatted(), missing)
+ if type(missing) == type(""):
+ self.assertEqual(analysis.missing_formatted(), missing)
+ else:
+ for missing_list in missing:
+ if analysis.missing_formatted() == missing_list:
+ break
else:
- for missing_list in missing:
- if analysis.missing == missing_list:
- break
- else:
- self.fail("None of the missing choices matched %r" %
- analysis.missing_formatted()
- )
+ self.fail("None of the missing choices matched %r" %
+ analysis.missing_formatted()
+ )
if arcs is not None:
- self.assertEqual(analysis.arc_possibilities(), arcs)
+ self.assertEqualArcs(
+ analysis.arc_possibilities(), arcs, "Possible arcs differ"
+ )
if arcs_missing is not None:
- self.assertEqual(analysis.arcs_missing(), arcs_missing)
+ self.assertEqualArcs(
+ analysis.arcs_missing(), arcs_missing,
+ "Missing arcs differ"
+ )
if arcs_unpredicted is not None:
- self.assertEqual(analysis.arcs_unpredicted(), arcs_unpredicted)
+ self.assertEqualArcs(
+ analysis.arcs_unpredicted(), arcs_unpredicted,
+ "Unpredicted arcs differ"
+ )
if report:
frep = StringIO()
@@ -215,68 +311,64 @@ class CoverageTest(unittest.TestCase):
rep = " ".join(frep.getvalue().split("\n")[2].split()[1:])
self.assertEqual(report, rep)
- def assert_raises_msg(self, excClass, msg, callableObj, *args, **kwargs):
- """ Just like unittest.TestCase.assertRaises,
- but checks that the message is right too.
- """
- try:
- callableObj(*args, **kwargs)
- except excClass:
- _, exc, _ = sys.exc_info()
- excMsg = str(exc)
- if not msg:
- # No message provided: it passes.
- return #pragma: no cover
- elif excMsg == msg:
- # Message provided, and we got the right message: it passes.
- return
- else: #pragma: no cover
- # Message provided, and it didn't match: fail!
- raise self.failureException(
- "Right exception, wrong message: got '%s' expected '%s'" %
- (excMsg, msg)
- )
- # No need to catch other exceptions: They'll fail the test all by
- # themselves!
- else: #pragma: no cover
- if hasattr(excClass,'__name__'):
- excName = excClass.__name__
- else:
- excName = str(excClass)
- raise self.failureException(
- "Expected to raise %s, didn't get an exception at all" %
- excName
- )
-
def nice_file(self, *fparts):
"""Canonicalize the filename composed of the parts in `fparts`."""
fname = os.path.join(*fparts)
return os.path.normcase(os.path.abspath(os.path.realpath(fname)))
-
+
+ def command_line(self, args, ret=OK, _covpkg=None):
+ """Run `args` through the command line.
+
+ Use this when you want to run the full coverage machinery, but in the
+ current process. Exceptions may be thrown from deep in the code.
+ Asserts that `ret` is returned by `CoverageScript.command_line`.
+
+ Compare with `run_command`.
+
+ Returns None.
+
+ """
+ script = coverage.CoverageScript(_covpkg=_covpkg)
+ ret_actual = script.command_line(shlex.split(args))
+ self.assertEqual(ret_actual, ret)
+
def run_command(self, cmd):
- """ Run the command-line `cmd`, print its output.
+ """Run the command-line `cmd` in a subprocess, and print its output.
+
+ Use this when you need to test the process behavior of coverage.
+
+ Compare with `command_line`.
+
+ Returns the process' stdout text.
+
+ """
+ _, output = self.run_command_status(cmd)
+ return output
+
+ def run_command_status(self, cmd, status=0):
+ """Run the command-line `cmd` in a subprocess, and print its output.
+
+ Use this when you need to test the process behavior of coverage.
+
+ Compare with `command_line`.
+
+ Returns a pair: the process' exit status and stdout text.
+
+ The `status` argument is returned as the status on older Pythons where
+ we can't get the actual exit status of the process.
+
"""
# Add our test modules directory to PYTHONPATH. I'm sure there's too
# much path munging here, but...
here = os.path.dirname(self.nice_file(coverage.__file__, ".."))
testmods = self.nice_file(here, 'test/modules')
zipfile = self.nice_file(here, 'test/zipmods.zip')
- pypath = self.old_pypath
+ pypath = self.original_environ('PYTHONPATH', "")
if pypath:
pypath += os.pathsep
pypath += testmods + os.pathsep + zipfile
- os.environ['PYTHONPATH'] = pypath
-
- _, output = run_command(cmd)
- print(output)
- return output
+ self.set_environ('PYTHONPATH', pypath)
- def assert_equal_sets(self, s1, s2):
- """Assert that the two arguments are equal as sets."""
- self.assertEqual(set(s1), set(s2))
-
- def assert_matches(self, s, regex):
- """Assert that `s` matches `regex`."""
- m = re.search(regex, s)
- if not m:
- raise self.failureException("%r doesn't match %r" % (s, regex))
+ status, output = run_command(cmd, status=status)
+ print(output)
+ return status, output
diff --git a/test/farm/annotate/run_multi.py b/test/farm/annotate/run_multi.py
index 872f0976..4e8252ed 100644
--- a/test/farm/annotate/run_multi.py
+++ b/test/farm/annotate/run_multi.py
@@ -1,7 +1,7 @@
copy("src", "out_multi")
run("""
coverage -e -x multi.py
- coverage -a
+ coverage -a
""", rundir="out_multi")
compare("out_multi", "gold_multi", "*,cover")
clean("out_multi")
diff --git a/test/farm/html/gold_a/a.html b/test/farm/html/gold_a/a.html
index b29831b6..b3a28792 100644
--- a/test/farm/html/gold_a/a.html
+++ b/test/farm/html/gold_a/a.html
@@ -1,24 +1,20 @@
<!doctype html PUBLIC "-//W3C//DTD html 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
-<title>Coverage for a</title>
-<link rel='stylesheet' href='style.css' type='text/css'>
-<script src='jquery-1.3.2.min.js'></script>
-<script>
-function toggle_lines(btn, cls) {
- var btn = $(btn);
- if (btn.hasClass("hide")) {
- $("#source ."+cls).removeClass("hide");
- btn.removeClass("hide");
- }
- else {
- $("#source ."+cls).addClass("hide");
- btn.addClass("hide");
- }
-}
-</script>
+ <meta http-equiv='Content-Type' content='text/html; charset=utf-8'>
+
+
+ <meta http-equiv='X-UA-Compatible' content='IE=emulateIE7' />
+ <title>Coverage for a: 67%</title>
+ <link rel='stylesheet' href='style.css' type='text/css'>
+ <script type='text/javascript' src='jquery-1.3.2.min.js'></script>
+ <script type='text/javascript' src='coverage_html.js'></script>
+ <script type='text/javascript' charset='utf-8'>
+ jQuery(document).ready(pyfile_ready);
+ </script>
</head>
-<body>
+<body id='pyfile'>
+
<div id='header'>
<div class='content'>
<h1>Coverage for <b>a</b> :
@@ -26,38 +22,47 @@ function toggle_lines(btn, cls) {
</h1>
<h2 class='stats'>
3 statements
- <span class='run hide' onclick='toggle_lines(this, "run")'>2 run</span>
- <span class='exc' onclick='toggle_lines(this, "exc")'>0 excluded</span>
+ <span class='run hide_run' onclick='toggle_lines(this, "run")'>2 run</span>
<span class='mis' onclick='toggle_lines(this, "mis")'>1 missing</span>
+ <span class='exc' onclick='toggle_lines(this, "exc")'>0 excluded</span>
+
</h2>
</div>
</div>
<div id='source'>
-<table cellspacing='0' cellpadding='0'>
-<tr>
-<td class='linenos' valign='top'>
-<p class='pln'>1</p>
-<p class='pln'>2</p>
-<p class='stm run hide'>3</p>
-<p class='pln'>4</p>
-<p class='stm run hide'>5</p>
-<p class='pln'>6</p>
-<p class='stm mis'>7</p>
-
-</td>
-<td class='text' valign='top'>
-<p class='pln'><span class='com'># A test file for HTML reporting by coverage.</span><span class="strut">&nbsp;</span></p>
-<p class='pln'><span class="strut">&nbsp;</span></p>
-<p class='stm run hide'><span class='key'>if</span> <span class='num'>1</span> <span class='op'>&lt;</span> <span class='num'>2</span><span class='op'>:</span><span class="strut">&nbsp;</span></p>
-<p class='pln'>&nbsp; &nbsp; <span class='com'># Needed a &lt; to look at HTML entities.</span><span class="strut">&nbsp;</span></p>
-<p class='stm run hide'>&nbsp; &nbsp; <span class='nam'>a</span> <span class='op'>=</span> <span class='num'>3</span><span class="strut">&nbsp;</span></p>
-<p class='pln'><span class='key'>else</span><span class='op'>:</span><span class="strut">&nbsp;</span></p>
-<p class='stm mis'>&nbsp; &nbsp; <span class='nam'>a</span> <span class='op'>=</span> <span class='num'>4</span><span class="strut">&nbsp;</span></p>
-
-</td>
-</tr>
-</table>
+ <table cellspacing='0' cellpadding='0'>
+ <tr>
+ <td class='linenos' valign='top'>
+<p id='n1' class='pln'><a href='#n1'>1</a></p>
+<p id='n2' class='pln'><a href='#n2'>2</a></p>
+<p id='n3' class='stm run hide_run'><a href='#n3'>3</a></p>
+<p id='n4' class='pln'><a href='#n4'>4</a></p>
+<p id='n5' class='stm run hide_run'><a href='#n5'>5</a></p>
+<p id='n6' class='pln'><a href='#n6'>6</a></p>
+<p id='n7' class='stm mis'><a href='#n7'>7</a></p>
+
+ </td>
+ <td class='text' valign='top'>
+<p id='t1' class='pln'><span class='com'># A test file for HTML reporting by coverage.</span><span class='strut'>&nbsp;</span></p>
+<p id='t2' class='pln'><span class='strut'>&nbsp;</span></p>
+<p id='t3' class='stm run hide_run'><span class='key'>if</span> <span class='num'>1</span> <span class='op'>&lt;</span> <span class='num'>2</span><span class='op'>:</span><span class='strut'>&nbsp;</span></p>
+<p id='t4' class='pln'>&nbsp; &nbsp; <span class='com'># Needed a &lt; to look at HTML entities.</span><span class='strut'>&nbsp;</span></p>
+<p id='t5' class='stm run hide_run'>&nbsp; &nbsp; <span class='nam'>a</span> <span class='op'>=</span> <span class='num'>3</span><span class='strut'>&nbsp;</span></p>
+<p id='t6' class='pln'><span class='key'>else</span><span class='op'>:</span><span class='strut'>&nbsp;</span></p>
+<p id='t7' class='stm mis'>&nbsp; &nbsp; <span class='nam'>a</span> <span class='op'>=</span> <span class='num'>4</span><span class='strut'>&nbsp;</span></p>
+
+ </td>
+ </tr>
+ </table>
+</div>
+
+<div id='footer'>
+ <div class='content'>
+ <p>
+ <a class='nav' href='index.html'>&#xab; index</a> &nbsp; &nbsp; <a class='nav' href='http://nedbatchelder.com/code/coverage'>coverage.py v3.3.2a1</a>
+ </p>
+ </div>
</div>
</body>
diff --git a/test/farm/html/gold_a/index.html b/test/farm/html/gold_a/index.html
index 88103442..35224e6b 100644
--- a/test/farm/html/gold_a/index.html
+++ b/test/farm/html/gold_a/index.html
@@ -1,55 +1,69 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
-<meta http-equiv='Content-Type' content='text/html; charset=utf-8'>
-<title>Coverage report</title>
-<link rel='stylesheet' href='style.css' type='text/css'>
+ <meta http-equiv='Content-Type' content='text/html; charset=utf-8'>
+ <title>Coverage report</title>
+ <link rel='stylesheet' href='style.css' type='text/css'>
+ <script type='text/javascript' src='jquery-1.3.2.min.js'></script>
+ <script type='text/javascript' src='jquery.tablesorter.min.js'></script>
+ <script type='text/javascript' src='coverage_html.js'></script>
+ <script type='text/javascript' charset='utf-8'>
+ jQuery(document).ready(index_ready);
+ </script>
</head>
-<body>
+<body id='indexfile'>
<div id='header'>
<div class='content'>
- <h1>Coverage report:
+ <h1>Coverage report:
<span class='pc_cov'>67%</span>
</h1>
</div>
</div>
<div id='index'>
-<table class='index'>
-<tr class='tablehead'>
- <th class='name'>Module</th>
- <th>statements</th>
- <th>run</th>
- <th>excluded</th>
-
- <th>coverage</th>
-</tr>
-
-<tr class='file'>
- <td class='name'><a href='a.html'>a</a></td>
- <td>3</td>
- <td>2</td>
- <td>0</td>
-
- <td>67%</td>
-</tr>
-
-<tr class='total'>
-<td class='name'>Total</td>
-<td>3</td>
-<td>2</td>
-<td>0</td>
-
-<td>67%</td>
-</tr>
-</table>
+ <table class='index'>
+ <thead>
+
+ <tr class='tablehead' title='Click to sort'>
+ <th class='name left headerSortDown'>Module</th>
+ <th>statements</th>
+ <th>missing</th>
+ <th>excluded</th>
+
+ <th class='right'>coverage</th>
+ </tr>
+ </thead>
+
+ <tfoot>
+ <tr class='total'>
+ <td class='name left'>Total</td>
+ <td>3</td>
+ <td>1</td>
+ <td>0</td>
+
+ <td class='right'>67%</td>
+ </tr>
+ </tfoot>
+ <tbody>
+
+ <tr class='file'>
+ <td class='name left'><a href='a.html'>a</a></td>
+ <td>3</td>
+ <td>1</td>
+ <td>0</td>
+
+ <td class='right'>67%</td>
+ </tr>
+
+ </tbody>
+ </table>
</div>
<div id='footer'>
<div class='content'>
<p>
- <a class='nav' href='http://nedbatchelder.com/code/coverage'>coverage.py v3.2a1</a>
+ <a class='nav' href='http://nedbatchelder.com/code/coverage'>coverage.py v3.3.2a1</a>
</p>
</div>
</div>
diff --git a/test/farm/html/gold_a/jquery-1.3.2.min.js b/test/farm/html/gold_a/jquery-1.3.2.min.js
deleted file mode 100644
index b1ae21d8..00000000
--- a/test/farm/html/gold_a/jquery-1.3.2.min.js
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * jQuery JavaScript Library v1.3.2
- * http://jquery.com/
- *
- * Copyright (c) 2009 John Resig
- * Dual licensed under the MIT and GPL licenses.
- * http://docs.jquery.com/License
- *
- * Date: 2009-02-19 17:34:21 -0500 (Thu, 19 Feb 2009)
- * Revision: 6246
- */
-(function(){var l=this,g,y=l.jQuery,p=l.$,o=l.jQuery=l.$=function(E,F){return new o.fn.init(E,F)},D=/^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,f=/^.[^:#\[\.,]*$/;o.fn=o.prototype={init:function(E,H){E=E||document;if(E.nodeType){this[0]=E;this.length=1;this.context=E;return this}if(typeof E==="string"){var G=D.exec(E);if(G&&(G[1]||!H)){if(G[1]){E=o.clean([G[1]],H)}else{var I=document.getElementById(G[3]);if(I&&I.id!=G[3]){return o().find(E)}var F=o(I||[]);F.context=document;F.selector=E;return F}}else{return o(H).find(E)}}else{if(o.isFunction(E)){return o(document).ready(E)}}if(E.selector&&E.context){this.selector=E.selector;this.context=E.context}return this.setArray(o.isArray(E)?E:o.makeArray(E))},selector:"",jquery:"1.3.2",size:function(){return this.length},get:function(E){return E===g?Array.prototype.slice.call(this):this[E]},pushStack:function(F,H,E){var G=o(F);G.prevObject=this;G.context=this.context;if(H==="find"){G.selector=this.selector+(this.selector?" ":"")+E}else{if(H){G.selector=this.selector+"."+H+"("+E+")"}}return G},setArray:function(E){this.length=0;Array.prototype.push.apply(this,E);return this},each:function(F,E){return o.each(this,F,E)},index:function(E){return o.inArray(E&&E.jquery?E[0]:E,this)},attr:function(F,H,G){var E=F;if(typeof F==="string"){if(H===g){return this[0]&&o[G||"attr"](this[0],F)}else{E={};E[F]=H}}return this.each(function(I){for(F in E){o.attr(G?this.style:this,F,o.prop(this,E[F],G,I,F))}})},css:function(E,F){if((E=="width"||E=="height")&&parseFloat(F)<0){F=g}return this.attr(E,F,"curCSS")},text:function(F){if(typeof F!=="object"&&F!=null){return this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(F))}var E="";o.each(F||this,function(){o.each(this.childNodes,function(){if(this.nodeType!=8){E+=this.nodeType!=1?this.nodeValue:o.fn.text([this])}})});return E},wrapAll:function(E){if(this[0]){var F=o(E,this[0].ownerDocument).clone();if(this[0].parentNode){F.insertBefore(this[0])}F.map(function(){var G=this;while(G.firstChild){G=G.firstChild}return G}).append(this)}return this},wrapInner:function(E){return this.each(function(){o(this).contents().wrapAll(E)})},wrap:function(E){return this.each(function(){o(this).wrapAll(E)})},append:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.appendChild(E)}})},prepend:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.insertBefore(E,this.firstChild)}})},before:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this)})},after:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this.nextSibling)})},end:function(){return this.prevObject||o([])},push:[].push,sort:[].sort,splice:[].splice,find:function(E){if(this.length===1){var F=this.pushStack([],"find",E);F.length=0;o.find(E,this[0],F);return F}else{return this.pushStack(o.unique(o.map(this,function(G){return o.find(E,G)})),"find",E)}},clone:function(G){var E=this.map(function(){if(!o.support.noCloneEvent&&!o.isXMLDoc(this)){var I=this.outerHTML;if(!I){var J=this.ownerDocument.createElement("div");J.appendChild(this.cloneNode(true));I=J.innerHTML}return o.clean([I.replace(/ jQuery\d+="(?:\d+|null)"/g,"").replace(/^\s*/,"")])[0]}else{return this.cloneNode(true)}});if(G===true){var H=this.find("*").andSelf(),F=0;E.find("*").andSelf().each(function(){if(this.nodeName!==H[F].nodeName){return}var I=o.data(H[F],"events");for(var K in I){for(var J in I[K]){o.event.add(this,K,I[K][J],I[K][J].data)}}F++})}return E},filter:function(E){return this.pushStack(o.isFunction(E)&&o.grep(this,function(G,F){return E.call(G,F)})||o.multiFilter(E,o.grep(this,function(F){return F.nodeType===1})),"filter",E)},closest:function(E){var G=o.expr.match.POS.test(E)?o(E):null,F=0;return this.map(function(){var H=this;while(H&&H.ownerDocument){if(G?G.index(H)>-1:o(H).is(E)){o.data(H,"closest",F);return H}H=H.parentNode;F++}})},not:function(E){if(typeof E==="string"){if(f.test(E)){return this.pushStack(o.multiFilter(E,this,true),"not",E)}else{E=o.multiFilter(E,this)}}var F=E.length&&E[E.length-1]!==g&&!E.nodeType;return this.filter(function(){return F?o.inArray(this,E)<0:this!=E})},add:function(E){return this.pushStack(o.unique(o.merge(this.get(),typeof E==="string"?o(E):o.makeArray(E))))},is:function(E){return !!E&&o.multiFilter(E,this).length>0},hasClass:function(E){return !!E&&this.is("."+E)},val:function(K){if(K===g){var E=this[0];if(E){if(o.nodeName(E,"option")){return(E.attributes.value||{}).specified?E.value:E.text}if(o.nodeName(E,"select")){var I=E.selectedIndex,L=[],M=E.options,H=E.type=="select-one";if(I<0){return null}for(var F=H?I:0,J=H?I+1:M.length;F<J;F++){var G=M[F];if(G.selected){K=o(G).val();if(H){return K}L.push(K)}}return L}return(E.value||"").replace(/\r/g,"")}return g}if(typeof K==="number"){K+=""}return this.each(function(){if(this.nodeType!=1){return}if(o.isArray(K)&&/radio|checkbox/.test(this.type)){this.checked=(o.inArray(this.value,K)>=0||o.inArray(this.name,K)>=0)}else{if(o.nodeName(this,"select")){var N=o.makeArray(K);o("option",this).each(function(){this.selected=(o.inArray(this.value,N)>=0||o.inArray(this.text,N)>=0)});if(!N.length){this.selectedIndex=-1}}else{this.value=K}}})},html:function(E){return E===g?(this[0]?this[0].innerHTML.replace(/ jQuery\d+="(?:\d+|null)"/g,""):null):this.empty().append(E)},replaceWith:function(E){return this.after(E).remove()},eq:function(E){return this.slice(E,+E+1)},slice:function(){return this.pushStack(Array.prototype.slice.apply(this,arguments),"slice",Array.prototype.slice.call(arguments).join(","))},map:function(E){return this.pushStack(o.map(this,function(G,F){return E.call(G,F,G)}))},andSelf:function(){return this.add(this.prevObject)},domManip:function(J,M,L){if(this[0]){var I=(this[0].ownerDocument||this[0]).createDocumentFragment(),F=o.clean(J,(this[0].ownerDocument||this[0]),I),H=I.firstChild;if(H){for(var G=0,E=this.length;G<E;G++){L.call(K(this[G],H),this.length>1||G>0?I.cloneNode(true):I)}}if(F){o.each(F,z)}}return this;function K(N,O){return M&&o.nodeName(N,"table")&&o.nodeName(O,"tr")?(N.getElementsByTagName("tbody")[0]||N.appendChild(N.ownerDocument.createElement("tbody"))):N}}};o.fn.init.prototype=o.fn;function z(E,F){if(F.src){o.ajax({url:F.src,async:false,dataType:"script"})}else{o.globalEval(F.text||F.textContent||F.innerHTML||"")}if(F.parentNode){F.parentNode.removeChild(F)}}function e(){return +new Date}o.extend=o.fn.extend=function(){var J=arguments[0]||{},H=1,I=arguments.length,E=false,G;if(typeof J==="boolean"){E=J;J=arguments[1]||{};H=2}if(typeof J!=="object"&&!o.isFunction(J)){J={}}if(I==H){J=this;--H}for(;H<I;H++){if((G=arguments[H])!=null){for(var F in G){var K=J[F],L=G[F];if(J===L){continue}if(E&&L&&typeof L==="object"&&!L.nodeType){J[F]=o.extend(E,K||(L.length!=null?[]:{}),L)}else{if(L!==g){J[F]=L}}}}}return J};var b=/z-?index|font-?weight|opacity|zoom|line-?height/i,q=document.defaultView||{},s=Object.prototype.toString;o.extend({noConflict:function(E){l.$=p;if(E){l.jQuery=y}return o},isFunction:function(E){return s.call(E)==="[object Function]"},isArray:function(E){return s.call(E)==="[object Array]"},isXMLDoc:function(E){return E.nodeType===9&&E.documentElement.nodeName!=="HTML"||!!E.ownerDocument&&o.isXMLDoc(E.ownerDocument)},globalEval:function(G){if(G&&/\S/.test(G)){var F=document.getElementsByTagName("head")[0]||document.documentElement,E=document.createElement("script");E.type="text/javascript";if(o.support.scriptEval){E.appendChild(document.createTextNode(G))}else{E.text=G}F.insertBefore(E,F.firstChild);F.removeChild(E)}},nodeName:function(F,E){return F.nodeName&&F.nodeName.toUpperCase()==E.toUpperCase()},each:function(G,K,F){var E,H=0,I=G.length;if(F){if(I===g){for(E in G){if(K.apply(G[E],F)===false){break}}}else{for(;H<I;){if(K.apply(G[H++],F)===false){break}}}}else{if(I===g){for(E in G){if(K.call(G[E],E,G[E])===false){break}}}else{for(var J=G[0];H<I&&K.call(J,H,J)!==false;J=G[++H]){}}}return G},prop:function(H,I,G,F,E){if(o.isFunction(I)){I=I.call(H,F)}return typeof I==="number"&&G=="curCSS"&&!b.test(E)?I+"px":I},className:{add:function(E,F){o.each((F||"").split(/\s+/),function(G,H){if(E.nodeType==1&&!o.className.has(E.className,H)){E.className+=(E.className?" ":"")+H}})},remove:function(E,F){if(E.nodeType==1){E.className=F!==g?o.grep(E.className.split(/\s+/),function(G){return !o.className.has(F,G)}).join(" "):""}},has:function(F,E){return F&&o.inArray(E,(F.className||F).toString().split(/\s+/))>-1}},swap:function(H,G,I){var E={};for(var F in G){E[F]=H.style[F];H.style[F]=G[F]}I.call(H);for(var F in G){H.style[F]=E[F]}},css:function(H,F,J,E){if(F=="width"||F=="height"){var L,G={position:"absolute",visibility:"hidden",display:"block"},K=F=="width"?["Left","Right"]:["Top","Bottom"];function I(){L=F=="width"?H.offsetWidth:H.offsetHeight;if(E==="border"){return}o.each(K,function(){if(!E){L-=parseFloat(o.curCSS(H,"padding"+this,true))||0}if(E==="margin"){L+=parseFloat(o.curCSS(H,"margin"+this,true))||0}else{L-=parseFloat(o.curCSS(H,"border"+this+"Width",true))||0}})}if(H.offsetWidth!==0){I()}else{o.swap(H,G,I)}return Math.max(0,Math.round(L))}return o.curCSS(H,F,J)},curCSS:function(I,F,G){var L,E=I.style;if(F=="opacity"&&!o.support.opacity){L=o.attr(E,"opacity");return L==""?"1":L}if(F.match(/float/i)){F=w}if(!G&&E&&E[F]){L=E[F]}else{if(q.getComputedStyle){if(F.match(/float/i)){F="float"}F=F.replace(/([A-Z])/g,"-$1").toLowerCase();var M=q.getComputedStyle(I,null);if(M){L=M.getPropertyValue(F)}if(F=="opacity"&&L==""){L="1"}}else{if(I.currentStyle){var J=F.replace(/\-(\w)/g,function(N,O){return O.toUpperCase()});L=I.currentStyle[F]||I.currentStyle[J];if(!/^\d+(px)?$/i.test(L)&&/^\d/.test(L)){var H=E.left,K=I.runtimeStyle.left;I.runtimeStyle.left=I.currentStyle.left;E.left=L||0;L=E.pixelLeft+"px";E.left=H;I.runtimeStyle.left=K}}}}return L},clean:function(F,K,I){K=K||document;if(typeof K.createElement==="undefined"){K=K.ownerDocument||K[0]&&K[0].ownerDocument||document}if(!I&&F.length===1&&typeof F[0]==="string"){var H=/^<(\w+)\s*\/?>$/.exec(F[0]);if(H){return[K.createElement(H[1])]}}var G=[],E=[],L=K.createElement("div");o.each(F,function(P,S){if(typeof S==="number"){S+=""}if(!S){return}if(typeof S==="string"){S=S.replace(/(<(\w+)[^>]*?)\/>/g,function(U,V,T){return T.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)?U:V+"></"+T+">"});var O=S.replace(/^\s+/,"").substring(0,10).toLowerCase();var Q=!O.indexOf("<opt")&&[1,"<select multiple='multiple'>","</select>"]||!O.indexOf("<leg")&&[1,"<fieldset>","</fieldset>"]||O.match(/^<(thead|tbody|tfoot|colg|cap)/)&&[1,"<table>","</table>"]||!O.indexOf("<tr")&&[2,"<table><tbody>","</tbody></table>"]||(!O.indexOf("<td")||!O.indexOf("<th"))&&[3,"<table><tbody><tr>","</tr></tbody></table>"]||!O.indexOf("<col")&&[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"]||!o.support.htmlSerialize&&[1,"div<div>","</div>"]||[0,"",""];L.innerHTML=Q[1]+S+Q[2];while(Q[0]--){L=L.lastChild}if(!o.support.tbody){var R=/<tbody/i.test(S),N=!O.indexOf("<table")&&!R?L.firstChild&&L.firstChild.childNodes:Q[1]=="<table>"&&!R?L.childNodes:[];for(var M=N.length-1;M>=0;--M){if(o.nodeName(N[M],"tbody")&&!N[M].childNodes.length){N[M].parentNode.removeChild(N[M])}}}if(!o.support.leadingWhitespace&&/^\s/.test(S)){L.insertBefore(K.createTextNode(S.match(/^\s*/)[0]),L.firstChild)}S=o.makeArray(L.childNodes)}if(S.nodeType){G.push(S)}else{G=o.merge(G,S)}});if(I){for(var J=0;G[J];J++){if(o.nodeName(G[J],"script")&&(!G[J].type||G[J].type.toLowerCase()==="text/javascript")){E.push(G[J].parentNode?G[J].parentNode.removeChild(G[J]):G[J])}else{if(G[J].nodeType===1){G.splice.apply(G,[J+1,0].concat(o.makeArray(G[J].getElementsByTagName("script"))))}I.appendChild(G[J])}}return E}return G},attr:function(J,G,K){if(!J||J.nodeType==3||J.nodeType==8){return g}var H=!o.isXMLDoc(J),L=K!==g;G=H&&o.props[G]||G;if(J.tagName){var F=/href|src|style/.test(G);if(G=="selected"&&J.parentNode){J.parentNode.selectedIndex}if(G in J&&H&&!F){if(L){if(G=="type"&&o.nodeName(J,"input")&&J.parentNode){throw"type property can't be changed"}J[G]=K}if(o.nodeName(J,"form")&&J.getAttributeNode(G)){return J.getAttributeNode(G).nodeValue}if(G=="tabIndex"){var I=J.getAttributeNode("tabIndex");return I&&I.specified?I.value:J.nodeName.match(/(button|input|object|select|textarea)/i)?0:J.nodeName.match(/^(a|area)$/i)&&J.href?0:g}return J[G]}if(!o.support.style&&H&&G=="style"){return o.attr(J.style,"cssText",K)}if(L){J.setAttribute(G,""+K)}var E=!o.support.hrefNormalized&&H&&F?J.getAttribute(G,2):J.getAttribute(G);return E===null?g:E}if(!o.support.opacity&&G=="opacity"){if(L){J.zoom=1;J.filter=(J.filter||"").replace(/alpha\([^)]*\)/,"")+(parseInt(K)+""=="NaN"?"":"alpha(opacity="+K*100+")")}return J.filter&&J.filter.indexOf("opacity=")>=0?(parseFloat(J.filter.match(/opacity=([^)]*)/)[1])/100)+"":""}G=G.replace(/-([a-z])/ig,function(M,N){return N.toUpperCase()});if(L){J[G]=K}return J[G]},trim:function(E){return(E||"").replace(/^\s+|\s+$/g,"")},makeArray:function(G){var E=[];if(G!=null){var F=G.length;if(F==null||typeof G==="string"||o.isFunction(G)||G.setInterval){E[0]=G}else{while(F){E[--F]=G[F]}}}return E},inArray:function(G,H){for(var E=0,F=H.length;E<F;E++){if(H[E]===G){return E}}return -1},merge:function(H,E){var F=0,G,I=H.length;if(!o.support.getAll){while((G=E[F++])!=null){if(G.nodeType!=8){H[I++]=G}}}else{while((G=E[F++])!=null){H[I++]=G}}return H},unique:function(K){var F=[],E={};try{for(var G=0,H=K.length;G<H;G++){var J=o.data(K[G]);if(!E[J]){E[J]=true;F.push(K[G])}}}catch(I){F=K}return F},grep:function(F,J,E){var G=[];for(var H=0,I=F.length;H<I;H++){if(!E!=!J(F[H],H)){G.push(F[H])}}return G},map:function(E,J){var F=[];for(var G=0,H=E.length;G<H;G++){var I=J(E[G],G);if(I!=null){F[F.length]=I}}return F.concat.apply([],F)}});var C=navigator.userAgent.toLowerCase();o.browser={version:(C.match(/.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/)||[0,"0"])[1],safari:/webkit/.test(C),opera:/opera/.test(C),msie:/msie/.test(C)&&!/opera/.test(C),mozilla:/mozilla/.test(C)&&!/(compatible|webkit)/.test(C)};o.each({parent:function(E){return E.parentNode},parents:function(E){return o.dir(E,"parentNode")},next:function(E){return o.nth(E,2,"nextSibling")},prev:function(E){return o.nth(E,2,"previousSibling")},nextAll:function(E){return o.dir(E,"nextSibling")},prevAll:function(E){return o.dir(E,"previousSibling")},siblings:function(E){return o.sibling(E.parentNode.firstChild,E)},children:function(E){return o.sibling(E.firstChild)},contents:function(E){return o.nodeName(E,"iframe")?E.contentDocument||E.contentWindow.document:o.makeArray(E.childNodes)}},function(E,F){o.fn[E]=function(G){var H=o.map(this,F);if(G&&typeof G=="string"){H=o.multiFilter(G,H)}return this.pushStack(o.unique(H),E,G)}});o.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(E,F){o.fn[E]=function(G){var J=[],L=o(G);for(var K=0,H=L.length;K<H;K++){var I=(K>0?this.clone(true):this).get();o.fn[F].apply(o(L[K]),I);J=J.concat(I)}return this.pushStack(J,E,G)}});o.each({removeAttr:function(E){o.attr(this,E,"");if(this.nodeType==1){this.removeAttribute(E)}},addClass:function(E){o.className.add(this,E)},removeClass:function(E){o.className.remove(this,E)},toggleClass:function(F,E){if(typeof E!=="boolean"){E=!o.className.has(this,F)}o.className[E?"add":"remove"](this,F)},remove:function(E){if(!E||o.filter(E,[this]).length){o("*",this).add([this]).each(function(){o.event.remove(this);o.removeData(this)});if(this.parentNode){this.parentNode.removeChild(this)}}},empty:function(){o(this).children().remove();while(this.firstChild){this.removeChild(this.firstChild)}}},function(E,F){o.fn[E]=function(){return this.each(F,arguments)}});function j(E,F){return E[0]&&parseInt(o.curCSS(E[0],F,true),10)||0}var h="jQuery"+e(),v=0,A={};o.extend({cache:{},data:function(F,E,G){F=F==l?A:F;var H=F[h];if(!H){H=F[h]=++v}if(E&&!o.cache[H]){o.cache[H]={}}if(G!==g){o.cache[H][E]=G}return E?o.cache[H][E]:H},removeData:function(F,E){F=F==l?A:F;var H=F[h];if(E){if(o.cache[H]){delete o.cache[H][E];E="";for(E in o.cache[H]){break}if(!E){o.removeData(F)}}}else{try{delete F[h]}catch(G){if(F.removeAttribute){F.removeAttribute(h)}}delete o.cache[H]}},queue:function(F,E,H){if(F){E=(E||"fx")+"queue";var G=o.data(F,E);if(!G||o.isArray(H)){G=o.data(F,E,o.makeArray(H))}else{if(H){G.push(H)}}}return G},dequeue:function(H,G){var E=o.queue(H,G),F=E.shift();if(!G||G==="fx"){F=E[0]}if(F!==g){F.call(H)}}});o.fn.extend({data:function(E,G){var H=E.split(".");H[1]=H[1]?"."+H[1]:"";if(G===g){var F=this.triggerHandler("getData"+H[1]+"!",[H[0]]);if(F===g&&this.length){F=o.data(this[0],E)}return F===g&&H[1]?this.data(H[0]):F}else{return this.trigger("setData"+H[1]+"!",[H[0],G]).each(function(){o.data(this,E,G)})}},removeData:function(E){return this.each(function(){o.removeData(this,E)})},queue:function(E,F){if(typeof E!=="string"){F=E;E="fx"}if(F===g){return o.queue(this[0],E)}return this.each(function(){var G=o.queue(this,E,F);if(E=="fx"&&G.length==1){G[0].call(this)}})},dequeue:function(E){return this.each(function(){o.dequeue(this,E)})}});
-/*
- * Sizzle CSS Selector Engine - v0.9.3
- * Copyright 2009, The Dojo Foundation
- * Released under the MIT, BSD, and GPL Licenses.
- * More information: http://sizzlejs.com/
- */
-(function(){var R=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g,L=0,H=Object.prototype.toString;var F=function(Y,U,ab,ac){ab=ab||[];U=U||document;if(U.nodeType!==1&&U.nodeType!==9){return[]}if(!Y||typeof Y!=="string"){return ab}var Z=[],W,af,ai,T,ad,V,X=true;R.lastIndex=0;while((W=R.exec(Y))!==null){Z.push(W[1]);if(W[2]){V=RegExp.rightContext;break}}if(Z.length>1&&M.exec(Y)){if(Z.length===2&&I.relative[Z[0]]){af=J(Z[0]+Z[1],U)}else{af=I.relative[Z[0]]?[U]:F(Z.shift(),U);while(Z.length){Y=Z.shift();if(I.relative[Y]){Y+=Z.shift()}af=J(Y,af)}}}else{var ae=ac?{expr:Z.pop(),set:E(ac)}:F.find(Z.pop(),Z.length===1&&U.parentNode?U.parentNode:U,Q(U));af=F.filter(ae.expr,ae.set);if(Z.length>0){ai=E(af)}else{X=false}while(Z.length){var ah=Z.pop(),ag=ah;if(!I.relative[ah]){ah=""}else{ag=Z.pop()}if(ag==null){ag=U}I.relative[ah](ai,ag,Q(U))}}if(!ai){ai=af}if(!ai){throw"Syntax error, unrecognized expression: "+(ah||Y)}if(H.call(ai)==="[object Array]"){if(!X){ab.push.apply(ab,ai)}else{if(U.nodeType===1){for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&(ai[aa]===true||ai[aa].nodeType===1&&K(U,ai[aa]))){ab.push(af[aa])}}}else{for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&ai[aa].nodeType===1){ab.push(af[aa])}}}}}else{E(ai,ab)}if(V){F(V,U,ab,ac);if(G){hasDuplicate=false;ab.sort(G);if(hasDuplicate){for(var aa=1;aa<ab.length;aa++){if(ab[aa]===ab[aa-1]){ab.splice(aa--,1)}}}}}return ab};F.matches=function(T,U){return F(T,null,null,U)};F.find=function(aa,T,ab){var Z,X;if(!aa){return[]}for(var W=0,V=I.order.length;W<V;W++){var Y=I.order[W],X;if((X=I.match[Y].exec(aa))){var U=RegExp.leftContext;if(U.substr(U.length-1)!=="\\"){X[1]=(X[1]||"").replace(/\\/g,"");Z=I.find[Y](X,T,ab);if(Z!=null){aa=aa.replace(I.match[Y],"");break}}}}if(!Z){Z=T.getElementsByTagName("*")}return{set:Z,expr:aa}};F.filter=function(ad,ac,ag,W){var V=ad,ai=[],aa=ac,Y,T,Z=ac&&ac[0]&&Q(ac[0]);while(ad&&ac.length){for(var ab in I.filter){if((Y=I.match[ab].exec(ad))!=null){var U=I.filter[ab],ah,af;T=false;if(aa==ai){ai=[]}if(I.preFilter[ab]){Y=I.preFilter[ab](Y,aa,ag,ai,W,Z);if(!Y){T=ah=true}else{if(Y===true){continue}}}if(Y){for(var X=0;(af=aa[X])!=null;X++){if(af){ah=U(af,Y,X,aa);var ae=W^!!ah;if(ag&&ah!=null){if(ae){T=true}else{aa[X]=false}}else{if(ae){ai.push(af);T=true}}}}}if(ah!==g){if(!ag){aa=ai}ad=ad.replace(I.match[ab],"");if(!T){return[]}break}}}if(ad==V){if(T==null){throw"Syntax error, unrecognized expression: "+ad}else{break}}V=ad}return aa};var I=F.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF_-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF_-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*_-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF_-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(T){return T.getAttribute("href")}},relative:{"+":function(aa,T,Z){var X=typeof T==="string",ab=X&&!/\W/.test(T),Y=X&&!ab;if(ab&&!Z){T=T.toUpperCase()}for(var W=0,V=aa.length,U;W<V;W++){if((U=aa[W])){while((U=U.previousSibling)&&U.nodeType!==1){}aa[W]=Y||U&&U.nodeName===T?U||false:U===T}}if(Y){F.filter(T,aa,true)}},">":function(Z,U,aa){var X=typeof U==="string";if(X&&!/\W/.test(U)){U=aa?U:U.toUpperCase();for(var V=0,T=Z.length;V<T;V++){var Y=Z[V];if(Y){var W=Y.parentNode;Z[V]=W.nodeName===U?W:false}}}else{for(var V=0,T=Z.length;V<T;V++){var Y=Z[V];if(Y){Z[V]=X?Y.parentNode:Y.parentNode===U}}if(X){F.filter(U,Z,true)}}},"":function(W,U,Y){var V=L++,T=S;if(!U.match(/\W/)){var X=U=Y?U:U.toUpperCase();T=P}T("parentNode",U,V,W,X,Y)},"~":function(W,U,Y){var V=L++,T=S;if(typeof U==="string"&&!U.match(/\W/)){var X=U=Y?U:U.toUpperCase();T=P}T("previousSibling",U,V,W,X,Y)}},find:{ID:function(U,V,W){if(typeof V.getElementById!=="undefined"&&!W){var T=V.getElementById(U[1]);return T?[T]:[]}},NAME:function(V,Y,Z){if(typeof Y.getElementsByName!=="undefined"){var U=[],X=Y.getElementsByName(V[1]);for(var W=0,T=X.length;W<T;W++){if(X[W].getAttribute("name")===V[1]){U.push(X[W])}}return U.length===0?null:U}},TAG:function(T,U){return U.getElementsByTagName(T[1])}},preFilter:{CLASS:function(W,U,V,T,Z,aa){W=" "+W[1].replace(/\\/g,"")+" ";if(aa){return W}for(var X=0,Y;(Y=U[X])!=null;X++){if(Y){if(Z^(Y.className&&(" "+Y.className+" ").indexOf(W)>=0)){if(!V){T.push(Y)}}else{if(V){U[X]=false}}}}return false},ID:function(T){return T[1].replace(/\\/g,"")},TAG:function(U,T){for(var V=0;T[V]===false;V++){}return T[V]&&Q(T[V])?U[1]:U[1].toUpperCase()},CHILD:function(T){if(T[1]=="nth"){var U=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(T[2]=="even"&&"2n"||T[2]=="odd"&&"2n+1"||!/\D/.test(T[2])&&"0n+"+T[2]||T[2]);T[2]=(U[1]+(U[2]||1))-0;T[3]=U[3]-0}T[0]=L++;return T},ATTR:function(X,U,V,T,Y,Z){var W=X[1].replace(/\\/g,"");if(!Z&&I.attrMap[W]){X[1]=I.attrMap[W]}if(X[2]==="~="){X[4]=" "+X[4]+" "}return X},PSEUDO:function(X,U,V,T,Y){if(X[1]==="not"){if(X[3].match(R).length>1||/^\w/.test(X[3])){X[3]=F(X[3],null,null,U)}else{var W=F.filter(X[3],U,V,true^Y);if(!V){T.push.apply(T,W)}return false}}else{if(I.match.POS.test(X[0])||I.match.CHILD.test(X[0])){return true}}return X},POS:function(T){T.unshift(true);return T}},filters:{enabled:function(T){return T.disabled===false&&T.type!=="hidden"},disabled:function(T){return T.disabled===true},checked:function(T){return T.checked===true},selected:function(T){T.parentNode.selectedIndex;return T.selected===true},parent:function(T){return !!T.firstChild},empty:function(T){return !T.firstChild},has:function(V,U,T){return !!F(T[3],V).length},header:function(T){return/h\d/i.test(T.nodeName)},text:function(T){return"text"===T.type},radio:function(T){return"radio"===T.type},checkbox:function(T){return"checkbox"===T.type},file:function(T){return"file"===T.type},password:function(T){return"password"===T.type},submit:function(T){return"submit"===T.type},image:function(T){return"image"===T.type},reset:function(T){return"reset"===T.type},button:function(T){return"button"===T.type||T.nodeName.toUpperCase()==="BUTTON"},input:function(T){return/input|select|textarea|button/i.test(T.nodeName)}},setFilters:{first:function(U,T){return T===0},last:function(V,U,T,W){return U===W.length-1},even:function(U,T){return T%2===0},odd:function(U,T){return T%2===1},lt:function(V,U,T){return U<T[3]-0},gt:function(V,U,T){return U>T[3]-0},nth:function(V,U,T){return T[3]-0==U},eq:function(V,U,T){return T[3]-0==U}},filter:{PSEUDO:function(Z,V,W,aa){var U=V[1],X=I.filters[U];if(X){return X(Z,W,V,aa)}else{if(U==="contains"){return(Z.textContent||Z.innerText||"").indexOf(V[3])>=0}else{if(U==="not"){var Y=V[3];for(var W=0,T=Y.length;W<T;W++){if(Y[W]===Z){return false}}return true}}}},CHILD:function(T,W){var Z=W[1],U=T;switch(Z){case"only":case"first":while(U=U.previousSibling){if(U.nodeType===1){return false}}if(Z=="first"){return true}U=T;case"last":while(U=U.nextSibling){if(U.nodeType===1){return false}}return true;case"nth":var V=W[2],ac=W[3];if(V==1&&ac==0){return true}var Y=W[0],ab=T.parentNode;if(ab&&(ab.sizcache!==Y||!T.nodeIndex)){var X=0;for(U=ab.firstChild;U;U=U.nextSibling){if(U.nodeType===1){U.nodeIndex=++X}}ab.sizcache=Y}var aa=T.nodeIndex-ac;if(V==0){return aa==0}else{return(aa%V==0&&aa/V>=0)}}},ID:function(U,T){return U.nodeType===1&&U.getAttribute("id")===T},TAG:function(U,T){return(T==="*"&&U.nodeType===1)||U.nodeName===T},CLASS:function(U,T){return(" "+(U.className||U.getAttribute("class"))+" ").indexOf(T)>-1},ATTR:function(Y,W){var V=W[1],T=I.attrHandle[V]?I.attrHandle[V](Y):Y[V]!=null?Y[V]:Y.getAttribute(V),Z=T+"",X=W[2],U=W[4];return T==null?X==="!=":X==="="?Z===U:X==="*="?Z.indexOf(U)>=0:X==="~="?(" "+Z+" ").indexOf(U)>=0:!U?Z&&T!==false:X==="!="?Z!=U:X==="^="?Z.indexOf(U)===0:X==="$="?Z.substr(Z.length-U.length)===U:X==="|="?Z===U||Z.substr(0,U.length+1)===U+"-":false},POS:function(X,U,V,Y){var T=U[2],W=I.setFilters[T];if(W){return W(X,V,U,Y)}}}};var M=I.match.POS;for(var O in I.match){I.match[O]=RegExp(I.match[O].source+/(?![^\[]*\])(?![^\(]*\))/.source)}var E=function(U,T){U=Array.prototype.slice.call(U);if(T){T.push.apply(T,U);return T}return U};try{Array.prototype.slice.call(document.documentElement.childNodes)}catch(N){E=function(X,W){var U=W||[];if(H.call(X)==="[object Array]"){Array.prototype.push.apply(U,X)}else{if(typeof X.length==="number"){for(var V=0,T=X.length;V<T;V++){U.push(X[V])}}else{for(var V=0;X[V];V++){U.push(X[V])}}}return U}}var G;if(document.documentElement.compareDocumentPosition){G=function(U,T){var V=U.compareDocumentPosition(T)&4?-1:U===T?0:1;if(V===0){hasDuplicate=true}return V}}else{if("sourceIndex" in document.documentElement){G=function(U,T){var V=U.sourceIndex-T.sourceIndex;if(V===0){hasDuplicate=true}return V}}else{if(document.createRange){G=function(W,U){var V=W.ownerDocument.createRange(),T=U.ownerDocument.createRange();V.selectNode(W);V.collapse(true);T.selectNode(U);T.collapse(true);var X=V.compareBoundaryPoints(Range.START_TO_END,T);if(X===0){hasDuplicate=true}return X}}}}(function(){var U=document.createElement("form"),V="script"+(new Date).getTime();U.innerHTML="<input name='"+V+"'/>";var T=document.documentElement;T.insertBefore(U,T.firstChild);if(!!document.getElementById(V)){I.find.ID=function(X,Y,Z){if(typeof Y.getElementById!=="undefined"&&!Z){var W=Y.getElementById(X[1]);return W?W.id===X[1]||typeof W.getAttributeNode!=="undefined"&&W.getAttributeNode("id").nodeValue===X[1]?[W]:g:[]}};I.filter.ID=function(Y,W){var X=typeof Y.getAttributeNode!=="undefined"&&Y.getAttributeNode("id");return Y.nodeType===1&&X&&X.nodeValue===W}}T.removeChild(U)})();(function(){var T=document.createElement("div");T.appendChild(document.createComment(""));if(T.getElementsByTagName("*").length>0){I.find.TAG=function(U,Y){var X=Y.getElementsByTagName(U[1]);if(U[1]==="*"){var W=[];for(var V=0;X[V];V++){if(X[V].nodeType===1){W.push(X[V])}}X=W}return X}}T.innerHTML="<a href='#'></a>";if(T.firstChild&&typeof T.firstChild.getAttribute!=="undefined"&&T.firstChild.getAttribute("href")!=="#"){I.attrHandle.href=function(U){return U.getAttribute("href",2)}}})();if(document.querySelectorAll){(function(){var T=F,U=document.createElement("div");U.innerHTML="<p class='TEST'></p>";if(U.querySelectorAll&&U.querySelectorAll(".TEST").length===0){return}F=function(Y,X,V,W){X=X||document;if(!W&&X.nodeType===9&&!Q(X)){try{return E(X.querySelectorAll(Y),V)}catch(Z){}}return T(Y,X,V,W)};F.find=T.find;F.filter=T.filter;F.selectors=T.selectors;F.matches=T.matches})()}if(document.getElementsByClassName&&document.documentElement.getElementsByClassName){(function(){var T=document.createElement("div");T.innerHTML="<div class='test e'></div><div class='test'></div>";if(T.getElementsByClassName("e").length===0){return}T.lastChild.className="e";if(T.getElementsByClassName("e").length===1){return}I.order.splice(1,0,"CLASS");I.find.CLASS=function(U,V,W){if(typeof V.getElementsByClassName!=="undefined"&&!W){return V.getElementsByClassName(U[1])}}})()}function P(U,Z,Y,ad,aa,ac){var ab=U=="previousSibling"&&!ac;for(var W=0,V=ad.length;W<V;W++){var T=ad[W];if(T){if(ab&&T.nodeType===1){T.sizcache=Y;T.sizset=W}T=T[U];var X=false;while(T){if(T.sizcache===Y){X=ad[T.sizset];break}if(T.nodeType===1&&!ac){T.sizcache=Y;T.sizset=W}if(T.nodeName===Z){X=T;break}T=T[U]}ad[W]=X}}}function S(U,Z,Y,ad,aa,ac){var ab=U=="previousSibling"&&!ac;for(var W=0,V=ad.length;W<V;W++){var T=ad[W];if(T){if(ab&&T.nodeType===1){T.sizcache=Y;T.sizset=W}T=T[U];var X=false;while(T){if(T.sizcache===Y){X=ad[T.sizset];break}if(T.nodeType===1){if(!ac){T.sizcache=Y;T.sizset=W}if(typeof Z!=="string"){if(T===Z){X=true;break}}else{if(F.filter(Z,[T]).length>0){X=T;break}}}T=T[U]}ad[W]=X}}}var K=document.compareDocumentPosition?function(U,T){return U.compareDocumentPosition(T)&16}:function(U,T){return U!==T&&(U.contains?U.contains(T):true)};var Q=function(T){return T.nodeType===9&&T.documentElement.nodeName!=="HTML"||!!T.ownerDocument&&Q(T.ownerDocument)};var J=function(T,aa){var W=[],X="",Y,V=aa.nodeType?[aa]:aa;while((Y=I.match.PSEUDO.exec(T))){X+=Y[0];T=T.replace(I.match.PSEUDO,"")}T=I.relative[T]?T+"*":T;for(var Z=0,U=V.length;Z<U;Z++){F(T,V[Z],W)}return F.filter(X,W)};o.find=F;o.filter=F.filter;o.expr=F.selectors;o.expr[":"]=o.expr.filters;F.selectors.filters.hidden=function(T){return T.offsetWidth===0||T.offsetHeight===0};F.selectors.filters.visible=function(T){return T.offsetWidth>0||T.offsetHeight>0};F.selectors.filters.animated=function(T){return o.grep(o.timers,function(U){return T===U.elem}).length};o.multiFilter=function(V,T,U){if(U){V=":not("+V+")"}return F.matches(V,T)};o.dir=function(V,U){var T=[],W=V[U];while(W&&W!=document){if(W.nodeType==1){T.push(W)}W=W[U]}return T};o.nth=function(X,T,V,W){T=T||1;var U=0;for(;X;X=X[V]){if(X.nodeType==1&&++U==T){break}}return X};o.sibling=function(V,U){var T=[];for(;V;V=V.nextSibling){if(V.nodeType==1&&V!=U){T.push(V)}}return T};return;l.Sizzle=F})();o.event={add:function(I,F,H,K){if(I.nodeType==3||I.nodeType==8){return}if(I.setInterval&&I!=l){I=l}if(!H.guid){H.guid=this.guid++}if(K!==g){var G=H;H=this.proxy(G);H.data=K}var E=o.data(I,"events")||o.data(I,"events",{}),J=o.data(I,"handle")||o.data(I,"handle",function(){return typeof o!=="undefined"&&!o.event.triggered?o.event.handle.apply(arguments.callee.elem,arguments):g});J.elem=I;o.each(F.split(/\s+/),function(M,N){var O=N.split(".");N=O.shift();H.type=O.slice().sort().join(".");var L=E[N];if(o.event.specialAll[N]){o.event.specialAll[N].setup.call(I,K,O)}if(!L){L=E[N]={};if(!o.event.special[N]||o.event.special[N].setup.call(I,K,O)===false){if(I.addEventListener){I.addEventListener(N,J,false)}else{if(I.attachEvent){I.attachEvent("on"+N,J)}}}}L[H.guid]=H;o.event.global[N]=true});I=null},guid:1,global:{},remove:function(K,H,J){if(K.nodeType==3||K.nodeType==8){return}var G=o.data(K,"events"),F,E;if(G){if(H===g||(typeof H==="string"&&H.charAt(0)==".")){for(var I in G){this.remove(K,I+(H||""))}}else{if(H.type){J=H.handler;H=H.type}o.each(H.split(/\s+/),function(M,O){var Q=O.split(".");O=Q.shift();var N=RegExp("(^|\\.)"+Q.slice().sort().join(".*\\.")+"(\\.|$)");if(G[O]){if(J){delete G[O][J.guid]}else{for(var P in G[O]){if(N.test(G[O][P].type)){delete G[O][P]}}}if(o.event.specialAll[O]){o.event.specialAll[O].teardown.call(K,Q)}for(F in G[O]){break}if(!F){if(!o.event.special[O]||o.event.special[O].teardown.call(K,Q)===false){if(K.removeEventListener){K.removeEventListener(O,o.data(K,"handle"),false)}else{if(K.detachEvent){K.detachEvent("on"+O,o.data(K,"handle"))}}}F=null;delete G[O]}}})}for(F in G){break}if(!F){var L=o.data(K,"handle");if(L){L.elem=null}o.removeData(K,"events");o.removeData(K,"handle")}}},trigger:function(I,K,H,E){var G=I.type||I;if(!E){I=typeof I==="object"?I[h]?I:o.extend(o.Event(G),I):o.Event(G);if(G.indexOf("!")>=0){I.type=G=G.slice(0,-1);I.exclusive=true}if(!H){I.stopPropagation();if(this.global[G]){o.each(o.cache,function(){if(this.events&&this.events[G]){o.event.trigger(I,K,this.handle.elem)}})}}if(!H||H.nodeType==3||H.nodeType==8){return g}I.result=g;I.target=H;K=o.makeArray(K);K.unshift(I)}I.currentTarget=H;var J=o.data(H,"handle");if(J){J.apply(H,K)}if((!H[G]||(o.nodeName(H,"a")&&G=="click"))&&H["on"+G]&&H["on"+G].apply(H,K)===false){I.result=false}if(!E&&H[G]&&!I.isDefaultPrevented()&&!(o.nodeName(H,"a")&&G=="click")){this.triggered=true;try{H[G]()}catch(L){}}this.triggered=false;if(!I.isPropagationStopped()){var F=H.parentNode||H.ownerDocument;if(F){o.event.trigger(I,K,F,true)}}},handle:function(K){var J,E;K=arguments[0]=o.event.fix(K||l.event);K.currentTarget=this;var L=K.type.split(".");K.type=L.shift();J=!L.length&&!K.exclusive;var I=RegExp("(^|\\.)"+L.slice().sort().join(".*\\.")+"(\\.|$)");E=(o.data(this,"events")||{})[K.type];for(var G in E){var H=E[G];if(J||I.test(H.type)){K.handler=H;K.data=H.data;var F=H.apply(this,arguments);if(F!==g){K.result=F;if(F===false){K.preventDefault();K.stopPropagation()}}if(K.isImmediatePropagationStopped()){break}}}},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),fix:function(H){if(H[h]){return H}var F=H;H=o.Event(F);for(var G=this.props.length,J;G;){J=this.props[--G];H[J]=F[J]}if(!H.target){H.target=H.srcElement||document}if(H.target.nodeType==3){H.target=H.target.parentNode}if(!H.relatedTarget&&H.fromElement){H.relatedTarget=H.fromElement==H.target?H.toElement:H.fromElement}if(H.pageX==null&&H.clientX!=null){var I=document.documentElement,E=document.body;H.pageX=H.clientX+(I&&I.scrollLeft||E&&E.scrollLeft||0)-(I.clientLeft||0);H.pageY=H.clientY+(I&&I.scrollTop||E&&E.scrollTop||0)-(I.clientTop||0)}if(!H.which&&((H.charCode||H.charCode===0)?H.charCode:H.keyCode)){H.which=H.charCode||H.keyCode}if(!H.metaKey&&H.ctrlKey){H.metaKey=H.ctrlKey}if(!H.which&&H.button){H.which=(H.button&1?1:(H.button&2?3:(H.button&4?2:0)))}return H},proxy:function(F,E){E=E||function(){return F.apply(this,arguments)};E.guid=F.guid=F.guid||E.guid||this.guid++;return E},special:{ready:{setup:B,teardown:function(){}}},specialAll:{live:{setup:function(E,F){o.event.add(this,F[0],c)},teardown:function(G){if(G.length){var E=0,F=RegExp("(^|\\.)"+G[0]+"(\\.|$)");o.each((o.data(this,"events").live||{}),function(){if(F.test(this.type)){E++}});if(E<1){o.event.remove(this,G[0],c)}}}}}};o.Event=function(E){if(!this.preventDefault){return new o.Event(E)}if(E&&E.type){this.originalEvent=E;this.type=E.type}else{this.type=E}this.timeStamp=e();this[h]=true};function k(){return false}function u(){return true}o.Event.prototype={preventDefault:function(){this.isDefaultPrevented=u;var E=this.originalEvent;if(!E){return}if(E.preventDefault){E.preventDefault()}E.returnValue=false},stopPropagation:function(){this.isPropagationStopped=u;var E=this.originalEvent;if(!E){return}if(E.stopPropagation){E.stopPropagation()}E.cancelBubble=true},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=u;this.stopPropagation()},isDefaultPrevented:k,isPropagationStopped:k,isImmediatePropagationStopped:k};var a=function(F){var E=F.relatedTarget;while(E&&E!=this){try{E=E.parentNode}catch(G){E=this}}if(E!=this){F.type=F.data;o.event.handle.apply(this,arguments)}};o.each({mouseover:"mouseenter",mouseout:"mouseleave"},function(F,E){o.event.special[E]={setup:function(){o.event.add(this,F,a,E)},teardown:function(){o.event.remove(this,F,a)}}});o.fn.extend({bind:function(F,G,E){return F=="unload"?this.one(F,G,E):this.each(function(){o.event.add(this,F,E||G,E&&G)})},one:function(G,H,F){var E=o.event.proxy(F||H,function(I){o(this).unbind(I,E);return(F||H).apply(this,arguments)});return this.each(function(){o.event.add(this,G,E,F&&H)})},unbind:function(F,E){return this.each(function(){o.event.remove(this,F,E)})},trigger:function(E,F){return this.each(function(){o.event.trigger(E,F,this)})},triggerHandler:function(E,G){if(this[0]){var F=o.Event(E);F.preventDefault();F.stopPropagation();o.event.trigger(F,G,this[0]);return F.result}},toggle:function(G){var E=arguments,F=1;while(F<E.length){o.event.proxy(G,E[F++])}return this.click(o.event.proxy(G,function(H){this.lastToggle=(this.lastToggle||0)%F;H.preventDefault();return E[this.lastToggle++].apply(this,arguments)||false}))},hover:function(E,F){return this.mouseenter(E).mouseleave(F)},ready:function(E){B();if(o.isReady){E.call(document,o)}else{o.readyList.push(E)}return this},live:function(G,F){var E=o.event.proxy(F);E.guid+=this.selector+G;o(document).bind(i(G,this.selector),this.selector,E);return this},die:function(F,E){o(document).unbind(i(F,this.selector),E?{guid:E.guid+this.selector+F}:null);return this}});function c(H){var E=RegExp("(^|\\.)"+H.type+"(\\.|$)"),G=true,F=[];o.each(o.data(this,"events").live||[],function(I,J){if(E.test(J.type)){var K=o(H.target).closest(J.data)[0];if(K){F.push({elem:K,fn:J})}}});F.sort(function(J,I){return o.data(J.elem,"closest")-o.data(I.elem,"closest")});o.each(F,function(){if(this.fn.call(this.elem,H,this.fn.data)===false){return(G=false)}});return G}function i(F,E){return["live",F,E.replace(/\./g,"`").replace(/ /g,"|")].join(".")}o.extend({isReady:false,readyList:[],ready:function(){if(!o.isReady){o.isReady=true;if(o.readyList){o.each(o.readyList,function(){this.call(document,o)});o.readyList=null}o(document).triggerHandler("ready")}}});var x=false;function B(){if(x){return}x=true;if(document.addEventListener){document.addEventListener("DOMContentLoaded",function(){document.removeEventListener("DOMContentLoaded",arguments.callee,false);o.ready()},false)}else{if(document.attachEvent){document.attachEvent("onreadystatechange",function(){if(document.readyState==="complete"){document.detachEvent("onreadystatechange",arguments.callee);o.ready()}});if(document.documentElement.doScroll&&l==l.top){(function(){if(o.isReady){return}try{document.documentElement.doScroll("left")}catch(E){setTimeout(arguments.callee,0);return}o.ready()})()}}}o.event.add(l,"load",o.ready)}o.each(("blur,focus,load,resize,scroll,unload,click,dblclick,mousedown,mouseup,mousemove,mouseover,mouseout,mouseenter,mouseleave,change,select,submit,keydown,keypress,keyup,error").split(","),function(F,E){o.fn[E]=function(G){return G?this.bind(E,G):this.trigger(E)}});o(l).bind("unload",function(){for(var E in o.cache){if(E!=1&&o.cache[E].handle){o.event.remove(o.cache[E].handle.elem)}}});(function(){o.support={};var F=document.documentElement,G=document.createElement("script"),K=document.createElement("div"),J="script"+(new Date).getTime();K.style.display="none";K.innerHTML=' <link/><table></table><a href="/a" style="color:red;float:left;opacity:.5;">a</a><select><option>text</option></select><object><param/></object>';var H=K.getElementsByTagName("*"),E=K.getElementsByTagName("a")[0];if(!H||!H.length||!E){return}o.support={leadingWhitespace:K.firstChild.nodeType==3,tbody:!K.getElementsByTagName("tbody").length,objectAll:!!K.getElementsByTagName("object")[0].getElementsByTagName("*").length,htmlSerialize:!!K.getElementsByTagName("link").length,style:/red/.test(E.getAttribute("style")),hrefNormalized:E.getAttribute("href")==="/a",opacity:E.style.opacity==="0.5",cssFloat:!!E.style.cssFloat,scriptEval:false,noCloneEvent:true,boxModel:null};G.type="text/javascript";try{G.appendChild(document.createTextNode("window."+J+"=1;"))}catch(I){}F.insertBefore(G,F.firstChild);if(l[J]){o.support.scriptEval=true;delete l[J]}F.removeChild(G);if(K.attachEvent&&K.fireEvent){K.attachEvent("onclick",function(){o.support.noCloneEvent=false;K.detachEvent("onclick",arguments.callee)});K.cloneNode(true).fireEvent("onclick")}o(function(){var L=document.createElement("div");L.style.width=L.style.paddingLeft="1px";document.body.appendChild(L);o.boxModel=o.support.boxModel=L.offsetWidth===2;document.body.removeChild(L).style.display="none"})})();var w=o.support.cssFloat?"cssFloat":"styleFloat";o.props={"for":"htmlFor","class":"className","float":w,cssFloat:w,styleFloat:w,readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",tabindex:"tabIndex"};o.fn.extend({_load:o.fn.load,load:function(G,J,K){if(typeof G!=="string"){return this._load(G)}var I=G.indexOf(" ");if(I>=0){var E=G.slice(I,G.length);G=G.slice(0,I)}var H="GET";if(J){if(o.isFunction(J)){K=J;J=null}else{if(typeof J==="object"){J=o.param(J);H="POST"}}}var F=this;o.ajax({url:G,type:H,dataType:"html",data:J,complete:function(M,L){if(L=="success"||L=="notmodified"){F.html(E?o("<div/>").append(M.responseText.replace(/<script(.|\s)*?\/script>/g,"")).find(E):M.responseText)}if(K){F.each(K,[M.responseText,L,M])}}});return this},serialize:function(){return o.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?o.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||/select|textarea/i.test(this.nodeName)||/text|hidden|password|search/i.test(this.type))}).map(function(E,F){var G=o(this).val();return G==null?null:o.isArray(G)?o.map(G,function(I,H){return{name:F.name,value:I}}):{name:F.name,value:G}}).get()}});o.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","),function(E,F){o.fn[F]=function(G){return this.bind(F,G)}});var r=e();o.extend({get:function(E,G,H,F){if(o.isFunction(G)){H=G;G=null}return o.ajax({type:"GET",url:E,data:G,success:H,dataType:F})},getScript:function(E,F){return o.get(E,null,F,"script")},getJSON:function(E,F,G){return o.get(E,F,G,"json")},post:function(E,G,H,F){if(o.isFunction(G)){H=G;G={}}return o.ajax({type:"POST",url:E,data:G,success:H,dataType:F})},ajaxSetup:function(E){o.extend(o.ajaxSettings,E)},ajaxSettings:{url:location.href,global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:function(){return l.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest()},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},ajax:function(M){M=o.extend(true,M,o.extend(true,{},o.ajaxSettings,M));var W,F=/=\?(&|$)/g,R,V,G=M.type.toUpperCase();if(M.data&&M.processData&&typeof M.data!=="string"){M.data=o.param(M.data)}if(M.dataType=="jsonp"){if(G=="GET"){if(!M.url.match(F)){M.url+=(M.url.match(/\?/)?"&":"?")+(M.jsonp||"callback")+"=?"}}else{if(!M.data||!M.data.match(F)){M.data=(M.data?M.data+"&":"")+(M.jsonp||"callback")+"=?"}}M.dataType="json"}if(M.dataType=="json"&&(M.data&&M.data.match(F)||M.url.match(F))){W="jsonp"+r++;if(M.data){M.data=(M.data+"").replace(F,"="+W+"$1")}M.url=M.url.replace(F,"="+W+"$1");M.dataType="script";l[W]=function(X){V=X;I();L();l[W]=g;try{delete l[W]}catch(Y){}if(H){H.removeChild(T)}}}if(M.dataType=="script"&&M.cache==null){M.cache=false}if(M.cache===false&&G=="GET"){var E=e();var U=M.url.replace(/(\?|&)_=.*?(&|$)/,"$1_="+E+"$2");M.url=U+((U==M.url)?(M.url.match(/\?/)?"&":"?")+"_="+E:"")}if(M.data&&G=="GET"){M.url+=(M.url.match(/\?/)?"&":"?")+M.data;M.data=null}if(M.global&&!o.active++){o.event.trigger("ajaxStart")}var Q=/^(\w+:)?\/\/([^\/?#]+)/.exec(M.url);if(M.dataType=="script"&&G=="GET"&&Q&&(Q[1]&&Q[1]!=location.protocol||Q[2]!=location.host)){var H=document.getElementsByTagName("head")[0];var T=document.createElement("script");T.src=M.url;if(M.scriptCharset){T.charset=M.scriptCharset}if(!W){var O=false;T.onload=T.onreadystatechange=function(){if(!O&&(!this.readyState||this.readyState=="loaded"||this.readyState=="complete")){O=true;I();L();T.onload=T.onreadystatechange=null;H.removeChild(T)}}}H.appendChild(T);return g}var K=false;var J=M.xhr();if(M.username){J.open(G,M.url,M.async,M.username,M.password)}else{J.open(G,M.url,M.async)}try{if(M.data){J.setRequestHeader("Content-Type",M.contentType)}if(M.ifModified){J.setRequestHeader("If-Modified-Since",o.lastModified[M.url]||"Thu, 01 Jan 1970 00:00:00 GMT")}J.setRequestHeader("X-Requested-With","XMLHttpRequest");J.setRequestHeader("Accept",M.dataType&&M.accepts[M.dataType]?M.accepts[M.dataType]+", */*":M.accepts._default)}catch(S){}if(M.beforeSend&&M.beforeSend(J,M)===false){if(M.global&&!--o.active){o.event.trigger("ajaxStop")}J.abort();return false}if(M.global){o.event.trigger("ajaxSend",[J,M])}var N=function(X){if(J.readyState==0){if(P){clearInterval(P);P=null;if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}}else{if(!K&&J&&(J.readyState==4||X=="timeout")){K=true;if(P){clearInterval(P);P=null}R=X=="timeout"?"timeout":!o.httpSuccess(J)?"error":M.ifModified&&o.httpNotModified(J,M.url)?"notmodified":"success";if(R=="success"){try{V=o.httpData(J,M.dataType,M)}catch(Z){R="parsererror"}}if(R=="success"){var Y;try{Y=J.getResponseHeader("Last-Modified")}catch(Z){}if(M.ifModified&&Y){o.lastModified[M.url]=Y}if(!W){I()}}else{o.handleError(M,J,R)}L();if(X){J.abort()}if(M.async){J=null}}}};if(M.async){var P=setInterval(N,13);if(M.timeout>0){setTimeout(function(){if(J&&!K){N("timeout")}},M.timeout)}}try{J.send(M.data)}catch(S){o.handleError(M,J,null,S)}if(!M.async){N()}function I(){if(M.success){M.success(V,R)}if(M.global){o.event.trigger("ajaxSuccess",[J,M])}}function L(){if(M.complete){M.complete(J,R)}if(M.global){o.event.trigger("ajaxComplete",[J,M])}if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}return J},handleError:function(F,H,E,G){if(F.error){F.error(H,E,G)}if(F.global){o.event.trigger("ajaxError",[H,F,G])}},active:0,httpSuccess:function(F){try{return !F.status&&location.protocol=="file:"||(F.status>=200&&F.status<300)||F.status==304||F.status==1223}catch(E){}return false},httpNotModified:function(G,E){try{var H=G.getResponseHeader("Last-Modified");return G.status==304||H==o.lastModified[E]}catch(F){}return false},httpData:function(J,H,G){var F=J.getResponseHeader("content-type"),E=H=="xml"||!H&&F&&F.indexOf("xml")>=0,I=E?J.responseXML:J.responseText;if(E&&I.documentElement.tagName=="parsererror"){throw"parsererror"}if(G&&G.dataFilter){I=G.dataFilter(I,H)}if(typeof I==="string"){if(H=="script"){o.globalEval(I)}if(H=="json"){I=l["eval"]("("+I+")")}}return I},param:function(E){var G=[];function H(I,J){G[G.length]=encodeURIComponent(I)+"="+encodeURIComponent(J)}if(o.isArray(E)||E.jquery){o.each(E,function(){H(this.name,this.value)})}else{for(var F in E){if(o.isArray(E[F])){o.each(E[F],function(){H(F,this)})}else{H(F,o.isFunction(E[F])?E[F]():E[F])}}}return G.join("&").replace(/%20/g,"+")}});var m={},n,d=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];function t(F,E){var G={};o.each(d.concat.apply([],d.slice(0,E)),function(){G[this]=F});return G}o.fn.extend({show:function(J,L){if(J){return this.animate(t("show",3),J,L)}else{for(var H=0,F=this.length;H<F;H++){var E=o.data(this[H],"olddisplay");this[H].style.display=E||"";if(o.css(this[H],"display")==="none"){var G=this[H].tagName,K;if(m[G]){K=m[G]}else{var I=o("<"+G+" />").appendTo("body");K=I.css("display");if(K==="none"){K="block"}I.remove();m[G]=K}o.data(this[H],"olddisplay",K)}}for(var H=0,F=this.length;H<F;H++){this[H].style.display=o.data(this[H],"olddisplay")||""}return this}},hide:function(H,I){if(H){return this.animate(t("hide",3),H,I)}else{for(var G=0,F=this.length;G<F;G++){var E=o.data(this[G],"olddisplay");if(!E&&E!=="none"){o.data(this[G],"olddisplay",o.css(this[G],"display"))}}for(var G=0,F=this.length;G<F;G++){this[G].style.display="none"}return this}},_toggle:o.fn.toggle,toggle:function(G,F){var E=typeof G==="boolean";return o.isFunction(G)&&o.isFunction(F)?this._toggle.apply(this,arguments):G==null||E?this.each(function(){var H=E?G:o(this).is(":hidden");o(this)[H?"show":"hide"]()}):this.animate(t("toggle",3),G,F)},fadeTo:function(E,G,F){return this.animate({opacity:G},E,F)},animate:function(I,F,H,G){var E=o.speed(F,H,G);return this[E.queue===false?"each":"queue"](function(){var K=o.extend({},E),M,L=this.nodeType==1&&o(this).is(":hidden"),J=this;for(M in I){if(I[M]=="hide"&&L||I[M]=="show"&&!L){return K.complete.call(this)}if((M=="height"||M=="width")&&this.style){K.display=o.css(this,"display");K.overflow=this.style.overflow}}if(K.overflow!=null){this.style.overflow="hidden"}K.curAnim=o.extend({},I);o.each(I,function(O,S){var R=new o.fx(J,K,O);if(/toggle|show|hide/.test(S)){R[S=="toggle"?L?"show":"hide":S](I)}else{var Q=S.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),T=R.cur(true)||0;if(Q){var N=parseFloat(Q[2]),P=Q[3]||"px";if(P!="px"){J.style[O]=(N||1)+P;T=((N||1)/R.cur(true))*T;J.style[O]=T+P}if(Q[1]){N=((Q[1]=="-="?-1:1)*N)+T}R.custom(T,N,P)}else{R.custom(T,S,"")}}});return true})},stop:function(F,E){var G=o.timers;if(F){this.queue([])}this.each(function(){for(var H=G.length-1;H>=0;H--){if(G[H].elem==this){if(E){G[H](true)}G.splice(H,1)}}});if(!E){this.dequeue()}return this}});o.each({slideDown:t("show",1),slideUp:t("hide",1),slideToggle:t("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(E,F){o.fn[E]=function(G,H){return this.animate(F,G,H)}});o.extend({speed:function(G,H,F){var E=typeof G==="object"?G:{complete:F||!F&&H||o.isFunction(G)&&G,duration:G,easing:F&&H||H&&!o.isFunction(H)&&H};E.duration=o.fx.off?0:typeof E.duration==="number"?E.duration:o.fx.speeds[E.duration]||o.fx.speeds._default;E.old=E.complete;E.complete=function(){if(E.queue!==false){o(this).dequeue()}if(o.isFunction(E.old)){E.old.call(this)}};return E},easing:{linear:function(G,H,E,F){return E+F*G},swing:function(G,H,E,F){return((-Math.cos(G*Math.PI)/2)+0.5)*F+E}},timers:[],fx:function(F,E,G){this.options=E;this.elem=F;this.prop=G;if(!E.orig){E.orig={}}}});o.fx.prototype={update:function(){if(this.options.step){this.options.step.call(this.elem,this.now,this)}(o.fx.step[this.prop]||o.fx.step._default)(this);if((this.prop=="height"||this.prop=="width")&&this.elem.style){this.elem.style.display="block"}},cur:function(F){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null)){return this.elem[this.prop]}var E=parseFloat(o.css(this.elem,this.prop,F));return E&&E>-10000?E:parseFloat(o.curCSS(this.elem,this.prop))||0},custom:function(I,H,G){this.startTime=e();this.start=I;this.end=H;this.unit=G||this.unit||"px";this.now=this.start;this.pos=this.state=0;var E=this;function F(J){return E.step(J)}F.elem=this.elem;if(F()&&o.timers.push(F)&&!n){n=setInterval(function(){var K=o.timers;for(var J=0;J<K.length;J++){if(!K[J]()){K.splice(J--,1)}}if(!K.length){clearInterval(n);n=g}},13)}},show:function(){this.options.orig[this.prop]=o.attr(this.elem.style,this.prop);this.options.show=true;this.custom(this.prop=="width"||this.prop=="height"?1:0,this.cur());o(this.elem).show()},hide:function(){this.options.orig[this.prop]=o.attr(this.elem.style,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(H){var G=e();if(H||G>=this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;var E=true;for(var F in this.options.curAnim){if(this.options.curAnim[F]!==true){E=false}}if(E){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;this.elem.style.display=this.options.display;if(o.css(this.elem,"display")=="none"){this.elem.style.display="block"}}if(this.options.hide){o(this.elem).hide()}if(this.options.hide||this.options.show){for(var I in this.options.curAnim){o.attr(this.elem.style,I,this.options.orig[I])}}this.options.complete.call(this.elem)}return false}else{var J=G-this.startTime;this.state=J/this.options.duration;this.pos=o.easing[this.options.easing||(o.easing.swing?"swing":"linear")](this.state,J,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update()}return true}};o.extend(o.fx,{speeds:{slow:600,fast:200,_default:400},step:{opacity:function(E){o.attr(E.elem.style,"opacity",E.now)},_default:function(E){if(E.elem.style&&E.elem.style[E.prop]!=null){E.elem.style[E.prop]=E.now+E.unit}else{E.elem[E.prop]=E.now}}}});if(document.documentElement.getBoundingClientRect){o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}var G=this[0].getBoundingClientRect(),J=this[0].ownerDocument,F=J.body,E=J.documentElement,L=E.clientTop||F.clientTop||0,K=E.clientLeft||F.clientLeft||0,I=G.top+(self.pageYOffset||o.boxModel&&E.scrollTop||F.scrollTop)-L,H=G.left+(self.pageXOffset||o.boxModel&&E.scrollLeft||F.scrollLeft)-K;return{top:I,left:H}}}else{o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}o.offset.initialized||o.offset.initialize();var J=this[0],G=J.offsetParent,F=J,O=J.ownerDocument,M,H=O.documentElement,K=O.body,L=O.defaultView,E=L.getComputedStyle(J,null),N=J.offsetTop,I=J.offsetLeft;while((J=J.parentNode)&&J!==K&&J!==H){M=L.getComputedStyle(J,null);N-=J.scrollTop,I-=J.scrollLeft;if(J===G){N+=J.offsetTop,I+=J.offsetLeft;if(o.offset.doesNotAddBorder&&!(o.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(J.tagName))){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}F=G,G=J.offsetParent}if(o.offset.subtractsBorderForOverflowNotVisible&&M.overflow!=="visible"){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}E=M}if(E.position==="relative"||E.position==="static"){N+=K.offsetTop,I+=K.offsetLeft}if(E.position==="fixed"){N+=Math.max(H.scrollTop,K.scrollTop),I+=Math.max(H.scrollLeft,K.scrollLeft)}return{top:N,left:I}}}o.offset={initialize:function(){if(this.initialized){return}var L=document.body,F=document.createElement("div"),H,G,N,I,M,E,J=L.style.marginTop,K='<div style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;"><div></div></div><table style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;" cellpadding="0" cellspacing="0"><tr><td></td></tr></table>';M={position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"};for(E in M){F.style[E]=M[E]}F.innerHTML=K;L.insertBefore(F,L.firstChild);H=F.firstChild,G=H.firstChild,I=H.nextSibling.firstChild.firstChild;this.doesNotAddBorder=(G.offsetTop!==5);this.doesAddBorderForTableAndCells=(I.offsetTop===5);H.style.overflow="hidden",H.style.position="relative";this.subtractsBorderForOverflowNotVisible=(G.offsetTop===-5);L.style.marginTop="1px";this.doesNotIncludeMarginInBodyOffset=(L.offsetTop===0);L.style.marginTop=J;L.removeChild(F);this.initialized=true},bodyOffset:function(E){o.offset.initialized||o.offset.initialize();var G=E.offsetTop,F=E.offsetLeft;if(o.offset.doesNotIncludeMarginInBodyOffset){G+=parseInt(o.curCSS(E,"marginTop",true),10)||0,F+=parseInt(o.curCSS(E,"marginLeft",true),10)||0}return{top:G,left:F}}};o.fn.extend({position:function(){var I=0,H=0,F;if(this[0]){var G=this.offsetParent(),J=this.offset(),E=/^body|html$/i.test(G[0].tagName)?{top:0,left:0}:G.offset();J.top-=j(this,"marginTop");J.left-=j(this,"marginLeft");E.top+=j(G,"borderTopWidth");E.left+=j(G,"borderLeftWidth");F={top:J.top-E.top,left:J.left-E.left}}return F},offsetParent:function(){var E=this[0].offsetParent||document.body;while(E&&(!/^body|html$/i.test(E.tagName)&&o.css(E,"position")=="static")){E=E.offsetParent}return o(E)}});o.each(["Left","Top"],function(F,E){var G="scroll"+E;o.fn[G]=function(H){if(!this[0]){return null}return H!==g?this.each(function(){this==l||this==document?l.scrollTo(!F?H:o(l).scrollLeft(),F?H:o(l).scrollTop()):this[G]=H}):this[0]==l||this[0]==document?self[F?"pageYOffset":"pageXOffset"]||o.boxModel&&document.documentElement[G]||document.body[G]:this[0][G]}});o.each(["Height","Width"],function(I,G){var E=I?"Left":"Top",H=I?"Right":"Bottom",F=G.toLowerCase();o.fn["inner"+G]=function(){return this[0]?o.css(this[0],F,false,"padding"):null};o.fn["outer"+G]=function(K){return this[0]?o.css(this[0],F,false,K?"margin":"border"):null};var J=G.toLowerCase();o.fn[J]=function(K){return this[0]==l?document.compatMode=="CSS1Compat"&&document.documentElement["client"+G]||document.body["client"+G]:this[0]==document?Math.max(document.documentElement["client"+G],document.body["scroll"+G],document.documentElement["scroll"+G],document.body["offset"+G],document.documentElement["offset"+G]):K===g?(this.length?o.css(this[0],J):null):this.css(J,typeof K==="string"?K:K+"px")}})})(); \ No newline at end of file
diff --git a/test/farm/html/gold_a/style.css b/test/farm/html/gold_a/style.css
deleted file mode 100644
index b55e4992..00000000
--- a/test/farm/html/gold_a/style.css
+++ /dev/null
@@ -1,182 +0,0 @@
-/* CSS styles for Coverage. */
-/* Page-wide styles */
-html, body, h1, h2, h3, p, td, th {
- margin: 0;
- padding: 0;
- border: 0;
- outline: 0;
- font-weight: inherit;
- font-style: inherit;
- font-size: 100%;
- font-family: inherit;
- vertical-align: baseline;
- }
-
-/* Set baseline grid to 16 pt. */
-body {
- font-family: georgia, serif;
- font-size: 1em;
- }
-
-html>body {
- font-size: 16px;
- }
-
-/* Set base font size to 12/16 */
-p {
- font-size: .75em; /* 12/16 */
- line-height: 1.3333em; /* 16/12 */
- }
-
-table {
- border-collapse: collapse;
- }
-
-a.nav {
- text-decoration: none;
- color: inherit;
- }
-a.nav:hover {
- text-decoration: underline;
- color: inherit;
- }
-
-/* Page structure */
-#header {
- background: #f8f8f8;
- width: 100%;
- border-bottom: 1px solid #eee;
- }
-
-#source {
- padding: 1em;
- font-family: "courier new", monospace;
- }
-
-#footer {
- margin: 1em 3em;
- }
-
-#footer .content {
- padding: 0;
- font-size: 85%;
- font-family: verdana, sans-serif;
- color: #666666;
- font-style: italic;
- }
-
-#index {
- margin: 1em 0 0 3em;
- }
-
-/* Header styles */
-#header .content {
- padding: 1em 3em;
- }
-
-h1 {
- font-size: 1.25em;
-}
-
-h2.stats {
- margin-top: .5em;
- font-size: 1em;
-}
-.stats span {
- border: 1px solid;
- padding: .1em .25em;
- margin: 0 .1em;
- cursor: pointer;
- border-color: #999 #ccc #ccc #999;
-}
-.stats span.hide {
- border-color: #ccc #999 #999 #ccc;
-}
-
-/* Source file styles */
-.linenos p {
- text-align: right;
- margin: 0;
- padding: 0 .5em;
- color: #999999;
- font-family: verdana, sans-serif;
- font-size: .625em; /* 10/16 */
- line-height: 1.6em; /* 16/10 */
- }
-td.text {
- width: 100%;
- }
-.text p {
- margin: 0;
- padding: 0 0 0 .5em;
- border-left: 2px solid #ffffff;
- white-space: nowrap;
- }
-
-.text p.mis {
- background: #ffdddd;
- border-left: 2px solid #ff0000;
- }
-.text p.run {
- background: #ddffdd;
- border-left: 2px solid #00ff00;
- }
-.text p.exc {
- background: #eeeeee;
- border-left: 2px solid #808080;
- }
-.text p.par {
- background: #ffffdd;
- border-left: 2px solid #ffff00;
- }
-.text p.hide {
- background: inherit;
- }
-
-/* Syntax coloring */
-.text .com {
- color: green;
- font-style: italic;
- line-height: 1px;
- }
-.text .key {
- font-weight: bold;
- line-height: 1px;
- }
-.text .str {
- color: #000080;
- }
-
-/* index styles */
-#index td, #index th {
- text-align: right;
- width: 6em;
- padding: .25em 0;
- border-bottom: 1px solid #eee;
- }
-#index th {
- font-style: italic;
- color: #333;
- border-bottom: 1px solid #ccc;
- }
-#index td.name, #index th.name {
- text-align: left;
- width: auto;
- height: 1.5em;
- }
-#index td.name a {
- text-decoration: none;
- color: #000;
- }
-#index td.name a:hover {
- text-decoration: underline;
- color: #000;
- }
-#index tr.total {
- font-weight: bold;
- }
-#index tr.total td {
- padding: .25em 0;
- border-top: 1px solid #ccc;
- border-bottom: none;
- }
diff --git a/test/farm/html/gold_b_branch/b.html b/test/farm/html/gold_b_branch/b.html
new file mode 100644
index 00000000..ba57e964
--- /dev/null
+++ b/test/farm/html/gold_b_branch/b.html
@@ -0,0 +1,113 @@
+<!doctype html PUBLIC "-//W3C//DTD html 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+ <meta http-equiv='Content-Type' content='text/html; charset=utf-8'>
+
+
+ <meta http-equiv='X-UA-Compatible' content='IE=emulateIE7' />
+ <title>Coverage for b: 76%</title>
+ <link rel='stylesheet' href='style.css' type='text/css'>
+ <script type='text/javascript' src='jquery-1.3.2.min.js'></script>
+ <script type='text/javascript' src='coverage_html.js'></script>
+ <script type='text/javascript' charset='utf-8'>
+ jQuery(document).ready(pyfile_ready);
+ </script>
+</head>
+<body id='pyfile'>
+
+<div id='header'>
+ <div class='content'>
+ <h1>Coverage for <b>b</b> :
+ <span class='pc_cov'>76%</span>
+ </h1>
+ <h2 class='stats'>
+ 16 statements
+ <span class='run hide_run' onclick='toggle_lines(this, "run")'>14 run</span>
+ <span class='mis' onclick='toggle_lines(this, "mis")'>2 missing</span>
+ <span class='exc' onclick='toggle_lines(this, "exc")'>0 excluded</span>
+
+ <span class='par run hide_run' onclick='toggle_lines(this, "par")'>3 partial</span>
+
+ </h2>
+ </div>
+</div>
+
+<div id='source'>
+ <table cellspacing='0' cellpadding='0'>
+ <tr>
+ <td class='linenos' valign='top'>
+<p id='n1' class='pln'><a href='#n1'>1</a></p>
+<p id='n2' class='pln'><a href='#n2'>2</a></p>
+<p id='n3' class='stm run hide_run'><a href='#n3'>3</a></p>
+<p id='n4' class='pln'><a href='#n4'>4</a></p>
+<p id='n5' class='stm par run hide_run'><a href='#n5'>5</a></p>
+<p id='n6' class='stm run hide_run'><a href='#n6'>6</a></p>
+<p id='n7' class='pln'><a href='#n7'>7</a></p>
+<p id='n8' class='stm mis'><a href='#n8'>8</a></p>
+<p id='n9' class='pln'><a href='#n9'>9</a></p>
+<p id='n10' class='stm run hide_run'><a href='#n10'>10</a></p>
+<p id='n11' class='pln'><a href='#n11'>11</a></p>
+<p id='n12' class='stm run hide_run'><a href='#n12'>12</a></p>
+<p id='n13' class='pln'><a href='#n13'>13</a></p>
+<p id='n14' class='stm par run hide_run'><a href='#n14'>14</a></p>
+<p id='n15' class='stm run hide_run'><a href='#n15'>15</a></p>
+<p id='n16' class='pln'><a href='#n16'>16</a></p>
+<p id='n17' class='stm run hide_run'><a href='#n17'>17</a></p>
+<p id='n18' class='pln'><a href='#n18'>18</a></p>
+<p id='n19' class='stm run hide_run'><a href='#n19'>19</a></p>
+<p id='n20' class='pln'><a href='#n20'>20</a></p>
+<p id='n21' class='stm par run hide_run'><a href='#n21'>21</a></p>
+<p id='n22' class='stm run hide_run'><a href='#n22'>22</a></p>
+<p id='n23' class='stm run hide_run'><a href='#n23'>23</a></p>
+<p id='n24' class='pln'><a href='#n24'>24</a></p>
+<p id='n25' class='stm mis'><a href='#n25'>25</a></p>
+<p id='n26' class='stm run hide_run'><a href='#n26'>26</a></p>
+<p id='n27' class='pln'><a href='#n27'>27</a></p>
+<p id='n28' class='stm run hide_run'><a href='#n28'>28</a></p>
+
+ </td>
+ <td class='text' valign='top'>
+<p id='t1' class='pln'><span class='com'># A test file for HTML reporting by coverage.</span><span class='strut'>&nbsp;</span></p>
+<p id='t2' class='pln'><span class='strut'>&nbsp;</span></p>
+<p id='t3' class='stm run hide_run'><span class='key'>def</span> <span class='nam'>one</span><span class='op'>(</span><span class='nam'>x</span><span class='op'>)</span><span class='op'>:</span><span class='strut'>&nbsp;</span></p>
+<p id='t4' class='pln'>&nbsp; &nbsp; <span class='com'># This will be a branch that misses the else.</span><span class='strut'>&nbsp;</span></p>
+<p id='t5' class='stm par run hide_run'><span class='annotate' title='no jump to this line number'>8</span>&nbsp; &nbsp; <span class='key'>if</span> <span class='nam'>x</span> <span class='op'>&lt;</span> <span class='num'>2</span><span class='op'>:</span><span class='strut'>&nbsp;</span></p>
+<p id='t6' class='stm run hide_run'>&nbsp; &nbsp; &nbsp; &nbsp; <span class='nam'>a</span> <span class='op'>=</span> <span class='num'>3</span><span class='strut'>&nbsp;</span></p>
+<p id='t7' class='pln'>&nbsp; &nbsp; <span class='key'>else</span><span class='op'>:</span><span class='strut'>&nbsp;</span></p>
+<p id='t8' class='stm mis'>&nbsp; &nbsp; &nbsp; &nbsp; <span class='nam'>a</span> <span class='op'>=</span> <span class='num'>4</span><span class='strut'>&nbsp;</span></p>
+<p id='t9' class='pln'><span class='strut'>&nbsp;</span></p>
+<p id='t10' class='stm run hide_run'><span class='nam'>one</span><span class='op'>(</span><span class='num'>1</span><span class='op'>)</span><span class='strut'>&nbsp;</span></p>
+<p id='t11' class='pln'><span class='strut'>&nbsp;</span></p>
+<p id='t12' class='stm run hide_run'><span class='key'>def</span> <span class='nam'>two</span><span class='op'>(</span><span class='nam'>x</span><span class='op'>)</span><span class='op'>:</span><span class='strut'>&nbsp;</span></p>
+<p id='t13' class='pln'>&nbsp; &nbsp; <span class='com'># A missed else that branches to &quot;exit&quot;</span><span class='strut'>&nbsp;</span></p>
+<p id='t14' class='stm par run hide_run'><span class='annotate' title='no jump to this line number'>exit</span>&nbsp; &nbsp; <span class='key'>if</span> <span class='nam'>x</span><span class='op'>:</span><span class='strut'>&nbsp;</span></p>
+<p id='t15' class='stm run hide_run'>&nbsp; &nbsp; &nbsp; &nbsp; <span class='nam'>a</span> <span class='op'>=</span> <span class='num'>5</span><span class='strut'>&nbsp;</span></p>
+<p id='t16' class='pln'><span class='strut'>&nbsp;</span></p>
+<p id='t17' class='stm run hide_run'><span class='nam'>two</span><span class='op'>(</span><span class='num'>1</span><span class='op'>)</span><span class='strut'>&nbsp;</span></p>
+<p id='t18' class='pln'><span class='strut'>&nbsp;</span></p>
+<p id='t19' class='stm run hide_run'><span class='key'>def</span> <span class='nam'>three_way</span><span class='op'>(</span><span class='op'>)</span><span class='op'>:</span><span class='strut'>&nbsp;</span></p>
+<p id='t20' class='pln'>&nbsp; &nbsp; <span class='com'># for-else can be a three-way branch.</span><span class='strut'>&nbsp;</span></p>
+<p id='t21' class='stm par run hide_run'><span class='annotate' title='no jumps to these line numbers'>25&nbsp;&nbsp; 26</span>&nbsp; &nbsp; <span class='key'>for</span> <span class='nam'>i</span> <span class='key'>in</span> <span class='nam'>range</span><span class='op'>(</span><span class='num'>10</span><span class='op'>)</span><span class='op'>:</span><span class='strut'>&nbsp;</span></p>
+<p id='t22' class='stm run hide_run'>&nbsp; &nbsp; &nbsp; &nbsp; <span class='key'>if</span> <span class='nam'>i</span> <span class='op'>==</span> <span class='num'>3</span><span class='op'>:</span><span class='strut'>&nbsp;</span></p>
+<p id='t23' class='stm run hide_run'>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class='key'>break</span><span class='strut'>&nbsp;</span></p>
+<p id='t24' class='pln'>&nbsp; &nbsp; <span class='key'>else</span><span class='op'>:</span><span class='strut'>&nbsp;</span></p>
+<p id='t25' class='stm mis'>&nbsp; &nbsp; &nbsp; &nbsp; <span class='key'>return</span> <span class='num'>23</span><span class='strut'>&nbsp;</span></p>
+<p id='t26' class='stm run hide_run'>&nbsp; &nbsp; <span class='key'>return</span> <span class='num'>17</span><span class='strut'>&nbsp;</span></p>
+<p id='t27' class='pln'><span class='strut'>&nbsp;</span></p>
+<p id='t28' class='stm run hide_run'><span class='nam'>three_way</span><span class='op'>(</span><span class='op'>)</span><span class='strut'>&nbsp;</span></p>
+
+ </td>
+ </tr>
+ </table>
+</div>
+
+<div id='footer'>
+ <div class='content'>
+ <p>
+ <a class='nav' href='index.html'>&#xab; index</a> &nbsp; &nbsp; <a class='nav' href='http://nedbatchelder.com/code/coverage'>coverage.py v3.3.2a1</a>
+ </p>
+ </div>
+</div>
+
+</body>
+</html>
diff --git a/test/farm/html/gold_b_branch/index.html b/test/farm/html/gold_b_branch/index.html
new file mode 100644
index 00000000..a37f357a
--- /dev/null
+++ b/test/farm/html/gold_b_branch/index.html
@@ -0,0 +1,81 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+ <meta http-equiv='Content-Type' content='text/html; charset=utf-8'>
+ <title>Coverage report</title>
+ <link rel='stylesheet' href='style.css' type='text/css'>
+ <script type='text/javascript' src='jquery-1.3.2.min.js'></script>
+ <script type='text/javascript' src='jquery.tablesorter.min.js'></script>
+ <script type='text/javascript' src='coverage_html.js'></script>
+ <script type='text/javascript' charset='utf-8'>
+ jQuery(document).ready(index_ready);
+ </script>
+</head>
+<body id='indexfile'>
+
+<div id='header'>
+ <div class='content'>
+ <h1>Coverage report:
+ <span class='pc_cov'>76%</span>
+ </h1>
+ </div>
+</div>
+
+<div id='index'>
+ <table class='index'>
+ <thead>
+
+ <tr class='tablehead' title='Click to sort'>
+ <th class='name left headerSortDown'>Module</th>
+ <th>statements</th>
+ <th>missing</th>
+ <th>excluded</th>
+
+ <th>branches</th>
+ <th>partial</th>
+
+ <th class='right'>coverage</th>
+ </tr>
+ </thead>
+
+ <tfoot>
+ <tr class='total'>
+ <td class='name left'>Total</td>
+ <td>16</td>
+ <td>2</td>
+ <td>0</td>
+
+ <td>9</td>
+ <td>4</td>
+
+ <td class='right'>76%</td>
+ </tr>
+ </tfoot>
+ <tbody>
+
+ <tr class='file'>
+ <td class='name left'><a href='b.html'>b</a></td>
+ <td>16</td>
+ <td>2</td>
+ <td>0</td>
+
+ <td>9</td>
+ <td>4</td>
+
+ <td class='right'>76%</td>
+ </tr>
+
+ </tbody>
+ </table>
+</div>
+
+<div id='footer'>
+ <div class='content'>
+ <p>
+ <a class='nav' href='http://nedbatchelder.com/code/coverage'>coverage.py v3.3.2a1</a>
+ </p>
+ </div>
+</div>
+
+</body>
+</html>
diff --git a/test/farm/html/gold_omit_1/index.html b/test/farm/html/gold_omit_1/index.html
new file mode 100644
index 00000000..2612a88e
--- /dev/null
+++ b/test/farm/html/gold_omit_1/index.html
@@ -0,0 +1,99 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+ <meta http-equiv='Content-Type' content='text/html; charset=utf-8'>
+ <title>Coverage report</title>
+ <link rel='stylesheet' href='style.css' type='text/css'>
+ <script type='text/javascript' src='jquery-1.3.2.min.js'></script>
+ <script type='text/javascript' src='jquery.tablesorter.min.js'></script>
+ <script type='text/javascript' src='coverage_html.js'></script>
+ <script type='text/javascript' charset='utf-8'>
+ jQuery(document).ready(index_ready);
+ </script>
+</head>
+<body id='indexfile'>
+
+<div id='header'>
+ <div class='content'>
+ <h1>Coverage report:
+ <span class='pc_cov'>100%</span>
+ </h1>
+ </div>
+</div>
+
+<div id='index'>
+ <table class='index'>
+ <thead>
+
+ <tr class='tablehead' title='Click to sort'>
+ <th class='name left headerSortDown'>Module</th>
+ <th>statements</th>
+ <th>missing</th>
+ <th>excluded</th>
+
+ <th class='right'>coverage</th>
+ </tr>
+ </thead>
+
+ <tfoot>
+ <tr class='total'>
+ <td class='name left'>Total</td>
+ <td>14</td>
+ <td>0</td>
+ <td>0</td>
+
+ <td class='right'>100%</td>
+ </tr>
+ </tfoot>
+ <tbody>
+
+ <tr class='file'>
+ <td class='name left'><a href='m1.html'>m1</a></td>
+ <td>2</td>
+ <td>0</td>
+ <td>0</td>
+
+ <td class='right'>100%</td>
+ </tr>
+
+ <tr class='file'>
+ <td class='name left'><a href='m2.html'>m2</a></td>
+ <td>2</td>
+ <td>0</td>
+ <td>0</td>
+
+ <td class='right'>100%</td>
+ </tr>
+
+ <tr class='file'>
+ <td class='name left'><a href='m3.html'>m3</a></td>
+ <td>2</td>
+ <td>0</td>
+ <td>0</td>
+
+ <td class='right'>100%</td>
+ </tr>
+
+ <tr class='file'>
+ <td class='name left'><a href='main.html'>main</a></td>
+ <td>8</td>
+ <td>0</td>
+ <td>0</td>
+
+ <td class='right'>100%</td>
+ </tr>
+
+ </tbody>
+ </table>
+</div>
+
+<div id='footer'>
+ <div class='content'>
+ <p>
+ <a class='nav' href='http://nedbatchelder.com/code/coverage'>coverage.py v3.3.2a1</a>
+ </p>
+ </div>
+</div>
+
+</body>
+</html>
diff --git a/test/farm/html/gold_omit_1/m1.html b/test/farm/html/gold_omit_1/m1.html
new file mode 100644
index 00000000..20b86df7
--- /dev/null
+++ b/test/farm/html/gold_omit_1/m1.html
@@ -0,0 +1,59 @@
+<!doctype html PUBLIC "-//W3C//DTD html 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+ <meta http-equiv='Content-Type' content='text/html; charset=utf-8'>
+
+
+ <meta http-equiv='X-UA-Compatible' content='IE=emulateIE7' />
+ <title>Coverage for m1: 100%</title>
+ <link rel='stylesheet' href='style.css' type='text/css'>
+ <script type='text/javascript' src='jquery-1.3.2.min.js'></script>
+ <script type='text/javascript' src='coverage_html.js'></script>
+ <script type='text/javascript' charset='utf-8'>
+ jQuery(document).ready(pyfile_ready);
+ </script>
+</head>
+<body id='pyfile'>
+
+<div id='header'>
+ <div class='content'>
+ <h1>Coverage for <b>m1</b> :
+ <span class='pc_cov'>100%</span>
+ </h1>
+ <h2 class='stats'>
+ 2 statements
+ <span class='run hide_run' onclick='toggle_lines(this, "run")'>2 run</span>
+ <span class='mis' onclick='toggle_lines(this, "mis")'>0 missing</span>
+ <span class='exc' onclick='toggle_lines(this, "exc")'>0 excluded</span>
+
+ </h2>
+ </div>
+</div>
+
+<div id='source'>
+ <table cellspacing='0' cellpadding='0'>
+ <tr>
+ <td class='linenos' valign='top'>
+<p id='n1' class='stm run hide_run'><a href='#n1'>1</a></p>
+<p id='n2' class='stm run hide_run'><a href='#n2'>2</a></p>
+
+ </td>
+ <td class='text' valign='top'>
+<p id='t1' class='stm run hide_run'><span class='nam'>m1a</span> <span class='op'>=</span> <span class='num'>1</span><span class='strut'>&nbsp;</span></p>
+<p id='t2' class='stm run hide_run'><span class='nam'>m1b</span> <span class='op'>=</span> <span class='num'>2</span><span class='strut'>&nbsp;</span></p>
+
+ </td>
+ </tr>
+ </table>
+</div>
+
+<div id='footer'>
+ <div class='content'>
+ <p>
+ <a class='nav' href='index.html'>&#xab; index</a> &nbsp; &nbsp; <a class='nav' href='http://nedbatchelder.com/code/coverage'>coverage.py v3.3.2a1</a>
+ </p>
+ </div>
+</div>
+
+</body>
+</html>
diff --git a/test/farm/html/gold_omit_1/m2.html b/test/farm/html/gold_omit_1/m2.html
new file mode 100644
index 00000000..6cbf78ed
--- /dev/null
+++ b/test/farm/html/gold_omit_1/m2.html
@@ -0,0 +1,59 @@
+<!doctype html PUBLIC "-//W3C//DTD html 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+ <meta http-equiv='Content-Type' content='text/html; charset=utf-8'>
+
+
+ <meta http-equiv='X-UA-Compatible' content='IE=emulateIE7' />
+ <title>Coverage for m2: 100%</title>
+ <link rel='stylesheet' href='style.css' type='text/css'>
+ <script type='text/javascript' src='jquery-1.3.2.min.js'></script>
+ <script type='text/javascript' src='coverage_html.js'></script>
+ <script type='text/javascript' charset='utf-8'>
+ jQuery(document).ready(pyfile_ready);
+ </script>
+</head>
+<body id='pyfile'>
+
+<div id='header'>
+ <div class='content'>
+ <h1>Coverage for <b>m2</b> :
+ <span class='pc_cov'>100%</span>
+ </h1>
+ <h2 class='stats'>
+ 2 statements
+ <span class='run hide_run' onclick='toggle_lines(this, "run")'>2 run</span>
+ <span class='mis' onclick='toggle_lines(this, "mis")'>0 missing</span>
+ <span class='exc' onclick='toggle_lines(this, "exc")'>0 excluded</span>
+
+ </h2>
+ </div>
+</div>
+
+<div id='source'>
+ <table cellspacing='0' cellpadding='0'>
+ <tr>
+ <td class='linenos' valign='top'>
+<p id='n1' class='stm run hide_run'><a href='#n1'>1</a></p>
+<p id='n2' class='stm run hide_run'><a href='#n2'>2</a></p>
+
+ </td>
+ <td class='text' valign='top'>
+<p id='t1' class='stm run hide_run'><span class='nam'>m2a</span> <span class='op'>=</span> <span class='num'>1</span><span class='strut'>&nbsp;</span></p>
+<p id='t2' class='stm run hide_run'><span class='nam'>m2b</span> <span class='op'>=</span> <span class='num'>2</span><span class='strut'>&nbsp;</span></p>
+
+ </td>
+ </tr>
+ </table>
+</div>
+
+<div id='footer'>
+ <div class='content'>
+ <p>
+ <a class='nav' href='index.html'>&#xab; index</a> &nbsp; &nbsp; <a class='nav' href='http://nedbatchelder.com/code/coverage'>coverage.py v3.3.2a1</a>
+ </p>
+ </div>
+</div>
+
+</body>
+</html>
diff --git a/test/farm/html/gold_omit_1/m3.html b/test/farm/html/gold_omit_1/m3.html
new file mode 100644
index 00000000..6e618619
--- /dev/null
+++ b/test/farm/html/gold_omit_1/m3.html
@@ -0,0 +1,59 @@
+<!doctype html PUBLIC "-//W3C//DTD html 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+ <meta http-equiv='Content-Type' content='text/html; charset=utf-8'>
+
+
+ <meta http-equiv='X-UA-Compatible' content='IE=emulateIE7' />
+ <title>Coverage for m3: 100%</title>
+ <link rel='stylesheet' href='style.css' type='text/css'>
+ <script type='text/javascript' src='jquery-1.3.2.min.js'></script>
+ <script type='text/javascript' src='coverage_html.js'></script>
+ <script type='text/javascript' charset='utf-8'>
+ jQuery(document).ready(pyfile_ready);
+ </script>
+</head>
+<body id='pyfile'>
+
+<div id='header'>
+ <div class='content'>
+ <h1>Coverage for <b>m3</b> :
+ <span class='pc_cov'>100%</span>
+ </h1>
+ <h2 class='stats'>
+ 2 statements
+ <span class='run hide_run' onclick='toggle_lines(this, "run")'>2 run</span>
+ <span class='mis' onclick='toggle_lines(this, "mis")'>0 missing</span>
+ <span class='exc' onclick='toggle_lines(this, "exc")'>0 excluded</span>
+
+ </h2>
+ </div>
+</div>
+
+<div id='source'>
+ <table cellspacing='0' cellpadding='0'>
+ <tr>
+ <td class='linenos' valign='top'>
+<p id='n1' class='stm run hide_run'><a href='#n1'>1</a></p>
+<p id='n2' class='stm run hide_run'><a href='#n2'>2</a></p>
+
+ </td>
+ <td class='text' valign='top'>
+<p id='t1' class='stm run hide_run'><span class='nam'>m3a</span> <span class='op'>=</span> <span class='num'>1</span><span class='strut'>&nbsp;</span></p>
+<p id='t2' class='stm run hide_run'><span class='nam'>m3b</span> <span class='op'>=</span> <span class='num'>2</span><span class='strut'>&nbsp;</span></p>
+
+ </td>
+ </tr>
+ </table>
+</div>
+
+<div id='footer'>
+ <div class='content'>
+ <p>
+ <a class='nav' href='index.html'>&#xab; index</a> &nbsp; &nbsp; <a class='nav' href='http://nedbatchelder.com/code/coverage'>coverage.py v3.3.2a1</a>
+ </p>
+ </div>
+</div>
+
+</body>
+</html>
diff --git a/test/farm/html/gold_omit_1/main.html b/test/farm/html/gold_omit_1/main.html
new file mode 100644
index 00000000..d7b84c45
--- /dev/null
+++ b/test/farm/html/gold_omit_1/main.html
@@ -0,0 +1,75 @@
+<!doctype html PUBLIC "-//W3C//DTD html 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+ <meta http-equiv='Content-Type' content='text/html; charset=utf-8'>
+
+
+ <meta http-equiv='X-UA-Compatible' content='IE=emulateIE7' />
+ <title>Coverage for main: 100%</title>
+ <link rel='stylesheet' href='style.css' type='text/css'>
+ <script type='text/javascript' src='jquery-1.3.2.min.js'></script>
+ <script type='text/javascript' src='coverage_html.js'></script>
+ <script type='text/javascript' charset='utf-8'>
+ jQuery(document).ready(pyfile_ready);
+ </script>
+</head>
+<body id='pyfile'>
+
+<div id='header'>
+ <div class='content'>
+ <h1>Coverage for <b>main</b> :
+ <span class='pc_cov'>100%</span>
+ </h1>
+ <h2 class='stats'>
+ 8 statements
+ <span class='run hide_run' onclick='toggle_lines(this, "run")'>8 run</span>
+ <span class='mis' onclick='toggle_lines(this, "mis")'>0 missing</span>
+ <span class='exc' onclick='toggle_lines(this, "exc")'>0 excluded</span>
+
+ </h2>
+ </div>
+</div>
+
+<div id='source'>
+ <table cellspacing='0' cellpadding='0'>
+ <tr>
+ <td class='linenos' valign='top'>
+<p id='n1' class='stm run hide_run'><a href='#n1'>1</a></p>
+<p id='n2' class='stm run hide_run'><a href='#n2'>2</a></p>
+<p id='n3' class='stm run hide_run'><a href='#n3'>3</a></p>
+<p id='n4' class='pln'><a href='#n4'>4</a></p>
+<p id='n5' class='stm run hide_run'><a href='#n5'>5</a></p>
+<p id='n6' class='stm run hide_run'><a href='#n6'>6</a></p>
+<p id='n7' class='pln'><a href='#n7'>7</a></p>
+<p id='n8' class='stm run hide_run'><a href='#n8'>8</a></p>
+<p id='n9' class='stm run hide_run'><a href='#n9'>9</a></p>
+<p id='n10' class='stm run hide_run'><a href='#n10'>10</a></p>
+
+ </td>
+ <td class='text' valign='top'>
+<p id='t1' class='stm run hide_run'><span class='key'>import</span> <span class='nam'>m1</span><span class='strut'>&nbsp;</span></p>
+<p id='t2' class='stm run hide_run'><span class='key'>import</span> <span class='nam'>m2</span><span class='strut'>&nbsp;</span></p>
+<p id='t3' class='stm run hide_run'><span class='key'>import</span> <span class='nam'>m3</span><span class='strut'>&nbsp;</span></p>
+<p id='t4' class='pln'><span class='strut'>&nbsp;</span></p>
+<p id='t5' class='stm run hide_run'><span class='nam'>a</span> <span class='op'>=</span> <span class='num'>5</span><span class='strut'>&nbsp;</span></p>
+<p id='t6' class='stm run hide_run'><span class='nam'>b</span> <span class='op'>=</span> <span class='num'>6</span><span class='strut'>&nbsp;</span></p>
+<p id='t7' class='pln'><span class='strut'>&nbsp;</span></p>
+<p id='t8' class='stm run hide_run'><span class='key'>assert</span> <span class='nam'>m1</span><span class='op'>.</span><span class='nam'>m1a</span> <span class='op'>==</span> <span class='num'>1</span><span class='strut'>&nbsp;</span></p>
+<p id='t9' class='stm run hide_run'><span class='key'>assert</span> <span class='nam'>m2</span><span class='op'>.</span><span class='nam'>m2a</span> <span class='op'>==</span> <span class='num'>1</span><span class='strut'>&nbsp;</span></p>
+<p id='t10' class='stm run hide_run'><span class='key'>assert</span> <span class='nam'>m3</span><span class='op'>.</span><span class='nam'>m3a</span> <span class='op'>==</span> <span class='num'>1</span><span class='strut'>&nbsp;</span></p>
+
+ </td>
+ </tr>
+ </table>
+</div>
+
+<div id='footer'>
+ <div class='content'>
+ <p>
+ <a class='nav' href='index.html'>&#xab; index</a> &nbsp; &nbsp; <a class='nav' href='http://nedbatchelder.com/code/coverage'>coverage.py v3.3.2a1</a>
+ </p>
+ </div>
+</div>
+
+</body>
+</html>
diff --git a/test/farm/html/gold_omit_2/index.html b/test/farm/html/gold_omit_2/index.html
new file mode 100644
index 00000000..6fababf4
--- /dev/null
+++ b/test/farm/html/gold_omit_2/index.html
@@ -0,0 +1,90 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+ <meta http-equiv='Content-Type' content='text/html; charset=utf-8'>
+ <title>Coverage report</title>
+ <link rel='stylesheet' href='style.css' type='text/css'>
+ <script type='text/javascript' src='jquery-1.3.2.min.js'></script>
+ <script type='text/javascript' src='jquery.tablesorter.min.js'></script>
+ <script type='text/javascript' src='coverage_html.js'></script>
+ <script type='text/javascript' charset='utf-8'>
+ jQuery(document).ready(index_ready);
+ </script>
+</head>
+<body id='indexfile'>
+
+<div id='header'>
+ <div class='content'>
+ <h1>Coverage report:
+ <span class='pc_cov'>100%</span>
+ </h1>
+ </div>
+</div>
+
+<div id='index'>
+ <table class='index'>
+ <thead>
+
+ <tr class='tablehead' title='Click to sort'>
+ <th class='name left headerSortDown'>Module</th>
+ <th>statements</th>
+ <th>missing</th>
+ <th>excluded</th>
+
+ <th class='right'>coverage</th>
+ </tr>
+ </thead>
+
+ <tfoot>
+ <tr class='total'>
+ <td class='name left'>Total</td>
+ <td>12</td>
+ <td>0</td>
+ <td>0</td>
+
+ <td class='right'>100%</td>
+ </tr>
+ </tfoot>
+ <tbody>
+
+ <tr class='file'>
+ <td class='name left'><a href='m2.html'>m2</a></td>
+ <td>2</td>
+ <td>0</td>
+ <td>0</td>
+
+ <td class='right'>100%</td>
+ </tr>
+
+ <tr class='file'>
+ <td class='name left'><a href='m3.html'>m3</a></td>
+ <td>2</td>
+ <td>0</td>
+ <td>0</td>
+
+ <td class='right'>100%</td>
+ </tr>
+
+ <tr class='file'>
+ <td class='name left'><a href='main.html'>main</a></td>
+ <td>8</td>
+ <td>0</td>
+ <td>0</td>
+
+ <td class='right'>100%</td>
+ </tr>
+
+ </tbody>
+ </table>
+</div>
+
+<div id='footer'>
+ <div class='content'>
+ <p>
+ <a class='nav' href='http://nedbatchelder.com/code/coverage'>coverage.py v3.3.2a1</a>
+ </p>
+ </div>
+</div>
+
+</body>
+</html>
diff --git a/test/farm/html/gold_omit_2/m2.html b/test/farm/html/gold_omit_2/m2.html
new file mode 100644
index 00000000..6cbf78ed
--- /dev/null
+++ b/test/farm/html/gold_omit_2/m2.html
@@ -0,0 +1,59 @@
+<!doctype html PUBLIC "-//W3C//DTD html 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+ <meta http-equiv='Content-Type' content='text/html; charset=utf-8'>
+
+
+ <meta http-equiv='X-UA-Compatible' content='IE=emulateIE7' />
+ <title>Coverage for m2: 100%</title>
+ <link rel='stylesheet' href='style.css' type='text/css'>
+ <script type='text/javascript' src='jquery-1.3.2.min.js'></script>
+ <script type='text/javascript' src='coverage_html.js'></script>
+ <script type='text/javascript' charset='utf-8'>
+ jQuery(document).ready(pyfile_ready);
+ </script>
+</head>
+<body id='pyfile'>
+
+<div id='header'>
+ <div class='content'>
+ <h1>Coverage for <b>m2</b> :
+ <span class='pc_cov'>100%</span>
+ </h1>
+ <h2 class='stats'>
+ 2 statements
+ <span class='run hide_run' onclick='toggle_lines(this, "run")'>2 run</span>
+ <span class='mis' onclick='toggle_lines(this, "mis")'>0 missing</span>
+ <span class='exc' onclick='toggle_lines(this, "exc")'>0 excluded</span>
+
+ </h2>
+ </div>
+</div>
+
+<div id='source'>
+ <table cellspacing='0' cellpadding='0'>
+ <tr>
+ <td class='linenos' valign='top'>
+<p id='n1' class='stm run hide_run'><a href='#n1'>1</a></p>
+<p id='n2' class='stm run hide_run'><a href='#n2'>2</a></p>
+
+ </td>
+ <td class='text' valign='top'>
+<p id='t1' class='stm run hide_run'><span class='nam'>m2a</span> <span class='op'>=</span> <span class='num'>1</span><span class='strut'>&nbsp;</span></p>
+<p id='t2' class='stm run hide_run'><span class='nam'>m2b</span> <span class='op'>=</span> <span class='num'>2</span><span class='strut'>&nbsp;</span></p>
+
+ </td>
+ </tr>
+ </table>
+</div>
+
+<div id='footer'>
+ <div class='content'>
+ <p>
+ <a class='nav' href='index.html'>&#xab; index</a> &nbsp; &nbsp; <a class='nav' href='http://nedbatchelder.com/code/coverage'>coverage.py v3.3.2a1</a>
+ </p>
+ </div>
+</div>
+
+</body>
+</html>
diff --git a/test/farm/html/gold_omit_2/m3.html b/test/farm/html/gold_omit_2/m3.html
new file mode 100644
index 00000000..6e618619
--- /dev/null
+++ b/test/farm/html/gold_omit_2/m3.html
@@ -0,0 +1,59 @@
+<!doctype html PUBLIC "-//W3C//DTD html 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+ <meta http-equiv='Content-Type' content='text/html; charset=utf-8'>
+
+
+ <meta http-equiv='X-UA-Compatible' content='IE=emulateIE7' />
+ <title>Coverage for m3: 100%</title>
+ <link rel='stylesheet' href='style.css' type='text/css'>
+ <script type='text/javascript' src='jquery-1.3.2.min.js'></script>
+ <script type='text/javascript' src='coverage_html.js'></script>
+ <script type='text/javascript' charset='utf-8'>
+ jQuery(document).ready(pyfile_ready);
+ </script>
+</head>
+<body id='pyfile'>
+
+<div id='header'>
+ <div class='content'>
+ <h1>Coverage for <b>m3</b> :
+ <span class='pc_cov'>100%</span>
+ </h1>
+ <h2 class='stats'>
+ 2 statements
+ <span class='run hide_run' onclick='toggle_lines(this, "run")'>2 run</span>
+ <span class='mis' onclick='toggle_lines(this, "mis")'>0 missing</span>
+ <span class='exc' onclick='toggle_lines(this, "exc")'>0 excluded</span>
+
+ </h2>
+ </div>
+</div>
+
+<div id='source'>
+ <table cellspacing='0' cellpadding='0'>
+ <tr>
+ <td class='linenos' valign='top'>
+<p id='n1' class='stm run hide_run'><a href='#n1'>1</a></p>
+<p id='n2' class='stm run hide_run'><a href='#n2'>2</a></p>
+
+ </td>
+ <td class='text' valign='top'>
+<p id='t1' class='stm run hide_run'><span class='nam'>m3a</span> <span class='op'>=</span> <span class='num'>1</span><span class='strut'>&nbsp;</span></p>
+<p id='t2' class='stm run hide_run'><span class='nam'>m3b</span> <span class='op'>=</span> <span class='num'>2</span><span class='strut'>&nbsp;</span></p>
+
+ </td>
+ </tr>
+ </table>
+</div>
+
+<div id='footer'>
+ <div class='content'>
+ <p>
+ <a class='nav' href='index.html'>&#xab; index</a> &nbsp; &nbsp; <a class='nav' href='http://nedbatchelder.com/code/coverage'>coverage.py v3.3.2a1</a>
+ </p>
+ </div>
+</div>
+
+</body>
+</html>
diff --git a/test/farm/html/gold_omit_2/main.html b/test/farm/html/gold_omit_2/main.html
new file mode 100644
index 00000000..d7b84c45
--- /dev/null
+++ b/test/farm/html/gold_omit_2/main.html
@@ -0,0 +1,75 @@
+<!doctype html PUBLIC "-//W3C//DTD html 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+ <meta http-equiv='Content-Type' content='text/html; charset=utf-8'>
+
+
+ <meta http-equiv='X-UA-Compatible' content='IE=emulateIE7' />
+ <title>Coverage for main: 100%</title>
+ <link rel='stylesheet' href='style.css' type='text/css'>
+ <script type='text/javascript' src='jquery-1.3.2.min.js'></script>
+ <script type='text/javascript' src='coverage_html.js'></script>
+ <script type='text/javascript' charset='utf-8'>
+ jQuery(document).ready(pyfile_ready);
+ </script>
+</head>
+<body id='pyfile'>
+
+<div id='header'>
+ <div class='content'>
+ <h1>Coverage for <b>main</b> :
+ <span class='pc_cov'>100%</span>
+ </h1>
+ <h2 class='stats'>
+ 8 statements
+ <span class='run hide_run' onclick='toggle_lines(this, "run")'>8 run</span>
+ <span class='mis' onclick='toggle_lines(this, "mis")'>0 missing</span>
+ <span class='exc' onclick='toggle_lines(this, "exc")'>0 excluded</span>
+
+ </h2>
+ </div>
+</div>
+
+<div id='source'>
+ <table cellspacing='0' cellpadding='0'>
+ <tr>
+ <td class='linenos' valign='top'>
+<p id='n1' class='stm run hide_run'><a href='#n1'>1</a></p>
+<p id='n2' class='stm run hide_run'><a href='#n2'>2</a></p>
+<p id='n3' class='stm run hide_run'><a href='#n3'>3</a></p>
+<p id='n4' class='pln'><a href='#n4'>4</a></p>
+<p id='n5' class='stm run hide_run'><a href='#n5'>5</a></p>
+<p id='n6' class='stm run hide_run'><a href='#n6'>6</a></p>
+<p id='n7' class='pln'><a href='#n7'>7</a></p>
+<p id='n8' class='stm run hide_run'><a href='#n8'>8</a></p>
+<p id='n9' class='stm run hide_run'><a href='#n9'>9</a></p>
+<p id='n10' class='stm run hide_run'><a href='#n10'>10</a></p>
+
+ </td>
+ <td class='text' valign='top'>
+<p id='t1' class='stm run hide_run'><span class='key'>import</span> <span class='nam'>m1</span><span class='strut'>&nbsp;</span></p>
+<p id='t2' class='stm run hide_run'><span class='key'>import</span> <span class='nam'>m2</span><span class='strut'>&nbsp;</span></p>
+<p id='t3' class='stm run hide_run'><span class='key'>import</span> <span class='nam'>m3</span><span class='strut'>&nbsp;</span></p>
+<p id='t4' class='pln'><span class='strut'>&nbsp;</span></p>
+<p id='t5' class='stm run hide_run'><span class='nam'>a</span> <span class='op'>=</span> <span class='num'>5</span><span class='strut'>&nbsp;</span></p>
+<p id='t6' class='stm run hide_run'><span class='nam'>b</span> <span class='op'>=</span> <span class='num'>6</span><span class='strut'>&nbsp;</span></p>
+<p id='t7' class='pln'><span class='strut'>&nbsp;</span></p>
+<p id='t8' class='stm run hide_run'><span class='key'>assert</span> <span class='nam'>m1</span><span class='op'>.</span><span class='nam'>m1a</span> <span class='op'>==</span> <span class='num'>1</span><span class='strut'>&nbsp;</span></p>
+<p id='t9' class='stm run hide_run'><span class='key'>assert</span> <span class='nam'>m2</span><span class='op'>.</span><span class='nam'>m2a</span> <span class='op'>==</span> <span class='num'>1</span><span class='strut'>&nbsp;</span></p>
+<p id='t10' class='stm run hide_run'><span class='key'>assert</span> <span class='nam'>m3</span><span class='op'>.</span><span class='nam'>m3a</span> <span class='op'>==</span> <span class='num'>1</span><span class='strut'>&nbsp;</span></p>
+
+ </td>
+ </tr>
+ </table>
+</div>
+
+<div id='footer'>
+ <div class='content'>
+ <p>
+ <a class='nav' href='index.html'>&#xab; index</a> &nbsp; &nbsp; <a class='nav' href='http://nedbatchelder.com/code/coverage'>coverage.py v3.3.2a1</a>
+ </p>
+ </div>
+</div>
+
+</body>
+</html>
diff --git a/test/farm/html/gold_omit_3/index.html b/test/farm/html/gold_omit_3/index.html
new file mode 100644
index 00000000..919fc965
--- /dev/null
+++ b/test/farm/html/gold_omit_3/index.html
@@ -0,0 +1,81 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+ <meta http-equiv='Content-Type' content='text/html; charset=utf-8'>
+ <title>Coverage report</title>
+ <link rel='stylesheet' href='style.css' type='text/css'>
+ <script type='text/javascript' src='jquery-1.3.2.min.js'></script>
+ <script type='text/javascript' src='jquery.tablesorter.min.js'></script>
+ <script type='text/javascript' src='coverage_html.js'></script>
+ <script type='text/javascript' charset='utf-8'>
+ jQuery(document).ready(index_ready);
+ </script>
+</head>
+<body id='indexfile'>
+
+<div id='header'>
+ <div class='content'>
+ <h1>Coverage report:
+ <span class='pc_cov'>100%</span>
+ </h1>
+ </div>
+</div>
+
+<div id='index'>
+ <table class='index'>
+ <thead>
+
+ <tr class='tablehead' title='Click to sort'>
+ <th class='name left headerSortDown'>Module</th>
+ <th>statements</th>
+ <th>missing</th>
+ <th>excluded</th>
+
+ <th class='right'>coverage</th>
+ </tr>
+ </thead>
+
+ <tfoot>
+ <tr class='total'>
+ <td class='name left'>Total</td>
+ <td>10</td>
+ <td>0</td>
+ <td>0</td>
+
+ <td class='right'>100%</td>
+ </tr>
+ </tfoot>
+ <tbody>
+
+ <tr class='file'>
+ <td class='name left'><a href='m3.html'>m3</a></td>
+ <td>2</td>
+ <td>0</td>
+ <td>0</td>
+
+ <td class='right'>100%</td>
+ </tr>
+
+ <tr class='file'>
+ <td class='name left'><a href='main.html'>main</a></td>
+ <td>8</td>
+ <td>0</td>
+ <td>0</td>
+
+ <td class='right'>100%</td>
+ </tr>
+
+ </tbody>
+ </table>
+</div>
+
+<div id='footer'>
+ <div class='content'>
+ <p>
+ <a class='nav' href='http://nedbatchelder.com/code/coverage'>coverage.py v3.3.2a1</a>
+ </p>
+ </div>
+</div>
+
+</body>
+</html>
diff --git a/test/farm/html/gold_omit_3/m3.html b/test/farm/html/gold_omit_3/m3.html
new file mode 100644
index 00000000..6e618619
--- /dev/null
+++ b/test/farm/html/gold_omit_3/m3.html
@@ -0,0 +1,59 @@
+<!doctype html PUBLIC "-//W3C//DTD html 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+ <meta http-equiv='Content-Type' content='text/html; charset=utf-8'>
+
+
+ <meta http-equiv='X-UA-Compatible' content='IE=emulateIE7' />
+ <title>Coverage for m3: 100%</title>
+ <link rel='stylesheet' href='style.css' type='text/css'>
+ <script type='text/javascript' src='jquery-1.3.2.min.js'></script>
+ <script type='text/javascript' src='coverage_html.js'></script>
+ <script type='text/javascript' charset='utf-8'>
+ jQuery(document).ready(pyfile_ready);
+ </script>
+</head>
+<body id='pyfile'>
+
+<div id='header'>
+ <div class='content'>
+ <h1>Coverage for <b>m3</b> :
+ <span class='pc_cov'>100%</span>
+ </h1>
+ <h2 class='stats'>
+ 2 statements
+ <span class='run hide_run' onclick='toggle_lines(this, "run")'>2 run</span>
+ <span class='mis' onclick='toggle_lines(this, "mis")'>0 missing</span>
+ <span class='exc' onclick='toggle_lines(this, "exc")'>0 excluded</span>
+
+ </h2>
+ </div>
+</div>
+
+<div id='source'>
+ <table cellspacing='0' cellpadding='0'>
+ <tr>
+ <td class='linenos' valign='top'>
+<p id='n1' class='stm run hide_run'><a href='#n1'>1</a></p>
+<p id='n2' class='stm run hide_run'><a href='#n2'>2</a></p>
+
+ </td>
+ <td class='text' valign='top'>
+<p id='t1' class='stm run hide_run'><span class='nam'>m3a</span> <span class='op'>=</span> <span class='num'>1</span><span class='strut'>&nbsp;</span></p>
+<p id='t2' class='stm run hide_run'><span class='nam'>m3b</span> <span class='op'>=</span> <span class='num'>2</span><span class='strut'>&nbsp;</span></p>
+
+ </td>
+ </tr>
+ </table>
+</div>
+
+<div id='footer'>
+ <div class='content'>
+ <p>
+ <a class='nav' href='index.html'>&#xab; index</a> &nbsp; &nbsp; <a class='nav' href='http://nedbatchelder.com/code/coverage'>coverage.py v3.3.2a1</a>
+ </p>
+ </div>
+</div>
+
+</body>
+</html>
diff --git a/test/farm/html/gold_omit_3/main.html b/test/farm/html/gold_omit_3/main.html
new file mode 100644
index 00000000..d7b84c45
--- /dev/null
+++ b/test/farm/html/gold_omit_3/main.html
@@ -0,0 +1,75 @@
+<!doctype html PUBLIC "-//W3C//DTD html 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+ <meta http-equiv='Content-Type' content='text/html; charset=utf-8'>
+
+
+ <meta http-equiv='X-UA-Compatible' content='IE=emulateIE7' />
+ <title>Coverage for main: 100%</title>
+ <link rel='stylesheet' href='style.css' type='text/css'>
+ <script type='text/javascript' src='jquery-1.3.2.min.js'></script>
+ <script type='text/javascript' src='coverage_html.js'></script>
+ <script type='text/javascript' charset='utf-8'>
+ jQuery(document).ready(pyfile_ready);
+ </script>
+</head>
+<body id='pyfile'>
+
+<div id='header'>
+ <div class='content'>
+ <h1>Coverage for <b>main</b> :
+ <span class='pc_cov'>100%</span>
+ </h1>
+ <h2 class='stats'>
+ 8 statements
+ <span class='run hide_run' onclick='toggle_lines(this, "run")'>8 run</span>
+ <span class='mis' onclick='toggle_lines(this, "mis")'>0 missing</span>
+ <span class='exc' onclick='toggle_lines(this, "exc")'>0 excluded</span>
+
+ </h2>
+ </div>
+</div>
+
+<div id='source'>
+ <table cellspacing='0' cellpadding='0'>
+ <tr>
+ <td class='linenos' valign='top'>
+<p id='n1' class='stm run hide_run'><a href='#n1'>1</a></p>
+<p id='n2' class='stm run hide_run'><a href='#n2'>2</a></p>
+<p id='n3' class='stm run hide_run'><a href='#n3'>3</a></p>
+<p id='n4' class='pln'><a href='#n4'>4</a></p>
+<p id='n5' class='stm run hide_run'><a href='#n5'>5</a></p>
+<p id='n6' class='stm run hide_run'><a href='#n6'>6</a></p>
+<p id='n7' class='pln'><a href='#n7'>7</a></p>
+<p id='n8' class='stm run hide_run'><a href='#n8'>8</a></p>
+<p id='n9' class='stm run hide_run'><a href='#n9'>9</a></p>
+<p id='n10' class='stm run hide_run'><a href='#n10'>10</a></p>
+
+ </td>
+ <td class='text' valign='top'>
+<p id='t1' class='stm run hide_run'><span class='key'>import</span> <span class='nam'>m1</span><span class='strut'>&nbsp;</span></p>
+<p id='t2' class='stm run hide_run'><span class='key'>import</span> <span class='nam'>m2</span><span class='strut'>&nbsp;</span></p>
+<p id='t3' class='stm run hide_run'><span class='key'>import</span> <span class='nam'>m3</span><span class='strut'>&nbsp;</span></p>
+<p id='t4' class='pln'><span class='strut'>&nbsp;</span></p>
+<p id='t5' class='stm run hide_run'><span class='nam'>a</span> <span class='op'>=</span> <span class='num'>5</span><span class='strut'>&nbsp;</span></p>
+<p id='t6' class='stm run hide_run'><span class='nam'>b</span> <span class='op'>=</span> <span class='num'>6</span><span class='strut'>&nbsp;</span></p>
+<p id='t7' class='pln'><span class='strut'>&nbsp;</span></p>
+<p id='t8' class='stm run hide_run'><span class='key'>assert</span> <span class='nam'>m1</span><span class='op'>.</span><span class='nam'>m1a</span> <span class='op'>==</span> <span class='num'>1</span><span class='strut'>&nbsp;</span></p>
+<p id='t9' class='stm run hide_run'><span class='key'>assert</span> <span class='nam'>m2</span><span class='op'>.</span><span class='nam'>m2a</span> <span class='op'>==</span> <span class='num'>1</span><span class='strut'>&nbsp;</span></p>
+<p id='t10' class='stm run hide_run'><span class='key'>assert</span> <span class='nam'>m3</span><span class='op'>.</span><span class='nam'>m3a</span> <span class='op'>==</span> <span class='num'>1</span><span class='strut'>&nbsp;</span></p>
+
+ </td>
+ </tr>
+ </table>
+</div>
+
+<div id='footer'>
+ <div class='content'>
+ <p>
+ <a class='nav' href='index.html'>&#xab; index</a> &nbsp; &nbsp; <a class='nav' href='http://nedbatchelder.com/code/coverage'>coverage.py v3.3.2a1</a>
+ </p>
+ </div>
+</div>
+
+</body>
+</html>
diff --git a/test/farm/html/gold_omit_4/index.html b/test/farm/html/gold_omit_4/index.html
new file mode 100644
index 00000000..1d528d39
--- /dev/null
+++ b/test/farm/html/gold_omit_4/index.html
@@ -0,0 +1,90 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+ <meta http-equiv='Content-Type' content='text/html; charset=utf-8'>
+ <title>Coverage report</title>
+ <link rel='stylesheet' href='style.css' type='text/css'>
+ <script type='text/javascript' src='jquery-1.3.2.min.js'></script>
+ <script type='text/javascript' src='jquery.tablesorter.min.js'></script>
+ <script type='text/javascript' src='coverage_html.js'></script>
+ <script type='text/javascript' charset='utf-8'>
+ jQuery(document).ready(index_ready);
+ </script>
+</head>
+<body id='indexfile'>
+
+<div id='header'>
+ <div class='content'>
+ <h1>Coverage report:
+ <span class='pc_cov'>100%</span>
+ </h1>
+ </div>
+</div>
+
+<div id='index'>
+ <table class='index'>
+ <thead>
+
+ <tr class='tablehead' title='Click to sort'>
+ <th class='name left headerSortDown'>Module</th>
+ <th>statements</th>
+ <th>missing</th>
+ <th>excluded</th>
+
+ <th class='right'>coverage</th>
+ </tr>
+ </thead>
+
+ <tfoot>
+ <tr class='total'>
+ <td class='name left'>Total</td>
+ <td>12</td>
+ <td>0</td>
+ <td>0</td>
+
+ <td class='right'>100%</td>
+ </tr>
+ </tfoot>
+ <tbody>
+
+ <tr class='file'>
+ <td class='name left'><a href='m1.html'>m1</a></td>
+ <td>2</td>
+ <td>0</td>
+ <td>0</td>
+
+ <td class='right'>100%</td>
+ </tr>
+
+ <tr class='file'>
+ <td class='name left'><a href='m3.html'>m3</a></td>
+ <td>2</td>
+ <td>0</td>
+ <td>0</td>
+
+ <td class='right'>100%</td>
+ </tr>
+
+ <tr class='file'>
+ <td class='name left'><a href='main.html'>main</a></td>
+ <td>8</td>
+ <td>0</td>
+ <td>0</td>
+
+ <td class='right'>100%</td>
+ </tr>
+
+ </tbody>
+ </table>
+</div>
+
+<div id='footer'>
+ <div class='content'>
+ <p>
+ <a class='nav' href='http://nedbatchelder.com/code/coverage'>coverage.py v3.3.2a1</a>
+ </p>
+ </div>
+</div>
+
+</body>
+</html>
diff --git a/test/farm/html/gold_omit_4/m1.html b/test/farm/html/gold_omit_4/m1.html
new file mode 100644
index 00000000..20b86df7
--- /dev/null
+++ b/test/farm/html/gold_omit_4/m1.html
@@ -0,0 +1,59 @@
+<!doctype html PUBLIC "-//W3C//DTD html 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+ <meta http-equiv='Content-Type' content='text/html; charset=utf-8'>
+
+
+ <meta http-equiv='X-UA-Compatible' content='IE=emulateIE7' />
+ <title>Coverage for m1: 100%</title>
+ <link rel='stylesheet' href='style.css' type='text/css'>
+ <script type='text/javascript' src='jquery-1.3.2.min.js'></script>
+ <script type='text/javascript' src='coverage_html.js'></script>
+ <script type='text/javascript' charset='utf-8'>
+ jQuery(document).ready(pyfile_ready);
+ </script>
+</head>
+<body id='pyfile'>
+
+<div id='header'>
+ <div class='content'>
+ <h1>Coverage for <b>m1</b> :
+ <span class='pc_cov'>100%</span>
+ </h1>
+ <h2 class='stats'>
+ 2 statements
+ <span class='run hide_run' onclick='toggle_lines(this, "run")'>2 run</span>
+ <span class='mis' onclick='toggle_lines(this, "mis")'>0 missing</span>
+ <span class='exc' onclick='toggle_lines(this, "exc")'>0 excluded</span>
+
+ </h2>
+ </div>
+</div>
+
+<div id='source'>
+ <table cellspacing='0' cellpadding='0'>
+ <tr>
+ <td class='linenos' valign='top'>
+<p id='n1' class='stm run hide_run'><a href='#n1'>1</a></p>
+<p id='n2' class='stm run hide_run'><a href='#n2'>2</a></p>
+
+ </td>
+ <td class='text' valign='top'>
+<p id='t1' class='stm run hide_run'><span class='nam'>m1a</span> <span class='op'>=</span> <span class='num'>1</span><span class='strut'>&nbsp;</span></p>
+<p id='t2' class='stm run hide_run'><span class='nam'>m1b</span> <span class='op'>=</span> <span class='num'>2</span><span class='strut'>&nbsp;</span></p>
+
+ </td>
+ </tr>
+ </table>
+</div>
+
+<div id='footer'>
+ <div class='content'>
+ <p>
+ <a class='nav' href='index.html'>&#xab; index</a> &nbsp; &nbsp; <a class='nav' href='http://nedbatchelder.com/code/coverage'>coverage.py v3.3.2a1</a>
+ </p>
+ </div>
+</div>
+
+</body>
+</html>
diff --git a/test/farm/html/gold_omit_4/m3.html b/test/farm/html/gold_omit_4/m3.html
new file mode 100644
index 00000000..6e618619
--- /dev/null
+++ b/test/farm/html/gold_omit_4/m3.html
@@ -0,0 +1,59 @@
+<!doctype html PUBLIC "-//W3C//DTD html 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+ <meta http-equiv='Content-Type' content='text/html; charset=utf-8'>
+
+
+ <meta http-equiv='X-UA-Compatible' content='IE=emulateIE7' />
+ <title>Coverage for m3: 100%</title>
+ <link rel='stylesheet' href='style.css' type='text/css'>
+ <script type='text/javascript' src='jquery-1.3.2.min.js'></script>
+ <script type='text/javascript' src='coverage_html.js'></script>
+ <script type='text/javascript' charset='utf-8'>
+ jQuery(document).ready(pyfile_ready);
+ </script>
+</head>
+<body id='pyfile'>
+
+<div id='header'>
+ <div class='content'>
+ <h1>Coverage for <b>m3</b> :
+ <span class='pc_cov'>100%</span>
+ </h1>
+ <h2 class='stats'>
+ 2 statements
+ <span class='run hide_run' onclick='toggle_lines(this, "run")'>2 run</span>
+ <span class='mis' onclick='toggle_lines(this, "mis")'>0 missing</span>
+ <span class='exc' onclick='toggle_lines(this, "exc")'>0 excluded</span>
+
+ </h2>
+ </div>
+</div>
+
+<div id='source'>
+ <table cellspacing='0' cellpadding='0'>
+ <tr>
+ <td class='linenos' valign='top'>
+<p id='n1' class='stm run hide_run'><a href='#n1'>1</a></p>
+<p id='n2' class='stm run hide_run'><a href='#n2'>2</a></p>
+
+ </td>
+ <td class='text' valign='top'>
+<p id='t1' class='stm run hide_run'><span class='nam'>m3a</span> <span class='op'>=</span> <span class='num'>1</span><span class='strut'>&nbsp;</span></p>
+<p id='t2' class='stm run hide_run'><span class='nam'>m3b</span> <span class='op'>=</span> <span class='num'>2</span><span class='strut'>&nbsp;</span></p>
+
+ </td>
+ </tr>
+ </table>
+</div>
+
+<div id='footer'>
+ <div class='content'>
+ <p>
+ <a class='nav' href='index.html'>&#xab; index</a> &nbsp; &nbsp; <a class='nav' href='http://nedbatchelder.com/code/coverage'>coverage.py v3.3.2a1</a>
+ </p>
+ </div>
+</div>
+
+</body>
+</html>
diff --git a/test/farm/html/gold_omit_4/main.html b/test/farm/html/gold_omit_4/main.html
new file mode 100644
index 00000000..d7b84c45
--- /dev/null
+++ b/test/farm/html/gold_omit_4/main.html
@@ -0,0 +1,75 @@
+<!doctype html PUBLIC "-//W3C//DTD html 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+ <meta http-equiv='Content-Type' content='text/html; charset=utf-8'>
+
+
+ <meta http-equiv='X-UA-Compatible' content='IE=emulateIE7' />
+ <title>Coverage for main: 100%</title>
+ <link rel='stylesheet' href='style.css' type='text/css'>
+ <script type='text/javascript' src='jquery-1.3.2.min.js'></script>
+ <script type='text/javascript' src='coverage_html.js'></script>
+ <script type='text/javascript' charset='utf-8'>
+ jQuery(document).ready(pyfile_ready);
+ </script>
+</head>
+<body id='pyfile'>
+
+<div id='header'>
+ <div class='content'>
+ <h1>Coverage for <b>main</b> :
+ <span class='pc_cov'>100%</span>
+ </h1>
+ <h2 class='stats'>
+ 8 statements
+ <span class='run hide_run' onclick='toggle_lines(this, "run")'>8 run</span>
+ <span class='mis' onclick='toggle_lines(this, "mis")'>0 missing</span>
+ <span class='exc' onclick='toggle_lines(this, "exc")'>0 excluded</span>
+
+ </h2>
+ </div>
+</div>
+
+<div id='source'>
+ <table cellspacing='0' cellpadding='0'>
+ <tr>
+ <td class='linenos' valign='top'>
+<p id='n1' class='stm run hide_run'><a href='#n1'>1</a></p>
+<p id='n2' class='stm run hide_run'><a href='#n2'>2</a></p>
+<p id='n3' class='stm run hide_run'><a href='#n3'>3</a></p>
+<p id='n4' class='pln'><a href='#n4'>4</a></p>
+<p id='n5' class='stm run hide_run'><a href='#n5'>5</a></p>
+<p id='n6' class='stm run hide_run'><a href='#n6'>6</a></p>
+<p id='n7' class='pln'><a href='#n7'>7</a></p>
+<p id='n8' class='stm run hide_run'><a href='#n8'>8</a></p>
+<p id='n9' class='stm run hide_run'><a href='#n9'>9</a></p>
+<p id='n10' class='stm run hide_run'><a href='#n10'>10</a></p>
+
+ </td>
+ <td class='text' valign='top'>
+<p id='t1' class='stm run hide_run'><span class='key'>import</span> <span class='nam'>m1</span><span class='strut'>&nbsp;</span></p>
+<p id='t2' class='stm run hide_run'><span class='key'>import</span> <span class='nam'>m2</span><span class='strut'>&nbsp;</span></p>
+<p id='t3' class='stm run hide_run'><span class='key'>import</span> <span class='nam'>m3</span><span class='strut'>&nbsp;</span></p>
+<p id='t4' class='pln'><span class='strut'>&nbsp;</span></p>
+<p id='t5' class='stm run hide_run'><span class='nam'>a</span> <span class='op'>=</span> <span class='num'>5</span><span class='strut'>&nbsp;</span></p>
+<p id='t6' class='stm run hide_run'><span class='nam'>b</span> <span class='op'>=</span> <span class='num'>6</span><span class='strut'>&nbsp;</span></p>
+<p id='t7' class='pln'><span class='strut'>&nbsp;</span></p>
+<p id='t8' class='stm run hide_run'><span class='key'>assert</span> <span class='nam'>m1</span><span class='op'>.</span><span class='nam'>m1a</span> <span class='op'>==</span> <span class='num'>1</span><span class='strut'>&nbsp;</span></p>
+<p id='t9' class='stm run hide_run'><span class='key'>assert</span> <span class='nam'>m2</span><span class='op'>.</span><span class='nam'>m2a</span> <span class='op'>==</span> <span class='num'>1</span><span class='strut'>&nbsp;</span></p>
+<p id='t10' class='stm run hide_run'><span class='key'>assert</span> <span class='nam'>m3</span><span class='op'>.</span><span class='nam'>m3a</span> <span class='op'>==</span> <span class='num'>1</span><span class='strut'>&nbsp;</span></p>
+
+ </td>
+ </tr>
+ </table>
+</div>
+
+<div id='footer'>
+ <div class='content'>
+ <p>
+ <a class='nav' href='index.html'>&#xab; index</a> &nbsp; &nbsp; <a class='nav' href='http://nedbatchelder.com/code/coverage'>coverage.py v3.3.2a1</a>
+ </p>
+ </div>
+</div>
+
+</body>
+</html>
diff --git a/test/farm/html/gold_omit_5/index.html b/test/farm/html/gold_omit_5/index.html
new file mode 100644
index 00000000..61eeceb8
--- /dev/null
+++ b/test/farm/html/gold_omit_5/index.html
@@ -0,0 +1,81 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+ <meta http-equiv='Content-Type' content='text/html; charset=utf-8'>
+ <title>Coverage report</title>
+ <link rel='stylesheet' href='style.css' type='text/css'>
+ <script type='text/javascript' src='jquery-1.3.2.min.js'></script>
+ <script type='text/javascript' src='jquery.tablesorter.min.js'></script>
+ <script type='text/javascript' src='coverage_html.js'></script>
+ <script type='text/javascript' charset='utf-8'>
+ jQuery(document).ready(index_ready);
+ </script>
+</head>
+<body id='indexfile'>
+
+<div id='header'>
+ <div class='content'>
+ <h1>Coverage report:
+ <span class='pc_cov'>100%</span>
+ </h1>
+ </div>
+</div>
+
+<div id='index'>
+ <table class='index'>
+ <thead>
+
+ <tr class='tablehead' title='Click to sort'>
+ <th class='name left headerSortDown'>Module</th>
+ <th>statements</th>
+ <th>missing</th>
+ <th>excluded</th>
+
+ <th class='right'>coverage</th>
+ </tr>
+ </thead>
+
+ <tfoot>
+ <tr class='total'>
+ <td class='name left'>Total</td>
+ <td>10</td>
+ <td>0</td>
+ <td>0</td>
+
+ <td class='right'>100%</td>
+ </tr>
+ </tfoot>
+ <tbody>
+
+ <tr class='file'>
+ <td class='name left'><a href='m1.html'>m1</a></td>
+ <td>2</td>
+ <td>0</td>
+ <td>0</td>
+
+ <td class='right'>100%</td>
+ </tr>
+
+ <tr class='file'>
+ <td class='name left'><a href='main.html'>main</a></td>
+ <td>8</td>
+ <td>0</td>
+ <td>0</td>
+
+ <td class='right'>100%</td>
+ </tr>
+
+ </tbody>
+ </table>
+</div>
+
+<div id='footer'>
+ <div class='content'>
+ <p>
+ <a class='nav' href='http://nedbatchelder.com/code/coverage'>coverage.py v3.3.2a1</a>
+ </p>
+ </div>
+</div>
+
+</body>
+</html>
diff --git a/test/farm/html/gold_omit_5/m1.html b/test/farm/html/gold_omit_5/m1.html
new file mode 100644
index 00000000..20b86df7
--- /dev/null
+++ b/test/farm/html/gold_omit_5/m1.html
@@ -0,0 +1,59 @@
+<!doctype html PUBLIC "-//W3C//DTD html 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+ <meta http-equiv='Content-Type' content='text/html; charset=utf-8'>
+
+
+ <meta http-equiv='X-UA-Compatible' content='IE=emulateIE7' />
+ <title>Coverage for m1: 100%</title>
+ <link rel='stylesheet' href='style.css' type='text/css'>
+ <script type='text/javascript' src='jquery-1.3.2.min.js'></script>
+ <script type='text/javascript' src='coverage_html.js'></script>
+ <script type='text/javascript' charset='utf-8'>
+ jQuery(document).ready(pyfile_ready);
+ </script>
+</head>
+<body id='pyfile'>
+
+<div id='header'>
+ <div class='content'>
+ <h1>Coverage for <b>m1</b> :
+ <span class='pc_cov'>100%</span>
+ </h1>
+ <h2 class='stats'>
+ 2 statements
+ <span class='run hide_run' onclick='toggle_lines(this, "run")'>2 run</span>
+ <span class='mis' onclick='toggle_lines(this, "mis")'>0 missing</span>
+ <span class='exc' onclick='toggle_lines(this, "exc")'>0 excluded</span>
+
+ </h2>
+ </div>
+</div>
+
+<div id='source'>
+ <table cellspacing='0' cellpadding='0'>
+ <tr>
+ <td class='linenos' valign='top'>
+<p id='n1' class='stm run hide_run'><a href='#n1'>1</a></p>
+<p id='n2' class='stm run hide_run'><a href='#n2'>2</a></p>
+
+ </td>
+ <td class='text' valign='top'>
+<p id='t1' class='stm run hide_run'><span class='nam'>m1a</span> <span class='op'>=</span> <span class='num'>1</span><span class='strut'>&nbsp;</span></p>
+<p id='t2' class='stm run hide_run'><span class='nam'>m1b</span> <span class='op'>=</span> <span class='num'>2</span><span class='strut'>&nbsp;</span></p>
+
+ </td>
+ </tr>
+ </table>
+</div>
+
+<div id='footer'>
+ <div class='content'>
+ <p>
+ <a class='nav' href='index.html'>&#xab; index</a> &nbsp; &nbsp; <a class='nav' href='http://nedbatchelder.com/code/coverage'>coverage.py v3.3.2a1</a>
+ </p>
+ </div>
+</div>
+
+</body>
+</html>
diff --git a/test/farm/html/gold_omit_5/main.html b/test/farm/html/gold_omit_5/main.html
new file mode 100644
index 00000000..d7b84c45
--- /dev/null
+++ b/test/farm/html/gold_omit_5/main.html
@@ -0,0 +1,75 @@
+<!doctype html PUBLIC "-//W3C//DTD html 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+ <meta http-equiv='Content-Type' content='text/html; charset=utf-8'>
+
+
+ <meta http-equiv='X-UA-Compatible' content='IE=emulateIE7' />
+ <title>Coverage for main: 100%</title>
+ <link rel='stylesheet' href='style.css' type='text/css'>
+ <script type='text/javascript' src='jquery-1.3.2.min.js'></script>
+ <script type='text/javascript' src='coverage_html.js'></script>
+ <script type='text/javascript' charset='utf-8'>
+ jQuery(document).ready(pyfile_ready);
+ </script>
+</head>
+<body id='pyfile'>
+
+<div id='header'>
+ <div class='content'>
+ <h1>Coverage for <b>main</b> :
+ <span class='pc_cov'>100%</span>
+ </h1>
+ <h2 class='stats'>
+ 8 statements
+ <span class='run hide_run' onclick='toggle_lines(this, "run")'>8 run</span>
+ <span class='mis' onclick='toggle_lines(this, "mis")'>0 missing</span>
+ <span class='exc' onclick='toggle_lines(this, "exc")'>0 excluded</span>
+
+ </h2>
+ </div>
+</div>
+
+<div id='source'>
+ <table cellspacing='0' cellpadding='0'>
+ <tr>
+ <td class='linenos' valign='top'>
+<p id='n1' class='stm run hide_run'><a href='#n1'>1</a></p>
+<p id='n2' class='stm run hide_run'><a href='#n2'>2</a></p>
+<p id='n3' class='stm run hide_run'><a href='#n3'>3</a></p>
+<p id='n4' class='pln'><a href='#n4'>4</a></p>
+<p id='n5' class='stm run hide_run'><a href='#n5'>5</a></p>
+<p id='n6' class='stm run hide_run'><a href='#n6'>6</a></p>
+<p id='n7' class='pln'><a href='#n7'>7</a></p>
+<p id='n8' class='stm run hide_run'><a href='#n8'>8</a></p>
+<p id='n9' class='stm run hide_run'><a href='#n9'>9</a></p>
+<p id='n10' class='stm run hide_run'><a href='#n10'>10</a></p>
+
+ </td>
+ <td class='text' valign='top'>
+<p id='t1' class='stm run hide_run'><span class='key'>import</span> <span class='nam'>m1</span><span class='strut'>&nbsp;</span></p>
+<p id='t2' class='stm run hide_run'><span class='key'>import</span> <span class='nam'>m2</span><span class='strut'>&nbsp;</span></p>
+<p id='t3' class='stm run hide_run'><span class='key'>import</span> <span class='nam'>m3</span><span class='strut'>&nbsp;</span></p>
+<p id='t4' class='pln'><span class='strut'>&nbsp;</span></p>
+<p id='t5' class='stm run hide_run'><span class='nam'>a</span> <span class='op'>=</span> <span class='num'>5</span><span class='strut'>&nbsp;</span></p>
+<p id='t6' class='stm run hide_run'><span class='nam'>b</span> <span class='op'>=</span> <span class='num'>6</span><span class='strut'>&nbsp;</span></p>
+<p id='t7' class='pln'><span class='strut'>&nbsp;</span></p>
+<p id='t8' class='stm run hide_run'><span class='key'>assert</span> <span class='nam'>m1</span><span class='op'>.</span><span class='nam'>m1a</span> <span class='op'>==</span> <span class='num'>1</span><span class='strut'>&nbsp;</span></p>
+<p id='t9' class='stm run hide_run'><span class='key'>assert</span> <span class='nam'>m2</span><span class='op'>.</span><span class='nam'>m2a</span> <span class='op'>==</span> <span class='num'>1</span><span class='strut'>&nbsp;</span></p>
+<p id='t10' class='stm run hide_run'><span class='key'>assert</span> <span class='nam'>m3</span><span class='op'>.</span><span class='nam'>m3a</span> <span class='op'>==</span> <span class='num'>1</span><span class='strut'>&nbsp;</span></p>
+
+ </td>
+ </tr>
+ </table>
+</div>
+
+<div id='footer'>
+ <div class='content'>
+ <p>
+ <a class='nav' href='index.html'>&#xab; index</a> &nbsp; &nbsp; <a class='nav' href='http://nedbatchelder.com/code/coverage'>coverage.py v3.3.2a1</a>
+ </p>
+ </div>
+</div>
+
+</body>
+</html>
diff --git a/test/farm/html/gold_other/blah_blah_other.html b/test/farm/html/gold_other/blah_blah_other.html
index 8f25d256..46e05aaf 100644
--- a/test/farm/html/gold_other/blah_blah_other.html
+++ b/test/farm/html/gold_other/blah_blah_other.html
@@ -1,57 +1,62 @@
<!doctype html PUBLIC "-//W3C//DTD html 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
-<title>Coverage for c:\ned\coverage\trunk\test\farm\html\othersrc\other</title>
-<link rel='stylesheet' href='style.css' type='text/css'>
-<script src='jquery-1.3.2.min.js'></script>
-<script>
-function toggle_lines(btn, cls) {
- var btn = $(btn);
- if (btn.hasClass("hide")) {
- $("#source ."+cls).removeClass("hide");
- btn.removeClass("hide");
- }
- else {
- $("#source ."+cls).addClass("hide");
- btn.addClass("hide");
- }
-}
-</script>
+ <meta http-equiv='Content-Type' content='text/html; charset=utf-8'>
+
+
+ <meta http-equiv='X-UA-Compatible' content='IE=emulateIE7' />
+ <title>Coverage for othersrc\other: 100%</title>
+ <link rel='stylesheet' href='style.css' type='text/css'>
+ <script type='text/javascript' src='jquery-1.3.2.min.js'></script>
+ <script type='text/javascript' src='coverage_html.js'></script>
+ <script type='text/javascript' charset='utf-8'>
+ jQuery(document).ready(pyfile_ready);
+ </script>
</head>
-<body>
+<body id='pyfile'>
+
<div id='header'>
<div class='content'>
- <h1>Coverage for <b>c:\ned\coverage\trunk\test\farm\html\othersrc\other</b> :
+ <h1>Coverage for <b>othersrc\other</b> :
<span class='pc_cov'>100%</span>
</h1>
<h2 class='stats'>
1 statements
- <span class='run hide' onclick='toggle_lines(this, "run")'>1 run</span>
- <span class='exc' onclick='toggle_lines(this, "exc")'>0 excluded</span>
+ <span class='run hide_run' onclick='toggle_lines(this, "run")'>1 run</span>
<span class='mis' onclick='toggle_lines(this, "mis")'>0 missing</span>
+ <span class='exc' onclick='toggle_lines(this, "exc")'>0 excluded</span>
+
</h2>
</div>
</div>
<div id='source'>
-<table cellspacing='0' cellpadding='0'>
-<tr>
-<td class='linenos' valign='top'>
-<p class='pln'>1</p>
-<p class='pln'>2</p>
-<p class='pln'>3</p>
-<p class='stm run hide'>4</p>
-
-</td>
-<td class='text' valign='top'>
-<p class='pln'><span class='com'># A file in another directory.&nbsp; We&#39;re checking that it ends up in the</span><span class="strut">&nbsp;</span></p>
-<p class='pln'><span class='com'># HTML report.</span><span class="strut">&nbsp;</span></p>
-<p class='pln'><span class="strut">&nbsp;</span></p>
-<p class='stm run hide'><span class='key'>print</span><span class='op'>(</span><span class='str'>&quot;This is the other src!&quot;</span><span class='op'>)</span><span class="strut">&nbsp;</span></p>
-
-</td>
-</tr>
-</table>
+ <table cellspacing='0' cellpadding='0'>
+ <tr>
+ <td class='linenos' valign='top'>
+<p id='n1' class='pln'><a href='#n1'>1</a></p>
+<p id='n2' class='pln'><a href='#n2'>2</a></p>
+<p id='n3' class='pln'><a href='#n3'>3</a></p>
+<p id='n4' class='stm run hide_run'><a href='#n4'>4</a></p>
+
+ </td>
+ <td class='text' valign='top'>
+<p id='t1' class='pln'><span class='com'># A file in another directory.&nbsp; We&#39;re checking that it ends up in the</span><span class='strut'>&nbsp;</span></p>
+<p id='t2' class='pln'><span class='com'># HTML report.</span><span class='strut'>&nbsp;</span></p>
+<p id='t3' class='pln'><span class='strut'>&nbsp;</span></p>
+<p id='t4' class='stm run hide_run'><span class='key'>print</span><span class='op'>(</span><span class='str'>&quot;This is the other src!&quot;</span><span class='op'>)</span><span class='strut'>&nbsp;</span></p>
+
+ </td>
+ </tr>
+ </table>
+</div>
+
+<div id='footer'>
+ <div class='content'>
+ <p>
+ <a class='nav' href='index.html'>&#xab; index</a> &nbsp; &nbsp; <a class='nav' href='http://nedbatchelder.com/code/coverage'>coverage.py v3.3.2a1</a>
+ </p>
+ </div>
</div>
</body>
diff --git a/test/farm/html/gold_other/here.html b/test/farm/html/gold_other/here.html
index a6e70dff..1ae248f5 100644
--- a/test/farm/html/gold_other/here.html
+++ b/test/farm/html/gold_other/here.html
@@ -1,24 +1,20 @@
<!doctype html PUBLIC "-//W3C//DTD html 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
-<title>Coverage for here</title>
-<link rel='stylesheet' href='style.css' type='text/css'>
-<script src='jquery-1.3.2.min.js'></script>
-<script>
-function toggle_lines(btn, cls) {
- var btn = $(btn);
- if (btn.hasClass("hide")) {
- $("#source ."+cls).removeClass("hide");
- btn.removeClass("hide");
- }
- else {
- $("#source ."+cls).addClass("hide");
- btn.addClass("hide");
- }
-}
-</script>
+ <meta http-equiv='Content-Type' content='text/html; charset=utf-8'>
+
+
+ <meta http-equiv='X-UA-Compatible' content='IE=emulateIE7' />
+ <title>Coverage for here: 75%</title>
+ <link rel='stylesheet' href='style.css' type='text/css'>
+ <script type='text/javascript' src='jquery-1.3.2.min.js'></script>
+ <script type='text/javascript' src='coverage_html.js'></script>
+ <script type='text/javascript' charset='utf-8'>
+ jQuery(document).ready(pyfile_ready);
+ </script>
</head>
-<body>
+<body id='pyfile'>
+
<div id='header'>
<div class='content'>
<h1>Coverage for <b>here</b> :
@@ -26,40 +22,49 @@ function toggle_lines(btn, cls) {
</h1>
<h2 class='stats'>
4 statements
- <span class='run hide' onclick='toggle_lines(this, "run")'>3 run</span>
- <span class='exc' onclick='toggle_lines(this, "exc")'>0 excluded</span>
+ <span class='run hide_run' onclick='toggle_lines(this, "run")'>3 run</span>
<span class='mis' onclick='toggle_lines(this, "mis")'>1 missing</span>
+ <span class='exc' onclick='toggle_lines(this, "exc")'>0 excluded</span>
+
</h2>
</div>
</div>
<div id='source'>
-<table cellspacing='0' cellpadding='0'>
-<tr>
-<td class='linenos' valign='top'>
-<p class='pln'>1</p>
-<p class='pln'>2</p>
-<p class='stm run hide'>3</p>
-<p class='pln'>4</p>
-<p class='stm run hide'>5</p>
-<p class='stm run hide'>6</p>
-<p class='pln'>7</p>
-<p class='stm mis'>8</p>
-
-</td>
-<td class='text' valign='top'>
-<p class='pln'><span class='com'># A test file for HTML reporting by coverage.</span><span class="strut">&nbsp;</span></p>
-<p class='pln'><span class="strut">&nbsp;</span></p>
-<p class='stm run hide'><span class='key'>import</span> <span class='nam'>other</span><span class="strut">&nbsp;</span></p>
-<p class='pln'><span class="strut">&nbsp;</span></p>
-<p class='stm run hide'><span class='key'>if</span> <span class='num'>1</span> <span class='op'>&lt;</span> <span class='num'>2</span><span class='op'>:</span><span class="strut">&nbsp;</span></p>
-<p class='stm run hide'>&nbsp; &nbsp; <span class='nam'>h</span> <span class='op'>=</span> <span class='num'>3</span><span class="strut">&nbsp;</span></p>
-<p class='pln'><span class='key'>else</span><span class='op'>:</span><span class="strut">&nbsp;</span></p>
-<p class='stm mis'>&nbsp; &nbsp; <span class='nam'>h</span> <span class='op'>=</span> <span class='num'>4</span><span class="strut">&nbsp;</span></p>
-
-</td>
-</tr>
-</table>
+ <table cellspacing='0' cellpadding='0'>
+ <tr>
+ <td class='linenos' valign='top'>
+<p id='n1' class='pln'><a href='#n1'>1</a></p>
+<p id='n2' class='pln'><a href='#n2'>2</a></p>
+<p id='n3' class='stm run hide_run'><a href='#n3'>3</a></p>
+<p id='n4' class='pln'><a href='#n4'>4</a></p>
+<p id='n5' class='stm run hide_run'><a href='#n5'>5</a></p>
+<p id='n6' class='stm run hide_run'><a href='#n6'>6</a></p>
+<p id='n7' class='pln'><a href='#n7'>7</a></p>
+<p id='n8' class='stm mis'><a href='#n8'>8</a></p>
+
+ </td>
+ <td class='text' valign='top'>
+<p id='t1' class='pln'><span class='com'># A test file for HTML reporting by coverage.</span><span class='strut'>&nbsp;</span></p>
+<p id='t2' class='pln'><span class='strut'>&nbsp;</span></p>
+<p id='t3' class='stm run hide_run'><span class='key'>import</span> <span class='nam'>other</span><span class='strut'>&nbsp;</span></p>
+<p id='t4' class='pln'><span class='strut'>&nbsp;</span></p>
+<p id='t5' class='stm run hide_run'><span class='key'>if</span> <span class='num'>1</span> <span class='op'>&lt;</span> <span class='num'>2</span><span class='op'>:</span><span class='strut'>&nbsp;</span></p>
+<p id='t6' class='stm run hide_run'>&nbsp; &nbsp; <span class='nam'>h</span> <span class='op'>=</span> <span class='num'>3</span><span class='strut'>&nbsp;</span></p>
+<p id='t7' class='pln'><span class='key'>else</span><span class='op'>:</span><span class='strut'>&nbsp;</span></p>
+<p id='t8' class='stm mis'>&nbsp; &nbsp; <span class='nam'>h</span> <span class='op'>=</span> <span class='num'>4</span><span class='strut'>&nbsp;</span></p>
+
+ </td>
+ </tr>
+ </table>
+</div>
+
+<div id='footer'>
+ <div class='content'>
+ <p>
+ <a class='nav' href='index.html'>&#xab; index</a> &nbsp; &nbsp; <a class='nav' href='http://nedbatchelder.com/code/coverage'>coverage.py v3.3.2a1</a>
+ </p>
+ </div>
</div>
</body>
diff --git a/test/farm/html/gold_other/index.html b/test/farm/html/gold_other/index.html
index 3e41afa3..9021036f 100644
--- a/test/farm/html/gold_other/index.html
+++ b/test/farm/html/gold_other/index.html
@@ -1,64 +1,78 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
-<meta http-equiv='Content-Type' content='text/html; charset=utf-8'>
-<title>Coverage report</title>
-<link rel='stylesheet' href='style.css' type='text/css'>
+ <meta http-equiv='Content-Type' content='text/html; charset=utf-8'>
+ <title>Coverage report</title>
+ <link rel='stylesheet' href='style.css' type='text/css'>
+ <script type='text/javascript' src='jquery-1.3.2.min.js'></script>
+ <script type='text/javascript' src='jquery.tablesorter.min.js'></script>
+ <script type='text/javascript' src='coverage_html.js'></script>
+ <script type='text/javascript' charset='utf-8'>
+ jQuery(document).ready(index_ready);
+ </script>
</head>
-<body>
+<body id='indexfile'>
<div id='header'>
<div class='content'>
- <h1>Coverage report:
+ <h1>Coverage report:
<span class='pc_cov'>80%</span>
</h1>
</div>
</div>
<div id='index'>
-<table class='index'>
-<tr class='tablehead'>
- <th class='name'>Module</th>
- <th>statements</th>
- <th>run</th>
- <th>excluded</th>
-
- <th>coverage</th>
-</tr>
-
-<tr class='file'>
- <td class='name'><a href='_ned_coverage_trunk_test_farm_html_othersrc_other.html'>c:\ned\coverage\trunk\test\farm\html\othersrc\other</a></td>
- <td>1</td>
- <td>1</td>
- <td>0</td>
-
- <td>100%</td>
-</tr>
-
-<tr class='file'>
- <td class='name'><a href='here.html'>here</a></td>
- <td>4</td>
- <td>3</td>
- <td>0</td>
-
- <td>75%</td>
-</tr>
-
-<tr class='total'>
-<td class='name'>Total</td>
-<td>5</td>
-<td>4</td>
-<td>0</td>
-
-<td>80%</td>
-</tr>
-</table>
+ <table class='index'>
+ <thead>
+
+ <tr class='tablehead' title='Click to sort'>
+ <th class='name left headerSortDown'>Module</th>
+ <th>statements</th>
+ <th>missing</th>
+ <th>excluded</th>
+
+ <th class='right'>coverage</th>
+ </tr>
+ </thead>
+
+ <tfoot>
+ <tr class='total'>
+ <td class='name left'>Total</td>
+ <td>5</td>
+ <td>1</td>
+ <td>0</td>
+
+ <td class='right'>80%</td>
+ </tr>
+ </tfoot>
+ <tbody>
+
+ <tr class='file'>
+ <td class='name left'><a href='here.html'>here</a></td>
+ <td>4</td>
+ <td>1</td>
+ <td>0</td>
+
+ <td class='right'>75%</td>
+ </tr>
+
+ <tr class='file'>
+ <td class='name left'><a href='othersrc_other.html'>othersrc\other</a></td>
+ <td>1</td>
+ <td>0</td>
+ <td>0</td>
+
+ <td class='right'>100%</td>
+ </tr>
+
+ </tbody>
+ </table>
</div>
<div id='footer'>
<div class='content'>
<p>
- <a class='nav' href='http://nedbatchelder.com/code/coverage'>coverage.py v3.2a1</a>
+ <a class='nav' href='http://nedbatchelder.com/code/coverage'>coverage.py v3.3.2a1</a>
</p>
</div>
</div>
diff --git a/test/farm/html/gold_other/jquery-1.3.2.min.js b/test/farm/html/gold_other/jquery-1.3.2.min.js
deleted file mode 100644
index b1ae21d8..00000000
--- a/test/farm/html/gold_other/jquery-1.3.2.min.js
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * jQuery JavaScript Library v1.3.2
- * http://jquery.com/
- *
- * Copyright (c) 2009 John Resig
- * Dual licensed under the MIT and GPL licenses.
- * http://docs.jquery.com/License
- *
- * Date: 2009-02-19 17:34:21 -0500 (Thu, 19 Feb 2009)
- * Revision: 6246
- */
-(function(){var l=this,g,y=l.jQuery,p=l.$,o=l.jQuery=l.$=function(E,F){return new o.fn.init(E,F)},D=/^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,f=/^.[^:#\[\.,]*$/;o.fn=o.prototype={init:function(E,H){E=E||document;if(E.nodeType){this[0]=E;this.length=1;this.context=E;return this}if(typeof E==="string"){var G=D.exec(E);if(G&&(G[1]||!H)){if(G[1]){E=o.clean([G[1]],H)}else{var I=document.getElementById(G[3]);if(I&&I.id!=G[3]){return o().find(E)}var F=o(I||[]);F.context=document;F.selector=E;return F}}else{return o(H).find(E)}}else{if(o.isFunction(E)){return o(document).ready(E)}}if(E.selector&&E.context){this.selector=E.selector;this.context=E.context}return this.setArray(o.isArray(E)?E:o.makeArray(E))},selector:"",jquery:"1.3.2",size:function(){return this.length},get:function(E){return E===g?Array.prototype.slice.call(this):this[E]},pushStack:function(F,H,E){var G=o(F);G.prevObject=this;G.context=this.context;if(H==="find"){G.selector=this.selector+(this.selector?" ":"")+E}else{if(H){G.selector=this.selector+"."+H+"("+E+")"}}return G},setArray:function(E){this.length=0;Array.prototype.push.apply(this,E);return this},each:function(F,E){return o.each(this,F,E)},index:function(E){return o.inArray(E&&E.jquery?E[0]:E,this)},attr:function(F,H,G){var E=F;if(typeof F==="string"){if(H===g){return this[0]&&o[G||"attr"](this[0],F)}else{E={};E[F]=H}}return this.each(function(I){for(F in E){o.attr(G?this.style:this,F,o.prop(this,E[F],G,I,F))}})},css:function(E,F){if((E=="width"||E=="height")&&parseFloat(F)<0){F=g}return this.attr(E,F,"curCSS")},text:function(F){if(typeof F!=="object"&&F!=null){return this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(F))}var E="";o.each(F||this,function(){o.each(this.childNodes,function(){if(this.nodeType!=8){E+=this.nodeType!=1?this.nodeValue:o.fn.text([this])}})});return E},wrapAll:function(E){if(this[0]){var F=o(E,this[0].ownerDocument).clone();if(this[0].parentNode){F.insertBefore(this[0])}F.map(function(){var G=this;while(G.firstChild){G=G.firstChild}return G}).append(this)}return this},wrapInner:function(E){return this.each(function(){o(this).contents().wrapAll(E)})},wrap:function(E){return this.each(function(){o(this).wrapAll(E)})},append:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.appendChild(E)}})},prepend:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.insertBefore(E,this.firstChild)}})},before:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this)})},after:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this.nextSibling)})},end:function(){return this.prevObject||o([])},push:[].push,sort:[].sort,splice:[].splice,find:function(E){if(this.length===1){var F=this.pushStack([],"find",E);F.length=0;o.find(E,this[0],F);return F}else{return this.pushStack(o.unique(o.map(this,function(G){return o.find(E,G)})),"find",E)}},clone:function(G){var E=this.map(function(){if(!o.support.noCloneEvent&&!o.isXMLDoc(this)){var I=this.outerHTML;if(!I){var J=this.ownerDocument.createElement("div");J.appendChild(this.cloneNode(true));I=J.innerHTML}return o.clean([I.replace(/ jQuery\d+="(?:\d+|null)"/g,"").replace(/^\s*/,"")])[0]}else{return this.cloneNode(true)}});if(G===true){var H=this.find("*").andSelf(),F=0;E.find("*").andSelf().each(function(){if(this.nodeName!==H[F].nodeName){return}var I=o.data(H[F],"events");for(var K in I){for(var J in I[K]){o.event.add(this,K,I[K][J],I[K][J].data)}}F++})}return E},filter:function(E){return this.pushStack(o.isFunction(E)&&o.grep(this,function(G,F){return E.call(G,F)})||o.multiFilter(E,o.grep(this,function(F){return F.nodeType===1})),"filter",E)},closest:function(E){var G=o.expr.match.POS.test(E)?o(E):null,F=0;return this.map(function(){var H=this;while(H&&H.ownerDocument){if(G?G.index(H)>-1:o(H).is(E)){o.data(H,"closest",F);return H}H=H.parentNode;F++}})},not:function(E){if(typeof E==="string"){if(f.test(E)){return this.pushStack(o.multiFilter(E,this,true),"not",E)}else{E=o.multiFilter(E,this)}}var F=E.length&&E[E.length-1]!==g&&!E.nodeType;return this.filter(function(){return F?o.inArray(this,E)<0:this!=E})},add:function(E){return this.pushStack(o.unique(o.merge(this.get(),typeof E==="string"?o(E):o.makeArray(E))))},is:function(E){return !!E&&o.multiFilter(E,this).length>0},hasClass:function(E){return !!E&&this.is("."+E)},val:function(K){if(K===g){var E=this[0];if(E){if(o.nodeName(E,"option")){return(E.attributes.value||{}).specified?E.value:E.text}if(o.nodeName(E,"select")){var I=E.selectedIndex,L=[],M=E.options,H=E.type=="select-one";if(I<0){return null}for(var F=H?I:0,J=H?I+1:M.length;F<J;F++){var G=M[F];if(G.selected){K=o(G).val();if(H){return K}L.push(K)}}return L}return(E.value||"").replace(/\r/g,"")}return g}if(typeof K==="number"){K+=""}return this.each(function(){if(this.nodeType!=1){return}if(o.isArray(K)&&/radio|checkbox/.test(this.type)){this.checked=(o.inArray(this.value,K)>=0||o.inArray(this.name,K)>=0)}else{if(o.nodeName(this,"select")){var N=o.makeArray(K);o("option",this).each(function(){this.selected=(o.inArray(this.value,N)>=0||o.inArray(this.text,N)>=0)});if(!N.length){this.selectedIndex=-1}}else{this.value=K}}})},html:function(E){return E===g?(this[0]?this[0].innerHTML.replace(/ jQuery\d+="(?:\d+|null)"/g,""):null):this.empty().append(E)},replaceWith:function(E){return this.after(E).remove()},eq:function(E){return this.slice(E,+E+1)},slice:function(){return this.pushStack(Array.prototype.slice.apply(this,arguments),"slice",Array.prototype.slice.call(arguments).join(","))},map:function(E){return this.pushStack(o.map(this,function(G,F){return E.call(G,F,G)}))},andSelf:function(){return this.add(this.prevObject)},domManip:function(J,M,L){if(this[0]){var I=(this[0].ownerDocument||this[0]).createDocumentFragment(),F=o.clean(J,(this[0].ownerDocument||this[0]),I),H=I.firstChild;if(H){for(var G=0,E=this.length;G<E;G++){L.call(K(this[G],H),this.length>1||G>0?I.cloneNode(true):I)}}if(F){o.each(F,z)}}return this;function K(N,O){return M&&o.nodeName(N,"table")&&o.nodeName(O,"tr")?(N.getElementsByTagName("tbody")[0]||N.appendChild(N.ownerDocument.createElement("tbody"))):N}}};o.fn.init.prototype=o.fn;function z(E,F){if(F.src){o.ajax({url:F.src,async:false,dataType:"script"})}else{o.globalEval(F.text||F.textContent||F.innerHTML||"")}if(F.parentNode){F.parentNode.removeChild(F)}}function e(){return +new Date}o.extend=o.fn.extend=function(){var J=arguments[0]||{},H=1,I=arguments.length,E=false,G;if(typeof J==="boolean"){E=J;J=arguments[1]||{};H=2}if(typeof J!=="object"&&!o.isFunction(J)){J={}}if(I==H){J=this;--H}for(;H<I;H++){if((G=arguments[H])!=null){for(var F in G){var K=J[F],L=G[F];if(J===L){continue}if(E&&L&&typeof L==="object"&&!L.nodeType){J[F]=o.extend(E,K||(L.length!=null?[]:{}),L)}else{if(L!==g){J[F]=L}}}}}return J};var b=/z-?index|font-?weight|opacity|zoom|line-?height/i,q=document.defaultView||{},s=Object.prototype.toString;o.extend({noConflict:function(E){l.$=p;if(E){l.jQuery=y}return o},isFunction:function(E){return s.call(E)==="[object Function]"},isArray:function(E){return s.call(E)==="[object Array]"},isXMLDoc:function(E){return E.nodeType===9&&E.documentElement.nodeName!=="HTML"||!!E.ownerDocument&&o.isXMLDoc(E.ownerDocument)},globalEval:function(G){if(G&&/\S/.test(G)){var F=document.getElementsByTagName("head")[0]||document.documentElement,E=document.createElement("script");E.type="text/javascript";if(o.support.scriptEval){E.appendChild(document.createTextNode(G))}else{E.text=G}F.insertBefore(E,F.firstChild);F.removeChild(E)}},nodeName:function(F,E){return F.nodeName&&F.nodeName.toUpperCase()==E.toUpperCase()},each:function(G,K,F){var E,H=0,I=G.length;if(F){if(I===g){for(E in G){if(K.apply(G[E],F)===false){break}}}else{for(;H<I;){if(K.apply(G[H++],F)===false){break}}}}else{if(I===g){for(E in G){if(K.call(G[E],E,G[E])===false){break}}}else{for(var J=G[0];H<I&&K.call(J,H,J)!==false;J=G[++H]){}}}return G},prop:function(H,I,G,F,E){if(o.isFunction(I)){I=I.call(H,F)}return typeof I==="number"&&G=="curCSS"&&!b.test(E)?I+"px":I},className:{add:function(E,F){o.each((F||"").split(/\s+/),function(G,H){if(E.nodeType==1&&!o.className.has(E.className,H)){E.className+=(E.className?" ":"")+H}})},remove:function(E,F){if(E.nodeType==1){E.className=F!==g?o.grep(E.className.split(/\s+/),function(G){return !o.className.has(F,G)}).join(" "):""}},has:function(F,E){return F&&o.inArray(E,(F.className||F).toString().split(/\s+/))>-1}},swap:function(H,G,I){var E={};for(var F in G){E[F]=H.style[F];H.style[F]=G[F]}I.call(H);for(var F in G){H.style[F]=E[F]}},css:function(H,F,J,E){if(F=="width"||F=="height"){var L,G={position:"absolute",visibility:"hidden",display:"block"},K=F=="width"?["Left","Right"]:["Top","Bottom"];function I(){L=F=="width"?H.offsetWidth:H.offsetHeight;if(E==="border"){return}o.each(K,function(){if(!E){L-=parseFloat(o.curCSS(H,"padding"+this,true))||0}if(E==="margin"){L+=parseFloat(o.curCSS(H,"margin"+this,true))||0}else{L-=parseFloat(o.curCSS(H,"border"+this+"Width",true))||0}})}if(H.offsetWidth!==0){I()}else{o.swap(H,G,I)}return Math.max(0,Math.round(L))}return o.curCSS(H,F,J)},curCSS:function(I,F,G){var L,E=I.style;if(F=="opacity"&&!o.support.opacity){L=o.attr(E,"opacity");return L==""?"1":L}if(F.match(/float/i)){F=w}if(!G&&E&&E[F]){L=E[F]}else{if(q.getComputedStyle){if(F.match(/float/i)){F="float"}F=F.replace(/([A-Z])/g,"-$1").toLowerCase();var M=q.getComputedStyle(I,null);if(M){L=M.getPropertyValue(F)}if(F=="opacity"&&L==""){L="1"}}else{if(I.currentStyle){var J=F.replace(/\-(\w)/g,function(N,O){return O.toUpperCase()});L=I.currentStyle[F]||I.currentStyle[J];if(!/^\d+(px)?$/i.test(L)&&/^\d/.test(L)){var H=E.left,K=I.runtimeStyle.left;I.runtimeStyle.left=I.currentStyle.left;E.left=L||0;L=E.pixelLeft+"px";E.left=H;I.runtimeStyle.left=K}}}}return L},clean:function(F,K,I){K=K||document;if(typeof K.createElement==="undefined"){K=K.ownerDocument||K[0]&&K[0].ownerDocument||document}if(!I&&F.length===1&&typeof F[0]==="string"){var H=/^<(\w+)\s*\/?>$/.exec(F[0]);if(H){return[K.createElement(H[1])]}}var G=[],E=[],L=K.createElement("div");o.each(F,function(P,S){if(typeof S==="number"){S+=""}if(!S){return}if(typeof S==="string"){S=S.replace(/(<(\w+)[^>]*?)\/>/g,function(U,V,T){return T.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)?U:V+"></"+T+">"});var O=S.replace(/^\s+/,"").substring(0,10).toLowerCase();var Q=!O.indexOf("<opt")&&[1,"<select multiple='multiple'>","</select>"]||!O.indexOf("<leg")&&[1,"<fieldset>","</fieldset>"]||O.match(/^<(thead|tbody|tfoot|colg|cap)/)&&[1,"<table>","</table>"]||!O.indexOf("<tr")&&[2,"<table><tbody>","</tbody></table>"]||(!O.indexOf("<td")||!O.indexOf("<th"))&&[3,"<table><tbody><tr>","</tr></tbody></table>"]||!O.indexOf("<col")&&[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"]||!o.support.htmlSerialize&&[1,"div<div>","</div>"]||[0,"",""];L.innerHTML=Q[1]+S+Q[2];while(Q[0]--){L=L.lastChild}if(!o.support.tbody){var R=/<tbody/i.test(S),N=!O.indexOf("<table")&&!R?L.firstChild&&L.firstChild.childNodes:Q[1]=="<table>"&&!R?L.childNodes:[];for(var M=N.length-1;M>=0;--M){if(o.nodeName(N[M],"tbody")&&!N[M].childNodes.length){N[M].parentNode.removeChild(N[M])}}}if(!o.support.leadingWhitespace&&/^\s/.test(S)){L.insertBefore(K.createTextNode(S.match(/^\s*/)[0]),L.firstChild)}S=o.makeArray(L.childNodes)}if(S.nodeType){G.push(S)}else{G=o.merge(G,S)}});if(I){for(var J=0;G[J];J++){if(o.nodeName(G[J],"script")&&(!G[J].type||G[J].type.toLowerCase()==="text/javascript")){E.push(G[J].parentNode?G[J].parentNode.removeChild(G[J]):G[J])}else{if(G[J].nodeType===1){G.splice.apply(G,[J+1,0].concat(o.makeArray(G[J].getElementsByTagName("script"))))}I.appendChild(G[J])}}return E}return G},attr:function(J,G,K){if(!J||J.nodeType==3||J.nodeType==8){return g}var H=!o.isXMLDoc(J),L=K!==g;G=H&&o.props[G]||G;if(J.tagName){var F=/href|src|style/.test(G);if(G=="selected"&&J.parentNode){J.parentNode.selectedIndex}if(G in J&&H&&!F){if(L){if(G=="type"&&o.nodeName(J,"input")&&J.parentNode){throw"type property can't be changed"}J[G]=K}if(o.nodeName(J,"form")&&J.getAttributeNode(G)){return J.getAttributeNode(G).nodeValue}if(G=="tabIndex"){var I=J.getAttributeNode("tabIndex");return I&&I.specified?I.value:J.nodeName.match(/(button|input|object|select|textarea)/i)?0:J.nodeName.match(/^(a|area)$/i)&&J.href?0:g}return J[G]}if(!o.support.style&&H&&G=="style"){return o.attr(J.style,"cssText",K)}if(L){J.setAttribute(G,""+K)}var E=!o.support.hrefNormalized&&H&&F?J.getAttribute(G,2):J.getAttribute(G);return E===null?g:E}if(!o.support.opacity&&G=="opacity"){if(L){J.zoom=1;J.filter=(J.filter||"").replace(/alpha\([^)]*\)/,"")+(parseInt(K)+""=="NaN"?"":"alpha(opacity="+K*100+")")}return J.filter&&J.filter.indexOf("opacity=")>=0?(parseFloat(J.filter.match(/opacity=([^)]*)/)[1])/100)+"":""}G=G.replace(/-([a-z])/ig,function(M,N){return N.toUpperCase()});if(L){J[G]=K}return J[G]},trim:function(E){return(E||"").replace(/^\s+|\s+$/g,"")},makeArray:function(G){var E=[];if(G!=null){var F=G.length;if(F==null||typeof G==="string"||o.isFunction(G)||G.setInterval){E[0]=G}else{while(F){E[--F]=G[F]}}}return E},inArray:function(G,H){for(var E=0,F=H.length;E<F;E++){if(H[E]===G){return E}}return -1},merge:function(H,E){var F=0,G,I=H.length;if(!o.support.getAll){while((G=E[F++])!=null){if(G.nodeType!=8){H[I++]=G}}}else{while((G=E[F++])!=null){H[I++]=G}}return H},unique:function(K){var F=[],E={};try{for(var G=0,H=K.length;G<H;G++){var J=o.data(K[G]);if(!E[J]){E[J]=true;F.push(K[G])}}}catch(I){F=K}return F},grep:function(F,J,E){var G=[];for(var H=0,I=F.length;H<I;H++){if(!E!=!J(F[H],H)){G.push(F[H])}}return G},map:function(E,J){var F=[];for(var G=0,H=E.length;G<H;G++){var I=J(E[G],G);if(I!=null){F[F.length]=I}}return F.concat.apply([],F)}});var C=navigator.userAgent.toLowerCase();o.browser={version:(C.match(/.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/)||[0,"0"])[1],safari:/webkit/.test(C),opera:/opera/.test(C),msie:/msie/.test(C)&&!/opera/.test(C),mozilla:/mozilla/.test(C)&&!/(compatible|webkit)/.test(C)};o.each({parent:function(E){return E.parentNode},parents:function(E){return o.dir(E,"parentNode")},next:function(E){return o.nth(E,2,"nextSibling")},prev:function(E){return o.nth(E,2,"previousSibling")},nextAll:function(E){return o.dir(E,"nextSibling")},prevAll:function(E){return o.dir(E,"previousSibling")},siblings:function(E){return o.sibling(E.parentNode.firstChild,E)},children:function(E){return o.sibling(E.firstChild)},contents:function(E){return o.nodeName(E,"iframe")?E.contentDocument||E.contentWindow.document:o.makeArray(E.childNodes)}},function(E,F){o.fn[E]=function(G){var H=o.map(this,F);if(G&&typeof G=="string"){H=o.multiFilter(G,H)}return this.pushStack(o.unique(H),E,G)}});o.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(E,F){o.fn[E]=function(G){var J=[],L=o(G);for(var K=0,H=L.length;K<H;K++){var I=(K>0?this.clone(true):this).get();o.fn[F].apply(o(L[K]),I);J=J.concat(I)}return this.pushStack(J,E,G)}});o.each({removeAttr:function(E){o.attr(this,E,"");if(this.nodeType==1){this.removeAttribute(E)}},addClass:function(E){o.className.add(this,E)},removeClass:function(E){o.className.remove(this,E)},toggleClass:function(F,E){if(typeof E!=="boolean"){E=!o.className.has(this,F)}o.className[E?"add":"remove"](this,F)},remove:function(E){if(!E||o.filter(E,[this]).length){o("*",this).add([this]).each(function(){o.event.remove(this);o.removeData(this)});if(this.parentNode){this.parentNode.removeChild(this)}}},empty:function(){o(this).children().remove();while(this.firstChild){this.removeChild(this.firstChild)}}},function(E,F){o.fn[E]=function(){return this.each(F,arguments)}});function j(E,F){return E[0]&&parseInt(o.curCSS(E[0],F,true),10)||0}var h="jQuery"+e(),v=0,A={};o.extend({cache:{},data:function(F,E,G){F=F==l?A:F;var H=F[h];if(!H){H=F[h]=++v}if(E&&!o.cache[H]){o.cache[H]={}}if(G!==g){o.cache[H][E]=G}return E?o.cache[H][E]:H},removeData:function(F,E){F=F==l?A:F;var H=F[h];if(E){if(o.cache[H]){delete o.cache[H][E];E="";for(E in o.cache[H]){break}if(!E){o.removeData(F)}}}else{try{delete F[h]}catch(G){if(F.removeAttribute){F.removeAttribute(h)}}delete o.cache[H]}},queue:function(F,E,H){if(F){E=(E||"fx")+"queue";var G=o.data(F,E);if(!G||o.isArray(H)){G=o.data(F,E,o.makeArray(H))}else{if(H){G.push(H)}}}return G},dequeue:function(H,G){var E=o.queue(H,G),F=E.shift();if(!G||G==="fx"){F=E[0]}if(F!==g){F.call(H)}}});o.fn.extend({data:function(E,G){var H=E.split(".");H[1]=H[1]?"."+H[1]:"";if(G===g){var F=this.triggerHandler("getData"+H[1]+"!",[H[0]]);if(F===g&&this.length){F=o.data(this[0],E)}return F===g&&H[1]?this.data(H[0]):F}else{return this.trigger("setData"+H[1]+"!",[H[0],G]).each(function(){o.data(this,E,G)})}},removeData:function(E){return this.each(function(){o.removeData(this,E)})},queue:function(E,F){if(typeof E!=="string"){F=E;E="fx"}if(F===g){return o.queue(this[0],E)}return this.each(function(){var G=o.queue(this,E,F);if(E=="fx"&&G.length==1){G[0].call(this)}})},dequeue:function(E){return this.each(function(){o.dequeue(this,E)})}});
-/*
- * Sizzle CSS Selector Engine - v0.9.3
- * Copyright 2009, The Dojo Foundation
- * Released under the MIT, BSD, and GPL Licenses.
- * More information: http://sizzlejs.com/
- */
-(function(){var R=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g,L=0,H=Object.prototype.toString;var F=function(Y,U,ab,ac){ab=ab||[];U=U||document;if(U.nodeType!==1&&U.nodeType!==9){return[]}if(!Y||typeof Y!=="string"){return ab}var Z=[],W,af,ai,T,ad,V,X=true;R.lastIndex=0;while((W=R.exec(Y))!==null){Z.push(W[1]);if(W[2]){V=RegExp.rightContext;break}}if(Z.length>1&&M.exec(Y)){if(Z.length===2&&I.relative[Z[0]]){af=J(Z[0]+Z[1],U)}else{af=I.relative[Z[0]]?[U]:F(Z.shift(),U);while(Z.length){Y=Z.shift();if(I.relative[Y]){Y+=Z.shift()}af=J(Y,af)}}}else{var ae=ac?{expr:Z.pop(),set:E(ac)}:F.find(Z.pop(),Z.length===1&&U.parentNode?U.parentNode:U,Q(U));af=F.filter(ae.expr,ae.set);if(Z.length>0){ai=E(af)}else{X=false}while(Z.length){var ah=Z.pop(),ag=ah;if(!I.relative[ah]){ah=""}else{ag=Z.pop()}if(ag==null){ag=U}I.relative[ah](ai,ag,Q(U))}}if(!ai){ai=af}if(!ai){throw"Syntax error, unrecognized expression: "+(ah||Y)}if(H.call(ai)==="[object Array]"){if(!X){ab.push.apply(ab,ai)}else{if(U.nodeType===1){for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&(ai[aa]===true||ai[aa].nodeType===1&&K(U,ai[aa]))){ab.push(af[aa])}}}else{for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&ai[aa].nodeType===1){ab.push(af[aa])}}}}}else{E(ai,ab)}if(V){F(V,U,ab,ac);if(G){hasDuplicate=false;ab.sort(G);if(hasDuplicate){for(var aa=1;aa<ab.length;aa++){if(ab[aa]===ab[aa-1]){ab.splice(aa--,1)}}}}}return ab};F.matches=function(T,U){return F(T,null,null,U)};F.find=function(aa,T,ab){var Z,X;if(!aa){return[]}for(var W=0,V=I.order.length;W<V;W++){var Y=I.order[W],X;if((X=I.match[Y].exec(aa))){var U=RegExp.leftContext;if(U.substr(U.length-1)!=="\\"){X[1]=(X[1]||"").replace(/\\/g,"");Z=I.find[Y](X,T,ab);if(Z!=null){aa=aa.replace(I.match[Y],"");break}}}}if(!Z){Z=T.getElementsByTagName("*")}return{set:Z,expr:aa}};F.filter=function(ad,ac,ag,W){var V=ad,ai=[],aa=ac,Y,T,Z=ac&&ac[0]&&Q(ac[0]);while(ad&&ac.length){for(var ab in I.filter){if((Y=I.match[ab].exec(ad))!=null){var U=I.filter[ab],ah,af;T=false;if(aa==ai){ai=[]}if(I.preFilter[ab]){Y=I.preFilter[ab](Y,aa,ag,ai,W,Z);if(!Y){T=ah=true}else{if(Y===true){continue}}}if(Y){for(var X=0;(af=aa[X])!=null;X++){if(af){ah=U(af,Y,X,aa);var ae=W^!!ah;if(ag&&ah!=null){if(ae){T=true}else{aa[X]=false}}else{if(ae){ai.push(af);T=true}}}}}if(ah!==g){if(!ag){aa=ai}ad=ad.replace(I.match[ab],"");if(!T){return[]}break}}}if(ad==V){if(T==null){throw"Syntax error, unrecognized expression: "+ad}else{break}}V=ad}return aa};var I=F.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF_-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF_-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*_-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF_-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(T){return T.getAttribute("href")}},relative:{"+":function(aa,T,Z){var X=typeof T==="string",ab=X&&!/\W/.test(T),Y=X&&!ab;if(ab&&!Z){T=T.toUpperCase()}for(var W=0,V=aa.length,U;W<V;W++){if((U=aa[W])){while((U=U.previousSibling)&&U.nodeType!==1){}aa[W]=Y||U&&U.nodeName===T?U||false:U===T}}if(Y){F.filter(T,aa,true)}},">":function(Z,U,aa){var X=typeof U==="string";if(X&&!/\W/.test(U)){U=aa?U:U.toUpperCase();for(var V=0,T=Z.length;V<T;V++){var Y=Z[V];if(Y){var W=Y.parentNode;Z[V]=W.nodeName===U?W:false}}}else{for(var V=0,T=Z.length;V<T;V++){var Y=Z[V];if(Y){Z[V]=X?Y.parentNode:Y.parentNode===U}}if(X){F.filter(U,Z,true)}}},"":function(W,U,Y){var V=L++,T=S;if(!U.match(/\W/)){var X=U=Y?U:U.toUpperCase();T=P}T("parentNode",U,V,W,X,Y)},"~":function(W,U,Y){var V=L++,T=S;if(typeof U==="string"&&!U.match(/\W/)){var X=U=Y?U:U.toUpperCase();T=P}T("previousSibling",U,V,W,X,Y)}},find:{ID:function(U,V,W){if(typeof V.getElementById!=="undefined"&&!W){var T=V.getElementById(U[1]);return T?[T]:[]}},NAME:function(V,Y,Z){if(typeof Y.getElementsByName!=="undefined"){var U=[],X=Y.getElementsByName(V[1]);for(var W=0,T=X.length;W<T;W++){if(X[W].getAttribute("name")===V[1]){U.push(X[W])}}return U.length===0?null:U}},TAG:function(T,U){return U.getElementsByTagName(T[1])}},preFilter:{CLASS:function(W,U,V,T,Z,aa){W=" "+W[1].replace(/\\/g,"")+" ";if(aa){return W}for(var X=0,Y;(Y=U[X])!=null;X++){if(Y){if(Z^(Y.className&&(" "+Y.className+" ").indexOf(W)>=0)){if(!V){T.push(Y)}}else{if(V){U[X]=false}}}}return false},ID:function(T){return T[1].replace(/\\/g,"")},TAG:function(U,T){for(var V=0;T[V]===false;V++){}return T[V]&&Q(T[V])?U[1]:U[1].toUpperCase()},CHILD:function(T){if(T[1]=="nth"){var U=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(T[2]=="even"&&"2n"||T[2]=="odd"&&"2n+1"||!/\D/.test(T[2])&&"0n+"+T[2]||T[2]);T[2]=(U[1]+(U[2]||1))-0;T[3]=U[3]-0}T[0]=L++;return T},ATTR:function(X,U,V,T,Y,Z){var W=X[1].replace(/\\/g,"");if(!Z&&I.attrMap[W]){X[1]=I.attrMap[W]}if(X[2]==="~="){X[4]=" "+X[4]+" "}return X},PSEUDO:function(X,U,V,T,Y){if(X[1]==="not"){if(X[3].match(R).length>1||/^\w/.test(X[3])){X[3]=F(X[3],null,null,U)}else{var W=F.filter(X[3],U,V,true^Y);if(!V){T.push.apply(T,W)}return false}}else{if(I.match.POS.test(X[0])||I.match.CHILD.test(X[0])){return true}}return X},POS:function(T){T.unshift(true);return T}},filters:{enabled:function(T){return T.disabled===false&&T.type!=="hidden"},disabled:function(T){return T.disabled===true},checked:function(T){return T.checked===true},selected:function(T){T.parentNode.selectedIndex;return T.selected===true},parent:function(T){return !!T.firstChild},empty:function(T){return !T.firstChild},has:function(V,U,T){return !!F(T[3],V).length},header:function(T){return/h\d/i.test(T.nodeName)},text:function(T){return"text"===T.type},radio:function(T){return"radio"===T.type},checkbox:function(T){return"checkbox"===T.type},file:function(T){return"file"===T.type},password:function(T){return"password"===T.type},submit:function(T){return"submit"===T.type},image:function(T){return"image"===T.type},reset:function(T){return"reset"===T.type},button:function(T){return"button"===T.type||T.nodeName.toUpperCase()==="BUTTON"},input:function(T){return/input|select|textarea|button/i.test(T.nodeName)}},setFilters:{first:function(U,T){return T===0},last:function(V,U,T,W){return U===W.length-1},even:function(U,T){return T%2===0},odd:function(U,T){return T%2===1},lt:function(V,U,T){return U<T[3]-0},gt:function(V,U,T){return U>T[3]-0},nth:function(V,U,T){return T[3]-0==U},eq:function(V,U,T){return T[3]-0==U}},filter:{PSEUDO:function(Z,V,W,aa){var U=V[1],X=I.filters[U];if(X){return X(Z,W,V,aa)}else{if(U==="contains"){return(Z.textContent||Z.innerText||"").indexOf(V[3])>=0}else{if(U==="not"){var Y=V[3];for(var W=0,T=Y.length;W<T;W++){if(Y[W]===Z){return false}}return true}}}},CHILD:function(T,W){var Z=W[1],U=T;switch(Z){case"only":case"first":while(U=U.previousSibling){if(U.nodeType===1){return false}}if(Z=="first"){return true}U=T;case"last":while(U=U.nextSibling){if(U.nodeType===1){return false}}return true;case"nth":var V=W[2],ac=W[3];if(V==1&&ac==0){return true}var Y=W[0],ab=T.parentNode;if(ab&&(ab.sizcache!==Y||!T.nodeIndex)){var X=0;for(U=ab.firstChild;U;U=U.nextSibling){if(U.nodeType===1){U.nodeIndex=++X}}ab.sizcache=Y}var aa=T.nodeIndex-ac;if(V==0){return aa==0}else{return(aa%V==0&&aa/V>=0)}}},ID:function(U,T){return U.nodeType===1&&U.getAttribute("id")===T},TAG:function(U,T){return(T==="*"&&U.nodeType===1)||U.nodeName===T},CLASS:function(U,T){return(" "+(U.className||U.getAttribute("class"))+" ").indexOf(T)>-1},ATTR:function(Y,W){var V=W[1],T=I.attrHandle[V]?I.attrHandle[V](Y):Y[V]!=null?Y[V]:Y.getAttribute(V),Z=T+"",X=W[2],U=W[4];return T==null?X==="!=":X==="="?Z===U:X==="*="?Z.indexOf(U)>=0:X==="~="?(" "+Z+" ").indexOf(U)>=0:!U?Z&&T!==false:X==="!="?Z!=U:X==="^="?Z.indexOf(U)===0:X==="$="?Z.substr(Z.length-U.length)===U:X==="|="?Z===U||Z.substr(0,U.length+1)===U+"-":false},POS:function(X,U,V,Y){var T=U[2],W=I.setFilters[T];if(W){return W(X,V,U,Y)}}}};var M=I.match.POS;for(var O in I.match){I.match[O]=RegExp(I.match[O].source+/(?![^\[]*\])(?![^\(]*\))/.source)}var E=function(U,T){U=Array.prototype.slice.call(U);if(T){T.push.apply(T,U);return T}return U};try{Array.prototype.slice.call(document.documentElement.childNodes)}catch(N){E=function(X,W){var U=W||[];if(H.call(X)==="[object Array]"){Array.prototype.push.apply(U,X)}else{if(typeof X.length==="number"){for(var V=0,T=X.length;V<T;V++){U.push(X[V])}}else{for(var V=0;X[V];V++){U.push(X[V])}}}return U}}var G;if(document.documentElement.compareDocumentPosition){G=function(U,T){var V=U.compareDocumentPosition(T)&4?-1:U===T?0:1;if(V===0){hasDuplicate=true}return V}}else{if("sourceIndex" in document.documentElement){G=function(U,T){var V=U.sourceIndex-T.sourceIndex;if(V===0){hasDuplicate=true}return V}}else{if(document.createRange){G=function(W,U){var V=W.ownerDocument.createRange(),T=U.ownerDocument.createRange();V.selectNode(W);V.collapse(true);T.selectNode(U);T.collapse(true);var X=V.compareBoundaryPoints(Range.START_TO_END,T);if(X===0){hasDuplicate=true}return X}}}}(function(){var U=document.createElement("form"),V="script"+(new Date).getTime();U.innerHTML="<input name='"+V+"'/>";var T=document.documentElement;T.insertBefore(U,T.firstChild);if(!!document.getElementById(V)){I.find.ID=function(X,Y,Z){if(typeof Y.getElementById!=="undefined"&&!Z){var W=Y.getElementById(X[1]);return W?W.id===X[1]||typeof W.getAttributeNode!=="undefined"&&W.getAttributeNode("id").nodeValue===X[1]?[W]:g:[]}};I.filter.ID=function(Y,W){var X=typeof Y.getAttributeNode!=="undefined"&&Y.getAttributeNode("id");return Y.nodeType===1&&X&&X.nodeValue===W}}T.removeChild(U)})();(function(){var T=document.createElement("div");T.appendChild(document.createComment(""));if(T.getElementsByTagName("*").length>0){I.find.TAG=function(U,Y){var X=Y.getElementsByTagName(U[1]);if(U[1]==="*"){var W=[];for(var V=0;X[V];V++){if(X[V].nodeType===1){W.push(X[V])}}X=W}return X}}T.innerHTML="<a href='#'></a>";if(T.firstChild&&typeof T.firstChild.getAttribute!=="undefined"&&T.firstChild.getAttribute("href")!=="#"){I.attrHandle.href=function(U){return U.getAttribute("href",2)}}})();if(document.querySelectorAll){(function(){var T=F,U=document.createElement("div");U.innerHTML="<p class='TEST'></p>";if(U.querySelectorAll&&U.querySelectorAll(".TEST").length===0){return}F=function(Y,X,V,W){X=X||document;if(!W&&X.nodeType===9&&!Q(X)){try{return E(X.querySelectorAll(Y),V)}catch(Z){}}return T(Y,X,V,W)};F.find=T.find;F.filter=T.filter;F.selectors=T.selectors;F.matches=T.matches})()}if(document.getElementsByClassName&&document.documentElement.getElementsByClassName){(function(){var T=document.createElement("div");T.innerHTML="<div class='test e'></div><div class='test'></div>";if(T.getElementsByClassName("e").length===0){return}T.lastChild.className="e";if(T.getElementsByClassName("e").length===1){return}I.order.splice(1,0,"CLASS");I.find.CLASS=function(U,V,W){if(typeof V.getElementsByClassName!=="undefined"&&!W){return V.getElementsByClassName(U[1])}}})()}function P(U,Z,Y,ad,aa,ac){var ab=U=="previousSibling"&&!ac;for(var W=0,V=ad.length;W<V;W++){var T=ad[W];if(T){if(ab&&T.nodeType===1){T.sizcache=Y;T.sizset=W}T=T[U];var X=false;while(T){if(T.sizcache===Y){X=ad[T.sizset];break}if(T.nodeType===1&&!ac){T.sizcache=Y;T.sizset=W}if(T.nodeName===Z){X=T;break}T=T[U]}ad[W]=X}}}function S(U,Z,Y,ad,aa,ac){var ab=U=="previousSibling"&&!ac;for(var W=0,V=ad.length;W<V;W++){var T=ad[W];if(T){if(ab&&T.nodeType===1){T.sizcache=Y;T.sizset=W}T=T[U];var X=false;while(T){if(T.sizcache===Y){X=ad[T.sizset];break}if(T.nodeType===1){if(!ac){T.sizcache=Y;T.sizset=W}if(typeof Z!=="string"){if(T===Z){X=true;break}}else{if(F.filter(Z,[T]).length>0){X=T;break}}}T=T[U]}ad[W]=X}}}var K=document.compareDocumentPosition?function(U,T){return U.compareDocumentPosition(T)&16}:function(U,T){return U!==T&&(U.contains?U.contains(T):true)};var Q=function(T){return T.nodeType===9&&T.documentElement.nodeName!=="HTML"||!!T.ownerDocument&&Q(T.ownerDocument)};var J=function(T,aa){var W=[],X="",Y,V=aa.nodeType?[aa]:aa;while((Y=I.match.PSEUDO.exec(T))){X+=Y[0];T=T.replace(I.match.PSEUDO,"")}T=I.relative[T]?T+"*":T;for(var Z=0,U=V.length;Z<U;Z++){F(T,V[Z],W)}return F.filter(X,W)};o.find=F;o.filter=F.filter;o.expr=F.selectors;o.expr[":"]=o.expr.filters;F.selectors.filters.hidden=function(T){return T.offsetWidth===0||T.offsetHeight===0};F.selectors.filters.visible=function(T){return T.offsetWidth>0||T.offsetHeight>0};F.selectors.filters.animated=function(T){return o.grep(o.timers,function(U){return T===U.elem}).length};o.multiFilter=function(V,T,U){if(U){V=":not("+V+")"}return F.matches(V,T)};o.dir=function(V,U){var T=[],W=V[U];while(W&&W!=document){if(W.nodeType==1){T.push(W)}W=W[U]}return T};o.nth=function(X,T,V,W){T=T||1;var U=0;for(;X;X=X[V]){if(X.nodeType==1&&++U==T){break}}return X};o.sibling=function(V,U){var T=[];for(;V;V=V.nextSibling){if(V.nodeType==1&&V!=U){T.push(V)}}return T};return;l.Sizzle=F})();o.event={add:function(I,F,H,K){if(I.nodeType==3||I.nodeType==8){return}if(I.setInterval&&I!=l){I=l}if(!H.guid){H.guid=this.guid++}if(K!==g){var G=H;H=this.proxy(G);H.data=K}var E=o.data(I,"events")||o.data(I,"events",{}),J=o.data(I,"handle")||o.data(I,"handle",function(){return typeof o!=="undefined"&&!o.event.triggered?o.event.handle.apply(arguments.callee.elem,arguments):g});J.elem=I;o.each(F.split(/\s+/),function(M,N){var O=N.split(".");N=O.shift();H.type=O.slice().sort().join(".");var L=E[N];if(o.event.specialAll[N]){o.event.specialAll[N].setup.call(I,K,O)}if(!L){L=E[N]={};if(!o.event.special[N]||o.event.special[N].setup.call(I,K,O)===false){if(I.addEventListener){I.addEventListener(N,J,false)}else{if(I.attachEvent){I.attachEvent("on"+N,J)}}}}L[H.guid]=H;o.event.global[N]=true});I=null},guid:1,global:{},remove:function(K,H,J){if(K.nodeType==3||K.nodeType==8){return}var G=o.data(K,"events"),F,E;if(G){if(H===g||(typeof H==="string"&&H.charAt(0)==".")){for(var I in G){this.remove(K,I+(H||""))}}else{if(H.type){J=H.handler;H=H.type}o.each(H.split(/\s+/),function(M,O){var Q=O.split(".");O=Q.shift();var N=RegExp("(^|\\.)"+Q.slice().sort().join(".*\\.")+"(\\.|$)");if(G[O]){if(J){delete G[O][J.guid]}else{for(var P in G[O]){if(N.test(G[O][P].type)){delete G[O][P]}}}if(o.event.specialAll[O]){o.event.specialAll[O].teardown.call(K,Q)}for(F in G[O]){break}if(!F){if(!o.event.special[O]||o.event.special[O].teardown.call(K,Q)===false){if(K.removeEventListener){K.removeEventListener(O,o.data(K,"handle"),false)}else{if(K.detachEvent){K.detachEvent("on"+O,o.data(K,"handle"))}}}F=null;delete G[O]}}})}for(F in G){break}if(!F){var L=o.data(K,"handle");if(L){L.elem=null}o.removeData(K,"events");o.removeData(K,"handle")}}},trigger:function(I,K,H,E){var G=I.type||I;if(!E){I=typeof I==="object"?I[h]?I:o.extend(o.Event(G),I):o.Event(G);if(G.indexOf("!")>=0){I.type=G=G.slice(0,-1);I.exclusive=true}if(!H){I.stopPropagation();if(this.global[G]){o.each(o.cache,function(){if(this.events&&this.events[G]){o.event.trigger(I,K,this.handle.elem)}})}}if(!H||H.nodeType==3||H.nodeType==8){return g}I.result=g;I.target=H;K=o.makeArray(K);K.unshift(I)}I.currentTarget=H;var J=o.data(H,"handle");if(J){J.apply(H,K)}if((!H[G]||(o.nodeName(H,"a")&&G=="click"))&&H["on"+G]&&H["on"+G].apply(H,K)===false){I.result=false}if(!E&&H[G]&&!I.isDefaultPrevented()&&!(o.nodeName(H,"a")&&G=="click")){this.triggered=true;try{H[G]()}catch(L){}}this.triggered=false;if(!I.isPropagationStopped()){var F=H.parentNode||H.ownerDocument;if(F){o.event.trigger(I,K,F,true)}}},handle:function(K){var J,E;K=arguments[0]=o.event.fix(K||l.event);K.currentTarget=this;var L=K.type.split(".");K.type=L.shift();J=!L.length&&!K.exclusive;var I=RegExp("(^|\\.)"+L.slice().sort().join(".*\\.")+"(\\.|$)");E=(o.data(this,"events")||{})[K.type];for(var G in E){var H=E[G];if(J||I.test(H.type)){K.handler=H;K.data=H.data;var F=H.apply(this,arguments);if(F!==g){K.result=F;if(F===false){K.preventDefault();K.stopPropagation()}}if(K.isImmediatePropagationStopped()){break}}}},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),fix:function(H){if(H[h]){return H}var F=H;H=o.Event(F);for(var G=this.props.length,J;G;){J=this.props[--G];H[J]=F[J]}if(!H.target){H.target=H.srcElement||document}if(H.target.nodeType==3){H.target=H.target.parentNode}if(!H.relatedTarget&&H.fromElement){H.relatedTarget=H.fromElement==H.target?H.toElement:H.fromElement}if(H.pageX==null&&H.clientX!=null){var I=document.documentElement,E=document.body;H.pageX=H.clientX+(I&&I.scrollLeft||E&&E.scrollLeft||0)-(I.clientLeft||0);H.pageY=H.clientY+(I&&I.scrollTop||E&&E.scrollTop||0)-(I.clientTop||0)}if(!H.which&&((H.charCode||H.charCode===0)?H.charCode:H.keyCode)){H.which=H.charCode||H.keyCode}if(!H.metaKey&&H.ctrlKey){H.metaKey=H.ctrlKey}if(!H.which&&H.button){H.which=(H.button&1?1:(H.button&2?3:(H.button&4?2:0)))}return H},proxy:function(F,E){E=E||function(){return F.apply(this,arguments)};E.guid=F.guid=F.guid||E.guid||this.guid++;return E},special:{ready:{setup:B,teardown:function(){}}},specialAll:{live:{setup:function(E,F){o.event.add(this,F[0],c)},teardown:function(G){if(G.length){var E=0,F=RegExp("(^|\\.)"+G[0]+"(\\.|$)");o.each((o.data(this,"events").live||{}),function(){if(F.test(this.type)){E++}});if(E<1){o.event.remove(this,G[0],c)}}}}}};o.Event=function(E){if(!this.preventDefault){return new o.Event(E)}if(E&&E.type){this.originalEvent=E;this.type=E.type}else{this.type=E}this.timeStamp=e();this[h]=true};function k(){return false}function u(){return true}o.Event.prototype={preventDefault:function(){this.isDefaultPrevented=u;var E=this.originalEvent;if(!E){return}if(E.preventDefault){E.preventDefault()}E.returnValue=false},stopPropagation:function(){this.isPropagationStopped=u;var E=this.originalEvent;if(!E){return}if(E.stopPropagation){E.stopPropagation()}E.cancelBubble=true},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=u;this.stopPropagation()},isDefaultPrevented:k,isPropagationStopped:k,isImmediatePropagationStopped:k};var a=function(F){var E=F.relatedTarget;while(E&&E!=this){try{E=E.parentNode}catch(G){E=this}}if(E!=this){F.type=F.data;o.event.handle.apply(this,arguments)}};o.each({mouseover:"mouseenter",mouseout:"mouseleave"},function(F,E){o.event.special[E]={setup:function(){o.event.add(this,F,a,E)},teardown:function(){o.event.remove(this,F,a)}}});o.fn.extend({bind:function(F,G,E){return F=="unload"?this.one(F,G,E):this.each(function(){o.event.add(this,F,E||G,E&&G)})},one:function(G,H,F){var E=o.event.proxy(F||H,function(I){o(this).unbind(I,E);return(F||H).apply(this,arguments)});return this.each(function(){o.event.add(this,G,E,F&&H)})},unbind:function(F,E){return this.each(function(){o.event.remove(this,F,E)})},trigger:function(E,F){return this.each(function(){o.event.trigger(E,F,this)})},triggerHandler:function(E,G){if(this[0]){var F=o.Event(E);F.preventDefault();F.stopPropagation();o.event.trigger(F,G,this[0]);return F.result}},toggle:function(G){var E=arguments,F=1;while(F<E.length){o.event.proxy(G,E[F++])}return this.click(o.event.proxy(G,function(H){this.lastToggle=(this.lastToggle||0)%F;H.preventDefault();return E[this.lastToggle++].apply(this,arguments)||false}))},hover:function(E,F){return this.mouseenter(E).mouseleave(F)},ready:function(E){B();if(o.isReady){E.call(document,o)}else{o.readyList.push(E)}return this},live:function(G,F){var E=o.event.proxy(F);E.guid+=this.selector+G;o(document).bind(i(G,this.selector),this.selector,E);return this},die:function(F,E){o(document).unbind(i(F,this.selector),E?{guid:E.guid+this.selector+F}:null);return this}});function c(H){var E=RegExp("(^|\\.)"+H.type+"(\\.|$)"),G=true,F=[];o.each(o.data(this,"events").live||[],function(I,J){if(E.test(J.type)){var K=o(H.target).closest(J.data)[0];if(K){F.push({elem:K,fn:J})}}});F.sort(function(J,I){return o.data(J.elem,"closest")-o.data(I.elem,"closest")});o.each(F,function(){if(this.fn.call(this.elem,H,this.fn.data)===false){return(G=false)}});return G}function i(F,E){return["live",F,E.replace(/\./g,"`").replace(/ /g,"|")].join(".")}o.extend({isReady:false,readyList:[],ready:function(){if(!o.isReady){o.isReady=true;if(o.readyList){o.each(o.readyList,function(){this.call(document,o)});o.readyList=null}o(document).triggerHandler("ready")}}});var x=false;function B(){if(x){return}x=true;if(document.addEventListener){document.addEventListener("DOMContentLoaded",function(){document.removeEventListener("DOMContentLoaded",arguments.callee,false);o.ready()},false)}else{if(document.attachEvent){document.attachEvent("onreadystatechange",function(){if(document.readyState==="complete"){document.detachEvent("onreadystatechange",arguments.callee);o.ready()}});if(document.documentElement.doScroll&&l==l.top){(function(){if(o.isReady){return}try{document.documentElement.doScroll("left")}catch(E){setTimeout(arguments.callee,0);return}o.ready()})()}}}o.event.add(l,"load",o.ready)}o.each(("blur,focus,load,resize,scroll,unload,click,dblclick,mousedown,mouseup,mousemove,mouseover,mouseout,mouseenter,mouseleave,change,select,submit,keydown,keypress,keyup,error").split(","),function(F,E){o.fn[E]=function(G){return G?this.bind(E,G):this.trigger(E)}});o(l).bind("unload",function(){for(var E in o.cache){if(E!=1&&o.cache[E].handle){o.event.remove(o.cache[E].handle.elem)}}});(function(){o.support={};var F=document.documentElement,G=document.createElement("script"),K=document.createElement("div"),J="script"+(new Date).getTime();K.style.display="none";K.innerHTML=' <link/><table></table><a href="/a" style="color:red;float:left;opacity:.5;">a</a><select><option>text</option></select><object><param/></object>';var H=K.getElementsByTagName("*"),E=K.getElementsByTagName("a")[0];if(!H||!H.length||!E){return}o.support={leadingWhitespace:K.firstChild.nodeType==3,tbody:!K.getElementsByTagName("tbody").length,objectAll:!!K.getElementsByTagName("object")[0].getElementsByTagName("*").length,htmlSerialize:!!K.getElementsByTagName("link").length,style:/red/.test(E.getAttribute("style")),hrefNormalized:E.getAttribute("href")==="/a",opacity:E.style.opacity==="0.5",cssFloat:!!E.style.cssFloat,scriptEval:false,noCloneEvent:true,boxModel:null};G.type="text/javascript";try{G.appendChild(document.createTextNode("window."+J+"=1;"))}catch(I){}F.insertBefore(G,F.firstChild);if(l[J]){o.support.scriptEval=true;delete l[J]}F.removeChild(G);if(K.attachEvent&&K.fireEvent){K.attachEvent("onclick",function(){o.support.noCloneEvent=false;K.detachEvent("onclick",arguments.callee)});K.cloneNode(true).fireEvent("onclick")}o(function(){var L=document.createElement("div");L.style.width=L.style.paddingLeft="1px";document.body.appendChild(L);o.boxModel=o.support.boxModel=L.offsetWidth===2;document.body.removeChild(L).style.display="none"})})();var w=o.support.cssFloat?"cssFloat":"styleFloat";o.props={"for":"htmlFor","class":"className","float":w,cssFloat:w,styleFloat:w,readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",tabindex:"tabIndex"};o.fn.extend({_load:o.fn.load,load:function(G,J,K){if(typeof G!=="string"){return this._load(G)}var I=G.indexOf(" ");if(I>=0){var E=G.slice(I,G.length);G=G.slice(0,I)}var H="GET";if(J){if(o.isFunction(J)){K=J;J=null}else{if(typeof J==="object"){J=o.param(J);H="POST"}}}var F=this;o.ajax({url:G,type:H,dataType:"html",data:J,complete:function(M,L){if(L=="success"||L=="notmodified"){F.html(E?o("<div/>").append(M.responseText.replace(/<script(.|\s)*?\/script>/g,"")).find(E):M.responseText)}if(K){F.each(K,[M.responseText,L,M])}}});return this},serialize:function(){return o.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?o.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||/select|textarea/i.test(this.nodeName)||/text|hidden|password|search/i.test(this.type))}).map(function(E,F){var G=o(this).val();return G==null?null:o.isArray(G)?o.map(G,function(I,H){return{name:F.name,value:I}}):{name:F.name,value:G}}).get()}});o.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","),function(E,F){o.fn[F]=function(G){return this.bind(F,G)}});var r=e();o.extend({get:function(E,G,H,F){if(o.isFunction(G)){H=G;G=null}return o.ajax({type:"GET",url:E,data:G,success:H,dataType:F})},getScript:function(E,F){return o.get(E,null,F,"script")},getJSON:function(E,F,G){return o.get(E,F,G,"json")},post:function(E,G,H,F){if(o.isFunction(G)){H=G;G={}}return o.ajax({type:"POST",url:E,data:G,success:H,dataType:F})},ajaxSetup:function(E){o.extend(o.ajaxSettings,E)},ajaxSettings:{url:location.href,global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:function(){return l.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest()},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},ajax:function(M){M=o.extend(true,M,o.extend(true,{},o.ajaxSettings,M));var W,F=/=\?(&|$)/g,R,V,G=M.type.toUpperCase();if(M.data&&M.processData&&typeof M.data!=="string"){M.data=o.param(M.data)}if(M.dataType=="jsonp"){if(G=="GET"){if(!M.url.match(F)){M.url+=(M.url.match(/\?/)?"&":"?")+(M.jsonp||"callback")+"=?"}}else{if(!M.data||!M.data.match(F)){M.data=(M.data?M.data+"&":"")+(M.jsonp||"callback")+"=?"}}M.dataType="json"}if(M.dataType=="json"&&(M.data&&M.data.match(F)||M.url.match(F))){W="jsonp"+r++;if(M.data){M.data=(M.data+"").replace(F,"="+W+"$1")}M.url=M.url.replace(F,"="+W+"$1");M.dataType="script";l[W]=function(X){V=X;I();L();l[W]=g;try{delete l[W]}catch(Y){}if(H){H.removeChild(T)}}}if(M.dataType=="script"&&M.cache==null){M.cache=false}if(M.cache===false&&G=="GET"){var E=e();var U=M.url.replace(/(\?|&)_=.*?(&|$)/,"$1_="+E+"$2");M.url=U+((U==M.url)?(M.url.match(/\?/)?"&":"?")+"_="+E:"")}if(M.data&&G=="GET"){M.url+=(M.url.match(/\?/)?"&":"?")+M.data;M.data=null}if(M.global&&!o.active++){o.event.trigger("ajaxStart")}var Q=/^(\w+:)?\/\/([^\/?#]+)/.exec(M.url);if(M.dataType=="script"&&G=="GET"&&Q&&(Q[1]&&Q[1]!=location.protocol||Q[2]!=location.host)){var H=document.getElementsByTagName("head")[0];var T=document.createElement("script");T.src=M.url;if(M.scriptCharset){T.charset=M.scriptCharset}if(!W){var O=false;T.onload=T.onreadystatechange=function(){if(!O&&(!this.readyState||this.readyState=="loaded"||this.readyState=="complete")){O=true;I();L();T.onload=T.onreadystatechange=null;H.removeChild(T)}}}H.appendChild(T);return g}var K=false;var J=M.xhr();if(M.username){J.open(G,M.url,M.async,M.username,M.password)}else{J.open(G,M.url,M.async)}try{if(M.data){J.setRequestHeader("Content-Type",M.contentType)}if(M.ifModified){J.setRequestHeader("If-Modified-Since",o.lastModified[M.url]||"Thu, 01 Jan 1970 00:00:00 GMT")}J.setRequestHeader("X-Requested-With","XMLHttpRequest");J.setRequestHeader("Accept",M.dataType&&M.accepts[M.dataType]?M.accepts[M.dataType]+", */*":M.accepts._default)}catch(S){}if(M.beforeSend&&M.beforeSend(J,M)===false){if(M.global&&!--o.active){o.event.trigger("ajaxStop")}J.abort();return false}if(M.global){o.event.trigger("ajaxSend",[J,M])}var N=function(X){if(J.readyState==0){if(P){clearInterval(P);P=null;if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}}else{if(!K&&J&&(J.readyState==4||X=="timeout")){K=true;if(P){clearInterval(P);P=null}R=X=="timeout"?"timeout":!o.httpSuccess(J)?"error":M.ifModified&&o.httpNotModified(J,M.url)?"notmodified":"success";if(R=="success"){try{V=o.httpData(J,M.dataType,M)}catch(Z){R="parsererror"}}if(R=="success"){var Y;try{Y=J.getResponseHeader("Last-Modified")}catch(Z){}if(M.ifModified&&Y){o.lastModified[M.url]=Y}if(!W){I()}}else{o.handleError(M,J,R)}L();if(X){J.abort()}if(M.async){J=null}}}};if(M.async){var P=setInterval(N,13);if(M.timeout>0){setTimeout(function(){if(J&&!K){N("timeout")}},M.timeout)}}try{J.send(M.data)}catch(S){o.handleError(M,J,null,S)}if(!M.async){N()}function I(){if(M.success){M.success(V,R)}if(M.global){o.event.trigger("ajaxSuccess",[J,M])}}function L(){if(M.complete){M.complete(J,R)}if(M.global){o.event.trigger("ajaxComplete",[J,M])}if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}return J},handleError:function(F,H,E,G){if(F.error){F.error(H,E,G)}if(F.global){o.event.trigger("ajaxError",[H,F,G])}},active:0,httpSuccess:function(F){try{return !F.status&&location.protocol=="file:"||(F.status>=200&&F.status<300)||F.status==304||F.status==1223}catch(E){}return false},httpNotModified:function(G,E){try{var H=G.getResponseHeader("Last-Modified");return G.status==304||H==o.lastModified[E]}catch(F){}return false},httpData:function(J,H,G){var F=J.getResponseHeader("content-type"),E=H=="xml"||!H&&F&&F.indexOf("xml")>=0,I=E?J.responseXML:J.responseText;if(E&&I.documentElement.tagName=="parsererror"){throw"parsererror"}if(G&&G.dataFilter){I=G.dataFilter(I,H)}if(typeof I==="string"){if(H=="script"){o.globalEval(I)}if(H=="json"){I=l["eval"]("("+I+")")}}return I},param:function(E){var G=[];function H(I,J){G[G.length]=encodeURIComponent(I)+"="+encodeURIComponent(J)}if(o.isArray(E)||E.jquery){o.each(E,function(){H(this.name,this.value)})}else{for(var F in E){if(o.isArray(E[F])){o.each(E[F],function(){H(F,this)})}else{H(F,o.isFunction(E[F])?E[F]():E[F])}}}return G.join("&").replace(/%20/g,"+")}});var m={},n,d=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];function t(F,E){var G={};o.each(d.concat.apply([],d.slice(0,E)),function(){G[this]=F});return G}o.fn.extend({show:function(J,L){if(J){return this.animate(t("show",3),J,L)}else{for(var H=0,F=this.length;H<F;H++){var E=o.data(this[H],"olddisplay");this[H].style.display=E||"";if(o.css(this[H],"display")==="none"){var G=this[H].tagName,K;if(m[G]){K=m[G]}else{var I=o("<"+G+" />").appendTo("body");K=I.css("display");if(K==="none"){K="block"}I.remove();m[G]=K}o.data(this[H],"olddisplay",K)}}for(var H=0,F=this.length;H<F;H++){this[H].style.display=o.data(this[H],"olddisplay")||""}return this}},hide:function(H,I){if(H){return this.animate(t("hide",3),H,I)}else{for(var G=0,F=this.length;G<F;G++){var E=o.data(this[G],"olddisplay");if(!E&&E!=="none"){o.data(this[G],"olddisplay",o.css(this[G],"display"))}}for(var G=0,F=this.length;G<F;G++){this[G].style.display="none"}return this}},_toggle:o.fn.toggle,toggle:function(G,F){var E=typeof G==="boolean";return o.isFunction(G)&&o.isFunction(F)?this._toggle.apply(this,arguments):G==null||E?this.each(function(){var H=E?G:o(this).is(":hidden");o(this)[H?"show":"hide"]()}):this.animate(t("toggle",3),G,F)},fadeTo:function(E,G,F){return this.animate({opacity:G},E,F)},animate:function(I,F,H,G){var E=o.speed(F,H,G);return this[E.queue===false?"each":"queue"](function(){var K=o.extend({},E),M,L=this.nodeType==1&&o(this).is(":hidden"),J=this;for(M in I){if(I[M]=="hide"&&L||I[M]=="show"&&!L){return K.complete.call(this)}if((M=="height"||M=="width")&&this.style){K.display=o.css(this,"display");K.overflow=this.style.overflow}}if(K.overflow!=null){this.style.overflow="hidden"}K.curAnim=o.extend({},I);o.each(I,function(O,S){var R=new o.fx(J,K,O);if(/toggle|show|hide/.test(S)){R[S=="toggle"?L?"show":"hide":S](I)}else{var Q=S.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),T=R.cur(true)||0;if(Q){var N=parseFloat(Q[2]),P=Q[3]||"px";if(P!="px"){J.style[O]=(N||1)+P;T=((N||1)/R.cur(true))*T;J.style[O]=T+P}if(Q[1]){N=((Q[1]=="-="?-1:1)*N)+T}R.custom(T,N,P)}else{R.custom(T,S,"")}}});return true})},stop:function(F,E){var G=o.timers;if(F){this.queue([])}this.each(function(){for(var H=G.length-1;H>=0;H--){if(G[H].elem==this){if(E){G[H](true)}G.splice(H,1)}}});if(!E){this.dequeue()}return this}});o.each({slideDown:t("show",1),slideUp:t("hide",1),slideToggle:t("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(E,F){o.fn[E]=function(G,H){return this.animate(F,G,H)}});o.extend({speed:function(G,H,F){var E=typeof G==="object"?G:{complete:F||!F&&H||o.isFunction(G)&&G,duration:G,easing:F&&H||H&&!o.isFunction(H)&&H};E.duration=o.fx.off?0:typeof E.duration==="number"?E.duration:o.fx.speeds[E.duration]||o.fx.speeds._default;E.old=E.complete;E.complete=function(){if(E.queue!==false){o(this).dequeue()}if(o.isFunction(E.old)){E.old.call(this)}};return E},easing:{linear:function(G,H,E,F){return E+F*G},swing:function(G,H,E,F){return((-Math.cos(G*Math.PI)/2)+0.5)*F+E}},timers:[],fx:function(F,E,G){this.options=E;this.elem=F;this.prop=G;if(!E.orig){E.orig={}}}});o.fx.prototype={update:function(){if(this.options.step){this.options.step.call(this.elem,this.now,this)}(o.fx.step[this.prop]||o.fx.step._default)(this);if((this.prop=="height"||this.prop=="width")&&this.elem.style){this.elem.style.display="block"}},cur:function(F){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null)){return this.elem[this.prop]}var E=parseFloat(o.css(this.elem,this.prop,F));return E&&E>-10000?E:parseFloat(o.curCSS(this.elem,this.prop))||0},custom:function(I,H,G){this.startTime=e();this.start=I;this.end=H;this.unit=G||this.unit||"px";this.now=this.start;this.pos=this.state=0;var E=this;function F(J){return E.step(J)}F.elem=this.elem;if(F()&&o.timers.push(F)&&!n){n=setInterval(function(){var K=o.timers;for(var J=0;J<K.length;J++){if(!K[J]()){K.splice(J--,1)}}if(!K.length){clearInterval(n);n=g}},13)}},show:function(){this.options.orig[this.prop]=o.attr(this.elem.style,this.prop);this.options.show=true;this.custom(this.prop=="width"||this.prop=="height"?1:0,this.cur());o(this.elem).show()},hide:function(){this.options.orig[this.prop]=o.attr(this.elem.style,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(H){var G=e();if(H||G>=this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;var E=true;for(var F in this.options.curAnim){if(this.options.curAnim[F]!==true){E=false}}if(E){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;this.elem.style.display=this.options.display;if(o.css(this.elem,"display")=="none"){this.elem.style.display="block"}}if(this.options.hide){o(this.elem).hide()}if(this.options.hide||this.options.show){for(var I in this.options.curAnim){o.attr(this.elem.style,I,this.options.orig[I])}}this.options.complete.call(this.elem)}return false}else{var J=G-this.startTime;this.state=J/this.options.duration;this.pos=o.easing[this.options.easing||(o.easing.swing?"swing":"linear")](this.state,J,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update()}return true}};o.extend(o.fx,{speeds:{slow:600,fast:200,_default:400},step:{opacity:function(E){o.attr(E.elem.style,"opacity",E.now)},_default:function(E){if(E.elem.style&&E.elem.style[E.prop]!=null){E.elem.style[E.prop]=E.now+E.unit}else{E.elem[E.prop]=E.now}}}});if(document.documentElement.getBoundingClientRect){o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}var G=this[0].getBoundingClientRect(),J=this[0].ownerDocument,F=J.body,E=J.documentElement,L=E.clientTop||F.clientTop||0,K=E.clientLeft||F.clientLeft||0,I=G.top+(self.pageYOffset||o.boxModel&&E.scrollTop||F.scrollTop)-L,H=G.left+(self.pageXOffset||o.boxModel&&E.scrollLeft||F.scrollLeft)-K;return{top:I,left:H}}}else{o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}o.offset.initialized||o.offset.initialize();var J=this[0],G=J.offsetParent,F=J,O=J.ownerDocument,M,H=O.documentElement,K=O.body,L=O.defaultView,E=L.getComputedStyle(J,null),N=J.offsetTop,I=J.offsetLeft;while((J=J.parentNode)&&J!==K&&J!==H){M=L.getComputedStyle(J,null);N-=J.scrollTop,I-=J.scrollLeft;if(J===G){N+=J.offsetTop,I+=J.offsetLeft;if(o.offset.doesNotAddBorder&&!(o.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(J.tagName))){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}F=G,G=J.offsetParent}if(o.offset.subtractsBorderForOverflowNotVisible&&M.overflow!=="visible"){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}E=M}if(E.position==="relative"||E.position==="static"){N+=K.offsetTop,I+=K.offsetLeft}if(E.position==="fixed"){N+=Math.max(H.scrollTop,K.scrollTop),I+=Math.max(H.scrollLeft,K.scrollLeft)}return{top:N,left:I}}}o.offset={initialize:function(){if(this.initialized){return}var L=document.body,F=document.createElement("div"),H,G,N,I,M,E,J=L.style.marginTop,K='<div style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;"><div></div></div><table style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;" cellpadding="0" cellspacing="0"><tr><td></td></tr></table>';M={position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"};for(E in M){F.style[E]=M[E]}F.innerHTML=K;L.insertBefore(F,L.firstChild);H=F.firstChild,G=H.firstChild,I=H.nextSibling.firstChild.firstChild;this.doesNotAddBorder=(G.offsetTop!==5);this.doesAddBorderForTableAndCells=(I.offsetTop===5);H.style.overflow="hidden",H.style.position="relative";this.subtractsBorderForOverflowNotVisible=(G.offsetTop===-5);L.style.marginTop="1px";this.doesNotIncludeMarginInBodyOffset=(L.offsetTop===0);L.style.marginTop=J;L.removeChild(F);this.initialized=true},bodyOffset:function(E){o.offset.initialized||o.offset.initialize();var G=E.offsetTop,F=E.offsetLeft;if(o.offset.doesNotIncludeMarginInBodyOffset){G+=parseInt(o.curCSS(E,"marginTop",true),10)||0,F+=parseInt(o.curCSS(E,"marginLeft",true),10)||0}return{top:G,left:F}}};o.fn.extend({position:function(){var I=0,H=0,F;if(this[0]){var G=this.offsetParent(),J=this.offset(),E=/^body|html$/i.test(G[0].tagName)?{top:0,left:0}:G.offset();J.top-=j(this,"marginTop");J.left-=j(this,"marginLeft");E.top+=j(G,"borderTopWidth");E.left+=j(G,"borderLeftWidth");F={top:J.top-E.top,left:J.left-E.left}}return F},offsetParent:function(){var E=this[0].offsetParent||document.body;while(E&&(!/^body|html$/i.test(E.tagName)&&o.css(E,"position")=="static")){E=E.offsetParent}return o(E)}});o.each(["Left","Top"],function(F,E){var G="scroll"+E;o.fn[G]=function(H){if(!this[0]){return null}return H!==g?this.each(function(){this==l||this==document?l.scrollTo(!F?H:o(l).scrollLeft(),F?H:o(l).scrollTop()):this[G]=H}):this[0]==l||this[0]==document?self[F?"pageYOffset":"pageXOffset"]||o.boxModel&&document.documentElement[G]||document.body[G]:this[0][G]}});o.each(["Height","Width"],function(I,G){var E=I?"Left":"Top",H=I?"Right":"Bottom",F=G.toLowerCase();o.fn["inner"+G]=function(){return this[0]?o.css(this[0],F,false,"padding"):null};o.fn["outer"+G]=function(K){return this[0]?o.css(this[0],F,false,K?"margin":"border"):null};var J=G.toLowerCase();o.fn[J]=function(K){return this[0]==l?document.compatMode=="CSS1Compat"&&document.documentElement["client"+G]||document.body["client"+G]:this[0]==document?Math.max(document.documentElement["client"+G],document.body["scroll"+G],document.documentElement["scroll"+G],document.body["offset"+G],document.documentElement["offset"+G]):K===g?(this.length?o.css(this[0],J):null):this.css(J,typeof K==="string"?K:K+"px")}})})(); \ No newline at end of file
diff --git a/test/farm/html/gold_other/style.css b/test/farm/html/gold_other/style.css
deleted file mode 100644
index 65a27905..00000000
--- a/test/farm/html/gold_other/style.css
+++ /dev/null
@@ -1,195 +0,0 @@
-/* CSS styles for Coverage. */
-/* Page-wide styles */
-html, body, h1, h2, h3, p, td, th {
- margin: 0;
- padding: 0;
- border: 0;
- outline: 0;
- font-weight: inherit;
- font-style: inherit;
- font-size: 100%;
- font-family: inherit;
- vertical-align: baseline;
- }
-
-/* Set baseline grid to 16 pt. */
-body {
- font-family: georgia, serif;
- font-size: 1em;
- }
-
-html>body {
- font-size: 16px;
- }
-
-/* Set base font size to 12/16 */
-p {
- font-size: .75em; /* 12/16 */
- line-height: 1.3333em; /* 16/12 */
- }
-
-table {
- border-collapse: collapse;
- }
-
-a.nav {
- text-decoration: none;
- color: inherit;
- }
-a.nav:hover {
- text-decoration: underline;
- color: inherit;
- }
-
-/* Page structure */
-#header {
- background: #f8f8f8;
- width: 100%;
- border-bottom: 1px solid #eee;
- }
-
-#source {
- padding: 1em;
- font-family: "courier new", monospace;
- }
-
-#footer {
- margin: 1em 3em;
- }
-
-#footer .content {
- padding: 0;
- font-size: 85%;
- font-family: verdana, sans-serif;
- color: #666666;
- font-style: italic;
- }
-
-#index {
- margin: 1em 0 0 3em;
- }
-
-/* Header styles */
-#header .content {
- padding: 1em 3em;
- }
-
-h1 {
- font-size: 1.25em;
-}
-
-h2.stats {
- margin-top: .5em;
- font-size: 1em;
-}
-.stats span {
- border: 1px solid;
- padding: .1em .25em;
- margin: 0 .1em;
- cursor: pointer;
- border-color: #999 #ccc #ccc #999;
-}
-.stats span.hide {
- border-color: #ccc #999 #999 #ccc;
-}
-
-/* Source file styles */
-.linenos p {
- text-align: right;
- margin: 0;
- padding: 0 .5em;
- color: #999999;
- font-family: verdana, sans-serif;
- font-size: .625em; /* 10/16 */
- line-height: 1.6em; /* 16/10 */
- }
-td.text {
- width: 100%;
- }
-.text p {
- margin: 0;
- padding: 0 0 0 .5em;
- border-left: 2px solid #ffffff;
- white-space: nowrap;
- }
-
-.text p.mis {
- background: #ffdddd;
- border-left: 2px solid #ff0000;
- }
-.text p.run {
- background: #ddffdd;
- border-left: 2px solid #00ff00;
- }
-.text p.exc {
- background: #eeeeee;
- border-left: 2px solid #808080;
- }
-.text p.par {
- background: #ffffaa;
- border-left: 2px solid #eeee99;
- }
-.text p.hide {
- background: inherit;
- }
-
-.text span.annotate {
- font-family: georgia;
- font-style: italic;
- color: #666;
- float: right;
- padding-right: .5em;
- }
-.text p.hide span.annotate {
- display: none;
- }
-
-/* Syntax coloring */
-.text .com {
- color: green;
- font-style: italic;
- line-height: 1px;
- }
-.text .key {
- font-weight: bold;
- line-height: 1px;
- }
-.text .str {
- color: #000080;
- }
-
-/* index styles */
-#index td, #index th {
- text-align: right;
- width: 6em;
- padding: .25em 0;
- border-bottom: 1px solid #eee;
- }
-#index th {
- font-style: italic;
- color: #333;
- border-bottom: 1px solid #ccc;
- }
-#index td.name, #index th.name {
- text-align: left;
- width: auto;
- }
-#index td.name a {
- text-decoration: none;
- color: #000;
- }
-#index td.name a:hover {
- text-decoration: underline;
- color: #000;
- }
-#index tr.total {
- font-weight: bold;
- }
-#index tr.total td {
- padding: .25em 0;
- border-top: 1px solid #ccc;
- border-bottom: none;
- }
-#index tr.file:hover {
- background: #eeeeee;
- }
diff --git a/test/farm/html/gold_x_xml/coverage.xml b/test/farm/html/gold_x_xml/coverage.xml
index 8c009f5d..37027efb 100644
--- a/test/farm/html/gold_x_xml/coverage.xml
+++ b/test/farm/html/gold_x_xml/coverage.xml
@@ -6,7 +6,7 @@
<packages>
<package branch-rate="0.0" complexity="0.0" line-rate="0.666666666667" name=".">
<classes>
- <class branch-rate="0.0" complexity="0.0" filename="x.py" line-rate="0.666666666667" name="x">
+ <class branch-rate="0.0" complexity="0.0" filename="a.py" line-rate="0.666666666667" name="a">
<methods/>
<lines>
<line hits="1" number="3"/>
diff --git a/test/farm/html/gold_y_xml_branch/coverage.xml b/test/farm/html/gold_y_xml_branch/coverage.xml
new file mode 100644
index 00000000..96459101
--- /dev/null
+++ b/test/farm/html/gold_y_xml_branch/coverage.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" ?>
+<!DOCTYPE coverage
+ SYSTEM 'http://cobertura.sourceforge.net/xml/coverage-03.dtd'>
+<coverage branch-rate="0.5" line-rate="0.8" timestamp="1259288252325" version="3.2b4">
+ <!-- Generated by coverage.py: http://nedbatchelder.com/code/coverage -->
+ <packages>
+ <package branch-rate="0.5" complexity="0.0" line-rate="0.8" name=".">
+ <classes>
+ <class branch-rate="0.5" complexity="0.0" filename="y.py" line-rate="0.8" name="y">
+ <methods/>
+ <lines>
+ <line hits="1" number="3"/>
+ <line branch="true" hits="1" number="4"/>
+ <line hits="1" number="5"/>
+ <line hits="0" number="7"/>
+ <line hits="1" number="9"/>
+ </lines>
+ </class>
+ </classes>
+ </package>
+ </packages>
+</coverage>
diff --git a/test/farm/html/run_a.py b/test/farm/html/run_a.py
index dc7719a2..047d8982 100644
--- a/test/farm/html/run_a.py
+++ b/test/farm/html/run_a.py
@@ -5,21 +5,21 @@ def html_it():
cov.start()
import a
cov.stop()
- cov.html_report(a, directory="../html")
+ cov.html_report(a, directory="../html_a")
runfunc(html_it, rundir="src")
# HTML files will change often. Check that the sizes are reasonable,
# and check that certain key strings are in the output.
-compare("gold_a", "html", size_within=10)
-contains("html/a.html",
+compare("gold_a", "html_a", size_within=10, file_pattern="*.html")
+contains("html_a/a.html",
"<span class='key'>if</span> <span class='num'>1</span> <span class='op'>&lt;</span> <span class='num'>2</span>",
"&nbsp; &nbsp; <span class='nam'>a</span> <span class='op'>=</span> <span class='num'>3</span>",
"<span class='pc_cov'>67%</span>"
)
-contains("html/index.html",
+contains("html_a/index.html",
"<a href='a.html'>a</a>",
"<span class='pc_cov'>67%</span>"
)
-clean("html")
+clean("html_a")
diff --git a/test/farm/html/run_x_xml.py b/test/farm/html/run_a_xml_1.py
index fe9cefa7..7f4805ef 100644
--- a/test/farm/html/run_x_xml.py
+++ b/test/farm/html/run_a_xml_1.py
@@ -1,20 +1,20 @@
def html_it():
- """Run coverage and make an XML report for x."""
+ """Run coverage and make an XML report for a."""
import coverage
cov = coverage.coverage()
cov.start()
- import x
+ import a
cov.stop()
- cov.xml_report(x, outfile="../xml/coverage.xml")
+ cov.xml_report(a, outfile="../xml_1/coverage.xml")
import os
-if not os.path.exists("xml"):
- os.makedirs("xml")
+if not os.path.exists("xml_1"):
+ os.makedirs("xml_1")
runfunc(html_it, rundir="src")
-compare("gold_x_xml", "xml", scrubs=[
+compare("gold_x_xml", "xml_1", scrubs=[
(r' timestamp="\d+"', ' timestamp="TIMESTAMP"'),
(r' version="[-.\w]+"', ' version="VERSION"'),
])
-clean("xml")
+clean("xml_1")
diff --git a/test/farm/html/run_a_xml_2.py b/test/farm/html/run_a_xml_2.py
new file mode 100644
index 00000000..b08d7960
--- /dev/null
+++ b/test/farm/html/run_a_xml_2.py
@@ -0,0 +1,20 @@
+def html_it():
+ """Run coverage and make an XML report for a."""
+ import coverage
+ cov = coverage.coverage(config_file="run_a_xml_2.ini")
+ cov.start()
+ import a
+ cov.stop()
+ cov.xml_report(a)
+
+import os
+if not os.path.exists("xml_2"):
+ os.makedirs("xml_2")
+
+runfunc(html_it, rundir="src")
+
+compare("gold_x_xml", "xml_2", scrubs=[
+ (r' timestamp="\d+"', ' timestamp="TIMESTAMP"'),
+ (r' version="[-.\w]+"', ' version="VERSION"'),
+ ])
+clean("xml_2")
diff --git a/test/farm/html/run_b_branch.py b/test/farm/html/run_b_branch.py
new file mode 100644
index 00000000..f129e436
--- /dev/null
+++ b/test/farm/html/run_b_branch.py
@@ -0,0 +1,28 @@
+def html_it():
+ """Run coverage with branches and make an HTML report for a."""
+ import coverage
+ cov = coverage.coverage(branch=True)
+ cov.start()
+ import b
+ cov.stop()
+ cov.html_report(b, directory="../html_b_branch")
+
+runfunc(html_it, rundir="src")
+
+# HTML files will change often. Check that the sizes are reasonable,
+# and check that certain key strings are in the output.
+compare("gold_b_branch", "html_b_branch", size_within=10, file_pattern="*.html")
+contains("html_b_branch/b.html",
+ "<span class='key'>if</span> <span class='nam'>x</span> <span class='op'>&lt;</span> <span class='num'>2</span>",
+ "&nbsp; &nbsp; <span class='nam'>a</span> <span class='op'>=</span> <span class='num'>3</span>",
+ "<span class='pc_cov'>76%</span>",
+ "<span class='annotate' title='no jump to this line number'>8</span>",
+ "<span class='annotate' title='no jump to this line number'>exit</span>",
+ "<span class='annotate' title='no jumps to these line numbers'>25&nbsp;&nbsp; 26</span>",
+ )
+contains("html_b_branch/index.html",
+ "<a href='b.html'>b</a>",
+ "<span class='pc_cov'>76%</span>"
+ )
+
+clean("html_b_branch")
diff --git a/test/farm/html/run_omit_1.py b/test/farm/html/run_omit_1.py
new file mode 100644
index 00000000..a493a8aa
--- /dev/null
+++ b/test/farm/html/run_omit_1.py
@@ -0,0 +1,12 @@
+def html_it():
+ """Run coverage and make an HTML report for main."""
+ import coverage
+ cov = coverage.coverage()
+ cov.start()
+ import main
+ cov.stop()
+ cov.html_report(directory="../html_omit_1")
+
+runfunc(html_it, rundir="src")
+compare("gold_omit_1", "html_omit_1", size_within=10, file_pattern="*.html")
+clean("html_omit_1")
diff --git a/test/farm/html/run_omit_2.py b/test/farm/html/run_omit_2.py
new file mode 100644
index 00000000..5d7e8329
--- /dev/null
+++ b/test/farm/html/run_omit_2.py
@@ -0,0 +1,12 @@
+def html_it():
+ """Run coverage and make an HTML report for main."""
+ import coverage
+ cov = coverage.coverage()
+ cov.start()
+ import main
+ cov.stop()
+ cov.html_report(directory="../html_omit_2", omit_prefixes=["m1"])
+
+runfunc(html_it, rundir="src")
+compare("gold_omit_2", "html_omit_2", size_within=10, file_pattern="*.html")
+clean("html_omit_2")
diff --git a/test/farm/html/run_omit_3.py b/test/farm/html/run_omit_3.py
new file mode 100644
index 00000000..537ec2c7
--- /dev/null
+++ b/test/farm/html/run_omit_3.py
@@ -0,0 +1,12 @@
+def html_it():
+ """Run coverage and make an HTML report for main."""
+ import coverage
+ cov = coverage.coverage()
+ cov.start()
+ import main
+ cov.stop()
+ cov.html_report(directory="../html_omit_3", omit_prefixes=["m1", "m2"])
+
+runfunc(html_it, rundir="src")
+compare("gold_omit_3", "html_omit_3", size_within=10, file_pattern="*.html")
+clean("html_omit_3")
diff --git a/test/farm/html/run_omit_4.py b/test/farm/html/run_omit_4.py
new file mode 100644
index 00000000..c62e9d57
--- /dev/null
+++ b/test/farm/html/run_omit_4.py
@@ -0,0 +1,12 @@
+def html_it():
+ """Run coverage and make an HTML report for main."""
+ import coverage
+ cov = coverage.coverage(config_file="omit4.ini")
+ cov.start()
+ import main
+ cov.stop()
+ cov.html_report(directory="../html_omit_4")
+
+runfunc(html_it, rundir="src")
+compare("gold_omit_4", "html_omit_4", size_within=10, file_pattern="*.html")
+clean("html_omit_4")
diff --git a/test/farm/html/run_omit_5.py b/test/farm/html/run_omit_5.py
new file mode 100644
index 00000000..bd0fc9e2
--- /dev/null
+++ b/test/farm/html/run_omit_5.py
@@ -0,0 +1,12 @@
+def html_it():
+ """Run coverage and make an HTML report for main."""
+ import coverage
+ cov = coverage.coverage(config_file="omit5.ini")
+ cov.start()
+ import main
+ cov.stop()
+ cov.html_report()
+
+runfunc(html_it, rundir="src")
+compare("gold_omit_5", "html_omit_5", size_within=10, file_pattern="*.html")
+clean("html_omit_5")
diff --git a/test/farm/html/run_other.py b/test/farm/html/run_other.py
index 22850326..e75500cf 100644
--- a/test/farm/html/run_other.py
+++ b/test/farm/html/run_other.py
@@ -5,22 +5,22 @@ def html_it():
cov.start()
import here
cov.stop()
- cov.html_report(directory="../otherhtml")
+ cov.html_report(directory="../html_other")
runfunc(html_it, rundir="src", addtopath="../othersrc")
# Different platforms will name the "other" file differently. Rename it
import os, glob
-for p in glob.glob("otherhtml/*_other.html"):
- os.rename(p, "otherhtml/blah_blah_other.html")
+for p in glob.glob("html_other/*_other.html"):
+ os.rename(p, "html_other/blah_blah_other.html")
# HTML files will change often. Check that the sizes are reasonable,
# and check that certain key strings are in the output.
-compare("gold_other", "otherhtml", size_within=10)
-contains("otherhtml/index.html",
+compare("gold_other", "html_other", size_within=10, file_pattern="*.html")
+contains("html_other/index.html",
"<a href='here.html'>here</a>",
"other.html'>", "other</a>",
)
-clean("otherhtml")
+clean("html_other")
diff --git a/test/farm/html/run_tabbed.py b/test/farm/html/run_tabbed.py
index e7e60cec..3076b4e5 100644
--- a/test/farm/html/run_tabbed.py
+++ b/test/farm/html/run_tabbed.py
@@ -5,20 +5,20 @@ def html_it():
cov.start()
import tabbed
cov.stop()
- cov.html_report(tabbed, directory="../html")
+ cov.html_report(tabbed, directory="../html_tabbed")
runfunc(html_it, rundir="src")
# Editors like to change things, make sure our source file still has tabs.
contains("src/tabbed.py", "\tif x:\t\t\t\t\t# look nice")
-contains("html/tabbed.html",
+contains("html_tabbed/tabbed.html",
">&nbsp; &nbsp; &nbsp; &nbsp; <span class='key'>if</span> "
"<span class='nam'>x</span><span class='op'>:</span>"
"&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "
"&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; "
- "<span class='com'># look nice</span>"
+ "<span class='com'># look nice</span>"
)
-doesnt_contain("html/tabbed.html", "\t")
-clean("html")
+doesnt_contain("html_tabbed/tabbed.html", "\t")
+clean("html_tabbed")
diff --git a/test/farm/html/run_y_xml_branch.py b/test/farm/html/run_y_xml_branch.py
new file mode 100644
index 00000000..46f426d3
--- /dev/null
+++ b/test/farm/html/run_y_xml_branch.py
@@ -0,0 +1,20 @@
+def xml_it():
+ """Run coverage and make an XML report for y."""
+ import coverage
+ cov = coverage.coverage(branch=True)
+ cov.start()
+ import y
+ cov.stop()
+ cov.xml_report(y, outfile="../xml_branch/coverage.xml")
+
+import os
+if not os.path.exists("xml_branch"):
+ os.makedirs("xml_branch")
+
+runfunc(xml_it, rundir="src")
+
+compare("gold_y_xml_branch", "xml_branch", scrubs=[
+ (r' timestamp="\d+"', ' timestamp="TIMESTAMP"'),
+ (r' version="[-.\w]+"', ' version="VERSION"'),
+ ])
+clean("xml_branch")
diff --git a/test/farm/html/src/b.py b/test/farm/html/src/b.py
new file mode 100644
index 00000000..dffdd50f
--- /dev/null
+++ b/test/farm/html/src/b.py
@@ -0,0 +1,28 @@
+# A test file for HTML reporting by coverage.
+
+def one(x):
+ # This will be a branch that misses the else.
+ if x < 2:
+ a = 3
+ else:
+ a = 4
+
+one(1)
+
+def two(x):
+ # A missed else that branches to "exit"
+ if x:
+ a = 5
+
+two(1)
+
+def three_way():
+ # for-else can be a three-way branch.
+ for i in range(10):
+ if i == 3:
+ break
+ else:
+ return 23
+ return 17
+
+three_way()
diff --git a/test/farm/html/src/coverage.xml b/test/farm/html/src/coverage.xml
new file mode 100644
index 00000000..bc517328
--- /dev/null
+++ b/test/farm/html/src/coverage.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" ?>
+<!DOCTYPE coverage
+ SYSTEM 'http://cobertura.sourceforge.net/xml/coverage-03.dtd'>
+<coverage branch-rate="0.0" line-rate="0.666666666667" timestamp="1263087779313" version="3.3a1">
+ <!-- Generated by coverage.py: http://nedbatchelder.com/code/coverage -->
+ <packages>
+ <package branch-rate="0.0" complexity="0.0" line-rate="0.666666666667" name=".">
+ <classes>
+ <class branch-rate="0.0" complexity="0.0" filename="a.py" line-rate="0.666666666667" name="a">
+ <methods/>
+ <lines>
+ <line hits="1" number="3"/>
+ <line hits="1" number="5"/>
+ <line hits="0" number="7"/>
+ </lines>
+ </class>
+ </classes>
+ </package>
+ </packages>
+</coverage>
diff --git a/test/farm/html/src/m1.py b/test/farm/html/src/m1.py
new file mode 100644
index 00000000..927e1f6b
--- /dev/null
+++ b/test/farm/html/src/m1.py
@@ -0,0 +1,2 @@
+m1a = 1
+m1b = 2
diff --git a/test/farm/html/src/m2.py b/test/farm/html/src/m2.py
new file mode 100644
index 00000000..ffddf6cf
--- /dev/null
+++ b/test/farm/html/src/m2.py
@@ -0,0 +1,2 @@
+m2a = 1
+m2b = 2
diff --git a/test/farm/html/src/m3.py b/test/farm/html/src/m3.py
new file mode 100644
index 00000000..395d7d25
--- /dev/null
+++ b/test/farm/html/src/m3.py
@@ -0,0 +1,2 @@
+m3a = 1
+m3b = 2
diff --git a/test/farm/html/src/main.py b/test/farm/html/src/main.py
new file mode 100644
index 00000000..ce894465
--- /dev/null
+++ b/test/farm/html/src/main.py
@@ -0,0 +1,10 @@
+import m1
+import m2
+import m3
+
+a = 5
+b = 6
+
+assert m1.m1a == 1
+assert m2.m2a == 1
+assert m3.m3a == 1
diff --git a/test/farm/html/src/omit4.ini b/test/farm/html/src/omit4.ini
new file mode 100644
index 00000000..95f62a13
--- /dev/null
+++ b/test/farm/html/src/omit4.ini
@@ -0,0 +1,2 @@
+[report]
+omit = m2
diff --git a/test/farm/html/src/omit5.ini b/test/farm/html/src/omit5.ini
new file mode 100644
index 00000000..70ef4917
--- /dev/null
+++ b/test/farm/html/src/omit5.ini
@@ -0,0 +1,8 @@
+[report]
+omit =
+ fooey
+ gooey, m2, kablooey
+ m3, helloworld
+
+[html]
+directory = ../html_omit_5
diff --git a/test/farm/html/src/run_a_xml_2.ini b/test/farm/html/src/run_a_xml_2.ini
new file mode 100644
index 00000000..8d28f97b
--- /dev/null
+++ b/test/farm/html/src/run_a_xml_2.ini
@@ -0,0 +1,3 @@
+# Put all the XML output in xml_2
+[xml]
+output = ../xml_2/coverage.xml
diff --git a/test/farm/html/src/tabbed.py b/test/farm/html/src/tabbed.py
index bc6bb456..4c39cafe 100644
--- a/test/farm/html/src/tabbed.py
+++ b/test/farm/html/src/tabbed.py
@@ -3,6 +3,6 @@ x = 1
if x:
a = "Tabbed" # Aligned comments
if x: # look nice
- b = "No spaces" # when they
+ b = "No spaces" # when they
c = "Done" # line up.
diff --git a/test/farm/html/src/x.py b/test/farm/html/src/x.py
deleted file mode 100644
index 9e71aebd..00000000
--- a/test/farm/html/src/x.py
+++ /dev/null
@@ -1,7 +0,0 @@
-# A test file for HTML reporting by coverage.
-
-if 1 < 2:
- # Needed a < to look at HTML entities.
- a = 3
-else:
- a = 4
diff --git a/test/farm/html/src/y.py b/test/farm/html/src/y.py
new file mode 100644
index 00000000..af7c9689
--- /dev/null
+++ b/test/farm/html/src/y.py
@@ -0,0 +1,9 @@
+# A test file for XML reporting by coverage.
+
+def choice(x):
+ if x < 2:
+ return 3
+ else:
+ return 4
+
+assert choice(1) == 3
diff --git a/test/farm/run/run_xxx.py b/test/farm/run/run_xxx.py
index 3c39f0f7..27967a9f 100644
--- a/test/farm/run/run_xxx.py
+++ b/test/farm/run/run_xxx.py
@@ -6,7 +6,7 @@ run("""
contains("out/stdout.txt",
"xxx: 3 4 0 7",
"\nxxx ", # The reporting line for xxx
- " 7 6 85%" # The reporting data for xxx
+ " 7 1 85%" # The reporting data for xxx
)
doesnt_contain("out/stdout.txt", "No such file or directory")
clean("out")
diff --git a/test/modules/aa/afile.odd.py b/test/modules/aa/afile.odd.py
new file mode 100644
index 00000000..c6f49e18
--- /dev/null
+++ b/test/modules/aa/afile.odd.py
@@ -0,0 +1 @@
+# afile.odd.py
diff --git a/test/modules/aa/bb.odd/bfile.py b/test/modules/aa/bb.odd/bfile.py
new file mode 100644
index 00000000..90875404
--- /dev/null
+++ b/test/modules/aa/bb.odd/bfile.py
@@ -0,0 +1 @@
+# bfile.py
diff --git a/test/modules/aa/bb/bfile.odd.py b/test/modules/aa/bb/bfile.odd.py
new file mode 100644
index 00000000..b45cba8c
--- /dev/null
+++ b/test/modules/aa/bb/bfile.odd.py
@@ -0,0 +1 @@
+# bfile.odd.py
diff --git a/test/osinfo.py b/test/osinfo.py
new file mode 100644
index 00000000..04855fe6
--- /dev/null
+++ b/test/osinfo.py
@@ -0,0 +1,69 @@
+"""OS information for testing."""
+
+import sys
+
+if sys.version_info >= (2, 5) and sys.platform == 'win32':
+ # Windows implementation
+ def process_ram():
+ """How much RAM is this process using? (Windows)"""
+ import ctypes
+ # lifted from:
+ # lists.ubuntu.com/archives/bazaar-commits/2009-February/011990.html
+ class PROCESS_MEMORY_COUNTERS_EX(ctypes.Structure):
+ """Used by GetProcessMemoryInfo"""
+ _fields_ = [('cb', ctypes.c_ulong),
+ ('PageFaultCount', ctypes.c_ulong),
+ ('PeakWorkingSetSize', ctypes.c_size_t),
+ ('WorkingSetSize', ctypes.c_size_t),
+ ('QuotaPeakPagedPoolUsage', ctypes.c_size_t),
+ ('QuotaPagedPoolUsage', ctypes.c_size_t),
+ ('QuotaPeakNonPagedPoolUsage', ctypes.c_size_t),
+ ('QuotaNonPagedPoolUsage', ctypes.c_size_t),
+ ('PagefileUsage', ctypes.c_size_t),
+ ('PeakPagefileUsage', ctypes.c_size_t),
+ ('PrivateUsage', ctypes.c_size_t),
+ ]
+
+ mem_struct = PROCESS_MEMORY_COUNTERS_EX()
+ ret = ctypes.windll.psapi.GetProcessMemoryInfo(
+ ctypes.windll.kernel32.GetCurrentProcess(),
+ ctypes.byref(mem_struct),
+ ctypes.sizeof(mem_struct)
+ )
+ if not ret:
+ return 0
+ return mem_struct.PrivateUsage
+
+elif sys.platform == 'linux2':
+ # Linux implementation
+ import os
+
+ _scale = {'kb': 1024, 'mb': 1024*1024}
+
+ def _VmB(key):
+ """Read the /proc/PID/status file to find memory use."""
+ try:
+ # get pseudo file /proc/<pid>/status
+ t = open('/proc/%d/status' % os.getpid())
+ v = t.read()
+ t.close()
+ except IOError:
+ return 0 # non-Linux?
+ # get VmKey line e.g. 'VmRSS: 9999 kB\n ...'
+ i = v.index(key)
+ v = v[i:].split(None, 3)
+ if len(v) < 3:
+ return 0 # invalid format?
+ # convert Vm value to bytes
+ return int(float(v[1]) * _scale[v[2].lower()])
+
+ def process_ram():
+ """How much RAM is this process using? (Linux implementation)"""
+ return _VmB('VmRSS')
+
+
+else:
+ # Don't have an implementation, at least satisfy the interface.
+ def process_ram():
+ """How much RAM is this process using? (placebo implementation)"""
+ return 0
diff --git a/test/stress_phystoken.txt b/test/stress_phystoken.tok
index bd6a453a..8d1b6bec 100644
--- a/test/stress_phystoken.txt
+++ b/test/stress_phystoken.tok
@@ -1,6 +1,6 @@
# Here's some random Python so that test_tokenize_myself will have some
-# stressful stuff to try. This file is .txt instead of .py so pylint won't
-# complain about it.
+# stressful stuff to try. This file is .tok instead of .py so pylint won't
+# complain about it, check_eol won't look at it, etc.
first_back = """\
hey there!
@@ -15,10 +15,22 @@ lots_of_back = """\
hey \
there
"""
+# This next line is supposed to have trailing whitespace:
fake_back = """\
ouch
"""
+# Lots of difficulty happens with code like:
+#
+# fake_back = """\
+# ouch
+# """
+#
+# Ugh, the edge cases...
+
+# What about a comment like this\
+"what's this string doing here?"
+
class C(object):
def there():
this = 5 + \
@@ -29,6 +41,11 @@ class C(object):
cont1 = "one line of text" + \
"another line of text"
+a_long_string = \
+ "part 1" \
+ "2" \
+ "3 is longer"
+
def hello():
print("Hello world!")
diff --git a/test/stress_phystoken_dos.tok b/test/stress_phystoken_dos.tok
new file mode 100644
index 00000000..b08fd70e
--- /dev/null
+++ b/test/stress_phystoken_dos.tok
@@ -0,0 +1,52 @@
+# Here's some random Python so that test_tokenize_myself will have some
+# stressful stuff to try. This file is .tok instead of .py so pylint won't
+# complain about it, check_eol won't look at it, etc.
+
+first_back = """\
+hey there!
+"""
+
+other_back = """
+hey \
+there
+"""
+
+lots_of_back = """\
+hey \
+there
+"""
+# This next line is supposed to have trailing whitespace:
+fake_back = """\
+ouch
+"""
+
+# Lots of difficulty happens with code like:
+#
+# fake_back = """\
+# ouch
+# """
+#
+# Ugh, the edge cases...
+
+# What about a comment like this\
+"what's this string doing here?"
+
+class C(object):
+ def there():
+ this = 5 + \
+ 7
+ that = \
+ "a continued line"
+
+cont1 = "one line of text" + \
+ "another line of text"
+
+a_long_string = \
+ "part 1" \
+ "2" \
+ "3 is longer"
+
+def hello():
+ print("Hello world!")
+
+hello()
diff --git a/test/test_api.py b/test/test_api.py
index 1a1f5412..aaae89cb 100644
--- a/test/test_api.py
+++ b/test/test_api.py
@@ -8,6 +8,9 @@ from coverage.backward import StringIO
sys.path.insert(0, os.path.split(__file__)[0]) # Force relative import for Py3k
from coveragetest import CoverageTest
+# This file uses the singleton module interface. Prevent it from writing
+# .coverage files at exit.
+coverage.use_cache(0)
class ApiTest(CoverageTest):
"""Api-oriented tests for Coverage."""
@@ -22,17 +25,17 @@ class ApiTest(CoverageTest):
c = 4
d = 5
""")
-
+
# Import the python file, executing it.
coverage.start()
- self.import_module("mycode")
- coverage.stop()
-
+ self.import_module("mycode") # pragma: recursive coverage
+ coverage.stop() # pragma: recursive coverage
+
_, statements, missing, missingtext = coverage.analysis("mycode.py")
self.assertEqual(statements, [1,2,3,4,5])
self.assertEqual(missing, [4])
self.assertEqual(missingtext, "4")
-
+
def doReportWork(self, modname):
"""Create a module named `modname`, then measure it."""
coverage.erase()
@@ -46,21 +49,21 @@ class ApiTest(CoverageTest):
e = 6
f = 7
""")
-
+
# Import the python file, executing it.
coverage.start()
- self.import_module(modname)
- coverage.stop()
-
+ self.import_module(modname) # pragma: recursive coverage
+ coverage.stop() # pragma: recursive coverage
+
def testReport(self):
self.doReportWork("mycode2")
coverage.report(["mycode2.py"])
self.assertEqual(self.stdout(), textwrap.dedent("""\
- Name Stmts Exec Cover Missing
+ Name Stmts Miss Cover Missing
---------------------------------------
- mycode2 7 4 57% 4-6
+ mycode2 7 3 57% 4-6
"""))
-
+
def testReportFile(self):
# The file= argument of coverage.report makes the report go there.
self.doReportWork("mycode3")
@@ -68,9 +71,9 @@ class ApiTest(CoverageTest):
coverage.report(["mycode3.py"], file=fout)
self.assertEqual(self.stdout(), "")
self.assertEqual(fout.getvalue(), textwrap.dedent("""\
- Name Stmts Exec Cover Missing
+ Name Stmts Miss Cover Missing
---------------------------------------
- mycode3 7 4 57% 4-6
+ mycode3 7 3 57% 4-6
"""))
def testReportDefault(self):
@@ -78,7 +81,7 @@ class ApiTest(CoverageTest):
self.doReportWork("mycode4")
coverage.report()
rpt = re.sub(r"\s+", " ", self.stdout())
- self.assert_("mycode4 7 4 57% 4-6" in rpt)
+ self.assertTrue("mycode4 7 3 57% 4-6" in rpt)
def testUnexecutedFile(self):
cov = coverage.coverage()
@@ -90,16 +93,16 @@ class ApiTest(CoverageTest):
c = 4
d = 5
""")
-
+
self.make_file("not_run.py", """\
fooey = 17
""")
-
+
# Import the python file, executing it.
cov.start()
- self.import_module("mycode")
- cov.stop()
-
+ self.import_module("mycode") # pragma: recursive coverage
+ cov.stop() # pragma: recursive coverage
+
_, statements, missing, _ = cov.analysis("not_run.py")
self.assertEqual(statements, [1])
self.assertEqual(missing, [1])
@@ -110,22 +113,22 @@ class ApiTest(CoverageTest):
import mymod
a = 1
""")
-
+
self.make_file("mymod.py", """\
fooey = 17
""")
-
+
# Import the python file, executing it.
cov = coverage.coverage()
cov.start()
- self.import_module("mymain")
- cov.stop()
-
+ self.import_module("mymain") # pragma: recursive coverage
+ cov.stop() # pragma: recursive coverage
+
filename, _, _, _ = cov.analysis("mymain.py")
self.assertEqual(os.path.basename(filename), "mymain.py")
filename, _, _, _ = cov.analysis("mymod.py")
self.assertEqual(os.path.basename(filename), "mymod.py")
-
+
filename, _, _, _ = cov.analysis(sys.modules["mymain"])
self.assertEqual(os.path.basename(filename), "mymain.py")
filename, _, _, _ = cov.analysis(sys.modules["mymod"])
@@ -135,14 +138,14 @@ class ApiTest(CoverageTest):
# already.
cov = coverage.coverage()
cov.start()
- self.import_module("mymain")
- cov.stop()
-
+ self.import_module("mymain") # pragma: recursive coverage
+ cov.stop() # pragma: recursive coverage
+
filename, _, _, _ = cov.analysis("mymain.py")
self.assertEqual(os.path.basename(filename), "mymain.py")
filename, _, _, _ = cov.analysis("mymod.py")
self.assertEqual(os.path.basename(filename), "mymod.py")
-
+
filename, _, _, _ = cov.analysis(sys.modules["mymain"])
self.assertEqual(os.path.basename(filename), "mymain.py")
filename, _, _, _ = cov.analysis(sys.modules["mymod"])
@@ -154,17 +157,17 @@ class ApiTest(CoverageTest):
a = 1
hls = colorsys.rgb_to_hls(1.0, 0.5, 0.0)
""")
-
+
self.make_file("mymod.py", """\
fooey = 17
""")
# Measure without the stdlib.
cov1 = coverage.coverage()
- self.assertEqual(cov1.cover_pylib, False)
+ self.assertEqual(cov1.config.cover_pylib, False)
cov1.start()
- self.import_module("mymain")
- cov1.stop()
+ self.import_module("mymain") # pragma: recursive coverage
+ cov1.stop() # pragma: recursive coverage
# some statements were marked executed in mymain.py
_, statements, missing, _ = cov1.analysis("mymain.py")
@@ -176,8 +179,8 @@ class ApiTest(CoverageTest):
# Measure with the stdlib.
cov2 = coverage.coverage(cover_pylib=True)
cov2.start()
- self.import_module("mymain")
- cov2.stop()
+ self.import_module("mymain") # pragma: recursive coverage
+ cov2.stop() # pragma: recursive coverage
# some statements were marked executed in mymain.py
_, statements, missing, _ = cov2.analysis("mymain.py")
@@ -204,13 +207,13 @@ class ApiTest(CoverageTest):
fooey = 17
""")
- self.assert_equal_sets(os.listdir("."), ["datatest1.py"])
+ self.assertSameElements(os.listdir("."), ["datatest1.py"])
cov = coverage.coverage()
cov.start()
- self.import_module("datatest1")
- cov.stop()
+ self.import_module("datatest1") # pragma: recursive coverage
+ cov.stop() # pragma: recursive coverage
cov.save()
- self.assert_equal_sets(os.listdir("."),
+ self.assertSameElements(os.listdir("."),
["datatest1.py", "datatest1.pyc", ".coverage"])
def testDatafileSpecified(self):
@@ -219,13 +222,13 @@ class ApiTest(CoverageTest):
fooey = 17
""")
- self.assert_equal_sets(os.listdir("."), ["datatest2.py"])
+ self.assertSameElements(os.listdir("."), ["datatest2.py"])
cov = coverage.coverage(data_file="cov.data")
cov.start()
- self.import_module("datatest2")
- cov.stop()
+ self.import_module("datatest2") # pragma: recursive coverage
+ cov.stop() # pragma: recursive coverage
cov.save()
- self.assert_equal_sets(os.listdir("."),
+ self.assertSameElements(os.listdir("."),
["datatest2.py", "datatest2.pyc", "cov.data"])
def testDatafileAndSuffixSpecified(self):
@@ -234,17 +237,108 @@ class ApiTest(CoverageTest):
fooey = 17
""")
- self.assert_equal_sets(os.listdir("."), ["datatest3.py"])
- cov = coverage.coverage(data_file="cov.data", data_suffix=".14")
+ self.assertSameElements(os.listdir("."), ["datatest3.py"])
+ cov = coverage.coverage(data_file="cov.data", data_suffix="14")
cov.start()
- self.import_module("datatest3")
- cov.stop()
+ self.import_module("datatest3") # pragma: recursive coverage
+ cov.stop() # pragma: recursive coverage
cov.save()
- self.assert_equal_sets(os.listdir("."),
+ self.assertSameElements(os.listdir("."),
["datatest3.py", "datatest3.pyc", "cov.data.14"])
+ def testDatafileFromRcFile(self):
+ # You can specify the data file name in the .coveragerc file
+ self.make_file("datatest4.py", """\
+ fooey = 17
+ """)
+ self.make_file(".coveragerc", """\
+ [run]
+ data_file = mydata.dat
+ """)
+
+ self.assertSameElements(os.listdir("."),
+ ["datatest4.py", ".coveragerc"])
+ cov = coverage.coverage()
+ cov.start()
+ self.import_module("datatest4") # pragma: recursive coverage
+ cov.stop() # pragma: recursive coverage
+ cov.save()
+ self.assertSameElements(os.listdir("."),
+ ["datatest4.py", "datatest4.pyc", ".coveragerc", "mydata.dat"])
+
def testEmptyReporting(self):
# Used to be you'd get an exception reporting on nothing...
cov = coverage.coverage()
cov.erase()
cov.report()
+
+class OmitIncludeTest(CoverageTest):
+ """Test using omit_prefixes and include_prefixes when measuring code."""
+
+ def test_nothing_specified(self):
+ self.make_file("a.py", """\
+ a = 1
+ """)
+ self.make_file("b.py", """\
+ import a
+ b = 1
+ """)
+
+ cov = coverage.coverage()
+ cov.start()
+ self.import_module("b")
+ cov.stop()
+ lines = cov.data.summary()
+ self.assertEqual(lines['a.py'], 1)
+ self.assertEqual(lines['b.py'], 2)
+
+ def test_include(self):
+ self.make_file("a.py", """\
+ a = 1
+ """)
+ self.make_file("b.py", """\
+ import a
+ b = 1
+ """)
+
+ cov = coverage.coverage(include_prefixes=["a"])
+ cov.start()
+ self.import_module("b")
+ cov.stop()
+ lines = cov.data.summary()
+ self.assertEqual(lines['a.py'], 1)
+ self.assert_('b.py' not in lines)
+
+ def test_omit(self):
+ self.make_file("a.py", """\
+ a = 1
+ """)
+ self.make_file("b.py", """\
+ import a
+ b = 1
+ """)
+
+ cov = coverage.coverage(omit_prefixes=["a"])
+ cov.start()
+ self.import_module("b")
+ cov.stop()
+ lines = cov.data.summary()
+ self.assert_('a.py' not in lines)
+ self.assertEqual(lines['b.py'], 2)
+
+ def test_omit_and_include(self):
+ self.make_file("aa.py", """\
+ a = 1
+ """)
+ self.make_file("ab.py", """\
+ import aa
+ b = 1
+ """)
+
+ cov = coverage.coverage(include_prefixes=["a"], omit_prefixes=["aa"])
+ cov.start()
+ self.import_module("ab")
+ cov.stop()
+ lines = cov.data.summary()
+ self.assert_('aa.py' not in lines)
+ self.assertEqual(lines['ab.py'], 2)
diff --git a/test/test_arcs.py b/test/test_arcs.py
index dea3700f..41731dba 100644
--- a/test/test_arcs.py
+++ b/test/test_arcs.py
@@ -25,16 +25,16 @@ class SimpleArcTest(CoverageTest):
a = 2
b = 3
-
+
c = 5
""",
- arcz=".2 23 35 5.")
+ arcz=".2 23 35 5-2")
def test_function_def(self):
self.check_coverage("""\
def foo():
a = 2
-
+
foo()
""",
arcz=".1 .2 14 2. 4.")
@@ -54,7 +54,7 @@ class SimpleArcTest(CoverageTest):
assert a == 1
""",
arcz=".1 12 23 24 34 4.", arcz_missing="23 34")
-
+
def test_if_else(self):
self.check_coverage("""\
if len([]) == 0:
@@ -90,6 +90,12 @@ class SimpleArcTest(CoverageTest):
arcz=".1 14 45 5. .2 2. 23 3.", arcz_missing="23 3.")
def test_multiline(self):
+ # The firstlineno of the a assignment below differs among Python
+ # versions.
+ if sys.version_info >= (2, 5):
+ arcz = ".1 15 5-2"
+ else:
+ arcz = ".1 15 5-1"
self.check_coverage("""\
a = (
2 +
@@ -98,7 +104,7 @@ class SimpleArcTest(CoverageTest):
b = \\
6
""",
- arcz=".1 15 5.", arcz_missing="")
+ arcz=arcz, arcz_missing="")
def test_if_return(self):
self.check_coverage("""\
@@ -113,10 +119,33 @@ class SimpleArcTest(CoverageTest):
arcz=".1 16 67 7. .2 23 24 3. 45 5.", arcz_missing=""
)
+ def test_dont_confuse_exit_and_else(self):
+ self.check_coverage("""\
+ def foo():
+ if foo:
+ a = 3
+ else:
+ a = 5
+ return a
+ assert foo() == 3 # 7
+ """,
+ arcz=".1 17 7. .2 23 36 25 56 6.", arcz_missing="25 56"
+ )
+ self.check_coverage("""\
+ def foo():
+ if foo:
+ a = 3
+ else:
+ a = 5
+ foo() # 6
+ """,
+ arcz=".1 16 6. .2 23 3. 25 5.", arcz_missing="25 5."
+ )
+
class LoopArcTest(CoverageTest):
"""Arc-measuring tests involving loops."""
-
+
def test_loop(self):
self.check_coverage("""\
for i in range(10):
@@ -189,7 +218,7 @@ class LoopArcTest(CoverageTest):
)
# With "while True", 2.x thinks it's computation, 3.x thinks it's
# constant.
- if sys.hexversion >= 0x03000000:
+ if sys.version_info >= (3, 0):
arcz = ".1 12 23 34 45 36 63 57 27 7."
else:
arcz = ".1 12 23 34 45 36 62 57 27 7."
@@ -206,6 +235,33 @@ class LoopArcTest(CoverageTest):
arcz_missing="27" # while loop never exits naturally.
)
+ def test_for_if_else_for(self):
+ self.check_coverage("""\
+ def branches_2(l):
+ if l:
+ for e in l:
+ a = 4
+ else:
+ a = 6
+
+ def branches_3(l):
+ for x in l:
+ if x:
+ for e in l:
+ a = 12
+ else:
+ a = 14
+
+ branches_2([0,1])
+ branches_3([0,1])
+ """,
+ arcz=
+ ".1 18 8G GH H. "
+ ".2 23 34 43 26 3. 6. "
+ ".9 9A 9-8 AB BC CB B9 AE E9",
+ arcz_missing="26 6."
+ )
+
class ExceptionArcTest(CoverageTest):
"""Arc-measuring tests involving exception handling."""
@@ -246,7 +302,7 @@ class ExceptionArcTest(CoverageTest):
b = 9
assert a == 5 and b == 9
""",
- arcz=".1 12 .3 3. 24 45 56 67 7A 89 9A A.",
+ arcz=".1 12 .3 3-2 24 45 56 67 7A 89 9A A.",
arcz_missing="67 7A", arcz_unpredicted="68")
def test_except_with_type(self):
@@ -265,7 +321,7 @@ class ExceptionArcTest(CoverageTest):
assert try_it(0) == 8 # C
assert try_it(1) == 6 # D
""",
- arcz=".1 12 .3 3. 24 4C CD D. .5 56 67 78 8B 9A AB B.",
+ arcz=".1 12 .3 3-2 24 4C CD D. .5 56 67 78 8B 9A AB B-4",
arcz_missing="",
arcz_unpredicted="79")
@@ -364,7 +420,7 @@ class ExceptionArcTest(CoverageTest):
arcz=".1 12 23 34 3D 45 56 67 68 7A 8A A3 AB AD BC CD D.",
arcz_missing="3D AB BC CD", arcz_unpredicted="")
- if sys.hexversion >= 0x02050000:
+ if sys.version_info >= (2, 5):
# Try-except-finally was new in 2.5
def test_except_finally(self):
self.check_coverage("""\
@@ -392,7 +448,7 @@ class ExceptionArcTest(CoverageTest):
c = 11
assert a == 5 and b == 9 and c == 11
""",
- arcz=".1 12 .3 3. 24 45 56 67 7B 89 9B BC C.",
+ arcz=".1 12 .3 3-2 24 45 56 67 7B 89 9B BC C.",
arcz_missing="67 7B", arcz_unpredicted="68")
diff --git a/test/test_cmdline.py b/test/test_cmdline.py
index cedcec1d..15fe1cec 100644
--- a/test/test_cmdline.py
+++ b/test/test_cmdline.py
@@ -1,33 +1,24 @@
"""Test cmdline.py for coverage."""
-import os, re, shlex, sys, textwrap, unittest
+import os, pprint, re, shlex, sys, textwrap
import mock
import coverage
+import coverage.cmdline
+from coverage.misc import ExceptionDuringRun
sys.path.insert(0, os.path.split(__file__)[0]) # Force relative import for Py3k
-from coveragetest import CoverageTest
+from coveragetest import CoverageTest, OK, ERR
-OK, ERR = 0, 1
-
class CmdLineTest(CoverageTest):
"""Tests of execution paths through the command line interpreter."""
-
+
run_in_temp_dir = False
INIT_LOAD = """\
- .coverage(cover_pylib=None, data_suffix=False, timid=None, branch=None)
- .load()\n"""
-
- def command_line(self, args, ret=OK):
- """Run `args` through the command line.
-
- Checks that `ret` is returned.
-
- """
- ret_actual = coverage.CoverageScript().command_line(shlex.split(args))
- self.assertEqual(ret_actual, ret)
-
+ .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, include_prefixes=None, omit_prefixes=None)
+ .load()\n"""
+
def model_object(self):
"""Return a Mock suitable for use in CoverageScript."""
mk = mock.Mock()
@@ -36,16 +27,16 @@ class CmdLineTest(CoverageTest):
def mock_command_line(self, args):
"""Run `args` through the command line, with a Mock.
-
+
Returns the Mock it used and the status code returned.
-
+
"""
m = self.model_object()
ret = coverage.CoverageScript(
_covpkg=m, _run_python_file=m.run_python_file, _help_fn=m.help_fn
).command_line(shlex.split(args))
return m, ret
-
+
def cmd_executes(self, args, code, ret=OK):
"""Assert that the `args` end up executing the sequence in `code`."""
m1, r1 = self.mock_command_line(args)
@@ -53,26 +44,37 @@ class CmdLineTest(CoverageTest):
"Wrong status: got %s, wanted %s" % (r1, ret)
)
- code = textwrap.dedent(code)
+ # Remove all indentation, and change ".foo()" to "m2.foo()".
+ code = re.sub(r"(?m)^\s+", "", code)
code = re.sub(r"(?m)^\.", "m2.", code)
m2 = self.model_object()
code_obj = compile(code, "<code>", "exec")
eval(code_obj, globals(), { 'm2': m2 })
- self.assertEqual(m1.method_calls, m2.method_calls)
-
+ self.assert_same_method_calls(m1, m2)
+
def cmd_executes_same(self, args1, args2):
"""Assert that the `args1` executes the same as `args2`."""
m1, r1 = self.mock_command_line(args1)
m2, r2 = self.mock_command_line(args2)
self.assertEqual(r1, r2)
- self.assertEqual(m1.method_calls, m2.method_calls)
+ self.assert_same_method_calls(m1, m2)
+
+ def assert_same_method_calls(self, m1, m2):
+ """Assert that `m1.method_calls` and `m2.method_calls` are the same."""
+ # Use a real equality comparison, but if it fails, use a nicer assert
+ # so we can tell what's going on. We have to use the real == first due
+ # to CmdOptionParser.__eq__
+ if m1.method_calls != m2.method_calls:
+ pp1 = pprint.pformat(m1.method_calls)
+ pp2 = pprint.pformat(m2.method_calls)
+ self.assertMultiLineEqual(pp1+'\n', pp2+'\n')
def cmd_help(self, args, help_msg=None, topic=None, ret=ERR):
"""Run a command line, and check that it prints the right help.
-
+
Only the last function call in the mock is checked, which should be the
help message that we want to see.
-
+
"""
m, r = self.mock_command_line(args)
self.assertEqual(r, ret,
@@ -86,7 +88,7 @@ class CmdLineTest(CoverageTest):
self.assertEqual(m.method_calls[-1],
('help_fn', (), {'topic':topic})
)
-
+
class ClassicCmdLineTest(CmdLineTest):
"""Tests of the classic coverage.py command line."""
@@ -94,17 +96,17 @@ class ClassicCmdLineTest(CmdLineTest):
def testErase(self):
# coverage -e
self.cmd_executes("-e", """\
- .coverage(cover_pylib=None, data_suffix=False, timid=None, branch=None)
+ .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, include_prefixes=None, omit_prefixes=None)
.erase()
""")
self.cmd_executes_same("-e", "--erase")
def testExecute(self):
# coverage -x [-p] [-L] [--timid] MODULE.py [ARG1 ARG2 ...]
-
+
# -x calls coverage.load first.
self.cmd_executes("-x foo.py", """\
- .coverage(cover_pylib=None, data_suffix=False, timid=None, branch=None)
+ .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, include_prefixes=None, omit_prefixes=None)
.load()
.start()
.run_python_file('foo.py', ['foo.py'])
@@ -113,7 +115,7 @@ class ClassicCmdLineTest(CmdLineTest):
""")
# -e -x calls coverage.erase first.
self.cmd_executes("-e -x foo.py", """\
- .coverage(cover_pylib=None, data_suffix=False, timid=None, branch=None)
+ .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, include_prefixes=None, omit_prefixes=None)
.erase()
.start()
.run_python_file('foo.py', ['foo.py'])
@@ -122,7 +124,7 @@ class ClassicCmdLineTest(CmdLineTest):
""")
# --timid sets a flag, and program arguments get passed through.
self.cmd_executes("-x --timid foo.py abc 123", """\
- .coverage(cover_pylib=None, data_suffix=False, timid=True, branch=None)
+ .coverage(cover_pylib=None, data_suffix=None, timid=True, branch=None, config_file=True, include_prefixes=None, omit_prefixes=None)
.load()
.start()
.run_python_file('foo.py', ['foo.py', 'abc', '123'])
@@ -131,7 +133,7 @@ class ClassicCmdLineTest(CmdLineTest):
""")
# -L sets a flag, and flags for the program don't confuse us.
self.cmd_executes("-x -p -L foo.py -a -b", """\
- .coverage(cover_pylib=True, data_suffix=True, timid=None, branch=None)
+ .coverage(cover_pylib=True, data_suffix=True, timid=None, branch=None, config_file=True, include_prefixes=None, omit_prefixes=None)
.load()
.start()
.run_python_file('foo.py', ['foo.py', '-a', '-b'])
@@ -148,7 +150,7 @@ class ClassicCmdLineTest(CmdLineTest):
def testCombine(self):
# coverage -c
self.cmd_executes("-c", """\
- .coverage(cover_pylib=None, data_suffix=False, timid=None, branch=None)
+ .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, include_prefixes=None, omit_prefixes=None)
.load()
.combine()
.save()
@@ -158,31 +160,35 @@ class ClassicCmdLineTest(CmdLineTest):
def testReport(self):
# coverage -r [-m] [-i] [-o DIR,...] [FILE1 FILE2 ...]
self.cmd_executes("-r", self.INIT_LOAD + """\
- .report(ignore_errors=None, omit_prefixes=None, morfs=[],
+ .report(ignore_errors=None, omit_prefixes=None, include_prefixes=None, morfs=[],
show_missing=None)
""")
self.cmd_executes("-r -i", self.INIT_LOAD + """\
- .report(ignore_errors=True, omit_prefixes=None, morfs=[],
+ .report(ignore_errors=True, omit_prefixes=None, include_prefixes=None, morfs=[],
show_missing=None)
""")
self.cmd_executes("-r -m", self.INIT_LOAD + """\
- .report(ignore_errors=None, omit_prefixes=None, morfs=[],
+ .report(ignore_errors=None, omit_prefixes=None, include_prefixes=None, morfs=[],
show_missing=True)
""")
- self.cmd_executes("-r -o fooey", self.INIT_LOAD + """\
- .report(ignore_errors=None, omit_prefixes=["fooey"],
+ self.cmd_executes("-r -o fooey", """\
+ .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, include_prefixes=None, omit_prefixes=["fooey"])
+ .load()
+ .report(ignore_errors=None, omit_prefixes=["fooey"], include_prefixes=None,
morfs=[], show_missing=None)
""")
- self.cmd_executes("-r -o fooey,booey", self.INIT_LOAD + """\
- .report(ignore_errors=None, omit_prefixes=["fooey", "booey"],
+ self.cmd_executes("-r -o fooey,booey", """\
+ .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, include_prefixes=None, omit_prefixes=["fooey", "booey"])
+ .load()
+ .report(ignore_errors=None, omit_prefixes=["fooey", "booey"], include_prefixes=None,
morfs=[], show_missing=None)
""")
self.cmd_executes("-r mod1", self.INIT_LOAD + """\
- .report(ignore_errors=None, omit_prefixes=None,
+ .report(ignore_errors=None, omit_prefixes=None, include_prefixes=None,
morfs=["mod1"], show_missing=None)
""")
self.cmd_executes("-r mod1 mod2 mod3", self.INIT_LOAD + """\
- .report(ignore_errors=None, omit_prefixes=None,
+ .report(ignore_errors=None, omit_prefixes=None, include_prefixes=None,
morfs=["mod1", "mod2", "mod3"], show_missing=None)
""")
@@ -200,31 +206,35 @@ class ClassicCmdLineTest(CmdLineTest):
# coverage -a [-d DIR] [-i] [-o DIR,...] [FILE1 FILE2 ...]
self.cmd_executes("-a", self.INIT_LOAD + """\
.annotate(directory=None, ignore_errors=None,
- omit_prefixes=None, morfs=[])
+ omit_prefixes=None, include_prefixes=None, morfs=[])
""")
self.cmd_executes("-a -d dir1", self.INIT_LOAD + """\
.annotate(directory="dir1", ignore_errors=None,
- omit_prefixes=None, morfs=[])
+ omit_prefixes=None, include_prefixes=None, morfs=[])
""")
self.cmd_executes("-a -i", self.INIT_LOAD + """\
.annotate(directory=None, ignore_errors=True,
- omit_prefixes=None, morfs=[])
+ omit_prefixes=None, include_prefixes=None, morfs=[])
""")
- self.cmd_executes("-a -o fooey", self.INIT_LOAD + """\
+ self.cmd_executes("-a -o fooey", """\
+ .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, include_prefixes=None, omit_prefixes=["fooey"])
+ .load()
.annotate(directory=None, ignore_errors=None,
- omit_prefixes=["fooey"], morfs=[])
+ omit_prefixes=["fooey"], include_prefixes=None, morfs=[])
""")
- self.cmd_executes("-a -o fooey,booey", self.INIT_LOAD + """\
+ self.cmd_executes("-a -o fooey,booey", """\
+ .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, include_prefixes=None, omit_prefixes=["fooey", "booey"])
+ .load()
.annotate(directory=None, ignore_errors=None,
- omit_prefixes=["fooey", "booey"], morfs=[])
+ omit_prefixes=["fooey", "booey"], include_prefixes=None, morfs=[])
""")
self.cmd_executes("-a mod1", self.INIT_LOAD + """\
.annotate(directory=None, ignore_errors=None,
- omit_prefixes=None, morfs=["mod1"])
+ omit_prefixes=None, include_prefixes=None, morfs=["mod1"])
""")
self.cmd_executes("-a mod1 mod2 mod3", self.INIT_LOAD + """\
.annotate(directory=None, ignore_errors=None,
- omit_prefixes=None, morfs=["mod1", "mod2", "mod3"])
+ omit_prefixes=None, include_prefixes=None, morfs=["mod1", "mod2", "mod3"])
""")
self.cmd_executes_same("-a", "--annotate")
@@ -241,31 +251,35 @@ class ClassicCmdLineTest(CmdLineTest):
# coverage -b -d DIR [-i] [-o DIR,...] [FILE1 FILE2 ...]
self.cmd_executes("-b", self.INIT_LOAD + """\
.html_report(directory=None, ignore_errors=None,
- omit_prefixes=None, morfs=[])
+ omit_prefixes=None, include_prefixes=None, morfs=[])
""")
self.cmd_executes("-b -d dir1", self.INIT_LOAD + """\
.html_report(directory="dir1", ignore_errors=None,
- omit_prefixes=None, morfs=[])
+ omit_prefixes=None, include_prefixes=None, morfs=[])
""")
self.cmd_executes("-b -i", self.INIT_LOAD + """\
.html_report(directory=None, ignore_errors=True,
- omit_prefixes=None, morfs=[])
+ omit_prefixes=None, include_prefixes=None, morfs=[])
""")
- self.cmd_executes("-b -o fooey", self.INIT_LOAD + """\
+ self.cmd_executes("-b -o fooey", """\
+ .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, include_prefixes=None, omit_prefixes=["fooey"])
+ .load()
.html_report(directory=None, ignore_errors=None,
- omit_prefixes=["fooey"], morfs=[])
+ omit_prefixes=["fooey"], include_prefixes=None, morfs=[])
""")
- self.cmd_executes("-b -o fooey,booey", self.INIT_LOAD + """\
+ self.cmd_executes("-b -o fooey,booey", """\
+ .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, include_prefixes=None, omit_prefixes=["fooey", "booey"])
+ .load()
.html_report(directory=None, ignore_errors=None,
- omit_prefixes=["fooey", "booey"], morfs=[])
+ omit_prefixes=["fooey", "booey"], include_prefixes=None, morfs=[])
""")
self.cmd_executes("-b mod1", self.INIT_LOAD + """\
.html_report(directory=None, ignore_errors=None,
- omit_prefixes=None, morfs=["mod1"])
+ omit_prefixes=None, include_prefixes=None, morfs=["mod1"])
""")
self.cmd_executes("-b mod1 mod2 mod3", self.INIT_LOAD + """\
.html_report(directory=None, ignore_errors=None,
- omit_prefixes=None, morfs=["mod1", "mod2", "mod3"])
+ omit_prefixes=None, include_prefixes=None, morfs=["mod1", "mod2", "mod3"])
""")
self.cmd_executes_same("-b", "--html")
@@ -281,8 +295,12 @@ class ClassicCmdLineTest(CmdLineTest):
self.cmd_help("-h", topic="help", ret=OK)
self.cmd_help("--help", topic="help", ret=OK)
+ def testVersion(self):
+ # coverage --version
+ self.cmd_help("--version", topic="version", ret=OK)
+
## Error cases
-
+
def testArglessActions(self):
self.cmd_help("-e foo bar", "Unexpected arguments: foo bar")
self.cmd_help("-c baz quux", "Unexpected arguments: baz quux")
@@ -332,6 +350,33 @@ class ClassicCmdLineTest(CmdLineTest):
self.cmd_help("-z", "no such option: -z")
+class FakeCoverageForDebugData(object):
+ """Just enough of a fake coverage package for the 'debug data' tests."""
+ def __init__(self, summary):
+ self._summary = summary
+ self.filename = "FILENAME"
+ self.data = self
+
+ # package members
+ def coverage(self, *unused_args, **unused_kwargs):
+ """The coverage class in the package."""
+ return self
+
+ # coverage methods
+ def load(self):
+ """Fake coverage().load()"""
+ pass
+
+ # data methods
+ def has_arcs(self):
+ """Fake coverage().data.has_arcs()"""
+ return False
+
+ def summary(self, fullpath): # pylint: disable-msg=W0613
+ """Fake coverage().data.summary()"""
+ return self._summary
+
+
class NewCmdLineTest(CmdLineTest):
"""Tests of the coverage.py command line."""
@@ -351,12 +396,37 @@ class NewCmdLineTest(CmdLineTest):
self.cmd_help("debug", "What information would you like: data, sys?")
self.cmd_help("debug foo", "Don't know what you mean by 'foo'")
+ def testDebugData(self):
+ fake = FakeCoverageForDebugData({
+ 'file1.py': 17, 'file2.py': 23,
+ })
+ self.command_line("debug data", _covpkg=fake)
+ self.assertMultiLineEqual(self.stdout(), textwrap.dedent("""\
+ -- data ---------------------------------------
+ path: FILENAME
+ has_arcs: False
+
+ 2 files:
+ file1.py: 17 lines
+ file2.py: 23 lines
+ """))
+
+ def testDebugDataWithNoData(self):
+ fake = FakeCoverageForDebugData({})
+ self.command_line("debug data", _covpkg=fake)
+ self.assertMultiLineEqual(self.stdout(), textwrap.dedent("""\
+ -- data ---------------------------------------
+ path: FILENAME
+ has_arcs: False
+ No data collected
+ """))
+
def testDebugSys(self):
self.command_line("debug sys")
out = self.stdout()
assert "version:" in out
- assert "data_file:" in out
-
+ assert "data_path:" in out
+
def testErase(self):
self.cmd_executes_same("erase", "-e")
@@ -394,39 +464,87 @@ class NewCmdLineTest(CmdLineTest):
self.cmd_executes_same("run -L f.py", "-e -x -L f.py")
self.cmd_executes_same("run --timid f.py", "-e -x --timid f.py")
self.cmd_executes_same("run", "-x")
-
+ self.cmd_executes("run --branch foo.py", """\
+ .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=True, config_file=True, include_prefixes=None, omit_prefixes=None)
+ .erase()
+ .start()
+ .run_python_file('foo.py', ['foo.py'])
+ .stop()
+ .save()
+ """)
+ self.cmd_executes("run --rcfile=myrc.rc foo.py", """\
+ .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file="myrc.rc", include_prefixes=None, omit_prefixes=None)
+ .erase()
+ .start()
+ .run_python_file('foo.py', ['foo.py'])
+ .stop()
+ .save()
+ """)
+ self.cmd_executes("run --include=pre1,pre2 foo.py", """\
+ .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, include_prefixes=["pre1", "pre2"], omit_prefixes=None)
+ .erase()
+ .start()
+ .run_python_file('foo.py', ['foo.py'])
+ .stop()
+ .save()
+ """)
+ self.cmd_executes("run --omit=opre1,opre2 foo.py", """\
+ .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, include_prefixes=None, omit_prefixes=["opre1", "opre2"])
+ .erase()
+ .start()
+ .run_python_file('foo.py', ['foo.py'])
+ .stop()
+ .save()
+ """)
+ self.cmd_executes("run --include=pre1,pre2 --omit=opre1,opre2 foo.py",
+ """\
+ .coverage(cover_pylib=None, data_suffix=None, timid=None,
+ branch=None, config_file=True,
+ include_prefixes=["pre1", "pre2"],
+ omit_prefixes=["opre1", "opre2"])
+ .erase()
+ .start()
+ .run_python_file('foo.py', ['foo.py'])
+ .stop()
+ .save()
+ """)
+
def testXml(self):
# coverage xml [-i] [--omit DIR,...] [FILE1 FILE2 ...]
self.cmd_executes("xml", self.INIT_LOAD + """\
- .xml_report(ignore_errors=None, omit_prefixes=None, morfs=[],
+ .xml_report(ignore_errors=None, omit_prefixes=None, include_prefixes=None, morfs=[],
outfile="coverage.xml")
""")
self.cmd_executes("xml -i", self.INIT_LOAD + """\
- .xml_report(ignore_errors=True, omit_prefixes=None, morfs=[],
+ .xml_report(ignore_errors=True, omit_prefixes=None, include_prefixes=None, morfs=[],
outfile="coverage.xml")
""")
self.cmd_executes("xml -o myxml.foo", self.INIT_LOAD + """\
- .xml_report(ignore_errors=None, omit_prefixes=None, morfs=[],
+ .xml_report(ignore_errors=None, omit_prefixes=None, include_prefixes=None, morfs=[],
outfile="myxml.foo")
""")
self.cmd_executes("xml -o -", self.INIT_LOAD + """\
- .xml_report(ignore_errors=None, omit_prefixes=None, morfs=[],
- outfile=None)
+ .xml_report(ignore_errors=None, omit_prefixes=None, include_prefixes=None, morfs=[],
+ outfile="-")
""")
- self.cmd_executes("xml --omit fooey", self.INIT_LOAD + """\
- .xml_report(ignore_errors=None, omit_prefixes=["fooey"], morfs=[],
+ self.cmd_executes("xml --omit fooey", """\
+ .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, include_prefixes=None, omit_prefixes=["fooey"])
+ .load()
+ .xml_report(ignore_errors=None, omit_prefixes=["fooey"], include_prefixes=None, morfs=[],
outfile="coverage.xml")
""")
- self.cmd_executes("xml --omit fooey,booey", self.INIT_LOAD + """\
- .xml_report(ignore_errors=None, omit_prefixes=["fooey", "booey"],
+ self.cmd_executes("xml --omit fooey,booey", """\
+ .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, include_prefixes=None, omit_prefixes=["fooey", "booey"])
+ .load()
+ .xml_report(ignore_errors=None, omit_prefixes=["fooey", "booey"], include_prefixes=None,
morfs=[], outfile="coverage.xml")
""")
self.cmd_executes("xml mod1", self.INIT_LOAD + """\
- .xml_report(ignore_errors=None, omit_prefixes=None, morfs=["mod1"],
+ .xml_report(ignore_errors=None, omit_prefixes=None, include_prefixes=None, morfs=["mod1"],
outfile="coverage.xml")
""")
self.cmd_executes("xml mod1 mod2 mod3", self.INIT_LOAD + """\
- .xml_report(ignore_errors=None, omit_prefixes=None,
+ .xml_report(ignore_errors=None, omit_prefixes=None, include_prefixes=None,
morfs=["mod1", "mod2", "mod3"], outfile="coverage.xml")
""")
@@ -439,19 +557,19 @@ class NewCmdLineTest(CmdLineTest):
class CmdLineStdoutTest(CmdLineTest):
"""Test the command line with real stdout output."""
-
+
def testMinimumHelp(self):
self.command_line("")
out = self.stdout()
assert "Code coverage for Python." in out
assert out.count("\n") < 4
-
+
def testHelp(self):
self.command_line("help")
out = self.stdout()
assert "nedbatchelder.com" in out
assert out.count("\n") > 10
-
+
def testCmdHelp(self):
self.command_line("help run")
out = self.stdout()
@@ -466,5 +584,58 @@ class CmdLineStdoutTest(CmdLineTest):
assert "help" in out
-if __name__ == '__main__':
- unittest.main()
+class CmdMainTest(CoverageTest):
+ """Tests of coverage.cmdline.main(), using mocking for isolation."""
+
+ class CoverageScriptStub(object):
+ """A stub for coverage.cmdline.CoverageScript, used by CmdMainTest."""
+
+ def command_line(self, argv):
+ """Stub for command_line, the arg determines what it will do."""
+ if argv[0] == 'hello':
+ print("Hello, world!")
+ elif argv[0] == 'raise':
+ try:
+ raise Exception("oh noes!")
+ except:
+ raise ExceptionDuringRun(*sys.exc_info())
+ elif argv[0] == 'internalraise':
+ raise ValueError("coverage is broken")
+ elif argv[0] == 'exit':
+ sys.exit(23)
+ else:
+ raise AssertionError("Bad CoverageScriptStub: %r"% (argv,))
+ return 0
+
+ def setUp(self):
+ super(CmdMainTest, self).setUp()
+ self.old_CoverageScript = coverage.cmdline.CoverageScript
+ coverage.cmdline.CoverageScript = self.CoverageScriptStub
+
+ def tearDown(self):
+ coverage.cmdline.CoverageScript = self.old_CoverageScript
+ super(CmdMainTest, self).tearDown()
+
+ def test_normal(self):
+ ret = coverage.cmdline.main(['hello'])
+ self.assertEqual(ret, 0)
+ self.assertEqual(self.stdout(), "Hello, world!\n")
+
+ def test_raise(self):
+ ret = coverage.cmdline.main(['raise'])
+ self.assertEqual(ret, 1)
+ self.assertEqual(self.stdout(), "")
+ err = self.stderr().split('\n')
+ self.assertEqual(err[0], 'Traceback (most recent call last):')
+ self.assertEqual(err[-3], ' raise Exception("oh noes!")')
+ self.assertEqual(err[-2], 'Exception: oh noes!')
+
+ def test_internalraise(self):
+ self.assertRaisesRegexp(ValueError,
+ "coverage is broken",
+ coverage.cmdline.main, ['internalraise']
+ )
+
+ def test_exit(self):
+ ret = coverage.cmdline.main(['exit'])
+ self.assertEqual(ret, 23)
diff --git a/test/test_codeunit.py b/test/test_codeunit.py
index 96df9633..7903d153 100644
--- a/test/test_codeunit.py
+++ b/test/test_codeunit.py
@@ -21,7 +21,7 @@ class CodeUnitTest(CoverageTest):
# Parent class saves and restores sys.path, we can just modify it.
testmods = self.nice_file(os.path.dirname(__file__), 'modules')
sys.path.append(testmods)
-
+
def test_filenames(self):
acu = code_unit_factory("aa/afile.py", FileLocator())
bcu = code_unit_factory("aa/bb/bfile.py", FileLocator())
@@ -36,6 +36,20 @@ class CodeUnitTest(CoverageTest):
self.assertEqual(bcu[0].source_file().read(), "# bfile.py\n")
self.assertEqual(ccu[0].source_file().read(), "# cfile.py\n")
+ def test_odd_filenames(self):
+ acu = code_unit_factory("aa/afile.odd.py", FileLocator())
+ bcu = code_unit_factory("aa/bb/bfile.odd.py", FileLocator())
+ b2cu = code_unit_factory("aa/bb.odd/bfile.py", FileLocator())
+ self.assertEqual(acu[0].name, "aa/afile.odd")
+ self.assertEqual(bcu[0].name, "aa/bb/bfile.odd")
+ self.assertEqual(b2cu[0].name, "aa/bb.odd/bfile")
+ self.assertEqual(acu[0].flat_rootname(), "aa_afile_odd")
+ self.assertEqual(bcu[0].flat_rootname(), "aa_bb_bfile_odd")
+ self.assertEqual(b2cu[0].flat_rootname(), "aa_bb_odd_bfile")
+ self.assertEqual(acu[0].source_file().read(), "# afile.odd.py\n")
+ self.assertEqual(bcu[0].source_file().read(), "# bfile.odd.py\n")
+ self.assertEqual(b2cu[0].source_file().read(), "# bfile.py\n")
+
def test_modules(self):
import aa, aa.bb, aa.bb.cc
cu = code_unit_factory([aa, aa.bb, aa.bb.cc], FileLocator())
@@ -64,10 +78,10 @@ class CodeUnitTest(CoverageTest):
self.assertEqual(cu[2].source_file().read(), "# cfile.py\n")
def test_comparison(self):
- acu = code_unit_factory("aa/afile.py", FileLocator())
- acu2 = code_unit_factory("aa/afile.py", FileLocator())
- zcu = code_unit_factory("aa/zfile.py", FileLocator())
- bcu = code_unit_factory("aa/bb/bfile.py", FileLocator())
+ acu = code_unit_factory("aa/afile.py", FileLocator())[0]
+ acu2 = code_unit_factory("aa/afile.py", FileLocator())[0]
+ zcu = code_unit_factory("aa/zfile.py", FileLocator())[0]
+ bcu = code_unit_factory("aa/bb/bfile.py", FileLocator())[0]
assert acu == acu2 and acu <= acu2 and acu >= acu2
assert acu < zcu and acu <= zcu and acu != zcu
assert zcu > acu and zcu >= acu and zcu != acu
@@ -81,4 +95,3 @@ class CodeUnitTest(CoverageTest):
self.assertEqual(cu[1].source_file().read().split("\n")[0],
"# My egg file!"
)
- \ No newline at end of file
diff --git a/test/test_config.py b/test/test_config.py
new file mode 100644
index 00000000..d29ab3d7
--- /dev/null
+++ b/test/test_config.py
@@ -0,0 +1,147 @@
+"""Test the config file handling for coverage.py"""
+
+import os, sys
+import coverage
+
+sys.path.insert(0, os.path.split(__file__)[0]) # Force relative import for Py3k
+from coveragetest import CoverageTest
+
+
+class ConfigTest(CoverageTest):
+ """Tests of the different sources of configuration settings."""
+
+ def test_default_config(self):
+ # Just constructing a coverage() object gets the right defaults.
+ cov = coverage.coverage()
+ self.assertFalse(cov.config.timid)
+ self.assertFalse(cov.config.branch)
+ self.assertEqual(cov.config.data_file, ".coverage")
+
+ def test_arguments(self):
+ # Arguments to the constructor are applied to the configuation.
+ cov = coverage.coverage(timid=True, data_file="fooey.dat")
+ self.assertTrue(cov.config.timid)
+ self.assertFalse(cov.config.branch)
+ self.assertEqual(cov.config.data_file, "fooey.dat")
+
+ def test_config_file(self):
+ # A .coveragerc file will be read into the configuration.
+ self.make_file(".coveragerc", """\
+ # This is just a bogus .rc file for testing.
+ [run]
+ timid = True
+ data_file = .hello_kitty.data
+ """)
+ cov = coverage.coverage()
+ self.assertTrue(cov.config.timid)
+ self.assertFalse(cov.config.branch)
+ self.assertEqual(cov.config.data_file, ".hello_kitty.data")
+
+ def test_named_config_file(self):
+ # You can name the config file what you like.
+ self.make_file("my_cov.ini", """\
+ [run]
+ timid = True
+ ; I wouldn't really use this as a data file...
+ data_file = delete.me
+ """)
+ cov = coverage.coverage(config_file="my_cov.ini")
+ self.assertTrue(cov.config.timid)
+ self.assertFalse(cov.config.branch)
+ self.assertEqual(cov.config.data_file, "delete.me")
+
+ def test_ignored_config_file(self):
+ # You can disable reading the .coveragerc file.
+ self.make_file(".coveragerc", """\
+ [run]
+ timid = True
+ data_file = delete.me
+ """)
+ cov = coverage.coverage(config_file=False)
+ self.assertFalse(cov.config.timid)
+ self.assertFalse(cov.config.branch)
+ self.assertEqual(cov.config.data_file, ".coverage")
+
+ def test_config_file_then_args(self):
+ # The arguments override the .coveragerc file.
+ self.make_file(".coveragerc", """\
+ [run]
+ timid = True
+ data_file = weirdo.file
+ """)
+ cov = coverage.coverage(timid=False, data_file=".mycov")
+ self.assertFalse(cov.config.timid)
+ self.assertFalse(cov.config.branch)
+ self.assertEqual(cov.config.data_file, ".mycov")
+
+ def test_data_file_from_environment(self):
+ # There's an environment variable for the data_file.
+ self.make_file(".coveragerc", """\
+ [run]
+ timid = True
+ data_file = weirdo.file
+ """)
+ self.set_environ("COVERAGE_FILE", "fromenv.dat")
+ cov = coverage.coverage()
+ self.assertEqual(cov.config.data_file, "fromenv.dat")
+ # But the constructor args override the env var.
+ cov = coverage.coverage(data_file="fromarg.dat")
+ self.assertEqual(cov.config.data_file, "fromarg.dat")
+
+
+class ConfigFileTest(CoverageTest):
+ """Tests of the config file settings in particular."""
+
+ def test_config_file_settings(self):
+ # This sample file tries to use lots of variation of syntax...
+ self.make_file(".coveragerc", """\
+ # This is a settings file for coverage.py
+ [run]
+ timid = yes
+ data_file = something_or_other.dat
+ branch = 1
+ cover_pylib = TRUE
+ parallel = on
+ include = a/ , b/
+
+ [report]
+ ; these settings affect reporting.
+ exclude_lines =
+ if 0:
+
+ pragma:?\\s+no cover
+ another_tab
+
+ ignore_errors = TRUE
+ omit =
+ one, another, some_more,
+ yet_more
+
+ [html]
+
+ directory = c:\\tricky\\dir.somewhere
+
+ [xml]
+ output=mycov.xml
+
+ """)
+ cov = coverage.coverage()
+
+ self.assertTrue(cov.config.timid)
+ self.assertEqual(cov.config.data_file, "something_or_other.dat")
+ self.assertTrue(cov.config.branch)
+ self.assertTrue(cov.config.cover_pylib)
+ self.assertTrue(cov.config.parallel)
+
+ self.assertEqual(cov.get_exclude_list(),
+ ["if 0:", "pragma:?\s+no cover", "another_tab"]
+ )
+ self.assertTrue(cov.config.ignore_errors)
+ self.assertEqual(cov.config.include_prefixes, ["a/", "b/"])
+ self.assertEqual(cov.config.omit_prefixes,
+ ["one", "another", "some_more", "yet_more"]
+ )
+
+ self.assertEqual(cov.config.html_dir, r"c:\tricky\dir.somewhere")
+
+ self.assertEqual(cov.config.xml_output, "mycov.xml")
diff --git a/test/test_coverage.py b/test/test_coverage.py
index 093065f8..27bfffca 100644
--- a/test/test_coverage.py
+++ b/test/test_coverage.py
@@ -1,30 +1,111 @@
"""Tests for Coverage."""
-# Copyright 2004-2009, Ned Batchelder
# http://nedbatchelder.com/code/coverage
-import os, sys, unittest
+import os, sys
import coverage
coverage.use_cache(0)
+from coverage.misc import CoverageException
+
sys.path.insert(0, os.path.split(__file__)[0]) # Force relative import for Py3k
from coveragetest import CoverageTest
+class TestCoverageTest(CoverageTest):
+ """Make sure our complex self.check_coverage method works."""
+
+ def test_successful_coverage(self):
+ # The simplest run possible.
+ self.check_coverage("""\
+ a = 1
+ b = 2
+ """,
+ [1,2]
+ )
+ # You can provide a list of possible statement matches.
+ self.check_coverage("""\
+ a = 1
+ b = 2
+ """,
+ ([100], [1,2], [1723,47]),
+ )
+ # You can specify missing lines.
+ self.check_coverage("""\
+ a = 1
+ if a == 2:
+ a = 3
+ """,
+ [1,2,3],
+ missing="3",
+ )
+ # You can specify a list of possible missing lines.
+ self.check_coverage("""\
+ a = 1
+ if a == 2:
+ a = 3
+ """,
+ [1,2,3],
+ missing=("47-49", "3", "100,102")
+ )
+
+ def test_failed_coverage(self):
+ # If the lines are wrong, the message shows right and wrong.
+ self.assertRaisesRegexp(AssertionError,
+ r"\[1, 2] != \[1]",
+ self.check_coverage, """\
+ a = 1
+ b = 2
+ """,
+ [1]
+ )
+ # If the list of lines possibilities is wrong, the msg shows right.
+ self.assertRaisesRegexp(AssertionError,
+ r"None of the lines choices matched \[1, 2]",
+ self.check_coverage, """\
+ a = 1
+ b = 2
+ """,
+ ([1], [2])
+ )
+ # If the missing lines are wrong, the message shows right and wrong.
+ self.assertRaisesRegexp(AssertionError,
+ r"'3' != '37'",
+ self.check_coverage, """\
+ a = 1
+ if a == 2:
+ a = 3
+ """,
+ [1,2,3],
+ missing="37",
+ )
+ # If the missing lines possibilities are wrong, the msg shows right.
+ self.assertRaisesRegexp(AssertionError,
+ r"None of the missing choices matched '3'",
+ self.check_coverage, """\
+ a = 1
+ if a == 2:
+ a = 3
+ """,
+ [1,2,3],
+ missing=("37", "4-10"),
+ )
+
+
class BasicCoverageTest(CoverageTest):
"""The simplest tests, for quick smoke testing of fundamental changes."""
-
+
def testSimple(self):
self.check_coverage("""\
a = 1
b = 2
-
+
c = 4
# Nothing here
d = 6
""",
- [1,2,4,6], report="4 4 100%")
-
+ [1,2,4,6], report="4 0 100%")
+
def testIndentationWackiness(self):
# Partial final lines are OK.
self.check_coverage("""\
@@ -55,11 +136,11 @@ class BasicCoverageTest(CoverageTest):
assert l == [12, 14, 16, 18]
""",
[1,5], "")
-
+
class SimpleStatementTest(CoverageTest):
"""Testing simple single-line statements."""
-
+
def testExpression(self):
self.check_coverage("""\
1 + 2
@@ -71,7 +152,7 @@ class SimpleStatementTest(CoverageTest):
def testAssert(self):
self.check_coverage("""\
assert (1 + 2)
- assert (1 +
+ assert (1 +
2)
assert (1 + 2), 'the universe is broken'
assert (1 +
@@ -98,7 +179,7 @@ class SimpleStatementTest(CoverageTest):
assert a == 7 and b == 8 and c == 9
""",
[1,2,3], "")
-
+
def testAttributeAssignment(self):
# Attribute assignment
self.check_coverage("""\
@@ -111,7 +192,7 @@ class SimpleStatementTest(CoverageTest):
1
""",
[1,2,3,4,6], "")
-
+
def testListofAttributeAssignment(self):
self.check_coverage("""\
class obj: pass
@@ -125,7 +206,7 @@ class SimpleStatementTest(CoverageTest):
2
""",
[1,2,3,4,7], "")
-
+
def testAugmentedAssignment(self):
self.check_coverage("""\
a = 1
@@ -151,7 +232,7 @@ class SimpleStatementTest(CoverageTest):
'''
c = len('''
long expression
- ''' +
+ ''' +
'''
on many
lines.
@@ -195,7 +276,7 @@ class SimpleStatementTest(CoverageTest):
Foo().foo()
""",
([1,2,4,5], [1,2,5]), "")
-
+
def testDel(self):
self.check_coverage("""\
d = { 'a': 1, 'b': 1, 'c': 1, 'd': 1, 'e': 1 }
@@ -210,7 +291,7 @@ class SimpleStatementTest(CoverageTest):
""",
[1,2,3,6,9], "")
- if sys.hexversion < 0x03000000: # Print statement is gone in Py3k.
+ if sys.version_info < (3, 0): # Print statement is gone in Py3k.
def testPrint(self):
self.check_coverage("""\
print "hello, world!"
@@ -223,7 +304,7 @@ class SimpleStatementTest(CoverageTest):
print "goodbye",
""",
[1,2,4,5,6,8], "")
-
+
def testRaise(self):
self.check_coverage("""\
try:
@@ -251,7 +332,7 @@ class SimpleStatementTest(CoverageTest):
return (
a +
1)
-
+
x = fn()
assert(x == 2)
""",
@@ -262,7 +343,7 @@ class SimpleStatementTest(CoverageTest):
return (a,
a + 1,
a + 2)
-
+
x,y,z = fn()
assert x == 1 and y == 2 and z == 3
""",
@@ -282,7 +363,7 @@ class SimpleStatementTest(CoverageTest):
assert a == 1 and b == 9 and c == (1,2)
""",
[1,2,3,4,7,9,10], "")
-
+
def testBreak(self):
self.check_coverage("""\
for x in range(10):
@@ -292,7 +373,7 @@ class SimpleStatementTest(CoverageTest):
assert a == 2
""",
[1,2,3,4,5], "4")
-
+
def testContinue(self):
self.check_coverage("""\
for x in range(10):
@@ -302,7 +383,7 @@ class SimpleStatementTest(CoverageTest):
assert a == 11
""",
[1,2,3,4,5], "4")
-
+
if 0:
# Peephole optimization of jumps to jumps can mean that some statements
# never hit the line tracer. The behavior is different in different
@@ -319,7 +400,7 @@ class SimpleStatementTest(CoverageTest):
b += 1
c += 1
assert a == 50 and b == 50 and c == 50
-
+
a = b = c = 0
for n in range(100):
if n % 2:
@@ -332,7 +413,7 @@ class SimpleStatementTest(CoverageTest):
assert a == 33 and b == 50 and c == 50
""",
[1,2,3,4,5,6,8,9,10, 12,13,14,15,16,17,19,20,21], "")
-
+
def testImport(self):
self.check_coverage("""\
import string
@@ -379,7 +460,7 @@ class SimpleStatementTest(CoverageTest):
assert len(path) > 0
""",
[1,3], "")
-
+
def testGlobal(self):
self.check_coverage("""\
g = h = i = 1
@@ -401,7 +482,7 @@ class SimpleStatementTest(CoverageTest):
""",
[1,2,3,4,5], "")
- if sys.hexversion < 0x03000000:
+ if sys.version_info < (3, 0):
# In Python 2.x, exec is a statement.
def testExec(self):
self.check_coverage("""\
@@ -486,24 +567,24 @@ class SimpleStatementTest(CoverageTest):
class CompoundStatementTest(CoverageTest):
"""Testing coverage of multi-line compound statements."""
-
+
def testStatementList(self):
self.check_coverage("""\
a = 1;
b = 2; c = 3
d = 4; e = 5;
-
+
assert (a,b,c,d,e) == (1,2,3,4,5)
""",
[1,2,3,5], "")
-
+
def testIf(self):
self.check_coverage("""\
a = 1
if a == 1:
x = 3
assert x == 3
- if (a ==
+ if (a ==
1):
x = 7
assert x == 7
@@ -539,7 +620,7 @@ class CompoundStatementTest(CoverageTest):
assert x == 4
""",
[1,2,3,4,6,8,9], "6-8")
-
+
def testElif(self):
self.check_coverage("""\
a = 1; b = 2; c = 3;
@@ -551,7 +632,7 @@ class CompoundStatementTest(CoverageTest):
z = 7
assert x == 3
""",
- [1,2,3,4,5,7,8], "4-7", report="7 4 57% 4-7")
+ [1,2,3,4,5,7,8], "4-7", report="7 3 57% 4-7")
self.check_coverage("""\
a = 1; b = 2; c = 3;
if a != 1:
@@ -562,7 +643,7 @@ class CompoundStatementTest(CoverageTest):
z = 7
assert y == 5
""",
- [1,2,3,4,5,7,8], "3, 7", report="7 5 71% 3, 7")
+ [1,2,3,4,5,7,8], "3, 7", report="7 2 71% 3, 7")
self.check_coverage("""\
a = 1; b = 2; c = 3;
if a != 1:
@@ -573,7 +654,7 @@ class CompoundStatementTest(CoverageTest):
z = 7
assert z == 7
""",
- [1,2,3,4,5,7,8], "3, 5", report="7 5 71% 3, 5")
+ [1,2,3,4,5,7,8], "3, 5", report="7 2 71% 3, 5")
def testElifNoElse(self):
self.check_coverage("""\
@@ -584,7 +665,7 @@ class CompoundStatementTest(CoverageTest):
y = 5
assert x == 3
""",
- [1,2,3,4,5,6], "4-5", report="6 4 66% 4-5")
+ [1,2,3,4,5,6], "4-5", report="6 2 66% 4-5")
self.check_coverage("""\
a = 1; b = 2; c = 3;
if a != 1:
@@ -593,7 +674,7 @@ class CompoundStatementTest(CoverageTest):
y = 5
assert y == 5
""",
- [1,2,3,4,5,6], "3", report="6 5 83% 3")
+ [1,2,3,4,5,6], "3", report="6 1 83% 3")
def testElifBizarre(self):
self.check_coverage("""\
@@ -653,7 +734,7 @@ class CompoundStatementTest(CoverageTest):
assert z == 7
""",
[1,2,4,5,7,9,10], "4, 7")
-
+
def testPathologicalSplitIf(self):
self.check_coverage("""\
a = 1; b = 2; c = 3;
@@ -700,7 +781,7 @@ class CompoundStatementTest(CoverageTest):
assert z == 7
""",
[1,2,5,6,9,11,12], "5, 9")
-
+
def testAbsurdSplitIf(self):
self.check_coverage("""\
a = 1; b = 2; c = 3;
@@ -786,7 +867,7 @@ class CompoundStatementTest(CoverageTest):
assert a == 2 and b == 1
""",
[1,2,3,4,5,6,8,9], "6-8")
-
+
def testSplitWhile(self):
self.check_coverage("""\
a = 3; b = 0
@@ -834,7 +915,7 @@ class CompoundStatementTest(CoverageTest):
assert a == 1
""",
[1,2,3,4,5,6], "5")
-
+
def testForElse(self):
self.check_coverage("""\
a = 0
@@ -856,7 +937,7 @@ class CompoundStatementTest(CoverageTest):
assert a == 1
""",
[1,2,3,4,5,7,8], "5-7")
-
+
def testSplitFor(self):
self.check_coverage("""\
a = 0
@@ -876,7 +957,7 @@ class CompoundStatementTest(CoverageTest):
assert a == 15
""",
[1,2,6,7], "")
-
+
def testTryExcept(self):
self.check_coverage("""\
a = 0
@@ -946,7 +1027,7 @@ class CompoundStatementTest(CoverageTest):
assert a == 99
""",
[1,2,3,4,5,6,8,9], "8")
-
+
def testTryFinally(self):
self.check_coverage("""\
a = 0
@@ -978,7 +1059,7 @@ class CompoundStatementTest(CoverageTest):
''' docstring
'''
return 1
-
+
a = foo()
assert a == 1
""",
@@ -991,7 +1072,7 @@ class CompoundStatementTest(CoverageTest):
''' docstring
'''
return a+b
-
+
x = foo(17, 23)
assert x == 40
""",
@@ -1007,7 +1088,7 @@ class CompoundStatementTest(CoverageTest):
''' docstring
'''
return a+b
-
+
x = foo()
assert x == 22
""",
@@ -1023,19 +1104,31 @@ class CompoundStatementTest(CoverageTest):
def __init__(self):
''' Another docstring. '''
self.a = 1
-
+
def foo(self):
return self.a
-
+
x = theClass().foo()
assert x == 1
""",
- [2,6,8,10,11,13,14], "")
+ [2,6,8,10,11,13,14], "")
class ExcludeTest(CoverageTest):
"""Tests of the exclusion feature to mark lines as not covered."""
-
+
+ def testDefault(self):
+ # A number of forms of pragma comment are accepted.
+ self.check_coverage("""\
+ a = 1
+ b = 2 # pragma: no cover
+ c = 3
+ d = 4 #pragma NOCOVER
+ e = 5
+ """,
+ [1,3,5]
+ )
+
def testSimple(self):
self.check_coverage("""\
a = 1; b = 2
@@ -1056,7 +1149,7 @@ class ExcludeTest(CoverageTest):
assert a == 1 and b == 2
""",
[1,3,5,7], "5", ['-cc', '-xx'])
-
+
def testExcludingIfSuite(self):
self.check_coverage("""\
a = 1; b = 2
@@ -1083,7 +1176,7 @@ class ExcludeTest(CoverageTest):
assert a == 8 and b == 9
""",
[1,8,9,10], "", ['if 0:'])
-
+
def testExcludingElseSuite(self):
self.check_coverage("""\
a = 1; b = 2
@@ -1105,14 +1198,14 @@ class ExcludeTest(CoverageTest):
a = 4
b = 5
c = 6
-
+
# Lots of comments to confuse the else handler.
# more.
-
+
else: #pragma: NO COVER
# Comments here too.
-
+
a = 8
b = 9
assert a == 4 and b == 5 and c == 6
@@ -1130,7 +1223,7 @@ class ExcludeTest(CoverageTest):
elif 1==0: #pragma: NO COVER
a = 8
b = 9
- else:
+ else:
a = 11
b = 12
assert a == 4 and b == 5 and c == 6
@@ -1143,7 +1236,7 @@ class ExcludeTest(CoverageTest):
a = 2
if 0: x = 3 # no cover
b = 4
-
+
foo()
""",
[1,2,4,6], "", ["no cover"])
@@ -1154,11 +1247,11 @@ class ExcludeTest(CoverageTest):
l = list(range(10))
a = l[:3] # no cover
b = 4
-
+
foo()
""",
[1,2,4,6], "", ["no cover"])
-
+
def testExcludingForSuite(self):
self.check_coverage("""\
a = 0
@@ -1186,7 +1279,7 @@ class ExcludeTest(CoverageTest):
assert a == 1
""",
[1,7], "", ['#pragma: NO COVER'])
-
+
def testExcludingForElse(self):
self.check_coverage("""\
a = 0
@@ -1199,7 +1292,7 @@ class ExcludeTest(CoverageTest):
assert a == 1
""",
[1,2,3,4,5,8], "5", ['#pragma: NO COVER'])
-
+
def testExcludingWhile(self):
self.check_coverage("""\
a = 3; b = 0
@@ -1290,7 +1383,7 @@ class ExcludeTest(CoverageTest):
assert a == 99
""",
[1,2,3,4,5,6,9], "", ['#pragma: NO COVER'])
-
+
def testExcludingTryExceptPass(self):
self.check_coverage("""\
a = 0
@@ -1336,7 +1429,7 @@ class ExcludeTest(CoverageTest):
assert a == 99
""",
[1,2,3,4,5,6,9], "", ['#pragma: NO COVER'])
-
+
def testExcludingIfPass(self):
# From a comment on the coverage page by Michael McNeil Forbes:
self.check_coverage("""\
@@ -1345,18 +1438,18 @@ class ExcludeTest(CoverageTest):
pass # This line still reported as missing
if False: # pragma: no cover
x = 1 # Now it is skipped.
-
+
f()
""",
[1,7], "", ["no cover"])
-
+
def testExcludingFunction(self):
self.check_coverage("""\
def fn(foo): #pragma: NO COVER
a = 1
b = 2
c = 3
-
+
x = 1
assert x == 1
""",
@@ -1367,71 +1460,47 @@ class ExcludeTest(CoverageTest):
class Fooey:
def __init__(self):
self.a = 1
-
+
def foo(self): #pragma: NO COVER
return self.a
-
+
x = Fooey()
assert x.a == 1
""",
[1,2,3,8,9], "", ['#pragma: NO COVER'])
-
+
def testExcludingClass(self):
self.check_coverage("""\
class Fooey: #pragma: NO COVER
def __init__(self):
self.a = 1
-
+
def foo(self):
return self.a
-
+
x = 1
assert x == 1
""",
[8,9], "", ['#pragma: NO COVER'])
-class ThreadingTest(CoverageTest):
- """Tests of the threading support."""
-
- def testThreading(self):
- self.check_coverage("""\
- import time, threading
-
- def fromMainThread():
- return "called from main thread"
-
- def fromOtherThread():
- return "called from other thread"
-
- def neverCalled():
- return "no one calls me"
-
- other = threading.Thread(target=fromOtherThread)
- other.start()
- fromMainThread()
- other.join()
- """,
- [1,3,4,6,7,9,10,12,13,14,15], "10")
-
-
-if sys.hexversion >= 0x020400f0:
+if sys.version_info >= (2, 4):
class Py24Test(CoverageTest):
"""Tests of new syntax in Python 2.4."""
-
+
def testFunctionDecorators(self):
self.check_coverage("""\
def require_int(func):
def wrapper(arg):
assert isinstance(arg, int)
return func(arg)
-
+
return wrapper
-
+
@require_int
def p1(arg):
return arg*2
-
+
assert p1(10) == 20
""",
[1,2,3,4,6,8,10,12], "")
@@ -1444,11 +1513,11 @@ if sys.hexversion >= 0x020400f0:
return extra*func(arg)
return wrapper
return decorator
-
+
@boost_by(10)
def boosted(arg):
return arg*2
-
+
assert boosted(10) == 200
""",
[1,2,3,4,5,6,8,10,12], "")
@@ -1467,45 +1536,45 @@ if sys.hexversion >= 0x020400f0:
return extra*func(arg)
return wrapper
return decorator
-
+
@require_int
@boost_by(10)
def boosted1(arg):
return arg*2
-
+
assert boosted1(10) == 200
@boost_by(10)
@require_int
def boosted2(arg):
return arg*2
-
+
assert boosted2(10) == 200
""",
([1,2,3,4,5,7,8,9,10,11,12,14,15,17,19,21,22,24,26],
[1,2,3,4,5,7,8,9,10,11,12,14, 17,19,21, 24,26]), "")
-if sys.hexversion >= 0x020500f0:
+if sys.version_info >= (2, 5):
class Py25Test(CoverageTest):
"""Tests of new syntax in Python 2.5."""
def testWithStatement(self):
self.check_coverage("""\
from __future__ import with_statement
-
+
class Managed:
def __enter__(self):
desc = "enter"
-
+
def __exit__(self, type, value, tb):
desc = "exit"
-
+
m = Managed()
with m:
desc = "block1a"
desc = "block1b"
-
+
try:
with m:
desc = "block2"
@@ -1514,7 +1583,7 @@ if sys.hexversion >= 0x020500f0:
desc = "caught"
""",
[1,3,4,5,7,8,10,11,12,13,15,16,17,18,19,20], "")
-
+
def testTryExceptFinally(self):
self.check_coverage("""\
a = 0; b = 0
@@ -1596,7 +1665,7 @@ if sys.hexversion >= 0x020500f0:
assert a == 99 and b == 2
""",
[1,2,3,4,5,6,8,10,11], "8")
-
+
class ModuleTest(CoverageTest):
"""Tests for the module-level behavior of the `coverage` module."""
@@ -1607,287 +1676,29 @@ class ModuleTest(CoverageTest):
coverage.coverage()
-class ProcessTest(CoverageTest):
- """Tests of the per-process behavior of coverage.py."""
-
- def testSaveOnExit(self):
- self.make_file("mycode.py", """\
- h = "Hello"
- w = "world"
- """)
-
- self.assert_(not os.path.exists(".coverage"))
- self.run_command("coverage -x mycode.py")
- self.assert_(os.path.exists(".coverage"))
-
- def testEnvironment(self):
- # Checks that we can import modules from the test directory at all!
- self.make_file("mycode.py", """\
- import covmod1
- import covmodzip1
- a = 1
- print ('done')
- """)
-
- self.assert_(not os.path.exists(".coverage"))
- out = self.run_command("coverage -x mycode.py")
- self.assert_(os.path.exists(".coverage"))
- self.assertEqual(out, 'done\n')
-
- def testCombineParallelData(self):
- self.make_file("b_or_c.py", """\
- import sys
- a = 1
- if sys.argv[1] == 'b':
- b = 1
- else:
- c = 1
- d = 1
- print ('done')
- """)
-
- out = self.run_command("coverage -x -p b_or_c.py b")
- self.assertEqual(out, 'done\n')
- self.assert_(not os.path.exists(".coverage"))
-
- out = self.run_command("coverage -x -p b_or_c.py c")
- self.assertEqual(out, 'done\n')
- self.assert_(not os.path.exists(".coverage"))
-
- # After two -p runs, there should be two .coverage.machine.123 files.
- self.assertEqual(
- len([f for f in os.listdir('.') if f.startswith('.coverage.')]),
- 2)
-
- # Combine the parallel coverage data files into .coverage .
- self.run_command("coverage -c")
- self.assert_(os.path.exists(".coverage"))
-
- # Read the coverage file and see that b_or_c.py has all 7 lines
- # executed.
- data = coverage.CoverageData()
- data.read_file(".coverage")
- self.assertEqual(data.summary()['b_or_c.py'], 7)
-
- def test_missing_source_file(self):
- # Check what happens if the source is missing when reporting happens.
- self.make_file("fleeting.py", """\
- s = 'goodbye, cruel world!'
- """)
-
- self.run_command("coverage run fleeting.py")
- os.remove("fleeting.py")
- out = self.run_command("coverage html -d htmlcov")
- self.assert_matches(out, "No source for code: '.*fleeting.py'")
- self.assert_("Traceback" not in out)
-
- # It happens that the code paths are different for *.py and other
- # files, so try again with no extension.
- self.make_file("fleeting", """\
- s = 'goodbye, cruel world!'
- """)
-
- self.run_command("coverage run fleeting")
- os.remove("fleeting")
- out = self.run_command("coverage html -d htmlcov")
- self.assert_matches(out, "No source for code: '.*fleeting'")
- self.assert_("Traceback" not in out)
-
- def test_running_missing_file(self):
- out = self.run_command("coverage run xyzzy.py")
- self.assert_matches(out, "No file to run: .*xyzzy.py")
- self.assert_("Traceback" not in out)
-
-
-class RecursionTest(CoverageTest):
- """Check what happens when recursive code gets near limits."""
-
- def testShortRecursion(self):
- # We can definitely get close to 500 stack frames.
- self.check_coverage("""\
- def recur(n):
- if n == 0:
- return 0
- else:
- return recur(n-1)+1
-
- recur(495) # We can get at least this many stack frames.
- """,
- [1,2,3,5,7], "")
-
- def testLongRecursion(self):
- # We can't finish a very deep recursion, but we don't crash.
- self.assertRaises(RuntimeError, self.check_coverage,
- """\
- def recur(n):
- if n == 0:
- return 0
- else:
- return recur(n-1)+1
-
- recur(100000) # This is definitely too many frames.
- """,
- [1,2,3,5,7], "")
-
-
-class PyexpatTest(CoverageTest):
- """Pyexpat screws up tracing. Make sure we've counter-defended properly."""
-
- def testPyexpat(self):
- # pyexpat calls the trace function explicitly (inexplicably), and does
- # it wrong for exceptions. Parsing a DOCTYPE for some reason throws
- # an exception internally, and triggers its wrong behavior. This test
- # checks that our fake PyTrace_RETURN hack in tracer.c works. It will
- # also detect if the pyexpat bug is fixed unbeknownst to us, meaning
- # we'd see two RETURNs where there should only be one.
-
- self.make_file("trydom.py", """\
- import xml.dom.minidom
-
- XML = '''\\
- <!DOCTYPE fooey SYSTEM "http://www.example.com/example.dtd">
- <root><child/><child/></root>
- '''
-
- def foo():
- dom = xml.dom.minidom.parseString(XML)
- assert len(dom.getElementsByTagName('child')) == 2
- a = 11
-
- foo()
- """)
-
- self.make_file("outer.py", "\n"*100 + "import trydom\na = 102\n")
-
- cov = coverage.coverage()
- cov.erase()
-
- # Import the python file, executing it.
- cov.start()
- self.import_module("outer")
- cov.stop()
-
- _, statements, missing, _ = cov.analysis("trydom.py")
- self.assertEqual(statements, [1,3,8,9,10,11,13])
- self.assertEqual(missing, [])
-
- _, statements, missing, _ = cov.analysis("outer.py")
- self.assertEqual(statements, [101,102])
- self.assertEqual(missing, [])
-
-
-class ExceptionTest(CoverageTest):
- """I suspect different versions of Python deal with exceptions differently
- in the trace function.
- """
-
- def testException(self):
- # Python 2.3's trace function doesn't get called with "return" if the
- # scope is exiting due to an exception. This confounds our trace
- # function which relies on scope announcements to track which files to
- # trace.
- #
- # This test is designed to sniff this out. Each function in the call
- # stack is in a different file, to try to trip up the tracer. Each
- # file has active lines in a different range so we'll see if the lines
- # get attributed to the wrong file.
-
- self.make_file("oops.py", """\
- def oops(args):
- a = 2
- raise Exception("oops")
- a = 4
- """)
-
- self.make_file("fly.py", "\n"*100 + """\
- def fly(calls):
- a = 2
- calls[0](calls[1:])
- a = 4
- """)
-
- self.make_file("catch.py", "\n"*200 + """\
- def catch(calls):
- try:
- a = 3
- calls[0](calls[1:])
- a = 5
- except:
- a = 7
- """)
-
- self.make_file("doit.py", "\n"*300 + """\
- def doit(calls):
- try:
- calls[0](calls[1:])
- except:
- a = 5
- """)
-
- # Import all the modules before starting coverage, so the def lines
- # won't be in all the results.
- for mod in "oops fly catch doit".split():
- self.import_module(mod)
-
- # Each run nests the functions differently to get different
- # combinations of catching exceptions and letting them fly.
- runs = [
- ("doit fly oops", {
- 'doit.py': [302,303,304,305],
- 'fly.py': [102,103],
- 'oops.py': [2,3],
- }),
- ("doit catch oops", {
- 'doit.py': [302,303],
- 'catch.py': [202,203,204,206,207],
- 'oops.py': [2,3],
- }),
- ("doit fly catch oops", {
- 'doit.py': [302,303],
- 'fly.py': [102,103,104],
- 'catch.py': [202,203,204,206,207],
- 'oops.py': [2,3],
- }),
- ("doit catch fly oops", {
- 'doit.py': [302,303],
- 'catch.py': [202,203,204,206,207],
- 'fly.py': [102,103],
- 'oops.py': [2,3],
- }),
- ]
-
- for callnames, lines_expected in runs:
-
- # Make the list of functions we'll call for this test.
- calls = [getattr(sys.modules[cn], cn) for cn in callnames.split()]
-
- cov = coverage.coverage()
- cov.start()
- # Call our list of functions: invoke the first, with the rest as
- # an argument.
- calls[0](calls[1:])
- cov.stop()
-
- # Clean the line data and compare to expected results.
- # The filenames are absolute, so keep just the base.
- lines = cov.data.line_data()
- clean_lines = {}
- for f, llist in lines.items():
- if f == __file__:
- # ignore this file.
- continue
- clean_lines[os.path.basename(f)] = llist
- self.assertEqual(clean_lines, lines_expected)
-
-
-if __name__ == '__main__':
- print("Testing under Python version: %s" % sys.version)
- unittest.main()
-
-
-# TODO: split "and" conditions across lines, and detect not running lines.
-# (Can't be done: trace function doesn't get called for each line
-# in an expression!)
-# TODO: Generator comprehensions?
-# TODO: Constant if tests ("if 1:"). Py 2.4 doesn't execute them.
-# TODO: There are no tests for analysis2 directly.
+class ReportingTest(CoverageTest):
+ """Tests of some reporting behavior."""
+
+ def test_no_data_to_report_on_annotate(self):
+ # Reporting with no data produces a nice message and no output dir.
+ self.assertRaisesRegexp(
+ CoverageException, "No data to report.",
+ self.command_line, "annotate -d ann"
+ )
+ self.assertFalse(os.path.exists("ann"))
+
+ def test_no_data_to_report_on_html(self):
+ # Reporting with no data produces a nice message and no output dir.
+ self.assertRaisesRegexp(
+ CoverageException, "No data to report.",
+ self.command_line, "html -d htmlcov"
+ )
+ self.assertFalse(os.path.exists("htmlcov"))
+
+ def test_no_data_to_report_on_xml(self):
+ # Reporting with no data produces a nice message.
+ self.assertRaisesRegexp(
+ CoverageException, "No data to report.",
+ self.command_line, "xml"
+ )
+ # Currently, this leaves an empty coverage.xml file... :(
diff --git a/test/test_data.py b/test/test_data.py
index 640f4f07..83a5b8ae 100644
--- a/test/test_data.py
+++ b/test/test_data.py
@@ -29,11 +29,11 @@ class DataTest(CoverageTest):
def assert_summary(self, covdata, summary):
"""Check that the summary of `covdata` is `summary`."""
self.assertEqual(covdata.summary(), summary)
-
+
def assert_executed_files(self, covdata, execed):
"""Check that `covdata`'s executed files are `execed`."""
- self.assert_equal_sets(covdata.executed_files(), execed)
-
+ self.assertSameElements(covdata.executed_files(), execed)
+
def test_reading_empty(self):
covdata = CoverageData()
covdata.read()
@@ -44,25 +44,25 @@ class DataTest(CoverageTest):
covdata.add_line_data(DATA_1)
self.assert_summary(covdata, SUMMARY_1)
self.assert_executed_files(covdata, EXECED_FILES_1)
-
+
def test_writing_and_reading(self):
covdata1 = CoverageData()
covdata1.add_line_data(DATA_1)
covdata1.write()
-
+
covdata2 = CoverageData()
covdata2.read()
self.assert_summary(covdata2, SUMMARY_1)
def test_combining(self):
- covdata1 = CoverageData(suffix='1')
+ covdata1 = CoverageData()
covdata1.add_line_data(DATA_1)
- covdata1.write()
-
- covdata2 = CoverageData(suffix='2')
+ covdata1.write(suffix='1')
+
+ covdata2 = CoverageData()
covdata2.add_line_data(DATA_2)
- covdata2.write()
-
+ covdata2.write(suffix='2')
+
covdata3 = CoverageData()
covdata3.combine_parallel_data()
self.assert_summary(covdata3, SUMMARY_1_2)
@@ -74,7 +74,7 @@ class DataTest(CoverageTest):
covdata1.write()
covdata1.erase()
self.assert_summary(covdata1, {})
-
+
covdata2 = CoverageData()
covdata2.read()
self.assert_summary(covdata2, {})
@@ -84,17 +84,17 @@ class DataTest(CoverageTest):
covdata = CoverageData()
covdata.add_line_data(DATA_1)
covdata.write()
-
+
fdata = open(".coverage", 'rb')
try:
data = pickle.load(fdata)
finally:
fdata.close()
-
+
lines = data['lines']
- self.assert_equal_sets(lines.keys(), EXECED_FILES_1)
- self.assert_equal_sets(lines['a.py'], A_PY_LINES_1)
- self.assert_equal_sets(lines['b.py'], B_PY_LINES_1)
+ self.assertSameElements(lines.keys(), EXECED_FILES_1)
+ self.assertSameElements(lines['a.py'], A_PY_LINES_1)
+ self.assertSameElements(lines['b.py'], B_PY_LINES_1)
# If not measuring branches, there's no arcs entry.
self.assertEqual(data.get('arcs', 'not there'), 'not there')
@@ -103,14 +103,14 @@ class DataTest(CoverageTest):
covdata = CoverageData()
covdata.add_arc_data(ARC_DATA_3)
covdata.write()
-
+
fdata = open(".coverage", 'rb')
try:
data = pickle.load(fdata)
finally:
fdata.close()
-
- self.assert_equal_sets(data['lines'].keys(), [])
+
+ self.assertSameElements(data['lines'].keys(), [])
arcs = data['arcs']
- self.assert_equal_sets(arcs['x.py'], X_PY_ARCS_3)
- self.assert_equal_sets(arcs['y.py'], Y_PY_ARCS_3)
+ self.assertSameElements(arcs['x.py'], X_PY_ARCS_3)
+ self.assertSameElements(arcs['y.py'], Y_PY_ARCS_3)
diff --git a/test/test_execfile.py b/test/test_execfile.py
index 5e9f4fd5..2f28a069 100644
--- a/test/test_execfile.py
+++ b/test/test_execfile.py
@@ -17,7 +17,7 @@ class RunTest(CoverageTest):
tryfile = os.path.join(here, "try_execfile.py")
run_python_file(tryfile, [tryfile, "arg1", "arg2"])
mod_globs = eval(self.stdout())
-
+
# The file should think it is __main__
self.assertEqual(mod_globs['__name__'], "__main__")
@@ -30,10 +30,10 @@ class RunTest(CoverageTest):
"Test file for run_python_file.")
self.assertEqual(mod_globs['DATA'], "xyzzy")
self.assertEqual(mod_globs['FN_VAL'], "my_fn('fooey')")
-
+
# It must be self-importable as __main__.
self.assertEqual(mod_globs['__main__.DATA'], "xyzzy")
-
+
# Argv should have the proper values.
self.assertEqual(mod_globs['argv'], [tryfile, "arg1", "arg2"])
@@ -60,5 +60,17 @@ class RunTest(CoverageTest):
run_python_file('nl.py', ['nl.py'])
self.assertEqual(self.stdout(), "Hello, world!\n"*3)
+ def test_missing_final_newline(self):
+ # Make sure we can deal with a Python file with no final newline.
+ self.make_file("abrupt.py", """\
+ if 1:
+ a = 1
+ print("a is %r" % a)
+ #""")
+ abrupt = open("abrupt.py").read()
+ self.assertEqual(abrupt[-1], '#')
+ run_python_file("abrupt.py", ["abrupt.py"])
+ self.assertEqual(self.stdout(), "a is 1\n")
+
def test_no_such_file(self):
self.assertRaises(NoSource, run_python_file, "xyzzy.py", [])
diff --git a/test/test_farm.py b/test/test_farm.py
index bc1d7a30..79b345a6 100644
--- a/test/test_farm.py
+++ b/test/test_farm.py
@@ -3,7 +3,7 @@
import difflib, filecmp, fnmatch, glob, os, re, shutil, sys
sys.path.insert(0, os.path.split(__file__)[0]) # Force relative import for Py3k
-from backtest import run_command, execfile # pylint: disable-msg=W0622
+from backtest import run_command, execfile # pylint: disable-msg=W0622
def test_farm(clean_only=False):
@@ -15,9 +15,9 @@ def test_farm(clean_only=False):
class FarmTestCase(object):
"""A test case from the farm tree.
-
+
Tests are short Python script files, often called run.py:
-
+
copy("src", "out")
run('''
coverage -x white.py
@@ -29,14 +29,14 @@ class FarmTestCase(object):
Verbs (copy, run, compare, clean) are methods in this class. FarmTestCase
has options to allow various uses of the test cases (normal execution,
cleaning-only, or run and leave the results for debugging).
-
+
"""
def __init__(self, runpy, clean_only=False, dont_clean=False):
"""Create a test case from a run.py file.
-
+
`clean_only` means that only the clean() action is executed.
`dont_clean` means that the clean() action is not executed.
-
+
"""
self.description = runpy
self.dir, self.runpy = os.path.split(runpy)
@@ -54,14 +54,14 @@ class FarmTestCase(object):
oldpath = sys.path[:]
sys.path.insert(0, directory)
return oldpath
-
+
def restorepath(self, path):
"""Restore the system path to `path`."""
sys.path = path
def __call__(self):
"""Execute the test from the run.py file.
-
+
"""
cwd = self.cd(self.dir)
@@ -74,13 +74,18 @@ class FarmTestCase(object):
glo = dict([(fn, getattr(self, fn)) for fn in fns])
if self.dont_clean:
glo['clean'] = self.noop
-
+
+ old_mods = dict(sys.modules)
try:
execfile(self.runpy, glo)
finally:
self.cd(cwd)
+ # Remove any new modules imported during the test run. This lets us
+ # import the same source files for more than one test.
+ for m in [m for m in sys.modules if m not in old_mods]:
+ del sys.modules[m]
- def run_fully(self):
+ def run_fully(self): # pragma: no cover
"""Run as a full test case, with setUp and tearDown."""
self.setUp()
try:
@@ -88,16 +93,16 @@ class FarmTestCase(object):
finally:
self.tearDown()
- def fnmatch_list(self, files, filepattern):
- """Filter the list of `files` to only those that match `filepattern`.
-
- If `filepattern` is None, then return the entire list of files.
-
+ def fnmatch_list(self, files, file_pattern):
+ """Filter the list of `files` to only those that match `file_pattern`.
+
+ If `file_pattern` is None, then return the entire list of files.
+
Returns a list of the filtered files.
-
+
"""
- if filepattern:
- files = [f for f in files if fnmatch.fnmatch(f, filepattern)]
+ if file_pattern:
+ files = [f for f in files if fnmatch.fnmatch(f, file_pattern)]
return files
def setUp(self):
@@ -106,7 +111,7 @@ class FarmTestCase(object):
# Modules should be importable from the current directory.
self.old_syspath = sys.path[:]
sys.path.insert(0, '')
-
+
def tearDown(self):
"""Test tear down, run by nose after __call__."""
# Make sure no matter what, the test is cleaned up.
@@ -118,11 +123,11 @@ class FarmTestCase(object):
sys.path = self.old_syspath
# Functions usable inside farm run.py files
-
+
def noop(self, *args, **kwargs):
"""A no-op function to stub out run, copy, etc, when only cleaning."""
pass
-
+
def copy(self, src, dst):
"""Copy a directory."""
@@ -132,11 +137,11 @@ class FarmTestCase(object):
def run(self, cmds, rundir="src", outfile=None):
"""Run a list of commands.
-
+
`cmds` is a string, commands separated by newlines.
`rundir` is the directory in which to run the commands.
`outfile` is a filename to redirect stdout to.
-
+
"""
cwd = self.cd(rundir)
try:
@@ -155,12 +160,12 @@ class FarmTestCase(object):
def runfunc(self, fn, rundir="src", addtopath=None):
"""Run a function.
-
+
`fn` is a callable.
`rundir` is the directory in which to run the function.
-
+
"""
-
+
cwd = self.cd(rundir)
oldpath = self.addtopath(addtopath)
try:
@@ -169,32 +174,32 @@ class FarmTestCase(object):
self.cd(cwd)
self.restorepath(oldpath)
- def compare(self, dir1, dir2, filepattern=None, size_within=0,
+ def compare(self, dir1, dir2, file_pattern=None, size_within=0,
left_extra=False, right_extra=False, scrubs=None
):
- """Compare files matching `filepattern` in `dir1` and `dir2`.
-
+ """Compare files matching `file_pattern` in `dir1` and `dir2`.
+
`dir2` is interpreted as a prefix, with Python version numbers appended
to find the actual directory to compare with. "foo" will compare against
"foo_v241", "foo_v24", "foo_v2", or "foo", depending on which directory
is found first.
-
+
`size_within` is a percentage delta for the file sizes. If non-zero,
then the file contents are not compared (since they are expected to
often be different), but the file sizes must be within this amount.
For example, size_within=10 means that the two files' sizes must be
within 10 percent of each other to compare equal.
-
+
`left_extra` true means the left directory can have extra files in it
without triggering an assertion. `right_extra` means the right
directory can.
-
+
`scrubs` is a list of pairs, regex find and replace patterns to use to
scrub the files of unimportant differences.
-
+
An assertion will be raised if the directories fail one of their
matches.
-
+
"""
# Search for a dir2 with a version suffix.
version_suff = ''.join(map(str, sys.version_info[:3]))
@@ -207,12 +212,12 @@ class FarmTestCase(object):
assert os.path.exists(dir1), "Left directory missing: %s" % dir1
assert os.path.exists(dir2), "Right directory missing: %s" % dir2
-
+
dc = filecmp.dircmp(dir1, dir2)
- diff_files = self.fnmatch_list(dc.diff_files, filepattern)
- left_only = self.fnmatch_list(dc.left_only, filepattern)
- right_only = self.fnmatch_list(dc.right_only, filepattern)
-
+ diff_files = self.fnmatch_list(dc.diff_files, file_pattern)
+ left_only = self.fnmatch_list(dc.left_only, file_pattern)
+ right_only = self.fnmatch_list(dc.right_only, file_pattern)
+
if size_within:
# The files were already compared, use the diff_files list as a
# guide for size comparison.
@@ -226,7 +231,10 @@ class FarmTestCase(object):
# print "%d %d" % (big, little)
# print "Left: ---\n%s\n-----\n%s" % (left, right)
wrong_size.append(f)
- assert not wrong_size, "File sizes differ: %s" % wrong_size
+ assert not wrong_size, (
+ "File sizes differ between %s and %s: %s" % (
+ dir1, dir2, wrong_size
+ ))
else:
# filecmp only compares in binary mode, but we want text mode. So
# look through the list of different files, and compare them
@@ -250,10 +258,10 @@ class FarmTestCase(object):
def _scrub(self, strlist, scrubs):
"""Scrub uninteresting data from the strings in `strlist`.
-
+
`scrubs is a list of (find, replace) pairs of regexes that are used on
each string in `strlist`. A list of scrubbed strings is returned.
-
+
"""
scrubbed = []
for s in strlist:
@@ -264,10 +272,10 @@ class FarmTestCase(object):
def contains(self, filename, *strlist):
"""Check that the file contains all of a list of strings.
-
+
An assert will be raised if one of the arguments in `strlist` is
missing in `filename`.
-
+
"""
text = open(filename, "r").read()
for s in strlist:
@@ -275,10 +283,10 @@ class FarmTestCase(object):
def doesnt_contain(self, filename, *strlist):
"""Check that the file contains none of a list of strings.
-
+
An assert will be raised if any of the strings in strlist appears in
`filename`.
-
+
"""
text = open(filename, "r").read()
for s in strlist:
@@ -286,18 +294,32 @@ class FarmTestCase(object):
def clean(self, cleandir):
"""Clean `cleandir` by removing it and all its children completely."""
- if os.path.exists(cleandir):
- shutil.rmtree(cleandir)
+ # rmtree gives mysterious failures on Win7, so retry a "few" times.
+ # I've seen it take over 100 tries, so, 1000! This is probably the
+ # most unpleasant hack I've written in a long time...
+ tries = 1000
+ while tries:
+ if os.path.exists(cleandir):
+ try:
+ shutil.rmtree(cleandir)
+ except OSError:
+ if tries == 1:
+ raise
+ else:
+ tries -= 1
+ continue
+ break
+
-def main():
+def main(): # pragma: no cover
"""Command-line access to test_farm.
-
+
Commands:
-
+
run testcase - Run a single test case.
out testcase - Run a test case, but don't clean up, to see the output.
clean - Clean all the output for all tests.
-
+
"""
op = sys.argv[1]
if op == 'run':
@@ -314,7 +336,7 @@ def main():
test[0].run_fully()
else:
print("Need an operation: run, out, clean")
-
+
# So that we can run just one farm run.py at a time.
if __name__ == '__main__':
main()
diff --git a/test/test_files.py b/test/test_files.py
new file mode 100644
index 00000000..ca9b4e0d
--- /dev/null
+++ b/test/test_files.py
@@ -0,0 +1,35 @@
+"""Tests for files.py"""
+
+import os, sys
+
+from coverage.files import FileLocator
+
+sys.path.insert(0, os.path.split(__file__)[0]) # Force relative import for Py3k
+from coveragetest import CoverageTest
+
+
+class FileLocatorTest(CoverageTest):
+ """Tests of `FileLocator`."""
+
+ def abs_path(self, p):
+ """Return the absolute path for `p`."""
+ return os.path.join(os.getcwd(), os.path.normpath(p))
+
+ def test_simple(self):
+ self.make_file("hello.py", "#hello")
+ fl = FileLocator()
+ self.assertEqual(fl.relative_filename("hello.py"), "hello.py")
+ a = self.abs_path("hello.py")
+ self.assertNotEqual(a, "hello.py")
+ self.assertEqual(fl.relative_filename(a), "hello.py")
+
+ def test_peer_directories(self):
+ self.make_file("sub/proj1/file1.py", "file1")
+ self.make_file("sub/proj2/file2.py", "file2")
+ a1 = self.abs_path("sub/proj1/file1.py")
+ a2 = self.abs_path("sub/proj2/file2.py")
+ d = os.path.normpath("sub/proj1")
+ os.chdir(d)
+ fl = FileLocator()
+ self.assertEqual(fl.relative_filename(a1), "file1.py")
+ self.assertEqual(fl.relative_filename(a2), a2)
diff --git a/test/test_oddball.py b/test/test_oddball.py
new file mode 100644
index 00000000..7d8084ae
--- /dev/null
+++ b/test/test_oddball.py
@@ -0,0 +1,284 @@
+"""Oddball cases for testing coverage.py"""
+
+import os, sys
+import coverage
+
+sys.path.insert(0, os.path.split(__file__)[0]) # Force relative import for Py3k
+from coveragetest import CoverageTest
+import osinfo
+
+class ThreadingTest(CoverageTest):
+ """Tests of the threading support."""
+
+ def testThreading(self):
+ self.check_coverage("""\
+ import time, threading
+
+ def fromMainThread():
+ return "called from main thread"
+
+ def fromOtherThread():
+ return "called from other thread"
+
+ def neverCalled():
+ return "no one calls me"
+
+ other = threading.Thread(target=fromOtherThread)
+ other.start()
+ fromMainThread()
+ other.join()
+ """,
+ [1,3,4,6,7,9,10,12,13,14,15], "10")
+
+
+class RecursionTest(CoverageTest):
+ """Check what happens when recursive code gets near limits."""
+
+ def testShortRecursion(self):
+ # We can definitely get close to 500 stack frames.
+ self.check_coverage("""\
+ def recur(n):
+ if n == 0:
+ return 0
+ else:
+ return recur(n-1)+1
+
+ recur(495) # We can get at least this many stack frames.
+ """,
+ [1,2,3,5,7], "")
+
+ def testLongRecursion(self):
+ # We can't finish a very deep recursion, but we don't crash.
+ self.assertRaises(RuntimeError, self.check_coverage,
+ """\
+ def recur(n):
+ if n == 0:
+ return 0
+ else:
+ return recur(n-1)+1
+
+ recur(100000) # This is definitely too many frames.
+ """,
+ [1,2,3,5,7], "")
+
+
+class MemoryLeakTest(CoverageTest):
+ """Attempt the impossible: test that memory doesn't leak."""
+
+ def test_for_leaks(self):
+ lines = list(range(301, 315))
+ lines.remove(306)
+ # Ugly string mumbo jumbo to get 300 blank lines at the beginning..
+ code = """\
+ # blank line\n""" * 300 + """\
+ def once(x):
+ if x % 100 == 0:
+ raise Exception("100!")
+ elif x % 2:
+ return 10
+ else:
+ return 11
+ i = 0 # Portable loop without alloc'ing memory.
+ while i < ITERS:
+ try:
+ once(i)
+ except:
+ pass
+ i += 1
+ """
+ ram_0 = osinfo.process_ram()
+ self.check_coverage(code.replace("ITERS", "10"), lines, "")
+ ram_1 = osinfo.process_ram()
+ self.check_coverage(code.replace("ITERS", "10000"), lines, "")
+ ram_2 = osinfo.process_ram()
+ ram_growth = (ram_2 - ram_1) - (ram_1 - ram_0)
+ self.assertTrue(ram_growth < 100000, "RAM grew by %d" % (ram_growth))
+
+
+class PyexpatTest(CoverageTest):
+ """Pyexpat screws up tracing. Make sure we've counter-defended properly."""
+
+ def testPyexpat(self):
+ # pyexpat calls the trace function explicitly (inexplicably), and does
+ # it wrong for exceptions. Parsing a DOCTYPE for some reason throws
+ # an exception internally, and triggers its wrong behavior. This test
+ # checks that our fake PyTrace_RETURN hack in tracer.c works. It will
+ # also detect if the pyexpat bug is fixed unbeknownst to us, meaning
+ # we'd see two RETURNs where there should only be one.
+
+ self.make_file("trydom.py", """\
+ import xml.dom.minidom
+
+ XML = '''\\
+ <!DOCTYPE fooey SYSTEM "http://www.example.com/example.dtd">
+ <root><child/><child/></root>
+ '''
+
+ def foo():
+ dom = xml.dom.minidom.parseString(XML)
+ assert len(dom.getElementsByTagName('child')) == 2
+ a = 11
+
+ foo()
+ """)
+
+ self.make_file("outer.py", "\n"*100 + "import trydom\na = 102\n")
+
+ cov = coverage.coverage()
+ cov.erase()
+
+ # Import the python file, executing it.
+ cov.start()
+ self.import_module("outer")
+ cov.stop()
+
+ _, statements, missing, _ = cov.analysis("trydom.py")
+ self.assertEqual(statements, [1,3,8,9,10,11,13])
+ self.assertEqual(missing, [])
+
+ _, statements, missing, _ = cov.analysis("outer.py")
+ self.assertEqual(statements, [101,102])
+ self.assertEqual(missing, [])
+
+
+class ExceptionTest(CoverageTest):
+ """I suspect different versions of Python deal with exceptions differently
+ in the trace function.
+ """
+
+ def testException(self):
+ # Python 2.3's trace function doesn't get called with "return" if the
+ # scope is exiting due to an exception. This confounds our trace
+ # function which relies on scope announcements to track which files to
+ # trace.
+ #
+ # This test is designed to sniff this out. Each function in the call
+ # stack is in a different file, to try to trip up the tracer. Each
+ # file has active lines in a different range so we'll see if the lines
+ # get attributed to the wrong file.
+
+ self.make_file("oops.py", """\
+ def oops(args):
+ a = 2
+ raise Exception("oops")
+ a = 4
+ """)
+
+ self.make_file("fly.py", "\n"*100 + """\
+ def fly(calls):
+ a = 2
+ calls[0](calls[1:])
+ a = 4
+ """)
+
+ self.make_file("catch.py", "\n"*200 + """\
+ def catch(calls):
+ try:
+ a = 3
+ calls[0](calls[1:])
+ a = 5
+ except:
+ a = 7
+ """)
+
+ self.make_file("doit.py", "\n"*300 + """\
+ def doit(calls):
+ try:
+ calls[0](calls[1:])
+ except:
+ a = 5
+ """)
+
+ # Import all the modules before starting coverage, so the def lines
+ # won't be in all the results.
+ for mod in "oops fly catch doit".split():
+ self.import_module(mod)
+
+ # Each run nests the functions differently to get different
+ # combinations of catching exceptions and letting them fly.
+ runs = [
+ ("doit fly oops", {
+ 'doit.py': [302,303,304,305],
+ 'fly.py': [102,103],
+ 'oops.py': [2,3],
+ }),
+ ("doit catch oops", {
+ 'doit.py': [302,303],
+ 'catch.py': [202,203,204,206,207],
+ 'oops.py': [2,3],
+ }),
+ ("doit fly catch oops", {
+ 'doit.py': [302,303],
+ 'fly.py': [102,103,104],
+ 'catch.py': [202,203,204,206,207],
+ 'oops.py': [2,3],
+ }),
+ ("doit catch fly oops", {
+ 'doit.py': [302,303],
+ 'catch.py': [202,203,204,206,207],
+ 'fly.py': [102,103],
+ 'oops.py': [2,3],
+ }),
+ ]
+
+ for callnames, lines_expected in runs:
+
+ # Make the list of functions we'll call for this test.
+ calls = [getattr(sys.modules[cn], cn) for cn in callnames.split()]
+
+ cov = coverage.coverage()
+ cov.start()
+ # Call our list of functions: invoke the first, with the rest as
+ # an argument.
+ calls[0](calls[1:])
+ cov.stop()
+
+ # Clean the line data and compare to expected results.
+ # The filenames are absolute, so keep just the base.
+ lines = cov.data.line_data()
+ clean_lines = {}
+ for f, llist in lines.items():
+ if f == __file__:
+ # ignore this file.
+ continue
+ clean_lines[os.path.basename(f)] = llist
+ self.assertEqual(clean_lines, lines_expected)
+
+
+if sys.version_info >= (2, 5):
+ class DoctestTest(CoverageTest):
+ """Tests invoked with doctest should measure properly."""
+
+ def setUp(self):
+ super(DoctestTest, self).setUp()
+
+ # Oh, the irony! This test case exists because Python 2.4's
+ # doctest module doesn't play well with coverage. But nose fixes
+ # the problem by monkeypatching doctest. I want to undo the
+ # monkeypatch to be sure I'm getting the doctest module that users
+ # of coverage will get. Deleting the imported module here is
+ # enough: when the test imports doctest again, it will get a fresh
+ # copy without the monkeypatch.
+ del sys.modules['doctest']
+
+ def testDoctest(self):
+ self.check_coverage('''\
+ def return_arg_or_void(arg):
+ """If <arg> is None, return "Void"; otherwise return <arg>
+
+ >>> return_arg_or_void(None)
+ 'Void'
+ >>> return_arg_or_void("arg")
+ 'arg'
+ >>> return_arg_or_void("None")
+ 'None'
+ """
+ if arg is None:
+ return "Void"
+ else:
+ return arg
+
+ import doctest, sys
+ doctest.testmod(sys.modules[__name__]) # we're not __main__ :(
+ ''',
+ [1,11,12,14,16,17], "")
diff --git a/test/test_parser.py b/test/test_parser.py
index 3d5726de..b398044d 100644
--- a/test/test_parser.py
+++ b/test/test_parser.py
@@ -16,10 +16,10 @@ class ParserTest(CoverageTest):
def parse_source(self, text):
"""Parse `text` as source, and return the `CodeParser` used."""
text = textwrap.dedent(text)
- cp = CodeParser(text)
+ cp = CodeParser(text, exclude="nocover")
cp.parse_source()
return cp
-
+
def test_exit_counts(self):
cp = self.parse_source("""\
# check some basic branch counting
@@ -29,7 +29,7 @@ class ParserTest(CoverageTest):
return 5
else:
return 7
-
+
class Bar:
pass
""")
@@ -52,4 +52,45 @@ class ParserTest(CoverageTest):
self.assertEqual(cp.exit_counts(), {
1: 1, 2:1, 3:1, 4:1, 5:1, 6:1, 7:1, 8:1, 9:1
})
- \ No newline at end of file
+
+ def test_excluded_classes(self):
+ cp = self.parse_source("""\
+ class Foo:
+ def __init__(self):
+ pass
+
+ if 0: # nocover
+ class Bar:
+ pass
+ """)
+ self.assertEqual(cp.exit_counts(), {
+ 1:0, 2:1, 3:1
+ })
+
+ def test_missing_branch_to_excluded_code(self):
+ cp = self.parse_source("""\
+ if fooey:
+ a = 2
+ else: # nocover
+ a = 4
+ b = 5
+ """)
+ self.assertEqual(cp.exit_counts(), { 1:1, 2:1, 5:1 })
+ cp = self.parse_source("""\
+ def foo():
+ if fooey:
+ a = 3
+ else:
+ a = 5
+ b = 6
+ """)
+ self.assertEqual(cp.exit_counts(), { 1:1, 2:2, 3:1, 5:1, 6:1 })
+ cp = self.parse_source("""\
+ def foo():
+ if fooey:
+ a = 3
+ else: # nocover
+ a = 5
+ b = 6
+ """)
+ self.assertEqual(cp.exit_counts(), { 1:1, 2:1, 3:1, 6:1 })
diff --git a/test/test_phystokens.py b/test/test_phystokens.py
index fa0fa043..0e778510 100644
--- a/test/test_phystokens.py
+++ b/test/test_phystokens.py
@@ -36,12 +36,10 @@ class PhysTokensTest(CoverageTest):
tokenized += text + "\n"
# source_token_lines doesn't preserve trailing spaces, so trim all that
# before comparing.
+ source = source.replace('\r\n', '\n')
source = re.sub("(?m)[ \t]+$", "", source)
tokenized = re.sub("(?m)[ \t]+$", "", tokenized)
- #if source != tokenized:
- # open("0.py", "w").write(source)
- # open("1.py", "w").write(tokenized)
- self.assertEqual(source, tokenized)
+ self.assertMultiLineEqual(source, tokenized)
def check_file_tokenization(self, fname):
"""Use the contents of `fname` for `check_tokenization`."""
@@ -78,7 +76,7 @@ class PhysTokensTest(CoverageTest):
def test_stress(self):
# Check the tokenization of a stress-test file.
- stress = os.path.join(HERE, "stress_phystoken.txt")
+ stress = os.path.join(HERE, "stress_phystoken.tok")
+ self.check_file_tokenization(stress)
+ stress = os.path.join(HERE, "stress_phystoken_dos.tok")
self.check_file_tokenization(stress)
-
- \ No newline at end of file
diff --git a/test/test_process.py b/test/test_process.py
new file mode 100644
index 00000000..1f8a9884
--- /dev/null
+++ b/test/test_process.py
@@ -0,0 +1,245 @@
+"""Tests for process behavior of coverage.py."""
+
+import os, sys, textwrap
+import coverage
+
+sys.path.insert(0, os.path.split(__file__)[0]) # Force relative import for Py3k
+from coveragetest import CoverageTest
+
+
+class ProcessTest(CoverageTest):
+ """Tests of the per-process behavior of coverage.py."""
+
+ def number_of_data_files(self):
+ """Return the number of coverage data files in this directory."""
+ num = 0
+ for f in os.listdir('.'):
+ if f.startswith('.coverage.') or f == '.coverage':
+ num += 1
+ return num
+
+ def testSaveOnExit(self):
+ self.make_file("mycode.py", """\
+ h = "Hello"
+ w = "world"
+ """)
+
+ self.assertFalse(os.path.exists(".coverage"))
+ self.run_command("coverage -x mycode.py")
+ self.assertTrue(os.path.exists(".coverage"))
+
+ def testEnvironment(self):
+ # Checks that we can import modules from the test directory at all!
+ self.make_file("mycode.py", """\
+ import covmod1
+ import covmodzip1
+ a = 1
+ print ('done')
+ """)
+
+ self.assertFalse(os.path.exists(".coverage"))
+ out = self.run_command("coverage -x mycode.py")
+ self.assertTrue(os.path.exists(".coverage"))
+ self.assertEqual(out, 'done\n')
+
+ def testCombineParallelData(self):
+ self.make_file("b_or_c.py", """\
+ import sys
+ a = 1
+ if sys.argv[1] == 'b':
+ b = 1
+ else:
+ c = 1
+ d = 1
+ print ('done')
+ """)
+
+ out = self.run_command("coverage -x -p b_or_c.py b")
+ self.assertEqual(out, 'done\n')
+ self.assertFalse(os.path.exists(".coverage"))
+
+ out = self.run_command("coverage -x -p b_or_c.py c")
+ self.assertEqual(out, 'done\n')
+ self.assertFalse(os.path.exists(".coverage"))
+
+ # After two -p runs, there should be two .coverage.machine.123 files.
+ self.assertEqual(self.number_of_data_files(), 2)
+
+ # Combine the parallel coverage data files into .coverage .
+ self.run_command("coverage -c")
+ self.assertTrue(os.path.exists(".coverage"))
+
+ # After combining, there should be only the .coverage file.
+ self.assertEqual(self.number_of_data_files(), 1)
+
+ # Read the coverage file and see that b_or_c.py has all 7 lines
+ # executed.
+ data = coverage.CoverageData()
+ data.read_file(".coverage")
+ self.assertEqual(data.summary()['b_or_c.py'], 7)
+
+ def test_combine_with_rc(self):
+ self.make_file("b_or_c.py", """\
+ import sys
+ a = 1
+ if sys.argv[1] == 'b':
+ b = 1
+ else:
+ c = 1
+ d = 1
+ print ('done')
+ """)
+
+ self.make_file(".coveragerc", """\
+ [run]
+ parallel = true
+ """)
+
+ out = self.run_command("coverage run b_or_c.py b")
+ self.assertEqual(out, 'done\n')
+ self.assertFalse(os.path.exists(".coverage"))
+
+ out = self.run_command("coverage run b_or_c.py c")
+ self.assertEqual(out, 'done\n')
+ self.assertFalse(os.path.exists(".coverage"))
+
+ # After two runs, there should be two .coverage.machine.123 files.
+ self.assertEqual(self.number_of_data_files(), 2)
+
+ # Combine the parallel coverage data files into .coverage .
+ self.run_command("coverage combine")
+ self.assertTrue(os.path.exists(".coverage"))
+ self.assertTrue(os.path.exists(".coveragerc"))
+
+ # After combining, there should be only the .coverage file.
+ self.assertEqual(self.number_of_data_files(), 1)
+
+ # Read the coverage file and see that b_or_c.py has all 7 lines
+ # executed.
+ data = coverage.CoverageData()
+ data.read_file(".coverage")
+ self.assertEqual(data.summary()['b_or_c.py'], 7)
+
+ # Reporting should still work even with the .rc file
+ out = self.run_command("coverage report")
+ self.assertMultiLineEqual(out, textwrap.dedent("""\
+ Name Stmts Miss Cover
+ ----------------------------
+ b_or_c 7 0 100%
+ """))
+
+ def test_missing_source_file(self):
+ # Check what happens if the source is missing when reporting happens.
+ self.make_file("fleeting.py", """\
+ s = 'goodbye, cruel world!'
+ """)
+
+ self.run_command("coverage run fleeting.py")
+ os.remove("fleeting.py")
+ out = self.run_command("coverage html -d htmlcov")
+ self.assertRegexpMatches(out, "No source for code: '.*fleeting.py'")
+ self.assertFalse("Traceback" in out)
+
+ # It happens that the code paths are different for *.py and other
+ # files, so try again with no extension.
+ self.make_file("fleeting", """\
+ s = 'goodbye, cruel world!'
+ """)
+
+ self.run_command("coverage run fleeting")
+ os.remove("fleeting")
+ status, out = self.run_command_status("coverage html -d htmlcov", 1)
+ self.assertRegexpMatches(out, "No source for code: '.*fleeting'")
+ self.assertFalse("Traceback" in out)
+ self.assertEqual(status, 1)
+
+ def test_running_missing_file(self):
+ status, out = self.run_command_status("coverage run xyzzy.py", 1)
+ self.assertRegexpMatches(out, "No file to run: .*xyzzy.py")
+ self.assertFalse("Traceback" in out)
+ self.assertEqual(status, 1)
+
+ def test_code_throws(self):
+ self.make_file("throw.py", """\
+ def f1():
+ raise Exception("hey!")
+
+ def f2():
+ f1()
+
+ f2()
+ """)
+
+ # The important thing is for "coverage run" and "python" to report the
+ # same traceback.
+ status, out = self.run_command_status("coverage run throw.py", 1)
+ out2 = self.run_command("python throw.py")
+ self.assertMultiLineEqual(out, out2)
+
+ # But also make sure that the output is what we expect.
+ self.assertTrue('File "throw.py", line 5, in f2' in out)
+ self.assertTrue('raise Exception("hey!")' in out)
+ self.assertFalse('coverage' in out)
+ self.assertEqual(status, 1)
+
+ def test_code_exits(self):
+ self.make_file("exit.py", """\
+ import sys
+ def f1():
+ print("about to exit..")
+ sys.exit(17)
+
+ def f2():
+ f1()
+
+ f2()
+ """)
+
+ # The important thing is for "coverage run" and "python" to have the
+ # same output. No traceback.
+ status, out = self.run_command_status("coverage run exit.py", 17)
+ status2, out2 = self.run_command_status("python exit.py", 17)
+ self.assertMultiLineEqual(out, out2)
+ self.assertMultiLineEqual(out, "about to exit..\n")
+ self.assertEqual(status, status2)
+ self.assertEqual(status, 17)
+
+ if hasattr(os, 'fork'):
+ def test_fork(self):
+ self.make_file("fork.py", """\
+ import os
+
+ def child():
+ print('Child!')
+
+ def main():
+ ret = os.fork()
+
+ if ret == 0:
+ child()
+ else:
+ os.waitpid(ret, 0)
+
+ main()
+ """)
+
+ out = self.run_command("coverage run -p fork.py")
+ self.assertEqual(out, 'Child!\n')
+ self.assertFalse(os.path.exists(".coverage"))
+
+ # After running the forking program, there should be two
+ # .coverage.machine.123 files.
+ self.assertEqual(self.number_of_data_files(), 2)
+
+ # Combine the parallel coverage data files into .coverage .
+ self.run_command("coverage -c")
+ self.assertTrue(os.path.exists(".coverage"))
+
+ # After combining, there should be only the .coverage file.
+ self.assertEqual(self.number_of_data_files(), 1)
+
+ # Read the coverage file and see that b_or_c.py has all 7 lines
+ # executed.
+ data = coverage.CoverageData()
+ data.read_file(".coverage")
+ self.assertEqual(data.summary()['fork.py'], 9)
diff --git a/test/test_results.py b/test/test_results.py
index 33ebe4d7..ef15121c 100644
--- a/test/test_results.py
+++ b/test/test_results.py
@@ -10,7 +10,7 @@ from coveragetest import CoverageTest
class NumbersTest(CoverageTest):
"""Tests for Coverage.py's numeric measurement summaries."""
-
+
run_in_temp_dir = False
def test_basic(self):
@@ -19,7 +19,7 @@ class NumbersTest(CoverageTest):
self.assertEqual(n1.n_executed, 180)
self.assertEqual(n1.n_missing, 20)
self.assertEqual(n1.pc_covered, 90)
-
+
def test_addition(self):
n1 = Numbers(n_files=1, n_statements=200, n_missing=20)
n2 = Numbers(n_files=1, n_statements=10, n_missing=8)
diff --git a/test/test_summary.py b/test/test_summary.py
index 36db9969..b41a3e7d 100644
--- a/test/test_summary.py
+++ b/test/test_summary.py
@@ -20,9 +20,9 @@ class SummaryTest(CoverageTest):
def report_from_command(self, cmd):
"""Return the report from the `cmd`, with some convenience added."""
report = self.run_command(cmd).replace('\\', '/')
- self.assert_("error" not in report.lower())
+ self.assertFalse("error" in report.lower())
return report
-
+
def line_count(self, report):
"""How many lines are in `report`?"""
self.assertEqual(report.split('\n')[-1], "")
@@ -38,52 +38,52 @@ class SummaryTest(CoverageTest):
self.assertEqual(out, 'done\n')
report = self.report_from_command("coverage -r")
- # Name Stmts Exec Cover
+ # Name Stmts Miss Cover
# ---------------------------------------------------------------------
- # c:/ned/coverage/trunk/test/modules/covmod1 2 2 100%
- # c:/ned/coverage/trunk/test/zipmods.zip/covmodzip1 2 2 100%
- # mycode 4 4 100%
+ # c:/ned/coverage/trunk/test/modules/covmod1 2 0 100%
+ # c:/ned/coverage/trunk/test/zipmods.zip/covmodzip1 2 0 100%
+ # mycode 4 0 100%
# ---------------------------------------------------------------------
- # TOTAL 8 8 100%
+ # TOTAL 8 0 100%
- self.assert_("/coverage/__init__/" not in report)
- self.assert_("/test/modules/covmod1 " in report)
- self.assert_("/test/zipmods.zip/covmodzip1 " in report)
- self.assert_("mycode " in report)
- self.assertEqual(self.last_line_squeezed(report), "TOTAL 8 8 100%")
+ self.assertFalse("/coverage/__init__/" in report)
+ self.assertTrue("/test/modules/covmod1 " in report)
+ self.assertTrue("/test/zipmods.zip/covmodzip1 " in report)
+ self.assertTrue("mycode " in report)
+ self.assertEqual(self.last_line_squeezed(report), "TOTAL 8 0 100%")
def test_report_just_one(self):
# Try reporting just one module
self.run_command("coverage -x mycode.py")
report = self.report_from_command("coverage -r mycode.py")
- # Name Stmts Exec Cover
+ # Name Stmts Miss Cover
# ----------------------------
- # mycode 4 4 100%
+ # mycode 4 0 100%
self.assertEqual(self.line_count(report), 3)
- self.assert_("/coverage/" not in report)
- self.assert_("/test/modules/covmod1 " not in report)
- self.assert_("/test/zipmods.zip/covmodzip1 " not in report)
- self.assert_("mycode " in report)
- self.assertEqual(self.last_line_squeezed(report), "mycode 4 4 100%")
+ self.assertFalse("/coverage/" in report)
+ self.assertFalse("/test/modules/covmod1 " in report)
+ self.assertFalse("/test/zipmods.zip/covmodzip1 " in report)
+ self.assertTrue("mycode " in report)
+ self.assertEqual(self.last_line_squeezed(report), "mycode 4 0 100%")
def test_report_omitting(self):
# Try reporting while omitting some modules
prefix = os.path.split(__file__)[0]
self.run_command("coverage -x mycode.py")
report = self.report_from_command("coverage -r -o %s" % prefix)
-
- # Name Stmts Exec Cover
+
+ # Name Stmts Miss Cover
# ----------------------------
- # mycode 4 4 100%
+ # mycode 4 0 100%
self.assertEqual(self.line_count(report), 3)
- self.assert_("/coverage/" not in report)
- self.assert_("/test/modules/covmod1 " not in report)
- self.assert_("/test/zipmods.zip/covmodzip1 " not in report)
- self.assert_("mycode " in report)
- self.assertEqual(self.last_line_squeezed(report), "mycode 4 4 100%")
+ self.assertFalse("/coverage/" in report)
+ self.assertFalse("/test/modules/covmod1 " in report)
+ self.assertFalse("/test/zipmods.zip/covmodzip1 " in report)
+ self.assertTrue("mycode " in report)
+ self.assertEqual(self.last_line_squeezed(report), "mycode 4 0 100%")
def test_report_branches(self):
self.make_file("mybranch.py", """\
@@ -97,11 +97,11 @@ class SummaryTest(CoverageTest):
self.assertEqual(out, 'x\n')
report = self.report_from_command("coverage report")
- # Name Stmts Exec Branch BrExec Cover
+ # Name Stmts Miss Branch BrPart Cover
# --------------------------------------------
- # mybranch 5 5 2 1 85%
+ # mybranch 5 0 2 1 85%
self.assertEqual(self.line_count(report), 3)
- self.assert_("mybranch " in report)
+ self.assertTrue("mybranch " in report)
self.assertEqual(self.last_line_squeezed(report),
- "mybranch 5 5 2 1 85%")
+ "mybranch 5 0 2 1 85%")
diff --git a/test/test_templite.py b/test/test_templite.py
index 8cb25865..93e9183d 100644
--- a/test/test_templite.py
+++ b/test/test_templite.py
@@ -9,9 +9,9 @@ import unittest
class AnyOldObject(object):
"""Simple testing object.
-
+
Use keyword arguments in the constructor to set attributes on the object.
-
+
"""
def __init__(self, **attrs):
for n, v in attrs.items():
@@ -45,7 +45,7 @@ class TempliteTest(unittest.TestCase):
'second': lambda x: x[1],
}
self.try_render("Hello, {{name|upper}}!", data, "Hello, NED!")
-
+
# Pipes can be concatenated.
self.try_render("Hello, {{name|upper|second}}!", data, "Hello, E!")
@@ -55,7 +55,7 @@ class TempliteTest(unittest.TestCase):
'upper': lambda x: x.upper(),
'punct': '!',
}
-
+
template = Templite("This is {{name|upper}}{{punct}}", globs)
self.assertEqual(template.render({'name':'Ned'}), "This is NED!")
self.assertEqual(template.render({'name':'Ben'}), "This is BEN!")
@@ -67,7 +67,7 @@ class TempliteTest(unittest.TestCase):
obj2 = AnyOldObject(obj=obj, b="Bee")
self.try_render("{{obj2.obj.a}} {{obj2.b}}", locals(), "Ay Bee")
-
+
def test_member_function(self):
# Variables' member functions can be used, as long as they are nullary.
class WithMemberFns(AnyOldObject):
@@ -97,7 +97,7 @@ class TempliteTest(unittest.TestCase):
l = l[:]
l.reverse()
return l
-
+
self.try_render(
"Look: {% for n in nums|rev %}{{n}}, {% endfor %}done.",
locals(),
@@ -117,7 +117,7 @@ class TempliteTest(unittest.TestCase):
{'nums':[1,2,3]},
"Look: \n\n1, \n\n2, \n\n3, \ndone."
)
-
+
def test_multiple_loops(self):
self.try_render(
"{% for n in nums %}{{n}}{% endfor %} and "
@@ -191,6 +191,14 @@ class TempliteTest(unittest.TestCase):
"@a0b0c0a1b1c1a2b2c2!"
)
-
-if __name__ == '__main__':
- unittest.main()
+ def test_exception_during_evaluation(self):
+ # TypeError: Couldn't evaluate {{ foo.bar.baz }}:
+ # 'NoneType' object is unsubscriptable
+ self.assertRaises(TypeError, self.try_render,
+ "Hey {{foo.bar.baz}} there", {'foo': None}, "Hey ??? there"
+ )
+
+ def test_bogus_tag_syntax(self):
+ self.assertRaises(SyntaxError, self.try_render,
+ "Huh: {% bogus %}!!{% endbogus %}??", {}, ""
+ )
diff --git a/test/test_testing.py b/test/test_testing.py
index 1e22202a..9bbb7cca 100644
--- a/test/test_testing.py
+++ b/test/test_testing.py
@@ -2,29 +2,110 @@
import os, sys
sys.path.insert(0, os.path.split(__file__)[0]) # Force relative import for Py3k
+from backunittest import TestCase
from coveragetest import CoverageTest
from coverage.backward import set # pylint: disable-msg=W0622
-class TestingTest(CoverageTest):
- """Tests of helper methods on CoverageTest."""
+class TestingTest(TestCase):
+ """Tests of helper methods on `backunittest.TestCase`."""
run_in_temp_dir = False
- def test_assert_equal_sets(self):
- self.assert_equal_sets(set(), set())
- self.assert_equal_sets(set([1,2,3]), set([3,1,2]))
- self.assertRaises(AssertionError, self.assert_equal_sets,
+ def please_raise(self, exc, msg):
+ """Raise an exception for testing assertRaisesRegexp."""
+ raise exc(msg)
+
+ def please_succeed(self):
+ """A simple successful method for testing assertRaisesRegexp."""
+ return "All is well"
+
+ def test_assert_same_elements(self):
+ self.assertSameElements(set(), set())
+ self.assertSameElements(set([1,2,3]), set([3,1,2]))
+ self.assertRaises(AssertionError, self.assertSameElements,
set([1,2,3]), set()
)
- self.assertRaises(AssertionError, self.assert_equal_sets,
+ self.assertRaises(AssertionError, self.assertSameElements,
set([1,2,3]), set([4,5,6])
)
- def test_assert_matches(self):
- self.assert_matches("hello", "hel*o")
- self.assert_matches("Oh, hello there!", "hel*o")
- self.assertRaises(AssertionError, self.assert_matches,
+ def test_assert_regexp_matches(self):
+ self.assertRegexpMatches("hello", "hel*o")
+ self.assertRegexpMatches("Oh, hello there!", "hel*o")
+ self.assertRaises(AssertionError, self.assertRegexpMatches,
"hello there", "^hello$"
)
+ def test_assert_multiline_equal(self):
+ self.assertMultiLineEqual("hello", "hello")
+ self.assertRaises(AssertionError, self.assertMultiLineEqual,
+ "hello there", "Hello there"
+ )
+ self.assertRaises(AssertionError, self.assertMultiLineEqual,
+ "hello\nthere", "hello\nThere"
+ )
+ # With messages also.
+ self.assertMultiLineEqual("hi", "hi", "it's ok")
+ self.assertRaisesRegexp(
+ AssertionError, "my message",
+ self.assertMultiLineEqual, "xyz", "abc", "my message"
+ )
+
+ def test_assert_raises_regexp(self):
+ # Raising the right error with the right message passes.
+ self.assertRaisesRegexp(
+ ZeroDivisionError, "Wow! Zero!",
+ self.please_raise, ZeroDivisionError, "Wow! Zero!"
+ )
+ # Raising the right error with a match passes.
+ self.assertRaisesRegexp(
+ ZeroDivisionError, "Zero",
+ self.please_raise, ZeroDivisionError, "Wow! Zero!"
+ )
+ # Raising the right error with a mismatch fails.
+ self.assertRaises(AssertionError,
+ self.assertRaisesRegexp, ZeroDivisionError, "XYZ",
+ self.please_raise, ZeroDivisionError, "Wow! Zero!"
+ )
+ # Raising the right error with a mismatch fails.
+ self.assertRaises(AssertionError,
+ self.assertRaisesRegexp, ZeroDivisionError, "XYZ",
+ self.please_raise, ZeroDivisionError, "Wow! Zero!"
+ )
+ # Raising the wrong error raises the error itself.
+ self.assertRaises(ZeroDivisionError,
+ self.assertRaisesRegexp, IOError, "Wow! Zero!",
+ self.please_raise, ZeroDivisionError, "Wow! Zero!"
+ )
+ # Raising no error fails.
+ self.assertRaises(AssertionError,
+ self.assertRaisesRegexp, ZeroDivisionError, "XYZ",
+ self.please_succeed
+ )
+
+ def test_assert_true(self):
+ self.assertTrue(True)
+ self.assertRaises(AssertionError, self.assertTrue, False)
+
+ def test_assert_false(self):
+ self.assertFalse(False)
+ self.assertRaises(AssertionError, self.assertFalse, True)
+
+
+class CoverageTestTest(CoverageTest):
+ """Test the methods in `CoverageTest`."""
+
+ def test_make_file(self):
+ # A simple file.
+ self.make_file("fooey.boo", "Hello there")
+ self.assertEqual(open("fooey.boo").read(), "Hello there")
+ # A file in a sub-directory
+ self.make_file("sub/another.txt", "Another")
+ self.assertEqual(open("sub/another.txt").read(), "Another")
+ # A second file in that sub-directory
+ self.make_file("sub/second.txt", "Second")
+ self.assertEqual(open("sub/second.txt").read(), "Second")
+ # A deeper directory
+ self.make_file("sub/deeper/evenmore/third.txt", "Third")
+ self.assertEqual(open("sub/deeper/evenmore/third.txt").read(), "Third")