Initial import of t_shmat.
[pcca-tests.git] / mqueue.h / t_mq_send3.c
1 /*
2  * Copyright (c) 2010, Stathis Kamperis
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
17  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
18  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
20  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
22  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
24  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27
28 #include <assert.h>
29 #include <mqueue.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>     /* memset() */
33 #include <sys/types.h>
34 #include <sys/wait.h>
35 #include <unistd.h>
36
37 #define MQNAME    "/t_mq_send3"
38 #define NMESSAGES 10
39
40 int
41 main(void)
42 {
43         /* Create message queue with maxmsg `10'. */
44         struct mq_attr attr;
45
46         memset(&attr, 0, sizeof(attr));
47         attr.mq_maxmsg = NMESSAGES;     /* Maximum number of messages. */
48         attr.mq_msgsize = 1024;         /* Maximum message size. */
49
50         /*
51          * We intentionally omit the O_NONBLOCK flag as we want our queue to
52          * operate on blocking mode.
53          */
54         mqd_t md;
55
56         md = mq_open(MQNAME, O_CREAT | O_EXCL | O_RDWR, 700, &attr);
57         assert(md != (mqd_t)-1);
58
59         /*
60          * A little bit of paranoia.
61          * Make sure that the maximum number of messages is equal to what we
62          * set it. I.e., it didn't round up under our feet, which would defeat
63          * the whole purpose of the test.
64          */
65         memset(&attr, 0, sizeof(attr));
66
67         assert(mq_getattr(md, &attr) != -1);
68         assert(attr.mq_maxmsg == NMESSAGES);
69
70         pid_t pid = fork();
71         assert(pid != -1);
72
73         if (pid == 0) {
74                 /*
75                  * We are inside the child.
76                  *
77                  * Send one more message than the maximum messages the queue
78                  * can hold. In the last message, the mq_send() call will block.
79                  */
80                 size_t i;
81
82                 for (i = 0; i < NMESSAGES + 1; i++) {
83                         assert(mq_send(md, "foo", sizeof("foo"),
84                                 /* priority */ i + 1) != -1);
85                 }
86         } else {
87                 /*
88                  * We are inside the parent.
89                  *
90                  * Sleep a bit so that child takes its time to block on
91                  * mq_send().
92                  */
93                 assert(sleep(2) == 0);
94
95                 /*
96                  * Start draining messages from the queue.
97                  * Messages are sent with increasing priority, so the last sent
98                  * is the first to be delivered.
99                  */
100                 char buf[1024];
101                 unsigned int prio;
102
103                 /*
104                  * Deliver 10th message --
105                  * this means that the last mq_send() call blocked.
106                  */
107                 assert(mq_receive(md, buf, sizeof(buf), &prio) != -1);
108                 assert(prio == NMESSAGES);
109
110                 assert(sleep(1) == 0);
111
112                 /*
113                  * Deliver 11th message --
114                  * this means that the last mq_send() call unblocked as it ought
115                  * to.
116                  */
117                 assert(mq_receive(md, buf, sizeof(buf), &prio) != -1);
118                 assert(prio == NMESSAGES + 1);
119
120                 /* We are done -- cleanup */
121                 assert(mq_close(md) != -1);
122                 assert(mq_unlink(MQNAME) != -1);
123
124                 printf("passed\n");
125
126                 return (EXIT_SUCCESS);
127         }
128
129         /* Only reached by the child. */
130         return (EXIT_SUCCESS);
131 }