Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: regression test #7195 #7233

Merged
merged 20 commits into from
Feb 21, 2025
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
d5d87fe
add raw-source-printing flag to debugger to disable highlighting, add…
michaeljklein Jan 29, 2025
69313d9
cargo clippy
michaeljklein Jan 29, 2025
b19100f
Merge branch 'master' into michaeljklein/regression_test_7195
michaeljklein Jan 29, 2025
816faf8
Merge branch 'master' into michaeljklein/regression_test_7195
michaeljklein Jan 30, 2025
3e80dd5
Merge branch 'master' into michaeljklein/regression_test_7195
michaeljklein Feb 4, 2025
c427370
Merge branch 'master' into michaeljklein/regression_test_7195
michaeljklein Feb 5, 2025
cbbd7db
wip debugging, add unconstrained call to test, wip only testing debug…
michaeljklein Feb 5, 2025
4e7dc83
debugging test and cleanup
michaeljklein Feb 5, 2025
e64e1b5
Merge branch 'master' into michaeljklein/regression_test_7195
michaeljklein Feb 5, 2025
7ebb52a
Merge branch 'master' into michaeljklein/regression_test_7195
michaeljklein Feb 6, 2025
b1bc63a
Merge branch 'master' into michaeljklein/regression_test_7195
michaeljklein Feb 7, 2025
674c758
responding to review comments: small refactor and add detail to doc c…
michaeljklein Feb 7, 2025
c1506c1
cargo clippy
michaeljklein Feb 7, 2025
6809698
Merge branch 'master' into michaeljklein/regression_test_7195
michaeljklein Feb 11, 2025
33d36dc
remove redundant default clap cli value
michaeljklein Feb 13, 2025
ce0c698
Merge branch 'master' into michaeljklein/regression_test_7195
michaeljklein Feb 18, 2025
c00cc64
Merge branch 'master' into michaeljklein/regression_test_7195
michaeljklein Feb 18, 2025
f563b9f
Merge branch 'master' into michaeljklein/regression_test_7195
michaeljklein Feb 19, 2025
cc6c4ba
nargo fmt
michaeljklein Feb 19, 2025
9af4834
Merge branch 'master' into michaeljklein/regression_test_7195
michaeljklein Feb 19, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions test_programs/execution_success/regression_7195/Nargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[package]
name = "regression_7195"
type = "bin"
authors = [""]

[dependencies]
2 changes: 2 additions & 0 deletions test_programs/execution_success/regression_7195/Prover.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
x = "1"
y = "2"
21 changes: 21 additions & 0 deletions test_programs/execution_success/regression_7195/src/main.nr
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
fn bar(y: Field) {
assert(y != 0);
}

fn foo(x: Field) {
/// Safety: test
let y = unsafe { baz(x) };
bar(y);
}

unconstrained fn baz(x: Field) -> Field {
x
}

fn main(x: Field, y: pub Field) {
/// Safety: test
let x = unsafe { baz(x) };
foo(x);
foo(y);
assert(x != y);
}
3 changes: 2 additions & 1 deletion tooling/debugger/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ pub fn run_repl_session<B: BlackBoxFunctionSolver<FieldElement>>(
solver: &B,
program: CompiledProgram,
initial_witness: WitnessMap<FieldElement>,
raw_source_printing: bool,
) -> Result<Option<WitnessStack<FieldElement>>, NargoError<FieldElement>> {
repl::run(solver, program, initial_witness)
repl::run(solver, program, initial_witness, raw_source_printing)
}

pub fn run_dap_loop<R: Read, W: Write, B: BlackBoxFunctionSolver<FieldElement>>(
Expand Down
15 changes: 13 additions & 2 deletions tooling/debugger/src/repl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ pub struct ReplDebugger<'a, B: BlackBoxFunctionSolver<FieldElement>> {

// Brillig functions referenced from the ACIR circuits above
unconstrained_functions: &'a [BrilligBytecode<FieldElement>],

// whether to print the source without highlighting / pretty-printing
raw_source_printing: bool,
}

impl<'a, B: BlackBoxFunctionSolver<FieldElement>> ReplDebugger<'a, B> {
Expand All @@ -41,6 +44,7 @@ impl<'a, B: BlackBoxFunctionSolver<FieldElement>> ReplDebugger<'a, B> {
debug_artifact: &'a DebugArtifact,
initial_witness: WitnessMap<FieldElement>,
unconstrained_functions: &'a [BrilligBytecode<FieldElement>],
raw_source_printing: bool,
) -> Self {
let foreign_call_executor = Box::new(DefaultDebugForeignCallExecutor::from_artifact(
PrintOutput::Stdout,
Expand Down Expand Up @@ -68,6 +72,7 @@ impl<'a, B: BlackBoxFunctionSolver<FieldElement>> ReplDebugger<'a, B> {
initial_witness,
last_result,
unconstrained_functions,
raw_source_printing,
}
}

Expand Down Expand Up @@ -97,7 +102,11 @@ impl<'a, B: BlackBoxFunctionSolver<FieldElement>> ReplDebugger<'a, B> {
}
}
let locations = self.context.get_source_location_for_debug_location(&location);
print_source_code_location(self.debug_artifact, &locations);
print_source_code_location(
self.debug_artifact,
&locations,
self.raw_source_printing,
);
}
}
}
Expand Down Expand Up @@ -125,7 +134,7 @@ impl<'a, B: BlackBoxFunctionSolver<FieldElement>> ReplDebugger<'a, B> {
}
}
let locations = self.context.get_source_location_for_debug_location(debug_location);
print_source_code_location(self.debug_artifact, &locations);
print_source_code_location(self.debug_artifact, &locations, self.raw_source_printing);
}

pub fn show_current_call_stack(&self) {
Expand Down Expand Up @@ -427,6 +436,7 @@ pub fn run<B: BlackBoxFunctionSolver<FieldElement>>(
blackbox_solver: &B,
program: CompiledProgram,
initial_witness: WitnessMap<FieldElement>,
raw_source_printing: bool,
) -> Result<Option<WitnessStack<FieldElement>>, NargoError<FieldElement>> {
let circuits = &program.program.functions;
let debug_artifact =
Expand All @@ -438,6 +448,7 @@ pub fn run<B: BlackBoxFunctionSolver<FieldElement>>(
debug_artifact,
initial_witness,
unconstrained_functions,
raw_source_printing,
));
let ref_context = &context;

Expand Down
34 changes: 29 additions & 5 deletions tooling/debugger/src/source_code_printer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,11 @@ struct LocationPrintContext {
// Given a DebugArtifact and an OpcodeLocation, prints all the source code
// locations the OpcodeLocation maps to, with some surrounding context and
// visual aids to highlight the location itself.
pub(super) fn print_source_code_location(debug_artifact: &DebugArtifact, locations: &[Location]) {
pub(super) fn print_source_code_location(
debug_artifact: &DebugArtifact,
locations: &[Location],
raw_source_printing: bool,
) {
let locations = locations.iter();

for loc in locations {
Expand All @@ -41,9 +45,11 @@ pub(super) fn print_source_code_location(debug_artifact: &DebugArtifact, locatio
for line in lines {
match line {
PrintedLine::Skip => {}
PrintedLine::Ellipsis { line_number } => print_ellipsis(line_number),
PrintedLine::Ellipsis { line_number } => {
print_ellipsis(line_number, raw_source_printing)
}
PrintedLine::Content { line_number, cursor, content, highlight } => {
print_content(line_number, cursor, content, highlight)
print_content(line_number, cursor, content, highlight, raw_source_printing)
}
}
}
Expand All @@ -57,11 +63,29 @@ fn print_location_path(debug_artifact: &DebugArtifact, loc: Location) {
println!("At {}:{line_number}:{column_number}", debug_artifact.name(loc.file).unwrap());
}

fn print_ellipsis(line_number: usize) {
fn print_ellipsis(line_number: usize, raw_source_printing: bool) {
if raw_source_printing {
println!("...");
return;
}

println!("{:>3} {:2} {}", line_number.dimmed(), "", "...".dimmed());
}

fn print_content(line_number: usize, cursor: &str, content: &str, highlight: Option<Range<usize>>) {
fn print_content(
line_number: usize,
cursor: &str,
content: &str,
highlight: Option<Range<usize>>,
raw_source_printing: bool,
) {
if raw_source_printing {
if cursor == "->" && highlight.is_some() {
println!("{}", content);
}
return;
}

match highlight {
Some(highlight) => {
println!(
Expand Down
118 changes: 118 additions & 0 deletions tooling/debugger/tests/debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,122 @@ mod tests {
// Exit the bash session.
dbg_session.send_line("exit").expect("Failed to quit bash session");
}

#[test]
fn debugger_expected_call_stack() {
let nargo_bin =
cargo_bin("nargo").into_os_string().into_string().expect("Cannot parse nargo path");

let timeout_seconds = 30;
let mut dbg_session =
spawn_bash(Some(timeout_seconds * 1000)).expect("Could not start bash session");

let test_program_path = std::path::Path::new(env!("CARGO_MANIFEST_DIR"))
.join("../../test_programs/execution_success/regression_7195");
let test_program_dir = test_program_path.display();

// Start debugger and test that it loads for the given program.
dbg_session
.execute(
&format!(
"{nargo_bin} debug --raw-source-printing true --program-dir {test_program_dir} --force-brillig --expression-width 3"
),
".*\\Starting debugger.*",
)
.expect("Could not start debugger");

let num_steps = 16;
for step_number in 1..=num_steps {
// While running the debugger, issue a "next" cmd,
// which should run to the program to the next source line given
// we haven't set any breakpoints.
// ">" is the debugger's prompt, so finding one
// after running "next" indicates that the
// debugger has not panicked for this step.
dbg_session
.send_line("next")
.expect("Debugger panicked while attempting to step through program.");
dbg_session
.exp_string(">")
.expect("Failed while waiting for debugger to step through program.");

if step_number == num_steps {
let mut lines = vec![];
while let Ok(line) = dbg_session.read_line() {
if !(line.starts_with(">next")
|| line.starts_with("At ")
|| line.starts_with("..."))
{
lines.push(line);
}
}

let lines_expected_to_contain: Vec<&str> = vec![
"> next",
" let x = unsafe { baz(x) };",
"unconstrained fn baz(x: Field) -> Field {",
"> next",
" let x = unsafe { baz(x) };",
"unconstrained fn baz(x: Field) -> Field {",
"> next",
" let x = unsafe { baz(x) };",
"}",
"> next",
" let x = unsafe { baz(x) };",
"> next",
" foo(x);",
"fn foo(x: Field) {",
"> next",
" foo(x);",
"fn foo(x: Field) {",
"> next",
" foo(x);",
" let y = unsafe { baz(x) };",
"unconstrained fn baz(x: Field) -> Field {",
"> next",
" foo(x);",
" let y = unsafe { baz(x) };",
"unconstrained fn baz(x: Field) -> Field {",
"> next",
" foo(x);",
" let y = unsafe { baz(x) };",
"}",
"> next",
" foo(x);",
" let y = unsafe { baz(x) };",
"> next",
" foo(x);",
" bar(y);",
"fn bar(y: Field) {",
"> next",
" foo(x);",
" bar(y);",
"fn bar(y: Field) {",
"> next",
" foo(x);",
" bar(y);",
" assert(y != 0);",
];

for (line, line_expected_to_contain) in
lines.into_iter().zip(lines_expected_to_contain)
{
let ascii_line: String = line.chars().filter(char::is_ascii).collect();
let line_expected_to_contain = line_expected_to_contain.trim_start();
assert!(
ascii_line.contains(line_expected_to_contain),
"{:?}\ndid not contain\n{:?}",
ascii_line,
line_expected_to_contain,
);
}
}
}

// Run the "quit" command
dbg_session.send_line("quit").expect("Failed to quit debugger");

// Exit the bash session.
dbg_session.send_line("exit").expect("Failed to quit bash session");
}
}
20 changes: 17 additions & 3 deletions tooling/nargo_cli/src/cli/debug_cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ pub(crate) struct DebugCommand {
/// Disable vars debug instrumentation (enabled by default)
#[clap(long)]
skip_instrumentation: Option<bool>,

/// Raw string printing of source for testing
#[clap(long, hide = true, default_value = "false")]
raw_source_printing: Option<bool>,
}

pub(crate) fn run(args: DebugCommand, config: NargoConfig) -> Result<(), CliError> {
Expand Down Expand Up @@ -92,6 +96,7 @@ pub(crate) fn run(args: DebugCommand, config: NargoConfig) -> Result<(), CliErro
&args.witness_name,
target_dir,
args.compile_options.pedantic_solving,
args.raw_source_printing.unwrap_or(false),
)
}

Expand Down Expand Up @@ -180,14 +185,20 @@ fn run_async(
witness_name: &Option<String>,
target_dir: &PathBuf,
pedantic_solving: bool,
raw_source_printing: bool,
) -> Result<(), CliError> {
use tokio::runtime::Builder;
let runtime = Builder::new_current_thread().enable_all().build().unwrap();

runtime.block_on(async {
println!("[{}] Starting debugger", package.name);
let (return_value, witness_stack) =
debug_program_and_decode(program, package, prover_name, pedantic_solving)?;
let (return_value, witness_stack) = debug_program_and_decode(
program,
package,
prover_name,
pedantic_solving,
raw_source_printing,
)?;

if let Some(solved_witness_stack) = witness_stack {
println!("[{}] Circuit witness successfully solved", package.name);
Expand Down Expand Up @@ -215,12 +226,13 @@ fn debug_program_and_decode(
package: &Package,
prover_name: &str,
pedantic_solving: bool,
raw_source_printing: bool,
) -> Result<(Option<InputValue>, Option<WitnessStack<FieldElement>>), CliError> {
// Parse the initial witness values from Prover.toml
let (inputs_map, _) =
read_inputs_from_file(&package.root_dir, prover_name, Format::Toml, &program.abi)?;
let program_abi = program.abi.clone();
let witness_stack = debug_program(program, &inputs_map, pedantic_solving)?;
let witness_stack = debug_program(program, &inputs_map, pedantic_solving, raw_source_printing)?;

match witness_stack {
Some(witness_stack) => {
Expand All @@ -239,13 +251,15 @@ pub(crate) fn debug_program(
compiled_program: CompiledProgram,
inputs_map: &InputMap,
pedantic_solving: bool,
raw_source_printing: bool,
) -> Result<Option<WitnessStack<FieldElement>>, CliError> {
let initial_witness = compiled_program.abi.encode(inputs_map, None)?;

noir_debugger::run_repl_session(
&Bn254BlackBoxSolver(pedantic_solving),
compiled_program,
initial_witness,
raw_source_printing,
)
.map_err(CliError::from)
}
Loading