summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThiago da Silva <thiago@redhat.com>2014-02-21 18:23:29 -0500
committerGerrit Code Review <review@dev.gluster.org>2014-02-24 19:25:23 -0800
commit4185c26e9f6ff6f5395c326e4fb71f60b8d1656e (patch)
tree6785031207a1052fddf1b1a19ce41668e8ae6492
parentf51edb0687dba2d6f6b07f8697c91f2df2f4cdda (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.py12
-rw-r--r--test/functional/libgfapi-python-tests.py34
-rw-r--r--test/unit/gluster/test_gfapi.py12
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