From 7eb392c8533e95208eb8736190f3f0836f8eb570 Mon Sep 17 00:00:00 2001 From: ok-nick Date: Mon, 5 Aug 2024 17:42:13 -0400 Subject: [PATCH] Revert diffing c test --- .github/workflows/compat.yml | 10 ++--- c2pa-compat/Cargo.toml | 1 - c2pa-compat/src/main.rs | 38 ++++++++++++------ sdk/Cargo.toml | 2 +- sdk/tests/compat.rs | 22 +++++----- .../fixtures/compat/0.33.0/bmff/embedded.c2pa | Bin 13419 -> 13419 bytes .../compat/0.33.0/bmff/embedded.expected | Bin 811373 -> 0 bytes .../fixtures/compat/0.33.0/bmff/embedded.json | 2 +- .../{embedded.actually => embedded.original} | Bin 811373 -> 811373 bytes .../compat/0.33.0/bmff/embedded.patch | Bin 1514 -> 4476 bytes .../fixtures/compat/0.33.0/bmff/remote.c2pa | Bin 13419 -> 13419 bytes .../fixtures/compat/0.33.0/bmff/remote.json | 2 +- .../fixtures/compat/0.33.0/bmff/remote.patch | Bin 395 -> 3691 bytes sdk/tests/fixtures/compat/0.33.0/bmff/test | Bin 395 -> 0 bytes .../compat/0.33.0/compat-details.json | 2 +- .../compat/0.33.0/gif/embedded.actually | Bin 753333 -> 0 bytes .../fixtures/compat/0.33.0/gif/embedded.c2pa | Bin 12794 -> 12794 bytes .../fixtures/compat/0.33.0/gif/embedded.json | 2 +- .../{embedded.expected => embedded.original} | Bin 753333 -> 753333 bytes .../fixtures/compat/0.33.0/gif/embedded.patch | Bin 2094 -> 4808 bytes .../fixtures/compat/0.33.0/gif/remote.c2pa | Bin 12794 -> 12794 bytes .../fixtures/compat/0.33.0/gif/remote.json | 2 +- .../fixtures/compat/0.33.0/gif/remote.patch | Bin 964 -> 3582 bytes sdk/tests/fixtures/compat/0.33.0/gif/test | Bin 964 -> 0 bytes .../fixtures/compat/0.33.0/jpeg/embedded.c2pa | Bin 12795 -> 12795 bytes .../compat/0.33.0/jpeg/embedded.expected | Bin 99441 -> 0 bytes .../fixtures/compat/0.33.0/jpeg/embedded.json | 2 +- .../{embedded.actually => embedded.original} | Bin 99441 -> 99441 bytes .../compat/0.33.0/jpeg/embedded.patch | Bin 1315 -> 1571 bytes .../fixtures/compat/0.33.0/jpeg/remote.c2pa | Bin 12794 -> 12794 bytes .../fixtures/compat/0.33.0/jpeg/remote.json | 2 +- .../fixtures/compat/0.33.0/jpeg/remote.patch | Bin 486 -> 735 bytes sdk/tests/fixtures/compat/0.33.0/jpeg/test | Bin 486 -> 0 bytes .../fixtures/compat/0.33.0/mp3/embedded.c2pa | Bin 12794 -> 12794 bytes .../compat/0.33.0/mp3/embedded.expected | Bin 1967065 -> 0 bytes .../fixtures/compat/0.33.0/mp3/embedded.json | 2 +- .../{embedded.actually => embedded.original} | Bin 1967065 -> 1967065 bytes .../fixtures/compat/0.33.0/mp3/embedded.patch | Bin 2073 -> 9611 bytes .../fixtures/compat/0.33.0/mp3/remote.c2pa | Bin 12795 -> 12795 bytes .../fixtures/compat/0.33.0/mp3/remote.json | 2 +- .../fixtures/compat/0.33.0/mp3/remote.patch | Bin 541 -> 8076 bytes sdk/tests/fixtures/compat/0.33.0/mp3/test | Bin 541 -> 0 bytes .../fixtures/compat/0.33.0/png/embedded.c2pa | Bin 12793 -> 12793 bytes .../compat/0.33.0/png/embedded.expected | Bin 16505 -> 0 bytes .../fixtures/compat/0.33.0/png/embedded.json | 2 +- .../{embedded.actually => embedded.original} | Bin 16505 -> 16505 bytes .../fixtures/compat/0.33.0/png/embedded.patch | Bin 1965 -> 1788 bytes .../fixtures/compat/0.33.0/png/remote.c2pa | Bin 12793 -> 12793 bytes .../fixtures/compat/0.33.0/png/remote.json | 2 +- .../fixtures/compat/0.33.0/png/remote.patch | Bin 505 -> 433 bytes sdk/tests/fixtures/compat/0.33.0/png/test | Bin 505 -> 0 bytes .../compat/0.33.0/svg/embedded.actually | 10 ----- .../fixtures/compat/0.33.0/svg/embedded.c2pa | Bin 12799 -> 0 bytes .../compat/0.33.0/svg/embedded.expected | 10 ----- .../fixtures/compat/0.33.0/svg/embedded.json | 1 - .../fixtures/compat/0.33.0/svg/embedded.patch | Bin 2430 -> 0 bytes .../fixtures/compat/0.33.0/tiff/embedded.c2pa | Bin 12790 -> 12790 bytes .../compat/0.33.0/tiff/embedded.expected | Bin 218642 -> 0 bytes .../fixtures/compat/0.33.0/tiff/embedded.json | 2 +- .../{embedded.actually => embedded.original} | Bin 218642 -> 218642 bytes .../compat/0.33.0/tiff/embedded.patch | Bin 2019 -> 2642 bytes .../fixtures/compat/0.33.0/tiff/remote.c2pa | Bin 12790 -> 12790 bytes .../fixtures/compat/0.33.0/tiff/remote.json | 2 +- .../fixtures/compat/0.33.0/tiff/remote.patch | Bin 534 -> 1254 bytes sdk/tests/fixtures/compat/0.33.0/tiff/test | Bin 534 -> 0 bytes 65 files changed, 55 insertions(+), 65 deletions(-) delete mode 100644 sdk/tests/fixtures/compat/0.33.0/bmff/embedded.expected rename sdk/tests/fixtures/compat/0.33.0/bmff/{embedded.actually => embedded.original} (99%) delete mode 100644 sdk/tests/fixtures/compat/0.33.0/bmff/test delete mode 100644 sdk/tests/fixtures/compat/0.33.0/gif/embedded.actually rename sdk/tests/fixtures/compat/0.33.0/gif/{embedded.expected => embedded.original} (99%) delete mode 100644 sdk/tests/fixtures/compat/0.33.0/gif/test delete mode 100644 sdk/tests/fixtures/compat/0.33.0/jpeg/embedded.expected rename sdk/tests/fixtures/compat/0.33.0/jpeg/{embedded.actually => embedded.original} (99%) delete mode 100644 sdk/tests/fixtures/compat/0.33.0/jpeg/test delete mode 100644 sdk/tests/fixtures/compat/0.33.0/mp3/embedded.expected rename sdk/tests/fixtures/compat/0.33.0/mp3/{embedded.actually => embedded.original} (99%) delete mode 100644 sdk/tests/fixtures/compat/0.33.0/mp3/test delete mode 100644 sdk/tests/fixtures/compat/0.33.0/png/embedded.expected rename sdk/tests/fixtures/compat/0.33.0/png/{embedded.actually => embedded.original} (98%) delete mode 100644 sdk/tests/fixtures/compat/0.33.0/png/test delete mode 100644 sdk/tests/fixtures/compat/0.33.0/svg/embedded.actually delete mode 100644 sdk/tests/fixtures/compat/0.33.0/svg/embedded.c2pa delete mode 100644 sdk/tests/fixtures/compat/0.33.0/svg/embedded.expected delete mode 100644 sdk/tests/fixtures/compat/0.33.0/svg/embedded.json delete mode 100644 sdk/tests/fixtures/compat/0.33.0/svg/embedded.patch delete mode 100644 sdk/tests/fixtures/compat/0.33.0/tiff/embedded.expected rename sdk/tests/fixtures/compat/0.33.0/tiff/{embedded.actually => embedded.original} (99%) delete mode 100644 sdk/tests/fixtures/compat/0.33.0/tiff/test diff --git a/.github/workflows/compat.yml b/.github/workflows/compat.yml index 7875bcc40..aecbb7ef3 100644 --- a/.github/workflows/compat.yml +++ b/.github/workflows/compat.yml @@ -24,11 +24,11 @@ jobs: - name: Create compat snapshot run: cargo run -p c2pa-compat - - name: Get the latest tag - run: | - git fetch --tags origin - LATEST_TAG=$(git describe --tags $(git rev-list --tags --max-count=1)) - echo "LATEST_TAG=${LATEST_TAG}" >> $GITHUB_ENV + # - name: Get the latest tag + # run: | + # git fetch --tags origin + # LATEST_TAG=$(git describe --tags $(git rev-list --tags --max-count=1)) + # echo "LATEST_TAG=${LATEST_TAG}" >> $GITHUB_ENV # - name: Send compat PR # uses: peter-evans/create-pull-request@v6 diff --git a/c2pa-compat/Cargo.toml b/c2pa-compat/Cargo.toml index f69480f2c..a1fc91453 100644 --- a/c2pa-compat/Cargo.toml +++ b/c2pa-compat/Cargo.toml @@ -16,5 +16,4 @@ serde_json = "1.0.117" ed25519-dalek = "2.1.1" pem = "3.0.2" bsdiff = "0.2.0" -qbsdiff = "1.4" lz4_flex = "0.11.3" diff --git a/c2pa-compat/src/main.rs b/c2pa-compat/src/main.rs index 12475a6d3..7d0f97a95 100644 --- a/c2pa-compat/src/main.rs +++ b/c2pa-compat/src/main.rs @@ -18,7 +18,6 @@ use std::{ }; use c2pa::{Builder, CallbackSigner, Error, Reader, Result, SigningAlg}; -use qbsdiff::{Bsdiff, Bspatch}; use serde::Serialize; // const FULL_MANIFEST: &str = include_str!("./full-manifest.json"); @@ -76,7 +75,7 @@ fn main() -> Result<()> { let mut details = CompatDetails::new(vec![ CompatAssetDetails::new("C.jpg", "jpeg"), CompatAssetDetails::new("sample1.gif", "gif"), - CompatAssetDetails::new("sample1.svg", "svg"), + // CompatAssetDetails::new("sample1.svg", "svg"), CompatAssetDetails::new("video1.mp4", "bmff"), // CompatAssetDetails::new("sample1.wav", "riff"), // TODO: https://github.com/contentauth/c2pa-rs/issues/530 CompatAssetDetails::new("sample1.mp3", "mp3"), @@ -150,11 +149,14 @@ fn main() -> Result<()> { )?; let mut signed_remote_asset_patch = Vec::new(); - Bsdiff::new(&original_asset, &signed_remote_asset.into_inner()) - .compare(&mut signed_remote_asset_patch) - .expect("TODO"); + bsdiff::diff( + &original_asset, + &signed_remote_asset.into_inner(), + &mut signed_remote_asset_patch, + ) + .expect("TODO"); asset_details.uncompressed_remote_size = Some(signed_remote_asset_patch.len()); - // let signed_remote_asset_patch = lz4_flex::compress(&signed_remote_asset_patch); + let signed_remote_asset_patch = lz4_flex::compress(&signed_remote_asset_patch); fs::write(dir_path.join("remote.patch"), signed_remote_asset_patch)?; fs::write(dir_path.join("remote.c2pa"), remote_c2pa_manifest)?; @@ -165,14 +167,26 @@ fn main() -> Result<()> { Err(err) => return Err(err), } - let t = signed_embedded_asset.into_inner(); - let mut signed_embedded_asset_patch = Vec::new(); - Bsdiff::new(&original_asset, &t) - .compare(&mut signed_embedded_asset_patch) - .expect("TODO"); + bsdiff::diff( + &original_asset, + &signed_embedded_asset.into_inner(), + &mut signed_embedded_asset_patch, + ) + .expect("TODO"); + + // TODO: temporary for testing + let mut original = Vec::new(); + bsdiff::patch( + &original_asset, + &mut Cursor::new(&mut signed_embedded_asset_patch), + &mut original, + ) + .unwrap(); + fs::write(dir_path.join("embedded.original"), original)?; + asset_details.uncompressed_embedded_size = Some(signed_embedded_asset_patch.len()); - // let signed_embedded_asset_patch = lz4_flex::compress(&signed_embedded_asset_patch); + let signed_embedded_asset_patch = lz4_flex::compress(&signed_embedded_asset_patch); fs::write(dir_path.join("embedded.patch"), signed_embedded_asset_patch)?; fs::write(dir_path.join("embedded.c2pa"), embedded_c2pa_manifest)?; diff --git a/sdk/Cargo.toml b/sdk/Cargo.toml index 01967b9ad..6b5317e0d 100644 --- a/sdk/Cargo.toml +++ b/sdk/Cargo.toml @@ -168,7 +168,7 @@ c2pa = { path = ".", features = [ jumbf = "0.4.0" insta = { version = "1.39.0", features = ["json", "redactions", "filters"] } tiny_http = "0.12.0" -qbsdiff = "1.4" +bsdiff = "0.2.0" lz4_flex = "0.11.3" [target.'cfg(target_arch = "wasm32")'.dev-dependencies] diff --git a/sdk/tests/compat.rs b/sdk/tests/compat.rs index 09d217115..7317c715f 100644 --- a/sdk/tests/compat.rs +++ b/sdk/tests/compat.rs @@ -19,7 +19,6 @@ use std::{ }; use c2pa::{Reader, Result}; -use qbsdiff::Bspatch; use serde::Deserialize; use serde_json::Value; use tiny_http::{Response, Server}; @@ -154,7 +153,6 @@ fn test_compat() -> Result<()> { serde_json::from_reader(File::open(version_dir.join("compat-details.json"))?)?; for asset_details in details.assets { - println!("{:?}", asset_details.asset); let asset_dir = version_dir.join(&asset_details.category); let format = c2pa::format_from_path(&asset_details.asset).unwrap(); @@ -166,11 +164,11 @@ fn test_compat() -> Result<()> { let remote_asset_path = asset_dir.join("remote.patch"); if remote_asset_path.exists() { let expected_remote_asset_patch = fs::read(remote_asset_path)?; - // let expected_remote_asset_patch = lz4_flex::decompress( - // &expected_remote_asset_patch, - // asset_details.uncompressed_remote_size.unwrap(), - // ) - // .expect("TODO3"); // TODO: err msg + let expected_remote_asset_patch = lz4_flex::decompress( + &expected_remote_asset_patch, + asset_details.uncompressed_remote_size.unwrap(), + ) + .expect("TODO3"); // TODO: err msg let mut expected_remote_asset = Vec::new(); // TODO: prealloc Bspatch::new(&expected_remote_asset_patch) .expect("TODO2") @@ -195,11 +193,11 @@ fn test_compat() -> Result<()> { } let expected_embedded_asset_patch = fs::read(asset_dir.join("embedded.patch"))?; - // let expected_embedded_asset_patch = lz4_flex::decompress( - // &expected_embedded_asset_patch, - // asset_details.uncompressed_embedded_size, - // ) - // .expect("TODO4"); // TODO: err msg + let expected_embedded_asset_patch = lz4_flex::decompress( + &expected_embedded_asset_patch, + asset_details.uncompressed_embedded_size, + ) + .expect("TODO4"); // TODO: err msg let mut expected_embedded_asset = Vec::new(); // TODO: prealloc Bspatch::new(&expected_embedded_asset_patch) .expect("TODO5") diff --git a/sdk/tests/fixtures/compat/0.33.0/bmff/embedded.c2pa b/sdk/tests/fixtures/compat/0.33.0/bmff/embedded.c2pa index 0296e757df897ed2627fb6008b93eb59bad1f363..8dc0e8ab3c594123081fb9dd79ae2bdb778fd6d6 100644 GIT binary patch delta 153 zcmV;K0A~N|XzOT@Q6n}uH8nM2H7zwUIXEpeWHMzfIc7LEEif=-HZ?M2WH(}BIk9xB z1SB#xVm4$lW;QJ|Ib=62G-Wq7Enzt`I4xo}Ibt+1H8M9eWn;5L1?Vn7OG8AMurAV3 z_=V-dcnCcS&1?E(!FRCV-9f)Zk*cJj8O2w{r#MBd)CW9II(oA z1SByxHZo;lWn?X6H8?dbG&Ey5En+q?I4xl_IWb}}IAvlmIc2j$1?Vn7?-nR>EWj2d zKZW+0`tke{_wkEak{!8ib*02Bl@BTFYj*5UD23M2P5Mho`)Pu>>gO2~pkVesK!bha HVLk)`G#)$O diff --git a/sdk/tests/fixtures/compat/0.33.0/bmff/embedded.expected b/sdk/tests/fixtures/compat/0.33.0/bmff/embedded.expected deleted file mode 100644 index 42eb27a7f47fa9ee2d36f3db16fc958f155ab50f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 811373 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