# SPDX-License-Identifier: (GPL-2.0 OR Linux-OpenIB)
# Copyright (c) 2020 Mellanox Technologies, Inc. All rights reserved. See COPYING file
"""
Test module for Shared PD.
"""
import unittest
import errno
import os

from tests.test_qpex import QpExRCRDMAWrite
from tests.base import RDMATestCase
from pyverbs.device import Context
from pyverbs.pd import PD
from pyverbs.mr import MR
from pyverbs.libibverbs_enums import ibv_wr_opcode
import tests.utils as u


def get_import_res_class(base_class):
    """
    This function creates a class that inherits base_class of any BaseResources
    type. Its purpose is to behave exactly as base_class does, except for the
    objects creation, which instead of creating context, PD and MR, it imports
    them. Hence the returned class must be initialized with (cmd_fd, pd_handle,
    mr_handle, mr_addr, **kwargs), while kwargs are the arguments needed
    (if any) for base_class. In addition it has unimport_resources() method
    which unimprot all the resources and closes the imported PD object.
    :param base_class: The base resources class to inherit from
    :return: ImportResources(cmd_fd, pd_handle, mr_handle, mr_addr, **kwargs)
             class
    """
    class ImportResources(base_class):
        def __init__(self, cmd_fd, pd_handle, mr_handle, mr_addr=None, **kwargs):
            self.cmd_fd = cmd_fd
            self.pd_handle = pd_handle
            self.mr_handle = mr_handle
            self.mr_addr = mr_addr
            super(ImportResources, self).__init__(**kwargs)

        def create_context(self):
            try:
                self.ctx = Context(cmd_fd=self.cmd_fd)
            except u.PyverbsRDMAError as ex:
                if ex.error_code in [errno.EOPNOTSUPP, errno.EPROTONOSUPPORT]:
                    raise unittest.SkipTest('Importing a device is not supported')
                raise ex

        def create_pd(self):
            self.pd = PD(self.ctx, handle=self.pd_handle)

        def create_mr(self):
            self.mr = MR(self.pd, handle=self.mr_handle, address=self.mr_addr)

        def unimport_resources(self):
            self.mr.unimport()
            self.pd.unimport()
            self.pd.close()

    return ImportResources


class SharedPDTestCase(RDMATestCase):
    def setUp(self):
        super().setUp()
        self.iters = 10
        self.server_res = None
        self.imported_res = []

    def tearDown(self):
        for res in self.imported_res:
            res.unimport_resources()
        super().tearDown()

    def test_imported_rc_ex_rdma_write(self):
        setup_params = {'dev_name': self.dev_name, 'ib_port': self.ib_port,
                        'gid_index': self.gid_index}
        self.server_res = QpExRCRDMAWrite(**setup_params)
        cmd_fd_dup = os.dup(self.server_res.ctx.cmd_fd)
        import_cls = get_import_res_class(QpExRCRDMAWrite)
        server_import = import_cls(
            cmd_fd_dup, self.server_res.pd.handle, self.server_res.mr.handle,
            # The imported MR's address is NULL, so using the address of the
            # "main" MR object to be able to validate the message
            self.server_res.mr.buf,
            **setup_params)
        self.imported_res.append(server_import)
        client = QpExRCRDMAWrite(**setup_params)
        client.pre_run(server_import.psns, server_import.qps_num)
        server_import.pre_run(client.psns, client.qps_num)
        client.rkey = server_import.mr.rkey
        server_import.rkey = client.mr.rkey
        client.raddr = server_import.mr.buf
        server_import.raddr = client.mr.buf
        u.rdma_traffic(client, server_import, self.iters, self.gid_index,
                       self.ib_port, send_op=ibv_wr_opcode.IBV_WR_RDMA_WRITE, new_send=True)
