From patchwork Sun Feb 24 13:06:26 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Noa Osherovich X-Patchwork-Id: 10827929 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 03CDE13B5 for ; Sun, 24 Feb 2019 13:08:55 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E71DB2B4E5 for ; Sun, 24 Feb 2019 13:08:54 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id CE0812B532; Sun, 24 Feb 2019 13:08:54 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI,UNPARSEABLE_RELAY autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A2ABD2B4FD for ; Sun, 24 Feb 2019 13:08:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728256AbfBXNIw (ORCPT ); Sun, 24 Feb 2019 08:08:52 -0500 Received: from mail-il-dmz.mellanox.com ([193.47.165.129]:50483 "EHLO mellanox.co.il" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1726835AbfBXNIw (ORCPT ); Sun, 24 Feb 2019 08:08:52 -0500 Received: from Internal Mail-Server by MTLPINE1 (envelope-from noaos@mellanox.com) with ESMTPS (AES256-SHA encrypted); 24 Feb 2019 15:06:49 +0200 Received: from reg-l-vrt-059-009.mtl.labs.mlnx (reg-l-vrt-059-009.mtl.labs.mlnx [10.135.59.9]) by labmailer.mlnx (8.13.8/8.13.8) with ESMTP id x1OD6mfb026210; Sun, 24 Feb 2019 15:06:48 +0200 From: Noa Osherovich To: leonro@mellanox.com, jgg@mellanox.com, dledford@redhat.com Cc: linux-rdma@vger.kernel.org, Noa Osherovich Subject: [PATCH rdma-core 07/19] pyverbs: Add unittests for MR class Date: Sun, 24 Feb 2019 15:06:26 +0200 Message-Id: <20190224130638.31848-8-noaos@mellanox.com> X-Mailer: git-send-email 2.17.2 In-Reply-To: <20190224130638.31848-1-noaos@mellanox.com> References: <20190224130638.31848-1-noaos@mellanox.com> Sender: linux-rdma-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-rdma@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This patch adds some basic unittests for MR class' API. Signed-off-by: Noa Osherovich --- 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 diff --git a/pyverbs/CMakeLists.txt b/pyverbs/CMakeLists.txt index b660b46f170a..18056d6fcd65 100644 --- a/pyverbs/CMakeLists.txt +++ b/pyverbs/CMakeLists.txt @@ -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( diff --git a/pyverbs/tests/mr.py b/pyverbs/tests/mr.py new file mode 100644 index 000000000000..409cd41e3c06 --- /dev/null +++ b/pyverbs/tests/mr.py @@ -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 + diff --git a/pyverbs/tests/utils.py b/pyverbs/tests/utils.py new file mode 100644 index 000000000000..3281a326b324 --- /dev/null +++ b/pyverbs/tests/utils.py @@ -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))