#[cfg(feature = "json_tests")] pub mod json_tests { use indoc::indoc; use serde::{Deserialize, Serialize}; use serde_json; use slugify::slugify; use std::fs::File; use std::io::{BufWriter, Write}; use std::path::PathBuf; #[derive(Debug, Serialize, Deserialize)] struct Symbol { name: String, value: String, } #[derive(Debug, Serialize, Deserialize)] struct StringColumn { name: String, value: String, } #[derive(Debug, Serialize, Deserialize)] struct LongColumn { name: String, value: i64, } #[derive(Debug, Serialize, Deserialize)] struct DoubleColumn { name: String, value: f64, } #[derive(Debug, Serialize, Deserialize)] struct BooleanColumn { name: String, value: bool, } #[derive(Debug, Serialize, Deserialize)] #[serde(tag = "type", rename_all = "UPPERCASE")] enum Column { String(StringColumn), Long(LongColumn), Double(DoubleColumn), Boolean(BooleanColumn), } #[derive(Debug, Serialize, Deserialize)] struct Expected { line: Option, #[serde(rename = "anyLines")] any_lines: Option>, } #[derive(Debug, Serialize, Deserialize)] #[serde(tag = "status", rename_all = "UPPERCASE")] enum Outcome { Success(Expected), Error, } #[derive(Debug, Serialize, Deserialize)] struct TestSpec { #[serde(rename = "testName")] test_name: String, table: String, symbols: Vec, columns: Vec, result: Outcome, } fn parse() -> Vec { let mut json_path = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap()); json_path.push("src"); json_path.push("tests"); json_path.push("interop"); json_path.push("ilp-client-interop-test.json"); let file = std::fs::File::open(json_path).unwrap(); serde_json::from_reader(file).unwrap() } pub fn build() -> Result<(), Box> { let specs = parse(); // eprintln!("Parsed JSON: {:#?}", specs); let mut file_path = PathBuf::from(std::env::var("OUT_DIR")?); file_path.push("json_tests.rs"); let mut output = BufWriter::new(File::create(file_path)?); // let mut output = String::new(); writeln!( output, "{}", indoc! {r#" // This file is auto-generated by build.rs. use crate::{Result, ingress::{Buffer}}; use crate::tests::{TestResult}; fn matches_any_line(line: &str, expected: &[&str]) -> bool { for &exp in expected { if line == exp { return true; } } eprintln!( "Could not match:\n {:?}\nTo any of: {:#?}", line, expected); false } "#} )?; for (index, spec) in specs.iter().enumerate() { writeln!(output, "/// {}", spec.test_name)?; // for line in serde_json::to_string_pretty(&spec).unwrap().split("\n") { // writeln!(output, "/// {}", line)?; // } writeln!(output, "#[test]")?; writeln!( output, "fn test_{:03}_{}() -> TestResult {{", index, slugify!(&spec.test_name, separator = "_") )?; writeln!(output, " let mut buffer = Buffer::new();")?; let (expected, indent) = match &spec.result { Outcome::Success(line) => (Some(line), ""), Outcome::Error => (None, " "), }; if expected.is_none() { writeln!(output, " || -> Result<()> {{")?; } writeln!(output, "{} buffer", indent)?; writeln!(output, "{} .table({:?})?", indent, spec.table)?; for symbol in spec.symbols.iter() { writeln!( output, "{} .symbol({:?}, {:?})?", indent, symbol.name, symbol.value )?; } for column in spec.columns.iter() { match column { Column::String(column) => writeln!( output, "{} .column_str({:?}, {:?})?", indent, column.name, column.value )?, Column::Long(column) => writeln!( output, "{} .column_i64({:?}, {:?})?", indent, column.name, column.value )?, Column::Double(column) => writeln!( output, "{} .column_f64({:?}, {:?})?", indent, column.name, column.value )?, Column::Boolean(column) => writeln!( output, "{} .column_bool({:?}, {:?})?", indent, column.name, column.value )?, } } writeln!(output, "{} .at_now()?;", indent)?; if let Some(expected) = expected { if let Some(ref line) = expected.line { let exp_ln = format!("{}\n", line); writeln!(output, " let exp = {:?};", exp_ln)?; writeln!(output, " assert_eq!(buffer.as_str(), exp);")?; } else { let any: Vec = expected .any_lines .as_ref() .unwrap() .iter() .map(|line| format!("{}\n", line)) .collect(); writeln!(output, " let any = [")?; for line in any.iter() { writeln!(output, " {:?},", line)?; } writeln!(output, " ];")?; writeln!( output, " assert!(matches_any_line(buffer.as_str(), &any));" )?; } } else { writeln!(output, " Ok(())")?; writeln!(output, " }}().unwrap_err();")?; } writeln!(output, " Ok(())")?; writeln!(output, "}}")?; } Ok(()) } } fn main() -> Result<(), Box> { #[cfg(feature = "json_tests")] { println!("cargo:rerun-if-changed=build.rs"); println!("cargo:rerun-if-changed=Cargo.lock"); println!("cargo:rerun-if-changed=src/test/interop/ilp-client-interop-test.json"); json_tests::build()?; } Ok(()) }