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 if pkt_name == "ToSrvPkt::Disco" {
27 Trial::test(pkt_name.clone(), move || {
28 let mut rng = rand::thread_rng();
29 let mut printed_stderr = false;
32 // use buffered IO instead of directly reading from the process
33 // this enables printing out payloads for debugging
35 let input = T::generate_random_variant(&mut rng, i);
37 let mut input_payload = Vec::new();
39 .mt_serialize::<DefCfg>(&mut input_payload)
40 .map_err(|e| format!("serialize error: {e}\ninput: {input:?}"))?;
42 let mut child = Command::new(&reserialize)
44 .stdin(Stdio::piped())
45 .stdout(Stdio::piped())
46 .stderr(Stdio::piped())
48 .expect("failed to spawn reserialize");
50 let mut stdin = child.stdin.take().unwrap();
51 let stdin_payload = input_payload.clone();
52 std::thread::spawn(move || {
53 stdin.write_all(&stdin_payload).unwrap();
56 let command_out = child.wait_with_output().unwrap();
58 let stderr = String::from_utf8_lossy(&command_out.stderr);
59 if command_out.status.success() {
60 if stderr.len() > 0 && !printed_stderr {
61 printed_stderr = true;
62 eprintln!("stderr for {pkt_name}: {stderr}");
66 "reserialize returned failure\n\
68 input payload: {input_payload:?}\n\
74 let mut reader = Cursor::new(command_out.stdout);
75 let output = T::mt_deserialize::<DefCfg>(&mut reader).map_err(|e| {
77 "deserialize error: {e}\n\
79 input payload: {input_payload:?}\n\
80 output payload: {:?}\n\
88 "output does not match input\n\
91 input payload: {input_payload:?}\n\
92 output payload: {:?}\n\
102 .with_kind("random"),
108 fn main() -> Result<(), Box<dyn Error>> {
109 let reserialize = Path::new(file!()).with_file_name("reserialize/reserialize");
111 if !reserialize.exists() {
112 if !Command::new("go")
114 .current_dir(reserialize.parent().unwrap())
116 .expect("go is required for random tests")
118 .expect("go build didn't run")
121 panic!("go build failed");
125 let args = Arguments::from_args();
127 let mut tests = Vec::new();
128 tests.extend(test_reserialize::<ToSrvPkt>("ToSrvPkt", &reserialize));
129 tests.extend(test_reserialize::<ToCltPkt>("ToCltPkt", &reserialize));
131 libtest_mimic::run(&args, tests).exit();