Skip to content

Commit 0912ef3

Browse files
add test public and migrate udpard fragment seek test there
1 parent d8fe974 commit 0912ef3

File tree

6 files changed

+111
-126
lines changed

6 files changed

+111
-126
lines changed

libudpard/udpard.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
// ReSharper disable CppDFATimeOver
77

88
#include "udpard.h"
9-
#include <string.h>
109
#include <assert.h>
10+
#include <string.h>
1111

1212
/// Define this macro to include build configuration header.
1313
/// Usage example with CMake: "-DUDPARD_CONFIG_HEADER=\"${CMAKE_CURRENT_SOURCE_DIR}/my_udpard_config.h\""
@@ -18,7 +18,6 @@
1818
/// By default, this macro resolves to the standard assert(). The user can redefine this if necessary.
1919
/// To disable assertion checks completely, make it expand into `(void)(0)`.
2020
#ifndef UDPARD_ASSERT
21-
// Intentional violation of MISRA: inclusion not at the top of the file to eliminate unnecessary dependency on assert.h.
2221
// Intentional violation of MISRA: assertion macro cannot be replaced with a function definition.
2322
#define UDPARD_ASSERT(x) assert(x) // NOSONAR
2423
#endif
@@ -122,6 +121,7 @@ static int32_t cavl_compare_fragment_end(const void* const user, const udpard_tr
122121
return 0; // clang-format on
123122
}
124123

124+
// NOLINTNEXTLINE(misc-no-recursion)
125125
void udpard_fragment_free_all(udpard_fragment_t* const frag, const udpard_mem_resource_t fragment_memory_resource)
126126
{
127127
if (frag != NULL) {

tests/.clang-tidy

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ Checks: >-
5050
-performance-avoid-endl,
5151
-cppcoreguidelines-avoid-do-while,
5252
-*DeprecatedOrUnsafeBufferHandling,
53+
-*-prefer-static-over-anonymous-namespace,
5354
WarningsAsErrors: '*'
5455
HeaderFilterRegex: '.*\.hpp'
5556
FormatStyle: file

tests/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ set(ENABLE_COVERAGE OFF CACHE BOOL "enable code coverage measurement")
2020
set(library_dir "${CMAKE_SOURCE_DIR}/libudpard")
2121
set(unity_root "${CMAKE_SOURCE_DIR}/submodules/unity")
2222

23-
include_directories(${CMAKE_SOURCE_DIR}/lib/cavl)
23+
include_directories(SYSTEM ${CMAKE_SOURCE_DIR}/lib/cavl)
2424

2525
# TODO FIXME: remove this later
2626
add_compile_options(-Wno-unused-function)
@@ -91,6 +91,7 @@ gen_test_matrix(test_intrusive_header "src/test_intrusive_header.c")
9191
gen_test_matrix(test_intrusive_misc "src/test_intrusive_misc.c")
9292
gen_test_matrix(test_intrusive_tx "src/test_intrusive_tx.c")
9393
gen_test_matrix(test_intrusive_rx "src/test_intrusive_rx.c")
94+
gen_test_matrix(test_public "src/test_public.cpp;${library_dir}/udpard.c")
9495

9596
# Coverage targets. Usage:
9697
# cmake -DENABLE_COVERAGE=ON ..

tests/src/helpers.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -158,14 +158,14 @@ static inline void instrumented_allocator_reset(instrumented_allocator_t* const
158158

159159
static inline udpard_mem_resource_t instrumented_allocator_make_resource(const instrumented_allocator_t* const self)
160160
{
161-
return (udpard_mem_resource_t){ .user = (void*)self,
162-
.free = &instrumented_allocator_free,
163-
.alloc = &instrumented_allocator_alloc };
161+
const udpard_mem_resource_t result = { (void*)self, &instrumented_allocator_free, &instrumented_allocator_alloc };
162+
return result;
164163
}
165164

166165
static inline udpard_mem_deleter_t instrumented_allocator_make_deleter(const instrumented_allocator_t* const self)
167166
{
168-
return (udpard_mem_deleter_t){ .user = (void*)self, .free = &instrumented_allocator_free };
167+
const udpard_mem_deleter_t result = { (void*)self, &instrumented_allocator_free };
168+
return result;
169169
}
170170

171171
static inline void seed_prng(void)

tests/src/test_intrusive_rx.c

Lines changed: 0 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -2644,123 +2644,6 @@ static void test_session_ordered(void)
26442644
instrumented_allocator_reset(&alloc_payload);
26452645
}
26462646

2647-
// --------------------------------------------- FRAGMENT ---------------------------------------------
2648-
2649-
static void test_udpard_fragment_seek(void)
2650-
{
2651-
instrumented_allocator_t alloc_frag = { 0 };
2652-
instrumented_allocator_new(&alloc_frag);
2653-
const udpard_mem_resource_t mem_frag = instrumented_allocator_make_resource(&alloc_frag);
2654-
2655-
instrumented_allocator_t alloc_payload = { 0 };
2656-
instrumented_allocator_new(&alloc_payload);
2657-
const udpard_mem_resource_t mem_payload = instrumented_allocator_make_resource(&alloc_payload);
2658-
const udpard_mem_deleter_t del_payload = instrumented_allocator_make_deleter(&alloc_payload);
2659-
2660-
// Build a fragment tree with multiple fragments with gaps between them.
2661-
// Using make_frame_base to control exact sizes (no null terminators).
2662-
// Fragments at offsets: 0-3 (3 bytes), 5-8 (3 bytes), 10-14 (4 bytes)
2663-
udpard_tree_t* root = NULL;
2664-
size_t cov = 0;
2665-
2666-
// Fragment 1: offset 0, size 3
2667-
rx_fragment_tree_update(&root, mem_frag, del_payload, make_frame_base(mem_payload, 0, 3, "abc"), 14, 14, &cov);
2668-
TEST_ASSERT_NOT_NULL(root);
2669-
TEST_ASSERT_EQUAL_size_t(3, cov); // Coverage is only the contiguous prefix from offset 0.
2670-
2671-
// Fragment 2: offset 5, size 3
2672-
rx_fragment_tree_update(&root, mem_frag, del_payload, make_frame_base(mem_payload, 5, 3, "def"), 14, 14, &cov);
2673-
TEST_ASSERT_EQUAL_size_t(3, cov); // Still 3, gap at [3-5).
2674-
2675-
// Fragment 3: offset 10, size 4
2676-
rx_fragment_tree_update(&root, mem_frag, del_payload, make_frame_base(mem_payload, 10, 4, "ghij"), 14, 14, &cov);
2677-
2678-
TEST_ASSERT_EQUAL(3, tree_count(root));
2679-
TEST_ASSERT_EQUAL_size_t(3, cov); // Still 3, gaps prevent full coverage.
2680-
2681-
// Get references to the fragments for testing.
2682-
udpard_fragment_t* frag0 = fragment_at(root, 0);
2683-
udpard_fragment_t* frag1 = fragment_at(root, 1);
2684-
udpard_fragment_t* frag2 = fragment_at(root, 2);
2685-
TEST_ASSERT_NOT_NULL(frag0);
2686-
TEST_ASSERT_NOT_NULL(frag1);
2687-
TEST_ASSERT_NOT_NULL(frag2);
2688-
2689-
// Test seeking to offset 0 (should return first fragment).
2690-
TEST_ASSERT_EQUAL_PTR(frag0, udpard_fragment_seek(frag0, 0));
2691-
TEST_ASSERT_EQUAL_PTR(frag0, udpard_fragment_seek(frag1, 0));
2692-
TEST_ASSERT_EQUAL_PTR(frag0, udpard_fragment_seek(frag2, 0));
2693-
2694-
// Test seeking within first fragment [0-3).
2695-
TEST_ASSERT_EQUAL_PTR(frag0, udpard_fragment_seek(frag0, 0));
2696-
TEST_ASSERT_EQUAL_PTR(frag0, udpard_fragment_seek(frag0, 1));
2697-
TEST_ASSERT_EQUAL_PTR(frag0, udpard_fragment_seek(frag0, 2));
2698-
2699-
// Test seeking in gap [3-5) - should return NULL.
2700-
TEST_ASSERT_NULL(udpard_fragment_seek(frag0, 3));
2701-
TEST_ASSERT_NULL(udpard_fragment_seek(frag1, 4));
2702-
2703-
// Test seeking to start of second fragment [5-8).
2704-
TEST_ASSERT_EQUAL_PTR(frag1, udpard_fragment_seek(frag0, 5));
2705-
TEST_ASSERT_EQUAL_PTR(frag1, udpard_fragment_seek(frag1, 5));
2706-
TEST_ASSERT_EQUAL_PTR(frag1, udpard_fragment_seek(frag2, 5));
2707-
2708-
// Test seeking within second fragment.
2709-
TEST_ASSERT_EQUAL_PTR(frag1, udpard_fragment_seek(frag0, 6));
2710-
TEST_ASSERT_EQUAL_PTR(frag1, udpard_fragment_seek(frag1, 7));
2711-
2712-
// Test seeking in gap [8-10) - should return NULL.
2713-
TEST_ASSERT_NULL(udpard_fragment_seek(frag0, 8));
2714-
TEST_ASSERT_NULL(udpard_fragment_seek(frag1, 9));
2715-
2716-
// Test seeking to start of third fragment [10-14).
2717-
TEST_ASSERT_EQUAL_PTR(frag2, udpard_fragment_seek(frag0, 10));
2718-
TEST_ASSERT_EQUAL_PTR(frag2, udpard_fragment_seek(frag1, 10));
2719-
TEST_ASSERT_EQUAL_PTR(frag2, udpard_fragment_seek(frag2, 10));
2720-
2721-
// Test seeking within third fragment.
2722-
TEST_ASSERT_EQUAL_PTR(frag2, udpard_fragment_seek(frag0, 11));
2723-
TEST_ASSERT_EQUAL_PTR(frag2, udpard_fragment_seek(frag1, 12));
2724-
TEST_ASSERT_EQUAL_PTR(frag2, udpard_fragment_seek(frag2, 13));
2725-
2726-
// Test seeking beyond payload (should return NULL).
2727-
TEST_ASSERT_NULL(udpard_fragment_seek(frag0, 14));
2728-
TEST_ASSERT_NULL(udpard_fragment_seek(frag1, 14));
2729-
TEST_ASSERT_NULL(udpard_fragment_seek(frag2, 14));
2730-
TEST_ASSERT_NULL(udpard_fragment_seek(frag0, 100));
2731-
2732-
// Cleanup.
2733-
udpard_fragment_free_all((udpard_fragment_t*)root, mem_frag);
2734-
TEST_ASSERT_EQUAL_size_t(0, alloc_frag.allocated_fragments);
2735-
TEST_ASSERT_EQUAL_size_t(0, alloc_payload.allocated_fragments);
2736-
2737-
instrumented_allocator_reset(&alloc_frag);
2738-
instrumented_allocator_reset(&alloc_payload);
2739-
2740-
// Test with single fragment.
2741-
root = NULL;
2742-
cov = 0;
2743-
rx_fragment_tree_update(&root, mem_frag, del_payload, make_frame_base(mem_payload, 0, 5, "hello"), 5, 5, &cov);
2744-
TEST_ASSERT_NOT_NULL(root);
2745-
2746-
udpard_fragment_t* single = fragment_at(root, 0);
2747-
TEST_ASSERT_NOT_NULL(single);
2748-
2749-
// Seek within single fragment.
2750-
TEST_ASSERT_EQUAL_PTR(single, udpard_fragment_seek(single, 0));
2751-
TEST_ASSERT_EQUAL_PTR(single, udpard_fragment_seek(single, 1));
2752-
TEST_ASSERT_EQUAL_PTR(single, udpard_fragment_seek(single, 2));
2753-
TEST_ASSERT_EQUAL_PTR(single, udpard_fragment_seek(single, 4));
2754-
2755-
// Seek beyond single fragment.
2756-
TEST_ASSERT_NULL(udpard_fragment_seek(single, 5));
2757-
2758-
// Cleanup.
2759-
udpard_fragment_free_all((udpard_fragment_t*)root, mem_frag);
2760-
TEST_ASSERT_EQUAL_size_t(0, alloc_frag.allocated_fragments);
2761-
TEST_ASSERT_EQUAL_size_t(0, alloc_payload.allocated_fragments);
2762-
}
2763-
27642647
void setUp(void) {}
27652648

27662649
void tearDown(void) {}
@@ -2781,7 +2664,5 @@ int main(void)
27812664

27822665
RUN_TEST(test_session_ordered);
27832666

2784-
RUN_TEST(test_udpard_fragment_seek);
2785-
27862667
return UNITY_END();
27872668
}

tests/src/test_public.cpp

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
/// This software is distributed under the terms of the MIT License.
2+
/// Copyright (C) OpenCyphal Development Team <opencyphal.org>
3+
/// Copyright Amazon.com Inc. or its affiliates.
4+
/// SPDX-License-Identifier: MIT
5+
6+
#include <udpard.h>
7+
#include "helpers.h"
8+
#include <unity.h>
9+
#include <cstring>
10+
11+
namespace {
12+
13+
/// The data is copied.
14+
udpard_fragment_t* make_test_fragment(const udpard_mem_resource_t& fragment_memory,
15+
const udpard_mem_resource_t& payload_memory,
16+
const udpard_mem_deleter_t payload_deleter,
17+
const size_t offset,
18+
const size_t size,
19+
const void* data)
20+
{
21+
auto* const frag =
22+
static_cast<udpard_fragment_t*>(fragment_memory.alloc(fragment_memory.user, sizeof(udpard_fragment_t)));
23+
if (frag == nullptr) {
24+
return nullptr;
25+
}
26+
void* payload_data = payload_memory.alloc(payload_memory.user, size);
27+
if (payload_data == nullptr) {
28+
fragment_memory.free(fragment_memory.user, sizeof(udpard_fragment_t), frag);
29+
return nullptr;
30+
}
31+
if (size > 0 && data != nullptr) {
32+
std::memcpy(payload_data, data, size);
33+
}
34+
std::memset(frag, 0, sizeof(*frag));
35+
frag->next = nullptr;
36+
frag->view.data = payload_data;
37+
frag->view.size = size;
38+
frag->origin.data = payload_data;
39+
frag->origin.size = size;
40+
frag->offset = offset;
41+
frag->payload_deleter = payload_deleter;
42+
return frag;
43+
}
44+
45+
void test_udpard_fragment_seek()
46+
{
47+
instrumented_allocator_t alloc_frag{};
48+
instrumented_allocator_new(&alloc_frag);
49+
const udpard_mem_resource_t mem_frag = instrumented_allocator_make_resource(&alloc_frag);
50+
51+
instrumented_allocator_t alloc_payload{};
52+
instrumented_allocator_new(&alloc_payload);
53+
const udpard_mem_resource_t mem_payload = instrumented_allocator_make_resource(&alloc_payload);
54+
const udpard_mem_deleter_t del_payload = instrumented_allocator_make_deleter(&alloc_payload);
55+
56+
// Test with single fragment at offset 0.
57+
// Note: udpard_fragment_seek() uses the index_offset tree structure internally,
58+
// which can only be properly built by the RX pipeline. For public API testing,
59+
// we can only test simple cases with standalone fragments.
60+
udpard_fragment_t* single = make_test_fragment(mem_frag, mem_payload, del_payload, 0, 5, "hello");
61+
TEST_ASSERT_NOT_NULL(single);
62+
single->next = nullptr;
63+
// Initialize the tree node to null (no parent, no children) - this makes it a standalone root
64+
single->index_offset.up = nullptr;
65+
single->index_offset.lr[0] = nullptr;
66+
single->index_offset.lr[1] = nullptr;
67+
single->index_offset.bf = 0;
68+
69+
// Seek to offset 0 should return the fragment itself.
70+
TEST_ASSERT_EQUAL_PTR(single, udpard_fragment_seek(single, 0));
71+
72+
// Seek within single fragment range [0-5).
73+
TEST_ASSERT_EQUAL_PTR(single, udpard_fragment_seek(single, 0));
74+
TEST_ASSERT_EQUAL_PTR(single, udpard_fragment_seek(single, 1));
75+
TEST_ASSERT_EQUAL_PTR(single, udpard_fragment_seek(single, 2));
76+
TEST_ASSERT_EQUAL_PTR(single, udpard_fragment_seek(single, 4));
77+
78+
// Seek beyond single fragment should return NULL.
79+
TEST_ASSERT_NULL(udpard_fragment_seek(single, 5));
80+
TEST_ASSERT_NULL(udpard_fragment_seek(single, 100));
81+
82+
// Cleanup.
83+
mem_payload.free(mem_payload.user, single->origin.size, single->origin.data);
84+
mem_frag.free(mem_frag.user, sizeof(udpard_fragment_t), single);
85+
TEST_ASSERT_EQUAL_size_t(0, alloc_frag.allocated_fragments);
86+
TEST_ASSERT_EQUAL_size_t(0, alloc_payload.allocated_fragments);
87+
}
88+
89+
} // namespace
90+
91+
extern "C"
92+
{
93+
void setUp() {}
94+
void tearDown() {}
95+
}
96+
97+
int main()
98+
{
99+
UNITY_BEGIN();
100+
RUN_TEST(test_udpard_fragment_seek);
101+
return UNITY_END();
102+
}

0 commit comments

Comments
 (0)