membuf: new module for linear memory buffers.
[ccan] / ccan / membuf / test / run.c
1 #include <ccan/membuf/membuf.h>
2 #include <stdlib.h>
3 #include <string.h>
4
5 static int num_realloc, num_memmove;
6
7 void *memmove_test(void *dest, const void *src, size_t n);
8 void *realloc_test(void *ptr, size_t size);
9
10 void *memmove_test(void *dest, const void *src, size_t n)
11 {
12         num_memmove++;
13         return memmove(dest, src, n);
14 }
15
16 void *realloc_test(void *ptr, size_t size)
17 {
18         num_realloc++;
19         return realloc(ptr, size);
20 }
21
22 #undef memmove
23 #define memmove memmove_test
24
25 #undef realloc
26 #define realloc realloc_test
27
28 /* Include the C files directly. */
29 #include <ccan/membuf/membuf.c>
30 #include <ccan/tap/tap.h>
31
32 int main(void)
33 {
34         int prev_reallocs;
35         MEMBUF(int) intbuf;
36
37         /* This is how many tests you plan to run */
38         plan_tests(13 + 100 * 4 + 999);
39
40         membuf_init(&intbuf, malloc(10 * sizeof(int)), 10, membuf_realloc);
41         ok1(membuf_num_elems(&intbuf) == 0);
42         ok1(membuf_num_space(&intbuf) == 10);
43         ok1(membuf_space(&intbuf) != NULL);
44
45         /* Add 100 ints. */
46         for (int i = 0; i < 100; i++) {
47                 memcpy(membuf_add(&intbuf, 1), &i, sizeof(i));
48                 ok1(membuf_num_elems(&intbuf) == i+1);
49
50                 /* Make sure membuf_elems works */
51                 if (i == 0)
52                         ok1(memcmp(membuf_elems(&intbuf), &i, sizeof(i)) == 0);
53         }
54
55
56         /* Pull 100 ints. */
57         for (int i = 0; i < 100; i++) {
58                 ok1(memcmp(membuf_consume(&intbuf, 1), &i, sizeof(i)) == 0);
59                 ok1(membuf_num_elems(&intbuf) == 100 - i - 1);
60         }
61
62         /* Should not have continuously realloced or memmoved */
63         ok1(num_realloc < 10);
64         ok1(num_memmove == 0);
65
66         /* Doing it again should give 0 reallocs. */
67         prev_reallocs = num_realloc;
68         for (int i = 0; i < 100; i++) {
69                 memcpy(membuf_add(&intbuf, 1), &i, sizeof(i));
70                 ok1(membuf_num_elems(&intbuf) == i+1);
71         }
72         ok1(num_realloc == prev_reallocs);
73         ok1(num_memmove == 0);
74
75         membuf_consume(&intbuf, 100);
76
77         /* Keep a single element in the queue, make sure we don't realloc! */
78         for (int i = 0; i < 1000; i++) {
79                 memcpy(membuf_add(&intbuf, 1), &i, sizeof(i));
80                 if (i > 0) {
81                         int prev = i - 1;
82                         ok1(memcmp(membuf_consume(&intbuf, 1),
83                                    &prev, sizeof(prev)) == 0);
84                 }
85         }
86
87         ok1(num_realloc == prev_reallocs);
88         /* Should have moved occasionally. */
89         ok1(num_memmove < 20);
90
91         ok1(membuf_consume(&intbuf, 1));
92         ok1(membuf_num_elems(&intbuf) == 0);
93         
94         /* Force it to more-than-double; make sure that works! */
95         memset(membuf_add(&intbuf, 300), 0, 300*sizeof(int));
96         ok1(membuf_num_elems(&intbuf) == 300);
97
98         /* Free buffer so valgrind is happy. */
99         free(membuf_cleanup(&intbuf));
100
101         /* This exits depending on whether all tests passed */
102         return exit_status();
103 }