-
Notifications
You must be signed in to change notification settings - Fork 239
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore(debugger): Integration tests (#3938)
# Description Adds integration tests for the debugger. ## Problem Related to #3015. Generates a new suite of tests that uses the examples at test_programs/execution_success to verify that the debugger can be started and stepped to completion with those examples. ## Summary We take the same approach used for the `nargo execute` cmd: generating test cases from those at test_programs/execution_success. This means future extensions to the Noir language captured in those examples will automatically be included in the debugger integration suite, and will help detect any potential divergence between the language runtime and the debugger instrumentation. ## Documentation Check one: - [x] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings.
- Loading branch information
Showing
5 changed files
with
176 additions
and
3 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
use rustc_version::{version, Version}; | ||
use std::fs::File; | ||
use std::io::Write; | ||
use std::path::{Path, PathBuf}; | ||
use std::{env, fs}; | ||
|
||
fn check_rustc_version() { | ||
assert!( | ||
version().unwrap() >= Version::parse("1.71.1").unwrap(), | ||
"The minimal supported rustc version is 1.71.1." | ||
); | ||
} | ||
|
||
const GIT_COMMIT: &&str = &"GIT_COMMIT"; | ||
|
||
fn main() { | ||
// Rebuild if the tests have changed | ||
println!("cargo:rerun-if-changed=tests"); | ||
|
||
check_rustc_version(); | ||
|
||
// Only use build_data if the environment variable isn't set | ||
// The environment variable is always set when working via Nix | ||
if std::env::var(GIT_COMMIT).is_err() { | ||
build_data::set_GIT_COMMIT(); | ||
build_data::set_GIT_DIRTY(); | ||
build_data::no_debug_rebuilds(); | ||
} | ||
|
||
let out_dir = env::var("OUT_DIR").unwrap(); | ||
let destination = Path::new(&out_dir).join("debug.rs"); | ||
let mut test_file = File::create(destination).unwrap(); | ||
|
||
// Try to find the directory that Cargo sets when it is running; otherwise fallback to assuming the CWD | ||
// is the root of the repository and append the crate path | ||
let root_dir = match std::env::var("CARGO_MANIFEST_DIR") { | ||
Ok(dir) => PathBuf::from(dir).parent().unwrap().parent().unwrap().to_path_buf(), | ||
Err(_) => std::env::current_dir().unwrap(), | ||
}; | ||
let test_dir = root_dir.join("test_programs"); | ||
|
||
generate_debugger_tests(&mut test_file, &test_dir); | ||
} | ||
|
||
fn generate_debugger_tests(test_file: &mut File, test_data_dir: &Path) { | ||
let test_sub_dir = "execution_success"; | ||
let test_data_dir = test_data_dir.join(test_sub_dir); | ||
|
||
let test_case_dirs = | ||
fs::read_dir(test_data_dir).unwrap().flatten().filter(|c| c.path().is_dir()); | ||
|
||
for test_dir in test_case_dirs { | ||
let test_name = | ||
test_dir.file_name().into_string().expect("Directory can't be converted to string"); | ||
if test_name.contains('-') { | ||
panic!( | ||
"Invalid test directory: {test_name}. Cannot include `-`, please convert to `_`" | ||
); | ||
}; | ||
let test_dir = &test_dir.path(); | ||
|
||
write!( | ||
test_file, | ||
r#" | ||
#[test] | ||
fn debug_{test_name}() {{ | ||
debugger_execution_success("{test_dir}"); | ||
}} | ||
"#, | ||
test_dir = test_dir.display(), | ||
) | ||
.expect("Could not write templated test file."); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
#[cfg(test)] | ||
mod tests { | ||
// Some of these imports are consumed by the injected tests | ||
use assert_cmd::cargo::cargo_bin; | ||
|
||
use rexpect::spawn_bash; | ||
|
||
test_binary::build_test_binary_once!(mock_backend, "../backend_interface/test-binaries"); | ||
|
||
// include tests generated by `build.rs` | ||
include!(concat!(env!("OUT_DIR"), "/debug.rs")); | ||
|
||
pub fn debugger_execution_success(test_program_dir: &str) { | ||
let nargo_bin = | ||
cargo_bin("nargo").into_os_string().into_string().expect("Cannot parse nargo path"); | ||
|
||
let mock_backend_path = | ||
path_to_mock_backend().into_string().expect("Cannot parse mock_backend path"); | ||
|
||
let mut dbg_session = spawn_bash(Some(10000)).expect("Could not start bash session"); | ||
|
||
dbg_session | ||
.send_line(&format!("export NARGO_BACKEND_PATH={}", mock_backend_path)) | ||
.expect("Could not export NARGO_BACKEND_PATH."); | ||
dbg_session.wait_for_prompt().expect("Could not export NARGO_BACKEND_PATH."); | ||
|
||
// Start debugger and test that it loads for the given program. | ||
dbg_session | ||
.execute( | ||
&format!("{} debug --program-dir {}", nargo_bin, test_program_dir), | ||
&format!(".*\\Starting debugger.*"), | ||
) | ||
.expect("Could not start debugger"); | ||
|
||
// While running the debugger, issue a "continue" cmd, | ||
// which should run to the program to end given | ||
// we haven't set any breakpoints. | ||
// ">" is the debugger's prompt, so finding one | ||
// after running "continue" indicates that the | ||
// debugger has not panicked until the end of the program. | ||
dbg_session | ||
.send_line("c") | ||
.expect("Debugger panicked while attempting to step through program."); | ||
dbg_session | ||
.exp_string(">") | ||
.expect("Failed while waiting for debugger to step through program."); | ||
|
||
// Run the "quit" command, then check that the debugger confirms | ||
// having successfully solved the circuit witness. | ||
dbg_session.send_line("quit").expect("Failed to quit debugger"); | ||
dbg_session | ||
.exp_regex(&format!(".*Circuit witness successfully solved.*")) | ||
.expect("Expected circuit witness to be successfully solved."); | ||
} | ||
} |