diff --git a/pyeclib/core.py b/pyeclib/core.py index e00fdfa..f9d5268 100644 --- a/pyeclib/core.py +++ b/pyeclib/core.py @@ -21,6 +21,7 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +from .ec_iface import ECBackendInstanceNotAvailable from .ec_iface import ECDriverError from .ec_iface import ECInsufficientFragments from .ec_iface import PyECLib_FRAGHDRCHKSUM_Types @@ -49,7 +50,7 @@ class ECPyECLibDriver(object): if self.chksum_type is PyECLib_FRAGHDRCHKSUM_Types.inline_crc32: self.inline_chksum = 1 - self.handle = pyeclib_c.init( + self._handle = pyeclib_c.init( self.k, self.m, ec_type.value, @@ -64,9 +65,16 @@ class ECPyECLibDriver(object): self.chksum_type) def close(self): - if self.handle: - pyeclib_c.destroy(self.handle) - self.handle = None + if self._handle is not None: + pyeclib_c.destroy(self._handle) + self._handle = None + + @property + def handle(self): + if self._handle is None: + raise ECBackendInstanceNotAvailable( + 'erasure coding handle is closed') + return self._handle def encode(self, data_bytes): return pyeclib_c.encode(self.handle, data_bytes) diff --git a/test/test_pyeclib_api.py b/test/test_pyeclib_api.py index 3908038..a443778 100644 --- a/test/test_pyeclib_api.py +++ b/test/test_pyeclib_api.py @@ -33,6 +33,7 @@ import unittest from itertools import combinations import pyeclib.ec_iface +from pyeclib.ec_iface import ECBackendInstanceNotAvailable from pyeclib.ec_iface import ECBackendNotSupported from pyeclib.ec_iface import ECDriver from pyeclib.ec_iface import ECDriverError @@ -294,6 +295,27 @@ class TestPyECLibDriver(unittest.TestCase): chksum_type=csum)) return pyeclib_drivers + def test_use_after_close(self): + pyeclib_drivers = self.get_pyeclib_testspec() + for pyeclib_driver in pyeclib_drivers: + frags = pyeclib_driver.encode(b"testdata") + self.assertEqual( + pyeclib_driver.reconstruct(frags[1:], [0])[0], frags[0]) + + pyeclib_driver.close() + with self.assertRaises(ECBackendInstanceNotAvailable) as ctx: + pyeclib_driver.encode(b"testdata") + self.assertEqual(str(ctx.exception), + 'erasure coding handle is closed') + with self.assertRaises(ECBackendInstanceNotAvailable) as ctx: + pyeclib_driver.decode(frags) + self.assertEqual(str(ctx.exception), + 'erasure coding handle is closed') + with self.assertRaises(ECBackendInstanceNotAvailable) as ctx: + pyeclib_driver.reconstruct(frags[1:], [0]) + self.assertEqual(str(ctx.exception), + 'erasure coding handle is closed') + def test_small_encode(self): pyeclib_drivers = self.get_pyeclib_testspec() encode_strs = [b"a", b"hello", b"hellohyhi", b"yo"]