#[cfg(feature = "wasm")]
mod wasm_tests {
use proofmode::generate::wasm::{generate_proof_wasm, get_file_hash};
use std::collections::HashMap;
use wasm_bindgen::prelude::*;
use wasm_bindgen_test::*;
#[wasm_bindgen]
extern "C" {
type MockCallbacks;
#[wasm_bindgen(constructor)]
fn new() -> MockCallbacks;
#[wasm_bindgen(method, js_name = getDeviceInfo)]
fn get_device_info(this: &MockCallbacks) -> JsValue;
#[wasm_bindgen(method, js_name = getLocationInfo)]
fn get_location_info(this: &MockCallbacks) -> JsValue;
#[wasm_bindgen(method, js_name = getNetworkInfo)]
fn get_network_info(this: &MockCallbacks) -> JsValue;
#[wasm_bindgen(method, js_name = saveData)]
fn save_data(this: &MockCallbacks, hash: &str, filename: &str, data: &[u8]) -> bool;
#[wasm_bindgen(method, js_name = saveText)]
fn save_text(this: &MockCallbacks, hash: &str, filename: &str, text: &str) -> bool;
#[wasm_bindgen(method, js_name = signData)]
fn sign_data(this: &MockCallbacks, data: &[u8]) -> JsValue;
#[wasm_bindgen(method, js_name = notarizeHash)]
fn notarize_hash(this: &MockCallbacks, hash: &str) -> JsValue;
}
fn create_mock_callbacks() -> JsValue {
let callbacks = js_sys::Object::new();
let get_device_info = js_sys::Function::new_no_args(
r#"
return {
manufacturer: "TestManufacturer",
model: "TestModel",
os_version: "TestOS 1.0",
device_id: "test-device-123"
};
"#,
);
js_sys::Reflect::set(&callbacks, &"getDeviceInfo".into(), &get_device_info).unwrap();
let get_location_info = js_sys::Function::new_no_args(
r#"
return {
latitude: 40.7128,
longitude: -74.0060,
altitude: 10.0,
accuracy: 5.0,
provider: "GPS"
};
"#,
);
js_sys::Reflect::set(&callbacks, &"getLocationInfo".into(), &get_location_info).unwrap();
let get_network_info = js_sys::Function::new_no_args(
r#"
return {
network_type: "WiFi",
wifi_ssid: "TestNetwork",
cell_info: null
};
"#,
);
js_sys::Reflect::set(&callbacks, &"getNetworkInfo".into(), &get_network_info).unwrap();
let save_data = js_sys::Function::new_with_args(
"hash, filename, data",
r#"
console.log("Saving data:", filename, "for hash:", hash);
return true;
"#,
);
js_sys::Reflect::set(&callbacks, &"saveData".into(), &save_data).unwrap();
let save_text = js_sys::Function::new_with_args(
"hash, filename, text",
r#"
console.log("Saving text:", filename, "for hash:", hash);
return true;
"#,
);
js_sys::Reflect::set(&callbacks, &"saveText".into(), &save_text).unwrap();
let sign_data = js_sys::Function::new_with_args(
"data",
r#"
return null; // No signing in test
"#,
);
js_sys::Reflect::set(&callbacks, &"signData".into(), &sign_data).unwrap();
let notarize_hash = js_sys::Function::new_with_args(
"hash",
r#"
return null; // No notarization in test
"#,
);
js_sys::Reflect::set(&callbacks, &"notarizeHash".into(), ¬arize_hash).unwrap();
callbacks.into()
}
#[wasm_bindgen_test]
fn test_get_file_hash() {
let data = b"WASM test data";
let hash = get_file_hash(data);
assert_eq!(hash.len(), 64); assert!(hash.chars().all(|c| c.is_ascii_hexdigit()));
let hash2 = get_file_hash(data);
assert_eq!(hash, hash2);
}
#[wasm_bindgen_test]
fn test_get_file_hash_different_data() {
let data1 = b"First data";
let data2 = b"Second data";
let hash1 = get_file_hash(data1);
let hash2 = get_file_hash(data2);
assert_ne!(hash1, hash2);
}
#[wasm_bindgen_test]
fn test_get_file_hash_empty() {
let data = b"";
let hash = get_file_hash(data);
assert_eq!(
hash,
"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
);
}
}
#[cfg(test)]
mod wasm_unit_tests {
use proofmode::crypto::hash::calculate_hash;
#[test]
fn test_hash_function_wasm_compatibility() {
let test_cases = vec![
(
"".as_bytes(),
"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
),
(
"a".as_bytes(),
"ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb",
),
(
"abc".as_bytes(),
"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad",
),
(
"Hello, World!".as_bytes(),
"dffd6021bb2bd5b0af676290809ec3a53191dd81c7f70a4b28688a362182986f",
),
];
for (input, expected) in test_cases {
let hash = calculate_hash(input);
assert_eq!(
hash,
expected,
"Hash mismatch for input: {:?}",
std::str::from_utf8(input)
);
}
}
#[test]
fn test_wasm_compatible_data_structures() {
use chrono::Utc;
use proofmode::generate_types::*;
use std::collections::HashMap;
let device_data = DeviceData {
manufacturer: "Test".to_string(),
model: "Device".to_string(),
os_version: "1.0".to_string(),
device_id: Some("test123".to_string()),
};
let location_data = LocationData {
latitude: 40.7128,
longitude: -74.0060,
altitude: Some(10.0),
accuracy: Some(5.0),
provider: Some("GPS".to_string()),
};
let network_data = NetworkData {
network_type: "WiFi".to_string(),
wifi_ssid: Some("TestNetwork".to_string()),
cell_info: None,
};
let proof_data = ProofData {
file_hash_sha256: "test_hash".to_string(),
metadata: HashMap::new(),
location: Some(location_data),
device: Some(device_data),
network: Some(network_data),
timestamps: TimestampData {
created_at: Utc::now(),
modified_at: None,
proof_generated_at: Utc::now(),
},
signature: None,
notarization: None,
};
let json = serde_json::to_string(&proof_data);
assert!(json.is_ok());
let deserialized: Result<ProofData, _> = serde_json::from_str(&json.unwrap());
assert!(deserialized.is_ok());
}
#[test]
fn test_error_types_wasm_compatibility() {
use proofmode::generate_error::ProofModeError;
let errors = vec![
ProofModeError::Io("IO error".to_string()),
ProofModeError::Serialization("Serialization error".to_string()),
ProofModeError::Crypto("Crypto error".to_string()),
ProofModeError::Storage("Storage error".to_string()),
];
for error in errors {
let error_string = error.to_string();
assert!(!error_string.is_empty());
}
}
#[cfg(feature = "wasm")]
#[test]
fn test_wasm_feature_compilation() {
use proofmode::generate::wasm::get_file_hash;
let hash = get_file_hash(b"test");
assert_eq!(hash.len(), 64);
}
#[test]
fn test_platform_agnostic_core() {
use proofmode::generate::core::{PlatformCallbacks, ProofGenerator};
use proofmode::generate_types::*;
use std::collections::HashMap;
struct TestCallbacks;
impl PlatformCallbacks for TestCallbacks {
fn get_device_info(&self) -> Option<DeviceData> {
Some(DeviceData {
manufacturer: "TestManufacturer".to_string(),
model: "TestModel".to_string(),
os_version: "TestOS".to_string(),
device_id: None,
})
}
fn get_location_info(&self) -> Option<LocationData> {
None
}
fn get_network_info(&self) -> Option<NetworkData> {
None
}
fn save_data(
&self,
_hash: &str,
_filename: &str,
_data: &[u8],
) -> proofmode::generate_error::Result<()> {
Ok(())
}
fn save_text(
&self,
_hash: &str,
_filename: &str,
_text: &str,
) -> proofmode::generate_error::Result<()> {
Ok(())
}
fn sign_data(
&self,
_data: &[u8],
) -> proofmode::generate_error::Result<Option<Vec<u8>>> {
Ok(None)
}
fn notarize_hash(
&self,
_hash: &str,
) -> proofmode::generate_error::Result<Option<NotarizationData>> {
Ok(None)
}
fn report_progress(&self, _message: &str) {}
}
let config = ProofModeConfig {
auto_notarize: false,
track_location: false,
track_device_id: true,
track_network: false,
add_credentials: false,
embed_c2pa: false,
};
let generator = ProofGenerator::new(config);
let callbacks = TestCallbacks;
let data = b"platform agnostic test";
let metadata = HashMap::new();
let result = generator.generate_proof(data, metadata, &callbacks);
assert!(result.is_ok());
let hash = result.unwrap();
assert_eq!(hash, calculate_hash(data));
}
}