use bytes::Bytes;
use ipfrs_core::{Block, CidBuilder, CidExt, Ipld, MultibaseEncoding};
use std::collections::BTreeMap;
#[test]
fn test_cid_matches_ipfs() {
let data = b"hello world";
let cid = CidBuilder::v0().build_v0(data).unwrap();
let cid_str = cid.to_string();
assert!(cid_str.starts_with("Qm"), "CIDv0 should start with Qm");
assert_eq!(cid_str.len(), 46, "CIDv0 should be 46 characters");
}
#[test]
fn test_cidv0_format() {
let data = b"test data";
let cid = CidBuilder::v0().build_v0(data).unwrap();
assert!(cid.is_v0());
assert!(!cid.is_v1());
assert_eq!(cid.hash_algorithm_code(), 0x12);
let cid_str = cid.to_string();
assert!(cid_str.starts_with("Qm"));
assert_eq!(cid_str.len(), 46);
}
#[test]
fn test_cidv1_multibase_formats() {
let data = b"test data";
let cid = CidBuilder::new().build(data).unwrap();
assert!(cid.is_v1());
let base32_lower = cid.to_string_with_base(MultibaseEncoding::Base32Lower);
assert!(
base32_lower.starts_with('b'),
"Base32lower should start with 'b'"
);
let base32_upper = cid.to_string_with_base(MultibaseEncoding::Base32Upper);
assert!(
base32_upper.starts_with('B'),
"Base32upper should start with 'B'"
);
let base58btc = cid.to_string_with_base(MultibaseEncoding::Base58Btc);
assert!(
base58btc.starts_with('z'),
"Base58btc should start with 'z'"
);
let base64 = cid.to_string_with_base(MultibaseEncoding::Base64);
assert!(base64.starts_with('m'), "Base64 should start with 'm'");
}
#[test]
fn test_cid_version_conversion() {
let data = b"conversion test";
let cid_v0 = CidBuilder::v0().build_v0(data).unwrap();
assert!(cid_v0.to_string().starts_with("Qm"));
let cid_v1 = cid_v0.to_v1().unwrap();
assert!(cid_v1.is_v1());
let back_to_v0 = cid_v1.to_v0().unwrap();
assert_eq!(cid_v0, back_to_v0);
}
#[test]
fn test_parse_ipfs_cids() {
let v0_str = "QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG";
let cid_v0: ipfrs_core::Cid = v0_str.parse().unwrap();
assert!(cid_v0.is_v0());
assert_eq!(cid_v0.to_string(), v0_str);
let data = b"test";
let cid = CidBuilder::new().build(data).unwrap();
let cid_str = cid.to_string_with_base(MultibaseEncoding::Base32Lower);
let parsed: ipfrs_core::Cid = cid_str.parse().unwrap();
assert_eq!(parsed, cid);
}
#[test]
fn test_block_size_limits() {
let max_size = 2 * 1024 * 1024;
let data = vec![0u8; max_size];
let block = Block::new(Bytes::from(data)).unwrap();
assert_eq!(block.size(), max_size as u64);
let min_block = Block::new(Bytes::from(vec![0u8])).unwrap();
assert_eq!(min_block.size(), 1);
let oversized = vec![0u8; max_size + 1];
let result = Block::new(Bytes::from(oversized));
assert!(result.is_err());
}
#[test]
fn test_block_verification() {
let data = b"verify this block";
let block = Block::new(Bytes::from_static(data)).unwrap();
assert!(block.verify().unwrap());
let wrong_cid = CidBuilder::new().build(b"different data").unwrap();
let invalid_block = Block::from_parts(wrong_cid, Bytes::from_static(data));
assert!(!invalid_block.verify().unwrap());
}
#[test]
fn test_dag_cbor_encoding() {
let mut map = BTreeMap::new();
map.insert("name".to_string(), Ipld::String("test".to_string()));
map.insert("size".to_string(), Ipld::Integer(1024));
let ipld = Ipld::Map(map);
let cbor = ipld.to_dag_cbor().unwrap();
assert!(!cbor.is_empty());
let decoded = Ipld::from_dag_cbor(&cbor).unwrap();
assert_eq!(decoded, ipld);
}
#[test]
fn test_dag_cbor_with_links() {
let target_cid = CidBuilder::new().build(b"linked data").unwrap();
let mut map = BTreeMap::new();
map.insert("file".to_string(), Ipld::String("data.txt".to_string()));
map.insert("link".to_string(), Ipld::Link(target_cid.into()));
let ipld = Ipld::Map(map);
let cbor = ipld.to_dag_cbor().unwrap();
let decoded = Ipld::from_dag_cbor(&cbor).unwrap();
if let Ipld::Map(decoded_map) = decoded {
if let Some(Ipld::Link(link_cid)) = decoded_map.get("link") {
let link_cid_unwrapped: ipfrs_core::Cid = (*link_cid).into();
assert_eq!(link_cid_unwrapped, target_cid);
} else {
panic!("Link not preserved in round-trip");
}
}
}
#[test]
fn test_dag_json_encoding() {
let mut map = BTreeMap::new();
map.insert("hello".to_string(), Ipld::String("world".to_string()));
map.insert("count".to_string(), Ipld::Integer(42));
let ipld = Ipld::Map(map);
let json_str = ipld.to_dag_json().unwrap();
assert!(json_str.contains("hello"));
assert!(json_str.contains("world"));
let decoded = Ipld::from_dag_json(&json_str).unwrap();
assert_eq!(decoded, ipld);
}
#[test]
fn test_sha256_compatibility() {
use ipfrs_core::HashAlgorithm;
let data = b"hash this";
let cid = CidBuilder::new()
.hash_algorithm(HashAlgorithm::Sha256)
.build(data)
.unwrap();
assert_eq!(cid.hash_algorithm_code(), 0x12); assert_eq!(cid.hash_algorithm_name(), "sha2-256");
}
#[test]
fn test_sha3_256_compatibility() {
use ipfrs_core::HashAlgorithm;
let data = b"hash this with sha3";
let cid = CidBuilder::new()
.hash_algorithm(HashAlgorithm::Sha3_256)
.build(data)
.unwrap();
let code = cid.hash_algorithm_code();
println!("Actual SHA3-256 code: 0x{:x}", code);
assert_eq!(code, 0x16);
let name = cid.hash_algorithm_name();
println!("Hash algorithm name: {}", name);
assert_eq!(name, "sha3-256");
}
#[test]
fn test_codec_compatibility() {
use ipfrs_core::codec;
let data = b"codec test";
let raw_cid = CidBuilder::new().codec(codec::RAW).build(data).unwrap();
assert_eq!(raw_cid.codec_code(), codec::RAW);
let cbor_cid = CidBuilder::new()
.codec(codec::DAG_CBOR)
.build(data)
.unwrap();
assert_eq!(cbor_cid.codec_code(), codec::DAG_CBOR);
let pb_cid = CidBuilder::new().codec(codec::DAG_PB).build(data).unwrap();
assert_eq!(pb_cid.codec_code(), codec::DAG_PB);
}
#[test]
fn test_ipfs_workflow() {
let data = b"Hello, IPFS world!";
let block = Block::new(Bytes::from_static(data)).unwrap();
let cid = block.cid();
assert!(block.verify().unwrap());
let cid2 = CidBuilder::new().build(data).unwrap();
assert_eq!(*cid, cid2);
let cid_str = cid.to_string();
assert!(!cid_str.is_empty());
let parsed: ipfrs_core::Cid = cid_str.parse().unwrap();
assert_eq!(*cid, parsed);
}
#[test]
fn test_ipfs_dag_structure() {
let chunk1 = b"chunk1";
let chunk2 = b"chunk2";
let cid1 = CidBuilder::new().build(chunk1).unwrap();
let cid2 = CidBuilder::new().build(chunk2).unwrap();
let mut root = BTreeMap::new();
root.insert("type".to_string(), Ipld::String("file".to_string()));
let links = vec![Ipld::Link(cid1.into()), Ipld::Link(cid2.into())];
root.insert("links".to_string(), Ipld::List(links));
let root_ipld = Ipld::Map(root);
let encoded = root_ipld.to_dag_cbor().unwrap();
assert!(!encoded.is_empty());
let root_cid = CidBuilder::new()
.codec(ipfrs_core::codec::DAG_CBOR)
.build(&encoded)
.unwrap();
assert!(root_cid.is_v1());
}
#[test]
fn test_multibase_roundtrips() {
let data = b"multibase test";
let cid = CidBuilder::new().build(data).unwrap();
let encodings = [
MultibaseEncoding::Base32Lower,
MultibaseEncoding::Base32Upper,
MultibaseEncoding::Base58Btc,
MultibaseEncoding::Base64,
MultibaseEncoding::Base64Url,
];
for encoding in &encodings {
let encoded = cid.to_string_with_base(*encoding);
let parsed: ipfrs_core::Cid = encoded.parse().unwrap();
assert_eq!(cid, parsed, "Round-trip failed for {:?}", encoding);
}
}
#[test]
fn test_chunking_compatibility() {
use ipfrs_core::{Chunker, ChunkingConfig};
let config = ChunkingConfig::with_chunk_size(256 * 1024).unwrap();
let chunker = Chunker::with_config(config);
let data = vec![0u8; 1_000_000];
let chunked = chunker.chunk(&data).unwrap();
for block in &chunked.blocks {
assert!(block.size() <= 256 * 1024);
}
assert!(chunked.root_cid.is_v1());
}