mod test_util;
use test_util::TestController;
use std::convert::TryInto;
use bindle::{signature::SecretKeyStorage, testing, SignatureRole};
use tokio_stream::StreamExt;
#[cfg(not(target_family = "windows"))]
const BINARY_NAME: &str = "bindle-server";
#[cfg(target_family = "windows")]
const BINARY_NAME: &str = "bindle-server.exe";
#[tokio::test]
async fn test_successful() {
let controller = TestController::new(BINARY_NAME).await;
let scaffold = testing::Scaffold::load("valid_v1").await;
let inv = controller
.client
.create_invoice(scaffold.invoice)
.await
.expect("unable to create invoice")
.invoice;
controller
.client
.get_invoice(&inv.bindle.id)
.await
.expect("Should be able to fetch newly created invoice");
for parcel in scaffold.parcel_files.values() {
controller
.client
.create_parcel(&inv.bindle.id, &parcel.sha, parcel.data.clone())
.await
.expect("Unable to create parcel");
}
for parcel in scaffold.parcel_files.values() {
let data = controller
.client
.get_parcel(&inv.bindle.id, &parcel.sha)
.await
.expect("unable to get parcel");
let expected_len = parcel.data.len();
assert_eq!(
data.len(),
expected_len,
"Expected file to be {} bytes, got {} bytes",
expected_len,
data.len()
);
}
controller
.client
.yank_invoice(&inv.bindle.id)
.await
.expect("unable to yank invoice");
match controller.client.get_invoice(inv.bindle.id).await {
Ok(_) => panic!("getting a yanked invoice should have errored"),
Err(e) => {
if !matches!(e, bindle::client::ClientError::InvoiceNotFound) {
panic!("Expected an invoice not found error, got: {:?}", e)
}
}
}
}
#[tokio::test]
async fn test_streaming_successful() {
let controller = TestController::new(BINARY_NAME).await;
let root = std::env::var("CARGO_MANIFEST_DIR").expect("Unable to get project directory");
let base = std::path::PathBuf::from(root).join("tests/scaffolds/valid_v1");
let inv = controller
.client
.create_invoice_from_file(base.join("invoice.toml"))
.await
.expect("unable to create invoice")
.invoice;
controller
.client
.get_invoice(&inv.bindle.id)
.await
.expect("Should be able to fetch newly created invoice");
let parcel_path = base.join("parcels/parcel.dat");
let parcel_sha = inv.parcel.expect("Should have parcels in invoice")[0]
.label
.sha256
.to_owned();
controller
.client
.create_parcel_from_file(&inv.bindle.id, &parcel_sha, &parcel_path)
.await
.expect("Unable to create parcel");
let mut stream = controller
.client
.get_parcel_stream(&inv.bindle.id, &parcel_sha)
.await
.expect("unable to get parcel");
let mut data = Vec::new();
while let Some(res) = stream.next().await {
let bytes = res.expect("Shouldn't get an error in stream");
data.extend(bytes);
}
let on_disk_len = tokio::fs::metadata(parcel_path)
.await
.expect("Unable to get file info")
.len() as usize;
assert_eq!(
data.len(),
on_disk_len,
"Expected file to be {} bytes, got {} bytes",
on_disk_len,
data.len()
);
}
#[tokio::test]
async fn test_already_created() {
let controller = TestController::new(BINARY_NAME).await;
let scaffold = testing::Scaffold::load("valid_v2").await;
controller
.client
.create_invoice(scaffold.invoice.clone())
.await
.expect("Invoice creation should not error");
for parcel in scaffold.parcel_files.values() {
controller
.client
.create_parcel(
&scaffold.invoice.bindle.id,
&parcel.sha,
parcel.data.clone(),
)
.await
.expect("Unable to create parcel");
}
let mut other_inv = scaffold.invoice.clone();
other_inv.bindle.id = "another.com/bindle/1.0.0".try_into().unwrap();
other_inv.signature = None;
other_inv
.sign(
SignatureRole::Creator,
scaffold
.keys
.get_first_matching(&SignatureRole::Creator, None)
.unwrap(),
)
.unwrap();
controller
.client
.create_invoice(other_inv)
.await
.expect("invoice creation should not error");
}
#[tokio::test]
async fn test_missing() {
let controller = TestController::new(BINARY_NAME).await;
let scaffold = testing::Scaffold::load("lotsa_parcels").await;
let inv = controller
.client
.create_invoice(scaffold.invoice)
.await
.expect("unable to create invoice")
.invoice;
let missing = controller
.client
.get_missing_parcels(&inv.bindle.id)
.await
.expect("Should be able to fetch list of missing parcels");
assert_eq!(
missing.len(),
scaffold.parcel_files.len(),
"Expected {} missing parcels, found {}",
scaffold.parcel_files.len(),
missing.len()
);
controller
.client
.yank_invoice(&inv.bindle.id)
.await
.expect("unable to yank invoice");
match controller.client.get_missing_parcels(&inv.bindle.id).await {
Ok(_) => panic!("getting a yanked invoice should have errored"),
Err(e) => {
if !matches!(e, bindle::client::ClientError::InvoiceNotFound) {
panic!("Expected an invoice not found error, got: {:?}", e)
}
}
}
}
#[tokio::test]
async fn test_charset() {
let controller = TestController::new(BINARY_NAME).await;
let scaffold = testing::RawScaffold::load("valid_v1").await;
let client = reqwest::Client::builder()
.http2_prior_knowledge()
.build()
.unwrap();
let url = format!("{}/_i", controller.base_url);
client
.post(&url)
.header("Content-Type", "application/toml; charset=utf-8")
.body(scaffold.parcel_files.get("parcel").unwrap().data.clone())
.send()
.await
.expect("Content-Type with charset shouldn't fail");
}
#[tokio::test]
async fn test_bindle_keys() {
let controller = TestController::new(BINARY_NAME).await;
let keyring = controller
.client
.get_host_keys()
.await
.expect("Should be able to fetch host keys using client");
assert!(
!keyring.key.is_empty(),
"Keyring should contain at least one key"
);
}