Skip to content

Commit

Permalink
[casr-cluster] --diff option. Get diff between two directories with r…
Browse files Browse the repository at this point in the history
…eports. (#193)
  • Loading branch information
anfedotoff authored Jan 22, 2024
1 parent 4d18827 commit 42b7599
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 16 deletions.
39 changes: 35 additions & 4 deletions casr/src/bin/casr-cluster.rs
Original file line number Diff line number Diff line change
Expand Up @@ -279,18 +279,22 @@ fn deduplication(indir: &Path, outdir: Option<PathBuf>, jobs: usize) -> Result<(
Ok((before, after))
}

/// Merge new reports from input directory into output directory
/// Merge unique reports from `input` directory into `output` directory.
/// If `diff` directory is set, unique (`input` \ `output`) reports are saved
/// in `diff` directory.
///
/// # Arguments
///
/// * `input` - path to directory with new CASR reports
///
/// * `output` - path to output directory with CASR reports
///
/// * `diff` - optional: path to save unique (`input` \ `output`) reports
///
/// # Return value
///
/// Number of merged reports
fn merge_dirs(input: &Path, output: &Path) -> Result<u64> {
fn merge_or_diff(input: &Path, output: &Path, diff: Option<&Path>) -> Result<u64> {
let dir = fs::read_dir(output).with_context(|| {
format!(
"Error occurred while opening directory with CASR reports. Directory: {}",
Expand All @@ -316,12 +320,19 @@ fn merge_dirs(input: &Path, output: &Path) -> Result<u64> {
)
})?;

let save_dir = if let Some(diff) = diff {
fs::create_dir(diff)?;
diff
} else {
output
};

let mut new: u64 = 0;
for entry in dir.flatten() {
if entry.path().extension().is_some() && entry.path().extension().unwrap() == "casrep" {
if let Ok(trace) = stacktrace(entry.path().as_path()) {
if mainhash.insert(trace) {
let target = Path::new(&output).join(entry.file_name());
let target = Path::new(&save_dir).join(entry.file_name());
if target.exists() {
eprintln!(
"File with name {} already exists in OUTPUT_DIR.",
Expand Down Expand Up @@ -408,6 +419,18 @@ fn main() -> Result<()> {
INPUT_DIR will be added to OUTPUT_DIR.",
),
)
.arg(
Arg::new("diff")
.long("diff")
.action(ArgAction::Set)
.num_args(3)
.value_parser(clap::value_parser!(PathBuf))
.value_names(["NEW_DIR", "PREV_DIR", "DIFF_DIR"])
.help(
"Compute report sets difference NEW_DIR \\ PREV_DIR. \
Copy new CASR reports from NEW_DIR into DIFF_DIR.",
),
)
.arg(
Arg::new("ignore")
.long("ignore")
Expand Down Expand Up @@ -474,12 +497,20 @@ fn main() -> Result<()> {
println!("Number of reports after deduplication: {after}");
} else if matches.contains_id("merge") {
let paths: Vec<&PathBuf> = matches.get_many::<PathBuf>("merge").unwrap().collect();
let new = merge_dirs(paths[0], paths[1])?;
let new = merge_or_diff(paths[0], paths[1], None)?;
println!(
"Merged {} new reports into {} directory",
new,
paths[1].display()
);
} else if matches.contains_id("diff") {
let paths: Vec<&PathBuf> = matches.get_many::<PathBuf>("diff").unwrap().collect();
let new = merge_or_diff(paths[0], paths[1], Some(paths[2]))?;
println!(
"Diff of {} new reports is saved into {} directory",
new,
paths[2].display()
);
}

Ok(())
Expand Down
21 changes: 20 additions & 1 deletion casr/tests/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2603,9 +2603,11 @@ fn test_casr_cluster_d_and_m() {
let paths = [
abs_path("tests/casr_tests/casrep/dedup/in"),
abs_path("tests/tmp_tests_casr/dedup_out"),
abs_path("tests/tmp_tests_casr/dedup_diff"),
];

let _ = fs::remove_dir_all(&paths[1]);
let _ = fs::remove_dir_all(&paths[2]);

let output = Command::new(*EXE_CASR_CLUSTER.read().unwrap())
.args(["-d", &paths[0], &paths[1]])
Expand Down Expand Up @@ -2648,7 +2650,24 @@ fn test_casr_cluster_d_and_m() {
"Something went wrong while merging directories"
);

let _ = std::fs::remove_dir_all(&paths[1]);
// Test --diff option
dirvec = match fs::read_dir(&paths[1]) {
Ok(vec) => vec,
Err(why) => {
panic!("{:?}", why.kind());
}
};
let casrep = dirvec.next().unwrap().unwrap().path();
let _ = std::fs::remove_file(casrep);
let output = Command::new(*EXE_CASR_CLUSTER.read().unwrap())
.args(["--diff", &paths[0], &paths[1], &paths[2]])
.output()
.expect("failed to start casr-cluster");
let out = String::from_utf8_lossy(&output.stdout);
assert!(
out.contains("Diff of 1 new reports") && (fs::read_dir(&paths[2]).unwrap().count() == 1),
"Something went wrong while diffing directories"
);
}

#[test]
Expand Down
25 changes: 14 additions & 11 deletions docs/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -170,24 +170,24 @@ Run casr-java:

## casr-js

Create CASR reports (.casrep) from JavaScript reports
Create CASR reports (.casrep) from JavaScript crash reports

Usage: casr-js [OPTIONS] <--stdout|--output <REPORT>> [-- <ARGS>...]

Arguments:
[ARGS]... Add "-- <path> <arguments>" to run

Options:
-o, --output <REPORT> Path to save report. Path can be a directory, then report
name is generated
--stdout Print CASR report to stdout
--stdin <FILE> Stdin file for program
-t, --timeout <SECONDS> Timeout (in seconds) for target execution, 0 value means
that timeout is disabled [default: 0]
--ignore <FILE> File with regular expressions for functions and file paths
that should be ignored
-h, --help Print help
-V, --version Print version
-o, --output <REPORT> Path to save report. Path can be a directory, then report name
is generated
--stdout Print CASR report to stdout
--stdin <FILE> Stdin file for program
-t, --timeout <SECONDS> Timeout (in seconds) for target execution, 0 value means that
timeout is disabled [default: 0]
--ignore <FILE> File with regular expressions for functions and file paths that
should be ignored
-h, --help Print help
-V, --version Print version

Run casr-js:

Expand Down Expand Up @@ -261,6 +261,9 @@ Tool for clustering CASR reports
-m, --merge <INPUT_DIR> <OUTPUT_DIR>
Merge INPUT_DIR into OUTPUT_DIR. Only new CASR reports from INPUT_DIR will be
added to OUTPUT_DIR.
--diff <NEW_DIR> <PREV_DIR> <DIFF_DIR>
Compute report sets difference NEW_DIR \ PREV_DIR. Copy new CASR reports from
NEW_DIR into DIFF_DIR.
--ignore <FILE>
File with regular expressions for functions and file paths that should be
ignored
Expand Down

0 comments on commit 42b7599

Please sign in to comment.