summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNed Batchelder <ned@nedbatchelder.com>2015-02-18 22:22:38 -0500
committerNed Batchelder <ned@nedbatchelder.com>2015-02-18 22:22:38 -0500
commitd28c7251e43bff2f2cc5a8cc56e6cdbb3973abab (patch)
tree2ac7102dcb3b5dec2c6812d1813eca1d67fe3a55
parent0155f1f0619640cce45dd2a3ace367e04c4eb0d2 (diff)
downloadpython-coveragepy-d28c7251e43bff2f2cc5a8cc56e6cdbb3973abab.tar.gz
Make branch=True get along with plugins.
-rw-r--r--coverage/tracer.c23
-rw-r--r--tests/test_plugins.py29
2 files changed, 38 insertions, 14 deletions
diff --git a/coverage/tracer.c b/coverage/tracer.c
index 43ecd18..8577afc 100644
--- a/coverage/tracer.c
+++ b/coverage/tracer.c
@@ -638,31 +638,30 @@ CTracer_handle_line(CTracer *self, PyFrameObject *frame)
}
if (lineno_from != -1) {
- if (self->tracing_arcs) {
- /* Tracing arcs: key is (last_line,this_line). */
- /* TODO: this needs to deal with lineno_to also. */
- if (CTracer_record_pair(self, self->cur_entry.last_line, lineno_from) < 0) {
- goto error;
+ for (; lineno_from <= lineno_to; lineno_from++) {
+ if (self->tracing_arcs) {
+ /* Tracing arcs: key is (last_line,this_line). */
+ if (CTracer_record_pair(self, self->cur_entry.last_line, lineno_from) < 0) {
+ goto error;
+ }
}
- }
- else {
- /* Tracing lines: key is simply this_line. */
- while (lineno_from <= lineno_to) {
+ else {
+ /* Tracing lines: key is simply this_line. */
PyObject * this_line = MyInt_FromInt(lineno_from);
if (this_line == NULL) {
goto error;
}
+
ret = PyDict_SetItem(self->cur_entry.file_data, this_line, Py_None);
Py_DECREF(this_line);
if (ret < 0) {
goto error;
}
- lineno_from++;
}
+
+ self->cur_entry.last_line = lineno_from;
}
}
-
- self->cur_entry.last_line = lineno_to;
}
}
diff --git a/tests/test_plugins.py b/tests/test_plugins.py
index 74f78cf..f39b062 100644
--- a/tests/test_plugins.py
+++ b/tests/test_plugins.py
@@ -277,7 +277,7 @@ class GoodPluginTest(FileTracerTest):
_, statements, _, _ = cov.analysis(zzfile)
self.assertEqual(statements, [105, 106, 107, 205, 206, 207])
- def test_plugin2(self):
+ def make_render_and_caller(self):
# plugin2 emulates a dynamic tracing plugin: the caller's locals
# are examined to determine the source file and line number.
# The plugin is in tests/plugin2.py.
@@ -295,6 +295,7 @@ class GoodPluginTest(FileTracerTest):
return x+1
""")
self.make_file("caller.py", """\
+ import sys
from render import helper, render
assert render("foo_7.html", 4) == "[foo_7.html @ 4]"
@@ -309,10 +310,13 @@ class GoodPluginTest(FileTracerTest):
assert render("quux_5.html", 3) == "[quux_5.html @ 3]"
# In Python 2, either kind of string should be OK.
- if type("") == type(b""):
+ if sys.version_info[0] == 2:
assert render(u"unicode_3.html", 2) == "[unicode_3.html @ 2]"
""")
+ def test_plugin2(self):
+ self.make_render_and_caller()
+
cov = coverage.Coverage(omit=["*quux*"])
CheckUniqueFilenames.hook(cov, '_should_trace')
CheckUniqueFilenames.hook(cov, '_check_include_omit_etc')
@@ -341,6 +345,27 @@ class GoodPluginTest(FileTracerTest):
self.assertEqual(missing, [1])
self.assertIn("unicode_3.html", cov.data.summary())
+ def test_plugin2_with_branch(self):
+ self.make_render_and_caller()
+
+ cov = coverage.Coverage(branch=True, omit=["*quux*"])
+ CheckUniqueFilenames.hook(cov, '_should_trace')
+ CheckUniqueFilenames.hook(cov, '_check_include_omit_etc')
+ cov.config["run:plugins"] = ["tests.plugin2"]
+
+ self.start_import_stop(cov, "caller")
+
+ # The way plugin2 works, a file named foo_7.html will be claimed to
+ # have 7 lines in it. If render() was called with line number 4,
+ # then the plugin will claim that lines 4 and 5 were executed.
+ analysis = cov._analyze("foo_7.html")
+ self.assertEqual(analysis.statements, set([1, 2, 3, 4, 5, 6, 7]))
+ # Plugins don't do branch coverage yet.
+ self.assertEqual(analysis.has_arcs(), True)
+ self.assertEqual(analysis.arc_possibilities(), [])
+
+ self.assertEqual(analysis.missing, set([1, 2, 3, 6, 7]))
+
class BadPluginTest(FileTracerTest):
"""Test error handling around plugins."""