Как протестировать код RDMA без реального оборудования?

У меня есть код C++, который использует глаголы infiniband для связи RDMA. Мне нужно выполнить модульное тестирование этого кода, и, таким образом, вызовы функций, связанные с RDMA, такие как ibv_get_device_list(), должны успешно выполняться без какого-либо реального оборудования. Насколько я понимаю, я могу сделать следующее:

  1. Создайте свое собственное определение каждой функции, чтобы возвращать желаемое значение, и свяжите это пользовательское определение вместо infinband/verbs.h во время тестирования. - оказалось очень утомительно
  2. Создайте интерфейс и предоставьте реальную и фальшивую реализации каждой функции. Настоящая просто назвала бы бесконечные глаголы. - Не могу этого сделать, так как потребуется слишком много изменений в исходном коде.
  3. Используйте Soft-RoCE — мне нужно использовать одну и ту же машину в качестве клиента и сервера, чего я не смог сделать.

Можно ли использовать gmock для имитации этих функций? Какие еще варианты я могу рассмотреть?


person xyz123    schedule 05.05.2020    source источник


Ответы (2)


Путь номер 2. Я собираюсь оспорить это утверждение:

Не могу этого сделать, так как потребуется слишком много изменений в исходном коде.

Если все пойдет хорошо, в вашей среде IDE есть "глобальный поиск и замена", который можно использовать.

Давайте найдем самый простой способ абстрагировать ваш код с минимальным количеством разрушительных изменений:

Начните с определения класса, который просто обертывает эти вызовы функций библиотеки C:

 class RDMA
 {
 public:
     virtual struct ibv_device **ibv_get_device_list(int *num_devices)
     {
          return ::ibv_get_device_list(num_devices);
     }

     virtual void ibv_free_device_list(struct ibv_device **list)
     {
           return ::ibv_free_device_list(list);
     }


     virtual uint64_t ibv_get_device_guid(struct ibv_device *device)
     {
          return ::ibv_get_device_guid(device);
     }
 };

Расширьте вышеуказанный класс любыми другими связанными вызовами, которые могут вам понадобиться.

В глобальной области объявите экземпляр вышеуказанного класса и указатель на него:

 RDMA g_product_code_rdma;
 RDMA* g_ptrRMDA = &g_product_code_rdma;

Замените все вызовы вашего кода продукта функциями ibv, чтобы они вызывали класс через глобальный указатель. То есть изменить это:

 ibv_free_device_list(&list);

вызываться как:

 g_ptrRMDA->ibv_free_device_list(&list);

В качестве альтернативы вы можете объявить вспомогательные функции:

ibv_device **global_ibv_get_device_list(int *num_devices)
{
     return g_ptrRDMA->ibv_get_device_list(num_devices);
}

А затем замените все свои вызовы на использование новой «глобальной» версии. Простой сценарий sed\awk или просто использование вашей IDE для глобального поиска и замены этих вызовов функций было бы самым простым подходом.

На этом этапе ваш код продукта работает так же, как и раньше.

в своих модульных тестах вы просто объявляете класс MockRDMA, который наследуется от класса RDMA выше.

 class MockRDMA : public RDMA
 {
 public:

     ibv_device **ibv_get_device_list(int *num_devices) override
     {
          // return a fake list of devices
     }

     virtual void ibv_free_device_list(struct ibv_device **list) override
     {
          return;
     }


     virtual uint64_t ibv_get_device_guid(struct ibv_device *device) override
     {
          return 0x012345678;
     }
 };

Затем вы просто говорите это в начале ваших модульных тестов:

    MockRDMA mock;
    g_ptrRDMA = &mock;

Пример:

bool test_that_thing()
{
    RDMA* original = g_ptrRDMA;
    MockRDMA mock;
    g_ptrRDMA = &mock;

    // test code to validate the code that depends on those RDMA calls

    // restore the RDMA class
    g_ptrRDMA = original;
    return result;

}
person selbie    schedule 05.05.2020

Если вы решите выбрать вариант 3 (SoftRoCE), вполне возможно, что клиент и сервер будут находиться на одном хосте. Вы можете попробовать vagrant box, который я создал, чтобы упростить тестирование SoftRoCE на виртуальной машине.

person haggai_e    schedule 06.05.2020