From b7b7979cf363e4b30aa2fe6576634df48aaec75a Mon Sep 17 00:00:00 2001 From: "James E. Blair" Date: Wed, 2 Mar 2016 08:24:15 -0800 Subject: [PATCH] Don't extend the passed in targets If the caller passes in a value for targets, copy it before extending it with our own targets. Because the argument is a reference, our extending the list here may cause the list to be extended again if the caller creates another ReadSubunit instance reusing the same argument. This caused "ValueError: I/O operation on closed file" errors because the pares_outcome callback of every previous instantiation was being called for each new outcome. Change-Id: Iadd7b063e61590869dbea6ce9db9ffe611fbae0a --- subunit2sql/read_subunit.py | 2 ++ subunit2sql/tests/test_read_subunit.py | 15 +++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/subunit2sql/read_subunit.py b/subunit2sql/read_subunit.py index 2850283..19e98aa 100644 --- a/subunit2sql/read_subunit.py +++ b/subunit2sql/read_subunit.py @@ -37,6 +37,8 @@ class ReadSubunit(object): targets=None): if targets is None: targets = [] + else: + targets = targets[:] self.stream_file = stream_file self.stream = subunit.ByteStreamToStreamResult(self.stream_file) starts = testtools.StreamResult() diff --git a/subunit2sql/tests/test_read_subunit.py b/subunit2sql/tests/test_read_subunit.py index 450264a..70d7547 100644 --- a/subunit2sql/tests/test_read_subunit.py +++ b/subunit2sql/tests/test_read_subunit.py @@ -175,3 +175,18 @@ class TestReadSubunit(base.TestCase): def test_targets_added_to_result(self, ttc_mock): subunit.ReadSubunit(mock.MagicMock(), targets=['foo']) self.assertIn('foo', ttc_mock.call_args[0][0]) + + @mock.patch('testtools.CopyStreamResult') + def test_targets_not_modified(self, ttc_mock): + # A regression test that verifies that the subunit reader does + # not modify the passed in value of targets. + targets = ['foo'] + + subunit.ReadSubunit(mock.MagicMock(), targets=targets) + ntargets1 = len(ttc_mock.call_args[0][0]) + + subunit.ReadSubunit(mock.MagicMock(), targets=targets) + ntargets2 = len(ttc_mock.call_args[0][0]) + + self.assertEqual(ntargets1, ntargets2) + self.assertEqual(targets, ['foo'])