Skip to content

Commit 5a4df9e

Browse files
updates
1 parent fe12794 commit 5a4df9e

File tree

4 files changed

+67
-5
lines changed

4 files changed

+67
-5
lines changed

libudpard/udpard.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -853,7 +853,6 @@ static rx_fragment_tree_update_result_t rx_fragment_tree_update(udpard_tree_t**
853853
// render smaller fragments that overlap with its edges redundant.
854854
// To check for that, we create a new virtual fragment that represents the new fragment together with those
855855
// that join it on either end, if any, and then look for fragments contained within.
856-
// The search interval would be (v_left, v_right-1) to avoid matching the neighbors themselves.
857856
// Example:
858857
// |--B--|
859858
// |--X--|
@@ -876,13 +875,13 @@ static rx_fragment_tree_update_result_t rx_fragment_tree_update(udpard_tree_t**
876875
}
877876
frag = (udpard_fragment_t*)cavl2_predecessor(*root, &right, &rx_cavl_compare_fragment_offset);
878877
if (frag != NULL) {
879-
v_right = larger(v_right, frag->offset + frag->view.size);
878+
v_right = larger(v_right, larger(frag->offset + frag->view.size, 1U) - 1U); // Avoid matching the right neighbor
880879
}
881880
UDPARD_ASSERT((v_left <= left) && (right <= v_right));
882881

883882
// Find the first victim. It has to be done early to decide if the new fragment is worth keeping at all.
884883
frag = (udpard_fragment_t*)cavl2_lower_bound(*root, &v_left, &rx_cavl_compare_fragment_offset);
885-
const bool need = ((frag != NULL) && ((frag->offset + frag->view.size) < v_right)) ||
884+
const bool need = ((frag != NULL) && ((frag->offset + frag->view.size) <= v_right)) ||
886885
rx_fragment_is_needed(*root, frame.offset, frame.payload.size, transfer_payload_size, extent);
887886
if (!need) {
888887
mem_free_payload(payload_deleter, frame.origin);
@@ -904,7 +903,7 @@ static rx_fragment_tree_update_result_t rx_fragment_tree_update(udpard_tree_t**
904903
mew->payload_deleter = payload_deleter;
905904

906905
// Remove all redundant fragments before inserting the new one.
907-
while ((frag != NULL) && ((frag->offset + frag->view.size) < v_right)) {
906+
while ((frag != NULL) && ((frag->offset + frag->view.size) <= v_right)) {
908907
cavl2_remove(root, &frag->index_offset);
909908
mem_free_payload(frag->payload_deleter, frag->origin);
910909
mem_free(fragment_memory, sizeof(udpard_fragment_t), frag);

tests/src/helpers.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@
22
// Copyright (c) 2016 Cyphal Development Team.
33
/// Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
44

5+
// ReSharper disable CppRedundantInlineSpecifier
6+
// NOLINTBEGIN(*DeprecatedOrUnsafeBufferHandling,*err34-c)
57
#pragma once
68

79
#include <udpard.h> // Shall always be included first.
810
#include <stdlib.h>
911
#include <stdio.h>
10-
#include <limits.h>
1112
#include <time.h>
1213

1314
#if !(defined(UDPARD_VERSION_MAJOR) && defined(UDPARD_VERSION_MINOR))
@@ -64,12 +65,16 @@ typedef struct
6465
/// The current state of the allocator.
6566
size_t allocated_fragments;
6667
size_t allocated_bytes;
68+
/// Event counters.
69+
uint64_t count_alloc;
70+
uint64_t count_free;
6771
} instrumented_allocator_t;
6872

6973
static inline void* instrumented_allocator_alloc(void* const user_reference, const size_t size)
7074
{
7175
instrumented_allocator_t* const self = (instrumented_allocator_t*)user_reference;
7276
void* result = NULL;
77+
self->count_alloc++;
7378
if ((size > 0U) && //
7479
((self->allocated_bytes + size) <= self->limit_bytes) && //
7580
((self->allocated_fragments + 1U) <= self->limit_fragments)) {
@@ -100,6 +105,7 @@ static inline void* instrumented_allocator_alloc(void* const user_reference, con
100105
static inline void instrumented_allocator_free(void* const user_reference, const size_t size, void* const pointer)
101106
{
102107
instrumented_allocator_t* const self = (instrumented_allocator_t*)user_reference;
108+
self->count_free++;
103109
if (pointer != NULL) {
104110
uint_least8_t* p = ((uint_least8_t*)pointer) - INSTRUMENTED_ALLOCATOR_CANARY_SIZE;
105111
void* const origin = p;
@@ -136,6 +142,8 @@ static inline void instrumented_allocator_new(instrumented_allocator_t* const se
136142
self->limit_bytes = SIZE_MAX;
137143
self->allocated_fragments = 0U;
138144
self->allocated_bytes = 0U;
145+
self->count_alloc = 0U;
146+
self->count_free = 0U;
139147
}
140148

141149
static inline udpard_mem_resource_t instrumented_allocator_make_resource(const instrumented_allocator_t* const self)
@@ -164,3 +172,5 @@ static inline void seed_prng(void)
164172
#ifdef __cplusplus
165173
}
166174
#endif
175+
176+
// NOLINTEND(*DeprecatedOrUnsafeBufferHandling,*err34-c)

tests/src/test_helpers.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,52 +10,74 @@ static void test_instrumented_allocator(void)
1010
instrumented_allocator_new(&al);
1111
TEST_ASSERT_EQUAL_size_t(0, al.allocated_fragments);
1212
TEST_ASSERT_EQUAL_size_t(SIZE_MAX, al.limit_bytes);
13+
TEST_ASSERT_EQUAL_UINT64(0, al.count_alloc);
14+
TEST_ASSERT_EQUAL_UINT64(0, al.count_free);
1315

1416
const udpard_mem_resource_t resource = instrumented_allocator_make_resource(&al);
1517

1618
void* a = resource.alloc(resource.user, 123);
1719
TEST_ASSERT_EQUAL_size_t(1, al.allocated_fragments);
1820
TEST_ASSERT_EQUAL_size_t(123, al.allocated_bytes);
21+
TEST_ASSERT_EQUAL_UINT64(1, al.count_alloc);
22+
TEST_ASSERT_EQUAL_UINT64(0, al.count_free);
1923

2024
void* b = resource.alloc(resource.user, 456);
2125
TEST_ASSERT_EQUAL_size_t(2, al.allocated_fragments);
2226
TEST_ASSERT_EQUAL_size_t(579, al.allocated_bytes);
27+
TEST_ASSERT_EQUAL_UINT64(2, al.count_alloc);
28+
TEST_ASSERT_EQUAL_UINT64(0, al.count_free);
2329

2430
al.limit_bytes = 600;
2531
al.limit_fragments = 2;
2632

2733
TEST_ASSERT_EQUAL_PTR(NULL, resource.alloc(resource.user, 100));
2834
TEST_ASSERT_EQUAL_size_t(2, al.allocated_fragments);
2935
TEST_ASSERT_EQUAL_size_t(579, al.allocated_bytes);
36+
TEST_ASSERT_EQUAL_UINT64(3, al.count_alloc);
37+
TEST_ASSERT_EQUAL_UINT64(0, al.count_free);
3038

3139
TEST_ASSERT_EQUAL_PTR(NULL, resource.alloc(resource.user, 21));
3240
TEST_ASSERT_EQUAL_size_t(2, al.allocated_fragments);
3341
TEST_ASSERT_EQUAL_size_t(579, al.allocated_bytes);
42+
TEST_ASSERT_EQUAL_UINT64(4, al.count_alloc);
43+
TEST_ASSERT_EQUAL_UINT64(0, al.count_free);
3444
al.limit_fragments = 4;
3545

3646
void* c = resource.alloc(resource.user, 21);
3747
TEST_ASSERT_EQUAL_size_t(3, al.allocated_fragments);
3848
TEST_ASSERT_EQUAL_size_t(600, al.allocated_bytes);
49+
TEST_ASSERT_EQUAL_UINT64(5, al.count_alloc);
50+
TEST_ASSERT_EQUAL_UINT64(0, al.count_free);
3951

4052
resource.free(resource.user, 123, a);
4153
TEST_ASSERT_EQUAL_size_t(2, al.allocated_fragments);
4254
TEST_ASSERT_EQUAL_size_t(477, al.allocated_bytes);
55+
TEST_ASSERT_EQUAL_UINT64(5, al.count_alloc);
56+
TEST_ASSERT_EQUAL_UINT64(1, al.count_free);
4357

4458
void* d = resource.alloc(resource.user, 100);
4559
TEST_ASSERT_EQUAL_size_t(3, al.allocated_fragments);
4660
TEST_ASSERT_EQUAL_size_t(577, al.allocated_bytes);
61+
TEST_ASSERT_EQUAL_UINT64(6, al.count_alloc);
62+
TEST_ASSERT_EQUAL_UINT64(1, al.count_free);
4763

4864
resource.free(resource.user, 21, c);
4965
TEST_ASSERT_EQUAL_size_t(2, al.allocated_fragments);
5066
TEST_ASSERT_EQUAL_size_t(556, al.allocated_bytes);
67+
TEST_ASSERT_EQUAL_UINT64(6, al.count_alloc);
68+
TEST_ASSERT_EQUAL_UINT64(2, al.count_free);
5169

5270
resource.free(resource.user, 100, d);
5371
TEST_ASSERT_EQUAL_size_t(1, al.allocated_fragments);
5472
TEST_ASSERT_EQUAL_size_t(456, al.allocated_bytes);
73+
TEST_ASSERT_EQUAL_UINT64(6, al.count_alloc);
74+
TEST_ASSERT_EQUAL_UINT64(3, al.count_free);
5575

5676
resource.free(resource.user, 456, b);
5777
TEST_ASSERT_EQUAL_size_t(0, al.allocated_fragments);
5878
TEST_ASSERT_EQUAL_size_t(0, al.allocated_bytes);
79+
TEST_ASSERT_EQUAL_UINT64(6, al.count_alloc);
80+
TEST_ASSERT_EQUAL_UINT64(4, al.count_free);
5981
}
6082

6183
void setUp(void) {}

tests/src/test_intrusive_rx.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,38 @@
44
/// SPDX-License-Identifier: MIT
55

66
#include <udpard.c> // NOLINT(bugprone-suspicious-include)
7+
#include "helpers.h"
78
#include <unity.h>
89

10+
typedef struct fragment_tree_match_item_t
11+
{
12+
size_t offset;
13+
const char* data; ///< A null-terminated string; NULL at the end.
14+
} fragment_tree_match_item_t;
15+
16+
static bool fragment_tree_match(udpard_fragment_t* const head, const fragment_tree_match_item_t items[])
17+
{
18+
if (head == NULL) {
19+
return (items[0].data == NULL);
20+
}
21+
const bool match = (head->offset == items[0].offset) &&
22+
(strlen((const char*)head->view.data) == strlen(items[0].data)) &&
23+
(memcmp(head->view.data, items[0].data, head->view.size) == 0);
24+
return match && fragment_tree_match((udpard_fragment_t*)cavl2_next_greater(&head->index_offset), &items[1]);
25+
}
26+
27+
static void test_rx_fragment_tree_update_a(void)
28+
{
29+
instrumented_allocator_t alloc_frag = { 0 };
30+
instrumented_allocator_new(&alloc_frag);
31+
const udpard_mem_resource_t mem_frag = instrumented_allocator_make_resource(&alloc_frag);
32+
33+
instrumented_allocator_t alloc_payload = { 0 };
34+
instrumented_allocator_new(&alloc_payload);
35+
const udpard_mem_resource_t mem_payload = instrumented_allocator_make_resource(&alloc_payload);
36+
const udpard_mem_deleter_t del_payload = instrumented_allocator_make_deleter(&alloc_payload);
37+
}
38+
939
static void test_rx_transfer_id_forward_distance(void)
1040
{
1141
// Test 1: Same value (distance is 0)
@@ -288,6 +318,7 @@ void tearDown(void) {}
288318
int main(void)
289319
{
290320
UNITY_BEGIN();
321+
RUN_TEST(test_rx_fragment_tree_update_a);
291322
RUN_TEST(test_rx_transfer_id_forward_distance);
292323
RUN_TEST(test_rx_transfer_id_window_slide);
293324
RUN_TEST(test_rx_transfer_id_window_manip);

0 commit comments

Comments
 (0)