Skip to content

Commit

Permalink
Merge 4d7453c into d416039
Browse files Browse the repository at this point in the history
  • Loading branch information
ChrisRega committed Oct 28, 2022
2 parents d416039 + 4d7453c commit 7bf2cc7
Show file tree
Hide file tree
Showing 4 changed files with 145 additions and 2 deletions.
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ itertools = "0.10"
tera = "1.17"
md5 = "0.7.0"
tempdir = "0.3"
sha2 = "0.10.6"
data-encoding = "2.3.2"

[target.'cfg(windows)'.dependencies]
ansi_term = "0.12"
Expand Down
34 changes: 32 additions & 2 deletions config_scheme.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Config",
"title": "ConfigurationFile",
"type": "object",
"required": [
"rules"
Expand Down Expand Up @@ -71,6 +71,23 @@
}
}
},
"HashConfig": {
"type": "object",
"required": [
"hash"
],
"properties": {
"hash": {
"$ref": "#/definitions/HashFunction"
}
}
},
"HashFunction": {
"type": "string",
"enum": [
"Sha256"
]
},
"ImageCompareConfig": {
"type": "object",
"required": [
Expand Down Expand Up @@ -149,7 +166,7 @@
"additionalProperties": false
},
{
"description": "stupid text compare",
"description": "plain text compare",
"type": "object",
"required": [
"PlainText"
Expand All @@ -160,6 +177,19 @@
}
},
"additionalProperties": false
},
{
"description": "Compare using file hashes",
"type": "object",
"required": [
"Hash"
],
"properties": {
"Hash": {
"$ref": "#/definitions/HashConfig"
}
},
"additionalProperties": false
}
],
"required": [
Expand Down
104 changes: 104 additions & 0 deletions src/hash.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
use crate::{report, Deserialize, Serialize};
use data_encoding::HEXLOWER;

use schemars_derive::JsonSchema;
use std::fs::File;
use std::io::Read;
use std::path::Path;

#[derive(Debug, Deserialize, Serialize, JsonSchema)]
pub enum HashFunction {
Sha256,
}

impl HashFunction {
fn hash_file(&self, mut file: impl Read) -> [u8; 32] {
match self {
Self::Sha256 => {
use sha2::{Digest, Sha256};
use std::io;

let mut hasher = Sha256::new();

let _ = io::copy(&mut file, &mut hasher).expect("Could not open file to hash");
let hash_bytes = hasher.finalize();
hash_bytes.into()
}
}
}
}

#[derive(Debug, Deserialize, Serialize, JsonSchema)]
pub struct HashConfig {
hash: HashFunction,
}

impl Default for HashConfig {
fn default() -> Self {
HashConfig {
hash: HashFunction::Sha256,
}
}
}

pub fn compare_files<P: AsRef<Path>>(
actual_path: P,
nominal_path: P,
config: &HashConfig,
rule_name: &str,
) -> report::FileCompareResult {
let act = config.hash.hash_file(
File::open(actual_path.as_ref()).expect("Could not open actual file for hashing"),
);
let nom = config.hash.hash_file(
File::open(nominal_path.as_ref()).expect("Could not open actual file for hashing"),
);

let diff = if act != nom {
vec![format!(
"Nominal file's hash is '{}' actual is '{}'",
HEXLOWER.encode(&act),
HEXLOWER.encode(&nom)
)]
} else {
vec![]
};

report::write_html_detail(nominal_path, actual_path, diff.as_slice(), rule_name)
}

#[cfg(test)]
mod test {
use super::*;
use crate::hash::HashFunction::Sha256;

#[test]
fn identity() {
let f1 = Sha256.hash_file(File::open("tests/integ.rs").unwrap());
let f2 = Sha256.hash_file(File::open("tests/integ.rs").unwrap());
assert_eq!(f1, f2);
}

#[test]
fn hash_pinning() {
let sum = "bc3abb411d305c4436185c474be3db2608e910612a573f6791b143d7d749b699";
let f1 = Sha256.hash_file(File::open("tests/integ/data/images/diff_100_DPI.png").unwrap());
assert_eq!(HEXLOWER.encode(&f1), sum);
}

#[test]
fn identity_outer() {
let file = "tests/integ.rs";
let result = compare_files(file, file, &HashConfig::default(), "test");
assert!(!result.is_error);
}

#[test]
fn different_files_throw_outer() {
let file_act = "tests/integ/data/images/actual/SaveImage_100DPI_default_size.jpg";
let file_nominal = "tests/integ/data/images/expected/SaveImage_100DPI_default_size.jpg";

let result = compare_files(file_act, file_nominal, &HashConfig::default(), "test");
assert!(result.is_error);
}
}
7 changes: 7 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@
#![deny(deprecated)]

mod csv;
mod hash;
mod html;
mod image;
mod report;

use crate::hash::HashConfig;
use crate::html::HTMLCompareConfig;
use crate::report::FileCompareResult;
use schemars::schema_for;
Expand All @@ -30,6 +32,8 @@ enum ComparisonMode {
Image(image::ImageCompareConfig),
/// plain text compare
PlainText(HTMLCompareConfig),
/// Compare using file hashes
Hash(HashConfig),
}

#[derive(Debug, Deserialize, Serialize, JsonSchema)]
Expand Down Expand Up @@ -92,6 +96,9 @@ fn process_file(
ComparisonMode::PlainText(conf) => {
html::compare_files(nominal.as_ref(), actual.as_ref(), conf, &rule.name)
}
ComparisonMode::Hash(conf) => {
hash::compare_files(nominal.as_ref(), actual.as_ref(), conf, &rule.name)
}
};

if compare_result.is_error {
Expand Down

0 comments on commit 7bf2cc7

Please sign in to comment.