From 3442ca99bafbf5f6ea67ce2de46608a70a2009a5 Mon Sep 17 00:00:00 2001 From: Lizzy Fleckenstein Date: Sun, 12 Feb 2023 19:40:19 +0100 Subject: [PATCH] Test against go mt package --- tests/random.rs | 147 ++++++++++++++++++++++++++++---------- tests/reserialize/go.mod | 4 +- tests/reserialize/go.sum | 4 ++ tests/reserialize/main.go | 10 +-- 4 files changed, 120 insertions(+), 45 deletions(-) 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(); } diff --git a/tests/reserialize/go.mod b/tests/reserialize/go.mod index 414ffb6..34d806e 100644 --- a/tests/reserialize/go.mod +++ b/tests/reserialize/go.mod @@ -2,9 +2,7 @@ module github.com/minetest-rust/mt_net/tests/reserialize go 1.20 -replace github.com/dragonfireclient/mt => /home/fleckenstein/src/mt - require ( - github.com/dragonfireclient/mt v0.0.1 // indirect + github.com/dragonfireclient/mt v0.0.2-0.20230212182515-e1bfd543b068 // indirect github.com/klauspost/compress v1.15.15 // indirect ) diff --git a/tests/reserialize/go.sum b/tests/reserialize/go.sum index c92cbb7..2688586 100644 --- a/tests/reserialize/go.sum +++ b/tests/reserialize/go.sum @@ -1,5 +1,9 @@ +github.com/dragonfireclient/mt v0.0.1 h1:iX6pW8L20orCrAYQTa+ADdm6OdNvIyP7Mev6VadQ1z8= +github.com/dragonfireclient/mt v0.0.1/go.mod h1:3oHbcSQytW21mTF7ozw3Il3UzdOAG30gPzO2XUAqvGs= github.com/dragonfireclient/mt v0.0.2-0.20220709120709-173ad6e339cf h1:0CY1XyRPpNTgPQJjgsqvBzBgXdf6NN6deKw81G0qeHQ= github.com/dragonfireclient/mt v0.0.2-0.20220709120709-173ad6e339cf/go.mod h1:3oHbcSQytW21mTF7ozw3Il3UzdOAG30gPzO2XUAqvGs= +github.com/dragonfireclient/mt v0.0.2-0.20230212182515-e1bfd543b068 h1:iseIXyVyA45MomwUdnWXoKm6V+Pp6ZLhXPKdlOQksAg= +github.com/dragonfireclient/mt v0.0.2-0.20230212182515-e1bfd543b068/go.mod h1:3oHbcSQytW21mTF7ozw3Il3UzdOAG30gPzO2XUAqvGs= github.com/klauspost/compress v1.15.5 h1:qyCLMz2JCrKADihKOh9FxnW3houKeNsp2h5OEz0QSEA= github.com/klauspost/compress v1.15.5/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= github.com/klauspost/compress v1.15.15 h1:EF27CXIuDsYJ6mmvtBRlEuB2UVOqHG1tAXgZ7yIO+lw= diff --git a/tests/reserialize/main.go b/tests/reserialize/main.go index 101f3bf..ef1b693 100644 --- a/tests/reserialize/main.go +++ b/tests/reserialize/main.go @@ -5,12 +5,14 @@ import ( "os" ) -// WIP: test against the Go mt package func main() { - pkt, err := mt.DeserializePkt(os.Stdin, false) + toSrv := os.Args[1] == "ToSrvPkt" + + pkt, err := mt.DeserializePkt(os.Stdin, !toSrv) if err != nil { - panic(err) + os.Stderr.WriteString(err.Error()) + os.Exit(1) } - mt.SerializePkt(*pkt, os.Stdout, false) + mt.SerializePkt(*pkt, os.Stdout, toSrv) } -- 2.44.0