use blockstore::{Blockstore, InMemoryBlockstore}; use futures_util::future::FutureExt; use futures_util::poll; use tokio::time::{sleep, Duration}; use crate::utils::{cid, spawn_node}; mod utils; #[tokio::test] async fn test_client_request() { let data_with_cid = ["foo", "bar", "baz"].map(|d| (cid(d.as_bytes()), d)); let store = InMemoryBlockstore::new(); for (cid, data) in data_with_cid { store.put_keyed(&cid, data.as_bytes()).await.unwrap() } let server = spawn_node(Some(store)).await; let mut client = spawn_node(None).await; let received0 = client.request_cid(data_with_cid[0].0); drop(client.connect(&server)); let received1 = client .request_cid(data_with_cid[1].0) .await .expect("could not get CID"); let received0 = received0.await.expect("could not get CID"); assert_eq!(&received0[..], data_with_cid[0].1.as_bytes()); assert_eq!(&received1[..], data_with_cid[1].1.as_bytes()); } #[tokio::test] async fn test_server_request() { let data_with_cid = ["foo", "bar", "baz"].map(|d| (cid(d.as_bytes()), d)); let store = InMemoryBlockstore::new(); for (cid, data) in data_with_cid { store.put_keyed(&cid, data.as_bytes()).await.unwrap() } let mut client = spawn_node(Some(store)).await; let mut server = spawn_node(None).await; let received0 = client.request_cid(data_with_cid[0].0); drop(client.connect(&server)); let received1 = server .request_cid(data_with_cid[1].0) .await .expect("could not get CID"); let received0 = received0.await.expect("Could not get CID"); assert_eq!(&received0[..], data_with_cid[0].1.as_bytes()); assert_eq!(&received1[..], data_with_cid[1].1.as_bytes()); } #[tokio::test] async fn test_chain_of_nodes() { let data = "foo"; let cid = cid(data.as_bytes()); let store = InMemoryBlockstore::new(); store.put_keyed(&cid, data.as_ref()).await.unwrap(); let mut node_with_data = spawn_node(Some(store)).await; let mut node0 = spawn_node(None).await; let mut node1 = spawn_node(None).await; let mut node2 = spawn_node(None).await; drop(node_with_data.connect(&node0)); drop(node0.connect(&node1)); drop(node1.connect(&node2)); let mut node2_request = node2.request_cid(cid); sleep(Duration::from_millis(300)).await; assert!(poll!(&mut node2_request).is_pending()); let mut node1_request = node1.request_cid(cid); sleep(Duration::from_millis(300)).await; assert!(poll!(&mut node1_request).is_pending()); assert!(poll!(&mut node2_request).is_pending()); let node0_request = node0.request_cid(cid); sleep(Duration::from_millis(300)).await; let data0 = node0_request .now_or_never() .expect("data should be ready") .unwrap(); let data1 = node1_request .now_or_never() .expect("data should be ready") .unwrap(); let data2 = node2_request .now_or_never() .expect("data should be ready") .unwrap(); assert_eq!(data0, data.as_bytes()); assert_eq!(data1, data.as_bytes()); assert_eq!(data2, data.as_bytes()); } #[tokio::test] async fn test_node_with_data_coming_online() { let data = "foo"; let cid = cid(data.as_bytes()); let store = InMemoryBlockstore::new(); store.put_keyed(&cid, data.as_ref()).await.unwrap(); let node_with_data = spawn_node(Some(store)).await; let mut node0 = spawn_node(None).await; let mut node1 = spawn_node(None).await; drop(node0.connect(&node1)); let mut node0_request = node0.request_cid(cid); let mut node1_request = node1.request_cid(cid); sleep(Duration::from_millis(300)).await; assert!(poll!(&mut node0_request).is_pending()); assert!(poll!(&mut node1_request).is_pending()); node1 .connect(&node_with_data) .await .expect("could not connect"); sleep(Duration::from_millis(300)).await; let data0 = node0_request .now_or_never() .expect("data should be ready") .unwrap(); let data1 = node1_request .now_or_never() .expect("data should be ready") .unwrap(); assert_eq!(data0, data.as_bytes()); assert_eq!(data1, data.as_bytes()); } #[tokio::test] async fn test_node_with_invalid_data() { let data = "foo"; let cid = cid(data.as_bytes()); let store = InMemoryBlockstore::new(); store.put_keyed(&cid, data.as_ref()).await.unwrap(); let invalid_data = "bar"; let invalid_store = InMemoryBlockstore::new(); invalid_store .put_keyed(&cid, invalid_data.as_ref()) .await .unwrap(); let mut client = spawn_node(None).await; let node = spawn_node(Some(store)).await; let malicious_node = spawn_node(Some(invalid_store)).await; client .connect(&malicious_node) .await .expect("could not connect"); let mut request = client.request_cid(cid); sleep(Duration::from_millis(200)).await; assert!(poll!(&mut request).is_pending()); drop(client.connect(&node)); let received = request.await.expect("could not get CID"); assert_eq!(received, data.as_bytes()); } #[tokio::test] async fn test_node_wishlist_updates() { let data_with_cid = ["foo", "bar", "baz"].map(|d| (cid(d.as_bytes()), d)); let store = InMemoryBlockstore::new(); for (cid, data) in data_with_cid { store.put_keyed(&cid, data.as_bytes()).await.unwrap() } let server = spawn_node(Some(store)).await; let mut client = spawn_node(None).await; let request0 = client.request_cid(data_with_cid[0].0); client.connect(&server).await.unwrap(); let request1 = client.request_cid(data_with_cid[1].0); let data0 = request0.await.unwrap(); assert_eq!(data0, data_with_cid[0].1.as_bytes()); let request2 = client.request_cid(data_with_cid[2].0); let data1 = request1.await.unwrap(); let data2 = request2.await.unwrap(); assert_eq!(data1, data_with_cid[1].1.as_bytes()); assert_eq!(data2, data_with_cid[2].1.as_bytes()); }