1/*
2* Copyright (c) 2004, Bull S.A..  All rights reserved.
3* Created by: Sebastien Decugis
4
5* This program is free software; you can redistribute it and/or modify it
6* under the terms of version 2 of the GNU General Public License as
7* published by the Free Software Foundation.
8*
9* This program is distributed in the hope that it would be useful, but
10* WITHOUT ANY WARRANTY; without even the implied warranty of
11* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12*
13* You should have received a copy of the GNU General Public License along
14* with this program; if not, write the Free Software Foundation, Inc., 59
15* Temple Place - Suite 330, Boston MA 02111-1307, USA.
16
17
18* This sample test aims to check the following assertion:
19*
20* The opened message queue descriptors are copied to the child process and
21* refer to the same object.
22
23* The steps are:
24* -> Open a message queue descriptor.
25* -> Send a message to this descriptor.
26* -> fork
27* -> check if that the child's message count for this descriptor is 1.
28
29* The test fails if the child reports 0 message count
30*  or if it fails to read the descriptor.
31
32*/
33
34
35/* We are testing conformance to IEEE Std 1003.1, 2003 Edition */
36#define _POSIX_C_SOURCE 200112L
37
38/********************************************************************************************/
39/****************************** standard includes *****************************************/
40/********************************************************************************************/
41#include <pthread.h>
42 #include <stdarg.h>
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <unistd.h>
47
48#include <sys/wait.h>
49 #include <errno.h>
50
51#include <mqueue.h>
52#include <sys/stat.h>
53
54/********************************************************************************************/
55/******************************   Test framework   *****************************************/
56/********************************************************************************************/
57#include "testfrmw.h"
58 #include "testfrmw.c"
59/* This header is responsible for defining the following macros:
60 * UNRESOLVED(ret, descr);
61 *    where descr is a description of the error and ret is an int (error code for example)
62 * FAILED(descr);
63 *    where descr is a short text saying why the test has failed.
64 * PASSED();
65 *    No parameter.
66 *
67 * Both three macros shall terminate the calling process.
68 * The testcase shall not terminate in any other maneer.
69 *
70 * The other file defines the functions
71 * void output_init()
72 * void output(char * string, ...)
73 *
74 * Those may be used to output information.
75 */
76
77/********************************************************************************************/
78/********************************** Configuration ******************************************/
79/********************************************************************************************/
80#ifndef VERBOSE
81#define VERBOSE 1
82#endif
83
84/********************************************************************************************/
85/***********************************    Test case   *****************************************/
86/********************************************************************************************/
87
88/* The main test function. */
89int main( int argc, char * argv[] )
90{
91	int ret, status;
92	pid_t child, ctl;
93
94	mqd_t mq;
95	char rcv[ 20 ];
96
97	struct mq_attr mqa;
98
99
100	/* Initialize output */
101	output_init();
102
103	/* Create a message queue descriptor */
104	mqa.mq_maxmsg = 2;
105	mqa.mq_msgsize = 20;
106
107	mq = mq_open( "/fork_19_1_mq"
108	              , O_RDWR | O_CREAT | O_NONBLOCK
109	              , S_IRUSR | S_IWUSR
110	              , &mqa );
111
112	if ( mq == ( mqd_t ) - 1 )
113	{
114		UNRESOLVED( errno, "Failed to create the message queue descriptor" );
115	}
116
117	/* Send 1 message to this message queue */
118	ret = mq_send( mq, "I'm your father...", 19, 0 );
119
120	if ( ret != 0 )
121	{
122		UNRESOLVED( errno, "Failed to send the message" );
123	}
124
125	/* Check the message has been queued */
126	ret = mq_getattr( mq, &mqa );
127
128	if ( ret != 0 )
129	{
130		UNRESOLVED( errno, "Failed to get message queue attributes" );
131	}
132
133	if ( mqa.mq_curmsgs != 1 )
134	{
135		UNRESOLVED( -1, "The queue information does not show the new message" );
136	}
137
138
139	/* Create the child */
140	child = fork();
141
142	if ( child == ( pid_t ) - 1 )
143	{
144		UNRESOLVED( errno, "Failed to fork" );
145	}
146
147	/* child */
148	if ( child == ( pid_t ) 0 )
149	{
150		ret = mq_getattr( mq, &mqa );
151
152		if ( ret != 0 )
153		{
154			FAILED( "Failed to get message queue attributes in child" );
155		}
156
157		if ( mqa.mq_curmsgs != 1 )
158		{
159			FAILED( "The queue information does not show the message in child" );
160		}
161
162		/* Now, receive the message */
163		ret = mq_receive( mq, rcv, 20, NULL );
164
165		if ( ret != 19 )  /* expected message size */
166		{
167			UNRESOLVED( errno, "Failed to receive the message" );
168		}
169
170#if VERBOSE > 0
171		output( "Received message: %s\n", rcv );
172
173#endif
174
175		/* We're done */
176		exit( PTS_PASS );
177	}
178
179	/* Parent joins the child */
180	ctl = waitpid( child, &status, 0 );
181
182	if ( ctl != child )
183	{
184		UNRESOLVED( errno, "Waitpid returned the wrong PID" );
185	}
186
187	if ( ( !WIFEXITED( status ) ) || ( WEXITSTATUS( status ) != PTS_PASS ) )
188	{
189		FAILED( "Child exited abnormally" );
190	}
191
192	/* Check the message has been unqueued */
193	ret = mq_getattr( mq, &mqa );
194
195	if ( ret != 0 )
196	{
197		UNRESOLVED( errno, "Failed to get message queue attributes the 2nd time" );
198	}
199
200	if ( mqa.mq_curmsgs != 0 )
201	{
202		FAILED( "The message received in child was not dequeued." );
203	}
204
205	/* Test passed */
206#if VERBOSE > 0
207	output( "Test passed\n" );
208
209#endif
210	PASSED;
211}
212
213