use std::sync::{Arc, Mutex};
use flowcore::errors::Result;
use flowcore::{Implementation, RunAgain, RUN_AGAIN};
use serde_json::Value;
use crate::gui::client_message::ClientMessage;
use crate::gui::coordinator_connection::CoordinatorConnection;
use crate::gui::coordinator_message::CoordinatorMessage;
pub struct Stdout {
pub server_connection: Arc<Mutex<CoordinatorConnection>>,
}
impl Implementation for Stdout {
fn run(&self, inputs: &[Value]) -> Result<(Option<Value>, RunAgain)> {
let input = inputs.first().ok_or("Could not get input")?;
let mut server = self
.server_connection
.lock()
.map_err(|_| "Could not lock server")?;
let _: Result<ClientMessage> = match input {
Value::Null => server.send_and_receive_response(CoordinatorMessage::StdoutEof),
Value::String(string) => {
server.send_and_receive_response(CoordinatorMessage::Stdout(string.clone()))
}
Value::Bool(boolean) => {
server.send_and_receive_response(CoordinatorMessage::Stdout(boolean.to_string()))
}
Value::Number(number) => {
server.send_and_receive_response(CoordinatorMessage::Stdout(number.to_string()))
}
Value::Array(_array) => {
server.send_and_receive_response(CoordinatorMessage::Stdout(input.to_string()))
}
Value::Object(_obj) => {
server.send_and_receive_response(CoordinatorMessage::Stdout(input.to_string()))
}
};
Ok((None, RUN_AGAIN))
}
}
#[cfg(test)]
#[allow(clippy::unwrap_used, clippy::expect_used)]
mod test {
use std::collections::HashMap;
use flowcore::{Implementation, RUN_AGAIN};
use serde_json::{json, Value};
use serial_test::serial;
use crate::gui::client_message::ClientMessage;
use crate::gui::coordinator_message::CoordinatorMessage;
use crate::gui::test_helper::test::wait_for_then_send;
use super::Stdout;
#[test]
#[serial]
fn send_null() {
let server_connection =
wait_for_then_send(CoordinatorMessage::StdoutEof, ClientMessage::Ack);
let stderr = &Stdout { server_connection } as &dyn Implementation;
let (value, run_again) = stderr.run(&[Value::Null]).expect("run() failed");
assert_eq!(run_again, RUN_AGAIN);
assert_eq!(value, None);
}
#[test]
#[serial]
fn send_string() {
let string = "string of text";
let value = json!(string);
let server_connection = wait_for_then_send(
CoordinatorMessage::Stdout(string.into()),
ClientMessage::Ack,
);
let stderr = &Stdout { server_connection } as &dyn Implementation;
let (value, run_again) = stderr.run(&[value]).expect("run() failed");
assert_eq!(run_again, RUN_AGAIN);
assert_eq!(value, None);
}
#[test]
#[serial]
fn send_bool() {
let bool = true;
let value = json!(bool);
let server_connection = wait_for_then_send(
CoordinatorMessage::Stdout("true".into()),
ClientMessage::Ack,
);
let stderr = &Stdout { server_connection } as &dyn Implementation;
let (value, run_again) = stderr.run(&[value]).expect("run() failed");
assert_eq!(run_again, RUN_AGAIN);
assert_eq!(value, None);
}
#[test]
#[serial]
fn send_number() {
let number = 42;
let value = json!(number);
let server_connection =
wait_for_then_send(CoordinatorMessage::Stdout("42".into()), ClientMessage::Ack);
let stderr = &Stdout { server_connection } as &dyn Implementation;
let (value, run_again) = stderr.run(&[value]).expect("run() failed");
assert_eq!(run_again, RUN_AGAIN);
assert_eq!(value, None);
}
#[test]
#[serial]
fn send_array() {
let array = [1, 2, 3];
let value = json!(array);
let server_connection = wait_for_then_send(
CoordinatorMessage::Stdout("[1,2,3]".into()),
ClientMessage::Ack,
);
let stderr = &Stdout { server_connection } as &dyn Implementation;
let (value, run_again) = stderr.run(&[value]).expect("run() failed");
assert_eq!(run_again, RUN_AGAIN);
assert_eq!(value, None);
}
#[test]
#[serial]
fn send_object() {
let mut map = HashMap::new();
map.insert("number1", 42);
map.insert("number2", 99);
let value = json!(map);
let server_connection = wait_for_then_send(
CoordinatorMessage::Stdout("{\"number1\":42,\"number2\":99}".into()),
ClientMessage::Ack,
);
let stderr = &Stdout { server_connection } as &dyn Implementation;
let (value, run_again) = stderr.run(&[value]).expect("run() failed");
assert_eq!(run_again, RUN_AGAIN);
assert_eq!(value, None);
}
}