Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 72 additions & 0 deletions .github/workflows/vrtd-unit-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# ##################################################################################################
# The MIT License (MIT)
# Copyright (c) 2025-2026 Advanced Micro Devices, Inc. All rights reserved.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy of this software
# and associated documentation files (the "Software"), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge, publish, distribute,
# sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all copies or
# substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
# NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# ##################################################################################################

name: VRTD unit testing

on:
push:
branches:
- main
- dev
pull_request:

jobs:
vrtd_unit_tests:
runs-on: ubuntu-24.04
permissions: { contents: read }

steps:
- name: Checkout code
uses: actions/checkout@v6
with:
submodules: "true"

- name: Install dependencies
run: |
sudo apt update
sudo apt install -y cmake pkg-config ninja-build \
libsystemd-dev libinih-dev lcov

- name: Build and run VRTD unit tests
run: |
mkdir vrt/vrtd/build
cd vrt/vrtd/build
cmake -DVRTD_BUILD_TESTS=1 -DVRTD_INCLUDE_LIBSLASH=1 -DENABLE_COVERAGE=1 ..
make unit_tests -j$(nproc)
export LD_LIBRARY_PATH=$(pwd)/libslash/src/:$LD_LIBRARY_PATH
cd tests && ctest --output-on-failure

- name: Generate coverage report
run: |
cd vrt/vrtd/build
lcov --capture --directory . --output-file coverage.info \
--ignore-errors mismatch --ignore-errors negative
lcov --remove coverage.info \
'/usr/*' '*/build/_deps/*' '*/tests/*' \
--output-file coverage.filtered.info \
--ignore-errors unused
genhtml coverage.filtered.info --output-directory coverage-report
lcov --list coverage.filtered.info

- name: Upload coverage report
uses: actions/upload-artifact@v4
with:
name: vrtd-coverage-report
path: vrt/vrtd/build/coverage-report/
22 changes: 21 additions & 1 deletion driver/libslash/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,17 +34,37 @@ message(STATUS "LIBSLASH version: ${LIBSLASH_VERSION} (${LIBSLASH_VERSION_MAJOR}

project(libslash
VERSION ${LIBSLASH_VERSION}
LANGUAGES C
LANGUAGES C CXX
)

# Allow user to choose shared vs static (standard CMake variable)
option(BUILD_SHARED_LIBS "Build shared libraries" ON)
option(LIBSLASH_BUILD_TESTS "Build unit tests" OFF)

option(ENABLE_SANITIZERS "Build with AddressSanitizer and UBSan" OFF)
if(ENABLE_SANITIZERS)
add_compile_options(-fsanitize=address,undefined -fno-omit-frame-pointer)
add_link_options(-fsanitize=address,undefined)
endif()

option(ENABLE_COVERAGE "Build with gcov coverage instrumentation" OFF)
if(ENABLE_COVERAGE)
if(ENABLE_SANITIZERS)
message(FATAL_ERROR "ENABLE_COVERAGE and ENABLE_SANITIZERS cannot be used together")
endif()
add_compile_options(--coverage -fno-inline)
add_link_options(--coverage)
endif()

include(GNUInstallDirs)
include(CMakePackageConfigHelpers)

add_subdirectory(src)

if(LIBSLASH_BUILD_TESTS)
add_subdirectory(tests)
endif()

# -------- Installation: headers and library --------
# Public headers are under include/ (layout: include/slash/*.h)
install(
Expand Down
9 changes: 5 additions & 4 deletions driver/libslash/include/slash/qdma.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@

#include "uapi/slash_interface.h"

#include <stdbool.h>
#include <stdint.h>

#ifdef __cplusplus
Expand All @@ -55,11 +54,13 @@ extern "C" {
/**
* @brief Handle to an open QDMA device.
*
* \@mock is reserved for future use and is always set to false.
* \@priv is NULL for real hardware handles. When slash_qdma_open() is
* called with "\@mock", it points to an internal slash_qdma_mock context;
* callers should treat it as opaque.
*/
struct slash_qdma {
int fd; /**< File descriptor for the QDMA character device. */
bool mock; /**< Reserved for mock support. */
int fd; /**< File descriptor for the QDMA character device (-1 in mock mode). */
void *priv; /**< Opaque mock context, or NULL for real hardware. */
};

/**
Expand Down
1 change: 1 addition & 0 deletions driver/libslash/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ add_library(slash
${CMAKE_CURRENT_SOURCE_DIR}/ctldev_mock.c
${CMAKE_CURRENT_SOURCE_DIR}/hotplug.c
${CMAKE_CURRENT_SOURCE_DIR}/qdma.c
${CMAKE_CURRENT_SOURCE_DIR}/qdma_mock.c
)

# Provide an alias target with namespace (nice for internal use too)
Expand Down
39 changes: 37 additions & 2 deletions driver/libslash/src/qdma.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,15 @@

#include <slash/qdma.h>

#include "qdma_mock.h"

#include <errno.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>

#include <sys/ioctl.h>

Expand All @@ -47,6 +50,10 @@ struct slash_qdma *slash_qdma_open(const char *path)
return NULL;
}

if (strcmp(path, "@mock") == 0) {
return slash_qdma_mock_open();
}

qdma = calloc(1, sizeof(*qdma));
if (qdma == NULL) {
return NULL;
Expand All @@ -58,8 +65,6 @@ struct slash_qdma *slash_qdma_open(const char *path)
return NULL;
}

qdma->mock = false;

return qdma;
}

Expand All @@ -72,6 +77,10 @@ int slash_qdma_close(struct slash_qdma *qdma)
return -1;
}

if (qdma->priv) {
return slash_qdma_mock_close(qdma);
}

ret = 0;
if (qdma->fd >= 0 && close(qdma->fd) != 0) {
ret = -1;
Expand All @@ -93,6 +102,10 @@ int slash_qdma_info_read(struct slash_qdma *qdma, struct slash_qdma_info *info)
return -1;
}

if (qdma->priv) {
return slash_qdma_mock_info_read(qdma, info);
}

memset(&tmp, 0, sizeof(tmp));
tmp.size = sizeof(tmp);

Expand Down Expand Up @@ -125,6 +138,10 @@ int slash_qdma_qpair_add(struct slash_qdma *qdma,
return -1;
}

if (qdma->priv) {
return slash_qdma_mock_qpair_add(qdma, req);
}

memset(&tmp, 0, sizeof(tmp));
tmp.size = sizeof(tmp);
tmp.mode = req->mode;
Expand Down Expand Up @@ -162,6 +179,20 @@ static int slash_qdma_qpair_op(struct slash_qdma *qdma,
return -1;
}

if (qdma->priv) {
switch (op) {
case SLASH_QDMA_QUEUE_OP_START:
return slash_qdma_mock_qpair_start(qdma, qid);
case SLASH_QDMA_QUEUE_OP_STOP:
return slash_qdma_mock_qpair_stop(qdma, qid);
case SLASH_QDMA_QUEUE_OP_DEL:
return slash_qdma_mock_qpair_del(qdma, qid);
default:
errno = EINVAL;
return -1;
}
}

memset(&req, 0, sizeof(req));
req.size = sizeof(req);
req.qid = qid;
Expand Down Expand Up @@ -200,6 +231,10 @@ int slash_qdma_qpair_get_fd(struct slash_qdma *qdma, uint32_t qid, int flags)
return -1;
}

if (qdma->priv) {
return slash_qdma_mock_qpair_get_fd(qdma, qid, flags);
}

memset(&req, 0, sizeof(req));
req.size = sizeof(req);
req.qid = qid;
Expand Down
Loading