Skip to content

Commit

Permalink
Better test discovery
Browse files Browse the repository at this point in the history
  • Loading branch information
Quaqqer committed Jan 6, 2024
1 parent ac3fdd8 commit a149fb0
Show file tree
Hide file tree
Showing 10 changed files with 171 additions and 64 deletions.
167 changes: 123 additions & 44 deletions crates/saft-macro/src/discover_tests.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
use std::path::PathBuf;
use quote::{format_ident, quote};
use std::{collections::HashMap, path::PathBuf};

use darling::{ast::NestedMeta, FromMeta};
use glob::glob;
use proc_macro::TokenStream;
use quote::{format_ident, quote};

#[derive(FromMeta)]
#[darling()]
struct Args {
path: String,
root: String,
glob: String,
}

#[derive(Debug)]
enum TestNode {
Node(HashMap<String, TestNode>),
Test(PathBuf),
}

pub fn expand_discover_tests(
Expand All @@ -28,54 +35,126 @@ pub fn expand_discover_tests(
};

let test_fn_ident = &test_fn.sig.ident.clone();
let dirs = glob(&args.path).unwrap();

let tests = dirs
.map(|path| {
let path = path.unwrap();
let file_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("../..")
.join(
path.to_str()
let dirs = glob(PathBuf::from(&args.root).join(&args.glob).to_str().unwrap()).unwrap();

let mut root_node = TestNode::Node(HashMap::new());

for dir in dirs {
let path = dir.unwrap();

let root_s = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("../..")
.join(&args.root)
.canonicalize()
.unwrap()
.to_str()
.unwrap()
.to_string();

let file_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("../..")
.join(&path)
.canonicalize()
.unwrap();

let parts = PathBuf::from((file_path.clone()).strip_prefix(&root_s).unwrap())
.components()
.map(|c| c.as_os_str().to_str().unwrap().to_string())
.collect::<Vec<_>>();

let mut curr = &mut root_node;

let parts = parts.iter().enumerate().collect::<Vec<_>>();

for (i, part) in &parts {
let last = *i == parts.len() - 1;

const CLASH_MSG: &'static str = "File and directory name clash, a directory and a name cannot exist with the same name in the same path";

let TestNode::Node(children) = curr else {
panic!("{}", CLASH_MSG)
};

if last {
let prev = children.insert(part.to_string(), TestNode::Test(file_path.clone()));

if prev.is_some() {
panic!("{}", CLASH_MSG);
}
} else {
children
.entry(part.to_string())
.or_insert(TestNode::Node(HashMap::new()));

curr = if let TestNode::Node(children) = curr {
children.get_mut(*part).unwrap()
} else {
panic!("Was just inserted?")
};
}
}
}

fn create_tests(
node: &TestNode,
test_fn_ident: &proc_macro2::Ident,
) -> proc_macro2::TokenStream {
match node {
TestNode::Node(children) => {
let mut toks = vec![];

for (dir, node) in children.iter() {
match node {
TestNode::Node(_) => {
let id = format_ident!("{}", dir);
let node_quote = create_tests(node, test_fn_ident);
toks.push(quote! {
mod #id {
#node_quote
}

})
}
TestNode::Test(_) => {
toks.push(create_tests(node, test_fn_ident));
}
}
}

quote!(#(#toks)*)
}
TestNode::Test(file_path) => {
let test_name = format_ident!(
"{}",
file_path
.file_name()
.unwrap()
.to_str()
.unwrap()
.to_string()
.split_once('.')
.unwrap()
.0
.to_string()
.strip_suffix(".out")
.unwrap(),
)
.to_str()
.unwrap()
.to_string();
let file_expected = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("../..")
.join(path.clone())
.to_str()
.unwrap()
.to_string();

let test_name = format_ident!(
"{}_{}",
test_fn_ident,
path.file_name()
.unwrap()
.to_str()
.unwrap()
.to_string()
.strip_suffix(".saf.out")
.unwrap()
);

quote! {
#[test]
fn #test_name() {
#test_fn_ident(#file_path, #file_expected);
);

let file_path_s = file_path.to_str().unwrap().to_string();

quote! {
#[test]
fn #test_name() {
#test_fn_ident(#file_path_s);
}
}
}
})
.collect::<Vec<_>>();
}
}

let tests = create_tests(&root_node, test_fn_ident);

Ok(quote! {
#test_fn

#(#tests)*
#tests
})
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,8 @@ fn fib(i) {
print(fib(0));
print(fib(1));
print(fib(20));

# output:
# 0
# 1
# 6765
3 changes: 0 additions & 3 deletions crates/saft-tests/res/tests/fib/fib.saf.out

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,7 @@ fn fib(n) {
}
}

print(fib(100));
print(fib(20));

# output:
# 6765
1 change: 0 additions & 1 deletion crates/saft-tests/res/tests/fib_loop/fib_loop.out

This file was deleted.

4 changes: 0 additions & 4 deletions crates/saft-tests/res/tests/loop/loop.saf.out

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,9 @@ x := loop {
};

print(x);

# output:
# 1
# 2
# 3
# 13
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,11 @@ print("asd");
print(print);
print(1.0);
print(1.1234);

# output:
# 1
# 2
# asd
# <builtin function>
# 1.0
# 1.1234
6 changes: 0 additions & 6 deletions crates/saft-tests/res/tests/print/print.saf.out

This file was deleted.

30 changes: 25 additions & 5 deletions crates/saft-tests/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,35 @@ mod test {
use pretty_assertions::assert_eq;
use saft_macro::discover_tests;

#[discover_tests(path = "./crates/saft-tests/res/tests/**/*.saf.out")]
fn test(file_name: &str, out_file: &str) {
#[discover_tests(root = "./crates/saft-tests/res/tests", glob = "**/[!_]*.saf")]
fn test(file_name: &str) {
let mut cmd = Command::cargo_bin("saft").unwrap();
cmd.arg(file_name);

let output = cmd.unwrap();
let got = String::from_utf8(cmd.unwrap().stdout)
.unwrap()
.lines()
.map(|line| line.trim())
.collect::<Vec<_>>()
.join("\n");

let expected_output = std::fs::read_to_string(out_file).unwrap();
let mut expected = Vec::new();

assert_eq!(String::from_utf8(output.stdout).unwrap(), expected_output);
let mut got_output = false;
for line in std::fs::read_to_string(file_name).unwrap().lines() {
if line.starts_with('#') {
let comment = &line[1..].trim();

if got_output {
expected.push(comment.to_string());
} else {
if *comment == "output:" {
got_output = true;
}
}
}
}

assert_eq!(got, expected.join("\n"));
}
}

0 comments on commit a149fb0

Please sign in to comment.