Skip to content
Draft
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
1 change: 1 addition & 0 deletions lib/platform/linux/platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ static void * dispatch_indication(void * unused)

// Force a garbage collect (to be sure it's called even if no frag are received)
reassembly_garbage_collect();
ssr_purge_expired();

// Check if we wake up but nothing in queue
if (m_queue_empty)
Expand Down
70 changes: 53 additions & 17 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ set(CMAKE_BUILD_TYPE RelWithDebInfo)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

add_compile_options(-Wall -Werror -Wextra)
option(WPC_ENABLE_COVERAGE "Enable coverage instrumentation for unit-test builds" OFF)

set(WPC_LIB_DIR "${CMAKE_CURRENT_LIST_DIR}/../lib/")
set(WPC_INTERNAL_INCLUDE_DIRS
Expand All @@ -15,6 +16,19 @@ set(WPC_INTERNAL_INCLUDE_DIRS
${WPC_LIB_DIR}/wpc/include
)

function(enable_coverage_if_requested target_name)
if(NOT WPC_ENABLE_COVERAGE)
return()
endif()

if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
target_compile_options(${target_name} PRIVATE -O0 -g --coverage)
target_link_options(${target_name} PRIVATE --coverage)
else()
message(WARNING "WPC_ENABLE_COVERAGE is only supported with GCC or Clang")
endif()
endfunction()

include(FetchContent)
FetchContent_Declare(
wpc-lib
Expand All @@ -28,6 +42,9 @@ FetchContent_Declare(
)
FetchContent_MakeAvailable(wpc-lib googletest)

enable_coverage_if_requested(wpc)
enable_coverage_if_requested(wpc_platform)

enable_testing()

add_executable(${CMAKE_PROJECT_NAME}
Expand Down Expand Up @@ -75,41 +92,60 @@ target_include_directories(meshAPI_ssr_unit PRIVATE
target_compile_options(meshAPI_ssr_unit PRIVATE -ffunction-sections -fdata-sections)
target_link_options(meshAPI_ssr_unit PRIVATE -Wl,--gc-sections)

enable_coverage_if_requested(meshAPI_ssr_unit)
gtest_discover_tests(meshAPI_ssr_unit)

add_executable(meshAPI_wpc_internal_unit
${WPC_LIB_DIR}/wpc/wpc_internal.c
${CMAKE_CURRENT_LIST_DIR}/wpc_internal_ssr_unit_tests.cpp
add_executable(meshAPI_wpc_unit
${WPC_LIB_DIR}/wpc/wpc.c
${WPC_LIB_DIR}/wpc/wpc_ssr.c
${CMAKE_CURRENT_LIST_DIR}/wpc_ssr_unit_tests.cpp
)

target_link_libraries(meshAPI_wpc_internal_unit
target_link_libraries(meshAPI_wpc_unit
GTest::gtest_main
)

target_include_directories(meshAPI_wpc_internal_unit PRIVATE
target_include_directories(meshAPI_wpc_unit PRIVATE
${WPC_INTERNAL_INCLUDE_DIRS}
)

target_compile_options(meshAPI_wpc_internal_unit PRIVATE -ffunction-sections -fdata-sections)
target_link_options(meshAPI_wpc_internal_unit PRIVATE -Wl,--gc-sections)
target_compile_options(meshAPI_wpc_unit PRIVATE -ffunction-sections -fdata-sections)
target_link_options(meshAPI_wpc_unit PRIVATE -Wl,--gc-sections)

gtest_discover_tests(meshAPI_wpc_internal_unit)
enable_coverage_if_requested(meshAPI_wpc_unit)
gtest_discover_tests(meshAPI_wpc_unit)

add_executable(meshAPI_wpc_unit
${WPC_LIB_DIR}/wpc/wpc.c
${WPC_LIB_DIR}/wpc/wpc_ssr.c
${CMAKE_CURRENT_LIST_DIR}/wpc_ssr_unit_tests.cpp
add_executable(meshAPI_platform_unit
${CMAKE_CURRENT_LIST_DIR}/platform_ssr_unit_tests.cpp
)

target_link_libraries(meshAPI_wpc_unit
target_link_libraries(meshAPI_platform_unit
GTest::gtest_main
wpc_platform
)

target_include_directories(meshAPI_wpc_unit PRIVATE
target_include_directories(meshAPI_platform_unit PRIVATE
${WPC_INTERNAL_INCLUDE_DIRS}
)

target_compile_options(meshAPI_wpc_unit PRIVATE -ffunction-sections -fdata-sections)
target_link_options(meshAPI_wpc_unit PRIVATE -Wl,--gc-sections)
enable_coverage_if_requested(meshAPI_platform_unit)
gtest_discover_tests(meshAPI_platform_unit)

gtest_discover_tests(meshAPI_wpc_unit)
add_executable(meshAPI_wpc_internal_unit
${WPC_LIB_DIR}/wpc/wpc_internal.c
${CMAKE_CURRENT_LIST_DIR}/wpc_internal_ssr_unit_tests.cpp
)

target_link_libraries(meshAPI_wpc_internal_unit
GTest::gtest_main
)

target_include_directories(meshAPI_wpc_internal_unit PRIVATE
${WPC_INTERNAL_INCLUDE_DIRS}
)

target_compile_options(meshAPI_wpc_internal_unit PRIVATE -ffunction-sections -fdata-sections)
target_link_options(meshAPI_wpc_internal_unit PRIVATE -Wl,--gc-sections)

enable_coverage_if_requested(meshAPI_wpc_internal_unit)
gtest_discover_tests(meshAPI_wpc_internal_unit)
71 changes: 71 additions & 0 deletions test/platform_ssr_unit_tests.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#include <gtest/gtest.h>

#include <atomic>
#include <chrono>
#include <thread>

#define _Static_assert static_assert
extern "C"
{
#include "platform.h"
}

namespace
{
std::atomic<int> g_gc_calls{0};
std::atomic<int> g_ssr_purge_calls{0};

int no_indication(unsigned int max_ind, onIndicationReceivedLocked_cb_f cb_locked)
{
(void) max_ind;
(void) cb_locked;
return 0;
}

void ignore_indication(wpc_frame_t * frame, unsigned long long timestamp_ms)
{
(void) frame;
(void) timestamp_ms;
}

bool wait_for(std::atomic<int> & counter, int expected, std::chrono::milliseconds timeout)
{
const auto deadline = std::chrono::steady_clock::now() + timeout;
while (std::chrono::steady_clock::now() < deadline)
{
if (counter.load() >= expected)
{
return true;
}
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

return counter.load() >= expected;
}
} // namespace

extern "C" bool reassembly_is_queue_empty(void)
{
return true;
}

extern "C" void reassembly_garbage_collect(void)
{
g_gc_calls.fetch_add(1);
}

extern "C" void ssr_purge_expired(void)
{
g_ssr_purge_calls.fetch_add(1);
}

TEST(PlatformSsrUnitTest, IdleDispatchWakeupPurgesExpiredSsrRoutes)
{
g_gc_calls.store(0);
g_ssr_purge_calls.store(0);

ASSERT_TRUE(Platform_init(no_indication, ignore_indication));
EXPECT_TRUE(wait_for(g_gc_calls, 1, std::chrono::milliseconds(6500)));
EXPECT_TRUE(wait_for(g_ssr_purge_calls, 1, std::chrono::milliseconds(6500)));
Platform_close();
}
Loading