| // Copyright 2026 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| use driver_debug_lib::{execute_command, list_commands}; |
| use fdf_component::testing::harness::TestHarness; |
| use fidl_fuchsia_driver_debug as fdebug; |
| |
| mod test_driver; |
| use test_driver::TestDriver; |
| |
| struct ExecutionResult { |
| stdout: String, |
| stderr: String, |
| exit_code: i32, |
| } |
| |
| async fn run_command(proxy: &fdebug::DebugProxy, args: &[&str]) -> ExecutionResult { |
| let (local_stdout, remote_stdout) = zx::Socket::create_stream(); |
| let (local_stderr, remote_stderr) = zx::Socket::create_stream(); |
| |
| let mut async_stdout = fuchsia_async::Socket::from_socket(local_stdout); |
| let mut async_stderr = fuchsia_async::Socket::from_socket(local_stderr); |
| |
| let mut stdout_bytes = Vec::new(); |
| let mut stderr_bytes = Vec::new(); |
| |
| use futures::io::AsyncReadExt; |
| let stdout_reader = async { |
| async_stdout.read_to_end(&mut stdout_bytes).await.unwrap(); |
| }; |
| let stderr_reader = async { |
| async_stderr.read_to_end(&mut stderr_bytes).await.unwrap(); |
| }; |
| |
| let args_strings: Vec<String> = args.iter().map(|s| s.to_string()).collect(); |
| let execute_fut = async { |
| execute_command(proxy, &args_strings, remote_stdout, remote_stderr) |
| .await |
| .expect("execute command") |
| }; |
| |
| let (_, _, exit_code) = futures::join!(stdout_reader, stderr_reader, execute_fut); |
| ExecutionResult { |
| stdout: String::from_utf8_lossy(&stdout_bytes).into_owned(), |
| stderr: String::from_utf8_lossy(&stderr_bytes).into_owned(), |
| exit_code, |
| } |
| } |
| |
| #[fuchsia::test] |
| async fn test_rust_driver_debug_e2e() { |
| let mut harness = TestHarness::<TestDriver>::new(); |
| let dut = harness.start_driver().await.expect("driver start"); |
| let proxy: fdebug::DebugProxy = |
| dut.driver_outgoing().connect_protocol::<fdebug::DebugProxy>().expect("connect"); |
| |
| // 1. debug list-commands |
| let table = list_commands(&proxy).await.expect("list commands"); |
| assert!(table.contains("COMMAND")); |
| assert!(table.contains("DESCRIPTION")); |
| assert!(table.contains("ping")); |
| assert!(table.contains("Ping the driver")); |
| assert!(table.contains("reset")); |
| assert!(table.contains("Reset the driver state")); |
| assert!(table.contains("fault")); |
| assert!(table.contains("Induce driver fault")); |
| |
| // 2. debug ping -c 3 |
| let res = run_command(&proxy, &["ping", "-c", "3"]).await; |
| assert_eq!(res.exit_code, 0); |
| assert_eq!(res.stdout, "ping 1\nping 2\nping 3\n"); |
| assert_eq!(res.stderr, ""); |
| |
| // 3. debug reset --hard |
| let res = run_command(&proxy, &["reset", "--hard"]).await; |
| assert_eq!(res.exit_code, 0); |
| assert_eq!(res.stdout, "hard reset\n"); |
| assert_eq!(res.stderr, ""); |
| |
| // 4. debug --help |
| let res = run_command(&proxy, &["--help"]).await; |
| assert_eq!(res.exit_code, 0); |
| assert!(res.stdout.contains("Usage:")); |
| assert_eq!(res.stderr, ""); |
| |
| // 5. syntax error (exit 2) |
| let res = run_command(&proxy, &["ping", "--unknown-flag"]).await; |
| assert_eq!(res.exit_code, 2); |
| assert_eq!(res.stdout, ""); |
| assert!(!res.stderr.is_empty()); |
| |
| // 6. driver fault (exit 1) |
| let res = run_command(&proxy, &["fault"]).await; |
| assert_eq!(res.exit_code, 1); |
| assert_eq!(res.stdout, ""); |
| assert!(res.stderr.contains("driver internal fault")); |
| |
| dut.stop_driver().await; |
| } |