Mercurial > hg > audiostuff
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/spandsp-0.0.6pre17/tests/queue_tests.c Fri Jun 25 15:50:58 2010 +0200 @@ -0,0 +1,740 @@ +/* + * SpanDSP - a series of DSP components for telephony + * + * queue_tests.c + * + * Written by Steve Underwood <steveu@coppice.org> + * + * Copyright (C) 2007 Steve Underwood + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * $Id: queue_tests.c,v 1.13 2009/04/11 17:43:04 steveu Exp $ + */ + +/* THIS IS A WORK IN PROGRESS. IT IS NOT FINISHED. */ + +/*! \page queue_tests_page Queue tests +\section queue_tests_page_sec_1 What does it do? +*/ + +#if defined(HAVE_CONFIG_H) +#include <config.h> +#endif + +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> +#include <string.h> +#include <assert.h> +#include <pthread.h> +#include <sched.h> + +//#if defined(WITH_SPANDSP_INTERNALS) +#define SPANDSP_EXPOSE_INTERNAL_STRUCTURES +//#endif + +#include "spandsp.h" + +#define BUF_LEN 10000 +#define MSG_LEN 17 + +pthread_t thread[2]; +queue_state_t *queue; +volatile int put_oks; +volatile int put_misses; +volatile int got_oks; +volatile int got_misses; + +int total_in; +int total_out; + +static void tests_failed(void) +{ + printf("Tests failed\n"); + exit(2); +} +/*- End of function --------------------------------------------------------*/ + +static void display_queue_pointers(void) +{ + printf("Pointers %d %d %d\n", queue->iptr, queue->optr, queue->len); +} +/*- End of function --------------------------------------------------------*/ + +static void *run_stream_write(void *arg) +{ + uint8_t buf[MSG_LEN]; + int i; + int next; + + printf("Write thread\n"); + next = 0; + for (i = 0; i < MSG_LEN; i++) + buf[i] = next; + next = (next + 1) & 0xFF; + put_oks = 0; + put_misses = 0; + for (;;) + { + if (queue_write(queue, buf, MSG_LEN) == MSG_LEN) + { + for (i = 0; i < MSG_LEN; i++) + buf[i] = next; + next = (next + 1) & 0xFF; + put_oks++; + if (put_oks%1000000 == 0) + printf("%d puts, %d misses\n", put_oks, put_misses); + } + else + { + sched_yield(); + put_misses++; + } + } + return NULL; +} +/*- End of function --------------------------------------------------------*/ + +static void *run_stream_read(void *arg) +{ + uint8_t buf[MSG_LEN]; + int i; + int len; + int next; + + printf("Read thread\n"); + next = 0; + got_oks = 0; + got_misses = 0; + for (;;) + { + if ((len = queue_read(queue, buf, MSG_LEN)) >= 0) + { + if (len != MSG_LEN) + { + printf("AHH! - len %d\n", len); + tests_failed(); + } + for (i = 0; i < len; i++) + { + if (buf[i] != next) + { + printf("AHH! - 0x%X 0x%X\n", buf[i], next); + tests_failed(); + } + } + next = (next + 1) & 0xFF; + got_oks++; + if (got_oks%1000000 == 0) + printf("%d gots, %d misses\n", got_oks, got_misses); + } + else + { + sched_yield(); + got_misses++; + } + } + return NULL; +} +/*- End of function --------------------------------------------------------*/ + +static void threaded_stream_tests(void) +{ + pthread_attr_t attr; + + if ((queue = queue_init(NULL, BUF_LEN, QUEUE_READ_ATOMIC | QUEUE_WRITE_ATOMIC)) == NULL) + { + printf("Failed to create the queue\n"); + tests_failed(); + } + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + if (pthread_create(&thread[0], &attr, run_stream_write, NULL)) + { + printf("Failed to create thread\n"); + tests_failed(); + } + if (pthread_create(&thread[1], &attr, run_stream_read, NULL)) + { + printf("Failed to create thread\n"); + tests_failed(); + } + for (;;) + { + sleep(5); + printf("Main thread - %d %d\n", put_oks, got_oks); + } + queue_free(queue); +} +/*- End of function --------------------------------------------------------*/ + +static void *run_message_write(void *arg) +{ + uint8_t buf[MSG_LEN]; + int i; + int next; + + printf("Write thread\n"); + next = 0; + for (i = 0; i < MSG_LEN; i++) + buf[i] = next; + next = (next + 1) & 0xFF; + put_oks = 0; + put_misses = 0; + for (;;) + { + if (queue_write_msg(queue, buf, MSG_LEN) == MSG_LEN) + { + for (i = 0; i < MSG_LEN; i++) + buf[i] = next; + next = (next + 1) & 0xFF; + put_oks++; + if (put_oks%1000000 == 0) + printf("%d puts, %d misses\n", put_oks, put_misses); + } + else + { + sched_yield(); + put_misses++; + } + } + return NULL; +} +/*- End of function --------------------------------------------------------*/ + +static void *run_message_read(void *arg) +{ + uint8_t buf[1024]; + int i; + int len; + int next; + + printf("Read thread\n"); + next = 0; + got_oks = 0; + got_misses = 0; + for (;;) + { + if ((len = queue_read_msg(queue, buf, 1024)) >= 0) + { + if (len != MSG_LEN) + { + printf("AHH! - len %d\n", len); + tests_failed(); + } + for (i = 0; i < len; i++) + { + if (buf[i] != next) + { + printf("AHH! - 0x%X 0x%X\n", buf[i], next); + tests_failed(); + } + } + next = (next + 1) & 0xFF; + got_oks++; + if (got_oks%1000000 == 0) + printf("%d gots, %d misses\n", got_oks, got_misses); + } + else + { + sched_yield(); + got_misses++; + } + } + return NULL; +} +/*- End of function --------------------------------------------------------*/ + +static void threaded_message_tests(void) +{ + pthread_attr_t attr; + + if ((queue = queue_init(NULL, BUF_LEN, QUEUE_READ_ATOMIC | QUEUE_WRITE_ATOMIC)) == NULL) + { + printf("Failed to create the queue\n"); + tests_failed(); + } + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + if (pthread_create(&thread[0], &attr, run_message_write, NULL)) + { + printf("Failed to create thread\n"); + tests_failed(); + } + if (pthread_create(&thread[1], &attr, run_message_read, NULL)) + { + printf("Failed to create thread\n"); + tests_failed(); + } + for (;;) + { + sleep(5); + printf("Main thread - %d %d\n", put_oks, got_oks); + } + queue_free(queue); +} +/*- End of function --------------------------------------------------------*/ + +static void check_contents(int total_in, int total_out) +{ + if (queue_contents(queue) != (total_in - total_out)) + { + printf("Contents = %d (%d)\n", queue_contents(queue), (total_in - total_out)); + display_queue_pointers(); + tests_failed(); + } + if (queue_free_space(queue) != BUF_LEN - (total_in - total_out)) + { + printf("Free space = %d (%d)\n", queue_free_space(queue), BUF_LEN - (total_in - total_out)); + display_queue_pointers(); + tests_failed(); + } +} +/*- End of function --------------------------------------------------------*/ + +static int monitored_queue_write(const uint8_t buf[], int len) +{ + int lenx; + + lenx = queue_write(queue, buf, len); + if (lenx >= 0) + total_in += lenx; + check_contents(total_in, total_out); + return lenx; +} +/*- End of function --------------------------------------------------------*/ + +static int monitored_queue_write_byte(const uint8_t buf) +{ + int res; + + if ((res = queue_write_byte(queue, buf)) >= 0) + total_in++; + check_contents(total_in, total_out); + return res; +} +/*- End of function --------------------------------------------------------*/ + +static int monitored_queue_read(uint8_t buf[], int len) +{ + int lenx; + + lenx = queue_read(queue, buf, len); + if (lenx >= 0) + total_out += lenx; + check_contents(total_in, total_out); + return lenx; +} +/*- End of function --------------------------------------------------------*/ + +static int monitored_queue_read_byte(void) +{ + int res; + + if ((res = queue_read_byte(queue)) >= 0) + total_out++; + check_contents(total_in, total_out); + return res; +} +/*- End of function --------------------------------------------------------*/ + +static void functional_stream_tests(void) +{ + uint8_t buf[MSG_LEN]; + int i; + int res; + + total_in = 0; + total_out = 0; + + for (i = 0; i < MSG_LEN; i++) + buf[i] = i; + if ((queue = queue_init(NULL, BUF_LEN, QUEUE_READ_ATOMIC | QUEUE_WRITE_ATOMIC)) == NULL) + { + printf("Failed to create the queue\n"); + tests_failed(); + } + check_contents(total_in, total_out); + /* Half fill the buffer, and check we can get out what we put in. */ + for (i = 1; i < 5000; i++) + { + if (monitored_queue_write_byte(i & 0xFF) != 1) + { + printf("Byte by byte full at %d/%d\n", i, BUF_LEN); + tests_failed(); + } + } + for (i = 1; i < 5001; i++) + { + if ((res = monitored_queue_read_byte()) != (i & 0xFF)) + break; + } + printf("Byte by byte read breaks at %d (expected %d) - %d\n", i, 5000, res); + if (i != 5000) + tests_failed(); + /* Now completely fill the buffer, and we should roll around the end. Check we can + get out what we put in. */ + for (i = 1; i < 20000; i++) + { + if (monitored_queue_write_byte(i & 0xFF) != 1) + break; + } + printf("Byte by byte full at %d (expected %d)\n", i, 10001); + if (i != 10001) + tests_failed(); + for (i = 1; i < 20000; i++) + { + if ((res = monitored_queue_read_byte()) != (i & 0xFF)) + break; + } + printf("Byte by byte read breaks at %d (expected %d) - %d\n", i, 10001, res); + if (i != 10001) + tests_failed(); + /* Fill the buffer, checking the contents grow correctly */ + for (i = 1; i < 1000; i++) + { + if (monitored_queue_write(buf, MSG_LEN) != MSG_LEN) + break; + } + printf("Full at chunk %d (expected %d)\n", i, BUF_LEN/MSG_LEN + 1); + if (i != BUF_LEN/MSG_LEN + 1) + tests_failed(); + if (monitored_queue_write(buf, 5) == 5) + { + printf("Write of 5 succeeded\n"); + tests_failed(); + } + if (monitored_queue_write(buf, 4) != 4) + { + printf("Write of 4 failed\n"); + tests_failed(); + } + /* Now full. Empty a little, and refill around the end */ + if (monitored_queue_read(buf, MSG_LEN) != MSG_LEN) + { + printf("Read failed\n"); + tests_failed(); + } + if (monitored_queue_write(buf, MSG_LEN) != MSG_LEN) + { + printf("Write failed\n"); + tests_failed(); + } + /* Empty completely, checking the contents shrink correctly */ + for (;;) + { + if (monitored_queue_read(buf, MSG_LEN) != MSG_LEN) + break; + } + if (monitored_queue_read(buf, 4) != 4) + { + printf("Read failed\n"); + tests_failed(); + } + /* Nudge around the buffer */ + for (i = 1; i < 588; i++) + { + if (monitored_queue_write(buf, MSG_LEN) != MSG_LEN) + { + printf("Write failed\n"); + tests_failed(); + } + if (monitored_queue_read(buf, MSG_LEN) != MSG_LEN) + { + printf("Read failed\n"); + tests_failed(); + } + } + /* Fill the buffer, checking the contents grow correctly */ + for (i = 1; i < 1000; i++) + { + if (monitored_queue_write(buf, MSG_LEN) != MSG_LEN) + break; + } + printf("Full at chunk %d (expected %d)\n", i, BUF_LEN/MSG_LEN + 1); + if (i != BUF_LEN/MSG_LEN + 1) + tests_failed(); + display_queue_pointers(); + if (monitored_queue_read(buf, MSG_LEN) != MSG_LEN) + { + printf("Read failed\n"); + tests_failed(); + } + if (monitored_queue_write(buf, MSG_LEN) != MSG_LEN) + { + printf("Write failed\n"); + tests_failed(); + } + display_queue_pointers(); + for (i = 1; i < 5000; i++) + { + if (monitored_queue_read(buf, MSG_LEN) != MSG_LEN) + { + printf("Read failed\n"); + tests_failed(); + } + if (monitored_queue_write(buf, MSG_LEN) != MSG_LEN) + { + printf("Write failed\n"); + tests_failed(); + } + } + display_queue_pointers(); + if (monitored_queue_write(buf, 5) == 5) + { + printf("Write of 5 succeeded\n"); + tests_failed(); + } + if (monitored_queue_write(buf, 4) != 4) + { + printf("Write of 4 failed\n"); + tests_failed(); + } + display_queue_pointers(); + for (i = 1; i < 5000; i++) + { + if (monitored_queue_read(buf, MSG_LEN) != MSG_LEN) + { + printf("Read failed\n"); + tests_failed(); + } + if (monitored_queue_write(buf, MSG_LEN) != MSG_LEN) + { + printf("Write failed\n"); + tests_failed(); + } + } + display_queue_pointers(); + queue_free(queue); +} +/*- End of function --------------------------------------------------------*/ + +static int monitored_queue_write_msg(const uint8_t buf[], int len) +{ + int lenx; + + lenx = queue_write_msg(queue, buf, len); + if (lenx >= 0) + total_in += lenx + sizeof(uint16_t); + check_contents(total_in, total_out); + return lenx; +} +/*- End of function --------------------------------------------------------*/ + +static int monitored_queue_read_msg(uint8_t buf[], int len) +{ + int lenx; + + lenx = queue_read_msg(queue, buf, len); + if (lenx >= 0) + total_out += lenx + sizeof(uint16_t); + check_contents(total_in, total_out); + return lenx; +} +/*- End of function --------------------------------------------------------*/ + +static void functional_message_tests(void) +{ + uint8_t buf[MSG_LEN]; + int i; + int len; + + total_in = 0; + total_out = 0; + + for (i = 0; i < MSG_LEN; i++) + buf[i] = i; + if ((queue = queue_init(NULL, BUF_LEN, QUEUE_READ_ATOMIC | QUEUE_WRITE_ATOMIC)) == NULL) + { + printf("Failed to create the queue\n"); + tests_failed(); + } + check_contents(total_in, total_out); + /* Fill the buffer, checking the contents grow correctly */ + for (i = 1; i < 1000; i++) + { + if (monitored_queue_write_msg(buf, MSG_LEN) != MSG_LEN) + break; + } + printf("Full at chunk %d (expected %u)\n", i, BUF_LEN/(MSG_LEN + sizeof(uint16_t)) + 1); + if (i != BUF_LEN/(MSG_LEN + sizeof(uint16_t)) + 1) + tests_failed(); + if ((len = monitored_queue_write_msg(buf, 5)) == 5) + { + printf("Write of 5 succeeded\n"); + tests_failed(); + } + if ((len = monitored_queue_write_msg(buf, 4)) != 4) + { + printf("Write of 4 failed\n"); + tests_failed(); + } + /* Now full. Empty a little, and refill around the end */ + if ((len = monitored_queue_read_msg(buf, MSG_LEN)) != MSG_LEN) + { + printf("Read failed - %d\n", len); + tests_failed(); + } + if ((len = monitored_queue_write_msg(buf, MSG_LEN)) != MSG_LEN) + { + printf("Write failed - %d\n", len); + tests_failed(); + } + /* Empty completely, checking the contents shrink correctly */ + for (;;) + { + if ((len = monitored_queue_read_msg(buf, MSG_LEN)) != MSG_LEN) + break; + } + if (len != 4) + { + printf("Read failed - %d\n", len); + tests_failed(); + } + /* We should now have one MSG_LEN message in the buffer */ + /* Nudge around the buffer */ + for (i = 1; i < 527; i++) + { + if ((len = monitored_queue_write_msg(buf, MSG_LEN)) != MSG_LEN) + { + printf("Write failed - %d\n", len); + tests_failed(); + } + if ((len = monitored_queue_read_msg(buf, MSG_LEN)) != MSG_LEN) + { + printf("Read failed - %d\n", len); + tests_failed(); + } + } + /* Fill the buffer, checking the contents grow correctly */ + for (i = 1; i < 1000; i++) + { + if ((len = monitored_queue_write_msg(buf, MSG_LEN)) != MSG_LEN) + break; + } + printf("Free space = %d (%d)\n", queue_free_space(queue), BUF_LEN - (total_in - total_out)); + display_queue_pointers(); + printf("Full at chunk %d (expected %u)\n", i, BUF_LEN/(MSG_LEN + sizeof(uint16_t))); + if (i != BUF_LEN/(MSG_LEN + sizeof(uint16_t))) + tests_failed(); + display_queue_pointers(); + + if ((len = monitored_queue_read_msg(buf, MSG_LEN)) != MSG_LEN) + { + printf("Read failed - %d\n", len); + tests_failed(); + } + if ((len = monitored_queue_write_msg(buf, MSG_LEN)) != MSG_LEN) + { + printf("Write failed - %d\n", len); + tests_failed(); + } + display_queue_pointers(); + for (i = 1; i < 5000; i++) + { + if ((len = monitored_queue_read_msg(buf, MSG_LEN)) != MSG_LEN) + { + printf("Read failed - %d\n", len); + tests_failed(); + } + if ((len = monitored_queue_write_msg(buf, MSG_LEN)) != MSG_LEN) + { + printf("Write failed - %d\n", len); + tests_failed(); + } + } + display_queue_pointers(); + if ((len = monitored_queue_write_msg(buf, 5)) == 5) + { + printf("Write of 5 succeeded\n"); + tests_failed(); + } + if ((len = monitored_queue_write_msg(buf, 4)) != 4) + { + printf("Write of 4 failed\n"); + tests_failed(); + } + display_queue_pointers(); + for (i = 1; i < 5000; i++) + { + if (i == 527) + { + if ((len = monitored_queue_read_msg(buf, MSG_LEN)) != 4) + { + printf("Read failed - %d\n", len); + tests_failed(); + } + } + if ((len = monitored_queue_read_msg(buf, MSG_LEN)) != MSG_LEN) + { + printf("Read failed - %d\n", len); + tests_failed(); + } + if ((len = monitored_queue_write_msg(buf, MSG_LEN)) != MSG_LEN) + { + printf("Write failed - %d\n", len); + tests_failed(); + } + } + display_queue_pointers(); + queue_free(queue); +} +/*- End of function --------------------------------------------------------*/ + +int main(int argc, char *argv[]) +{ + int threaded_messages; + int threaded_streams; + int opt; + + threaded_messages = FALSE; + threaded_streams = FALSE; + while ((opt = getopt(argc, argv, "ms")) != -1) + { + switch (opt) + { + case 'm': + threaded_messages = TRUE; + break; + case 's': + threaded_streams = TRUE; + break; + } + } + + /* Test the basic functionality of the queueing code in stream and message modes */ + printf("Stream mode functional tests\n"); + functional_stream_tests(); + printf("Message mode functional tests\n"); + functional_message_tests(); + + /* Run separate write and read threads for a while, to verify there are no locking + issues. */ + if (threaded_streams) + { + printf("Stream mode threaded tests\n"); + threaded_stream_tests(); + } + if (threaded_messages) + { + printf("Message mode threaded tests\n"); + threaded_message_tests(); + } + return 0; +} +/*- End of function --------------------------------------------------------*/ +/*- End of file ------------------------------------------------------------*/