aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichał Łyszczek <michal.lyszczek@bofc.pl>2018-09-12 22:18:45 +0200
committerMichał Łyszczek <michal.lyszczek@bofc.pl>2018-09-12 22:18:45 +0200
commit1919c275ac6b33f68cfdd82fea43ad536c58e60f (patch)
tree1a58c56669def7f75e2fadff9e045cfa10cd10a5
parent44692b7e7a7134f64d6c0a70b5075b466471a152 (diff)
downloadlibrb-1919c275ac6b33f68cfdd82fea43ad536c58e60f.tar.gz
librb-1919c275ac6b33f68cfdd82fea43ad536c58e60f.tar.bz2
librb-1919c275ac6b33f68cfdd82fea43ad536c58e60f.zip
add: unit tests for all that stuff
-rw-r--r--mtest.h80
-rw-r--r--tests.c1056
2 files changed, 1089 insertions, 47 deletions
diff --git a/mtest.h b/mtest.h
index 8f177d2..4f1c3cf 100644
--- a/mtest.h
+++ b/mtest.h
@@ -1,24 +1,51 @@
/* ==========================================================================
Licensed under BSD 2clause license. See LICENSE file for more information
Author: Michał Łyszczek <michal.lyszczek@bofc.pl>
+ ==========================================================================
+ __________________________________________________________
+ / mtest version v1.1.3 \
+ | |
+ | Simple test framework that uses TAP output format |
+ \ http://testanything.org /
+ ----------------------------------------------------------
+ \ ,-^-.
+ \ !oYo!
+ \ /./=\.\______
+ ## )\/\
+ ||-----w||
+ || ||
+
+ Cowth Vader
========================================================================== */
-/* ==== mtest version v0.2.0 ================================================ */
-
-
/* ==========================================================================
- Tests uses simple TAP output format (http://testanything.org)
- ========================================================================== */
-
+ _ __ __ ____ _ __
+ (_)____ _____ / /__ __ ____/ /___ / __/(_)/ /___ _____
+ / // __ \ / ___// // / / // __ // _ \ / /_ / // // _ \ / ___/
+ / // / / // /__ / // /_/ // /_/ // __/ / __// // // __/(__ )
+ /_//_/ /_/ \___//_/ \__,_/ \__,_/ \___/ /_/ /_//_/ \___//____/
-/* ==== include files ======================================================= */
+ ========================================================================== */
#include <stdio.h>
-/* ==== public macros ======================================================= */
+/* ==========================================================================
+ __ __ _
+ ____ __ __ / /_ / /(_)_____
+ / __ \ / / / // __ \ / // // ___/
+ / /_/ // /_/ // /_/ // // // /__
+ / .___/ \__,_//_.___//_//_/ \___/
+ /_/
+
+ ____ ___ ____ _ _____ _____ ____ _____
+ / __ `__ \ / __ `// ___// ___// __ \ / ___/
+ / / / / / // /_/ // /__ / / / /_/ /(__ )
+ /_/ /_/ /_/ \__,_/ \___//_/ \____//____/
+
+ ========================================================================== */
/* ==========================================================================
@@ -31,7 +58,11 @@
const char *curr_test; \
int mt_test_status; \
int mt_total_tests = 0; \
- int mt_total_failed = 0
+ int mt_total_failed = 0; \
+ int mt_total_checks = 0; \
+ int mt_checks_failed = 0; \
+ static void (*mt_prepare_test)(void); \
+ static void (*mt_cleanup_test)(void)
/* ==========================================================================
@@ -45,7 +76,11 @@
extern const char *curr_test; \
extern int mt_test_status; \
extern int mt_total_tests; \
- extern int mt_total_failed;
+ extern int mt_total_failed; \
+ extern int mt_total_checks; \
+ extern int mt_checks_failed; \
+ static void (*mt_prepare_test)(void); \
+ static void (*mt_cleanup_test)(void)
/* ==========================================================================
@@ -54,10 +89,23 @@
#define mt_run(f) do { \
- curr_test = #f; \
+ mt_run_named(f, #f); \
+ } while (0)
+
+
+/* ==========================================================================
+ macro runs test 'f' and instead of printing function name as a test name
+ it allows to provide custom name 'n'
+ ========================================================================== */
+
+
+#define mt_run_named(f, n) do { \
+ curr_test = n; \
mt_test_status = 0; \
++mt_total_tests; \
+ if (mt_prepare_test) mt_prepare_test(); \
f(); \
+ if (mt_cleanup_test) mt_cleanup_test(); \
if (mt_test_status != 0) \
{ \
fprintf(stdout, "not ok %d - %s\n", mt_total_tests, curr_test); \
@@ -75,11 +123,13 @@
#define mt_assert(e) do { \
+ ++mt_total_checks; \
if (!(e)) \
{ \
fprintf(stdout, "# assert [%s:%d] %s, %s\n", \
__FILE__, __LINE__, curr_test, #e); \
mt_test_status = -1; \
+ ++mt_checks_failed; \
return; \
} } while (0)
@@ -91,11 +141,13 @@
#define mt_fail(e) do { \
+ ++mt_total_checks; \
if (!(e)) \
{ \
fprintf(stdout, "# assert [%s:%d] %s, %s\n", \
__FILE__, __LINE__, curr_test, #e); \
mt_test_status = -1; \
+ ++mt_checks_failed; \
} } while (0)
@@ -130,4 +182,10 @@
#define mt_return() do { \
fprintf(stdout, "1..%d\n", mt_total_tests); \
+ fprintf(stderr, "# total tests.......:%4d\n", mt_total_tests); \
+ fprintf(stderr, "# passed tests......:%4d\n", mt_total_tests - mt_total_failed); \
+ fprintf(stderr, "# failed tests......:%4d\n", mt_total_failed); \
+ fprintf(stderr, "# total checks......:%4d\n", mt_total_checks); \
+ fprintf(stderr, "# passed checks.....:%4d\n", mt_total_checks - mt_checks_failed); \
+ fprintf(stderr, "# failed checks.....:%4d\n", mt_checks_failed); \
return mt_total_failed > 254 ? 254 : mt_total_failed; } while(0)
diff --git a/tests.c b/tests.c
index f2da020..f0b7e8d 100644
--- a/tests.c
+++ b/tests.c
@@ -16,28 +16,51 @@
#include <stdlib.h>
#include <errno.h>
#include <stdint.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <time.h>
+#include <sys/select.h>
#include "mtest.h"
#include <sys/types.h>
#include <unistd.h>
+
+#define TEST_BUFFER 0
+#define TEST_FD_FILE 1
+
+#define MULTI_CONSUMERS 0
+#define MULTI_PRODUCERS 1
+
struct tdata
{
struct rb *rb;
unsigned char *data;
+ int fd;
int len;
int objsize;
size_t buflen;
+ int test_type;
+};
+
+struct multi_data
+{
+ struct rb *rb;
+ const char *pipe;
+ int fd;
};
static int t_rblen;
static int t_readlen;
static int t_writelen;
static int t_objsize;
+static int t_multi_test_type;
+static int multi;
static int t_num_producers;
static int t_num_consumers;
-static int data[128];
+static int data[4];
static pthread_mutex_t multi_mutex;
static pthread_mutex_t multi_mutex_count;
static unsigned int multi_index;
@@ -49,13 +72,28 @@ mt_defs();
static void *consumer(void *arg)
{
struct tdata *data = arg;
- size_t read = 0;
+ size_t r = 0;
+
+ while (r != data->buflen)
+ {
+ size_t left = data->buflen - r;
+ left = left < data->len ? left : data->len;
+ r += rb_read(data->rb, data->data + r * data->objsize, left);
+ }
+
+ return data;
+}
+
+static void *producer_file(void *arg)
+{
+ struct tdata *data = arg;
+ size_t w = 0;
- while (read != data->buflen)
+ while (w != data->buflen)
{
- size_t left = data->buflen - read;
+ size_t left = data->buflen - w;
left = left < data->len ? left : data->len;
- read += rb_read(data->rb, data->data + read * data->objsize, left);
+ w += rb_fd_write(data->rb, data->fd, left);
}
return data;
@@ -64,13 +102,28 @@ static void *consumer(void *arg)
static void *producer(void *arg)
{
struct tdata *data = arg;
- size_t written = 0;
+ size_t w = 0;
- while (written != data->buflen)
+ while (w != data->buflen)
{
- size_t left = data->buflen - written;
+ size_t left = data->buflen - w;
left = left < data->len ? left : data->len;
- written += rb_write(data->rb, data->data + written * data->objsize, left);
+ w += rb_write(data->rb, data->data + w * data->objsize, left);
+ }
+
+ return data;
+}
+
+static void *consumer_file(void *arg)
+{
+ struct tdata *data = arg;
+ size_t r = 0;
+
+ while (r != data->buflen)
+ {
+ size_t left = data->buflen - r;
+ left = left < data->len ? left : data->len;
+ r += rb_fd_read(data->rb, data->fd, left);
}
return data;
@@ -78,8 +131,51 @@ static void *producer(void *arg)
static void *multi_producer(void *arg)
{
- struct rb *rb = arg;
+ struct multi_data *d = arg;
+ struct rb *rb = d->rb;
+ int fd = d->fd;
+ unsigned int index;
+
+ for (;;)
+ {
+ if (fd == -1)
+ {
+ pthread_mutex_lock(&multi_mutex);
+ index = multi_index++;
+ pthread_mutex_unlock(&multi_mutex);
+
+ if (index >= (sizeof(data)/sizeof(*data)))
+ {
+ return NULL;
+ }
+
+ rb_write(rb, &index, 1);
+ }
+ else
+ {
+ if (rb_fd_write(rb, fd, 1) == -1)
+ {
+ if (errno == ECANCELED)
+ {
+ /*
+ * stop, no more, rb is not valid any more
+ */
+
+ return NULL;
+ }
+ }
+ }
+ }
+}
+
+static void *multi_pipe_producer(void *arg)
+{
+ struct multi_data *d = arg;
+ struct rb *rb = d->rb;
unsigned int index;
+ int fd;
+
+ fd = open(d->pipe, O_WRONLY);
for (;;)
{
@@ -89,28 +185,120 @@ static void *multi_producer(void *arg)
if (index >= (sizeof(data)/sizeof(*data)))
{
+ close(fd);
return NULL;
}
- rb_write(rb, &index, 1);
+ write(fd, &index, sizeof(index));
}
}
static void *multi_consumer(void *arg)
{
- struct rb *rb = arg;
+ struct multi_data *d = arg;
+ struct rb *rb = d->rb;
+ int fd = d->fd;
unsigned int index;
for (;;)
{
int overflow;
- if (rb_read(rb, &index, 1) == -1)
+ if (fd == -1)
{
- /*
- * force exit received
- */
+ if (rb_read(rb, &index, 1) == -1)
+ {
+ /*
+ * force exit received
+ */
+
+ return NULL;
+ }
+ overflow = index >= sizeof(data)/sizeof(*data);
+
+ if (overflow)
+ {
+ continue;
+ }
+
+ data[index] = 1;
+ pthread_mutex_lock(&multi_mutex_count);
+ ++multi_index_count;
+ pthread_mutex_unlock(&multi_mutex_count);
+
+ }
+ else
+ {
+ if (rb_fd_read(rb, fd, 1) == -1)
+ {
+ /*
+ * force exit received
+ */
+
+ return NULL;
+ }
+ }
+ }
+}
+
+static void *multi_pipe_consumer(void *arg)
+{
+ struct multi_data *d = arg;
+ struct rb *rb = d->rb;
+ unsigned int index;
+ int fd;
+
+ fd = open(d->pipe, O_RDONLY);
+
+ for (;;)
+ {
+ unsigned int overflow;
+ index = -1u;
+
+ struct timeval tv;
+ fd_set fds;
+ int sact;
+
+ tv.tv_sec = 0;
+ tv.tv_usec = 1000;
+
+ FD_ZERO(&fds);
+ FD_SET(fd, &fds);
+
+ sact = select(fd + 1, &fds, NULL, NULL, &tv);
+
+ if (sact == -1)
+ {
+ perror("select()");
+ close(fd);
+ return NULL;
+ }
+
+ if (sact == 0)
+ {
+ pthread_mutex_lock(&multi_mutex_count);
+ index = multi_index_count;
+ pthread_mutex_unlock(&multi_mutex_count);
+
+ if (index >= sizeof(data)/sizeof(*data))
+ {
+ /*
+ * we have consumed all there was to consume
+ */
+
+ close(fd);
+ return NULL;
+ }
+
+ continue;
+ }
+
+
+ if (read(fd, &index, sizeof(index)) == -1)
+ {
+ perror("read()");
+ close(fd);
return NULL;
}
@@ -132,7 +320,7 @@ static void multi_producers_consumers(void)
{
pthread_t *cons;
pthread_t *prod;
- struct rb *rb;
+ struct multi_data tdata;
unsigned int i, r;
int count;
@@ -143,18 +331,19 @@ static void multi_producers_consumers(void)
cons = malloc(t_num_consumers * sizeof(*cons));
prod = malloc(t_num_producers * sizeof(*prod));
- rb = rb_new(8, sizeof(unsigned int), O_MULTITHREAD);
+ tdata.rb = rb_new(8, sizeof(unsigned int), O_MULTITHREAD);
+ tdata.fd = -1;
pthread_mutex_init(&multi_mutex, NULL);
pthread_mutex_init(&multi_mutex_count, NULL);
for (i = 0; i != t_num_consumers; ++i)
{
- pthread_create(&cons[i], NULL, multi_consumer, rb);
+ pthread_create(&cons[i], NULL, multi_consumer, &tdata);
}
for (i = 0; i != t_num_producers; ++i)
{
- pthread_create(&prod[i], NULL, multi_producer, rb);
+ pthread_create(&prod[i], NULL, multi_producer, &tdata);
}
/*
@@ -173,10 +362,10 @@ static void multi_producers_consumers(void)
* peeking won't make a difference
*/
- rb_recv(rb, buf, rand() % 16, MSG_PEEK);
+ //rb_recv(tdata.rb, buf, rand() % 16, MSG_PEEK);
}
- rb_stop(rb);
+ rb_stop(tdata.rb);
for (i = 0; i != t_num_consumers; ++i)
{
@@ -188,7 +377,7 @@ static void multi_producers_consumers(void)
pthread_join(prod[i], NULL);
}
- rb_destroy(rb);
+ rb_destroy(tdata.rb);
for (r = 0, i = 0; i < sizeof(data)/sizeof(*data); ++i)
{
@@ -209,10 +398,134 @@ static void multi_producers_consumers(void)
pthread_mutex_destroy(&multi_mutex_count);
}
+static void multi_file_consumer_producer(void)
+{
+ pthread_t *prod;
+ pthread_t *cons;
+ pthread_t pipet;
+
+ struct multi_data prod_data;
+ struct multi_data cons_data;
+ struct multi_data pipe_data;
+ struct rb *rb;
+ int fd;
+ unsigned int i, r;
+ int count;
+
+ multi_index = 0;
+ multi_index_count = 0;
+ count = 0;
+ memset(data, 0, sizeof(data));
+
+ unlink("/tmp/rb-test-fifo");
+ mkfifo("/tmp/rb-test-fifo", 0777);
+
+ rb = rb_new(8, sizeof(unsigned int), O_MULTITHREAD);
+
+ pthread_mutex_init(&multi_mutex, NULL);
+ pthread_mutex_init(&multi_mutex_count, NULL);
+
+ if (multi == MULTI_CONSUMERS)
+ {
+ /*
+ * +-cons-+
+ * / \
+ * +------+ +------+
+ * prod --> | rb |---cons---| pipe | --> pipet
+ * +------+ +------+
+ * \ /
+ * +-cons-+
+ */
+ prod = malloc(sizeof(*prod));
+ cons = malloc(t_num_consumers * sizeof(*cons));
+
+ pipe_data.pipe = "/tmp/rb-test-fifo";
+ pthread_create(&pipet, NULL, multi_pipe_consumer, &pipe_data);
+
+ prod_data.rb = rb;
+ prod_data.fd = -1;
+ pthread_create(prod, NULL, multi_producer, &prod_data);
+
+ cons_data.rb = rb;
+ cons_data.fd = open("/tmp/rb-test-fifo", O_WRONLY);
+ for (i = 0; i != t_num_consumers; ++i)
+ {
+ pthread_create(&cons[i], NULL, multi_consumer, &cons_data);
+ }
+ }
+ else
+ {
+ prod = malloc(t_num_producers * sizeof(*prod));
+ cons = malloc(sizeof(*cons));
+
+ pipe_data.pipe = "/tmp/rb-test-fifo";
+ pthread_create(&pipet, NULL, multi_pipe_producer, &pipe_data);
+
+ cons_data.rb = rb;
+ cons_data.fd = -1;
+ pthread_create(cons, NULL, multi_consumer, &cons_data);
+
+ prod_data.rb = rb;
+ prod_data.fd = open("/tmp/rb-test-fifo", O_RDONLY);
+ for (i = 0; i != t_num_producers; ++i)
+ {
+ pthread_create(&prod[i], NULL, multi_producer, &prod_data);
+ }
+ }
+
+ while(count < sizeof(data)/sizeof(*data))
+ {
+ int buf[16];
+
+ pthread_mutex_lock(&multi_mutex_count);
+ count = multi_index_count;
+ pthread_mutex_unlock(&multi_mutex_count);
+ }
+
+ rb_stop(rb);
+
+ if (multi == MULTI_CONSUMERS)
+ {
+ for (i = 0; i != t_num_consumers; ++i)
+ {
+ pthread_join(cons[i], NULL);
+ }
+ pthread_join(*prod, NULL);
+ pthread_join(pipet, NULL);
+ close(cons_data.fd);
+ }
+ else
+ {
+ pthread_join(*cons, NULL);
+ pthread_join(pipet, NULL);
+ for (i = 0; i != t_num_producers; ++i)
+ {
+ pthread_join(prod[i], NULL);
+ }
+ close(prod_data.fd);
+ }
+
+ rb_destroy(rb);
+
+ for (r = 0, i = 0; i < sizeof(data)/sizeof(*data); ++i)
+ {
+ r += data[i] != 1;
+ }
+
+ mt_fail(r == 0);
+
+ free(cons);
+ free(prod);
+ pthread_mutex_destroy(&multi_mutex);
+ pthread_mutex_destroy(&multi_mutex_count);
+}
+
static void multi_thread(void)
{
pthread_t cons;
pthread_t prod;
+ pthread_t cons_file;
+ pthread_t prod_file;
size_t buflen = t_readlen > t_writelen ? t_readlen : t_writelen;
unsigned char *send_buf = malloc(t_objsize * buflen);
@@ -221,6 +534,7 @@ static void multi_thread(void)
int rc;
struct rb *rb;
+ struct rb *rb2;
struct tdata consdata;
struct tdata proddata;
static unsigned long c;
@@ -239,12 +553,36 @@ static void multi_thread(void)
proddata.objsize = t_objsize;
proddata.rb = rb;
proddata.buflen = buflen;
+ proddata.fd = -1;
consdata.data = recv_buf;
consdata.len = t_readlen;
consdata.objsize = t_objsize;
consdata.rb = rb;
consdata.buflen = buflen;
+ consdata.fd = -1;
+
+ if (t_multi_test_type == TEST_FD_FILE)
+ {
+ int fd;
+ int fd2;
+
+ fd2 = open("/tmp/rb-test-file", O_RDWR | O_CREAT | O_TRUNC, 0644);
+ fd = open("/tmp/rb-test-file", O_RDWR | O_CREAT | O_TRUNC, 0644);
+ if (fd < 0 || fd2 < 0)
+ {
+ perror("open");
+ mt_assert(0);
+ }
+
+ proddata.fd = fd;
+ consdata.fd = fd2;
+ rb2 = rb_new(t_rblen, t_objsize, O_MULTITHREAD);
+ consdata.rb = rb2;
+
+ pthread_create(&cons_file, NULL, consumer_file, &proddata);
+ pthread_create(&prod_file, NULL, producer_file, &consdata);
+ }
pthread_create(&cons, NULL, consumer, &consdata);
pthread_create(&prod, NULL, producer, &proddata);
@@ -252,6 +590,13 @@ static void multi_thread(void)
pthread_join(cons, NULL);
pthread_join(prod, NULL);
+ if (t_multi_test_type == TEST_FD_FILE)
+ {
+ pthread_join(cons_file, NULL);
+ pthread_join(prod_file, NULL);
+ rb_destroy(rb2);
+ }
+
rc = memcmp(send_buf, recv_buf, t_objsize * buflen);
mt_fail(rc == 0);
@@ -384,6 +729,29 @@ static void peeking(void)
mt_fail(v[4] == 0);
mt_fail(v[5] == 0);
+ /*
+ * now with overlaped memory
+ */
+
+ memset(v, 0, sizeof(v));
+ mt_fail(rb_discard(rb, 7) == 4);
+ rb_write(rb, d, 6);
+ rb_recv(rb, v, 6, MSG_PEEK);
+ mt_fail(v[0] == 0);
+ mt_fail(v[1] == 1);
+ mt_fail(v[2] == 2);
+ mt_fail(v[3] == 3);
+ mt_fail(v[4] == 4);
+ mt_fail(v[5] == 5);
+ memset(v, 0, sizeof(v));
+ rb_recv(rb, v, 6, MSG_PEEK);
+ mt_fail(v[0] == 0);
+ mt_fail(v[1] == 1);
+ mt_fail(v[2] == 2);
+ mt_fail(v[3] == 3);
+ mt_fail(v[4] == 4);
+ mt_fail(v[5] == 5);
+
rb_destroy(rb);
}
@@ -420,22 +788,39 @@ static void single_thread(void)
{
if (written != buflen)
{
+ long w;
if (written + writelen > buflen)
{
writelen = buflen - written;
}
- written += rb_write(rb, send_buf + written * t_objsize, writelen);
+ w = rb_write(rb, send_buf + written * t_objsize, writelen);
+
+ if (w == -1)
+ {
+ break;
+ }
+
+ written += w;
}
if (read != buflen)
{
+ long r;
+
if (read + readlen > buflen)
{
readlen = buflen - read;
}
- read+= rb_read(rb, recv_buf + read * t_objsize, readlen);
+ r = rb_read(rb, recv_buf + read * t_objsize, readlen);
+
+ if (r == -1)
+ {
+ break;
+ }
+
+ read += r;
}
}
@@ -453,6 +838,7 @@ static void single_thread(void)
rb_destroy(rb);
}
+
static void discard(void)
{
char s[8] = "0123456";
@@ -666,17 +1052,570 @@ static void stack_init(void)
#endif
}
+static void fd_write_single(void)
+{
+ int fd;
+ int i;
+ int pos;
+ char data[128];
+ char rdata[128];
+ struct rb *rb;
+
+ /*
+ * prepare file with some content to read into rb
+ */
+
+ if ((fd = open("/tmp/rb-test-file", O_RDWR | O_CREAT | O_TRUNC, 0644)) < 0)
+ {
+ perror("posix_read_single; prepare; open");
+ mt_assert(0);
+ }
+
+ for (i = 0; i != sizeof(data); ++i)
+ {
+ data[i] = rand() % 127;
+ }
+
+ write(fd, data, sizeof(data));
+ lseek(fd, 0, SEEK_SET);
+
+ rb = rb_new(sizeof(data), sizeof(char), 0);
+
+ /*
+ * now let's read some data from fd to ring buffer
+ */
+
+ mt_fail(rb_fd_write(rb, fd, 100) == 100);
+ mt_fail(rb_read(rb, rdata, 100) == 100);
+ mt_fail(memcmp(rdata, data, 100) == 0);
+
+ mt_fail(rb_fd_write(rb, fd, 100) == 28);
+ mt_fail(rb_read(rb, rdata, 100) == 28);
+ mt_fail(memcmp(rdata, data + 100, 28) == 0);
+
+ rb_destroy(rb);
+ close(fd);
+}
+
+static void fd_write_single_multibyte(void)
+{
+ int fd;
+ int i;
+ int pos;
+ int data[128];
+ int rdata[128];
+ struct rb *rb;
+
+ /*
+ * prepare file with some content to read into rb
+ */
+
+ if ((fd = open("/tmp/rb-test-file", O_RDWR | O_CREAT | O_TRUNC, 0644)) < 0)
+ {
+ perror("posix_read_single; prepare; open");
+ mt_assert(0);
+ }
+
+ for (i = 0; i != 128; ++i)
+ {
+ data[i] = rand();
+ }
+
+ write(fd, data, sizeof(data));
+ lseek(fd, 0, SEEK_SET);
+
+ rb = rb_new(128, sizeof(int), 0);
+
+ mt_fail(rb_fd_write(rb, fd, 100) == 100);
+ mt_fail(rb_read(rb, rdata, 100) == 100);
+
+ for (i = 0; i != 100; ++i)
+ {
+ mt_fail(data[i] == rdata[i]);
+ }
+
+ mt_fail(rb_fd_write(rb, fd, 100) == 28);
+ mt_fail(rb_read(rb, rdata, 100) == 28);
+ for (i = 0; i != 28; ++i)
+ {
+ mt_fail(data[i + 100] == rdata[i]);
+ }
+
+ /*
+ * we read all data from file, read() on our fd will return 0 (end of file),
+ * so rb will return 0 as well
+ */
+ mt_fail(rb_fd_write(rb, fd, 10) == 0);
+
+ rb_destroy(rb);
+ close(fd);
+}
+
+static void fd_write_single_overlap(void)
+{
+ int fd;
+ int i;
+ int pos;
+ int data[128];
+ int rdata[128];
+ struct rb *rb;
+
+ /*
+ * prepare file with some content to read into rb
+ */
+
+ if ((fd = open("/tmp/rb-test-file", O_RDWR | O_CREAT | O_TRUNC, 0644)) < 0)
+ {
+ perror("posix_read_single; prepare; open");
+ mt_assert(0);
+ }
+
+ for (i = 0; i != 128; ++i)
+ {
+ data[i] = rand();
+ }
+
+ write(fd, data, sizeof(data));
+ lseek(fd, 0, SEEK_SET);
+
+ rb = rb_new(16, sizeof(int), 0);
+
+ /*
+ * cause overlap condition
+ */
+
+ mt_fail(rb_fd_write(rb, fd, 10) == 10);
+ mt_fail(rb_read(rb, rdata, 10) == 10);
+
+ /*
+ * and check overlap set
+ */
+
+ mt_fail(rb_fd_write(rb, fd, 15) == 15);
+ mt_fail(rb_read(rb, rdata, 15) == 15);
+ for (i = 0; i != 15; ++i)
+ {
+ mt_fail(data[i + 10] == rdata[i]);
+ }
+
+ rb_destroy(rb);
+}
+
+static void fd_write_single_partial(void)
+{
+ int fd;
+ int i;
+ int pos;
+ char data[128];
+ char rdata[128];
+ struct rb *rb;
+
+ /*
+ * prepare file with some content to read into rb
+ */
+
+ if ((fd = open("/tmp/rb-test-file", O_RDWR | O_CREAT | O_TRUNC, 0644)) < 0)
+ {
+ perror("posix_read_single; prepare; open");
+ mt_assert(0);
+ }
+
+ for (i = 0; i != 128; ++i)
+ {
+ data[i] = rand() % 127;
+ }
+
+ write(fd, data, sizeof(data));
+
+ rb = rb_new(16, 1, 0);
+
+
+ /*
+ * partial read no overlap
+ */
+
+ lseek(fd, 120, SEEK_SET);
+ mt_fail(rb_fd_write(rb, fd, 15) == 8);
+ mt_fail(rb_read(rb, rdata, 15) == 8);
+ mt_fail(memcmp(rdata, data + 120, 8) == 0);
+
+ /*
+ * partial read with overlap
+ */
+
+ lseek(fd, 118, SEEK_SET);
+ mt_fail(rb_fd_write(rb, fd, 15) == 10);
+ mt_fail(rb_read(rb, rdata, 15) == 10);
+ mt_fail(memcmp(rdata, data + 118, 10) == 0);
+
+ /*
+ * partial read, overlap, with first read satisfied fully
+ */
+
+ mt_fok(rb_clear(rb, 0));
+ lseek(fd, 113, SEEK_SET);
+ mt_fail(rb_fd_write(rb, fd, 5) == 5);
+ mt_fail(rb_discard(rb, 5) == 5);
+ mt_fail(rb_fd_write(rb, fd, 15) == 10);
+ mt_fail(rb_read(rb, rdata, 15) == 10);
+ mt_fail(memcmp(rdata, data + 118, 10) == 0);
+
+ close(fd);
+ rb_destroy(rb);
+}
+
+static void fd_write_enosys(void)
+{
+ struct rb *rb;
+ rb = rb_new(16, 1, 0);
+ mt_ferr(rb_fd_write(rb, 0, 1), ENOSYS);
+ mt_ferr(rb_fd_send(rb, 0, 1, 0), ENOSYS);
+}
+
+static void fd_read_single(void)
+{
+ struct rb *rb;
+ int fd;
+ int i;
+ char data[128];
+ char rdata[128];
+
+
+ if ((fd = open("/tmp/rb-test-file", O_RDWR | O_CREAT | O_TRUNC, 0644)) < 0)
+ {
+ perror("prepare; open");
+ mt_assert(0);
+ }
+
+ for (i = 0; i != 128; ++i)
+ {
+ data[i] = rand() % 127;
+ }
+
+ rb = rb_new(128, 1, 0);
+
+ mt_fail(rb_write(rb, data, 100) == 100);
+ mt_fail(rb_fd_read(rb, fd, 100) == 100);
+ mt_fail(rb_write(rb, data + 100, 28) == 28);
+ mt_fail(rb_fd_read(rb, fd, 28) == 28);
+
+ lseek(fd, 0, SEEK_SET);
+ mt_fail(read(fd, rdata, 128) == 128);
+ mt_fail(memcmp(data, rdata, 128) == 0);
+ mt_fail(read(fd, rdata, 1) == 0);
+
+ rb_destroy(rb);
+ close(fd);
+}
+
+
+static void fd_read_single_multibyte(void)
+{
+ struct rb *rb;
+ int fd;
+ int i;
+ int data[128];
+ int rdata[128];
+
+
+ if ((fd = open("/tmp/rb-test-file", O_RDWR | O_CREAT | O_TRUNC, 0644)) < 0)
+ {
+ perror("prepare; open");
+ mt_assert(0);
+ }
+
+ for (i = 0; i != 128; ++i)
+ {
+ data[i] = rand();
+ }
+
+ rb = rb_new(128, sizeof(int), 0);
+
+ mt_fail(rb_write(rb, data, 100) == 100);
+ mt_fail(rb_fd_read(rb, fd, 100) == 100);
+ mt_fail(rb_write(rb, data + 100, 28) == 28);
+ mt_fail(rb_fd_read(rb, fd, 28) == 28);
+
+ lseek(fd, 0, SEEK_SET);
+ mt_fail(read(fd, rdata, 128 * sizeof(int)) == 128 * sizeof(int));
+
+ for (i = 0; i != 128; ++i)
+ {
+ mt_fail(rdata[i] == data[i]);
+ }
+ mt_fail(read(fd, rdata, 1) == 0);
+
+ rb_destroy(rb);
+ close(fd);
+
+}
+
+static void fd_read_single_overlap(void)
+{
+ struct rb *rb;
+ int fd;
+ int i;
+ char data[128];
+ char rdata[128];
+
+ if ((fd = open("/tmp/rb-test-file", O_RDWR | O_CREAT | O_TRUNC, 0644)) < 0)
+ {
+ perror("prepare; open");
+ mt_assert(0);
+ }
+
+ for (i = 0; i != 128; ++i)
+ {
+ data[i] = rand() % 127;
+ }
+
+ rb = rb_new(16, 1, 0);
+
+ /*
+ * cause overlap condition
+ */
+
+ mt_fail(rb_write(rb, data, 10) == 10);
+ mt_fail(rb_fd_read(rb, fd, 10) == 10);
+
+ /*
+ * and check overlap set
+ */
+
+ mt_fail(rb_write(rb, data + 10, 15) == 15);
+ mt_fail(rb_fd_read(rb, fd, 15) == 15);
+
+ lseek(fd, 0, SEEK_SET);
+ mt_fail(read(fd, rdata, 25) == 25);
+ mt_fail(memcmp(rdata, data, 25) == 0);
+ mt_fail(read(fd, rdata, 1) == 0);
+
+ /*
+ * another read to check rb is consistent
+ */
+
+ mt_fail(rb_write(rb, data + 25, 15) == 15);
+ mt_fail(rb_fd_read(rb, fd, 15) == 15);
+
+ lseek(fd, 0, SEEK_SET);
+ mt_fail(read(fd, rdata, 40) == 40);
+ mt_fail(memcmp(rdata, data, 40) == 0);
+ mt_fail(read(fd, rdata, 1) == 0);
+
+ rb_destroy(rb);
+ close(fd);
+}
+
+
+static void fd_read_single_partial(void)
+{
+ struct rb *rb;
+ int fd;
+ int i;
+ char data[128];
+ char rdata[128];
+
+ if ((fd = open("/tmp/rb-test-file", O_RDWR | O_CREAT | O_TRUNC, 0644)) < 0)
+ {
+ perror("prepare; open");
+ mt_assert(0);
+ }
+
+ for (i = 0; i != 128; ++i)
+ {
+ data[i] = i;
+ }
+
+ rb = rb_new(16, 1, 0);
+
+ /*
+ * partial write no overlap
+ */
+
+ mt_fail(rb_write(rb, data, 10) == 10);
+ mt_fail(rb_fd_read(rb, fd, 15) == 10);
+
+ lseek(fd, 0, SEEK_SET);
+ mt_fail(read(fd, rdata, 20) == 10);
+ mt_fail(memcmp(rdata, data, 10) == 0);
+
+ /*
+ * partial write with overlap
+ */
+
+ mt_fail(rb_write(rb, data + 10, 15) == 15);
+ mt_fail(rb_fd_read(rb, fd, 20) == 15);
+ lseek(fd, 0, SEEK_SET);
+ mt_fail(read(fd, rdata, 25) == 25);
+ mt_fail(memcmp(rdata, data, 25) == 0);
+
+ /*
+ * partial write, overlap, with first write satisfied fully
+ */
+
+ mt_fok(rb_clear(rb, 0));
+ mt_fail(rb_write(rb, data, 5) == 5);
+ mt_fail(rb_discard(rb, 5) == 5);
+ mt_fail(rb_write(rb, data + 25, 10) == 10);
+ mt_fail(rb_fd_read(rb, fd, 15) == 10);
+ lseek(fd, 0, SEEK_SET);
+ mt_fail(read(fd, rdata, 35) == 35);
+ mt_fail(memcmp(rdata, data, 35) == 0);
+
+ rb_destroy(rb);
+ close(fd);
+}
+
+static void fd_read_single_peek(void)
+{
+ struct rb *rb;
+ int fd;
+ int i;
+ char data[128];
+ char rdata[128];
+
+
+ if ((fd = open("/tmp/rb-test-file", O_RDWR | O_CREAT | O_TRUNC, 0644)) < 0)
+ {
+ perror("prepare; open");
+ mt_assert(0);
+ }
+
+ for (i = 0; i != 128; ++i)
+ {
+ data[i] = rand() % 127;
+ }
+
+ rb = rb_new(32, 1, 0);
+
+ mt_fail(rb_write(rb, data, 30) == 30);
+ mt_fail(rb_fd_recv(rb, fd, 10, MSG_PEEK) == 10);
+ mt_fail(rb_fd_recv(rb, fd, 10, MSG_PEEK) == 10);
+ mt_fail(rb_fd_recv(rb, fd, 10, MSG_PEEK) == 10);
+
+ lseek(fd, 0, SEEK_SET);
+ mt_fail(read(fd, rdata, 30) == 30);
+ mt_fail(memcmp(data, rdata, 10) == 0);
+ mt_fail(memcmp(data, rdata + 10, 10) == 0);
+ mt_fail(memcmp(data, rdata + 20, 10) == 0);
+ mt_fail(read(fd, rdata, 1) == 0);
+
+
+ mt_fail(rb_fd_recv(rb, fd, 40, MSG_PEEK) == 30);
+ lseek(fd, 0, SEEK_SET);
+ mt_fail(read(fd, rdata, 60) == 60);
+ mt_fail(memcmp(data, rdata, 10) == 0);
+ mt_fail(memcmp(data, rdata + 10, 10) == 0);
+ mt_fail(memcmp(data, rdata + 20, 10) == 0);
+ mt_fail(memcmp(data, rdata + 30, 30) == 0);
+ mt_fail(read(fd, rdata, 1) == 0);
+
+
+ mt_fail(rb_fd_recv(rb, fd, 10, MSG_PEEK) == 10);
+ mt_fail(rb_fd_recv(rb, fd, 10, MSG_PEEK) == 10);
+
+ lseek(fd, 0, SEEK_SET);
+ mt_fail(read(fd, rdata, 80) == 80);
+ mt_fail(memcmp(data, rdata, 10) == 0);
+ mt_fail(memcmp(data, rdata + 10, 10) == 0);
+ mt_fail(memcmp(data, rdata + 20, 10) == 0);
+ mt_fail(memcmp(data, rdata + 30, 30) == 0);
+ mt_fail(memcmp(data, rdata + 60, 10) == 0);
+ mt_fail(memcmp(data, rdata + 70, 10) == 0);
+ mt_fail(read(fd, rdata, 1) == 0);
+
+ rb_destroy(rb);
+ close(fd);
+}
+
+static void fd_read_single_peek_overlap(void)
+{
+ struct rb *rb;
+ int fd;
+ int i;
+ char data[128];
+ char rdata[128];
+
+
+ if ((fd = open("/tmp/rb-test-file", O_RDWR | O_CREAT | O_TRUNC, 0644)) < 0)
+ {
+ perror("prepare; open");
+ mt_assert(0);
+ }
+
+ for (i = 0; i != 128; ++i)
+ {
+ data[i] = rand() % 127;
+ }
+
+ rb = rb_new(32, 1, 0);
+
+ mt_fail(rb_write(rb, data, 16) == 16);
+ mt_fail(rb_discard(rb, 16) == 16);
+
+ mt_fail(rb_write(rb, data, 30) == 30);
+ mt_fail(rb_fd_recv(rb, fd, 10, MSG_PEEK) == 10);
+ mt_fail(rb_fd_recv(rb, fd, 10, MSG_PEEK) == 10);
+ mt_fail(rb_fd_recv(rb, fd, 10, MSG_PEEK) == 10);
+
+ lseek(fd, 0, SEEK_SET);
+ mt_fail(read(fd, rdata, 30) == 30);
+ mt_fail(memcmp(data, rdata, 10) == 0);
+ mt_fail(memcmp(data, rdata + 10, 10) == 0);
+ mt_fail(memcmp(data, rdata + 20, 10) == 0);
+ mt_fail(read(fd, rdata, 1) == 0);
+
+
+ mt_fail(rb_fd_recv(rb, fd, 40, MSG_PEEK) == 30);
+ lseek(fd, 0, SEEK_SET);
+ mt_fail(read(fd, rdata, 60) == 60);
+ mt_fail(memcmp(data, rdata, 10) == 0);
+ mt_fail(memcmp(data, rdata + 10, 10) == 0);
+ mt_fail(memcmp(data, rdata + 20, 10) == 0);
+ mt_fail(memcmp(data, rdata + 30, 30) == 0);
+ mt_fail(read(fd, rdata, 1) == 0);
+
+
+ mt_fail(rb_fd_recv(rb, fd, 10, MSG_PEEK) == 10);
+ mt_fail(rb_fd_recv(rb, fd, 10, MSG_PEEK) == 10);
+
+ lseek(fd, 0, SEEK_SET);
+ mt_fail(read(fd, rdata, 80) == 80);
+ mt_fail(memcmp(data, rdata, 10) == 0);
+ mt_fail(memcmp(data, rdata + 10, 10) == 0);
+ mt_fail(memcmp(data, rdata + 20, 10) == 0);
+ mt_fail(memcmp(data, rdata + 30, 30) == 0);
+ mt_fail(memcmp(data, rdata + 60, 10) == 0);
+ mt_fail(memcmp(data, rdata + 70, 10) == 0);
+ mt_fail(read(fd, rdata, 1) == 0);
+
+ rb_destroy(rb);
+ close(fd);
+}
+
+static void fd_read_enosys(void)
+{
+ struct rb *rb;
+ rb = rb_new(16, 1, 0);
+ mt_ferr(rb_fd_read(rb, 0, 1), ENOSYS);
+ mt_ferr(rb_fd_recv(rb, 0, 1, 0), ENOSYS);
+ rb_destroy(rb);
+}
+
+
int main(void)
{
- unsigned int t_rblen_max = 128;
- unsigned int t_readlen_max = 128;
- unsigned int t_writelen_max = 128;
- unsigned int t_objsize_max = 128;
+ srand(time(NULL));
+ //mt_return();
+ unsigned int t_rblen_max = 32;
+ unsigned int t_readlen_max = 32;
+ unsigned int t_writelen_max = 32;
+ unsigned int t_objsize_max = 32;
unsigned int t_num_producers_max = 8;
unsigned int t_num_consumers_max = 8;
+ char name[128];
- srand(time(NULL));
#if ENABLE_THREADS
for (t_num_consumers = 1; t_num_consumers <= t_num_consumers_max;
@@ -685,7 +1624,19 @@ int main(void)
for (t_num_producers = 1; t_num_producers <= t_num_producers_max;
t_num_producers++)
{
- mt_run(multi_producers_consumers);
+ sprintf(name, "multi_producers_consumers producers: %d "
+ "consumers %d", t_num_producers, t_num_consumers);
+ mt_run_named(multi_producers_consumers, name);
+
+ sprintf(name, "multi_file_consumer_producer: MULTI_CONSUMERS "
+ "prod: %d, cons: %d", t_num_producers, t_num_consumers);
+ multi = MULTI_CONSUMERS;
+ mt_run_named(multi_file_consumer_producer, name);
+
+ sprintf(name, "multi_file_consumer_producer: MULTI_PRODUCERS "
+ "prod: %d, cons: %d", t_num_producers, t_num_consumers);
+ multi = MULTI_PRODUCERS;
+ mt_run_named(multi_file_consumer_producer, name);
}
}
#endif
@@ -693,19 +1644,37 @@ int main(void)
for (t_rblen = 2; t_rblen < t_rblen_max; t_rblen *= 2)
{
for (t_readlen = 2; t_readlen < t_readlen_max;
- t_readlen += rand() % 128)
+ t_readlen *= 2)
{
for (t_writelen = 2; t_writelen < t_writelen_max;
- t_writelen += rand() % 128)
+ t_writelen *= 2)
{
for (t_objsize = 2; t_objsize < t_objsize_max;
- t_objsize += rand() % 128)
+ t_objsize *= 2)
{
+ t_multi_test_type = TEST_BUFFER;
#if ENABLE_THREADS
- mt_run(multi_thread);
+ sprintf(name, "multi_thread with buffer %3d, %3d, %3d, %3d",
+ t_rblen, t_readlen, t_writelen, t_objsize);
+ mt_run_named(multi_thread, name);
#endif
- mt_run(single_thread);
+ sprintf(name, "singl_thread with buffer %3d, %3d, %3d, %3d",
+ t_rblen, t_readlen, t_writelen, t_objsize);
+ mt_run_named(single_thread, name);
}
+
+ t_objsize = 1;
+
+ t_multi_test_type = TEST_FD_FILE;
+#if ENABLE_THREADS
+ sprintf(name, "multi_thread with file %3d, %3d, %3d, %3d",
+ t_rblen, t_readlen, t_writelen, t_objsize);
+ mt_run_named(multi_thread, name);
+
+#endif
+ sprintf(name, "singl_thread with file %3d, %3d, %3d, %3d",
+ t_rblen, t_readlen, t_writelen, t_objsize);
+ mt_run_named(single_thread, name);
}
}
}
@@ -726,5 +1695,20 @@ int main(void)
mt_run(multithread_eagain);
#endif
+#if ENABLE_POSIX_CALLS
+ mt_run(fd_write_single);
+ mt_run(fd_write_single_multibyte);
+ mt_run(fd_write_single_overlap);
+ mt_run(fd_write_single_partial);
+ mt_run(fd_read_single);
+ mt_run(fd_read_single_multibyte);
+ mt_run(fd_read_single_overlap);
+ mt_run(fd_read_single_partial);
+ mt_run(fd_read_single_peek);
+ mt_run(fd_read_single_peek_overlap);
+#else
+ mt_run(fd_write_enosys);
+ mt_run(fd_read_enosys);
+#endif
mt_return();
}