diff --git a/test_whisper.py b/test_whisper.py index 49a92376..56a29054 100755 --- a/test_whisper.py +++ b/test_whisper.py @@ -187,7 +187,7 @@ def test_aggregate(self): with AssertRaisesException(whisper.InvalidAggregationMethod('Unrecognized aggregation method derp')): whisper.aggregate('derp', [12, 2, 3123, 1]) - def _test_create_IOError(self, ioerror_method='write', e=errno.ENOSPC): + def _test_create_exception(self, exception_method='write', e=None): """ Behaviour when creating a whisper file on a full filesystem """ @@ -195,12 +195,15 @@ def _test_create_IOError(self, ioerror_method='write', e=errno.ENOSPC): # Get the mocked file object and override interresting attributes m_file = m_open.return_value m_file.name = self.filename - method = getattr(m_file, ioerror_method) - method.side_effect = IOError(e, "Mocked IOError - ENOSPC") + method = getattr(m_file, exception_method) + + if not e: + e = IOError(errno.ENOSPC, "Mocked IOError") + method.side_effect = e with patch('whisper.open', m_open, create=True): with patch('os.unlink') as m_unlink: - self.assertRaises(IOError, whisper.create, self.filename, self.retention) + self.assertRaises(e.__class__, whisper.create, self.filename, self.retention) return (m_file, m_unlink) @@ -208,24 +211,31 @@ def test_create_write_ENOSPC(self): """ Behaviour when creating a whisper file on a full filesystem (write) """ - (m_file, m_unlink) = self._test_create_IOError('write') + (m_file, m_unlink) = self._test_create_exception('write') m_unlink.assert_called_with(self.filename) def test_create_close_ENOSPC(self): """ Behaviour when creating a whisper file on a full filesystem (close) """ - (m_file, m_unlink) = self._test_create_IOError('close') + (m_file, m_unlink) = self._test_create_exception('close') m_unlink.assert_called_with(self.filename) def test_create_close_EIO(self): """ - Behaviour when creating a whisper file and getting an I/O error + Behaviour when creating a whisper file and getting an I/O error (EIO) + """ + (m_file, m_unlink) = self._test_create_exception('close', e=IOError(errno.EIO)) + self.assertTrue(m_unlink.called) + + def test_create_close_exception(self): + """ + Behaviour when creating a whisper file and getting a generic exception """ - (m_file, m_unlink) = self._test_create_IOError('close', e=errno.EIO) + (m_file, m_unlink) = self._test_create_exception('close', e=Exception("boom!")) + # Must not call os.unlink on exception other than IOError self.assertFalse(m_unlink.called) - def test_create_and_info(self): """ Create a db and use info() to validate diff --git a/whisper.py b/whisper.py index a38ac00a..0d53c004 100644 --- a/whisper.py +++ b/whisper.py @@ -420,9 +420,9 @@ def create(path,archiveList,xFilesFactor=None,aggregationMethod=None,sparse=Fals # Explicitly close the file to catch IOError on close() fh.close() except IOError, e: - # Cleanup after ourself if there's no space left on device - if e.errno == ENOSPC: - os.unlink(fh.name) + # if we got an IOError above, the file is either empty or half created. + # Better off deleting it to avoid surprises later + os.unlink(fh.name) raise