unit tests for store handler

This commit is contained in:
Dylan Knutson
2024-04-25 00:26:47 -07:00
parent d93f9bd9df
commit afbf648528
5 changed files with 63 additions and 6 deletions

View File

@@ -30,3 +30,56 @@ pub async fn store_handler(
.store(sha256, request.content_type, request.data.contents) .store(sha256, request.content_type, request.data.contents)
.await .await
} }
#[cfg(test)]
mod test {
use super::*;
use crate::shard::test::make_shard;
use axum::body::Bytes;
use axum_typed_multipart::FieldData;
async fn make_shards() -> Shards {
Shards::new(vec![make_shard().await]).unwrap()
}
async fn send_request(sha256: Option<Sha256>, data: Bytes) -> StoreResult {
store_handler(
Extension(make_shards().await),
TypedMultipart(StoreRequest {
sha256: sha256.map(|s| s.hex_string()),
content_type: "text/plain".to_string(),
data: FieldData {
metadata: Default::default(),
contents: data,
},
}),
)
.await
}
#[tokio::test]
async fn test_store_handler() {
let result = send_request(None, "hello, world!".as_bytes().into()).await;
assert!(matches!(result, StoreResult::Created { .. }));
}
#[tokio::test]
async fn test_store_handler_mismatched_sha256() {
let not_hello_world = Sha256::from_bytes("not hello, world!".as_bytes());
let hello_world = Sha256::from_bytes("hello, world!".as_bytes());
let result = send_request(Some(not_hello_world), "hello, world!".as_bytes().into()).await;
assert_eq!(
result,
StoreResult::Sha256Mismatch {
sha256: hello_world.hex_string()
}
);
}
#[tokio::test]
async fn test_store_handler_matching_sha256() {
let hello_world = Sha256::from_bytes("hello, world!".as_bytes());
let result = send_request(Some(hello_world), "hello, world!".as_bytes().into()).await;
assert!(matches!(result, StoreResult::Created { .. }));
}
}

View File

@@ -77,7 +77,7 @@ fn main() -> Result<(), Box<dyn Error>> {
shards_vec.push(shard); shards_vec.push(shard);
} }
let shards = Shards::new(shards_vec); let shards = Shards::new(shards_vec).ok_or("num shards must be > 0")?;
server_loop(server, shards.clone()).await?; server_loop(server, shards.clone()).await?;
info!("shutting down server..."); info!("shutting down server...");
shards.close_all().await?; shards.close_all().await?;

View File

@@ -42,7 +42,8 @@ impl Sha256 {
format!("{:x}", self) format!("{:x}", self)
} }
pub fn modulo(&self, num: usize) -> usize { pub fn modulo(&self, num: usize) -> usize {
self.0[0] as usize % num let sum: usize = self.0.iter().map(|v| *v as usize).sum();
sum % num
} }
} }

View File

@@ -154,10 +154,10 @@ async fn get_num_entries(conn: &Connection) -> Result<usize, tokio_rusqlite::Err
} }
#[cfg(test)] #[cfg(test)]
mod test { pub mod test {
use crate::sha256::Sha256; use crate::sha256::Sha256;
async fn make_shard() -> super::Shard { pub async fn make_shard() -> super::Shard {
let conn = tokio_rusqlite::Connection::open_in_memory().await.unwrap(); let conn = tokio_rusqlite::Connection::open_in_memory().await.unwrap();
super::Shard::open(0, conn).await.unwrap() super::Shard::open(0, conn).await.unwrap()
} }

View File

@@ -5,8 +5,11 @@ use crate::{sha256::Sha256, shard::Shard};
#[derive(Clone)] #[derive(Clone)]
pub struct Shards(Vec<Shard>); pub struct Shards(Vec<Shard>);
impl Shards { impl Shards {
pub fn new(shards: Vec<Shard>) -> Self { pub fn new(shards: Vec<Shard>) -> Option<Self> {
Self(shards) if shards.is_empty() {
return None;
}
Some(Self(shards))
} }
pub fn shard_for(&self, sha256: &Sha256) -> &Shard { pub fn shard_for(&self, sha256: &Sha256) -> &Shard {