integration.rs (8131B)
1 // Copyright 2022 Adobe. All rights reserved. 2 // This file is licensed to you under the Apache License, 3 // Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) 4 // or the MIT license (http://opensource.org/licenses/MIT), 5 // at your option. 6 7 // Unless required by applicable law or agreed to in writing, 8 // this software is distributed on an "AS IS" BASIS, WITHOUT 9 // WARRANTIES OR REPRESENTATIONS OF ANY KIND, either express or 10 // implied. See the LICENSE-MIT and LICENSE-APACHE files for the 11 // specific language governing permissions and limitations under 12 // each license. 13 14 /// Complete functional integration test with parent and ingredients. 15 // Isolate from wasm by wrapping in module. 16 #[cfg(feature = "file_io")] 17 mod integration_1 { 18 19 use std::path::PathBuf; 20 21 use c2pa::{ 22 assertions::{c2pa_action, Action, Actions}, 23 create_signer, 24 settings::load_settings_from_str, 25 Ingredient, Manifest, ManifestStore, Result, Signer, SigningAlg, 26 }; 27 use tempfile::tempdir; 28 29 const GENERATOR: &str = "app"; 30 31 // prevent tests from polluting the results of each other because of Rust unit test concurrency 32 static PROTECT: std::sync::Mutex<u32> = std::sync::Mutex::new(1); // prevent tests from polluting the results of each other 33 34 fn get_temp_signer() -> Box<dyn Signer> { 35 // sign and embed into the target file 36 let mut signcert_path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); 37 signcert_path.push("tests/fixtures/certs/ps256.pub"); 38 let mut pkey_path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); 39 pkey_path.push("tests/fixtures/certs/ps256.pem"); 40 create_signer::from_files(signcert_path, pkey_path, SigningAlg::Ps256, None) 41 .expect("get_signer_from_files") 42 } 43 44 fn configure_trust( 45 trust_anchors: Option<String>, 46 allowed_list: Option<String>, 47 trust_config: Option<String>, 48 ) -> Result<()> { 49 let ta = r#"{"trust": { "trust_anchors": replacement_val } }"#; 50 let al = r#"{"trust": { "allowed_list": replacement_val } }"#; 51 let tc = r#"{"trust": { "trust_config": replacement_val } }"#; 52 53 let mut enable_trust_checks = false; 54 if let Some(trust_list) = trust_anchors { 55 let replacement_val = serde_json::Value::String(trust_list).to_string(); // escape string 56 let setting = ta.replace("replacement_val", &replacement_val); 57 58 load_settings_from_str(&setting, "json")?; 59 60 enable_trust_checks = true; 61 } 62 63 if let Some(allowed_list) = allowed_list { 64 let replacement_val = serde_json::Value::String(allowed_list).to_string(); // escape string 65 let setting = al.replace("replacement_val", &replacement_val); 66 67 load_settings_from_str(&setting, "json")?; 68 69 enable_trust_checks = true; 70 } 71 72 if let Some(trust_config) = trust_config { 73 let replacement_val = serde_json::Value::String(trust_config).to_string(); // escape string 74 let setting = tc.replace("replacement_val", &replacement_val); 75 76 load_settings_from_str(&setting, "json")?; 77 78 enable_trust_checks = true; 79 } 80 81 // enable trust checks 82 if enable_trust_checks { 83 load_settings_from_str(r#"{"verify": { "verify_trust": true} }"#, "json")?; 84 } 85 86 Ok(()) 87 } 88 89 #[test] 90 #[cfg(feature = "file_io")] 91 fn test_embed_manifest() -> Result<()> { 92 let _protect = PROTECT.lock().unwrap(); 93 94 // set up parent and destination paths 95 let dir = tempdir()?; 96 let output_path = dir.path().join("test_file.jpg"); 97 let mut parent_path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); 98 parent_path.push("tests/fixtures/earth_apollo17.jpg"); 99 let mut ingredient_path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); 100 ingredient_path.push("tests/fixtures/libpng-test.png"); 101 102 let config = include_bytes!("../tests/fixtures/certs/trust/store.cfg"); 103 let priv_trust = include_bytes!("../tests/fixtures/certs/trust/test_cert_root_bundle.pem"); 104 105 // Configure before first use so that trust settings are used for all calls. 106 // In production code you should check that the file is indeed UTF-8 text. 107 configure_trust( 108 Some(String::from_utf8_lossy(priv_trust).to_string()), 109 None, 110 Some(String::from_utf8_lossy(config).to_string()), 111 )?; 112 113 // create a new Manifest 114 let mut manifest = Manifest::new(GENERATOR.to_owned()); 115 116 // allocate actions so we can add them 117 let mut actions = Actions::new(); 118 119 // add a parent ingredient 120 let parent = Ingredient::from_file(&parent_path)?; 121 // add an action assertion stating that we imported this file 122 actions = actions.add_action( 123 Action::new(c2pa_action::EDITED) 124 .set_when("2015-06-26T16:43:23+0200") 125 .set_parameter("name".to_owned(), "import")? 126 .set_parameter("identifier".to_owned(), parent.instance_id().to_owned())?, 127 ); 128 129 // set the parent ingredient 130 manifest.set_parent(parent)?; 131 132 actions = actions.add_action( 133 Action::new("c2pa.edit").set_parameter("name".to_owned(), "brightnesscontrast")?, 134 ); 135 136 // add an ingredient 137 let ingredient = Ingredient::from_file(&ingredient_path)?; 138 139 // add an action assertion stating that we imported this file 140 actions = actions.add_action( 141 Action::new(c2pa_action::EDITED) 142 .set_parameter("name".to_owned(), "import")? 143 .set_parameter("identifier".to_owned(), ingredient.instance_id().to_owned())?, 144 // could add other parameters for position and size here 145 ); 146 147 manifest.add_ingredient(ingredient); 148 149 manifest.add_assertion(&actions)?; 150 151 // sign and embed into the target file 152 let signer = get_temp_signer(); 153 manifest.embed(&parent_path, &output_path, &*signer)?; 154 155 // read our new file with embedded manifest 156 let manifest_store = ManifestStore::from_file(&output_path)?; 157 158 println!("{manifest_store}"); 159 160 assert!(manifest_store.get_active().is_some()); 161 if let Some(manifest) = manifest_store.get_active() { 162 assert!(manifest.title().is_some()); 163 assert_eq!(manifest.ingredients().len(), 2); 164 } else { 165 panic!("no manifest in store"); 166 } 167 Ok(()) 168 } 169 170 #[test] 171 #[cfg(feature = "file_io")] 172 fn test_embed_json_manifest() -> Result<()> { 173 let _protect = PROTECT.lock().unwrap(); 174 175 c2pa::settings::reset_default_settings().unwrap(); 176 177 // set up parent and destination paths 178 let dir = tempdir()?; 179 let output_path = dir.path().join("test_file.jpg"); 180 181 let mut fixture_path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); 182 fixture_path.push("tests/fixtures"); 183 184 let mut parent_path = fixture_path.clone(); 185 parent_path.push("earth_apollo17.jpg"); 186 let mut manifest_path = fixture_path.clone(); 187 manifest_path.push("manifest.json"); 188 189 let json = std::fs::read_to_string(manifest_path)?; 190 191 let mut manifest = Manifest::from_json(&json)?; 192 manifest.with_base_path(fixture_path.canonicalize()?)?; 193 194 // sign and embed into the target file 195 let signer = get_temp_signer(); 196 manifest.embed(&parent_path, &output_path, &*signer)?; 197 198 // read our new file with embedded manifest 199 let manifest_store = ManifestStore::from_file(&output_path)?; 200 201 println!("{manifest_store}"); 202 // std::fs::copy(&output_path, "test_file.jpg")?; // for debugging to get copy of the file 203 204 assert!(manifest_store.get_active().is_some()); 205 if let Some(manifest) = manifest_store.get_active() { 206 assert!(manifest.title().is_some()); 207 assert_eq!(manifest.ingredients().len(), 2); 208 } else { 209 panic!("no manifest in store"); 210 } 211 Ok(()) 212 } 213 }