]> git.lizzy.rs Git - mt_net.git/commitdiff
Test against go mt package
authorLizzy Fleckenstein <eliasfleckenstein@web.de>
Sun, 12 Feb 2023 18:40:19 +0000 (19:40 +0100)
committerLizzy Fleckenstein <eliasfleckenstein@web.de>
Sun, 12 Feb 2023 18:40:19 +0000 (19:40 +0100)
tests/random.rs
tests/reserialize/go.mod
tests/reserialize/go.sum
tests/reserialize/main.go

index a9d16092b1ef5f4f9eed65764c7fbd15432070e3..d92ce799407ac78270a3061cf54fd13db897b32e 100644 (file)
@@ -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<T>(type_name: &'static str) -> impl Iterator<Item = Trial>
+fn test_reserialize<'a, T>(type_name: &'static str, reserialize: &Path) -> Vec<Trial>
 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::<DefCfg>(&mut writer)
-                    .map_err(|e| format!("serialize error: {e}\ninput: {input:?}"))?;
-
-                let mut reader = std::io::Cursor::new(writer);
-                let output = T::mt_deserialize::<DefCfg>(&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::<DefCfg>(&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::<DefCfg>(&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<dyn Error>> {
+    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>("ToSrvPkt")
-        .chain(test_reserialize::<ToCltPkt>("ToCltPkt"))
-        .collect();
+
+    let mut tests = Vec::new();
+    tests.extend(test_reserialize::<ToSrvPkt>("ToSrvPkt", &reserialize));
+    tests.extend(test_reserialize::<ToCltPkt>("ToCltPkt", &reserialize));
+
     libtest_mimic::run(&args, tests).exit();
 }
index 414ffb60e6ed4324abc5d32d66666fc53ab290be..34d806efe786d90a746984f811106b2c670b69d8 100644 (file)
@@ -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
 )
index c92cbb73d32bcce2508037f8de8ea60f401c3e7f..2688586542ecb1082da9f6a99629938561eb3279 100644 (file)
@@ -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=
index 101f3bfa0a2c2ffcd5ab0360bda00b8769cf091a..ef1b6939584657a610445f84780e67da345043fe 100644 (file)
@@ -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)
 }