comparison spandsp-0.0.6pre17/tests/queue_tests.c @ 4:26cd8f1ef0b1

import spandsp-0.0.6pre17
author Peter Meerwald <pmeerw@cosy.sbg.ac.at>
date Fri, 25 Jun 2010 15:50:58 +0200
parents
children
comparison
equal deleted inserted replaced
3:c6c5a16ce2f2 4:26cd8f1ef0b1
1 /*
2 * SpanDSP - a series of DSP components for telephony
3 *
4 * queue_tests.c
5 *
6 * Written by Steve Underwood <steveu@coppice.org>
7 *
8 * Copyright (C) 2007 Steve Underwood
9 *
10 * All rights reserved.
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2, as
14 * published by the Free Software Foundation.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 * $Id: queue_tests.c,v 1.13 2009/04/11 17:43:04 steveu Exp $
26 */
27
28 /* THIS IS A WORK IN PROGRESS. IT IS NOT FINISHED. */
29
30 /*! \page queue_tests_page Queue tests
31 \section queue_tests_page_sec_1 What does it do?
32 */
33
34 #if defined(HAVE_CONFIG_H)
35 #include <config.h>
36 #endif
37
38 #include <stdlib.h>
39 #include <stdio.h>
40 #include <unistd.h>
41 #include <string.h>
42 #include <assert.h>
43 #include <pthread.h>
44 #include <sched.h>
45
46 //#if defined(WITH_SPANDSP_INTERNALS)
47 #define SPANDSP_EXPOSE_INTERNAL_STRUCTURES
48 //#endif
49
50 #include "spandsp.h"
51
52 #define BUF_LEN 10000
53 #define MSG_LEN 17
54
55 pthread_t thread[2];
56 queue_state_t *queue;
57 volatile int put_oks;
58 volatile int put_misses;
59 volatile int got_oks;
60 volatile int got_misses;
61
62 int total_in;
63 int total_out;
64
65 static void tests_failed(void)
66 {
67 printf("Tests failed\n");
68 exit(2);
69 }
70 /*- End of function --------------------------------------------------------*/
71
72 static void display_queue_pointers(void)
73 {
74 printf("Pointers %d %d %d\n", queue->iptr, queue->optr, queue->len);
75 }
76 /*- End of function --------------------------------------------------------*/
77
78 static void *run_stream_write(void *arg)
79 {
80 uint8_t buf[MSG_LEN];
81 int i;
82 int next;
83
84 printf("Write thread\n");
85 next = 0;
86 for (i = 0; i < MSG_LEN; i++)
87 buf[i] = next;
88 next = (next + 1) & 0xFF;
89 put_oks = 0;
90 put_misses = 0;
91 for (;;)
92 {
93 if (queue_write(queue, buf, MSG_LEN) == MSG_LEN)
94 {
95 for (i = 0; i < MSG_LEN; i++)
96 buf[i] = next;
97 next = (next + 1) & 0xFF;
98 put_oks++;
99 if (put_oks%1000000 == 0)
100 printf("%d puts, %d misses\n", put_oks, put_misses);
101 }
102 else
103 {
104 sched_yield();
105 put_misses++;
106 }
107 }
108 return NULL;
109 }
110 /*- End of function --------------------------------------------------------*/
111
112 static void *run_stream_read(void *arg)
113 {
114 uint8_t buf[MSG_LEN];
115 int i;
116 int len;
117 int next;
118
119 printf("Read thread\n");
120 next = 0;
121 got_oks = 0;
122 got_misses = 0;
123 for (;;)
124 {
125 if ((len = queue_read(queue, buf, MSG_LEN)) >= 0)
126 {
127 if (len != MSG_LEN)
128 {
129 printf("AHH! - len %d\n", len);
130 tests_failed();
131 }
132 for (i = 0; i < len; i++)
133 {
134 if (buf[i] != next)
135 {
136 printf("AHH! - 0x%X 0x%X\n", buf[i], next);
137 tests_failed();
138 }
139 }
140 next = (next + 1) & 0xFF;
141 got_oks++;
142 if (got_oks%1000000 == 0)
143 printf("%d gots, %d misses\n", got_oks, got_misses);
144 }
145 else
146 {
147 sched_yield();
148 got_misses++;
149 }
150 }
151 return NULL;
152 }
153 /*- End of function --------------------------------------------------------*/
154
155 static void threaded_stream_tests(void)
156 {
157 pthread_attr_t attr;
158
159 if ((queue = queue_init(NULL, BUF_LEN, QUEUE_READ_ATOMIC | QUEUE_WRITE_ATOMIC)) == NULL)
160 {
161 printf("Failed to create the queue\n");
162 tests_failed();
163 }
164 pthread_attr_init(&attr);
165 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
166 if (pthread_create(&thread[0], &attr, run_stream_write, NULL))
167 {
168 printf("Failed to create thread\n");
169 tests_failed();
170 }
171 if (pthread_create(&thread[1], &attr, run_stream_read, NULL))
172 {
173 printf("Failed to create thread\n");
174 tests_failed();
175 }
176 for (;;)
177 {
178 sleep(5);
179 printf("Main thread - %d %d\n", put_oks, got_oks);
180 }
181 queue_free(queue);
182 }
183 /*- End of function --------------------------------------------------------*/
184
185 static void *run_message_write(void *arg)
186 {
187 uint8_t buf[MSG_LEN];
188 int i;
189 int next;
190
191 printf("Write thread\n");
192 next = 0;
193 for (i = 0; i < MSG_LEN; i++)
194 buf[i] = next;
195 next = (next + 1) & 0xFF;
196 put_oks = 0;
197 put_misses = 0;
198 for (;;)
199 {
200 if (queue_write_msg(queue, buf, MSG_LEN) == MSG_LEN)
201 {
202 for (i = 0; i < MSG_LEN; i++)
203 buf[i] = next;
204 next = (next + 1) & 0xFF;
205 put_oks++;
206 if (put_oks%1000000 == 0)
207 printf("%d puts, %d misses\n", put_oks, put_misses);
208 }
209 else
210 {
211 sched_yield();
212 put_misses++;
213 }
214 }
215 return NULL;
216 }
217 /*- End of function --------------------------------------------------------*/
218
219 static void *run_message_read(void *arg)
220 {
221 uint8_t buf[1024];
222 int i;
223 int len;
224 int next;
225
226 printf("Read thread\n");
227 next = 0;
228 got_oks = 0;
229 got_misses = 0;
230 for (;;)
231 {
232 if ((len = queue_read_msg(queue, buf, 1024)) >= 0)
233 {
234 if (len != MSG_LEN)
235 {
236 printf("AHH! - len %d\n", len);
237 tests_failed();
238 }
239 for (i = 0; i < len; i++)
240 {
241 if (buf[i] != next)
242 {
243 printf("AHH! - 0x%X 0x%X\n", buf[i], next);
244 tests_failed();
245 }
246 }
247 next = (next + 1) & 0xFF;
248 got_oks++;
249 if (got_oks%1000000 == 0)
250 printf("%d gots, %d misses\n", got_oks, got_misses);
251 }
252 else
253 {
254 sched_yield();
255 got_misses++;
256 }
257 }
258 return NULL;
259 }
260 /*- End of function --------------------------------------------------------*/
261
262 static void threaded_message_tests(void)
263 {
264 pthread_attr_t attr;
265
266 if ((queue = queue_init(NULL, BUF_LEN, QUEUE_READ_ATOMIC | QUEUE_WRITE_ATOMIC)) == NULL)
267 {
268 printf("Failed to create the queue\n");
269 tests_failed();
270 }
271 pthread_attr_init(&attr);
272 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
273 if (pthread_create(&thread[0], &attr, run_message_write, NULL))
274 {
275 printf("Failed to create thread\n");
276 tests_failed();
277 }
278 if (pthread_create(&thread[1], &attr, run_message_read, NULL))
279 {
280 printf("Failed to create thread\n");
281 tests_failed();
282 }
283 for (;;)
284 {
285 sleep(5);
286 printf("Main thread - %d %d\n", put_oks, got_oks);
287 }
288 queue_free(queue);
289 }
290 /*- End of function --------------------------------------------------------*/
291
292 static void check_contents(int total_in, int total_out)
293 {
294 if (queue_contents(queue) != (total_in - total_out))
295 {
296 printf("Contents = %d (%d)\n", queue_contents(queue), (total_in - total_out));
297 display_queue_pointers();
298 tests_failed();
299 }
300 if (queue_free_space(queue) != BUF_LEN - (total_in - total_out))
301 {
302 printf("Free space = %d (%d)\n", queue_free_space(queue), BUF_LEN - (total_in - total_out));
303 display_queue_pointers();
304 tests_failed();
305 }
306 }
307 /*- End of function --------------------------------------------------------*/
308
309 static int monitored_queue_write(const uint8_t buf[], int len)
310 {
311 int lenx;
312
313 lenx = queue_write(queue, buf, len);
314 if (lenx >= 0)
315 total_in += lenx;
316 check_contents(total_in, total_out);
317 return lenx;
318 }
319 /*- End of function --------------------------------------------------------*/
320
321 static int monitored_queue_write_byte(const uint8_t buf)
322 {
323 int res;
324
325 if ((res = queue_write_byte(queue, buf)) >= 0)
326 total_in++;
327 check_contents(total_in, total_out);
328 return res;
329 }
330 /*- End of function --------------------------------------------------------*/
331
332 static int monitored_queue_read(uint8_t buf[], int len)
333 {
334 int lenx;
335
336 lenx = queue_read(queue, buf, len);
337 if (lenx >= 0)
338 total_out += lenx;
339 check_contents(total_in, total_out);
340 return lenx;
341 }
342 /*- End of function --------------------------------------------------------*/
343
344 static int monitored_queue_read_byte(void)
345 {
346 int res;
347
348 if ((res = queue_read_byte(queue)) >= 0)
349 total_out++;
350 check_contents(total_in, total_out);
351 return res;
352 }
353 /*- End of function --------------------------------------------------------*/
354
355 static void functional_stream_tests(void)
356 {
357 uint8_t buf[MSG_LEN];
358 int i;
359 int res;
360
361 total_in = 0;
362 total_out = 0;
363
364 for (i = 0; i < MSG_LEN; i++)
365 buf[i] = i;
366 if ((queue = queue_init(NULL, BUF_LEN, QUEUE_READ_ATOMIC | QUEUE_WRITE_ATOMIC)) == NULL)
367 {
368 printf("Failed to create the queue\n");
369 tests_failed();
370 }
371 check_contents(total_in, total_out);
372 /* Half fill the buffer, and check we can get out what we put in. */
373 for (i = 1; i < 5000; i++)
374 {
375 if (monitored_queue_write_byte(i & 0xFF) != 1)
376 {
377 printf("Byte by byte full at %d/%d\n", i, BUF_LEN);
378 tests_failed();
379 }
380 }
381 for (i = 1; i < 5001; i++)
382 {
383 if ((res = monitored_queue_read_byte()) != (i & 0xFF))
384 break;
385 }
386 printf("Byte by byte read breaks at %d (expected %d) - %d\n", i, 5000, res);
387 if (i != 5000)
388 tests_failed();
389 /* Now completely fill the buffer, and we should roll around the end. Check we can
390 get out what we put in. */
391 for (i = 1; i < 20000; i++)
392 {
393 if (monitored_queue_write_byte(i & 0xFF) != 1)
394 break;
395 }
396 printf("Byte by byte full at %d (expected %d)\n", i, 10001);
397 if (i != 10001)
398 tests_failed();
399 for (i = 1; i < 20000; i++)
400 {
401 if ((res = monitored_queue_read_byte()) != (i & 0xFF))
402 break;
403 }
404 printf("Byte by byte read breaks at %d (expected %d) - %d\n", i, 10001, res);
405 if (i != 10001)
406 tests_failed();
407 /* Fill the buffer, checking the contents grow correctly */
408 for (i = 1; i < 1000; i++)
409 {
410 if (monitored_queue_write(buf, MSG_LEN) != MSG_LEN)
411 break;
412 }
413 printf("Full at chunk %d (expected %d)\n", i, BUF_LEN/MSG_LEN + 1);
414 if (i != BUF_LEN/MSG_LEN + 1)
415 tests_failed();
416 if (monitored_queue_write(buf, 5) == 5)
417 {
418 printf("Write of 5 succeeded\n");
419 tests_failed();
420 }
421 if (monitored_queue_write(buf, 4) != 4)
422 {
423 printf("Write of 4 failed\n");
424 tests_failed();
425 }
426 /* Now full. Empty a little, and refill around the end */
427 if (monitored_queue_read(buf, MSG_LEN) != MSG_LEN)
428 {
429 printf("Read failed\n");
430 tests_failed();
431 }
432 if (monitored_queue_write(buf, MSG_LEN) != MSG_LEN)
433 {
434 printf("Write failed\n");
435 tests_failed();
436 }
437 /* Empty completely, checking the contents shrink correctly */
438 for (;;)
439 {
440 if (monitored_queue_read(buf, MSG_LEN) != MSG_LEN)
441 break;
442 }
443 if (monitored_queue_read(buf, 4) != 4)
444 {
445 printf("Read failed\n");
446 tests_failed();
447 }
448 /* Nudge around the buffer */
449 for (i = 1; i < 588; i++)
450 {
451 if (monitored_queue_write(buf, MSG_LEN) != MSG_LEN)
452 {
453 printf("Write failed\n");
454 tests_failed();
455 }
456 if (monitored_queue_read(buf, MSG_LEN) != MSG_LEN)
457 {
458 printf("Read failed\n");
459 tests_failed();
460 }
461 }
462 /* Fill the buffer, checking the contents grow correctly */
463 for (i = 1; i < 1000; i++)
464 {
465 if (monitored_queue_write(buf, MSG_LEN) != MSG_LEN)
466 break;
467 }
468 printf("Full at chunk %d (expected %d)\n", i, BUF_LEN/MSG_LEN + 1);
469 if (i != BUF_LEN/MSG_LEN + 1)
470 tests_failed();
471 display_queue_pointers();
472 if (monitored_queue_read(buf, MSG_LEN) != MSG_LEN)
473 {
474 printf("Read failed\n");
475 tests_failed();
476 }
477 if (monitored_queue_write(buf, MSG_LEN) != MSG_LEN)
478 {
479 printf("Write failed\n");
480 tests_failed();
481 }
482 display_queue_pointers();
483 for (i = 1; i < 5000; i++)
484 {
485 if (monitored_queue_read(buf, MSG_LEN) != MSG_LEN)
486 {
487 printf("Read failed\n");
488 tests_failed();
489 }
490 if (monitored_queue_write(buf, MSG_LEN) != MSG_LEN)
491 {
492 printf("Write failed\n");
493 tests_failed();
494 }
495 }
496 display_queue_pointers();
497 if (monitored_queue_write(buf, 5) == 5)
498 {
499 printf("Write of 5 succeeded\n");
500 tests_failed();
501 }
502 if (monitored_queue_write(buf, 4) != 4)
503 {
504 printf("Write of 4 failed\n");
505 tests_failed();
506 }
507 display_queue_pointers();
508 for (i = 1; i < 5000; i++)
509 {
510 if (monitored_queue_read(buf, MSG_LEN) != MSG_LEN)
511 {
512 printf("Read failed\n");
513 tests_failed();
514 }
515 if (monitored_queue_write(buf, MSG_LEN) != MSG_LEN)
516 {
517 printf("Write failed\n");
518 tests_failed();
519 }
520 }
521 display_queue_pointers();
522 queue_free(queue);
523 }
524 /*- End of function --------------------------------------------------------*/
525
526 static int monitored_queue_write_msg(const uint8_t buf[], int len)
527 {
528 int lenx;
529
530 lenx = queue_write_msg(queue, buf, len);
531 if (lenx >= 0)
532 total_in += lenx + sizeof(uint16_t);
533 check_contents(total_in, total_out);
534 return lenx;
535 }
536 /*- End of function --------------------------------------------------------*/
537
538 static int monitored_queue_read_msg(uint8_t buf[], int len)
539 {
540 int lenx;
541
542 lenx = queue_read_msg(queue, buf, len);
543 if (lenx >= 0)
544 total_out += lenx + sizeof(uint16_t);
545 check_contents(total_in, total_out);
546 return lenx;
547 }
548 /*- End of function --------------------------------------------------------*/
549
550 static void functional_message_tests(void)
551 {
552 uint8_t buf[MSG_LEN];
553 int i;
554 int len;
555
556 total_in = 0;
557 total_out = 0;
558
559 for (i = 0; i < MSG_LEN; i++)
560 buf[i] = i;
561 if ((queue = queue_init(NULL, BUF_LEN, QUEUE_READ_ATOMIC | QUEUE_WRITE_ATOMIC)) == NULL)
562 {
563 printf("Failed to create the queue\n");
564 tests_failed();
565 }
566 check_contents(total_in, total_out);
567 /* Fill the buffer, checking the contents grow correctly */
568 for (i = 1; i < 1000; i++)
569 {
570 if (monitored_queue_write_msg(buf, MSG_LEN) != MSG_LEN)
571 break;
572 }
573 printf("Full at chunk %d (expected %u)\n", i, BUF_LEN/(MSG_LEN + sizeof(uint16_t)) + 1);
574 if (i != BUF_LEN/(MSG_LEN + sizeof(uint16_t)) + 1)
575 tests_failed();
576 if ((len = monitored_queue_write_msg(buf, 5)) == 5)
577 {
578 printf("Write of 5 succeeded\n");
579 tests_failed();
580 }
581 if ((len = monitored_queue_write_msg(buf, 4)) != 4)
582 {
583 printf("Write of 4 failed\n");
584 tests_failed();
585 }
586 /* Now full. Empty a little, and refill around the end */
587 if ((len = monitored_queue_read_msg(buf, MSG_LEN)) != MSG_LEN)
588 {
589 printf("Read failed - %d\n", len);
590 tests_failed();
591 }
592 if ((len = monitored_queue_write_msg(buf, MSG_LEN)) != MSG_LEN)
593 {
594 printf("Write failed - %d\n", len);
595 tests_failed();
596 }
597 /* Empty completely, checking the contents shrink correctly */
598 for (;;)
599 {
600 if ((len = monitored_queue_read_msg(buf, MSG_LEN)) != MSG_LEN)
601 break;
602 }
603 if (len != 4)
604 {
605 printf("Read failed - %d\n", len);
606 tests_failed();
607 }
608 /* We should now have one MSG_LEN message in the buffer */
609 /* Nudge around the buffer */
610 for (i = 1; i < 527; i++)
611 {
612 if ((len = monitored_queue_write_msg(buf, MSG_LEN)) != MSG_LEN)
613 {
614 printf("Write failed - %d\n", len);
615 tests_failed();
616 }
617 if ((len = monitored_queue_read_msg(buf, MSG_LEN)) != MSG_LEN)
618 {
619 printf("Read failed - %d\n", len);
620 tests_failed();
621 }
622 }
623 /* Fill the buffer, checking the contents grow correctly */
624 for (i = 1; i < 1000; i++)
625 {
626 if ((len = monitored_queue_write_msg(buf, MSG_LEN)) != MSG_LEN)
627 break;
628 }
629 printf("Free space = %d (%d)\n", queue_free_space(queue), BUF_LEN - (total_in - total_out));
630 display_queue_pointers();
631 printf("Full at chunk %d (expected %u)\n", i, BUF_LEN/(MSG_LEN + sizeof(uint16_t)));
632 if (i != BUF_LEN/(MSG_LEN + sizeof(uint16_t)))
633 tests_failed();
634 display_queue_pointers();
635
636 if ((len = monitored_queue_read_msg(buf, MSG_LEN)) != MSG_LEN)
637 {
638 printf("Read failed - %d\n", len);
639 tests_failed();
640 }
641 if ((len = monitored_queue_write_msg(buf, MSG_LEN)) != MSG_LEN)
642 {
643 printf("Write failed - %d\n", len);
644 tests_failed();
645 }
646 display_queue_pointers();
647 for (i = 1; i < 5000; i++)
648 {
649 if ((len = monitored_queue_read_msg(buf, MSG_LEN)) != MSG_LEN)
650 {
651 printf("Read failed - %d\n", len);
652 tests_failed();
653 }
654 if ((len = monitored_queue_write_msg(buf, MSG_LEN)) != MSG_LEN)
655 {
656 printf("Write failed - %d\n", len);
657 tests_failed();
658 }
659 }
660 display_queue_pointers();
661 if ((len = monitored_queue_write_msg(buf, 5)) == 5)
662 {
663 printf("Write of 5 succeeded\n");
664 tests_failed();
665 }
666 if ((len = monitored_queue_write_msg(buf, 4)) != 4)
667 {
668 printf("Write of 4 failed\n");
669 tests_failed();
670 }
671 display_queue_pointers();
672 for (i = 1; i < 5000; i++)
673 {
674 if (i == 527)
675 {
676 if ((len = monitored_queue_read_msg(buf, MSG_LEN)) != 4)
677 {
678 printf("Read failed - %d\n", len);
679 tests_failed();
680 }
681 }
682 if ((len = monitored_queue_read_msg(buf, MSG_LEN)) != MSG_LEN)
683 {
684 printf("Read failed - %d\n", len);
685 tests_failed();
686 }
687 if ((len = monitored_queue_write_msg(buf, MSG_LEN)) != MSG_LEN)
688 {
689 printf("Write failed - %d\n", len);
690 tests_failed();
691 }
692 }
693 display_queue_pointers();
694 queue_free(queue);
695 }
696 /*- End of function --------------------------------------------------------*/
697
698 int main(int argc, char *argv[])
699 {
700 int threaded_messages;
701 int threaded_streams;
702 int opt;
703
704 threaded_messages = FALSE;
705 threaded_streams = FALSE;
706 while ((opt = getopt(argc, argv, "ms")) != -1)
707 {
708 switch (opt)
709 {
710 case 'm':
711 threaded_messages = TRUE;
712 break;
713 case 's':
714 threaded_streams = TRUE;
715 break;
716 }
717 }
718
719 /* Test the basic functionality of the queueing code in stream and message modes */
720 printf("Stream mode functional tests\n");
721 functional_stream_tests();
722 printf("Message mode functional tests\n");
723 functional_message_tests();
724
725 /* Run separate write and read threads for a while, to verify there are no locking
726 issues. */
727 if (threaded_streams)
728 {
729 printf("Stream mode threaded tests\n");
730 threaded_stream_tests();
731 }
732 if (threaded_messages)
733 {
734 printf("Message mode threaded tests\n");
735 threaded_message_tests();
736 }
737 return 0;
738 }
739 /*- End of function --------------------------------------------------------*/
740 /*- End of file ------------------------------------------------------------*/

Repositories maintained by Peter Meerwald, pmeerw@pmeerw.net.