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
Code coverage support for tests (scrypto coverage command) #1640
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
/target | ||
/coverage |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
use crate::types::*; | ||
use std::env; | ||
use std::fs::{self, File}; | ||
use std::io::Write; | ||
use std::path::Path; | ||
|
||
#[cfg(feature = "coverage")] | ||
pub fn save_coverage_data(blueprint_name: &String, coverage_data: &Vec<u8>) { | ||
if let Some(dir) = env::var_os("COVERAGE_DIRECTORY") { | ||
let mut file_path = Path::new(&dir).to_path_buf(); | ||
file_path.push(blueprint_name); | ||
|
||
// Check if the blueprint directory exists, if not create it | ||
if !file_path.exists() { | ||
// error is ignored because when multiple tests are running it may fail | ||
fs::create_dir(&file_path).ok(); | ||
} | ||
|
||
// Write .profraw binary data | ||
let file_name = hash(&coverage_data); | ||
let file_name: String = file_name.0[..16] | ||
.iter() | ||
.map(|byte| format!("{:02x}", byte)) | ||
.collect(); | ||
file_path.push(format!("{}.profraw", file_name)); | ||
let mut file = File::create(file_path).unwrap(); | ||
file.write_all(&coverage_data).unwrap(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -983,15 +983,18 @@ impl WasmModule { | |
mut self, | ||
rules: &R, | ||
) -> Result<Self, PrepareError> { | ||
let backend = gas_metering::host_function::Injector::new( | ||
MODULE_ENV_NAME, | ||
COSTING_CONSUME_WASM_EXECUTION_UNITS_FUNCTION_NAME, | ||
); | ||
gas_metering::inject(&mut self.module, backend, rules).map_err(|err| { | ||
PrepareError::RejectedByInstructionMetering { | ||
reason: err.to_string(), | ||
} | ||
})?; | ||
#[cfg(not(feature = "coverage"))] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Out of curiosity, did you run into any issue with gas metering ingestion for the coverage-enabled wasm code? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes. When transaction fails for example due to out of gas then dump_coverage cannot be called because it will fail due to out of gas. When this is commented, the function dump_coverage is not using any build-in native functions so it's going to work even in case of transaction failure. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That makes sense. I was hoping it wasn't an error with the instrumentation itself, otherwise we have a problem. All is good. |
||
{ | ||
let backend = gas_metering::host_function::Injector::new( | ||
MODULE_ENV_NAME, | ||
COSTING_CONSUME_WASM_EXECUTION_UNITS_FUNCTION_NAME, | ||
); | ||
gas_metering::inject(&mut self.module, backend, rules).map_err(|err| { | ||
PrepareError::RejectedByInstructionMetering { | ||
reason: err.to_string(), | ||
} | ||
})?; | ||
} | ||
|
||
Ok(self) | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Due to the difference in configuration, some tests may fail in
coverage
mode but not in regular test mode. I guess it's not a big deal for most cases. We will need to make sure the--no-fail-fast
flag is provided when running coverage.