1 #include "osi/include/fixed_queue.h"
2
3 #include <gtest/gtest.h>
4
5 #include <climits>
6
7 #include "osi/include/allocator.h"
8 #include "osi/include/future.h"
9 #include "osi/include/thread.h"
10
11 static const size_t TEST_QUEUE_SIZE = 10;
12 static const char* DUMMY_DATA_STRING = "Dummy data string";
13 static const char* DUMMY_DATA_STRING1 = "Dummy data string1";
14 static const char* DUMMY_DATA_STRING2 = "Dummy data string2";
15 static const char* DUMMY_DATA_STRING3 = "Dummy data string3";
16 static future_t* received_message_future = NULL;
17
18 static int test_queue_entry_free_counter = 0;
19
20 // Test whether a file descriptor |fd| is readable.
21 // Return true if the file descriptor is readable, otherwise false.
is_fd_readable(int fd)22 static bool is_fd_readable(int fd) {
23 fd_set rfds;
24 struct timeval tv;
25
26 FD_ZERO(&rfds);
27 tv.tv_sec = 0;
28 tv.tv_usec = 0;
29 FD_SET(fd, &rfds);
30 // Only the enqueue_fd should be readable
31 int result = select(FD_SETSIZE, &rfds, NULL, NULL, &tv);
32 EXPECT_TRUE(result >= 0);
33
34 return FD_ISSET(fd, &rfds);
35 }
36
37 // Function for performing dequeue operations from the queue when is ready
fixed_queue_ready(fixed_queue_t * queue,void *)38 static void fixed_queue_ready(fixed_queue_t* queue, void* /* context */) {
39 void* msg = fixed_queue_try_dequeue(queue);
40 EXPECT_TRUE(msg != NULL);
41 future_ready(received_message_future, msg);
42 }
43
test_queue_entry_free_cb(void * data)44 static void test_queue_entry_free_cb(void* data) {
45 // Don't free the data, because we are testing only whether the callback
46 // is called.
47 test_queue_entry_free_counter++;
48 }
49
50 class FixedQueueTest : public ::testing::Test {};
51
TEST_F(FixedQueueTest,test_fixed_queue_new_free)52 TEST_F(FixedQueueTest, test_fixed_queue_new_free) {
53 fixed_queue_t* queue;
54
55 // Test a corner case: queue of size 0
56 queue = fixed_queue_new(0);
57 EXPECT_TRUE(queue != NULL);
58 fixed_queue_free(queue, NULL);
59
60 // Test a corner case: queue of size 1
61 queue = fixed_queue_new(1);
62 EXPECT_TRUE(queue != NULL);
63 fixed_queue_free(queue, NULL);
64
65 // Test a corner case: queue of maximum size
66 queue = fixed_queue_new((size_t)-1);
67 EXPECT_TRUE(queue != NULL);
68 fixed_queue_free(queue, NULL);
69
70 // Test a queue of some size
71 queue = fixed_queue_new(TEST_QUEUE_SIZE);
72 EXPECT_TRUE(queue != NULL);
73 fixed_queue_free(queue, NULL);
74
75 // Test free-ing a NULL queue
76 fixed_queue_free(NULL, NULL);
77 fixed_queue_free(NULL, osi_free);
78 }
79
TEST_F(FixedQueueTest,test_fixed_queue_flush)80 TEST_F(FixedQueueTest, test_fixed_queue_flush) {
81 fixed_queue_t* queue;
82
83 // Test a corner case: queue of size 0 and no callback to free entries
84 queue = fixed_queue_new(0);
85 EXPECT_TRUE(queue != NULL);
86 fixed_queue_flush(queue, NULL);
87 EXPECT_TRUE(fixed_queue_is_empty(queue));
88 fixed_queue_free(queue, osi_free);
89
90 // Test a corner case: queue of size 0 and a callback to free entries
91 queue = fixed_queue_new(0);
92 EXPECT_TRUE(queue != NULL);
93 fixed_queue_flush(queue, osi_free);
94 EXPECT_TRUE(fixed_queue_is_empty(queue));
95 fixed_queue_free(queue, osi_free);
96
97 // Test a queue of some size and no callback to free entries
98 queue = fixed_queue_new(TEST_QUEUE_SIZE);
99 EXPECT_TRUE(queue != NULL);
100 fixed_queue_try_enqueue(queue, (void*)DUMMY_DATA_STRING1);
101 fixed_queue_try_enqueue(queue, (void*)DUMMY_DATA_STRING2);
102 fixed_queue_try_enqueue(queue, (void*)DUMMY_DATA_STRING3);
103 EXPECT_FALSE(fixed_queue_is_empty(queue));
104 fixed_queue_flush(queue, NULL);
105 EXPECT_TRUE(fixed_queue_is_empty(queue));
106 fixed_queue_free(queue, osi_free);
107
108 // Test a queue of some size and a callback to free entries
109 test_queue_entry_free_counter = 0;
110 queue = fixed_queue_new(TEST_QUEUE_SIZE);
111 EXPECT_TRUE(queue != NULL);
112 fixed_queue_try_enqueue(queue, (void*)DUMMY_DATA_STRING1);
113 fixed_queue_try_enqueue(queue, (void*)DUMMY_DATA_STRING2);
114 fixed_queue_try_enqueue(queue, (void*)DUMMY_DATA_STRING3);
115 EXPECT_FALSE(fixed_queue_is_empty(queue));
116 fixed_queue_flush(queue, test_queue_entry_free_cb);
117 EXPECT_TRUE(test_queue_entry_free_counter == 3);
118 EXPECT_TRUE(fixed_queue_is_empty(queue));
119 fixed_queue_free(queue, osi_free);
120 }
121
TEST_F(FixedQueueTest,test_fixed_queue_is_empty)122 TEST_F(FixedQueueTest, test_fixed_queue_is_empty) {
123 fixed_queue_t* queue;
124
125 // Test a NULL queue
126 EXPECT_TRUE(fixed_queue_is_empty(NULL));
127
128 // Test an empty queue
129 queue = fixed_queue_new(TEST_QUEUE_SIZE);
130 ASSERT_TRUE(queue != NULL);
131 EXPECT_TRUE(fixed_queue_is_empty(queue));
132
133 // Test a non-empty queue
134 fixed_queue_try_enqueue(queue, (void*)DUMMY_DATA_STRING);
135 EXPECT_FALSE(fixed_queue_is_empty(queue));
136
137 // Test an empty dequeued queue
138 ASSERT_EQ(DUMMY_DATA_STRING, fixed_queue_try_dequeue(queue));
139 EXPECT_TRUE(fixed_queue_is_empty(queue));
140
141 fixed_queue_free(queue, NULL);
142 }
143
TEST_F(FixedQueueTest,test_fixed_queue_length)144 TEST_F(FixedQueueTest, test_fixed_queue_length) {
145 fixed_queue_t* queue;
146
147 // Test a NULL queue
148 EXPECT_EQ((size_t)0, fixed_queue_length(NULL));
149
150 // Test an empty queue
151 queue = fixed_queue_new(TEST_QUEUE_SIZE);
152 ASSERT_TRUE(queue != NULL);
153 EXPECT_EQ((size_t)0, fixed_queue_length(queue));
154
155 // Test a non-empty queue
156 fixed_queue_try_enqueue(queue, (void*)DUMMY_DATA_STRING);
157 EXPECT_EQ((size_t)1, fixed_queue_length(queue));
158
159 // Test an empty dequeued queue
160 ASSERT_EQ(DUMMY_DATA_STRING, fixed_queue_try_dequeue(queue));
161 EXPECT_EQ((size_t)0, fixed_queue_length(queue));
162
163 fixed_queue_free(queue, NULL);
164 }
165
TEST_F(FixedQueueTest,test_fixed_queue_capacity)166 TEST_F(FixedQueueTest, test_fixed_queue_capacity) {
167 fixed_queue_t* queue;
168
169 // Test a corner case: queue of size 0
170 queue = fixed_queue_new(0);
171 ASSERT_TRUE(queue != NULL);
172 EXPECT_EQ((size_t)0, fixed_queue_capacity(queue));
173 fixed_queue_free(queue, NULL);
174
175 // Test a corner case: queue of size 1
176 queue = fixed_queue_new(1);
177 ASSERT_TRUE(queue != NULL);
178 EXPECT_EQ((size_t)1, fixed_queue_capacity(queue));
179 fixed_queue_free(queue, NULL);
180
181 // Test a corner case: queue of maximum size
182 queue = fixed_queue_new((size_t)-1);
183 ASSERT_TRUE(queue != NULL);
184 EXPECT_EQ((size_t)-1, fixed_queue_capacity(queue));
185 fixed_queue_free(queue, NULL);
186
187 // Test a queue of some size
188 queue = fixed_queue_new(TEST_QUEUE_SIZE);
189 ASSERT_TRUE(queue != NULL);
190 EXPECT_EQ(TEST_QUEUE_SIZE, fixed_queue_capacity(queue));
191 fixed_queue_free(queue, NULL);
192 }
193
TEST_F(FixedQueueTest,test_fixed_queue_enqueue_dequeue)194 TEST_F(FixedQueueTest, test_fixed_queue_enqueue_dequeue) {
195 fixed_queue_t* queue = fixed_queue_new(TEST_QUEUE_SIZE);
196 ASSERT_TRUE(queue != NULL);
197
198 // Test blocking enqueue and blocking dequeue
199 fixed_queue_enqueue(queue, (void*)DUMMY_DATA_STRING);
200 EXPECT_EQ((size_t)1, fixed_queue_length(queue));
201 EXPECT_EQ(DUMMY_DATA_STRING, fixed_queue_dequeue(queue));
202 EXPECT_EQ((size_t)0, fixed_queue_length(queue));
203
204 // Test non-blocking enqueue and non-blocking dequeue
205 EXPECT_TRUE(fixed_queue_try_enqueue(queue, (void*)DUMMY_DATA_STRING));
206 EXPECT_EQ((size_t)1, fixed_queue_length(queue));
207 EXPECT_EQ(DUMMY_DATA_STRING, fixed_queue_try_dequeue(queue));
208 EXPECT_EQ((size_t)0, fixed_queue_length(queue));
209
210 // Test non-blocking enqueue beyond queue capacity
211 for (size_t i = 0; i < TEST_QUEUE_SIZE; i++) {
212 EXPECT_TRUE(fixed_queue_try_enqueue(queue, (void*)DUMMY_DATA_STRING));
213 }
214 // The next enqueue operation is beyond the queue capacity, so it should fail
215 EXPECT_FALSE(fixed_queue_try_enqueue(queue, (void*)DUMMY_DATA_STRING));
216
217 // Test non-blocking dequeue from a queue that is full to max capacity
218 for (size_t i = 0; i < TEST_QUEUE_SIZE; i++) {
219 EXPECT_EQ(DUMMY_DATA_STRING, fixed_queue_try_dequeue(queue));
220 }
221
222 // Test non-blocking dequeue from an empty queue
223 EXPECT_EQ(NULL, fixed_queue_try_dequeue(queue));
224
225 // Test non-blocking dequeue from a NULL queue
226 EXPECT_EQ(NULL, fixed_queue_try_dequeue(NULL));
227
228 fixed_queue_free(queue, NULL);
229 }
230
TEST_F(FixedQueueTest,test_fixed_queue_try_peek_first_last)231 TEST_F(FixedQueueTest, test_fixed_queue_try_peek_first_last) {
232 fixed_queue_t* queue = fixed_queue_new(TEST_QUEUE_SIZE);
233 ASSERT_TRUE(queue != NULL);
234
235 // Test peek first/last from a NULL queue
236 EXPECT_EQ(NULL, fixed_queue_try_peek_first(NULL));
237 EXPECT_EQ(NULL, fixed_queue_try_peek_last(NULL));
238
239 // Test peek first/last from an empty queue
240 EXPECT_EQ(NULL, fixed_queue_try_peek_first(queue));
241 EXPECT_EQ(NULL, fixed_queue_try_peek_last(queue));
242
243 // Test peek first/last from a queue with one element
244 fixed_queue_enqueue(queue, (void*)DUMMY_DATA_STRING1);
245 EXPECT_EQ(DUMMY_DATA_STRING1, fixed_queue_try_peek_first(queue));
246 EXPECT_EQ(DUMMY_DATA_STRING1, fixed_queue_try_peek_last(queue));
247
248 // Test peek first/last from a queue with two elements
249 fixed_queue_enqueue(queue, (void*)DUMMY_DATA_STRING2);
250 EXPECT_EQ(DUMMY_DATA_STRING1, fixed_queue_try_peek_first(queue));
251 EXPECT_EQ(DUMMY_DATA_STRING2, fixed_queue_try_peek_last(queue));
252
253 // Test peek first/last from a queue with three elements
254 fixed_queue_enqueue(queue, (void*)DUMMY_DATA_STRING3);
255 EXPECT_EQ(DUMMY_DATA_STRING1, fixed_queue_try_peek_first(queue));
256 EXPECT_EQ(DUMMY_DATA_STRING3, fixed_queue_try_peek_last(queue));
257
258 fixed_queue_free(queue, NULL);
259 }
260
TEST_F(FixedQueueTest,test_fixed_queue_try_remove_from_queue)261 TEST_F(FixedQueueTest, test_fixed_queue_try_remove_from_queue) {
262 fixed_queue_t* queue = fixed_queue_new(TEST_QUEUE_SIZE);
263 ASSERT_TRUE(queue != NULL);
264
265 // Test removing from a NULL queue
266 EXPECT_EQ(NULL,
267 fixed_queue_try_remove_from_queue(NULL, (void*)DUMMY_DATA_STRING));
268
269 // Test removing from an empty queue
270 EXPECT_EQ(NULL,
271 fixed_queue_try_remove_from_queue(queue, (void*)DUMMY_DATA_STRING));
272
273 // Test removing a queued string from a queue
274 fixed_queue_enqueue(queue, (void*)DUMMY_DATA_STRING1);
275 fixed_queue_enqueue(queue, (void*)DUMMY_DATA_STRING2);
276 fixed_queue_enqueue(queue, (void*)DUMMY_DATA_STRING3);
277 EXPECT_EQ((size_t)3, fixed_queue_length(queue));
278 EXPECT_EQ(DUMMY_DATA_STRING2, fixed_queue_try_remove_from_queue(
279 queue, (void*)DUMMY_DATA_STRING2));
280 EXPECT_EQ((size_t)2, fixed_queue_length(queue));
281 // Removing again should fail
282 EXPECT_EQ(NULL, fixed_queue_try_remove_from_queue(queue,
283 (void*)DUMMY_DATA_STRING2));
284
285 // Test removing a non-queued string from a queue
286 EXPECT_EQ(NULL,
287 fixed_queue_try_remove_from_queue(queue, (void*)DUMMY_DATA_STRING));
288
289 fixed_queue_free(queue, NULL);
290 }
291
TEST_F(FixedQueueTest,test_fixed_queue_get_enqueue_dequeue_fd)292 TEST_F(FixedQueueTest, test_fixed_queue_get_enqueue_dequeue_fd) {
293 fixed_queue_t* queue = fixed_queue_new(TEST_QUEUE_SIZE);
294 ASSERT_TRUE(queue != NULL);
295
296 // Test validity of enqueue and dequeue file descriptors
297 int enqueue_fd = fixed_queue_get_enqueue_fd(queue);
298 int dequeue_fd = fixed_queue_get_dequeue_fd(queue);
299 EXPECT_TRUE(enqueue_fd >= 0);
300 EXPECT_TRUE(dequeue_fd >= 0);
301 EXPECT_TRUE(enqueue_fd < FD_SETSIZE);
302 EXPECT_TRUE(dequeue_fd < FD_SETSIZE);
303
304 // Test the file descriptors of an empty queue
305 // Only the enqueue_fd should be readable
306 EXPECT_TRUE(is_fd_readable(enqueue_fd));
307 EXPECT_FALSE(is_fd_readable(dequeue_fd));
308
309 // Test the file descriptors of a non-empty queue
310 // Both the enqueue_fd and dequeue_fd should be readable
311 fixed_queue_enqueue(queue, (void*)DUMMY_DATA_STRING);
312 EXPECT_TRUE(is_fd_readable(enqueue_fd));
313 EXPECT_TRUE(is_fd_readable(dequeue_fd));
314 fixed_queue_dequeue(queue);
315
316 // Test the file descriptors of a full queue
317 // Only the dequeue_fd should be readable
318 for (size_t i = 0; i < TEST_QUEUE_SIZE; i++) {
319 EXPECT_TRUE(fixed_queue_try_enqueue(queue, (void*)DUMMY_DATA_STRING));
320 }
321 EXPECT_FALSE(is_fd_readable(enqueue_fd));
322 EXPECT_TRUE(is_fd_readable(dequeue_fd));
323
324 fixed_queue_free(queue, NULL);
325 }
326
TEST_F(FixedQueueTest,test_fixed_queue_register_dequeue)327 TEST_F(FixedQueueTest, test_fixed_queue_register_dequeue) {
328 fixed_queue_t* queue = fixed_queue_new(TEST_QUEUE_SIZE);
329 ASSERT_TRUE(queue != NULL);
330
331 received_message_future = future_new();
332 ASSERT_TRUE(received_message_future != NULL);
333
334 thread_t* worker_thread = thread_new("test_fixed_queue_worker_thread");
335 ASSERT_TRUE(worker_thread != NULL);
336
337 fixed_queue_register_dequeue(queue, thread_get_reactor(worker_thread),
338 fixed_queue_ready, NULL);
339
340 // Add a message to the queue, and expect to receive it
341 fixed_queue_enqueue(queue, (void*)DUMMY_DATA_STRING);
342 const char* msg = (const char*)future_await(received_message_future);
343 EXPECT_EQ(DUMMY_DATA_STRING, msg);
344
345 fixed_queue_unregister_dequeue(queue);
346 thread_free(worker_thread);
347 fixed_queue_free(queue, NULL);
348 }
349