1 use libtest_mimic::{Arguments, Trial};
3 use mt_net::{generate_random::GenerateRandomVariant, rand, ToCltPkt, ToSrvPkt};
4 use mt_ser::{DefCfg, MtDeserialize, MtSerialize};
10 process::{Command, Stdio},
13 fn test_reserialize<'a, T>(type_name: &'static str, reserialize: &Path) -> Vec<Trial>
15 T: MtSerialize + MtDeserialize + GenerateRandomVariant + PartialEq + Debug,
17 (0..T::num_variants())
19 let pkt_name = format!("{type_name}::{}", T::variant_name(i));
20 let reserialize = reserialize.as_os_str().to_os_string();
22 Trial::test(pkt_name.clone(), move || {
23 let mut rng = rand::thread_rng();
24 let mut printed_stderr = false;
27 // use buffered IO instead of directly reading from the process
28 // this enables printing out payloads for debugging
30 let input = T::generate_random_variant(&mut rng, i);
32 let mut writer = Vec::new();
34 .mt_serialize::<DefCfg>(&mut writer)
35 .map_err(|e| format!("serialize error: {e}\ninput: {input:?}"))?;
37 let mut child = Command::new(&reserialize)
39 .stdin(Stdio::piped())
40 .stdout(Stdio::piped())
41 .stderr(Stdio::piped())
43 .expect("failed to spawn reserialize");
45 let mut stdin = child.stdin.take().expect("failed to open stdin");
46 let payload = writer.clone();
47 std::thread::spawn(move || {
48 stdin.write_all(&payload).expect("failed to write to stdin");
51 let command_out = child.wait_with_output().expect("failed to read stdout");
53 let stderr = String::from_utf8_lossy(&command_out.stderr);
54 if command_out.status.success() {
55 if stderr.len() > 0 && !printed_stderr {
56 printed_stderr = true;
57 eprintln!("stderr for {pkt_name}: {stderr}");
61 "reserialize returned failure\n\
63 input payload: {writer:?}\n\
69 let mut reader = Cursor::new(command_out.stdout);
70 let output = T::mt_deserialize::<DefCfg>(&mut reader).map_err(|e| {
72 "deserialize error: {e}\n\
74 input payload: {writer:?}\n\
75 output payload: {:?}\n\
83 "output does not match input\n\
86 input payload: {writer:?}\n\
87 output payload: {:?}\n\
102 fn main() -> Result<(), Box<dyn Error>> {
103 let reserialize = Path::new(file!()).with_file_name("reserialize/reserialize");
105 if !reserialize.exists() {
106 if !Command::new("go")
108 .current_dir(reserialize.parent().unwrap())
110 .expect("go is required for random tests")
112 .expect("go build didn't run")
115 panic!("go build failed");
119 let args = Arguments::from_args();
121 let mut tests = Vec::new();
122 tests.extend(test_reserialize::<ToSrvPkt>("ToSrvPkt", &reserialize));
123 tests.extend(test_reserialize::<ToCltPkt>("ToCltPkt", &reserialize));
125 libtest_mimic::run(&args, tests).exit();