feat: Add testing and benchmarking capabilities
This commit introduces a new `tester` module to the `ast` crate, enabling functional tests and performance benchmarks for MYC scripts. Functional tests are executed by reading `.myc` files from the `examples` directory, parsing expected output comments, and comparing them against the actual script execution results. Benchmarking involves measuring the execution time of scripts, calculating median durations, and comparing them against stored baselines. The commit also adds support for updating these baselines. The `ast.rs` CLI and the `main.rs` GUI application have been updated to expose these new testing and benchmarking features. The `Cargo.toml` and `Cargo.lock` files have been updated to include the `regex` dependency required for parsing benchmark comments.
This commit is contained in:
+62
-12
@@ -16,7 +16,6 @@ fn main() -> eframe::Result {
|
||||
struct Example {
|
||||
name: String,
|
||||
content: String,
|
||||
is_benchmark: bool,
|
||||
}
|
||||
|
||||
struct CompilerApp {
|
||||
@@ -37,8 +36,7 @@ impl Default for CompilerApp {
|
||||
.filter_map(|e| {
|
||||
let name = e.file_name().into_string().ok()?;
|
||||
let content = std::fs::read_to_string(e.path()).ok()?;
|
||||
let is_benchmark = content.contains(";; Benchmark");
|
||||
Some(Example { name, content, is_benchmark })
|
||||
Some(Example { name, content })
|
||||
})
|
||||
.collect()
|
||||
})
|
||||
@@ -82,6 +80,37 @@ impl CompilerApp {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn run_all_tests(&mut self) {
|
||||
use myc::ast::tester;
|
||||
let results = tester::run_functional_tests();
|
||||
let mut log = String::from("FUNCTIONAL TEST RESULTS:\n\n");
|
||||
let mut passed = 0;
|
||||
for res in &results {
|
||||
log.push_str(&format!("{}: {} - {}\n", if res.success { "✅" } else { "❌" }, res.name, res.message));
|
||||
if res.success { passed += 1; }
|
||||
}
|
||||
log.push_str(&format!("\nTotal: {}/{}", passed, results.len()));
|
||||
self.output_log = log;
|
||||
}
|
||||
|
||||
fn run_benchmarks(&mut self, update: bool) {
|
||||
use myc::ast::tester;
|
||||
if cfg!(debug_assertions) && !update {
|
||||
self.output_log = String::from("⚠️ WARNING: Benchmarks in Debug mode are inaccurate!\nUse Release build for real measurements.\n\n");
|
||||
} else {
|
||||
self.output_log = String::from(if update { "UPDATING BASELINES...\n\n" } else { "RUNNING BENCHMARKS...\n\n" });
|
||||
}
|
||||
|
||||
let results = tester::run_benchmarks(update);
|
||||
let mut log = self.output_log.clone();
|
||||
|
||||
for res in results {
|
||||
let diff = res.diff_pct.map_or(String::new(), |d| format!(" ({:+.1}%)", d));
|
||||
log.push_str(&format!("{}: {} - {:?}{}\n", res.status, res.name, res.median, diff));
|
||||
}
|
||||
self.output_log = log;
|
||||
}
|
||||
}
|
||||
|
||||
impl eframe::App for CompilerApp {
|
||||
@@ -94,12 +123,7 @@ impl eframe::App for CompilerApp {
|
||||
ui.heading("Examples");
|
||||
ui.add_space(5.0);
|
||||
for example in &self.examples {
|
||||
let label = if example.is_benchmark {
|
||||
format!("⚡ {}", example.name)
|
||||
} else {
|
||||
example.name.clone()
|
||||
};
|
||||
if ui.button(label).clicked() {
|
||||
if ui.button(&example.name).clicked() {
|
||||
self.source_code = example.content.clone();
|
||||
}
|
||||
}
|
||||
@@ -114,9 +138,35 @@ impl eframe::App for CompilerApp {
|
||||
ui.add_space(5.0);
|
||||
|
||||
// Compile Button (at the top of the bottom panel)
|
||||
if ui.button("Compile").clicked() {
|
||||
self.compile();
|
||||
}
|
||||
ui.horizontal(|ui| {
|
||||
if ui.button("Compile").clicked() {
|
||||
self.compile();
|
||||
}
|
||||
|
||||
if ui.button("Test All").clicked() {
|
||||
self.run_all_tests();
|
||||
}
|
||||
|
||||
let is_debug = cfg!(debug_assertions);
|
||||
|
||||
ui.add_enabled_ui(!is_debug, |ui| {
|
||||
let btn = ui.button("Run Benchmarks");
|
||||
if is_debug {
|
||||
btn.on_hover_text("Benchmarks are only available in Release builds for accuracy.");
|
||||
} else if btn.clicked() {
|
||||
self.run_benchmarks(false);
|
||||
}
|
||||
});
|
||||
|
||||
ui.add_enabled_ui(!is_debug, |ui| {
|
||||
let btn = ui.button("Update Baselines");
|
||||
if is_debug {
|
||||
btn.on_hover_text("Updating baselines is only allowed in Release builds.");
|
||||
} else if btn.clicked() {
|
||||
self.run_benchmarks(true);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
ui.add_space(5.0);
|
||||
ui.horizontal(|ui| {
|
||||
|
||||
Reference in New Issue
Block a user