1
1
use super :: FORK_MTX ;
2
+ use nix:: errno:: Errno ;
2
3
use nix:: spawn:: { self , PosixSpawnAttr , PosixSpawnFileActions } ;
3
4
use nix:: sys:: signal;
4
5
use nix:: sys:: wait:: { waitpid, WaitPidFlag , WaitStatus } ;
5
- use std:: ffi:: CString ;
6
+ use std:: ffi:: { CStr , CString } ;
7
+
8
+ /// Helper function to find a binary in the $PATH
9
+ fn which ( exe_name : & str ) -> Option < std:: path:: PathBuf > {
10
+ std:: env:: var_os ( "PATH" ) . and_then ( |paths| {
11
+ std:: env:: split_paths ( & paths)
12
+ . filter_map ( |dir| {
13
+ let full_path = dir. join ( exe_name) ;
14
+ if full_path. is_file ( ) {
15
+ Some ( full_path)
16
+ } else {
17
+ None
18
+ }
19
+ } )
20
+ . next ( )
21
+ } )
22
+ }
6
23
7
24
#[ test]
8
25
fn spawn_true ( ) {
9
26
let _guard = FORK_MTX . lock ( ) ;
10
27
28
+ let bin = which ( "true" ) . unwrap ( ) ;
29
+ let args = & [
30
+ CString :: new ( "true" ) . unwrap ( ) ,
31
+ CString :: new ( "story" ) . unwrap ( ) ,
32
+ ] ;
33
+ let vars: & [ CString ] = & [ ] ;
34
+ let actions = PosixSpawnFileActions :: init ( ) . unwrap ( ) ;
35
+ let attr = PosixSpawnAttr :: init ( ) . unwrap ( ) ;
36
+
37
+ let pid =
38
+ spawn:: posix_spawn ( bin. as_path ( ) , & actions, & attr, args, vars) . unwrap ( ) ;
39
+
40
+ let status = waitpid ( pid, Some ( WaitPidFlag :: empty ( ) ) ) . unwrap ( ) ;
41
+
42
+ match status {
43
+ WaitStatus :: Exited ( wpid, ret) => {
44
+ assert_eq ! ( pid, wpid) ;
45
+ assert_eq ! ( ret, 0 ) ;
46
+ }
47
+ _ => {
48
+ panic ! ( "Invalid WaitStatus" ) ;
49
+ }
50
+ } ;
51
+ }
52
+
53
+ #[ test]
54
+ fn spawn_sleep ( ) {
55
+ let _guard = FORK_MTX . lock ( ) ;
56
+
57
+ let bin = which ( "sleep" ) . unwrap ( ) ;
58
+ let args = & [ CString :: new ( "sleep" ) . unwrap ( ) , CString :: new ( "30" ) . unwrap ( ) ] ;
59
+ let vars: & [ CString ] = & [ ] ;
60
+ let actions = PosixSpawnFileActions :: init ( ) . unwrap ( ) ;
61
+ let attr = PosixSpawnAttr :: init ( ) . unwrap ( ) ;
62
+
63
+ let pid =
64
+ spawn:: posix_spawn ( bin. as_path ( ) , & actions, & attr, args, vars) . unwrap ( ) ;
65
+
66
+ let status =
67
+ waitpid ( pid, WaitPidFlag :: from_bits ( WaitPidFlag :: WNOHANG . bits ( ) ) )
68
+ . unwrap ( ) ;
69
+ match status {
70
+ WaitStatus :: StillAlive => { }
71
+ _ => {
72
+ panic ! ( "Invalid WaitStatus" ) ;
73
+ }
74
+ } ;
75
+
76
+ signal:: kill ( pid, signal:: SIGTERM ) . unwrap ( ) ;
77
+
78
+ let status = waitpid ( pid, Some ( WaitPidFlag :: empty ( ) ) ) . unwrap ( ) ;
79
+ match status {
80
+ WaitStatus :: Signaled ( wpid, wsignal, _) => {
81
+ assert_eq ! ( pid, wpid) ;
82
+ assert_eq ! ( wsignal, signal:: SIGTERM ) ;
83
+ }
84
+ _ => {
85
+ panic ! ( "Invalid WaitStatus" ) ;
86
+ }
87
+ } ;
88
+ }
89
+
90
+ #[ test]
91
+ // `posix_spawn(path_not_exist)` succeeds under QEMU, so ignore the test. No need
92
+ // to investigate the root cause, this test still works in native environments, which
93
+ // is sufficient to test the binding.
94
+ #[ cfg_attr( qemu, ignore) ]
95
+ fn spawn_cmd_does_not_exist ( ) {
96
+ let _guard = FORK_MTX . lock ( ) ;
97
+
98
+ let args = & [ CString :: new ( "buzz" ) . unwrap ( ) ] ;
99
+ let envs: & [ CString ] = & [ ] ;
100
+ let actions = PosixSpawnFileActions :: init ( ) . unwrap ( ) ;
101
+ let attr = PosixSpawnAttr :: init ( ) . unwrap ( ) ;
102
+
103
+ let bin = "2b7433c4-523b-470c-abb5-d7ee9fd295d5-fdasf" ;
104
+ let errno =
105
+ spawn:: posix_spawn ( bin, & actions, & attr, args, envs) . unwrap_err ( ) ;
106
+ assert_eq ! ( errno, Errno :: ENOENT ) ;
107
+ }
108
+
109
+ #[ test]
110
+ fn spawnp_true ( ) {
111
+ let _guard = FORK_MTX . lock ( ) ;
112
+
11
113
let bin = & CString :: new ( "true" ) . unwrap ( ) ;
12
114
let args = & [
13
115
CString :: new ( "true" ) . unwrap ( ) ,
@@ -33,7 +135,7 @@ fn spawn_true() {
33
135
}
34
136
35
137
#[ test]
36
- fn spawn_sleep ( ) {
138
+ fn spawnp_sleep ( ) {
37
139
let _guard = FORK_MTX . lock ( ) ;
38
140
39
141
let bin = & CString :: new ( "sleep" ) . unwrap ( ) ;
@@ -67,3 +169,25 @@ fn spawn_sleep() {
67
169
}
68
170
} ;
69
171
}
172
+
173
+ #[ test]
174
+ // `posix_spawnp(bin_not_exist)` succeeds under QEMU, so ignore the test. No need
175
+ // to investigate the root cause, this test still works in native environments, which
176
+ // is sufficient to test the binding.
177
+ #[ cfg_attr( qemu, ignore) ]
178
+ fn spawnp_cmd_does_not_exist ( ) {
179
+ let _guard = FORK_MTX . lock ( ) ;
180
+
181
+ let args = & [ CString :: new ( "buzz" ) . unwrap ( ) ] ;
182
+ let envs: & [ CString ] = & [ ] ;
183
+ let actions = PosixSpawnFileActions :: init ( ) . unwrap ( ) ;
184
+ let attr = PosixSpawnAttr :: init ( ) . unwrap ( ) ;
185
+
186
+ let bin = CStr :: from_bytes_with_nul (
187
+ "2b7433c4-523b-470c-abb5-d7ee9fd295d5-fdasf\0 " . as_bytes ( ) ,
188
+ )
189
+ . unwrap ( ) ;
190
+ let errno =
191
+ spawn:: posix_spawnp ( bin, & actions, & attr, args, envs) . unwrap_err ( ) ;
192
+ assert_eq ! ( errno, Errno :: ENOENT ) ;
193
+ }
0 commit comments