From 3442ca99bafbf5f6ea67ce2de46608a70a2009a5 Mon Sep 17 00:00:00 2001 From: Lizzy Fleckenstein Date: Sun, 12 Feb 2023 19:40:19 +0100 Subject: Test against go mt package --- tests/random.rs | 147 +++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 109 insertions(+), 38 deletions(-) (limited to 'tests/random.rs') diff --git a/tests/random.rs b/tests/random.rs index a9d1609..d92ce79 100644 --- a/tests/random.rs +++ b/tests/random.rs @@ -2,54 +2,125 @@ use libtest_mimic::{Arguments, Trial}; use mt_net::{generate_random::GenerateRandomVariant, rand, ToCltPkt, ToSrvPkt}; use mt_ser::{DefCfg, MtDeserialize, MtSerialize}; -use std::{error::Error, fmt::Debug}; +use std::{ + error::Error, + fmt::Debug, + io::{Cursor, Write}, + path::Path, + process::{Command, Stdio}, +}; -fn test_reserialize(type_name: &'static str) -> impl Iterator +fn test_reserialize<'a, T>(type_name: &'static str, reserialize: &Path) -> Vec where T: MtSerialize + MtDeserialize + GenerateRandomVariant + PartialEq + Debug, { - (0..T::num_variants()).map(move |i| { - Trial::test(format!("{type_name}::{}", T::variant_name(i)), move || { - let mut rng = rand::thread_rng(); - - for _ in 0..100 { - let input = T::generate_random_variant(&mut rng, i); - - let mut writer = Vec::new(); - input - .mt_serialize::(&mut writer) - .map_err(|e| format!("serialize error: {e}\ninput: {input:?}"))?; - - let mut reader = std::io::Cursor::new(writer); - let output = T::mt_deserialize::(&mut reader).map_err(|e| { - format!( - "deserialize error: {e}\ninput: {input:?}\npayload: {:?}", - reader.get_ref() - ) - })?; - - if input != output { - return Err(format!( - "output did not match input\n\ - input: {input:?}\n\ - payload: {:?}\n\ - output: {output:?}", - reader.get_ref(), - ) - .into()); + (0..T::num_variants()) + .map(move |i| { + let pkt_name = format!("{type_name}::{}", T::variant_name(i)); + let reserialize = reserialize.as_os_str().to_os_string(); + + Trial::test(pkt_name.clone(), move || { + let mut rng = rand::thread_rng(); + let mut printed_stderr = false; + + for _ in 0..100 { + // use buffered IO instead of directly reading from the process + // this enables printing out payloads for debugging + + let input = T::generate_random_variant(&mut rng, i); + + let mut writer = Vec::new(); + input + .mt_serialize::(&mut writer) + .map_err(|e| format!("serialize error: {e}\ninput: {input:?}"))?; + + let mut child = Command::new(&reserialize) + .arg(type_name) + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .spawn() + .expect("failed to spawn reserialize"); + + let mut stdin = child.stdin.take().expect("failed to open stdin"); + let payload = writer.clone(); + std::thread::spawn(move || { + stdin.write_all(&payload).expect("failed to write to stdin"); + }); + + let command_out = child.wait_with_output().expect("failed to read stdout"); + + let stderr = String::from_utf8_lossy(&command_out.stderr); + if command_out.status.success() { + if stderr.len() > 0 && !printed_stderr { + printed_stderr = true; + eprintln!("stderr for {pkt_name}: {stderr}"); + } + } else { + return Err(format!( + "reserialize returned failure\n\ + input: {input:?}\n\ + input payload: {writer:?}\n\ + stderr: {stderr}" + ) + .into()); + } + + let mut reader = Cursor::new(command_out.stdout); + let output = T::mt_deserialize::(&mut reader).map_err(|e| { + format!( + "deserialize error: {e}\n\ + input: {input:?}\n\ + input payload: {writer:?}\n\ + output payload: {:?}\n\ + stderr: {stderr}", + reader.get_ref() + ) + })?; + + if input != output { + return Err(format!( + "output does not match input\n\ + input: {input:?}\n\ + output: {output:?}\n\ + input payload: {writer:?}\n\ + output payload: {:?}\n\ + stderr: {stderr}", + reader.get_ref(), + ) + .into()); + } } - } - Ok(()) + Ok(()) + }) + .with_kind("random") }) - .with_kind("random") - }) + .collect() } fn main() -> Result<(), Box> { + let reserialize = Path::new(file!()).with_file_name("reserialize/reserialize"); + + if !reserialize.exists() { + if !Command::new("go") + .arg("build") + .current_dir(reserialize.parent().unwrap()) + .spawn() + .expect("go is required for random tests") + .wait() + .expect("go build didn't run") + .success() + { + panic!("go build failed"); + } + } + let args = Arguments::from_args(); - let tests = test_reserialize::("ToSrvPkt") - .chain(test_reserialize::("ToCltPkt")) - .collect(); + + let mut tests = Vec::new(); + tests.extend(test_reserialize::("ToSrvPkt", &reserialize)); + tests.extend(test_reserialize::("ToCltPkt", &reserialize)); + libtest_mimic::run(&args, tests).exit(); } -- cgit v1.2.3