1 // Copyright (c) 2023 Huawei Device Co., Ltd.
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 // http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13
14 #![cfg(all(target_os = "linux", feature = "process"))]
15
16 use std::os::fd::{AsFd, AsRawFd};
17 use std::process::Stdio;
18
19 use ylong_runtime::io::{AsyncReadExt, AsyncWriteExt};
20 use ylong_runtime::process::{ChildStderr, ChildStdin, ChildStdout, Command};
21
22 /// SDV test cases for `output()`.
23 ///
24 /// # Brief
25 /// 1. Create a `Command` with arg.
26 /// 2. Use `output()` waiting result.
27 #[test]
sdv_process_output_test()28 fn sdv_process_output_test() {
29 let handle = ylong_runtime::spawn(async {
30 let mut command = Command::new("echo");
31 command.arg("Hello, world!");
32 let output = command.output().await.unwrap();
33
34 assert!(output.status.success());
35 assert_eq!(output.stdout.as_slice(), b"Hello, world!\n");
36 assert!(output.stderr.is_empty());
37 });
38 ylong_runtime::block_on(handle).unwrap();
39 }
40
41 /// SDV test cases for `status()`.
42 ///
43 /// # Brief
44 /// 1. Create a `Command` with arg.
45 /// 2. Use `status()` waiting result.
46 #[test]
sdv_process_status_test()47 fn sdv_process_status_test() {
48 let handle = ylong_runtime::spawn(async {
49 let mut command = Command::new("echo");
50 command.arg("Hello, world!");
51
52 let status = command.status().await.unwrap();
53 assert!(status.success());
54 });
55 ylong_runtime::block_on(handle).unwrap();
56 }
57
58 /// SDV test cases for `spawn()`.
59 ///
60 /// # Brief
61 /// 1. Create a `Command` with arg.
62 /// 2. Use `spawn()` create a child handle
63 /// 3. Use `wait()` waiting result.
64 #[test]
sdv_process_spawn_test()65 fn sdv_process_spawn_test() {
66 let handle = ylong_runtime::spawn(async {
67 let mut command = Command::new("echo");
68 command.arg("Hello, world!");
69 let mut child = command.spawn().unwrap();
70 assert!(child.id().is_some());
71
72 let status = child.wait().await.unwrap();
73 assert!(status.success());
74 assert!(child.start_kill().is_err());
75 assert!(child.id().is_none());
76
77 let status = child.wait().await.unwrap();
78 assert!(status.success());
79 });
80 ylong_runtime::block_on(handle).unwrap();
81 }
82
83 /// SDV test cases for ChildStdio.
84 ///
85 /// # Brief
86 /// 1. Create a `Command` and `spawn()`.
87 /// 2. Take `child.stdin` and write something in it.
88 /// 3. Take `child.stdout` and read it, check the result.
89 /// 4. Check child's result.
90 #[test]
sdv_process_child_stdio_test()91 fn sdv_process_child_stdio_test() {
92 let handle = ylong_runtime::spawn(async {
93 let mut child = Command::new("rev")
94 .stdin(Stdio::piped())
95 .stdout(Stdio::piped())
96 .stderr(Stdio::piped())
97 .spawn()
98 .expect("Failed to spawn child process");
99
100 let mut stdin = child.take_stdin().expect("Failed to open stdin");
101 let stdin_handle = ylong_runtime::spawn(async move {
102 stdin.write_all(b"Hello, world!").await.unwrap();
103 stdin.flush().await.unwrap();
104 stdin.shutdown().await.unwrap();
105 });
106
107 let mut stdout = child.take_stdout().expect("Failed to open stdout");
108 let stdout_handle = ylong_runtime::spawn(async move {
109 let mut buf = Vec::new();
110 stdout.read_to_end(&mut buf).await.unwrap();
111 let str = "!dlrow ,olleH";
112 assert!(String::from_utf8(buf).unwrap().contains(str));
113 });
114
115 let mut stderr = child.take_stderr().expect("Failed to open stderr");
116 let stderr_handle = ylong_runtime::spawn(async move {
117 let mut buf = Vec::new();
118 stderr.read_to_end(&mut buf).await.unwrap();
119 assert!(buf.is_empty());
120 });
121
122 let status = child.wait().await.unwrap();
123 assert!(status.success());
124
125 stdin_handle.await.unwrap();
126 stdout_handle.await.unwrap();
127 stderr_handle.await.unwrap();
128 });
129 ylong_runtime::block_on(handle).unwrap();
130 }
131
132 /// SDV test cases for `kill()`.
133 ///
134 /// # Brief
135 /// 1. Create a `Command` with arg.
136 /// 2. Use `spawn()` create a child handle
137 /// 3. Use `kill()` to kill the child handle.
138 #[test]
sdv_process_kill_test()139 fn sdv_process_kill_test() {
140 let handle = ylong_runtime::spawn(async {
141 let mut command = Command::new("echo");
142 command.arg("Hello, world!");
143 let mut child = command.spawn().unwrap();
144
145 assert!(child.kill().await.is_ok());
146 });
147 ylong_runtime::block_on(handle).unwrap();
148 }
149
150 /// SDV test cases for `try_wait()`.
151 ///
152 /// # Brief
153 /// 1. Create a `Command` with arg.
154 /// 2. Use `spawn()` create a child handle
155 /// 3. Use `try_wait()` waiting result until the child handle is ok.
156 #[test]
sdv_process_try_wait_test()157 fn sdv_process_try_wait_test() {
158 let handle = ylong_runtime::spawn(async {
159 let mut command = Command::new("echo");
160 command.arg("Hello, world!");
161 let mut child = command.spawn().unwrap();
162
163 loop {
164 if child.try_wait().unwrap().is_some() {
165 break;
166 }
167 }
168 assert!(child.try_wait().unwrap().is_some());
169 });
170 ylong_runtime::block_on(handle).unwrap();
171 }
172
173 /// SDV test cases for drop.
174 ///
175 /// # Brief
176 /// 1. Create a `Command` with kill_on_drop.
177 /// 2. Use `spawn()` create a child handle
178 /// 3. Use `drop()` to drop the child handle.
179 #[test]
sdv_process_drop_test()180 fn sdv_process_drop_test() {
181 let handle = ylong_runtime::spawn(async {
182 let mut command = Command::new("echo");
183 command.arg("Hello, world!").kill_on_drop(true);
184 let child = command.spawn();
185 assert!(child.is_ok());
186 drop(child.unwrap());
187
188 let mut command = Command::new("echo");
189 command.arg("Hello, world!");
190 let child = command.spawn();
191 assert!(child.is_ok());
192 drop(child.unwrap());
193 });
194 ylong_runtime::block_on(handle).unwrap();
195 }
196
197 /// SDV test cases for stdio.
198 ///
199 /// # Brief
200 /// 1. Create a `Command` with arg.
201 /// 2. Use `spawn()` create a child handle
202 /// 3. Use `wait()` waiting result.
203 #[test]
sdv_process_stdio_test()204 fn sdv_process_stdio_test() {
205 let handle = ylong_runtime::spawn(async {
206 let mut command = Command::new("echo");
207 command
208 .arg("Hello, world!")
209 .stdin(Stdio::piped())
210 .stdout(Stdio::piped())
211 .stderr(Stdio::piped());
212 let mut child = command.spawn().unwrap();
213
214 let child_stdin = child.take_stdin().unwrap();
215 assert!(child_stdin.into_owned_fd().is_ok());
216 let child_stdout = child.take_stdout().unwrap();
217 assert!(child_stdout.into_owned_fd().is_ok());
218 let child_stderr = child.take_stderr().unwrap();
219 assert!(child_stderr.into_owned_fd().is_ok());
220
221 drop(child);
222
223 let mut child = command.spawn().unwrap();
224
225 let child_stdin = child.take_stdin().unwrap();
226 assert!(child_stdin.as_fd().as_raw_fd() >= 0);
227 assert!(child_stdin.as_raw_fd() >= 0);
228 assert!(TryInto::<Stdio>::try_into(child_stdin).is_ok());
229
230 let child_stdout = child.take_stdout().unwrap();
231 assert!(child_stdout.as_fd().as_raw_fd() >= 0);
232 assert!(child_stdout.as_raw_fd() >= 0);
233 assert!(TryInto::<Stdio>::try_into(child_stdout).is_ok());
234
235 let child_stderr = child.take_stderr().unwrap();
236 assert!(child_stderr.as_fd().as_raw_fd() >= 0);
237 assert!(child_stderr.as_raw_fd() >= 0);
238 assert!(TryInto::<Stdio>::try_into(child_stderr).is_ok());
239 drop(child);
240 });
241 ylong_runtime::block_on(handle).unwrap();
242 }
243
244 /// SDV test cases for ChildStd.
245 ///
246 /// # Brief
247 /// 1. Create a `std::process::Command`.
248 /// 2. Use `spawn()` create a child handle
249 /// 3. Use `from_std()` to convert std to ylong_runtime::process::ChildStd.
250 #[test]
sdv_process_child_stdio_convert_test()251 fn sdv_process_child_stdio_convert_test() {
252 let handle = ylong_runtime::spawn(async {
253 let mut command = std::process::Command::new("echo");
254 command
255 .stdin(Stdio::piped())
256 .stdout(Stdio::piped())
257 .stderr(Stdio::piped());
258 let mut child = command.spawn().unwrap();
259 let stdin = child.stdin.take().unwrap();
260 assert!(ChildStdin::from_std(stdin).is_ok());
261 let stdout = child.stdout.take().unwrap();
262 assert!(ChildStdout::from_std(stdout).is_ok());
263 let stderr = child.stderr.take().unwrap();
264 assert!(ChildStderr::from_std(stderr).is_ok());
265 });
266 ylong_runtime::block_on(handle).unwrap();
267 }
268
269 /// SDV test cases for command debug.
270 ///
271 /// # Brief
272 /// 1. Debug Command and Child.
273 /// 2. Check format is correct.
274 #[test]
sdv_process_debug_test()275 fn sdv_process_debug_test() {
276 let handle = ylong_runtime::spawn(async {
277 let mut command = Command::new("echo");
278 assert_eq!(
279 format!("{command:?}"),
280 "Command { std: \"echo\", kill: false }"
281 );
282 let mut child = command.spawn().unwrap();
283
284 assert_eq!(format!("{child:?}"), "Child { state: Pending(Some(Child { stdin: None, stdout: None, stderr: None, .. })), kill_on_drop: false, stdin: None, stdout: None, stderr: None }");
285 let status = child.wait().await.unwrap();
286 assert!(status.success());
287 });
288 ylong_runtime::block_on(handle).unwrap();
289 }
290