diff options
author | Ned Batchelder <ned@nedbatchelder.com> | 2015-07-19 11:20:38 -0400 |
---|---|---|
committer | Ned Batchelder <ned@nedbatchelder.com> | 2015-07-19 11:20:38 -0400 |
commit | 3cf3f1a78231e8da18153e7aa5ff9dd1f814e7bb (patch) | |
tree | 261d7a2e7c5077be20ca7361210c9bd8b23d93ac | |
parent | 5a1bce52a2514322fe8f6ee276d53de17aacafcd (diff) | |
download | python-coveragepy-git-3cf3f1a78231e8da18153e7aa5ff9dd1f814e7bb.tar.gz |
Start preventing incorrect mixing of data.
-rw-r--r-- | coverage/data.py | 34 | ||||
-rw-r--r-- | tests/test_data.py | 68 |
2 files changed, 94 insertions, 8 deletions
diff --git a/coverage/data.py b/coverage/data.py index be9ceba6..f50bf1cf 100644 --- a/coverage/data.py +++ b/coverage/data.py @@ -173,6 +173,9 @@ class CoverageData(object): `line_data` is { filename: { lineno: None, ... }, ...} """ + if self.has_arcs(): + raise CoverageException("Can't add lines to existing arc data") + for filename, linenos in iitems(line_data): self._lines.setdefault(filename, {}).update(linenos) @@ -182,6 +185,9 @@ class CoverageData(object): `arc_data` is { filename: { (l1,l2): None, ... }, ...} """ + if self.has_lines(): + raise CoverageException("Can't add arcs to existing line data") + for filename, arcs in iitems(arc_data): self._arcs.setdefault(filename, {}).update(arcs) @@ -200,14 +206,36 @@ class CoverageData(object): re-map paths to match the local machine's. """ + if ((self.has_lines() and other_data.has_arcs()) or + (self.has_arcs() and other_data.has_lines())): + raise CoverageException("Can't combine line data with arc data") + aliases = aliases or PathAliases() + + # _lines: merge dicts. for filename, file_data in iitems(other_data._lines): filename = aliases.map(filename) self._lines.setdefault(filename, {}).update(file_data) + + # _arcs: merge dicts. for filename, file_data in iitems(other_data._arcs): filename = aliases.map(filename) self._arcs.setdefault(filename, {}).update(file_data) - self._plugins.update(other_data._plugins) + + # _plugins: only have a string, so they have to agree. + for filename, plugin_name in iitems(other_data._plugins): + filename = aliases.map(filename) + this_plugin = self._plugins.get(filename) + # TODO: plugin=None could mean no filename recorded, or it could + # mean, handled by Python. Need to distinguish those cases. + if this_plugin is None: + self._plugins[filename] = plugin_name + elif this_plugin != plugin_name: + raise CoverageException( + "Conflicting plugin name for '%s': %s vs %s" % ( + filename, this_plugin, plugin_name, + ) + ) def touch_file(self, filename): """Ensure that `filename` appears in the data, empty if needed.""" @@ -247,6 +275,10 @@ class CoverageData(object): __bool__ = __nonzero__ + def has_lines(self): + """Does this data have lines?""" + return bool(self._lines) + def has_arcs(self): """Does this data have arcs?""" return bool(self._arcs) diff --git a/tests/test_data.py b/tests/test_data.py index 3cae55bd..1d913c3d 100644 --- a/tests/test_data.py +++ b/tests/test_data.py @@ -45,6 +45,7 @@ Y_PY_ARCS_3 = [(-1, 17), (17, 23), (23, -1)] SUMMARY_3 = {'x.py': 3, 'y.py': 2} MEASURED_FILES_3 = ['x.py', 'y.py'] X_PY_LINES_3 = [1, 2, 3] +Y_PY_LINES_3 = [17, 23] class DataTestHelpers(CoverageTest): @@ -92,12 +93,32 @@ class CoverageDataTest(DataTestHelpers, CoverageTest): self.assert_measured_files(covdata, MEASURED_FILES_3) self.assertCountEqual(covdata.lines("x.py"), X_PY_LINES_3) self.assertCountEqual(covdata.arcs("x.py"), X_PY_ARCS_3) + self.assertCountEqual(covdata.lines("y.py"), Y_PY_LINES_3) + self.assertCountEqual(covdata.arcs("y.py"), Y_PY_ARCS_3) - def test_touch_file(self): + def test_cant_add_arcs_to_lines(self): covdata = CoverageData() covdata.add_lines(DATA_1) - covdata.touch_file('x.py') - self.assert_measured_files(covdata, MEASURED_FILES_1 + ['x.py']) + with self.assertRaises(CoverageException): + covdata.add_arcs(ARC_DATA_3) + + def test_cant_add_lines_to_arcs(self): + covdata = CoverageData() + covdata.add_arcs(ARC_DATA_3) + with self.assertRaises(CoverageException): + covdata.add_lines(DATA_1) + + def test_touch_file_with_lines(self): + covdata = CoverageData() + covdata.add_lines(DATA_1) + covdata.touch_file('zzz.py') + self.assert_measured_files(covdata, MEASURED_FILES_1 + ['zzz.py']) + + def test_touch_file_with_arcs(self): + covdata = CoverageData() + covdata.add_arcs(ARC_DATA_3) + covdata.touch_file('zzz.py') + self.assert_measured_files(covdata, MEASURED_FILES_3 + ['zzz.py']) def test_plugin_name(self): covdata = CoverageData() @@ -105,6 +126,30 @@ class CoverageDataTest(DataTestHelpers, CoverageTest): self.assertEqual(covdata.plugin_name("p1.foo"), "p1.plugin") self.assertIsNone(covdata.plugin_name("p3.not_here")) + def test_update(self): + covdata1 = CoverageData() + covdata1.add_lines(DATA_1) + + covdata2 = CoverageData() + covdata2.add_lines(DATA_2) + + covdata3 = CoverageData() + covdata3.update(covdata1) + covdata3.update(covdata2) + + self.assert_line_counts(covdata3, SUMMARY_1_2) + self.assert_measured_files(covdata3, MEASURED_FILES_1_2) + + def test_update_cant_mix_lines_and_arcs(self): + covdata1 = CoverageData() + covdata1.add_lines(DATA_1) + + covdata2 = CoverageData() + covdata2.add_arcs(ARC_DATA_3) + + with self.assertRaises(CoverageException): + covdata1.update(covdata2) + class CoverageDataTestInTempDir(DataTestHelpers, CoverageTest): """Tests of CoverageData that need a temp dir to make files.""" @@ -131,6 +176,8 @@ class CoverageDataTestInTempDir(DataTestHelpers, CoverageTest): self.assert_measured_files(covdata2, MEASURED_FILES_3) self.assertCountEqual(covdata2.lines("x.py"), X_PY_LINES_3) self.assertCountEqual(covdata2.arcs("x.py"), X_PY_ARCS_3) + self.assertCountEqual(covdata2.lines("y.py"), Y_PY_LINES_3) + self.assertCountEqual(covdata2.arcs("y.py"), Y_PY_ARCS_3) def test_read_errors(self): covdata = CoverageData() @@ -207,18 +254,26 @@ class CoverageDataFilesTest(DataTestHelpers, CoverageTest): self.assertEqual(debug.get_output(), "") def test_combining(self): + self.assert_doesnt_exist(".coverage.1") + self.assert_doesnt_exist(".coverage.2") + covdata1 = CoverageData() covdata1.add_lines(DATA_1) self.data_files.write(covdata1, suffix='1') + self.assert_exists(".coverage.1") + self.assert_doesnt_exist(".coverage.2") covdata2 = CoverageData() covdata2.add_lines(DATA_2) self.data_files.write(covdata2, suffix='2') + self.assert_exists(".coverage.2") covdata3 = CoverageData() self.data_files.combine_parallel_data(covdata3) self.assert_line_counts(covdata3, SUMMARY_1_2) self.assert_measured_files(covdata3, MEASURED_FILES_1_2) + self.assert_doesnt_exist(".coverage.1") + self.assert_doesnt_exist(".coverage.2") def test_erasing(self): covdata1 = CoverageData() @@ -303,10 +358,9 @@ class CoverageDataFilesTest(DataTestHelpers, CoverageTest): covdata2.write_file('cov2/.coverage.2') covdata3 = CoverageData() - self.data_files.combine_parallel_data(covdata3, data_dirs=[ - 'cov1/', - 'cov2/', - ]) + self.data_files.combine_parallel_data(covdata3, data_dirs=['cov1/', 'cov2/']) self.assert_line_counts(covdata3, SUMMARY_1_2) self.assert_measured_files(covdata3, MEASURED_FILES_1_2) + self.assert_doesnt_exist("cov1/.coverage.1") + self.assert_doesnt_exist("cov2/.coverage.2") |