1
+ use cfg_if:: cfg_if;
1
2
use std:: ffi:: CString ;
2
3
use std:: str;
3
4
@@ -6,6 +7,25 @@ use nix::mqueue::{mq_open, mq_close, mq_send, mq_receive, mq_attr_member_t};
6
7
use nix:: mqueue:: { MqAttr , MQ_OFlag } ;
7
8
use nix:: sys:: stat:: Mode ;
8
9
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
+
9
29
#[ test]
10
30
fn test_mq_send_and_receive ( ) {
11
31
const MSG_SIZE : mq_attr_member_t = 32 ;
@@ -37,7 +57,6 @@ fn test_mq_send_and_receive() {
37
57
38
58
39
59
#[ test]
40
- #[ cfg( not( any( target_os = "netbsd" ) ) ) ]
41
60
fn test_mq_getattr ( ) {
42
61
use nix:: mqueue:: mq_getattr;
43
62
const MSG_SIZE : mq_attr_member_t = 32 ;
@@ -53,13 +72,12 @@ fn test_mq_getattr() {
53
72
let mqd = r. unwrap ( ) ;
54
73
55
74
let read_attr = mq_getattr ( mqd) . unwrap ( ) ;
56
- assert_eq ! ( read_attr, initial_attr) ;
75
+ assert_attr_eq ! ( read_attr, initial_attr) ;
57
76
mq_close ( mqd) . unwrap ( ) ;
58
77
}
59
78
60
79
// FIXME: Fix failures for mips in QEMU
61
80
#[ test]
62
- #[ cfg( not( any( target_os = "netbsd" ) ) ) ]
63
81
#[ cfg_attr( all(
64
82
qemu,
65
83
any( target_arch = "mips" , target_arch = "mips64" )
@@ -79,28 +97,33 @@ fn test_mq_setattr() {
79
97
} ;
80
98
let mqd = r. unwrap ( ) ;
81
99
82
- let new_attr = MqAttr :: new ( 0 , 20 , MSG_SIZE * 2 , 100 ) ;
100
+ let new_attr = MqAttr :: new ( 0 , 20 , MSG_SIZE * 2 , 100 ) ;
83
101
let old_attr = mq_setattr ( mqd, & new_attr) . unwrap ( ) ;
84
- assert_eq ! ( old_attr, initial_attr) ;
102
+ assert_attr_eq ! ( old_attr, initial_attr) ;
85
103
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
88
105
// 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
+ }
90
111
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 ) ;
92
113
mq_setattr ( mqd, & new_attr_non_blocking) . unwrap ( ) ;
93
114
let new_attr_get = mq_getattr ( mqd) . unwrap ( ) ;
94
115
95
116
// 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) ;
98
122
mq_close ( mqd) . unwrap ( ) ;
99
123
}
100
124
101
125
// FIXME: Fix failures for mips in QEMU
102
126
#[ test]
103
- #[ cfg( not( any( target_os = "netbsd" ) ) ) ]
104
127
#[ cfg_attr( all(
105
128
qemu,
106
129
any( target_arch = "mips" , target_arch = "mips64" )
@@ -121,20 +144,21 @@ fn test_mq_set_nonblocking() {
121
144
let mqd = r. unwrap ( ) ;
122
145
mq_set_nonblock ( mqd) . unwrap ( ) ;
123
146
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) ;
125
149
mq_remove_nonblock ( mqd) . unwrap ( ) ;
126
150
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 ) ;
128
152
mq_close ( mqd) . unwrap ( ) ;
129
153
}
130
154
131
155
#[ test]
132
- #[ cfg( not( any( target_os = "netbsd" ) ) ) ]
133
156
fn test_mq_unlink ( ) {
134
157
use nix:: mqueue:: mq_unlink;
135
158
const MSG_SIZE : mq_attr_member_t = 32 ;
136
159
let initial_attr = MqAttr :: new ( 0 , 10 , MSG_SIZE , 0 ) ;
137
160
let mq_name_opened = & CString :: new ( b"/mq_unlink_test" . as_ref ( ) ) . unwrap ( ) ;
161
+ #[ cfg( not( any( target_os = "dragonfly" , target_os = "netbsd" ) ) ) ]
138
162
let mq_name_not_opened = & CString :: new ( b"/mq_unlink_test" . as_ref ( ) ) . unwrap ( ) ;
139
163
let oflag = MQ_OFlag :: O_CREAT | MQ_OFlag :: O_WRONLY ;
140
164
let mode = Mode :: S_IWUSR | Mode :: S_IRUSR | Mode :: S_IRGRP | Mode :: S_IROTH ;
@@ -148,8 +172,14 @@ fn test_mq_unlink() {
148
172
let res_unlink = mq_unlink ( mq_name_opened) ;
149
173
assert_eq ! ( res_unlink, Ok ( ( ) ) ) ;
150
174
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
+ }
153
183
154
184
mq_close ( mqd) . unwrap ( ) ;
155
185
let res_unlink_after_close = mq_unlink ( mq_name_opened) ;
0 commit comments