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

[casr-cluster] --diff option. Get diff between two directories with reports. #193

Merged
merged 4 commits into from
Jan 22, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
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
41 changes: 36 additions & 5 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
/// * `input` - path to directory with previous CASR reports
SweetVishnya marked this conversation as resolved.
Show resolved Hide resolved
///
/// * `diff` - optional: path to save unique (`input` \ `output`) reports
///
/// # Return value
///
/// Number of merged reports
fn merge_dirs(input: &Path, output: &Path) -> Result<u64> {
anfedotoff marked this conversation as resolved.
Show resolved Hide resolved
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
Loading