From 18e9a8b7278a2bc0eeb24b27aa3bac0ea57b0a47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?O=CC=88zgu=CC=88r=20Akgu=CC=88n?= Date: Tue, 21 Nov 2023 11:01:16 +0000 Subject: [PATCH 1/4] adding 3 simple bool tests --- conjure_oxide/tests/integration/basic/bool-01/bool-01.essence | 1 + conjure_oxide/tests/integration/basic/bool-02/bool-02.essence | 1 + conjure_oxide/tests/integration/basic/bool-03/bool-03.essence | 2 ++ 3 files changed, 4 insertions(+) create mode 100644 conjure_oxide/tests/integration/basic/bool-01/bool-01.essence create mode 100644 conjure_oxide/tests/integration/basic/bool-02/bool-02.essence create mode 100644 conjure_oxide/tests/integration/basic/bool-03/bool-03.essence diff --git a/conjure_oxide/tests/integration/basic/bool-01/bool-01.essence b/conjure_oxide/tests/integration/basic/bool-01/bool-01.essence new file mode 100644 index 000000000..67256f5f7 --- /dev/null +++ b/conjure_oxide/tests/integration/basic/bool-01/bool-01.essence @@ -0,0 +1 @@ +find x : bool diff --git a/conjure_oxide/tests/integration/basic/bool-02/bool-02.essence b/conjure_oxide/tests/integration/basic/bool-02/bool-02.essence new file mode 100644 index 000000000..38ac0068f --- /dev/null +++ b/conjure_oxide/tests/integration/basic/bool-02/bool-02.essence @@ -0,0 +1 @@ +find x, y : bool \ No newline at end of file diff --git a/conjure_oxide/tests/integration/basic/bool-03/bool-03.essence b/conjure_oxide/tests/integration/basic/bool-03/bool-03.essence new file mode 100644 index 000000000..99a6dc38a --- /dev/null +++ b/conjure_oxide/tests/integration/basic/bool-03/bool-03.essence @@ -0,0 +1,2 @@ +find x, y : bool +such that x != y From 8cdcd50572667ad2e62ee83686efc87ccab6cf20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?O=CC=88zgu=CC=88r=20Akgu=CC=88n?= Date: Tue, 21 Nov 2023 11:25:59 +0000 Subject: [PATCH 2/4] using walkdir so we find the new test cases... --- Cargo.lock | 42 +++++++++++++++++++++++++++++++++------- conjure_oxide/Cargo.toml | 4 ++++ conjure_oxide/build.rs | 38 +++++++++++++++++++++++------------- 3 files changed, 64 insertions(+), 20 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 573ed9a22..a9dec58ba 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -26,6 +26,12 @@ dependencies = [ "libc", ] +[[package]] +name = "anyhow" +version = "1.0.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" + [[package]] name = "assert-json-diff" version = "2.0.2" @@ -48,13 +54,6 @@ version = "0.21.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" -[[package]] -name = "anyhow" -version = "1.0.75" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" - - [[package]] name = "bindgen" version = "0.64.0" @@ -185,6 +184,7 @@ dependencies = [ "serde_json", "serde_with", "thiserror", + "walkdir", ] [[package]] @@ -592,6 +592,15 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "serde" version = "1.0.192" @@ -741,6 +750,16 @@ version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +[[package]] +name = "walkdir" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" +dependencies = [ + "same-file", + "winapi-util", +] + [[package]] name = "wasm-bindgen" version = "0.2.88" @@ -823,6 +842,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +dependencies = [ + "winapi", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" diff --git a/conjure_oxide/Cargo.toml b/conjure_oxide/Cargo.toml index e4ea59526..0eb8db7f7 100644 --- a/conjure_oxide/Cargo.toml +++ b/conjure_oxide/Cargo.toml @@ -4,6 +4,10 @@ version = "0.0.1" edition = "2021" default-run = "conjure_oxide" +# these are available inside build.rs +[build-dependencies] +walkdir = "2.4.0" + [dependencies] assert-json-diff = "2.0.2" serde = { version = "1.0.192", features = ["derive"] } diff --git a/conjure_oxide/build.rs b/conjure_oxide/build.rs index 350f42380..696d33264 100644 --- a/conjure_oxide/build.rs +++ b/conjure_oxide/build.rs @@ -1,10 +1,7 @@ -use std::{ - env::var, - fs::File, - fs::{read_dir, DirEntry}, - io::Write, - path::Path, -}; +use std::fs::read_dir; +use std::io::Write; +use std::{env::var, fs::File, path::Path}; +use walkdir::WalkDir; fn main() { let out_dir = var("OUT_DIR").unwrap(); @@ -12,18 +9,33 @@ fn main() { let mut f = File::create(&dest).unwrap(); let test_dir = "tests/integration"; - for dir in read_dir(test_dir).unwrap() { - write_test(&mut f, &dir.unwrap()); + + for subdir in WalkDir::new(test_dir) { + let subdir = subdir.unwrap(); + if subdir.file_type().is_dir() { + let essence_file_count = read_dir(subdir.path()) + .expect("Failed to read directory") + .filter_map(Result::ok) + .filter(|entry| { + entry + .path() + .extension() + .map_or(false, |ext| ext == "essence") + }) + .count(); + if essence_file_count == 1 { + write_test(&mut f, subdir.path().display().to_string()); + } + } } } -fn write_test(file: &mut File, dir: &DirEntry) { - let binding = dir.path(); - let path = binding.to_str().unwrap(); +fn write_test(file: &mut File, path: String) { write!( file, include_str!("./tests/gen_test_template"), - name = path.replace("./", "").replace("/", "_"), + // TODO: better sanitisation of paths to function names + name = path.replace("./", "").replace("/", "_").replace("-", "_"), path = path ) .unwrap(); From f785e6fc392aa135eb4a4154d4db1a29321dd506 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?O=CC=88zgu=CC=88r=20Akgu=CC=88n?= Date: Tue, 21 Nov 2023 19:48:26 +0000 Subject: [PATCH 3/4] tester rewrite - recursively walk all directories under tests/integration - generate a *.generated.* file - ACCEPT=true cargo test will accept all generated files as correct - add test outputs for the new test cases --- .gitignore | 2 + Cargo.lock | 11 ---- conjure_oxide/Cargo.toml | 1 - conjure_oxide/build.rs | 57 +++++++++++------- conjure_oxide/src/main.rs | 2 +- conjure_oxide/tests/gen_test_template | 4 +- conjure_oxide/tests/generated_tests.rs | 58 ++++++++++++++----- .../bool-01/bool-01.expected.serialised.json | 13 +++++ .../bool-02/bool-02.expected.serialised.json | 21 +++++++ .../bool-03/bool-03.expected.serialised.json | 21 +++++++ ...ed.json => input.expected.serialised.json} | 49 ++-------------- 11 files changed, 144 insertions(+), 95 deletions(-) create mode 100644 conjure_oxide/tests/integration/basic/bool-01/bool-01.expected.serialised.json create mode 100644 conjure_oxide/tests/integration/basic/bool-02/bool-02.expected.serialised.json create mode 100644 conjure_oxide/tests/integration/basic/bool-03/bool-03.expected.serialised.json rename conjure_oxide/tests/integration/xyz/{input.serialised.expected.json => input.expected.serialised.json} (52%) diff --git a/.gitignore b/.gitignore index e2769d9d2..b707be5e6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,8 @@ *.log coverage +conjure_oxide/tests/**/*.generated.* + ## Rust debug/ target/ diff --git a/Cargo.lock b/Cargo.lock index a9dec58ba..695f2eeb9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -32,16 +32,6 @@ version = "1.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" -[[package]] -name = "assert-json-diff" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47e4f2b81832e72834d7518d8487a0396a28cc408186a2e8854c0f98011faf12" -dependencies = [ - "serde", - "serde_json", -] - [[package]] name = "autocfg" version = "1.1.0" @@ -178,7 +168,6 @@ dependencies = [ name = "conjure_oxide" version = "0.0.1" dependencies = [ - "assert-json-diff", "minion_rs", "serde", "serde_json", diff --git a/conjure_oxide/Cargo.toml b/conjure_oxide/Cargo.toml index 0eb8db7f7..5d53553b9 100644 --- a/conjure_oxide/Cargo.toml +++ b/conjure_oxide/Cargo.toml @@ -9,7 +9,6 @@ default-run = "conjure_oxide" walkdir = "2.4.0" [dependencies] -assert-json-diff = "2.0.2" serde = { version = "1.0.192", features = ["derive"] } serde_json = "1.0.108" serde_with = "3.4.0" diff --git a/conjure_oxide/build.rs b/conjure_oxide/build.rs index 696d33264..7a160cba8 100644 --- a/conjure_oxide/build.rs +++ b/conjure_oxide/build.rs @@ -1,20 +1,20 @@ -use std::fs::read_dir; -use std::io::Write; -use std::{env::var, fs::File, path::Path}; +use std::env::var; +use std::fs::{read_dir, File}; +use std::io::{self, Write}; +use std::path::Path; use walkdir::WalkDir; -fn main() { - let out_dir = var("OUT_DIR").unwrap(); +fn main() -> io::Result<()> { + let out_dir = var("OUT_DIR").map_err(|e| io::Error::new(io::ErrorKind::Other, e))?; // wrapping in a std::io::Error to match main's error type let dest = Path::new(&out_dir).join("gen_tests.rs"); - let mut f = File::create(&dest).unwrap(); + let mut f = File::create(&dest)?; let test_dir = "tests/integration"; for subdir in WalkDir::new(test_dir) { - let subdir = subdir.unwrap(); + let subdir = subdir?; if subdir.file_type().is_dir() { - let essence_file_count = read_dir(subdir.path()) - .expect("Failed to read directory") + let essence_files: Vec = read_dir(subdir.path())? .filter_map(Result::ok) .filter(|entry| { entry @@ -22,21 +22,34 @@ fn main() { .extension() .map_or(false, |ext| ext == "essence") }) - .count(); - if essence_file_count == 1 { - write_test(&mut f, subdir.path().display().to_string()); - } + .filter_map(|entry| { + entry + .path() + .file_stem() + .and_then(|stem| stem.to_str()) + .map(|s| s.to_owned()) + }) + .collect(); + + write_test(&mut f, subdir.path().display().to_string(), essence_files)?; } } + + Ok(()) } -fn write_test(file: &mut File, path: String) { - write!( - file, - include_str!("./tests/gen_test_template"), - // TODO: better sanitisation of paths to function names - name = path.replace("./", "").replace("/", "_").replace("-", "_"), - path = path - ) - .unwrap(); +fn write_test(file: &mut File, path: String, essence_files: Vec) -> io::Result<()> { + // TODO: Consider supporting multiple Essence files? + if essence_files.len() == 1 { + write!( + file, + include_str!("./tests/gen_test_template"), + // TODO: better sanitisation of paths to function names + test_name = path.replace("./", "").replace("/", "_").replace("-", "_"), + test_dir = path, + essence_file = essence_files[0] + ) + } else { + Ok(()) + } } diff --git a/conjure_oxide/src/main.rs b/conjure_oxide/src/main.rs index 9d2b7d103..579011bcb 100644 --- a/conjure_oxide/src/main.rs +++ b/conjure_oxide/src/main.rs @@ -1,4 +1,4 @@ -use std::{collections::HashMap, fs::File, io::Read}; +use std::{collections::HashMap}; use conjure_oxide::ast::*; diff --git a/conjure_oxide/tests/gen_test_template b/conjure_oxide/tests/gen_test_template index 337c98a2d..2c3dd27ff 100644 --- a/conjure_oxide/tests/gen_test_template +++ b/conjure_oxide/tests/gen_test_template @@ -1,4 +1,4 @@ #[test] -fn {name}() -> Result<(), Box> {{ - integration_test("{path}") +fn {test_name}() -> Result<(), Box> {{ + integration_test("{test_dir}", "{essence_file}") }} diff --git a/conjure_oxide/tests/generated_tests.rs b/conjure_oxide/tests/generated_tests.rs index 56895cff6..03d86a8c8 100644 --- a/conjure_oxide/tests/generated_tests.rs +++ b/conjure_oxide/tests/generated_tests.rs @@ -1,34 +1,66 @@ -use assert_json_diff::assert_json_eq; +use std::env; use std::error::Error; use std::fs::File; use std::io::prelude::*; use conjure_oxide::ast::Model; -fn integration_test(path: &str) -> Result<(), Box> { - println!("Integration test for: {}", path); +use std::path::Path; + +fn main() { + let file_path = Path::new("/path/to/your/file.txt"); + let base_name = file_path.file_stem().and_then(|stem| stem.to_str()); + + match base_name { + Some(name) => println!("Base name: {}", name), + None => println!("Could not extract the base name"), + } +} + +fn integration_test(path: &str, essence_base: &str) -> Result<(), Box> { + // -------------------------------------------------------------------------------- + // -- parsing the essence file + + // calling conjure to convert Essence to astjson let mut cmd = std::process::Command::new("conjure"); let output = cmd .arg("pretty") .arg("--output-format=astjson") - .arg(format!("{path}/input.essence", path = path)) + .arg(format!("{path}/{essence_base}.essence")) .output()?; + assert!( + String::from_utf8(output.stderr)?.is_empty(), + "conjure's stderr is not empty" + ); let astjson = String::from_utf8(output.stdout)?; + + // "parsing" astjson as Model let generated_mdl = Model::from_json(&astjson)?; - let mut expected_str = String::new(); - let mut f = File::open(format!( - "{path}/input.serialised.expected.json", - path = path - ))?; - f.read_to_string(&mut expected_str)?; + // serialise to file + let generated_json = serde_json::to_string_pretty(&generated_mdl)?; + File::create(format!("{path}/{essence_base}.generated.serialised.json"))? + .write_all(generated_json.as_bytes())?; + + if std::env::var("ACCEPT").map_or(false, |v| v == "true") { + std::fs::copy( + format!("{path}/{essence_base}.generated.serialised.json"), + format!("{path}/{essence_base}.expected.serialised.json"), + )?; + } + + // -------------------------------------------------------------------------------- + // -- reading the expected version from the filesystem + + let expected_str = + std::fs::read_to_string(format!("{path}/{essence_base}.expected.serialised.json"))?; + let mut expected_mdl: Model = serde_json::from_str(&expected_str)?; expected_mdl.constraints = Vec::new(); // TODO - remove this line once we parse constraints - println!("Expected {:#?}", expected_mdl); - println!("\nActual {:#?}", generated_mdl); + // -------------------------------------------------------------------------------- + // assert that they are the same model - // assert_json_eq!(serde_json::to_string_pretty(&generated_mdl)?, expected_str); // TODO - replace line once we parse constraints assert_eq!(generated_mdl, expected_mdl); Ok(()) diff --git a/conjure_oxide/tests/integration/basic/bool-01/bool-01.expected.serialised.json b/conjure_oxide/tests/integration/basic/bool-01/bool-01.expected.serialised.json new file mode 100644 index 000000000..06dbb91f2 --- /dev/null +++ b/conjure_oxide/tests/integration/basic/bool-01/bool-01.expected.serialised.json @@ -0,0 +1,13 @@ +{ + "variables": [ + [ + { + "UserName": "x" + }, + { + "domain": "BoolDomain" + } + ] + ], + "constraints": [] +} \ No newline at end of file diff --git a/conjure_oxide/tests/integration/basic/bool-02/bool-02.expected.serialised.json b/conjure_oxide/tests/integration/basic/bool-02/bool-02.expected.serialised.json new file mode 100644 index 000000000..d5883b4ff --- /dev/null +++ b/conjure_oxide/tests/integration/basic/bool-02/bool-02.expected.serialised.json @@ -0,0 +1,21 @@ +{ + "variables": [ + [ + { + "UserName": "y" + }, + { + "domain": "BoolDomain" + } + ], + [ + { + "UserName": "x" + }, + { + "domain": "BoolDomain" + } + ] + ], + "constraints": [] +} \ No newline at end of file diff --git a/conjure_oxide/tests/integration/basic/bool-03/bool-03.expected.serialised.json b/conjure_oxide/tests/integration/basic/bool-03/bool-03.expected.serialised.json new file mode 100644 index 000000000..2ef697aed --- /dev/null +++ b/conjure_oxide/tests/integration/basic/bool-03/bool-03.expected.serialised.json @@ -0,0 +1,21 @@ +{ + "variables": [ + [ + { + "UserName": "x" + }, + { + "domain": "BoolDomain" + } + ], + [ + { + "UserName": "y" + }, + { + "domain": "BoolDomain" + } + ] + ], + "constraints": [] +} \ No newline at end of file diff --git a/conjure_oxide/tests/integration/xyz/input.serialised.expected.json b/conjure_oxide/tests/integration/xyz/input.expected.serialised.json similarity index 52% rename from conjure_oxide/tests/integration/xyz/input.serialised.expected.json rename to conjure_oxide/tests/integration/xyz/input.expected.serialised.json index 905e956aa..f7a71e68e 100644 --- a/conjure_oxide/tests/integration/xyz/input.serialised.expected.json +++ b/conjure_oxide/tests/integration/xyz/input.expected.serialised.json @@ -2,7 +2,7 @@ "variables": [ [ { - "UserName": "b" + "UserName": "a" }, { "domain": { @@ -19,7 +19,7 @@ ], [ { - "UserName": "a" + "UserName": "b" }, { "domain": { @@ -52,46 +52,5 @@ } ] ], - "constraints": [ - { - "Eq": [ - { - "Sum": [ - { - "Reference": { - "UserName": "a" - } - }, - { - "Reference": { - "UserName": "b" - } - }, - { - "Reference": { - "UserName": "c" - } - } - ] - }, - { - "ConstantInt": 4 - } - ] - }, - { - "Geq": [ - { - "Reference": { - "UserName": "a" - } - }, - { - "Reference": { - "UserName": "b" - } - } - ] - } - ] -} + "constraints": [] +} \ No newline at end of file From dbb4fc40ee4c793b54802a639c8c77682fbf9eb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?O=CC=88zgu=CC=88r=20Akgu=CC=88n?= Date: Tue, 21 Nov 2023 20:08:56 +0000 Subject: [PATCH 4/4] cargo format --- conjure_oxide/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conjure_oxide/src/main.rs b/conjure_oxide/src/main.rs index 579011bcb..cc3937147 100644 --- a/conjure_oxide/src/main.rs +++ b/conjure_oxide/src/main.rs @@ -1,4 +1,4 @@ -use std::{collections::HashMap}; +use std::collections::HashMap; use conjure_oxide::ast::*;