#![cfg_attr(not(feature = "std"), no_std)]
#[cfg(feature = "std")]
mod std_tests {
use std::collections::HashMap;
use std::convert::{TryFrom, TryInto};
use std::str::FromStr;
use cid::{Cid, CidGeneric, Error, Version};
use multibase::Base;
use multihash_codetable::{Code, MultihashDigest};
const RAW: u64 = 0x55;
const DAG_PB: u64 = 0x70;
#[test]
fn basic_marshalling() {
let h = Code::Sha2_256.digest(b"beep boop");
let cid = Cid::new_v1(DAG_PB, h);
let data = cid.to_bytes();
let out = Cid::try_from(data.clone()).unwrap();
assert_eq!(cid, out);
let out2 = data.try_into().unwrap();
assert_eq!(cid, out2);
let s = cid.to_string();
let out3 = Cid::try_from(&s[..]).unwrap();
assert_eq!(cid, out3);
let out4 = (&s[..]).try_into().unwrap();
assert_eq!(cid, out4);
}
#[test]
fn empty_string() {
assert!(matches!(Cid::try_from(""), Err(Error::InputTooShort)))
}
#[test]
fn v0_handling() {
let old = "QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n";
let cid = Cid::try_from(old).unwrap();
assert_eq!(cid.version(), Version::V0);
assert_eq!(cid.to_string(), old);
}
#[test]
fn from_str() {
let cid: Cid = "QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n"
.parse()
.unwrap();
assert_eq!(cid.version(), Version::V0);
let bad = "QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zIII".parse::<Cid>();
assert!(matches!(bad, Err(Error::ParsingError)));
}
#[test]
fn v0_error() {
let bad = "QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zIII";
assert!(matches!(Cid::try_from(bad), Err(Error::ParsingError)));
}
#[test]
fn from() {
let the_hash = "QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n";
let cases = vec![
format!("/ipfs/{:}", &the_hash),
format!("https://ipfs.io/ipfs/{:}", &the_hash),
format!("http://localhost:8080/ipfs/{:}", &the_hash),
];
for case in cases {
let cid = Cid::try_from(case).unwrap();
assert_eq!(cid.version(), Version::V0);
assert_eq!(cid.to_string(), the_hash);
}
}
#[test]
fn test_hash() {
let data: Vec<u8> = vec![1, 2, 3];
let hash = Code::Sha2_256.digest(&data);
let mut map = HashMap::new();
let cid = Cid::new_v0(hash).unwrap();
map.insert(cid, data.clone());
assert_eq!(&data, map.get(&cid).unwrap());
}
#[test]
fn test_base32() {
let cid =
Cid::from_str("bafkreibme22gw2h7y2h7tg2fhqotaqjucnbc24deqo72b6mkl2egezxhvy").unwrap();
assert_eq!(cid.version(), Version::V1);
assert_eq!(cid.codec(), RAW);
assert_eq!(cid.hash(), &Code::Sha2_256.digest(b"foo"));
}
#[test]
fn to_string() {
let expected_cid = "bafkreibme22gw2h7y2h7tg2fhqotaqjucnbc24deqo72b6mkl2egezxhvy";
let cid = Cid::new_v1(RAW, Code::Sha2_256.digest(b"foo"));
assert_eq!(cid.to_string(), expected_cid);
}
#[test]
fn to_string_of_base32() {
let expected_cid = "bafkreibme22gw2h7y2h7tg2fhqotaqjucnbc24deqo72b6mkl2egezxhvy";
let cid = Cid::new_v1(RAW, Code::Sha2_256.digest(b"foo"));
assert_eq!(
cid.to_string_of_base(Base::Base32Lower).unwrap(),
expected_cid
);
}
#[test]
fn to_string_of_base64() {
let expected_cid = "mAVUSICwmtGto/8aP+ZtFPB0wQTQTQi1wZIO/oPmKXohiZueu";
let cid = Cid::new_v1(RAW, Code::Sha2_256.digest(b"foo"));
assert_eq!(cid.to_string_of_base(Base::Base64).unwrap(), expected_cid);
}
#[test]
fn to_string_of_base58_v0() {
let expected_cid = "QmRJzsvyCQyizr73Gmms8ZRtvNxmgqumxc2KUp71dfEmoj";
let cid = Cid::new_v0(Code::Sha2_256.digest(b"foo")).unwrap();
assert_eq!(
cid.to_string_of_base(Base::Base58Btc).unwrap(),
expected_cid
);
}
#[test]
fn to_string_of_base_v0_error() {
let cid = Cid::new_v0(Code::Sha2_256.digest(b"foo")).unwrap();
assert!(matches!(
cid.to_string_of_base(Base::Base16Upper),
Err(Error::InvalidCidV0Base)
));
}
#[test]
fn explicit_v0_is_disallowed() {
use std::io::Cursor;
assert!(matches!(
Cid::read_bytes(Cursor::new([
0x00, 0x70, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12
])),
Err(Error::InvalidExplicitCidV0)
));
}
#[test]
fn new_v0_accepts_only_32_bytes() {
use multihash::Multihash;
const SHA2_256: u64 = 0x12;
for i in 1..64 {
if i == 32 {
continue;
}
assert!(matches!(
Cid::new_v0(Multihash::wrap(SHA2_256, &vec![7; i]).unwrap()),
Err(Error::InvalidCidV0Multihash)
));
}
}
fn a_function_that_takes_a_generic_cid<const S: usize>(cid: &CidGeneric<S>) -> String {
cid.to_string()
}
#[test]
fn method_can_take_differently_sized_cids() {
#[derive(Clone, Copy, Debug, Eq, PartialEq, MultihashDigest)]
#[mh(alloc_size = 128)]
enum Code128 {
#[mh(code = 0x12, hasher = multihash_codetable::Sha2_256)]
Sha2_256,
}
let cid_default = Cid::new_v1(RAW, Code::Sha2_256.digest(b"foo"));
let cid_128 = CidGeneric::<128>::new_v1(RAW, Code128::Sha2_256.digest(b"foo"));
assert_eq!(
a_function_that_takes_a_generic_cid(&cid_default),
a_function_that_takes_a_generic_cid(&cid_128)
);
}
#[test]
fn test_into_v1() {
let cid = Cid::from_str("QmTPcW343HGMdoxarwvHHoPhkbo5GfNYjnZkyW5DBtpvLe").unwrap();
let cid_v1 = cid.into_v1().unwrap();
assert_eq!(cid_v1.version(), Version::V1);
assert_eq!(
cid_v1.to_string(),
"bafybeiclbsxcvqpfliqcejqz5ghpvw4r7vktjkyk3ruvjvdmam5azct2v4"
);
let cid =
Cid::from_str("bafyreibjo4xmgaevkgud7mbifn3dzp4v4lyaui4yvqp3f2bqwtxcjrdqg4").unwrap();
let cid_v1 = cid.into_v1().unwrap();
assert_eq!(cid_v1.version(), Version::V1);
assert_eq!(cid_v1, cid);
}
}
#[cfg(all(test, not(feature = "std")))]
mod no_std_tests {
use cid::Cid;
#[test]
fn validate_cid_unwrap_panics() {
let bad_cid = [255, 255, 255, 255, 0, 6, 85, 0];
assert!(Cid::read_bytes(&bad_cid[..]).is_err());
}
}