1 /*
2 * we include the c source file to get at the opaque types and
3 * api functions
4 */
5 #include <string.h>
6 #include <stdio.h>
7 #include <assert.h>
8 #include <sys/types.h>
9 #include <signal.h>
10 #include <unistd.h>
11 #include <sys/time.h>
12 #include "squeue.c"
13 #include "t-utils.h"
14
squeue_foreach(squeue_t * q,int (* walker)(squeue_event *,void *),void * arg)15 static void squeue_foreach(squeue_t *q, int (*walker)(squeue_event *, void *), void *arg)
16 {
17 squeue_t *dup;
18 void *e, *dup_d;
19
20 dup = squeue_create(q->size);
21 dup_d = dup->d;
22 memcpy(dup, q, sizeof(*q));
23 dup->d = dup_d;
24 memcpy(dup->d, q->d, (q->size * sizeof(void *)));
25
26 while ((e = pqueue_pop(dup))) {
27 walker(e, arg);
28 }
29 squeue_destroy(dup, 0);
30 }
31
32 #define t(expr, args...) \
33 do { \
34 if ((expr)) { \
35 t_pass(#expr); \
36 } else { \
37 t_fail(#expr " @%s:%d", __FILE__, __LINE__); \
38 } \
39 } while(0)
40
41 typedef struct sq_test_event {
42 unsigned long id;
43 squeue_event *evt;
44 } sq_test_event;
45
46 static time_t sq_high = 0;
sq_walker(squeue_event * evt,void * arg)47 static int sq_walker(squeue_event *evt, void *arg)
48 {
49 static int walks = 0;
50
51 walks++;
52 t(sq_high <= evt->when.tv_sec, "sq_high: %lu; evt->when: %lu\n",
53 sq_high, evt->when.tv_sec);
54 sq_high = (unsigned long)evt->when.tv_sec;
55
56 return 0;
57 }
58
59 #define EVT_ARY 65101
sq_test_random(squeue_t * sq)60 static int sq_test_random(squeue_t *sq)
61 {
62 unsigned long size, i;
63 unsigned long long numbers[EVT_ARY], *d, max = 0;
64 struct timeval now;
65
66 size = squeue_size(sq);
67 now.tv_sec = time(NULL);
68 srand((int)now.tv_sec);
69 for (i = 0; i < EVT_ARY; i++) {
70 now.tv_usec = (time_t)rand();
71 squeue_add_tv(sq, &now, &numbers[i]);
72 numbers[i] = evt_compute_pri(&now);
73 t(squeue_size(sq) == i + 1 + size);
74 }
75
76 t(pqueue_is_valid(sq));
77
78 /*
79 * make sure we pop events in increasing "priority",
80 * since we calculate priority based on time and later
81 * is lower prio
82 */
83 for (i = 0; i < EVT_ARY; i++) {
84 d = (unsigned long long *)squeue_pop(sq);
85 t(max <= *d, "popping randoms. i: %lu; delta: %lld; max: %llu; *d: %llu\n",
86 i, max - *d, max, *d);
87 max = *d;
88 t(squeue_size(sq) == size + (EVT_ARY - i - 1));
89 }
90 t(pqueue_is_valid(sq));
91
92 return 0;
93 }
94
main(int argc,char ** argv)95 int main(int argc, char **argv)
96 {
97 squeue_t *sq;
98 struct timeval tv;
99 sq_test_event a, b, c, d, *x;
100
101 t_set_colors(0);
102 t_start("squeue tests");
103
104 a.id = 1;
105 b.id = 2;
106 c.id = 3;
107 d.id = 4;
108
109 gettimeofday(&tv, NULL);
110 /* Order in is a, b, c, d, but we should get b, c, d, a out. */
111 srand(tv.tv_usec ^ tv.tv_sec);
112 t((sq = squeue_create(1024)) != NULL);
113 t(squeue_size(sq) == 0);
114
115 /* we fill and empty the squeue completely once before testing */
116 sq_test_random(sq);
117 t(squeue_size(sq) == 0, "Size should be 0 after first sq_test_random");
118
119 t((a.evt = squeue_add(sq, time(NULL) + 9, &a)) != NULL);
120 t(squeue_size(sq) == 1);
121 t((b.evt = squeue_add(sq, time(NULL) + 3, &b)) != NULL);
122 t(squeue_size(sq) == 2);
123 t((c.evt = squeue_add_msec(sq, time(NULL) + 5, 0, &c)) != NULL);
124 t(squeue_size(sq) == 3);
125 t((d.evt = squeue_add_usec(sq, time(NULL) + 5, 1, &d)) != NULL);
126 t(squeue_size(sq) == 4);
127
128 /* add and remove lots. remainder should be what we have above */
129 sq_test_random(sq);
130
131 /* testing squeue_peek() */
132 t((x = (sq_test_event *)squeue_peek(sq)) != NULL);
133 t(x == &b, "x: %p; a: %p; b: %p; c: %p; d: %p\n", x, &a, &b, &c, &d);
134 t(x->id == b.id);
135 t(squeue_size(sq) == 4);
136
137 /* testing squeue_remove() and re-add */
138 t(squeue_remove(sq, b.evt) == 0);
139 t(squeue_size(sq) == 3);
140 t((x = squeue_peek(sq)) != NULL);
141 t(x == &c);
142 t((b.evt = squeue_add(sq, time(NULL) + 3, &b)) != NULL);
143 t(squeue_size(sq) == 4);
144
145 /* peek should now give us the &b event (again) */
146 t((x = squeue_peek(sq)) != NULL);
147 if (x != &b) {
148 printf("about to fail pretty fucking hard...\n");
149 printf("ea: %p; &b: %p; &c: %p; ed: %p; x: %p\n",
150 &a, &b, &c, &d, x);
151 }
152 t(x == &b);
153 t(x->id == b.id);
154 t(squeue_size(sq) == 4);
155
156 /* testing squeue_pop(), lifo manner */
157 t((x = squeue_pop(sq)) != NULL);
158 t(squeue_size(sq) == 3,
159 "squeue_size(sq) = %d\n", squeue_size(sq));
160 t(x == &b, "x: %p; &b: %p\n", x, &b);
161 t(x->id == b.id, "x->id: %lu; d.id: %lu\n", x->id, d.id);
162
163 /* Test squeue_pop() */
164 t((x = squeue_pop(sq)) != NULL);
165 t(squeue_size(sq) == 2);
166 t(x == &c, "x->id: %lu; c.id: %lu\n", x->id, c.id);
167 t(x->id == c.id, "x->id: %lu; c.id: %lu\n", x->id, c.id);
168
169 /* this should fail gracefully (-1 return from squeue_remove()) */
170 t(squeue_remove(NULL, NULL) == -1);
171 t(squeue_remove(NULL, a.evt) == -1);
172
173 squeue_foreach(sq, sq_walker, NULL);
174
175 /* clean up to prevent false valgrind positives */
176 squeue_destroy(sq, 0);
177
178 return t_end();
179 }
180