Skip to content

Commit dd7dd26

Browse files
update the test suite
1 parent 1100c65 commit dd7dd26

11 files changed

Lines changed: 236 additions & 198 deletions

tests/src/helpers.h

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -176,18 +176,40 @@ static inline void instrumented_allocator_reset(instrumented_allocator_t* const
176176
instrumented_allocator_new(self);
177177
}
178178

179-
static inline udpard_mem_resource_t instrumented_allocator_make_resource(const instrumented_allocator_t* const self)
179+
// Shared vtable for instrumented allocators.
180+
static const udpard_mem_vtable_t instrumented_allocator_vtable = {
181+
.base = { .free = instrumented_allocator_free },
182+
.alloc = instrumented_allocator_alloc,
183+
};
184+
185+
static inline udpard_mem_t instrumented_allocator_make_resource(const instrumented_allocator_t* const self)
180186
{
181-
const udpard_mem_resource_t result = { (void*)self, &instrumented_allocator_free, &instrumented_allocator_alloc };
187+
const udpard_mem_t result = { .vtable = &instrumented_allocator_vtable, .context = (void*)self };
182188
return result;
183189
}
184190

185-
static inline udpard_mem_deleter_t instrumented_allocator_make_deleter(const instrumented_allocator_t* const self)
191+
static inline udpard_deleter_t instrumented_allocator_make_deleter(const instrumented_allocator_t* const self)
186192
{
187-
const udpard_mem_deleter_t result = { (void*)self, &instrumented_allocator_free };
193+
const udpard_deleter_t result = { .vtable = &instrumented_allocator_vtable.base, .context = (void*)self };
188194
return result;
189195
}
190196

197+
// Shortcuts for vtable-based memory access.
198+
static inline void* mem_res_alloc(const udpard_mem_t mem, const size_t size)
199+
{
200+
return mem.vtable->alloc(mem.context, size);
201+
}
202+
203+
static inline void mem_res_free(const udpard_mem_t mem, const size_t size, void* const ptr)
204+
{
205+
mem.vtable->base.free(mem.context, size, ptr);
206+
}
207+
208+
static inline void mem_del_free(const udpard_deleter_t del, const size_t size, void* const ptr)
209+
{
210+
del.vtable->free(del.context, size, ptr);
211+
}
212+
191213
static inline void seed_prng(void)
192214
{
193215
unsigned seed = (unsigned)time(NULL);

tests/src/test_e2e_api.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ void tx_refcount_free(void* const user, const size_t size, void* const payload)
4242
udpard_tx_refcount_dec(udpard_bytes_t{ .size = size, .data = payload });
4343
}
4444

45+
// Shared deleter for captured TX frames.
46+
constexpr udpard_deleter_vtable_t tx_refcount_deleter_vt{ .free = &tx_refcount_free };
47+
4548
bool capture_tx_frame(udpard_tx_t* const tx, udpard_tx_ejection_t* const ejection)
4649
{
4750
auto* frames = static_cast<std::vector<CapturedFrame>*>(tx->user);
@@ -222,9 +225,9 @@ void test_reliable_delivery_under_losses()
222225
pub_tx.mtu[0] = 600;
223226
pub_tx.mtu[1] = 900;
224227
pub_tx.mtu[2] = 500;
225-
const udpard_us_t start = 0;
226-
const udpard_us_t deadline = start + 200000;
227-
const udpard_mem_deleter_t tx_payload_deleter{ .user = nullptr, .free = &tx_refcount_free };
228+
const udpard_us_t start = 0;
229+
const udpard_us_t deadline = start + 200000;
230+
const udpard_deleter_t tx_payload_deleter{ .vtable = &tx_refcount_deleter_vt, .context = nullptr };
228231
TEST_ASSERT_GREATER_THAN_UINT32(0U,
229232
udpard_tx_push(&pub_tx,
230233
start,
@@ -414,7 +417,7 @@ void test_reliable_stats_and_failures()
414417
&record_feedback,
415418
make_user_context(&fb_ignore)));
416419
udpard_tx_poll(&src_tx, 0, UDPARD_IFACE_MASK_ALL);
417-
const udpard_mem_deleter_t tx_payload_deleter{ .user = nullptr, .free = &tx_refcount_free };
420+
const udpard_deleter_t tx_payload_deleter{ .vtable = &tx_refcount_deleter_vt, .context = nullptr };
418421
for (const auto& f : src_frames) {
419422
TEST_ASSERT_TRUE(udpard_rx_port_push(
420423
&rx, &port, 0, ctx.sources[f.iface_index], f.datagram, tx_payload_deleter, f.iface_index));

tests/src/test_e2e_edge.cpp

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ void tx_refcount_free(void* const user, const size_t size, void* const payload)
3838
udpard_tx_refcount_dec(udpard_bytes_t{ .size = size, .data = payload });
3939
}
4040

41+
// Shared deleter for captured TX frames.
42+
constexpr udpard_deleter_vtable_t tx_refcount_deleter_vt{ .free = &tx_refcount_free };
43+
4144
bool capture_tx_frame(udpard_tx_t* const tx, udpard_tx_ejection_t* const ejection)
4245
{
4346
auto* frames = static_cast<std::vector<CapturedFrame>*>(tx->user);
@@ -89,7 +92,7 @@ struct Fixture
8992
udpard_tx_t tx{};
9093
udpard_rx_t rx{};
9194
udpard_rx_port_t port{};
92-
udpard_mem_deleter_t tx_payload_deleter{};
95+
udpard_deleter_t tx_payload_deleter{};
9396
std::vector<CapturedFrame> frames;
9497
Context ctx{};
9598
udpard_udpip_ep_t dest{};
@@ -114,7 +117,7 @@ struct Fixture
114117
}
115118
const udpard_rx_mem_resources_t rx_mem{ .session = instrumented_allocator_make_resource(&rx_alloc_session),
116119
.fragment = instrumented_allocator_make_resource(&rx_alloc_frag) };
117-
tx_payload_deleter = udpard_mem_deleter_t{ .user = nullptr, .free = &tx_refcount_free };
120+
tx_payload_deleter = udpard_deleter_t{ .vtable = &tx_refcount_deleter_vt, .context = nullptr };
118121
source = { .ip = 0x0A000001U, .port = 7501U };
119122
dest = udpard_make_subject_endpoint(222U);
120123

@@ -503,7 +506,7 @@ void test_udpard_tx_push_p2p()
503506
udpard_tx_poll(&tx, now, UDPARD_IFACE_MASK_ALL);
504507
TEST_ASSERT_FALSE(frames.empty());
505508

506-
const udpard_mem_deleter_t tx_payload_deleter{ .user = nullptr, .free = &tx_refcount_free };
509+
const udpard_deleter_t tx_payload_deleter{ .vtable = &tx_refcount_deleter_vt, .context = nullptr };
507510
for (const auto& f : frames) {
508511
TEST_ASSERT_TRUE(udpard_rx_port_push(
509512
&rx, reinterpret_cast<udpard_rx_port_t*>(&port), now, source, f.datagram, tx_payload_deleter, f.iface_index));
@@ -594,7 +597,7 @@ void test_udpard_rx_p2p_malformed_kind()
594597

595598
// Push the frame to RX P2P port.
596599
TEST_ASSERT_EQUAL_UINT64(0, rx.errors_transfer_malformed);
597-
const udpard_mem_deleter_t tx_payload_deleter{ .user = nullptr, .free = &tx_refcount_free };
600+
const udpard_deleter_t tx_payload_deleter{ .vtable = &tx_refcount_deleter_vt, .context = nullptr };
598601
for (const auto& f : frames) {
599602
TEST_ASSERT_TRUE(udpard_rx_port_push(
600603
&rx, reinterpret_cast<udpard_rx_port_t*>(&port), now, source, f.datagram, tx_payload_deleter, f.iface_index));
@@ -690,7 +693,7 @@ void test_udpard_tx_minimum_mtu()
690693
TEST_ASSERT_TRUE(frames.size() > 1);
691694

692695
// Deliver frames to RX
693-
const udpard_mem_deleter_t tx_payload_deleter{ .user = nullptr, .free = &tx_refcount_free };
696+
const udpard_deleter_t tx_payload_deleter{ .vtable = &tx_refcount_deleter_vt, .context = nullptr };
694697
for (const auto& f : frames) {
695698
TEST_ASSERT_TRUE(
696699
udpard_rx_port_push(&rx, &port, now, ctx.source, f.datagram, tx_payload_deleter, f.iface_index));
@@ -832,7 +835,7 @@ void test_udpard_rx_zero_extent()
832835
TEST_ASSERT_FALSE(frames.empty());
833836

834837
// Deliver to RX with zero extent
835-
const udpard_mem_deleter_t tx_payload_deleter{ .user = nullptr, .free = &tx_refcount_free };
838+
const udpard_deleter_t tx_payload_deleter{ .vtable = &tx_refcount_deleter_vt, .context = nullptr };
836839
for (const auto& f : frames) {
837840
TEST_ASSERT_TRUE(udpard_rx_port_push(&rx, &port, now, source, f.datagram, tx_payload_deleter, f.iface_index));
838841
}
@@ -902,7 +905,7 @@ void test_udpard_all_priority_levels()
902905
udpard_us_t now = 0;
903906

904907
// Test all 8 priority levels
905-
for (uint8_t prio = 0; prio <= UDPARD_PRIORITY_MAX; prio++) {
908+
for (uint8_t prio = 0; prio < UDPARD_PRIORITY_COUNT; prio++) {
906909
fix.frames.clear();
907910
std::array<uint8_t, 8> payload{};
908911
payload[0] = prio;
@@ -933,8 +936,8 @@ void test_udpard_all_priority_levels()
933936
}
934937

935938
// All 8 transfers should be received
936-
TEST_ASSERT_EQUAL_size_t(8, fix.ctx.ids.size());
937-
for (uint8_t prio = 0; prio <= UDPARD_PRIORITY_MAX; prio++) {
939+
TEST_ASSERT_EQUAL_size_t(UDPARD_PRIORITY_COUNT, fix.ctx.ids.size());
940+
for (uint8_t prio = 0; prio < UDPARD_PRIORITY_COUNT; prio++) {
938941
TEST_ASSERT_EQUAL_UINT64(100U + prio, fix.ctx.ids[prio]);
939942
}
940943
}
@@ -1000,7 +1003,7 @@ void test_udpard_topic_hash_collision()
10001003
TEST_ASSERT_FALSE(frames.empty());
10011004

10021005
// Deliver to RX - should trigger collision callback
1003-
const udpard_mem_deleter_t tx_payload_deleter{ .user = nullptr, .free = &tx_refcount_free };
1006+
const udpard_deleter_t tx_payload_deleter{ .vtable = &tx_refcount_deleter_vt, .context = nullptr };
10041007
for (const auto& f : frames) {
10051008
TEST_ASSERT_TRUE(
10061009
udpard_rx_port_push(&rx, &port, now, ctx.source, f.datagram, tx_payload_deleter, f.iface_index));

tests/src/test_e2e_random.cpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,9 @@ void tx_refcount_free(void* const user, const size_t size, void* const payload)
9090
udpard_tx_refcount_dec(udpard_bytes_t{ .size = size, .data = payload });
9191
}
9292

93+
// Shared deleter for captured TX frames.
94+
constexpr udpard_deleter_vtable_t tx_refcount_deleter_vt{ .free = &tx_refcount_free };
95+
9396
bool capture_tx_frame(udpard_tx_t* const tx, udpard_tx_ejection_t* const ejection)
9497
{
9598
auto* frames = static_cast<std::vector<CapturedFrame>*>(tx->user);
@@ -244,7 +247,7 @@ void test_udpard_tx_rx_end_to_end()
244247
.port = static_cast<uint16_t>(7400U + i) };
245248
}
246249
rx.user = &ctx;
247-
constexpr udpard_mem_deleter_t tx_payload_deleter{ .user = nullptr, .free = &tx_refcount_free };
250+
constexpr udpard_deleter_t tx_payload_deleter{ .vtable = &tx_refcount_deleter_vt, .context = nullptr };
248251
// Ack path wiring.
249252
std::vector<CapturedFrame> frames;
250253
tx.user = &frames;
@@ -280,10 +283,10 @@ void test_udpard_tx_rx_end_to_end()
280283

281284
// Each transfer is sent on all redundant interfaces with different MTUs to exercise fragmentation variety.
282285
const udpard_bytes_scattered_t payload_view = make_scattered(payload.data(), payload.size());
283-
const auto priority = static_cast<udpard_prio_t>(random_range(0, UDPARD_PRIORITY_MAX));
284-
const udpard_udpip_ep_t dest = udpard_make_subject_endpoint(subject_ids[port_index]);
285-
const TransferKey key{ .transfer_id = transfer_id, .topic_hash = topic_hashes[port_index] };
286-
const bool inserted =
286+
const auto priority = static_cast<udpard_prio_t>(random_range(0, UDPARD_PRIORITY_COUNT - 1U));
287+
const udpard_udpip_ep_t dest = udpard_make_subject_endpoint(subject_ids[port_index]);
288+
const TransferKey key{ .transfer_id = transfer_id, .topic_hash = topic_hashes[port_index] };
289+
const bool inserted =
287290
ctx.expected.emplace(key, ExpectedPayload{ .payload = payload, .payload_size_wire = payload.size() }).second;
288291
TEST_ASSERT_TRUE(inserted);
289292

tests/src/test_e2e_responses.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,10 @@ void drop_frame(const CapturedFrame& frame)
4646
udpard_tx_refcount_dec(udpard_bytes_t{ .size = frame.datagram.size, .data = frame.datagram.data });
4747
}
4848

49-
constexpr udpard_tx_vtable_t tx_vtable{ .eject = &capture_tx_frame };
50-
constexpr udpard_mem_deleter_t tx_payload_deleter{ .user = nullptr, .free = &tx_refcount_free };
49+
constexpr udpard_tx_vtable_t tx_vtable{ .eject = &capture_tx_frame };
50+
// Shared deleter for captured TX frames.
51+
constexpr udpard_deleter_vtable_t tx_refcount_deleter_vt{ .free = &tx_refcount_free };
52+
constexpr udpard_deleter_t tx_payload_deleter{ .vtable = &tx_refcount_deleter_vt, .context = nullptr };
5153

5254
// --------------------------------------------------------------------------------------------------------------------
5355
// FEEDBACK AND CONTEXT STRUCTURES

tests/src/test_fragment.cpp

Lines changed: 31 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -12,21 +12,20 @@
1212
namespace {
1313

1414
/// The data is copied.
15-
udpard_fragment_t* make_test_fragment(const udpard_mem_resource_t& fragment_memory,
16-
const udpard_mem_resource_t& payload_memory,
17-
const udpard_mem_deleter_t payload_deleter,
18-
const size_t offset,
19-
const size_t size,
20-
const void* data)
15+
udpard_fragment_t* make_test_fragment(const udpard_mem_t& fragment_memory,
16+
const udpard_mem_t& payload_memory,
17+
const udpard_deleter_t payload_deleter,
18+
const size_t offset,
19+
const size_t size,
20+
const void* data)
2121
{
22-
auto* frag =
23-
static_cast<udpard_fragment_t*>(fragment_memory.alloc(fragment_memory.user, sizeof(udpard_fragment_t)));
22+
auto* frag = static_cast<udpard_fragment_t*>(mem_res_alloc(fragment_memory, sizeof(udpard_fragment_t)));
2423
if (frag == nullptr) {
2524
return nullptr;
2625
}
27-
void* payload_data = payload_memory.alloc(payload_memory.user, size);
26+
void* payload_data = mem_res_alloc(payload_memory, size);
2827
if (payload_data == nullptr) {
29-
fragment_memory.free(fragment_memory.user, sizeof(udpard_fragment_t), frag);
28+
mem_res_free(fragment_memory, sizeof(udpard_fragment_t), frag);
3029
return nullptr;
3130
}
3231
if (size > 0 && data != nullptr) {
@@ -46,12 +45,12 @@ void test_udpard_fragment_seek()
4645
{
4746
instrumented_allocator_t alloc_frag{};
4847
instrumented_allocator_new(&alloc_frag);
49-
const udpard_mem_resource_t mem_frag = instrumented_allocator_make_resource(&alloc_frag);
48+
const udpard_mem_t mem_frag = instrumented_allocator_make_resource(&alloc_frag);
5049

5150
instrumented_allocator_t alloc_payload{};
5251
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);
52+
const udpard_mem_t mem_payload = instrumented_allocator_make_resource(&alloc_payload);
53+
const udpard_deleter_t del_payload = instrumented_allocator_make_deleter(&alloc_payload);
5554

5655
// Test 1: Single fragment at offset 0 (root node).
5756
// Note: udpard_fragment_seek() uses the index_offset tree structure internally,
@@ -79,8 +78,8 @@ void test_udpard_fragment_seek()
7978
TEST_ASSERT_NULL(udpard_fragment_seek(single, 100));
8079

8180
// Cleanup.
82-
mem_payload.free(mem_payload.user, single->origin.size, single->origin.data);
83-
mem_frag.free(mem_frag.user, sizeof(udpard_fragment_t), single);
81+
mem_res_free(mem_payload, single->origin.size, single->origin.data);
82+
mem_res_free(mem_frag, sizeof(udpard_fragment_t), single);
8483
TEST_ASSERT_EQUAL_size_t(0, alloc_frag.allocated_fragments);
8584
TEST_ASSERT_EQUAL_size_t(0, alloc_payload.allocated_fragments);
8685

@@ -138,12 +137,12 @@ void test_udpard_fragment_seek()
138137
TEST_ASSERT_NULL(udpard_fragment_seek(right, 14)); // beyond all fragments
139138

140139
// Cleanup.
141-
mem_payload.free(mem_payload.user, left->origin.size, left->origin.data);
142-
mem_frag.free(mem_frag.user, sizeof(udpard_fragment_t), left);
143-
mem_payload.free(mem_payload.user, root->origin.size, root->origin.data);
144-
mem_frag.free(mem_frag.user, sizeof(udpard_fragment_t), root);
145-
mem_payload.free(mem_payload.user, right->origin.size, right->origin.data);
146-
mem_frag.free(mem_frag.user, sizeof(udpard_fragment_t), right);
140+
mem_res_free(mem_payload, left->origin.size, left->origin.data);
141+
mem_res_free(mem_frag, sizeof(udpard_fragment_t), left);
142+
mem_res_free(mem_payload, root->origin.size, root->origin.data);
143+
mem_res_free(mem_frag, sizeof(udpard_fragment_t), root);
144+
mem_res_free(mem_payload, right->origin.size, right->origin.data);
145+
mem_res_free(mem_frag, sizeof(udpard_fragment_t), right);
147146
TEST_ASSERT_EQUAL_size_t(0, alloc_frag.allocated_fragments);
148147
TEST_ASSERT_EQUAL_size_t(0, alloc_payload.allocated_fragments);
149148
}
@@ -152,12 +151,12 @@ void test_udpard_fragment_gather()
152151
{
153152
instrumented_allocator_t alloc_frag{};
154153
instrumented_allocator_new(&alloc_frag);
155-
const udpard_mem_resource_t mem_frag = instrumented_allocator_make_resource(&alloc_frag);
154+
const udpard_mem_t mem_frag = instrumented_allocator_make_resource(&alloc_frag);
156155

157156
instrumented_allocator_t alloc_payload{};
158157
instrumented_allocator_new(&alloc_payload);
159-
const udpard_mem_resource_t mem_payload = instrumented_allocator_make_resource(&alloc_payload);
160-
const udpard_mem_deleter_t del_payload = instrumented_allocator_make_deleter(&alloc_payload);
158+
const udpard_mem_t mem_payload = instrumented_allocator_make_resource(&alloc_payload);
159+
const udpard_deleter_t del_payload = instrumented_allocator_make_deleter(&alloc_payload);
161160

162161
// Test 1: NULL fragment returns 0.
163162
char buf[100]; // NOLINT(*-avoid-c-arrays)
@@ -197,8 +196,8 @@ void test_udpard_fragment_gather()
197196
TEST_ASSERT_EQUAL_PTR(single, cursor);
198197

199198
// Cleanup single fragment.
200-
mem_payload.free(mem_payload.user, single->origin.size, single->origin.data);
201-
mem_frag.free(mem_frag.user, sizeof(udpard_fragment_t), single);
199+
mem_res_free(mem_payload, single->origin.size, single->origin.data);
200+
mem_res_free(mem_frag, sizeof(udpard_fragment_t), single);
202201

203202
// Test 6: Multiple fragments forming a tree.
204203
// Create tree: root at offset 5 ("MID"), left at offset 0 ("ABCDE"), right at offset 8 ("WXYZ")
@@ -301,12 +300,12 @@ void test_udpard_fragment_gather()
301300
TEST_ASSERT_EQUAL_PTR(root, cursor);
302301

303302
// Cleanup.
304-
mem_payload.free(mem_payload.user, left->origin.size, left->origin.data);
305-
mem_frag.free(mem_frag.user, sizeof(udpard_fragment_t), left);
306-
mem_payload.free(mem_payload.user, root->origin.size, root->origin.data);
307-
mem_frag.free(mem_frag.user, sizeof(udpard_fragment_t), root);
308-
mem_payload.free(mem_payload.user, right->origin.size, right->origin.data);
309-
mem_frag.free(mem_frag.user, sizeof(udpard_fragment_t), right);
303+
mem_res_free(mem_payload, left->origin.size, left->origin.data);
304+
mem_res_free(mem_frag, sizeof(udpard_fragment_t), left);
305+
mem_res_free(mem_payload, root->origin.size, root->origin.data);
306+
mem_res_free(mem_frag, sizeof(udpard_fragment_t), root);
307+
mem_res_free(mem_payload, right->origin.size, right->origin.data);
308+
mem_res_free(mem_frag, sizeof(udpard_fragment_t), right);
310309
TEST_ASSERT_EQUAL_size_t(0, alloc_frag.allocated_fragments);
311310
TEST_ASSERT_EQUAL_size_t(0, alloc_payload.allocated_fragments);
312311
}

0 commit comments

Comments
 (0)