From bf689303d4ed81450f555a25114634c7d14dc542 Mon Sep 17 00:00:00 2001 From: Richard Patel Date: Sun, 13 Feb 2022 18:50:22 +0100 Subject: [PATCH] rbpf-cli: support json output --- rbpf-cli/src/main.rs | 63 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 52 insertions(+), 11 deletions(-) diff --git a/rbpf-cli/src/main.rs b/rbpf-cli/src/main.rs index be056248f..210bb971e 100644 --- a/rbpf-cli/src/main.rs +++ b/rbpf-cli/src/main.rs @@ -19,10 +19,11 @@ use { transaction_context::TransactionContext, }, std::{ + fmt::{Debug, Formatter}, fs::File, io::{Read, Seek, SeekFrom}, path::Path, - time::Instant, + time::{Duration, Instant}, }, }; @@ -43,10 +44,10 @@ struct Input { fn load_accounts(path: &Path) -> Result { let file = File::open(path).unwrap(); let input: Input = serde_json::from_reader(file)?; - println!("Program input:"); - println!("accounts {:?}", &input.accounts); - println!("instruction_data {:?}", &input.instruction_data); - println!("----------------------------------------"); + eprintln!("Program input:"); + eprintln!("accounts {:?}", &input.accounts); + eprintln!("instruction_data {:?}", &input.instruction_data); + eprintln!("----------------------------------------"); Ok(input) } @@ -157,6 +158,15 @@ native machine code before execting it in the virtual machine.", .short('v') .long("verify"), ) + .arg( + Arg::new("output_format") + .about("Return information in specified output format") + .long("output") + .value_name("FORMAT") + .global(true) + .takes_value(true) + .possible_values(&["json", "json-compact"]), + ) .get_matches(); let config = Config { @@ -286,7 +296,6 @@ native machine code before execting it in the virtual machine.", &account_lengths, ) .unwrap(); - println!("Program output:"); let start_time = Instant::now(); let result = if matches.value_of("use").unwrap() == "interpreter" { vm.execute_program_interpreted(&mut instruction_meter) @@ -294,17 +303,33 @@ native machine code before execting it in the virtual machine.", vm.execute_program_jit(&mut instruction_meter) }; let duration = Instant::now() - start_time; - println!("Result: {:?}", result); - println!("Instruction Count: {}", vm.get_total_instruction_count()); - println!("Execution time: {} us", duration.as_micros()); + + let output = Output { + result: format!("{:?}", result), + instruction_count: vm.get_total_instruction_count(), + execution_time: duration, + }; + match matches.value_of("output_format") { + Some("json") => { + println!("{}", serde_json::to_string_pretty(&output).unwrap()); + } + Some("json-compact") => { + println!("{}", serde_json::to_string(&output).unwrap()); + } + _ => { + println!("Program output:"); + println!("{:?}", output); + } + } + if matches.is_present("trace") { - println!("Trace is saved in trace.out"); + eprintln!("Trace is saved in trace.out"); let mut file = File::create("trace.out").unwrap(); let analysis = Analysis::from_executable(&executable); vm.get_tracer().write(&mut file, &analysis).unwrap(); } if matches.is_present("profile") { - println!("Profile is saved in profile.dot"); + eprintln!("Profile is saved in profile.dot"); let tracer = &vm.get_tracer(); let dynamic_analysis = DynamicAnalysis::new(tracer, &analysis); let mut file = File::create("profile.dot").unwrap(); @@ -313,3 +338,19 @@ native machine code before execting it in the virtual machine.", .unwrap(); } } + +#[derive(Serialize)] +struct Output { + result: String, + instruction_count: u64, + execution_time: Duration, +} + +impl Debug for Output { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + writeln!(f, "Result: {}", self.result)?; + writeln!(f, "Instruction Count: {}", self.instruction_count)?; + writeln!(f, "Execution time: {} us", self.execution_time.as_micros())?; + Ok(()) + } +}