source: rtems/testsuites/psxtests/psxmsgq01/init.c @ 53fb837a

4.104.114.84.95
Last change on this file since 53fb837a was 53fb837a, checked in by Joel Sherrill <joel.sherrill@…>, on 01/13/00 at 19:25:15

POSIX message queues now include complete functionality including
blocking sends when the queue is full. The SuperCore? was enhanced
to support blocking on send. The existing POSIX API was debugged
and numerous test cases were added to psxmsgq01 by Jennifer Averett.
SuperCore? enhancements and resulting modifications to other APIs
were done by Joel.

There is one significant point of interpretation for the POSIX API.
What happens to threads already blocked on a message queue when the
mode of that same message queue is changed from blocking to non-blocking?
We decided to unblock all waiting tasks with an EAGAIN error just
as if a non-blocking version of the same operation had returned
unsatisfied. This case is not discussed in the POSIX standard and
other implementations may have chosen differently.

  • Property mode set to 100644
File size: 33.8 KB
Line 
1/*
2 *  COPYRIGHT (c) 1989-1999.
3 *  On-Line Applications Research Corporation (OAR).
4 *
5 *  The license and distribution terms for this file may be
6 *  found in the file LICENSE in this distribution or at
7 *  http://www.OARcorp.com/rtems/license.html.
8 *
9 *  $Id$
10 */
11
12#define CONFIGURE_INIT
13#include "system.h"
14#include <sched.h>
15#include <fcntl.h>
16#include <time.h>
17#include <tmacros.h>
18#include <signal.h>   /* signal facilities */
19
20typedef struct {
21  char         msg[ 50 ];
22  int          size;
23  unsigned int priority;
24}Test_Message_t;
25Test_Message_t Predefined_Msgs[MAXMSG+1];
26Test_Message_t Predefined_Msgs[MAXMSG+1] = {
27  { "12345678",   9, MQ_PRIO_MAX-1 },  /* Max Length Message med  */
28  { "",           1, 1             },  /* NULL  Message      low  */
29  { "Last",       5, MQ_PRIO_MAX   },  /* Queue Full Message hi   */ 
30  { "No Message", 0, MQ_PRIO_MAX-1 },  /* 0 length Message   med  */
31  { "1",          2, 0             },  /* Cause Overflow Behavior */
32};
33int Priority_Order[MAXMSG+1] = { 2, 0, 3, 1, MAXMSG };
34
35
36typedef struct {
37  mqd_t              mq;
38  Test_Queue_Types   index;
39  char              *name;
40  int                oflag;
41  int                maxmsg;
42  int                msgsize;
43  int                count;
44} Test_queue_type;
45
46Test_queue_type Test_q[ NUMBER_OF_TEST_QUEUES ] =
47{
48  { 0, 0, "Qread",    ( O_CREAT | O_RDONLY | O_NONBLOCK ), MAXMSG, MSGSIZE, 0 },
49  { 0, 1, "Qwrite",   ( O_CREAT | O_WRONLY | O_NONBLOCK ), MAXMSG, MSGSIZE, 0 },
50  { 0, 2, "Qnoblock", ( O_CREAT | O_RDWR   | O_NONBLOCK ), MAXMSG, MSGSIZE, 0 },
51  { 0, 3, "Qblock",   ( O_CREAT | O_RDWR )               , MAXMSG, MSGSIZE, 0 },
52  { 0, 4, "Qdefault", ( O_CREAT | O_RDWR )               , 10,     16,      0 },
53  { 0, 5, "mq6",      ( O_CREAT | O_WRONLY | O_NONBLOCK ), MAXMSG, MSGSIZE, 0 },
54};
55
56#define RW_NAME             Test_q[ RW_QUEUE ].name
57#define DEFAULT_NAME        Test_q[ DEFAULT_RW ].name
58#define RD_NAME             Test_q[ RD_QUEUE ].name
59#define WR_NAME             Test_q[ WR_QUEUE ].name
60#define BLOCKING_NAME       Test_q[ BLOCKING ].name
61#define CLOSED_NAME         Test_q[ CLOSED ].name
62
63#define RW_ATTR         Test_q[ RW_QUEUE ].oflag
64#define DEFAULT_ATTR    Test_q[ DEFAULT_RW ].oflag
65#define RD_ATTR         Test_q[ RD_QUEUE ].oflag
66#define WR_ATTR         Test_q[ WR_QUEUE ].oflag
67#define BLOCK_ATTR      Test_q[ BLOCKING ].oflag
68#define CLOSED_ATTR     Test_q[ CLOSED ].oflag
69
70/*
71 * Outputs a header at each test section.
72 */
73void Start_Test(
74  char *description
75)
76{
77  printf( "_______________%s\n", description );
78}
79
80
81void Validate_attributes(
82    mqd_t  mq,
83    int    oflag,
84    int    msg_count
85)
86{
87  int             status;
88  struct mq_attr  attr;
89
90  status = mq_getattr( mq, &attr );
91  fatal_posix_service_status( status, 0, "mq_getattr valid return status");
92 
93  if ( mq != Test_q[ DEFAULT_RW ].mq ){
94    fatal_int_service_status((int)attr.mq_maxmsg, MAXMSG, "maxmsg attribute" );
95    fatal_int_service_status((int)attr.mq_msgsize,MSGSIZE,"msgsize attribute");
96  }
97
98  fatal_int_service_status((int)attr.mq_curmsgs, msg_count, "count attribute" );
99  fatal_int_service_status((int)attr.mq_flags, oflag, "flag attribute" );
100}
101
102char Queue_Name[PATH_MAX + 2];
103#define Get_Queue_Name( i )  Test_q[i].name
104
105char *Build_Queue_Name( int i ) {
106  sprintf(Queue_Name,"mq%d", i+1 );
107  return Queue_Name;
108}
109
110char *Get_Too_Long_Name()
111{
112  int i;
113
114  for ( i=0; i< PATH_MAX+1; i++ )
115    Queue_Name[i] = 'N';
116  Queue_Name[i] = '\0';
117  return Queue_Name;
118}
119
120
121void open_test_queues()
122{
123  struct mq_attr   attr;
124  int              status;
125  Test_queue_type *tq;
126  int              que;
127
128  attr.mq_maxmsg  = MAXMSG;
129  attr.mq_msgsize = MSGSIZE;
130
131  puts( "Init: Open Test Queues" );
132
133  for( que = 0; que < NUMBER_OF_TEST_QUEUES; que++ ) {
134
135    tq = &Test_q[ que ];
136    if ( que == DEFAULT_RW)
137      Test_q[que].mq = mq_open( tq->name, tq->oflag, 0x777, NULL );
138    else
139      Test_q[que].mq = mq_open( tq->name, tq->oflag, 0x777, &attr );
140
141    assert( Test_q[que].mq != (-1) );
142  }
143
144  status = mq_close( Test_q[CLOSED].mq );
145  fatal_posix_service_status( status, 0, "mq_close message queue");
146  status = mq_unlink( CLOSED_NAME );
147  fatal_posix_service_status( status, 0, "mq_unlink message queue");
148}
149
150/*
151 * Opens CONFIGURE_MAXIMUM_POSIX_MESSAGE_QUEUES then leaves size queues
152 * opened but closes the rest.
153 */
154
155void validate_mq_open_error_codes()
156{
157  int             i;
158  mqd_t           n_mq2;
159  struct mq_attr  attr;
160  int             status;
161  mqd_t           open_mq[CONFIGURE_MAXIMUM_POSIX_MESSAGE_QUEUES];
162
163  attr.mq_maxmsg  = MAXMSG;
164  attr.mq_msgsize = MSGSIZE;
165
166  Start_Test( "mq_open errors" );
167
168  /*
169   * XXX EINVAL - inappropriate name was given for the message queue
170   */
171
172  /*
173   * EINVAL - Create with negative maxmsg.
174   */
175
176  attr.mq_maxmsg = -1;
177  puts( "Init: mq_open - Create with maxmsg (-1) (EINVAL)" );
178  n_mq2 = mq_open( "mq2", O_CREAT | O_RDONLY, 0x777, &attr);
179  fatal_posix_service_status(
180    (int) n_mq2, (int ) (-1), "mq_open error return status" );
181  fatal_posix_service_status( errno, EINVAL,  "mq_open errno EINVAL");
182  attr.mq_maxmsg  = MAXMSG;
183
184  /*
185   * EINVAL - Create withnegative msgsize.
186   */
187
188  attr.mq_msgsize = -1;
189  puts( "Init: mq_open - Create with msgsize (-1) (EINVAL)" );
190  n_mq2 = mq_open( "mq2", O_CREAT | O_RDONLY, 0x777, &attr);
191  fatal_posix_service_status(
192    (int) n_mq2, (int ) (-1), "mq_open error return status" );
193  fatal_posix_service_status( errno, EINVAL,  "mq_open errno EINVAL");
194  attr.mq_msgsize = MSGSIZE;
195
196  /*
197   * ENOENT - Open a non-created file.
198   */
199
200  puts( "Init: mq_open - Open new mq without create flag (ENOENT)" );
201  n_mq2 = mq_open( "mq3", O_EXCL | O_RDONLY, 0x777, NULL);
202  fatal_posix_service_status(
203    (int) n_mq2, (int ) (-1), "mq_open error return status" );
204  fatal_posix_service_status( errno, ENOENT,  "mq_open errno ENOENT");
205
206
207  /*
208   * XXX EINTR  - call was interrupted by a signal
209   */
210
211  /*
212   * ENAMETOOLONG - Give a name greater than PATH_MAX.
213   */
214
215  puts( "Init: mq_open - Open with too long of a name (ENAMETOOLONG)" );
216  n_mq2 = mq_open( Get_Too_Long_Name(), O_CREAT | O_RDONLY, 0x777, NULL );
217  fatal_posix_service_status(
218    (int) n_mq2, (int ) (-1), "mq_open error return status" );
219  fatal_posix_service_status( errno, ENAMETOOLONG, "mq_open errno ENAMETOOLONG");
220 
221  /*
222   * XXX - ENAMETOOLONG - Give a name greater than NAME_MAX
223   *       Per implementation not possible.
224   */
225
226  /*
227   * Open maximum number of message queues
228   */
229
230  puts( "Init: mq_open - SUCCESSFUL" );
231  for (i = 0; i < CONFIGURE_MAXIMUM_POSIX_MESSAGE_QUEUES; i++) {
232    open_mq[i] = mq_open(
233      Build_Queue_Name(i), O_CREAT | O_RDWR | O_NONBLOCK, 0x777, NULL );
234    assert( open_mq[i] != (-1) );
235    /*XXX - Isn't there a more general check */
236  }
237
238  /*
239   * XXX EACCES - permission to create is denied.
240   */
241
242  /*
243   * XXX EACCES - queue exists permissions specified by o_flag are denied.
244   */
245
246  /*
247   * EEXIST - Create an existing queue.
248   */
249
250  puts( "Init: mq_open - Create an Existing mq (EEXIST)" );
251  n_mq2 = mq_open(
252    Build_Queue_Name(0), O_CREAT | O_EXCL | O_RDONLY, 0x777, NULL);
253  fatal_posix_service_status(
254    (int) n_mq2, (int ) (-1), "mq_open error return status" );
255  fatal_posix_service_status( errno, EEXIST,  "mq_open errno EEXIST");
256
257  /*
258   * XXX EMFILE  - Too many message queues in use by the process
259   */
260
261  /*
262   * ENFILE -  Too many message queues open in the system
263   */
264
265  puts( "Init: mq_open - system is out of resources (ENFILE)" );
266  n_mq2 = mq_open( Build_Queue_Name(i), O_CREAT | O_RDONLY, 0x777, NULL );
267  fatal_posix_service_status(
268    (int) n_mq2, (int ) (-1), "mq_open error return status" );
269  fatal_posix_service_status( errno, ENFILE,  "mq_open errno ENFILE");
270
271  /*
272   * Unlink and Close all queues.
273   */
274
275  puts( "Init: mq_close and mq_unlink (mq3...mqn) - SUCCESSFUL" );
276  for (i = 0; i < CONFIGURE_MAXIMUM_POSIX_MESSAGE_QUEUES; i++) {
277
278    status = mq_close( open_mq[i]);
279    fatal_posix_service_status( status, 0, "mq_close message queue");
280
281    status = mq_unlink( Build_Queue_Name(i) );
282    fatal_posix_service_status( status, 0, "mq_unlink message queue");
283  }
284}
285
286void validate_mq_unlink_error_codes()
287{
288  int             status;
289
290  Start_Test( "mq_unlink errors" );
291
292  /*
293   * XXX - EACCES Permission Denied
294   */
295
296  /*
297   * ENAMETOOLONG - Give a name greater than PATH_MAX.
298   */
299
300  puts( "Init: mq_unlink - mq_unlink with too long of a name (ENAMETOOLONG)" );
301  status = mq_unlink( Get_Too_Long_Name() );
302  fatal_posix_service_status( status, -1, "mq_unlink error return status");
303  fatal_posix_service_status( errno, ENAMETOOLONG, "mq_unlink errno ENAMETOOLONG");
304 
305  /*
306   * XXX - ENAMETOOLONG - Give a name greater than NAME_MAX
307   *       Per implementation not possible.
308   */
309
310  /*
311   *  ENOENT - Unlink an unopened queue
312   */
313
314  puts( "Init: mq_unlink - A Queue not opened  (ENOENT)" );
315  status = mq_unlink( CLOSED_NAME );
316  fatal_posix_service_status( status, -1, "mq_unlink error return status");
317  fatal_posix_service_status( errno, ENOENT, "mq_unlink errno ENOENT");
318
319  /*
320   * XXX - The following were not listed in the POSIX document as
321   *       possible errors.  Under other commands the EINVAL is
322   *       given for these conditions.
323   */
324
325  /*
326   *  EINVAL - Unlink a queue with no name
327   */
328
329  puts( "Init: mq_unlink (NULL) - EINVAL" );
330  status = mq_unlink( NULL );
331  fatal_posix_service_status( status, -1, "mq_unlink error return status");
332  fatal_posix_service_status( errno, EINVAL, "mq_unlink errno value");
333
334  /*
335   *  EINVAL - Unlink a queue with a null name
336   */
337
338  puts( "Init: mq_unlink (\"\") - EINVAL" );
339  status = mq_unlink( "" );
340  fatal_posix_service_status( status, -1, "mq_unlink error return status");
341  fatal_posix_service_status( errno, EINVAL, "mq_unlink errno value");
342}
343
344void validate_mq_close_error_codes()
345{
346  int             status;
347
348  Start_Test( "mq_close errors" );
349
350  /*
351   * EBADF - Close a queue that is not open.
352   */
353
354  puts( "Init: mq_close - unopened queue (EBADF)" );
355  status = mq_close( Test_q[CLOSED].mq );
356  fatal_posix_service_status( status, -1, "mq_close error return status");
357  fatal_posix_service_status( errno, EBADF, "mq_close errno EBADF");
358}
359 
360
361void validate_mq_getattr_error_codes()
362{
363  struct mq_attr  attr;
364  int             status;
365
366  Start_Test( "mq_getattr errors" );
367
368  /*
369   * EBADF - Get the attributes from a closed queue.
370   */
371
372  puts( "Init: mq_getattr - unopened queue (EBADF)" );
373  status = mq_getattr( Test_q[CLOSED].mq, &attr );
374  fatal_posix_service_status( status, -1, "mq_close error return status");
375  fatal_posix_service_status( errno, EBADF, "mq_close errno EBADF"); 
376
377  /*
378   * XXX - The following are not listed in the POSIX manual but
379   *       may occur.
380   */
381
382  /*
383   * EINVAL - NULL attributes
384   */
385
386  puts( "Init: mq_getattr - NULL attributes (EINVAL)" );
387  status = mq_getattr( Test_q[RW_QUEUE].mq, NULL );
388  fatal_posix_service_status( status, -1, "mq_close error return status");
389  fatal_posix_service_status( errno, EINVAL, "mq_close errno EINVAL"); 
390
391}
392
393
394void Send_msg_to_que(
395  int que,
396  int msg
397)
398{
399  Test_Message_t *ptr = &Predefined_Msgs[msg];
400  int             status;
401
402  status = mq_send( Test_q[que].mq, ptr->msg, ptr->size , ptr->priority );
403  fatal_posix_service_status( status, 0, "mq_send valid return status");
404  Test_q[que].count++;
405}
406
407void Show_send_msg_to_que(
408  char *task_name,
409  int   que,
410  int   msg
411)
412{
413  Test_Message_t *ptr = &Predefined_Msgs[msg];
414  printf( "%s mq_send -  to %s msg: %s priority %d\n",
415    task_name, Test_q[que].name, ptr->msg, ptr->priority);
416  Send_msg_to_que( que, msg );
417}
418
419void verify_queues_full( 
420  char *task_name
421)
422{
423  int          que;
424
425  /*
426   * Validate that the queues are full.
427   */
428
429  printf( "%s Verify Queues are full\n", task_name );
430  for( que = RW_QUEUE; que < CLOSED; que++ )
431    Validate_attributes( Test_q[que].mq, Test_q[que].oflag, Test_q[que].count );
432
433}
434void verify_queues_empty(
435  char *task_name
436)
437{
438  int             que;
439
440  printf( "%s Verify Queues are empty\n", task_name );
441  for( que = RW_QUEUE; que < CLOSED; que++ )
442    Validate_attributes( Test_q[que].mq, Test_q[que].oflag, 0 );
443}
444
445int fill_message_queues(
446  char *task_name
447)
448{
449  int             msg;
450  int             status;
451  int             que;
452
453
454  verify_queues_empty( task_name );
455
456  /*
457   * Fill Queue with predefined messages.
458   */
459
460  printf( "%s Fill Queues with messages\n", task_name );
461  for(msg=0; msg<MAXMSG; msg++){
462    for( que = RW_QUEUE; que < CLOSED; que++ ) {
463      Send_msg_to_que( que, msg );
464    }
465  }
466
467  verify_queues_full( "Init:" );
468  return msg;
469}
470
471
472void Read_msg_from_que(
473  int que,
474  int msg
475)
476{
477  unsigned int    priority;
478  Test_Message_t *ptr;
479  int             status;
480  char            message[100];
481  char            err_msg[100];
482
483  ptr = &Predefined_Msgs[msg];
484  status = mq_receive(Test_q[ que ].mq, message, 100, &priority );
485  Test_q[que].count--;
486
487  sprintf( err_msg, "%s msg %s size failure", Test_q[ que ].name, ptr->msg );
488  fatal_int_service_status( status, ptr->size, err_msg );
489
490  assert( !strcmp( message, ptr->msg ) );
491  strcpy( message, "No Message" );
492
493  sprintf( err_msg,"%s msg %s size failure", Test_q[ que ].name, ptr->msg );
494  fatal_int_service_status(priority, ptr->priority, err_msg );
495}
496
497int empty_message_queues(
498  char *task_name
499)
500{
501  int que;
502  int i;
503
504  printf( "%s Empty all Queues\n", task_name );
505  for( que = RW_QUEUE; que < CLOSED; que++ ) {
506    for(i=0; Test_q[que].count != 0; i++ )
507      Read_msg_from_que( que,  Priority_Order[i] );
508
509    Validate_attributes( Test_q[ que].mq, Test_q[ que ].oflag, 0 );
510  }
511  return 0;
512}
513
514/*
515 * Returns the number of messages queued after the test on the
516 * first queue.
517 */
518
519int validate_mq_send_error_codes( )
520{
521  int             status;
522  int             i;
523  char           *str;
524
525  Start_Test( "mq_send errors" );
526
527  /*
528   * EBADF - Write to a closed queue.
529   */
530
531  puts( "Init: mq_send - Closed message queue (EBADF)" );
532  status = mq_send( Test_q[CLOSED].mq, "", 1, 0 );
533  fatal_posix_service_status( status, -1, "mq_send error return status");
534  fatal_posix_service_status( errno, EBADF, "mq_send errno EBADF");
535
536  /*
537   * EBADF - Write to a read only  queue.
538   */
539
540  puts( "Init: mq_send - Read only message queue (EBADF)" );
541  status = mq_send( Test_q[ RD_QUEUE ].mq, "", 1, 0 );
542  fatal_posix_service_status( status, -1, "mq_send error return status");
543  fatal_posix_service_status( errno, EBADF, "mq_send errno EBADF");
544
545  /*
546   * XXX - EINTR      Signal interrupted the call.
547   *
548  puts( "Init: mq_send - UNSUCCESSFUL (EINTR)" );
549  status = mq_send( Test_q, "", 0xffff, 0 );
550  fatal_posix_service_status( status, -1, "mq_send error return status");
551  fatal_posix_service_status( errno, E, "mq_send errno E");
552   */
553
554  /*
555   * EINVAL priority is out of range.
556   */
557
558  puts( "Init: mq_send - Priority out of range (EINVAL)" );
559  status = mq_send( Test_q[ RW_QUEUE ].mq, "", 1, MQ_PRIO_MAX + 1 );
560  fatal_posix_service_status( status, -1, "mq_send error return status");
561  fatal_posix_service_status( errno, EINVAL, "mq_send errno EINVAL");
562
563  /*
564   *  EMSGSIZE - Message size larger than msg_len
565   *             Validates that msgsize is stored correctly.
566   */
567
568  puts( "Init: mq_send - Message longer than msg_len (EMSGSIZE)" );
569  status = mq_send( Test_q[ RW_QUEUE ].mq, "", MSGSIZE+1, 0 );
570  fatal_posix_service_status( status, -1, "mq_send error return status");
571  fatal_posix_service_status( errno, EMSGSIZE, "mq_send errno EMSGSIZE");
572
573  i = fill_message_queues( "Init:" );
574
575  /*
576   * ENOSYS - send not supported
577  puts( "Init: mq_send - Blocking Queue overflow (ENOSYS)" );
578  status = mq_send( n_mq1, Predefined_Msgs[i], 0, 0 );
579  fatal_posix_service_status( status, -1, "mq_send error return status");
580  fatal_posix_service_status( errno, EBADF, "mq_send errno EBADF");
581
582  status = mq_close( n_mq1 );
583  fatal_posix_service_status( status, 0, "mq_close message queue");
584
585  status = mq_unlink( "read_only" );
586  fatal_posix_service_status( status, 0, "mq_unlink message queue");
587   */
588
589  /*
590   * EAGAIN - O_NONBLOCK and message queue is full.
591   */
592
593  puts( "Init: mq_send - on a FULL non-blocking queue with (EAGAIN)" );
594  str = Predefined_Msgs[i].msg;
595  status = mq_send(Test_q[RW_QUEUE].mq, str, 0, 0 );
596  fatal_posix_service_status( status, -1, "mq_send error return status");
597  fatal_posix_service_status( errno, EAGAIN, "mq_send errno EAGAIN");
598
599  return i-1;
600}
601
602void validate_mq_receive_error_codes( )
603{
604  int            status;
605  char           message[100];
606  unsigned int   priority;
607  int            i;
608
609  Start_Test( "mq_receive errors"  );
610
611  /*
612   * EBADF - Not A Valid Message Queue
613   */
614
615  puts( "Init: mq_receive - Unopened message queue (EBADF)" );
616  status = mq_receive( Test_q[CLOSED].mq, message, 100, &priority );
617  fatal_posix_service_status( status, -1, "mq_ error return status");
618  fatal_posix_service_status( errno, EBADF, "mq_receive errno EBADF");
619
620  /*
621   * EBADF - Queue not opened to read
622   */
623
624  puts( "Init: mq_receive - Write only queue (EBADF)" );
625  status = mq_receive( Test_q[WR_QUEUE].mq, message, 100, &priority  );
626  fatal_posix_service_status( status, -1, "mq_ error return status");
627  fatal_posix_service_status( errno, EBADF, "mq_receive errno EBADF");
628
629  /*
630   * EMSGSIZE - Size is less than the message size attribute
631   */
632
633  puts( "Init: mq_receive - Size is less than the message (EMSGSIZE)" );
634  status = mq_receive(
635    Test_q[RW_QUEUE].mq, message, Predefined_Msgs[0].size-1, &priority );
636  fatal_posix_service_status( status, -1, "mq_ error return status");
637  fatal_posix_service_status( errno, EMSGSIZE, "mq_receive errno EMSGSIZE");
638
639
640  /*
641   * EAGAIN - O_NONBLOCK and Queue is empty
642   */
643  verify_queues_full( "Init:" );
644  empty_message_queues( "Init:" );
645
646  puts( "Init: mq_receive - Queue is empty (EAGAIN)" );
647  status = mq_receive( Test_q[RW_QUEUE].mq, message, 100, &priority );
648  fatal_posix_service_status( status, -1, "mq_ error return status");
649  fatal_posix_service_status( errno, EAGAIN, "mq_receive errno EAGAIN");
650
651  /*
652   * XXX - EINTR - Interrupted by a signal
653   */
654
655  /*
656   * XXX - EBADMSG - a data corruption problem.
657   */
658
659  /*
660   * XXX - ENOSYS - mq_receive not supported
661   */
662}
663
664void verify_open_functionality()
665{
666  mqd_t           n_mq;
667
668  Start_Test( "mq_open functionality" );
669
670  /*
671   * Validate a second open returns the same message queue.
672   */
673
674  puts( "Init: mq_open - Open an existing mq ( same id )" );
675  n_mq = mq_open( RD_NAME, 0 );
676  fatal_posix_service_status(
677    (int) n_mq, (int ) Test_q[RD_QUEUE].mq, "mq_open error return status" );
678}
679
680void verify_unlink_functionality()
681
682  mqd_t           n_mq;
683  int             status;
684
685  Start_Test( "mq_unlink functionality" );
686
687  /*
688   * Unlink the message queue, then verify an open of the same name produces a
689   * different message queue.
690   */
691
692  puts( "Init: Unlink and Open without closing SUCCESSFUL" );
693  status = mq_unlink( DEFAULT_NAME );
694  fatal_posix_service_status( status, 0, "mq_unlink locked message queue");
695
696  n_mq = mq_open( DEFAULT_NAME, DEFAULT_ATTR, 0x777, NULL );
697  assert( n_mq != (-1) );
698  assert( n_mq != Test_q[ DEFAULT_RW ].mq );
699
700
701  status = mq_unlink( DEFAULT_NAME );
702  fatal_posix_service_status( status, 0, "mq_unlink locked message queue");
703  status = mq_close( Test_q[ DEFAULT_RW ].mq );
704  fatal_posix_service_status( status, 0, "mq_close message queue");
705
706  Test_q[ DEFAULT_RW ].mq = n_mq;
707}
708
709void verify_close_functionality()
710{
711  int i;
712  int status;
713  Start_Test( "Unlink and Close All Files"  );
714  for (i=0; i<DEFAULT_RW; i++) {
715   
716    status = mq_unlink( Get_Queue_Name(i) );
717    fatal_posix_service_status( status, 0, "mq_unlink message queue");
718
719    status = mq_close( Test_q[i].mq );
720    fatal_posix_service_status( status, 0, "mq_close message queue");
721  }
722}
723
724
725void verify_timed_send_queue(
726  int  que,
727  int  is_blocking
728)
729{
730  int             i;
731  struct timespec timeout;
732  struct timeval  tv1, tv2, tv3;
733  struct timezone tz1, tz2;
734  int              len;
735  int              status;
736  char            *msg;
737
738  timeout.tv_sec  = 1;
739  timeout.tv_nsec = 0;
740 
741  printf( "Init: mq_timedsend - on queue %s ", Test_q[que].name);
742  len = Predefined_Msgs[MAXMSG].size;
743  msg = Predefined_Msgs[MAXMSG].msg;
744  gettimeofday( &tv1, &tz1 );
745  status = mq_timedsend( Test_q[que].mq, msg, len , 0, &timeout );
746  gettimeofday( &tv2, &tz2 );
747  tv3.tv_sec  = tv2.tv_sec - tv1.tv_sec;
748  tv3.tv_usec = tv2.tv_usec - tv1.tv_usec;
749
750  if ( is_blocking ) { /* Don't verify the non-blocking queue */
751    fatal_int_service_status( status, -1, "mq_timedsend status");
752    fatal_posix_service_status( errno, ETIMEDOUT,  "errno ETIMEDOUT");
753  }
754
755  printf("Init: %d sec %d us\n", tv3.tv_sec, tv3.tv_usec );
756
757  if ( is_blocking ) /* non-blocking queue */
758    assert( tv3.tv_sec == 1 );
759  else
760    assert( tv3.tv_sec == 0 );
761
762  if ( que == DEFAULT_RW )
763    Test_q[que].count++;
764}
765
766void verify_timed_send()
767{
768  int              que;
769
770  Start_Test( "mq_timedsend"  );
771
772  for( que = RW_QUEUE; que < CLOSED; que++ ) {
773    if ( que == BLOCKING )
774      verify_timed_send_queue( que, 1 );
775    else
776      verify_timed_send_queue( que, 0 );
777  }
778}
779
780void verify_timed_receive_queue(
781  char *task_name,
782  int   que,
783  int   is_blocking
784)
785{
786  char message[ 100 ];
787  unsigned int priority;
788  struct timespec tm;
789  struct timeval  tv1, tv2, tv3;
790  struct timezone tz1, tz2;
791  int              status;
792 
793  tm.tv_sec  = 1;
794  tm.tv_nsec = 0;
795
796  printf( "Init: %s mq_timedreceive - on queue %s ", task_name, Test_q[que].name);
797
798  gettimeofday( &tv1, &tz1 );
799  status = mq_timedreceive( Test_q[ que ].mq, message, 100, &priority, &tm );
800  gettimeofday( &tv2, &tz2 );
801  tv3.tv_sec  = tv2.tv_sec - tv1.tv_sec;
802  tv3.tv_usec = tv2.tv_usec - tv1.tv_usec;
803
804  fatal_int_service_status( status, -1, "mq_timedreceive status");
805  if ( is_blocking )
806    fatal_posix_service_status( errno, ETIMEDOUT,  "errno ETIMEDOUT");
807  printf( "Init: %d sec %d us\n", tv3.tv_sec, tv3.tv_usec );
808
809  if ( is_blocking )
810    assert( tv3.tv_sec == 1 );
811  else
812    assert( tv3.tv_sec == 0 );
813}
814
815
816
817void verify_timed_receive()
818{
819  int  que;
820 
821  Start_Test( "mq_timedreceive"  );
822
823  for( que = RW_QUEUE; que < CLOSED; que++ ) {
824    if (( que == BLOCKING ) || ( que == DEFAULT_RW ))
825      verify_timed_receive_queue( "Init:", que, 1 );
826    else
827      verify_timed_receive_queue( "Init:", que, 0 );
828  }
829}
830
831#if (0)
832void verify_set_attr()
833{
834  struct mq_attr save_attr[ NUMBER_OF_TEST_QUEUES ];
835  struct mq_attr attr;
836  int            i;
837  int            status;
838
839  attr.mq_maxmsg  = 0;
840  attr.mq_msgsize = 0;
841
842  Start_Test( "mq_setattr"  );
843
844  puts( "Init: set_attr all queues to blocking" );
845  for(i=0; i<CLOSED; i++) {
846    attr.mq_flags =  Test_q[i].oflag & (~O_NONBLOCK );
847    status = mq_setattr( Test_q[i].mq, &attr, &save_attr[i] );
848    fatal_int_service_status( status, 0, "mq_setattr valid return status");
849
850    Validate_attributes( Test_q[i].mq, attr.mq_flags, 0 );
851  }
852
853  for( i = RW_QUEUE; i < CLOSED; i++ ) {
854    verify_timed_receive_queue( "Init:", i, 1 );
855  }
856 
857  for(i=0; i<CLOSED; i++) {
858    attr.mq_flags =  Test_q[i].oflag & (~O_NONBLOCK );
859    status = mq_setattr( Test_q[i].mq, &save_attr[i], NULL );
860    fatal_int_service_status( status, 0, "mq_setattr valid return status");
861
862    Validate_attributes( Test_q[i].mq, Test_q[i].oflag, 0 );
863  }
864}
865#endif
866
867void wait_for_signal(
868  sigset_t     *waitset,
869  int           sec,
870  int           expect_signal
871)
872{
873  siginfo_t         siginfo;
874  int               status;
875  struct timespec   timeout;
876  int               signo;
877
878  siginfo.si_code = -1;
879  siginfo.si_signo = -1;
880  siginfo.si_value.sival_int = -1;
881
882  timeout.tv_sec = sec;
883  timeout.tv_nsec = 0;
884
885  status = sigemptyset( waitset );
886  assert( !status );
887
888  status = sigaddset( waitset, SIGUSR1 );
889  assert( !status );
890
891  printf( "waiting on any signal for %d seconds.\n", sec );
892  signo = sigtimedwait( waitset, &siginfo, &timeout );
893  if (expect_signal) {
894    fatal_int_service_status( signo, SIGUSR1, "got SISUSR1" );
895  } else {
896    fatal_int_service_status( signo, -1, "error return status");
897    fatal_posix_service_status( errno, EAGAIN, "errno EAGAIN");
898  }
899}
900
901void verify_notify()
902{
903  struct sigevent event;
904  int             status;
905  timer_t         timer_id;
906  sigset_t        set;
907  Test_Message_t *ptr;
908
909  Start_Test( "mq_notify"  );
910
911  /* timer create */
912  event.sigev_notify = SIGEV_SIGNAL;
913  event.sigev_signo  = SIGUSR1;
914  if (timer_create (CLOCK_REALTIME, &event, &timer_id) == -1)
915    fatal_posix_service_status( errno, 0,  "errno ETIMEDOUT");
916
917  /* block the timer signal */
918  sigemptyset( &set );
919  sigaddset( &set, SIGUSR1 );
920  pthread_sigmask( SIG_BLOCK, &set, NULL );
921
922  /*
923   * EBADF - Not A Valid Message Queue
924   */
925
926  puts( "Init: mq_notify - Unopened message queue (EBADF)" );
927  status = mq_notify( Test_q[CLOSED].mq, NULL );
928  fatal_posix_service_status( status, -1, "mq_ error return status");
929  fatal_posix_service_status( errno, EBADF, "mq_receive errno EBADF");
930
931  /*
932   * Create ...
933   */
934
935  /*
936   * XXX setup notification
937   */
938
939  printf( "_____mq_notify - notify when %s gets a message\n",RW_NAME);
940  status = mq_notify( Test_q[RW_QUEUE].mq, &event );
941  fatal_posix_service_status( status, 0, "mq_notify valid status");
942  wait_for_signal( &set, 3, 0 );
943
944  /*
945   * Send and verify signal occurs and registration is removed.
946   */
947
948  puts( "Init: Verify Signal when send" );
949  Show_send_msg_to_que( "Init:", RW_QUEUE, 0 );
950  wait_for_signal( &set, 3, 1 );
951  Read_msg_from_que( RW_QUEUE, 0 );
952
953  puts( "Init: Verify No Signal when send" );
954  Show_send_msg_to_que( "Init:", RW_QUEUE, 0 );
955  wait_for_signal( &set, 3, 0 );
956  Read_msg_from_que( RW_QUEUE, 0 );
957
958
959  /*
960   * EBUSY - Already Registered
961   */
962
963  printf( "____mq_notify - notify when %s gets a message\n",RD_NAME);
964  status = mq_notify( Test_q[RW_QUEUE].mq, &event );
965  fatal_posix_service_status( status, 0, "mq_notify valid status");
966  wait_for_signal( &set, 3, 0 );
967
968  puts( "Init: mq_notify -  (EBUSY)" );
969  status = mq_notify( Test_q[RW_QUEUE].mq, &event );
970  fatal_posix_service_status( status, -1, "mq_notify error return status");
971  fatal_posix_service_status( errno, EBUSY, "mq_notify errno EBUSY");
972
973  /*
974   * Verify NULL removes registration.
975   */
976
977  puts( "Init: mq_notify - Remove notification with null" );
978  status = mq_notify( Test_q[RW_QUEUE].mq, NULL );
979  fatal_posix_service_status( status, 0, "mq_notify valid status");
980
981  puts( "Init: Verify No Signal when send" );
982  Show_send_msg_to_que( "Init:", RW_QUEUE, 0 );
983  wait_for_signal( &set, 3, 0 );
984  Read_msg_from_que( RW_QUEUE, 0 );
985
986}
987
988void verify_with_threads()
989{
990  int               status;
991  pthread_t         id;
992  Test_Message_t   *ptr;
993  unsigned int      priority;
994  char              message[100];
995
996
997  /*
998   * Create a task then block until the task sends the message.
999   * Task tests set attributes so one queue will have a thread
1000   * blocked while attributes are changed.
1001   */
1002
1003  Start_Test( "multi-thread Task 4 Receive Test"  );
1004  status = pthread_create( &id, NULL, Task_4, NULL );
1005  assert( !status );
1006  puts( "Init: mq_receive - Empty queue changes to non-blocking (EAGAIN)" );
1007  status = mq_receive( Test_q[BLOCKING].mq, message, 100, &priority );
1008  fatal_int_service_status( status, -1, "mq_receive error return status");
1009  fatal_posix_service_status( errno, EAGAIN, "mq_receive errno EAGAIN");
1010  print_current_time( "Init: ", "" );
1011
1012  /*
1013   * Create a task then block until the task sends the message.
1014   * Task tests set attributes so one queue will have a thread
1015   * blocked while attributes are changed.
1016   */
1017
1018  Start_Test( "multi-thread Task 1 Test"  );
1019  status = pthread_create( &id, NULL, Task_1, NULL );
1020  assert( !status );
1021  Read_msg_from_que(  BLOCKING, 0 ); /* Block until init writes */
1022  print_current_time( "Init: ", "" );
1023
1024  /*
1025   * Create a task then block until the task reads a message.
1026   */
1027
1028  Start_Test( "multi-thread Task 4 Send Test"  );
1029  fill_message_queues( "Init:" );
1030  status = pthread_create( &id, NULL, Task_4, NULL );
1031  assert( !status );
1032  puts( "Init: mq_send - Full queue changes to non-blocking (EAGAIN)" );
1033  status = mq_send(Test_q[BLOCKING].mq, message, 0, 0 );
1034  fatal_posix_service_status( status, -1, "mq_send error return status");
1035  fatal_posix_service_status( errno, EAGAIN, "mq_send errno EAGAIN");
1036  verify_queues_full( "Init:" );
1037  empty_message_queues( "Init:" );
1038
1039  /*
1040   * Create a task then block until the task reads a message.
1041   */
1042
1043  Start_Test( "multi-thread Task 2 Test"  );
1044  fill_message_queues( "Init:" );
1045  status = pthread_create( &id, NULL, Task_2, NULL );
1046  assert( !status );
1047  Show_send_msg_to_que( "Init:", BLOCKING, Priority_Order[0] );
1048  print_current_time( "Init: ", "" );
1049  verify_queues_full( "Init:" );
1050  empty_message_queues( "Init:" );
1051
1052  /*
1053   * Create a task then block until it deletes and closes all queues.
1054   *     EBADF - Queue unlinked and closed while blocked
1055   */
1056
1057  Start_Test( "multi-thread Task 3 Test"  );
1058  fill_message_queues( "Init:" );
1059  status = pthread_create( &id, NULL, Task_3, NULL );
1060  assert( !status );
1061  puts( "Init: mq_send - Block while thread deletes queue (EBADF)" );
1062  ptr = &Predefined_Msgs[0];
1063  status = mq_send( Test_q[BLOCKING].mq, ptr->msg, ptr->size , ptr->priority );
1064  fatal_posix_service_status( status, -1, "mq_send error return status");
1065  fatal_posix_service_status( errno, EBADF, "mq_send errno EBADF");
1066
1067}
1068
1069void validate_mq_setattr()
1070{
1071  struct mq_attr  attr;
1072  struct mq_attr  save_attr[ NUMBER_OF_TEST_QUEUES ];
1073  int             status;
1074  int            i;
1075
1076  /*
1077   * EBADF - Get the attributes from a closed queue.
1078   */
1079
1080  puts( "Task1:mq_setattr - unopened queue (EBADF)" );
1081  status = mq_setattr( Test_q[CLOSED].mq, &attr, NULL );
1082  fatal_posix_service_status( status, -1, "mq_setattr error return status");
1083  fatal_posix_service_status( errno, EBADF, "mq_setattr errno EBADF"); 
1084
1085  /*
1086   * XXX - The following are not listed in the POSIX manual but
1087   *       may occur.
1088   */
1089
1090  /*
1091   * EINVAL - NULL attributes
1092   */
1093
1094  puts( "Task1:mq_setattr - NULL attributes (EINVAL)" );
1095  status = mq_setattr( Test_q[RW_QUEUE].mq, NULL, NULL );
1096  fatal_posix_service_status( status, -1, "mq_setattr error return status");
1097  fatal_posix_service_status( errno, EINVAL, "mq_setattr errno EINVAL"); 
1098
1099  /*
1100   * Verify change queues to blocking, by verifying all queues block
1101   * for a timed receive.
1102   */
1103
1104  puts( "Init: set_attr all queues to blocking" );
1105  for(i=0; i<CLOSED; i++) {
1106    attr.mq_flags =  Test_q[i].oflag & (~O_NONBLOCK );
1107    status = mq_setattr( Test_q[i].mq, &attr, &save_attr[i] );
1108    fatal_int_service_status( status, 0, "mq_setattr valid return status");
1109    Validate_attributes( Test_q[i].mq, attr.mq_flags, 0 );
1110  }
1111  for( i = RW_QUEUE; i < CLOSED; i++ ) {
1112    verify_timed_receive_queue( "Init:", i, 1 );
1113  }
1114
1115  /*
1116   * Restore restore all queues to their old attribute.
1117   */
1118 
1119  for(i=0; i<CLOSED; i++) {
1120    status = mq_setattr( Test_q[i].mq, &save_attr[i], NULL );
1121    fatal_int_service_status( status, 0, "mq_setattr valid return status");
1122    Validate_attributes( Test_q[i].mq, Test_q[i].oflag, 0 );
1123  }
1124}
1125
1126void *POSIX_Init(
1127  void *argument
1128)
1129{
1130  int             status;
1131  mqd_t           n_mq2;
1132
1133  puts( "\n\n*** POSIX MESSAGE QUEUE TEST ***" );
1134
1135  validate_mq_open_error_codes( );
1136  open_test_queues();
1137  validate_mq_unlink_error_codes();
1138  validate_mq_close_error_codes();
1139  verify_unlink_functionality();
1140  validate_mq_setattr( );
1141  validate_mq_send_error_codes();
1142  validate_mq_getattr_error_codes();
1143  verify_timed_send();
1144  validate_mq_receive_error_codes();
1145  verify_timed_receive();
1146  verify_open_functionality();
1147  verify_notify();
1148  verify_with_threads();
1149 
1150  puts( "*** END OF POSIX MESSAGE QUEUE TEST ***" );
1151  exit( 0 );
1152
1153  return NULL; /* just so the compiler thinks we returned something */
1154}
1155
1156
1157void *Task_1 (
1158  void *argument
1159)
1160{
1161  int      status;
1162  int      count = 0;
1163  sigset_t set;
1164
1165  /* Block Waiting for a message */
1166
1167  print_current_time( "Task_1: ", "" );
1168
1169  Show_send_msg_to_que( "Task_1:", BLOCKING, 0 );
1170
1171  puts( "Task_1: pthread_exit" );
1172  pthread_exit( NULL );
1173
1174  /* switch to Init */
1175
1176  assert( 0 );
1177  return NULL; /* just so the compiler thinks we returned something */
1178}
1179
1180void *Task_2(
1181  void *argument
1182)
1183{
1184  int status;
1185
1186 
1187  print_current_time( "Task_2: ", "" );
1188
1189 
1190  /* Block waiting to send a message */
1191
1192  verify_queues_full( "Task_2:" );
1193  Read_msg_from_que( BLOCKING, Priority_Order[0] ); /* Cause context switch */
1194
1195  puts( "Task_2: pthread_exit" );
1196  pthread_exit( NULL );
1197
1198     /* switch to Init */
1199
1200  return NULL; /* just so the compiler thinks we returned something */
1201}
1202
1203void *Task_3 (
1204  void *argument
1205)
1206{
1207
1208  print_current_time( "Task_3: ", "" );
1209
1210  /*
1211   * close and unlink all queues.
1212   */
1213
1214  verify_close_functionality( "Task_3: " );
1215  puts( "Task_3: pthread_exit" );
1216  pthread_exit( NULL );
1217
1218     /* switch to Init */
1219
1220  return NULL; /* just so the compiler thinks we returned something */
1221
1222}
1223
1224void *Task_4 (
1225  void *argument
1226)
1227{
1228  struct mq_attr  attr;
1229  int             status;
1230  int             count;
1231
1232  print_current_time( "Task_4: ", "" );
1233
1234  /*
1235   * Set the count to the number of messages in the queue.
1236   */
1237
1238  status = mq_getattr( Test_q[BLOCKING].mq, &attr );
1239  fatal_posix_service_status( status, 0, "mq_getattr valid return status");
1240  count = attr.mq_curmsgs;
1241
1242  puts("Task_4: Set queue to non-blocking");
1243  attr.mq_flags =  Test_q[BLOCKING].oflag | O_NONBLOCK;
1244  status = mq_setattr( Test_q[BLOCKING].mq, &attr, NULL );
1245  fatal_int_service_status( status, 0, "mq_setattr valid return status");
1246  Validate_attributes( Test_q[BLOCKING].mq, attr.mq_flags, count );
1247
1248  puts("Task_4: Return queue to blocking");
1249  attr.mq_flags =  Test_q[BLOCKING].oflag;
1250  status = mq_setattr( Test_q[BLOCKING].mq, &attr, NULL );
1251  fatal_int_service_status( status, 0, "mq_setattr valid return status");
1252  Validate_attributes( Test_q[BLOCKING].mq, attr.mq_flags, count );
1253
1254  puts( "Task_4: pthread_exit" );
1255  pthread_exit( NULL );
1256
1257     /* switch to Init */
1258
1259  return NULL; /* just so the compiler thinks we returned something */
1260
1261}
1262
1263void *Task_5 (
1264  void *argument
1265)
1266{
1267
1268  print_current_time( "Task_5: ", "" );
1269
1270  puts( "Task_5: pthread_exit" );
1271  pthread_exit( NULL );
1272
1273     /* switch to Init */
1274
1275  return NULL; /* just so the compiler thinks we returned something */
1276
1277}
1278
1279void *Task_ (
1280  void *argument
1281)
1282{
1283
1284  print_current_time( "Task_: ", "" );
1285
1286  puts( "Task_: pthread_exit" );
1287  pthread_exit( NULL );
1288
1289     /* switch to Init */
1290
1291  return NULL; /* just so the compiler thinks we returned something */
1292
1293}
1294
1295
1296
1297 
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
Note: See TracBrowser for help on using the repository browser.