@@ -19,7 +19,9 @@ rdma_python_module(pyverbs
rdma_python_test(pyverbs/tests
tests/__init__.py
tests/device.py
+ tests/mr.py
tests/pd.py
+ tests/utils.py
)
rdma_internal_binary(
new file mode 100644
@@ -0,0 +1,146 @@
+# SPDX-License-Identifier: (GPL-2.0 OR Linux-OpenIB)
+# Copyright (c) 2019, Mellanox Technologies. All rights reserved. See COPYING file
+import unittest
+import random
+
+from pyverbs.pyverbs_error import PyverbsRDMAError
+from pyverbs.base import PyverbsRDMAErrno
+import pyverbs.tests.utils as u
+import pyverbs.device as d
+from pyverbs.mr import MR
+from pyverbs.pd import PD
+import pyverbs.enums as e
+
+MAX_IO_LEN = 1048576
+
+
+class mr_test(unittest.TestCase):
+ """
+ Test various functionalities of the MR class.
+ """
+ def test_reg_mr(self):
+ """ Test ibv_reg_mr() """
+ lst = d.get_device_list()
+ for dev in lst:
+ with d.Context(name=dev.name.decode()) as ctx:
+ with PD(ctx) as pd:
+ with MR(pd, u.get_mr_length(), u.get_access_flags()) as mr:
+ pass
+
+ def test_dereg_mr(self):
+ """ Test ibv_dereg_mr() """
+ lst = d.get_device_list()
+ for dev in lst:
+ with d.Context(name=dev.name.decode()) as ctx:
+ with PD(ctx) as pd:
+ with MR(pd, u.get_mr_length(), u.get_access_flags()) as mr:
+ mr.close()
+
+ def test_reg_mr_bad_flow(self):
+ """ Verify that trying to register a MR with None PD fails """
+ try:
+ mr = MR(None, random.randint(0, 10000), u.get_access_flags())
+ except TypeError as te:
+ assert 'expected pyverbs.pd.PD' in te.args[0]
+ assert 'got NoneType' in te.args[0]
+ else:
+ raise PyverbsRDMAErrno('Created a MR with None PD')
+
+ def test_dereg_mr_twice(self):
+ """ Verify that explicit call to MR's close() doesn't fails """
+ lst = d.get_device_list()
+ for dev in lst:
+ with d.Context(name=dev.name.decode()) as ctx:
+ with PD(ctx) as pd:
+ with MR(pd, u.get_mr_length(), u.get_access_flags()) as mr:
+ # Pyverbs supports multiple destruction of objects, we are
+ # not expecting an exception here.
+ mr.close()
+ mr.close()
+
+ def test_reg_mr_bad_flags(self):
+ """ Verify that illegal flags combination fails as expected """
+ lst = d.get_device_list()
+ for dev in lst:
+ with d.Context(name=dev.name.decode()) as ctx:
+ with PD(ctx) as pd:
+ flags = random.sample([e.IBV_ACCESS_REMOTE_WRITE,
+ e.IBV_ACCESS_REMOTE_ATOMIC],
+ random.randint(1, 2))
+ mr_flags = 0
+ for i in flags:
+ mr_flags += i.value
+ try:
+ mr = MR(pd, u.get_mr_length(), mr_flags)
+ except PyverbsRDMAError as err:
+ assert 'Failed to register a MR' in err.args[0]
+ else:
+ raise PyverbsRDMAError('Registered a MR with illegal falgs')
+
+ def test_write(self):
+ """
+ Test writing to MR's buffer
+ """
+ lst = d.get_device_list()
+ for dev in lst:
+ with d.Context(name=dev.name.decode()) as ctx:
+ with PD(ctx) as pd:
+ mr_len = u.get_mr_length()
+ with MR(pd, mr_len, u.get_access_flags()) as mr:
+ write_len = min(random.randint(1, MAX_IO_LEN), mr_len)
+ mr.write(u.get_data(write_len), write_len)
+
+ def test_read(self):
+ """
+ Test reading from MR's buffer
+ """
+ lst = d.get_device_list()
+ for dev in lst:
+ with d.Context(name=dev.name.decode()) as ctx:
+ with PD(ctx) as pd:
+ mr_len = u.get_mr_length()
+ with MR(pd, mr_len, u.get_access_flags()) as mr:
+ write_len = min(random.randint(1, MAX_IO_LEN), mr_len)
+ write_str = u.get_data(write_len)
+ mr.write(write_str, write_len)
+ read_len = random.randint(1, write_len)
+ offset = random.randint(0, write_len-read_len)
+ read_str = mr.read(read_len, offset).decode()
+ assert read_str in write_str
+
+ def test_lkey(self):
+ """
+ Test reading lkey property
+ """
+ lst = d.get_device_list()
+ for dev in lst:
+ with d.Context(name=dev.name.decode()) as ctx:
+ with PD(ctx) as pd:
+ length = u.get_mr_length()
+ with MR(pd, length, u.get_access_flags()) as mr:
+ lkey = mr.lkey
+
+ def test_rkey(self):
+ """
+ Test reading rkey property
+ """
+ lst = d.get_device_list()
+ for dev in lst:
+ with d.Context(name=dev.name.decode()) as ctx:
+ with PD(ctx) as pd:
+ length = u.get_mr_length()
+ with MR(pd, length, u.get_access_flags()) as mr:
+ rkey = mr.rkey
+
+ def test_buffer(self):
+ """
+ Test reading buf property
+ """
+ lst = d.get_device_list()
+ for dev in lst:
+ with d.Context(name=dev.name.decode()) as ctx:
+ with PD(ctx) as pd:
+ length = u.get_mr_length()
+ with MR(pd, length, u.get_access_flags()) as mr:
+ buf = mr.buf
+
new file mode 100644
@@ -0,0 +1,28 @@
+# SPDX-License-Identifier: (GPL-2.0 OR Linux-OpenIB)
+# Copyright (c) 2019, Mellanox Technologies. All rights reserved. See COPYING file
+from string import ascii_lowercase as al
+import random
+import pyverbs.enums as e
+
+MAX_MR_SIZE = 4194304
+
+def get_mr_length():
+ # Allocating large buffers typically fails
+ return random.randint(0, MAX_MR_SIZE)
+
+
+def get_access_flags():
+ vals = list(e.ibv_access_flags)
+ selected = random.sample(vals, random.randint(1, 7))
+ # Remote write / remote atomic are not allowed without local write
+ if e.IBV_ACCESS_REMOTE_WRITE in selected or e.IBV_ACCESS_REMOTE_ATOMIC in selected:
+ if not e.IBV_ACCESS_LOCAL_WRITE in selected:
+ selected.append(e.IBV_ACCESS_LOCAL_WRITE)
+ flags = 0
+ for i in selected:
+ flags += i.value
+ return flags
+
+
+def get_data(length):
+ return ''.join(random.choice(al) for i in range(length))
This patch adds some basic unittests for MR class' API. Signed-off-by: Noa Osherovich <noaos@mellanox.com> --- pyverbs/CMakeLists.txt | 2 + pyverbs/tests/mr.py | 146 +++++++++++++++++++++++++++++++++++++++++ pyverbs/tests/utils.py | 28 ++++++++ 3 files changed, 176 insertions(+) create mode 100644 pyverbs/tests/mr.py create mode 100644 pyverbs/tests/utils.py