blob: c78a0fa7419143aa23cd13cdbceee82d50ffec3a [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
use anyhow::{anyhow, Result};
use regex::Regex;
use serde::de::DeserializeOwned;
use serde::Serialize;
use std::io::Write;
use std::time::Duration;
use crate::io::uart::{Uart, UartError};
use crate::test_utils::status::Status;
use crate::uart::console::{ExitStatus, UartConsole};
pub trait UartSend {
fn send(&self, uart: &dyn Uart) -> Result<()>;
}
impl<T: Serialize> UartSend for T {
fn send(&self, uart: &dyn Uart) -> Result<()> {
let s = serde_json::to_string(self)?;
log::info!("Sending: {}", s);
uart.write(s.as_bytes())?;
Ok(())
}
}
pub trait UartRecv {
fn recv(uart: &dyn Uart, timeout: Duration, quiet: bool) -> Result<Self>
where
Self: Sized;
}
impl<T: DeserializeOwned> UartRecv for T {
fn recv(uart: &dyn Uart, timeout: Duration, quiet: bool) -> Result<Self>
where
Self: Sized,
{
let mut console = UartConsole {
timeout: Some(timeout),
exit_success: Some(Regex::new(r"RESP_OK:(.*)\r")?),
exit_failure: Some(Regex::new(r"RESP_ERR:(.*)\r")?),
..Default::default()
};
let mut stdout = std::io::stdout();
let out = if !quiet {
let w: &mut dyn Write = &mut stdout;
Some(w)
} else {
None
};
let result = console.interact(uart, None, out)?;
match result {
ExitStatus::ExitSuccess => {
let cap = console
.captures(ExitStatus::ExitSuccess)
.expect("RESP_OK capture");
let s = cap.get(1).expect("RESP_OK group").as_str();
Ok(serde_json::from_str::<Self>(s)?)
}
ExitStatus::ExitFailure => {
let cap = console
.captures(ExitStatus::ExitFailure)
.expect("RESP_ERR capture");
let s = cap.get(1).expect("RESP_ERR group").as_str();
let err = serde_json::from_str::<Status>(s)?;
Err(err.into())
}
ExitStatus::Timeout => Err(UartError::GenericError("Timed Out".into()).into()),
_ => Err(anyhow!("Impossible result: {:?}", result)),
}
}
}