1+ use cfg_if:: cfg_if;
12use std:: ffi:: CString ;
23use std:: str;
34
@@ -6,6 +7,25 @@ use nix::mqueue::{mq_open, mq_close, mq_send, mq_receive, mq_attr_member_t};
67use nix:: mqueue:: { MqAttr , MQ_OFlag } ;
78use nix:: sys:: stat:: Mode ;
89
10+ // Defined as a macro such that the error source is reported as the caller's location.
11+ macro_rules! assert_attr_eq {
12+ ( $read_attr: ident, $initial_attr: ident) => {
13+ cfg_if! {
14+ if #[ cfg( any( target_os = "dragonfly" , target_os = "netbsd" ) ) ] {
15+ // NetBSD (and others which inherit its implementation) include other flags
16+ // in read_attr, such as those specified by oflag. Just make sure at least
17+ // the correct bits are set.
18+ assert_eq!( $read_attr. flags( ) & $initial_attr. flags( ) , $initial_attr. flags( ) ) ;
19+ assert_eq!( $read_attr. maxmsg( ) , $initial_attr. maxmsg( ) ) ;
20+ assert_eq!( $read_attr. msgsize( ) , $initial_attr. msgsize( ) ) ;
21+ assert_eq!( $read_attr. curmsgs( ) , $initial_attr. curmsgs( ) ) ;
22+ } else {
23+ assert_eq!( $read_attr, $initial_attr) ;
24+ }
25+ }
26+ }
27+ }
28+
929#[ test]
1030fn test_mq_send_and_receive ( ) {
1131 const MSG_SIZE : mq_attr_member_t = 32 ;
@@ -37,7 +57,6 @@ fn test_mq_send_and_receive() {
3757
3858
3959#[ test]
40- #[ cfg( not( any( target_os = "netbsd" ) ) ) ]
4160fn test_mq_getattr ( ) {
4261 use nix:: mqueue:: mq_getattr;
4362 const MSG_SIZE : mq_attr_member_t = 32 ;
@@ -53,13 +72,12 @@ fn test_mq_getattr() {
5372 let mqd = r. unwrap ( ) ;
5473
5574 let read_attr = mq_getattr ( mqd) . unwrap ( ) ;
56- assert_eq ! ( read_attr, initial_attr) ;
75+ assert_attr_eq ! ( read_attr, initial_attr) ;
5776 mq_close ( mqd) . unwrap ( ) ;
5877}
5978
6079// FIXME: Fix failures for mips in QEMU
6180#[ test]
62- #[ cfg( not( any( target_os = "netbsd" ) ) ) ]
6381#[ cfg_attr( all(
6482 qemu,
6583 any( target_arch = "mips" , target_arch = "mips64" )
@@ -79,28 +97,33 @@ fn test_mq_setattr() {
7997 } ;
8098 let mqd = r. unwrap ( ) ;
8199
82- let new_attr = MqAttr :: new ( 0 , 20 , MSG_SIZE * 2 , 100 ) ;
100+ let new_attr = MqAttr :: new ( 0 , 20 , MSG_SIZE * 2 , 100 ) ;
83101 let old_attr = mq_setattr ( mqd, & new_attr) . unwrap ( ) ;
84- assert_eq ! ( old_attr, initial_attr) ;
102+ assert_attr_eq ! ( old_attr, initial_attr) ;
85103
86- let new_attr_get = mq_getattr ( mqd) . unwrap ( ) ;
87- // The following tests make sense. No changes here because according to the Linux man page only
104+ // No changes here because according to the Linux man page only
88105 // O_NONBLOCK can be set (see tests below)
89- assert_ne ! ( new_attr_get, new_attr) ;
106+ #[ cfg( not( any( target_os = "dragonfly" , target_os = "netbsd" ) ) ) ]
107+ {
108+ let new_attr_get = mq_getattr ( mqd) . unwrap ( ) ;
109+ assert_ne ! ( new_attr_get, new_attr) ;
110+ }
90111
91- let new_attr_non_blocking = MqAttr :: new ( MQ_OFlag :: O_NONBLOCK . bits ( ) as mq_attr_member_t , 10 , MSG_SIZE , 0 ) ;
112+ let new_attr_non_blocking = MqAttr :: new ( MQ_OFlag :: O_NONBLOCK . bits ( ) as mq_attr_member_t , 10 , MSG_SIZE , 0 ) ;
92113 mq_setattr ( mqd, & new_attr_non_blocking) . unwrap ( ) ;
93114 let new_attr_get = mq_getattr ( mqd) . unwrap ( ) ;
94115
95116 // now the O_NONBLOCK flag has been set
96- assert_ne ! ( new_attr_get, initial_attr) ;
97- assert_eq ! ( new_attr_get, new_attr_non_blocking) ;
117+ #[ cfg( not( any( target_os = "dragonfly" , target_os = "netbsd" ) ) ) ]
118+ {
119+ assert_ne ! ( new_attr_get, initial_attr) ;
120+ }
121+ assert_attr_eq ! ( new_attr_get, new_attr_non_blocking) ;
98122 mq_close ( mqd) . unwrap ( ) ;
99123}
100124
101125// FIXME: Fix failures for mips in QEMU
102126#[ test]
103- #[ cfg( not( any( target_os = "netbsd" ) ) ) ]
104127#[ cfg_attr( all(
105128 qemu,
106129 any( target_arch = "mips" , target_arch = "mips64" )
@@ -121,20 +144,21 @@ fn test_mq_set_nonblocking() {
121144 let mqd = r. unwrap ( ) ;
122145 mq_set_nonblock ( mqd) . unwrap ( ) ;
123146 let new_attr = mq_getattr ( mqd) ;
124- assert_eq ! ( new_attr. unwrap( ) . flags( ) , MQ_OFlag :: O_NONBLOCK . bits( ) as mq_attr_member_t) ;
147+ let o_nonblock_bits = MQ_OFlag :: O_NONBLOCK . bits ( ) as mq_attr_member_t ;
148+ assert_eq ! ( new_attr. unwrap( ) . flags( ) & o_nonblock_bits, o_nonblock_bits) ;
125149 mq_remove_nonblock ( mqd) . unwrap ( ) ;
126150 let new_attr = mq_getattr ( mqd) ;
127- assert_eq ! ( new_attr. unwrap( ) . flags( ) , 0 ) ;
151+ assert_eq ! ( new_attr. unwrap( ) . flags( ) & o_nonblock_bits , 0 ) ;
128152 mq_close ( mqd) . unwrap ( ) ;
129153}
130154
131155#[ test]
132- #[ cfg( not( any( target_os = "netbsd" ) ) ) ]
133156fn test_mq_unlink ( ) {
134157 use nix:: mqueue:: mq_unlink;
135158 const MSG_SIZE : mq_attr_member_t = 32 ;
136159 let initial_attr = MqAttr :: new ( 0 , 10 , MSG_SIZE , 0 ) ;
137160 let mq_name_opened = & CString :: new ( b"/mq_unlink_test" . as_ref ( ) ) . unwrap ( ) ;
161+ #[ cfg( not( any( target_os = "dragonfly" , target_os = "netbsd" ) ) ) ]
138162 let mq_name_not_opened = & CString :: new ( b"/mq_unlink_test" . as_ref ( ) ) . unwrap ( ) ;
139163 let oflag = MQ_OFlag :: O_CREAT | MQ_OFlag :: O_WRONLY ;
140164 let mode = Mode :: S_IWUSR | Mode :: S_IRUSR | Mode :: S_IRGRP | Mode :: S_IROTH ;
@@ -148,8 +172,14 @@ fn test_mq_unlink() {
148172 let res_unlink = mq_unlink ( mq_name_opened) ;
149173 assert_eq ! ( res_unlink, Ok ( ( ) ) ) ;
150174
151- let res_unlink_not_opened = mq_unlink ( mq_name_not_opened) ;
152- assert_eq ! ( res_unlink_not_opened, Err ( Errno :: ENOENT ) ) ;
175+ // NetBSD (and others which inherit its implementation) defer removing the message
176+ // queue name until all references are closed, whereas Linux and others remove the
177+ // message queue name immediately.
178+ #[ cfg( not( any( target_os = "dragonfly" , target_os = "netbsd" ) ) ) ]
179+ {
180+ let res_unlink_not_opened = mq_unlink ( mq_name_not_opened) ;
181+ assert_eq ! ( res_unlink_not_opened, Err ( Errno :: ENOENT ) ) ;
182+ }
153183
154184 mq_close ( mqd) . unwrap ( ) ;
155185 let res_unlink_after_close = mq_unlink ( mq_name_opened) ;
0 commit comments