extern crate failure;
extern crate hypercore;
extern crate random_access_memory as ram;
extern crate random_access_storage;
mod common;
use self::failure::Error;
use self::random_access_storage::RandomAccess;
use common::create_feed;
use hypercore::{generate_keypair, Feed, NodeTrait, PublicKey, SecretKey, Storage};
use std::env::temp_dir;
use std::fmt::Debug;
use std::fs;
use std::io::Write;
#[test]
fn create_with_key() {
let keypair = generate_keypair();
let storage = Storage::new_memory().unwrap();
let _feed = Feed::builder(keypair.public, storage)
.secret_key(keypair.secret)
.build()
.unwrap();
}
#[test]
fn display() {
let feed = create_feed(50).unwrap();
let output = format!("{}", feed);
assert_eq!(output.len(), 61);
}
#[test]
fn set_get() {
let mut feed = create_feed(50).unwrap();
feed.append(b"hello").unwrap();
feed.append(b"world").unwrap();
assert_eq!(feed.get(0).unwrap(), Some(b"hello".to_vec()));
assert_eq!(feed.get(1).unwrap(), Some(b"world".to_vec()));
}
#[test]
fn append() {
let mut feed = create_feed(50).unwrap();
feed.append(br#"{"hello":"world"}"#).unwrap();
feed.append(br#"{"hello":"mundo"}"#).unwrap();
feed.append(br#"{"hello":"welt"}"#).unwrap();
assert_eq!(feed.len(), 3);
assert_eq!(feed.byte_len(), 50);
assert_eq!(feed.get(0).unwrap(), Some(br#"{"hello":"world"}"#.to_vec()));
assert_eq!(feed.get(1).unwrap(), Some(br#"{"hello":"mundo"}"#.to_vec()));
assert_eq!(feed.get(2).unwrap(), Some(br#"{"hello":"welt"}"#.to_vec()));
}
#[test]
fn root_hashes() {
let mut feed = create_feed(50).unwrap();
let res = feed.root_hashes(0);
assert!(res.is_err());
feed.append(b"data").unwrap();
let roots = feed.root_hashes(0).unwrap();
assert_eq!(roots.len(), 1);
assert_eq!(roots[0].index(), 0);
let res = feed.root_hashes(6);
assert!(res.is_err());
feed.append(b"data").unwrap();
feed.append(b"data").unwrap();
let roots = feed.root_hashes(2).unwrap();
assert_eq!(roots.len(), 2);
assert_eq!(roots[0].index(), 1);
assert_eq!(roots[1].index(), 4);
}
#[test]
fn verify() {
let mut feed = create_feed(50).unwrap();
let (public, secret) = copy_keys(&feed);
let feed_bytes = secret.to_bytes().to_vec();
let storage = Storage::new(|_| Ok(ram::RandomAccessMemory::new(50))).unwrap();
let mut evil_feed = Feed::builder(public, storage)
.secret_key(secret)
.build()
.unwrap();
let evil_bytes = match &feed.secret_key() {
Some(key) => key.to_bytes(),
None => panic!("no secret key found"),
};
assert_eq!(&feed_bytes, &evil_bytes.to_vec());
feed.append(b"test").unwrap();
let sig = feed.signature(0).unwrap();
feed.verify(0, &sig).unwrap();
evil_feed.append(b"t0st").unwrap();
let res = evil_feed.verify(0, &sig);
assert!(res.is_err());
}
#[test]
fn put() {
let mut a = create_feed(50).unwrap();
let (public, secret) = copy_keys(&a);
let storage = Storage::new(|_| Ok(ram::RandomAccessMemory::new(50))).unwrap();
let mut b = Feed::builder(public, storage)
.secret_key(secret)
.build()
.unwrap();
for _ in 0..10 {
a.append(b"foo").unwrap();
}
let proof = a.proof(0, true).unwrap();
b.put(0, None, proof).expect("no error");
let proof = a
.proof_with_digest(4, b.digest(4), true)
.expect(".proof() index 4, digest 4");
b.put(4, None, proof).unwrap();
}
#[test]
fn create_with_storage() {
let storage = Storage::new_memory().unwrap();
assert!(
Feed::with_storage(storage).is_ok(),
"Could not create a feed with a storage."
);
}
#[test]
fn create_with_stored_public_key() {
let mut storage = Storage::new_memory().unwrap();
let keypair = generate_keypair();
storage.write_public_key(&keypair.public).unwrap();
assert!(
Feed::with_storage(storage).is_ok(),
"Could not create a feed with a stored public key."
);
}
#[test]
fn create_with_stored_keys() {
let mut storage = Storage::new_memory().unwrap();
let keypair = generate_keypair();
storage.write_public_key(&keypair.public).unwrap();
storage.write_secret_key(&keypair.secret).unwrap();
assert!(
Feed::with_storage(storage).is_ok(),
"Could not create a feed with a stored keypair."
);
}
fn copy_keys(feed: &Feed<impl RandomAccess<Error = Error> + Debug>) -> (PublicKey, SecretKey) {
match &feed.secret_key() {
Some(secret) => {
let secret = secret.to_bytes();
let public = &feed.public_key().to_bytes();
let public = PublicKey::from_bytes(public).unwrap();
let secret = SecretKey::from_bytes(&secret).unwrap();
(public, secret)
}
_ => panic!("<tests/common>: Could not access secret key"),
}
}
#[test]
fn audit() {
let mut feed = create_feed(50).unwrap();
feed.append(b"hello").unwrap();
feed.append(b"world").unwrap();
match feed.audit() {
Ok(audit_report) => {
assert_eq!(audit_report.valid_blocks, 2);
assert_eq!(audit_report.invalid_blocks, 0);
}
Err(e) => {
panic!(e);
}
}
}
#[test]
fn audit_bad_data() {
let mut dir = temp_dir();
dir.push("audit_bad_data");
let storage = Storage::new_disk(&dir).unwrap();
let mut feed = Feed::with_storage(storage).unwrap();
feed.append(b"hello").unwrap();
feed.append(b"world").unwrap();
let datapath = dir.join("data");
let mut hypercore_data = fs::OpenOptions::new()
.write(true)
.open(datapath)
.expect("Unable to open the hypercore's data file!");
hypercore_data
.write_all(b"yello")
.expect("Unable to corrupt the hypercore data file!");
match feed.audit() {
Ok(audit_report) => {
assert_eq!(audit_report.valid_blocks, 1);
assert_eq!(audit_report.invalid_blocks, 1);
match feed.audit() {
Ok(audit_report) => {
assert_eq!(
audit_report.valid_blocks, 1,
"Audit did not clean up the invalid block!"
);
assert_eq!(
audit_report.invalid_blocks, 0,
"Audit did not clean up the invalid block!"
);
fs::remove_dir_all(dir)
.expect("Should be able to remove our temporary directory");
}
Err(e) => {
fs::remove_dir_all(dir)
.expect("Should be able to remove our temporary directory");
panic!(e);
}
}
}
Err(e) => {
fs::remove_dir_all(dir).expect("Should be able to remove our temporary directory");
panic!(e);
}
}
}