File: reorderqueue.c

package info (click to toggle)
chiaki 2.2.0-1.2
  • links: PTS
  • area: main
  • in suites: forky, sid
  • size: 5,312 kB
  • sloc: ansic: 17,616; cpp: 7,901; xml: 2,691; sh: 395; python: 96; makefile: 6
file content (185 lines) | stat: -rw-r--r-- 6,519 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
// SPDX-License-Identifier: LicenseRef-AGPL-3.0-only-OpenSSL

#include <munit.h>

#include <chiaki/reorderqueue.h>

#define DROP_RECORD_MAX 16

typedef struct drop_record_t
{
	uint64_t count[DROP_RECORD_MAX];
	uint64_t seq_num[DROP_RECORD_MAX];
	bool failed;
} DropRecord;

static void drop(uint64_t seq_num, void *elem_user, void *cb_user)
{
	DropRecord *record = cb_user;
	uint64_t v = (uint64_t)(size_t)elem_user;
	if(v > DROP_RECORD_MAX)
	{
		record->failed = true;
		return;
	}
	record->count[v]++;
	record->seq_num[v] = seq_num;
}

static MunitResult test_reorder_queue_16(const MunitParameter params[], void *test_user)
{
	ChiakiReorderQueue queue;
	ChiakiErrorCode err = chiaki_reorder_queue_init_16(&queue, 2, 42);
	munit_assert_int(err, ==, CHIAKI_ERR_SUCCESS);
	munit_assert_size(chiaki_reorder_queue_size(&queue), ==, 4);
	munit_assert_uint64(chiaki_reorder_queue_count(&queue), ==, 0);

	chiaki_reorder_queue_set_drop_strategy(&queue, CHIAKI_REORDER_QUEUE_DROP_STRATEGY_END);

	DropRecord drop_record = { 0 };
	chiaki_reorder_queue_set_drop_cb(&queue, drop, &drop_record);

	uint64_t seq_num = 0;
	void *user = NULL;

	// pull from empty
	bool pulled = chiaki_reorder_queue_pull(&queue, &seq_num, &user);
	munit_assert(!pulled);
	munit_assert_uint64(chiaki_reorder_queue_count(&queue), ==, 0);
	munit_assert(!drop_record.failed);

	// push one
	chiaki_reorder_queue_push(&queue, 42, (void *)0);
	munit_assert_uint64(chiaki_reorder_queue_count(&queue), ==, 1);

	// pull one
	pulled = chiaki_reorder_queue_pull(&queue, &seq_num, &user);
	munit_assert(pulled);
	munit_assert_uint64(chiaki_reorder_queue_count(&queue), ==, 0);
	munit_assert(!drop_record.failed);
	munit_assert_uint64(drop_record.count[0], ==, 0);
	munit_assert_uint64((uint64_t)(size_t)user, ==, 0);
	munit_assert_uint64(seq_num, ==, 42);

	// push outdated
	chiaki_reorder_queue_push(&queue, 42, (void *)0);
	munit_assert_uint64(chiaki_reorder_queue_count(&queue), ==, 0);
	munit_assert(!drop_record.failed);
	munit_assert_uint64(drop_record.count[0], ==, 1);
	munit_assert_uint64(drop_record.seq_num[0], ==, 42);
	memset(&drop_record, 0, sizeof(drop_record));

	// push until full out of order and try to pull in between
	chiaki_reorder_queue_push(&queue, 46, (void *)1);
	pulled = chiaki_reorder_queue_pull(&queue, &seq_num, &user);
	munit_assert(!pulled);
	chiaki_reorder_queue_push(&queue, 45, (void *)2);
	pulled = chiaki_reorder_queue_pull(&queue, &seq_num, &user);
	munit_assert(!pulled);
	chiaki_reorder_queue_push(&queue, 44, (void *)3);
	pulled = chiaki_reorder_queue_pull(&queue, &seq_num, &user);
	munit_assert(!pulled);
	chiaki_reorder_queue_push(&queue, 43, (void *)4);
	munit_assert(!drop_record.failed);
	for(size_t i=0; i<DROP_RECORD_MAX; i++)
		munit_assert_uint64(drop_record.count[i], ==, 0);

	// push more, because of CHIAKI_REORDER_QUEUE_DROP_STRATEGY_END this should be dropped
	chiaki_reorder_queue_push(&queue, 47, (void *)5);
	munit_assert(!drop_record.failed);
	for(size_t i=0; i<DROP_RECORD_MAX; i++)
		munit_assert_uint64(drop_record.count[i], ==, i == 5 ? 1 : 0);
	munit_assert_uint64(drop_record.seq_num[5], ==, 47);
	memset(&drop_record, 0, sizeof(drop_record));

	// push more with CHIAKI_REORDER_QUEUE_DROP_STRATEGY_BEGIN, so older elements should be dropped
	chiaki_reorder_queue_set_drop_strategy(&queue, CHIAKI_REORDER_QUEUE_DROP_STRATEGY_BEGIN);
	chiaki_reorder_queue_push(&queue, 47, (void *)5);
	munit_assert(!drop_record.failed);
	for(size_t i=0; i<DROP_RECORD_MAX; i++)
		munit_assert_uint64(drop_record.count[i], ==, i == 4 ? 1 : 0);
	munit_assert_uint64(drop_record.seq_num[4], ==, 43);
	memset(&drop_record, 0, sizeof(drop_record));
	
	// pull all, elements should arrive in order
	pulled = chiaki_reorder_queue_pull(&queue, &seq_num, &user);
	munit_assert(pulled);
	munit_assert_uint64(seq_num, ==, 44);
	munit_assert_uint64((uint64_t)(size_t)user, ==, 3);

	pulled = chiaki_reorder_queue_pull(&queue, &seq_num, &user);
	munit_assert(pulled);
	munit_assert_uint64(seq_num, ==, 45);
	munit_assert_uint64((uint64_t)(size_t)user, ==, 2);

	pulled = chiaki_reorder_queue_pull(&queue, &seq_num, &user);
	munit_assert(pulled);
	munit_assert_uint64(seq_num, ==, 46);
	munit_assert_uint64((uint64_t)(size_t)user, ==, 1);

	pulled = chiaki_reorder_queue_pull(&queue, &seq_num, &user);
	munit_assert(pulled);
	munit_assert_uint64(seq_num, ==, 47);
	munit_assert_uint64((uint64_t)(size_t)user, ==, 5);

	// should be empty now again
	pulled = chiaki_reorder_queue_pull(&queue, &seq_num, &user);
	munit_assert(!pulled);
	munit_assert_uint64(chiaki_reorder_queue_count(&queue), ==, 0);

	munit_assert(!drop_record.failed);
	for(size_t i=0; i<DROP_RECORD_MAX; i++)
		munit_assert_uint64(drop_record.count[i], ==, 0);

	// now push something much higher, because of CHIAKI_REORDER_QUEUE_DROP_STRATEGY_BEGIN, the queue should be relocated
	chiaki_reorder_queue_push(&queue, 1337, (void *)6);
	munit_assert_uint64(chiaki_reorder_queue_count(&queue), ==, 1);
	munit_assert(!drop_record.failed);
	for(size_t i=0; i<DROP_RECORD_MAX; i++)
		munit_assert_uint64(drop_record.count[i], ==, 0);

	// and pull again
	pulled = chiaki_reorder_queue_pull(&queue, &seq_num, &user);
	munit_assert(pulled);
	munit_assert_uint64(seq_num, ==, 1337);
	munit_assert_uint64((uint64_t)(size_t)user, ==, 6);
	munit_assert_uint64(chiaki_reorder_queue_count(&queue), ==, 0);

	// same as before, but with an element in the queue that will be dropped
	chiaki_reorder_queue_push(&queue, 1338, (void *)7);
	munit_assert_uint64(chiaki_reorder_queue_count(&queue), ==, 1);
	munit_assert(!drop_record.failed);
	for(size_t i=0; i<DROP_RECORD_MAX; i++)
		munit_assert_uint64(drop_record.count[i], ==, 0);

	chiaki_reorder_queue_push(&queue, 2000, (void *)8);
	munit_assert_uint64(chiaki_reorder_queue_count(&queue), ==, 1);
	munit_assert(!drop_record.failed);
	for(size_t i=0; i<DROP_RECORD_MAX; i++)
		munit_assert_uint64(drop_record.count[i], ==, i == 7 ? 1 : 0);
	munit_assert_uint64(drop_record.seq_num[7], ==, 1338);

	// pull again
	pulled = chiaki_reorder_queue_pull(&queue, &seq_num, &user);
	munit_assert(pulled);
	munit_assert_uint64(seq_num, ==, 2000);
	munit_assert_uint64((uint64_t)(size_t)user, ==, 8);
	munit_assert_uint64(chiaki_reorder_queue_count(&queue), ==, 0);

	chiaki_reorder_queue_fini(&queue);

	return MUNIT_OK;
}


MunitTest tests_reorder_queue[] = {
	{
		"/reorder_queue_16",
		test_reorder_queue_16,
		NULL,
		NULL,
		MUNIT_TEST_OPTION_NONE,
		NULL
	},
	{ NULL, NULL, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL }
};