librfn/messageq: Lock-free N:1 message queue implementation
[tintamp:tintamp.git] / src / librfn / tests / messageqtest.c
1 /*
2  * messageqtest.c
3  *
4  * Part of librfn (a general utility library from redfelineninja.org.uk)
5  *
6  * Copyright (C) 2013 Daniel Thompson <daniel@redfelineninja.org.uk>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  */
13
14 #undef NDEBUG
15
16 #include <assert.h>
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20
21 #include <librfn.h>
22
23 int queue_buf[3];
24 messageq_t queue = MESSAGEQ_VAR_INIT(
25                 queue_buf, sizeof(queue_buf), sizeof(queue_buf[0]));
26
27
28 int main()
29 {
30         messageq_t myqueue;
31
32         /*
33          * The messageq_t data structure is intended to be safe to *send*
34          * messages from multiple threads (although only one receiver thread
35          * is permitted). However at present these tests only check for
36          * sequential correctness.
37          */
38
39         /* prove the equivalence of the initializer and the init fn */
40         messageq_init(&myqueue,
41                         queue_buf, sizeof(queue_buf), sizeof(queue_buf[0]));
42         verify(0 == memcmp(&queue, &myqueue, sizeof(queue)));
43
44         /* simple claim, send, receive, release loop */
45         for (int i=0; i<lengthof(queue_buf)*3; i++) {
46                 int *sendp = messageq_claim(&queue);
47                 verify(queue_buf + (i%lengthof(queue_buf)) == sendp);
48
49                 *sendp = i;
50                 messageq_send(&queue, sendp);
51
52                 int *receivep = messageq_receive(&queue);
53                 verify(sendp == receivep);
54                 verify(*receivep == i);
55
56                 messageq_release(&queue, receivep);
57         }
58
59         /* zealous claim with in-order sends and greedy receive */
60         verify(queue_buf+0 == messageq_claim(&queue));
61         verify(queue_buf+1 == messageq_claim(&queue));
62         verify(queue_buf+2 == messageq_claim(&queue));
63         verify(NULL == messageq_claim(&queue));
64
65         messageq_send(&queue, queue_buf+0);
66         verify(queue_buf+0 == messageq_receive(&queue));
67         verify(NULL == messageq_receive(&queue));
68         messageq_release(&queue, queue_buf+0);
69
70         messageq_send(&queue, queue_buf+1);
71         verify(queue_buf+1 == messageq_receive(&queue));
72         verify(NULL == messageq_receive(&queue));
73         messageq_release(&queue, queue_buf+1);
74
75         messageq_send(&queue, queue_buf+2);
76         verify(queue_buf+2 == messageq_receive(&queue));
77         verify(NULL == messageq_receive(&queue));
78         messageq_release(&queue, queue_buf+2);
79
80         /* zealous claim with out-of-order sends and greedy receive */
81         verify(queue_buf+0 == messageq_claim(&queue));
82         verify(queue_buf+1 == messageq_claim(&queue));
83         verify(queue_buf+2 == messageq_claim(&queue));
84         verify(NULL == messageq_claim(&queue));
85
86         messageq_send(&queue, queue_buf+2);
87         verify(NULL == messageq_receive(&queue));
88
89         messageq_send(&queue, queue_buf+1);
90         verify(NULL == messageq_receive(&queue));
91
92         messageq_send(&queue, queue_buf+0);
93         verify(queue_buf+0 == messageq_receive(&queue));
94         messageq_release(&queue, queue_buf+0);
95         verify(queue_buf+1 == messageq_receive(&queue));
96         messageq_release(&queue, queue_buf+1);
97         verify(queue_buf+2 == messageq_receive(&queue));
98         messageq_release(&queue, queue_buf+2);
99         verify(NULL == messageq_receive(&queue));
100
101         return 0;
102 }