diff options
author | Thiago da Silva <thiago@redhat.com> | 2014-02-21 18:23:29 -0500 |
---|---|---|
committer | Gerrit Code Review <review@dev.gluster.org> | 2014-02-24 19:25:23 -0800 |
commit | 4185c26e9f6ff6f5395c326e4fb71f60b8d1656e (patch) | |
tree | 6785031207a1052fddf1b1a19ce41668e8ae6492 | |
parent | f51edb0687dba2d6f6b07f8697c91f2df2f4cdda (diff) |
changed write and read functions to support binary data
both functions were only supporting text data and needed to be
changed to support binary data.
The issue was found while testing libgfapi-python with smallfile
(https://github.com/bengland2/smallfile).
When calling gflfs_write, ctypes has no problem converting strings
to the correct C data type, but is unable to handle bytearray:
b = bytearray(1024)
with vol.create(path, os.O_WRONLY | os.O_EXCL, 0644) as fd:
fd.write(b)
It would throw this error:
exception: argument 2: <type 'exceptions.TypeError'>:
Don't know how to convert parameter 2
reference: http://docs.python.org/2/library/ctypes.html#calling-functions-continued
Change-Id: Ia2bb47343880cbf7121fed9510e4cfa085fe23bd
Signed-off-by: Thiago da Silva <thiago@redhat.com>
-rw-r--r-- | gluster/gfapi.py | 12 | ||||
-rw-r--r-- | test/functional/libgfapi-python-tests.py | 34 | ||||
-rw-r--r-- | test/unit/gluster/test_gfapi.py | 12 |
3 files changed, 52 insertions, 6 deletions
diff --git a/gluster/gfapi.py b/gluster/gfapi.py index 7d09102..b1f14d2 100644 --- a/gluster/gfapi.py +++ b/gluster/gfapi.py @@ -101,15 +101,21 @@ class File(object): rbuf = ctypes.create_string_buffer(buflen) ret = api.glfs_read(self.fd, rbuf, buflen, flags) if ret > 0: - return rbuf.value[:ret] + return rbuf elif ret < 0: err = ctypes.get_errno() raise OSError(err, os.strerror(err)) else: return ret - def write(self, data, flags=0): - ret = api.glfs_write(self.fd, data, len(data), flags) + def write(self, data): + # creating a ctypes.c_ubyte buffer to handle converting bytearray + # to the required C data type + if type(data) is bytearray: + buf = (ctypes.c_ubyte * len(data)).from_buffer(data) + else: + buf = data + ret = api.glfs_write(self.fd, buf, len(buf)) if ret < 0: err = ctypes.get_errno() raise OSError(err, os.strerror(err)) diff --git a/test/functional/libgfapi-python-tests.py b/test/functional/libgfapi-python-tests.py index d0703df..08742f3 100644 --- a/test/functional/libgfapi-python-tests.py +++ b/test/functional/libgfapi-python-tests.py @@ -7,6 +7,36 @@ from nose import SkipTest from gluster import gfapi +class BinFileOpsTest(unittest.TestCase): + + vol = None + path = None + data = None + + @classmethod + def setUpClass(cls): + cls.vol = gfapi.Volume("gfshost", "test") + cls.vol.set_logging("/dev/null", 7) + cls.vol.mount() + + @classmethod + def tearDownClass(cls): + cls.vol = None + + def setUp(self): + self.data = bytearray([(k % 128) for k in range(0, 1024)]) + self.path = self._testMethodName + ".io" + with self.vol.creat(self.path, os.O_WRONLY | os.O_EXCL, 0644) as fd: + fd.write(self.data) + + def test_bin_open_and_read(self): + with self.vol.open(self.path, os.O_RDONLY) as fd: + self.assertTrue(isinstance(fd, gfapi.File)) + buf = fd.read(len(self.data)) + self.assertFalse(isinstance(buf, types.IntType)) + self.assertEqual(buf, self.data) + + class FileOpsTest(unittest.TestCase): vol = None @@ -27,7 +57,7 @@ class FileOpsTest(unittest.TestCase): self.data = loremipsum.get_sentence() self.path = self._testMethodName + ".io" with self.vol.creat(self.path, os.O_WRONLY | os.O_EXCL, 0644) as fd: - rc = fd.write(self.data) + fd.write(self.data) def tearDown(self): self.path = None @@ -38,7 +68,7 @@ class FileOpsTest(unittest.TestCase): self.assertTrue(isinstance(fd, gfapi.File)) buf = fd.read(len(self.data)) self.assertFalse(isinstance(buf, types.IntType)) - self.assertEqual(buf, self.data) + self.assertEqual(buf.value, self.data) def test_lstat(self): sb = self.vol.lstat(self.path) diff --git a/test/unit/gluster/test_gfapi.py b/test/unit/gluster/test_gfapi.py index 6270148..549357b 100644 --- a/test/unit/gluster/test_gfapi.py +++ b/test/unit/gluster/test_gfapi.py @@ -56,7 +56,7 @@ class TestFile(unittest.TestCase): with patch("gluster.gfapi.api.glfs_read", _mock_glfs_read): fd = gfapi.File(2) b = fd.read(5) - self.assertEqual(b, "hello") + self.assertEqual(b.value, "hello") def test_read_fail_exception(self): mock_glfs_read = Mock() @@ -84,6 +84,16 @@ class TestFile(unittest.TestCase): ret = fd.write("hello") self.assertEqual(ret, 5) + def test_write_binary_success(self): + mock_glfs_write = Mock() + mock_glfs_write.return_value = 3 + + with patch("gluster.gfapi.api.glfs_write", mock_glfs_write): + fd = gfapi.File(2) + b = bytearray(3) + ret = fd.write(b) + self.assertEqual(ret, 3) + def test_write_fail_exception(self): mock_glfs_write = Mock() mock_glfs_write.return_value = -1 |