Skip to content

Commit

Permalink
Add json checker
Browse files Browse the repository at this point in the history
  • Loading branch information
ChrisRega committed Oct 4, 2023
1 parent 9e3a76c commit c613c72
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 8 deletions.
15 changes: 8 additions & 7 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
[package]
name = "havocompare"
description = "A flexible rule-based file and folder comparison tool and crate including nice html reporting. Compares CSVs, text files, pdf-texts and images."
description = "A flexible rule-based file and folder comparison tool and crate including nice html reporting. Compares CSVs, JSON, text files, pdf-texts and images."
repository = "https://github.com/VolumeGraphics/havocompare"
homepage = "https://github.com/VolumeGraphics/havocompare"
documentation = "https://docs.rs/havocompare"
version = "0.4.0"
version = "0.5.0"
edition = "2021"
license = "MIT"
authors = ["Volume Graphics GmbH"]
Expand All @@ -18,7 +18,7 @@ path = "src/print_args.rs"


[dependencies]
clap = {version= "4.3", features=["derive"]}
clap = {version= "4.4", features=["derive"]}
chrono = "0.4"
serde = "1.0"
serde_yaml = "0.9"
Expand All @@ -27,7 +27,7 @@ schemars_derive = "0.8"
thiserror = "1.0"
regex = "1.8"
image = "0.24"
image-compare = "0.3.0"
image-compare = "0.3.1"
tracing = "0.1"
tracing-subscriber = "0.3"
serde_json = "1.0"
Expand All @@ -39,14 +39,15 @@ tera = "1.19"
sha2 = "0.10"
data-encoding = "2.4"
permutation = "0.4"
pdf-extract = "0.6"
pdf-extract = "0.7"
vg_errortools = "0.1"
rayon = "1.7.0"
rayon = "1.8.0"
enable-ansi-support = "0.2"
tempfile = "3.6"
tempfile = "3.8"
fs_extra = "1.3"
opener = "0.6"
anyhow = "1.0"
json_diff = {git = "https://github.com/ChrisRega/json-diff"}

[dev-dependencies]
env_logger = "0.10"
Expand Down
28 changes: 28 additions & 0 deletions config_scheme.json
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,21 @@
}
}
},
"JsonConfig": {
"description": "configuration for the json compare module",
"type": "object",
"required": [
"ignore_keys"
],
"properties": {
"ignore_keys": {
"type": "array",
"items": {
"type": "string"
}
}
}
},
"Mode": {
"description": "comparison mode for csv cells",
"oneOf": [
Expand Down Expand Up @@ -457,6 +472,19 @@
},
"additionalProperties": false
},
{
"description": "Compare JSON files",
"type": "object",
"required": [
"Json"
],
"properties": {
"Json": {
"$ref": "#/definitions/JsonConfig"
}
},
"additionalProperties": false
},
{
"description": "Run external comparison executable",
"type": "object",
Expand Down
59 changes: 59 additions & 0 deletions src/json.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
use crate::report::{DiffDetail, Difference};
use crate::Error;
use itertools::Itertools;
use schemars_derive::JsonSchema;
use serde::{Deserialize, Serialize};
use std::path::Path;
use tracing::error;

#[derive(Debug, Deserialize, Serialize, JsonSchema, Clone)]
/// configuration for the json compare module
pub struct JsonConfig {
ignore_keys: Vec<String>,
}

pub(crate) fn compare_files<P: AsRef<Path>>(
nominal: P,
actual: P,
config: &JsonConfig,
) -> Result<Difference, Error> {
let mut diff = Difference::new_for_file(&nominal, &actual);
let compared_file_name = nominal.as_ref().to_string_lossy().into_owned();

let nominal = vg_errortools::fat_io_wrap_std(&nominal, &std::fs::read_to_string)?;
let actual = vg_errortools::fat_io_wrap_std(&actual, &std::fs::read_to_string)?;

let json_diff = json_diff::process::compare_jsons(&nominal, &actual);
let json_diff = match json_diff {
Ok(diff) => diff,
Err(e) => {
let error_message =
format!("JSON deserialization failed for {compared_file_name} (error: {e})");
error!("{}", error_message);
diff.push_detail(DiffDetail::Error(error_message));
diff.error();
return Ok(diff);
}
};
let filtered_diff: Vec<_> = json_diff
.all_diffs()
.into_iter()
.filter(|(_d, v)| !config.ignore_keys.contains(v))
.collect();

if !filtered_diff.is_empty() {
let all_diffs_log = filtered_diff.iter().map(|(_, v)| v).join("\n");
diff.push_detail(DiffDetail::External {
stdout: all_diffs_log,
stderr: String::new(),
});

diff.error();
}

for (d_type, key) in filtered_diff {
error!("{d_type}: {key}");
}

Ok(diff)
}
9 changes: 9 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ mod pdf;
mod properties;
mod report;

mod json;
pub use crate::json::JsonConfig;

use crate::external::ExternalConfig;
pub use crate::html::HTMLCompareConfig;
use crate::properties::PropertiesConfig;
Expand Down Expand Up @@ -93,6 +96,9 @@ pub enum ComparisonMode {
/// Compare file-properties
FileProperties(PropertiesConfig),

/// Compare JSON files
Json(JsonConfig),

/// Run external comparison executable
External(ExternalConfig),
}
Expand Down Expand Up @@ -194,6 +200,9 @@ fn process_file(nominal: impl AsRef<Path>, actual: impl AsRef<Path>, rule: &Rule
external::compare_files(nominal.as_ref(), actual.as_ref(), conf)
.map_err(|e| e.into())
}
ComparisonMode::Json(conf) => {
json::compare_files(nominal.as_ref(), actual.as_ref(), conf).map_err(|e| e.into())
}
}
};
let compare_result = match compare_result {
Expand Down
2 changes: 1 addition & 1 deletion src/report/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -703,7 +703,7 @@ pub(crate) fn create_html(
)
.unwrap_or_else(|e| log_detail_html_creation_error(&e))
}
ComparisonMode::External(_) => {
ComparisonMode::External(_) | ComparisonMode::Json(_) => {
if let Some((stdout, stderr)) = file
.detail
.iter()
Expand Down

0 comments on commit c613c72

Please sign in to comment.