#[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<String>,
#[serde(rename = "anyLines")]
any_lines: Option<Vec<String>>,
}
#[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<Symbol>,
columns: Vec<Column>,
result: Outcome,
}
fn parse() -> Vec<TestSpec> {
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<dyn std::error::Error>> {
let specs = parse();
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)?);
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)?;
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<String> = 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<dyn std::error::Error>> {
#[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(())
}