1 | #include "data-struct/ring_buffer.h" |
---|
2 | #include <pthread.h> |
---|
3 | #include <assert.h> |
---|
4 | |
---|
5 | #define TEST_SIZE ((char *) 1000000) |
---|
6 | #define RINGBUFFER_SIZE ((char *) 10000) |
---|
7 | |
---|
8 | static void * producer(void * a) { |
---|
9 | libtrace_ringbuffer_t * rb = (libtrace_ringbuffer_t *) a; |
---|
10 | char * i; |
---|
11 | for (i = NULL; i < TEST_SIZE; i++) { |
---|
12 | libtrace_ringbuffer_write(rb, i); |
---|
13 | } |
---|
14 | return 0; |
---|
15 | } |
---|
16 | |
---|
17 | static void * consumer(void * a) { |
---|
18 | libtrace_ringbuffer_t * rb = (libtrace_ringbuffer_t *) a; |
---|
19 | char *i; |
---|
20 | void *value; |
---|
21 | for (i = NULL; i < TEST_SIZE; i++) { |
---|
22 | value = libtrace_ringbuffer_read(rb); |
---|
23 | assert(value == i); |
---|
24 | } |
---|
25 | return 0; |
---|
26 | } |
---|
27 | |
---|
28 | /** |
---|
29 | * Tests the ringbuffer data structure, first this establishes that single |
---|
30 | * threaded operations work correctly, then does a basic consumer producer |
---|
31 | * thread-safety test. |
---|
32 | */ |
---|
33 | int main() { |
---|
34 | char *i; |
---|
35 | void *value; |
---|
36 | pthread_t t[4]; |
---|
37 | libtrace_ringbuffer_t rb_block; |
---|
38 | libtrace_ringbuffer_t rb_polling; |
---|
39 | |
---|
40 | libtrace_ringbuffer_init(&rb_block, (size_t) RINGBUFFER_SIZE, LIBTRACE_RINGBUFFER_BLOCKING); |
---|
41 | libtrace_ringbuffer_init(&rb_polling, (size_t) RINGBUFFER_SIZE, LIBTRACE_RINGBUFFER_BLOCKING); |
---|
42 | assert(libtrace_ringbuffer_is_empty(&rb_block)); |
---|
43 | assert(libtrace_ringbuffer_is_empty(&rb_polling)); |
---|
44 | |
---|
45 | for (i = NULL; i < RINGBUFFER_SIZE; i++) { |
---|
46 | value = (void *) i; |
---|
47 | libtrace_ringbuffer_write(&rb_block, value); |
---|
48 | libtrace_ringbuffer_write(&rb_polling, value); |
---|
49 | } |
---|
50 | |
---|
51 | assert(libtrace_ringbuffer_is_full(&rb_block)); |
---|
52 | assert(libtrace_ringbuffer_is_full(&rb_polling)); |
---|
53 | |
---|
54 | // Full so trying to write should fail |
---|
55 | assert(!libtrace_ringbuffer_try_write(&rb_block, value)); |
---|
56 | assert(!libtrace_ringbuffer_try_write(&rb_polling, value)); |
---|
57 | assert(!libtrace_ringbuffer_try_swrite(&rb_block, value)); |
---|
58 | assert(!libtrace_ringbuffer_try_swrite(&rb_polling, value)); |
---|
59 | assert(!libtrace_ringbuffer_try_swrite_bl(&rb_block, value)); |
---|
60 | assert(!libtrace_ringbuffer_try_swrite_bl(&rb_polling, value)); |
---|
61 | |
---|
62 | // Cycle the buffer a few times |
---|
63 | for (i = NULL; i < TEST_SIZE; i++) { |
---|
64 | value = (void *) -1; |
---|
65 | value = libtrace_ringbuffer_read(&rb_block); |
---|
66 | assert(value == (void *) i); |
---|
67 | value = (void *) -1; |
---|
68 | value = libtrace_ringbuffer_read(&rb_polling); |
---|
69 | assert(value == (void *) i); |
---|
70 | value = (void *) (i + (size_t) RINGBUFFER_SIZE); |
---|
71 | libtrace_ringbuffer_write(&rb_block, value); |
---|
72 | libtrace_ringbuffer_write(&rb_polling, value); |
---|
73 | } |
---|
74 | |
---|
75 | // Empty it completely |
---|
76 | for (i = TEST_SIZE; i < TEST_SIZE + (size_t) RINGBUFFER_SIZE; i++) { |
---|
77 | value = libtrace_ringbuffer_read(&rb_block); |
---|
78 | assert(value == (void *) i); |
---|
79 | value = libtrace_ringbuffer_read(&rb_polling); |
---|
80 | assert(value == (void *) i); |
---|
81 | } |
---|
82 | assert(libtrace_ringbuffer_is_empty(&rb_block)); |
---|
83 | assert(libtrace_ringbuffer_is_empty(&rb_polling)); |
---|
84 | |
---|
85 | // Empty so trying to read should fail |
---|
86 | assert(!libtrace_ringbuffer_try_read(&rb_block, &value)); |
---|
87 | assert(!libtrace_ringbuffer_try_read(&rb_polling, &value)); |
---|
88 | assert(!libtrace_ringbuffer_try_sread(&rb_block, &value)); |
---|
89 | assert(!libtrace_ringbuffer_try_sread(&rb_polling, &value)); |
---|
90 | assert(!libtrace_ringbuffer_try_sread_bl(&rb_block, &value)); |
---|
91 | assert(!libtrace_ringbuffer_try_sread_bl(&rb_polling, &value)); |
---|
92 | |
---|
93 | // Test thread safety - We only really care about the single producer single |
---|
94 | // consumer case |
---|
95 | pthread_create(&t[0], NULL, &producer, (void *) &rb_block); |
---|
96 | pthread_create(&t[1], NULL, &consumer, (void *) &rb_block); |
---|
97 | pthread_join(t[0], NULL); |
---|
98 | pthread_join(t[1], NULL); |
---|
99 | assert(libtrace_ringbuffer_is_empty(&rb_block)); |
---|
100 | |
---|
101 | pthread_create(&t[0], NULL, &producer, (void *) &rb_polling); |
---|
102 | pthread_create(&t[1], NULL, &consumer, (void *) &rb_polling); |
---|
103 | pthread_join(t[0], NULL); |
---|
104 | pthread_join(t[1], NULL); |
---|
105 | assert(libtrace_ringbuffer_is_empty(&rb_polling)); |
---|
106 | |
---|
107 | return 0; |
---|
108 | } |
---|