Skip to content

Commit 2110818

Browse files
add tests
1 parent cd40b5e commit 2110818

File tree

1 file changed

+167
-0
lines changed

1 file changed

+167
-0
lines changed

tests/src/test_intrusive_tx.c

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,27 @@ static tx_transfer_t* find_transfer_by_id(udpard_tx_t* const tx, const uint64_t
114114
return ((tr != NULL) && (tr->transfer_id == transfer_id)) ? tr : NULL;
115115
}
116116

117+
// Counts transfers by transfer-ID and kind.
118+
static size_t count_transfers_by_id_and_kind(udpard_tx_t* const tx, const uint64_t transfer_id, const frame_kind_t kind)
119+
{
120+
if (tx == NULL) {
121+
return 0;
122+
}
123+
size_t count = 0;
124+
const tx_key_transfer_id_t key = { .transfer_id = transfer_id, .seq_no = 0 };
125+
for (tx_transfer_t* tr =
126+
CAVL2_TO_OWNER(cavl2_lower_bound(tx->index_transfer_id, &key, &tx_cavl_compare_transfer_id),
127+
tx_transfer_t,
128+
index_transfer_id);
129+
(tr != NULL) && (tr->transfer_id == transfer_id);
130+
tr = CAVL2_TO_OWNER(cavl2_next_greater(&tr->index_transfer_id), tx_transfer_t, index_transfer_id)) {
131+
if (tr->kind == kind) {
132+
count++;
133+
}
134+
}
135+
return count;
136+
}
137+
117138
static void test_bytes_scattered_read(void)
118139
{
119140
// Skips empty fragments and spans boundaries.
@@ -509,6 +530,70 @@ static void test_tx_ack_and_scheduler(void)
509530
TEST_ASSERT_NOT_NULL(find_transfer_by_id(&tx_be, 43));
510531
udpard_tx_free(&tx_be);
511532

533+
// ACK acceptance skips colliding P2P transfers from other remotes.
534+
udpard_tx_t tx_coll_rx = { 0 };
535+
TEST_ASSERT_TRUE(udpard_tx_new(
536+
&tx_coll_rx,
537+
10U,
538+
1U,
539+
8U,
540+
mem,
541+
&(udpard_tx_vtable_t){ .eject_subject = eject_subject_with_flag, .eject_p2p = eject_p2p_with_flag }));
542+
udpard_rx_t rx_coll = { .tx = &tx_coll_rx };
543+
feedback_state_t fb_a = { 0 };
544+
feedback_state_t fb_b = { 0 };
545+
const uint64_t coll_id = 55;
546+
// Insert first colliding transfer.
547+
tx_transfer_t* tr_a = mem_alloc(mem.transfer, sizeof(tx_transfer_t));
548+
mem_zero(sizeof(*tr_a), tr_a);
549+
tr_a->kind = frame_msg_reliable;
550+
tr_a->is_p2p = true;
551+
tr_a->transfer_id = coll_id;
552+
tr_a->seq_no = 1;
553+
tr_a->deadline = 10;
554+
tr_a->priority = udpard_prio_fast;
555+
tr_a->p2p_remote.uid = 1001;
556+
tr_a->user = make_user_context(&fb_a);
557+
tr_a->feedback = record_feedback;
558+
cavl2_find_or_insert(
559+
&tx_coll_rx.index_deadline, tr_a, tx_cavl_compare_deadline, &tr_a->index_deadline, cavl2_trivial_factory);
560+
cavl2_find_or_insert(&tx_coll_rx.index_transfer_id,
561+
&(tx_key_transfer_id_t){ .transfer_id = tr_a->transfer_id, .seq_no = tr_a->seq_no },
562+
tx_cavl_compare_transfer_id,
563+
&tr_a->index_transfer_id,
564+
cavl2_trivial_factory);
565+
enlist_head(&tx_coll_rx.agewise, &tr_a->agewise);
566+
// Insert second colliding transfer with different remote UID.
567+
tx_transfer_t* tr_b = mem_alloc(mem.transfer, sizeof(tx_transfer_t));
568+
mem_zero(sizeof(*tr_b), tr_b);
569+
tr_b->kind = frame_msg_reliable;
570+
tr_b->is_p2p = true;
571+
tr_b->transfer_id = coll_id;
572+
tr_b->seq_no = 2;
573+
tr_b->deadline = 10;
574+
tr_b->priority = udpard_prio_fast;
575+
tr_b->p2p_remote.uid = 1002;
576+
tr_b->user = make_user_context(&fb_b);
577+
tr_b->feedback = record_feedback;
578+
cavl2_find_or_insert(
579+
&tx_coll_rx.index_deadline, tr_b, tx_cavl_compare_deadline, &tr_b->index_deadline, cavl2_trivial_factory);
580+
cavl2_find_or_insert(&tx_coll_rx.index_transfer_id,
581+
&(tx_key_transfer_id_t){ .transfer_id = tr_b->transfer_id, .seq_no = tr_b->seq_no },
582+
tx_cavl_compare_transfer_id,
583+
&tr_b->index_transfer_id,
584+
cavl2_trivial_factory);
585+
enlist_head(&tx_coll_rx.agewise, &tr_b->agewise);
586+
// Accept ack for the second transfer only.
587+
tx_receive_ack(&rx_coll, tr_b->p2p_remote.uid, coll_id);
588+
TEST_ASSERT_EQUAL_size_t(0, fb_a.count);
589+
TEST_ASSERT_EQUAL_size_t(1, fb_b.count);
590+
TEST_ASSERT_EQUAL_size_t(1, count_transfers_by_id_and_kind(&tx_coll_rx, coll_id, frame_msg_reliable));
591+
// Accept ack for the first transfer.
592+
tx_receive_ack(&rx_coll, tr_a->p2p_remote.uid, coll_id);
593+
TEST_ASSERT_EQUAL_size_t(1, fb_a.count);
594+
TEST_ASSERT_EQUAL_size_t(0, count_transfers_by_id_and_kind(&tx_coll_rx, coll_id, frame_msg_reliable));
595+
udpard_tx_free(&tx_coll_rx);
596+
512597
// Ack suppressed when coverage not improved.
513598
udpard_tx_t tx2 = { 0 };
514599
TEST_ASSERT_TRUE(udpard_tx_new(
@@ -559,6 +644,33 @@ static void test_tx_ack_and_scheduler(void)
559644
TEST_ASSERT_NOT_EQUAL(0U, udpard_tx_pending_ifaces(&tx3));
560645
udpard_tx_free(&tx3);
561646

647+
// Ack emission ignores colliding non-ack transfers.
648+
udpard_tx_t tx_coll_ack = { 0 };
649+
TEST_ASSERT_TRUE(udpard_tx_new(
650+
&tx_coll_ack,
651+
12U,
652+
3U,
653+
4U,
654+
mem,
655+
&(udpard_tx_vtable_t){ .eject_subject = eject_subject_with_flag, .eject_p2p = eject_p2p_with_flag }));
656+
rx.tx = &tx_coll_ack;
657+
rx.errors_ack_tx = 0;
658+
TEST_ASSERT_TRUE(udpard_tx_push(&tx_coll_ack,
659+
0,
660+
1000,
661+
iface_bitmap_01,
662+
udpard_prio_fast,
663+
60,
664+
make_scattered(NULL, 0),
665+
record_feedback,
666+
make_user_context(&fstate)));
667+
TEST_ASSERT_EQUAL_size_t(1, count_transfers_by_id_and_kind(&tx_coll_ack, 60, frame_msg_reliable));
668+
tx_send_ack(&rx, 0, udpard_prio_fast, 60, (udpard_remote_t){ .uid = 77, .endpoints = { make_ep(7) } });
669+
TEST_ASSERT_EQUAL_UINT64(0, rx.errors_ack_tx);
670+
TEST_ASSERT_EQUAL_size_t(1, count_transfers_by_id_and_kind(&tx_coll_ack, 60, frame_msg_reliable));
671+
TEST_ASSERT_EQUAL_size_t(1, count_transfers_by_id_and_kind(&tx_coll_ack, 60, frame_ack));
672+
udpard_tx_free(&tx_coll_ack);
673+
562674
// Ack push failure with TX present.
563675
udpard_tx_mem_resources_t fail_mem = { .transfer = { .vtable = &mem_vtable_noop_alloc, .context = NULL } };
564676
for (size_t i = 0; i < UDPARD_IFACE_COUNT_MAX; i++) {
@@ -825,6 +937,61 @@ static void test_tx_cancel(void)
825937
TEST_ASSERT_TRUE(udpard_tx_cancel(&tx, 201, false));
826938
TEST_ASSERT_EQUAL_size_t(0, tx.enqueued_frames_count);
827939

940+
// Collisions cancel all reliable transfers with the same ID.
941+
fstate.count = 0;
942+
const uint64_t coll_id = 300;
943+
TEST_ASSERT_TRUE(udpard_tx_push(&tx,
944+
0,
945+
100,
946+
iface_bitmap_1,
947+
udpard_prio_fast,
948+
coll_id,
949+
make_scattered(NULL, 0),
950+
record_feedback,
951+
make_user_context(&fstate)));
952+
TEST_ASSERT_TRUE(udpard_tx_push(&tx,
953+
0,
954+
100,
955+
iface_bitmap_1,
956+
udpard_prio_fast,
957+
coll_id,
958+
make_scattered(NULL, 0),
959+
record_feedback,
960+
make_user_context(&fstate)));
961+
TEST_ASSERT_EQUAL_size_t(2, count_transfers_by_id_and_kind(&tx, coll_id, frame_msg_reliable));
962+
TEST_ASSERT_TRUE(udpard_tx_cancel(&tx, coll_id, true));
963+
TEST_ASSERT_EQUAL_size_t(0, count_transfers_by_id_and_kind(&tx, coll_id, frame_msg_reliable));
964+
TEST_ASSERT_EQUAL_size_t(2, fstate.count);
965+
966+
// Best-effort collisions do not cancel reliable transfers.
967+
fstate.count = 0;
968+
const uint64_t coll_id2 = 301;
969+
TEST_ASSERT_TRUE(udpard_tx_push(&tx,
970+
0,
971+
100,
972+
iface_bitmap_1,
973+
udpard_prio_fast,
974+
coll_id2,
975+
make_scattered(NULL, 0),
976+
record_feedback,
977+
make_user_context(&fstate)));
978+
TEST_ASSERT_TRUE(udpard_tx_push(&tx,
979+
0,
980+
100,
981+
iface_bitmap_1,
982+
udpard_prio_fast,
983+
coll_id2,
984+
make_scattered(NULL, 0),
985+
NULL,
986+
UDPARD_USER_CONTEXT_NULL));
987+
TEST_ASSERT_EQUAL_size_t(1, count_transfers_by_id_and_kind(&tx, coll_id2, frame_msg_reliable));
988+
TEST_ASSERT_EQUAL_size_t(1, count_transfers_by_id_and_kind(&tx, coll_id2, frame_msg_best));
989+
TEST_ASSERT_TRUE(udpard_tx_cancel(&tx, coll_id2, false));
990+
TEST_ASSERT_EQUAL_size_t(1, count_transfers_by_id_and_kind(&tx, coll_id2, frame_msg_reliable));
991+
TEST_ASSERT_EQUAL_size_t(0, count_transfers_by_id_and_kind(&tx, coll_id2, frame_msg_best));
992+
TEST_ASSERT_TRUE(udpard_tx_cancel(&tx, coll_id2, true));
993+
TEST_ASSERT_EQUAL_size_t(0, count_transfers_by_id_and_kind(&tx, coll_id2, frame_msg_reliable));
994+
828995
udpard_tx_free(&tx);
829996
instrumented_allocator_reset(&alloc);
830997
}

0 commit comments

Comments
 (0)