1314818Sngie/*	$NetBSD: t_mqueue.c,v 1.6 2017/01/14 20:57:24 christos Exp $ */
2272343Sngie
3272343Sngie/*
4272343Sngie * Test for POSIX message queue priority handling.
5272343Sngie *
6272343Sngie * This file is in the Public Domain.
7272343Sngie */
8272343Sngie
9290913Sngie#include <sys/stat.h>
10290913Sngie
11272343Sngie#include <atf-c.h>
12314818Sngie#include <errno.h>
13314818Sngie#include <fcntl.h>
14314818Sngie#include <mqueue.h>
15272343Sngie#include <stdio.h>
16272343Sngie#include <stdlib.h>
17272343Sngie#include <string.h>
18272343Sngie#include <unistd.h>
19272343Sngie
20314818Sngie#ifdef __FreeBSD__
21314818Sngie#include "freebsd_test_suite/macros.h"
22314818Sngie#endif
23272343Sngie
24272343Sngie#define	MQ_PRIO_BASE	24
25272343Sngie
26272343Sngiestatic void
27272343Sngiesend_msgs(mqd_t mqfd)
28272343Sngie{
29272343Sngie	char msg[2];
30272343Sngie
31272343Sngie	msg[1] = '\0';
32272343Sngie
33272343Sngie	msg[0] = 'a';
34272343Sngie	ATF_REQUIRE_MSG(mq_send(mqfd, msg, sizeof(msg), MQ_PRIO_BASE) != -1,
35272343Sngie	    "mq_send 1 failed: %d", errno);
36272343Sngie
37272343Sngie	msg[0] = 'b';
38272343Sngie	ATF_REQUIRE_MSG(mq_send(mqfd, msg, sizeof(msg), MQ_PRIO_BASE + 1) != -1,
39272343Sngie	    "mq_send 2 failed: %d", errno);
40272343Sngie
41272343Sngie	msg[0] = 'c';
42272343Sngie	ATF_REQUIRE_MSG(mq_send(mqfd, msg, sizeof(msg), MQ_PRIO_BASE) != -1,
43272343Sngie	    "mq_send 3 failed: %d", errno);
44272343Sngie
45272343Sngie	msg[0] = 'd';
46272343Sngie	ATF_REQUIRE_MSG(mq_send(mqfd, msg, sizeof(msg), MQ_PRIO_BASE - 1) != -1,
47272343Sngie	    "mq_send 4 failed: %d", errno);
48272343Sngie
49272343Sngie	msg[0] = 'e';
50272343Sngie	ATF_REQUIRE_MSG(mq_send(mqfd, msg, sizeof(msg), 0) != -1,
51272343Sngie	    "mq_send 5 failed: %d", errno);
52272343Sngie
53272343Sngie	msg[0] = 'f';
54272343Sngie	ATF_REQUIRE_MSG(mq_send(mqfd, msg, sizeof(msg), MQ_PRIO_BASE + 1) != -1,
55272343Sngie	    "mq_send 6 failed: %d", errno);
56272343Sngie}
57272343Sngie
58272343Sngiestatic void
59272343Sngiereceive_msgs(mqd_t mqfd)
60272343Sngie{
61272343Sngie	struct mq_attr mqa;
62272343Sngie	char *m;
63272343Sngie	unsigned p;
64272343Sngie	int len;
65272343Sngie
66272343Sngie	ATF_REQUIRE_MSG(mq_getattr(mqfd, &mqa) != -1, "mq_getattr failed %d",
67272343Sngie	    errno);
68272343Sngie
69272343Sngie	len = mqa.mq_msgsize;
70272343Sngie	m = calloc(1, len);
71272343Sngie	ATF_REQUIRE_MSG(m != NULL, "calloc failed");
72272343Sngie
73272343Sngie	ATF_REQUIRE_MSG(mq_receive(mqfd, m, len, &p) != -1,
74272343Sngie	    "mq_receive 1 failed: %d", errno);
75272343Sngie	ATF_REQUIRE_MSG(p == (MQ_PRIO_BASE + 1) && m[0] == 'b',
76272343Sngie	    "mq_receive 1 prio/data mismatch");
77272343Sngie
78272343Sngie	ATF_REQUIRE_MSG(mq_receive(mqfd, m, len, &p) != -1,
79272343Sngie	    "mq_receive 2 failed: %d", errno);
80272343Sngie	ATF_REQUIRE_MSG(p == (MQ_PRIO_BASE + 1) && m[0] == 'f',
81272343Sngie	    "mq_receive 2 prio/data mismatch");
82272343Sngie
83272343Sngie	ATF_REQUIRE_MSG(mq_receive(mqfd, m, len, &p) != -1,
84272343Sngie	    "mq_receive 3 failed: %d", errno);
85272343Sngie	ATF_REQUIRE_MSG(p == MQ_PRIO_BASE && m[0] == 'a',
86272343Sngie	    "mq_receive 3 prio/data mismatch");
87272343Sngie
88272343Sngie	ATF_REQUIRE_MSG(mq_receive(mqfd, m, len, &p) != -1,
89272343Sngie	    "mq_receive 4 failed: %d", errno);
90272343Sngie	ATF_REQUIRE_MSG(p == MQ_PRIO_BASE && m[0] == 'c',
91272343Sngie	    "mq_receive 4 prio/data mismatch");
92272343Sngie
93272343Sngie	ATF_REQUIRE_MSG(mq_receive(mqfd, m, len, &p) != -1,
94272343Sngie	    "mq_receive 5 failed: %d", errno);
95272343Sngie	ATF_REQUIRE_MSG(p == (MQ_PRIO_BASE - 1) && m[0] == 'd',
96272343Sngie	    "mq_receive 5 prio/data mismatch");
97272343Sngie
98272343Sngie	ATF_REQUIRE_MSG(mq_receive(mqfd, m, len, &p) != -1,
99272343Sngie	    "mq_receive 6 failed: %d", errno);
100272343Sngie	ATF_REQUIRE_MSG(p == 0 && m[0] == 'e',
101272343Sngie	    "mq_receive 6 prio/data mismatch");
102272343Sngie}
103272343Sngie
104272343SngieATF_TC(mqueue);
105272343SngieATF_TC_HEAD(mqueue, tc)
106272343Sngie{
107272343Sngie
108272343Sngie	atf_tc_set_md_var(tc, "timeout", "3");
109272343Sngie	atf_tc_set_md_var(tc, "descr", "Checks mqueue send/receive");
110272343Sngie}
111272343Sngie
112272343SngieATF_TC_BODY(mqueue, tc)
113272343Sngie{
114272343Sngie	int status;
115272343Sngie	char *tmpdir;
116272343Sngie	char template[32];
117272343Sngie	char mq_name[64];
118272343Sngie
119290913Sngie#ifdef __FreeBSD__
120290913Sngie	ATF_REQUIRE_KERNEL_MODULE("mqueuefs");
121290913Sngie#endif
122290913Sngie
123272343Sngie	strlcpy(template, "./t_mqueue.XXXXXX", sizeof(template));
124272343Sngie	tmpdir = mkdtemp(template);
125272343Sngie	ATF_REQUIRE_MSG(tmpdir != NULL, "mkdtemp failed: %d", errno);
126290913Sngie#ifdef __FreeBSD__
127290913Sngie	snprintf(mq_name, sizeof(mq_name), "/t_mqueue");
128290913Sngie#else
129272343Sngie	snprintf(mq_name, sizeof(mq_name), "%s/mq", tmpdir);
130290913Sngie#endif
131272343Sngie
132272343Sngie	mqd_t mqfd;
133272343Sngie
134272343Sngie	mqfd = mq_open(mq_name, O_RDWR | O_CREAT,
135272343Sngie	    S_IRUSR | S_IRWXG | S_IROTH, NULL);
136290913Sngie#ifdef __FreeBSD__
137290913Sngie	ATF_REQUIRE_MSG(mqfd != (mqd_t)-1, "mq_open failed: %d", errno);
138290913Sngie#else
139272343Sngie	ATF_REQUIRE_MSG(mqfd != -1, "mq_open failed: %d", errno);
140290913Sngie#endif
141272343Sngie
142272343Sngie	send_msgs(mqfd);
143272343Sngie	receive_msgs(mqfd);
144272343Sngie
145272343Sngie	status = mq_close(mqfd);
146272343Sngie	ATF_REQUIRE_MSG(status == 0, "mq_close failed: %d", errno);
147272343Sngie}
148272343Sngie
149272343SngieATF_TP_ADD_TCS(tp)
150272343Sngie{
151272343Sngie	ATF_TP_ADD_TC(tp, mqueue);
152272343Sngie
153272343Sngie	return atf_no_error();
154272343Sngie}
155