Skip to content

Commit

Permalink
feat: add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Cyrix126 committed Jul 9, 2024
1 parent c9a4b7b commit de9f9a1
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 10 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ Work in progress, not functional.
- [x] allows to limit cache by size
- [x] organize code in modules
- [x] tracing
- [x] tests
- [ ] remove allocation when possible
- [ ] tests
- [ ] benchmarks
- [ ] documentation
## Description
Expand Down
6 changes: 3 additions & 3 deletions src/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ use std::str::FromStr;
use axum::body::Bytes;
use derive_more::{Deref, DerefMut};
use moka::future::Cache as MokaCache;
use reqwest::header::HeaderMap;
use reqwest::header::{HeaderMap, ETAG};
use reqwest::StatusCode;
use typesize::TypeSize;
use uuid::Uuid;

use crate::config::Config;
#[derive(Deref, DerefMut, Clone)]
#[derive(Deref, DerefMut, Clone, Debug)]
pub struct Cache(pub MokaCache<Uuid, (StatusCode, HeaderMap, Bytes), ahash::RandomState>);

impl Cache {
Expand Down Expand Up @@ -38,7 +38,7 @@ impl Cache {
)
}
pub fn check_etag(&self, headers: &HeaderMap) -> bool {
if let Some(etag) = headers.get("Etag") {
if let Some(etag) = headers.get(ETAG) {
if let Ok(str) = etag.to_str() {
if let Ok(uuid) = Uuid::from_str(str) {
return self.contains_key(&uuid);
Expand Down
117 changes: 111 additions & 6 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,12 +87,18 @@ fn new_state(config: Config) -> AppState {
#[cfg(test)]
// backend
mod test {
use std::time::Duration;

use anyhow::Result;
use axum::{http::HeaderValue, routing::get, Router};
use axum_test::TestServer;
use reqwest::header::HOST;
use tokio::{net::TcpListener, spawn};
use reqwest::{
header::{ETAG, HOST},
StatusCode,
};
use tokio::{net::TcpListener, spawn, time::sleep};
use url::Url;
use uuid::Uuid;

use crate::{config::Config, new_state, router};

Expand All @@ -107,9 +113,7 @@ mod test {
axum::serve(listener, router_backend().into_make_service()).await?;
Ok(())
}
#[tokio::test]
async fn first_request() -> Result<()> {
tracing_subscriber::fmt::init();
async fn app() -> Result<TestServer> {
// start backend service
let listener = tokio::net::TcpListener::bind("127.0.0.1:0").await?;
let port = listener.local_addr().unwrap().port();
Expand All @@ -127,7 +131,12 @@ mod test {
// router
let router = router().with_state(state);
// start Mnemosyne
let app = TestServer::new(router).unwrap();
Ok(TestServer::new(router).unwrap())
}
#[tokio::test]
async fn first_request() -> Result<()> {
// tracing_subscriber::fmt::init();
let app = app().await.unwrap();
// send get request for the first time
let rep = app
.get("/")
Expand All @@ -136,4 +145,100 @@ mod test {
rep.assert_status_ok();
Ok(())
}
#[tokio::test]
async fn correct_etag() -> Result<()> {
// tracing_subscriber::fmt::init();
let app = app().await.unwrap();
// send get request for the first time
let rep = app
.get("/")
.add_header(HOST, HeaderValue::from_static("example.com"))
.await;
rep.assert_status_ok();
let etag = rep.headers().get(ETAG).unwrap();
// wait for the cache to save the entry.
sleep(Duration::from_millis(100)).await;
// resend same request with the etag
let rep = app
.get("/")
.add_header(HOST, HeaderValue::from_static("example.com"))
.add_header(ETAG, etag.clone())
.await;
// reponse should only contains header not modified without the body

Check warning on line 167 in src/main.rs

View workflow job for this annotation

GitHub Actions / typo

"reponse" should be "response".
rep.assert_status(StatusCode::NOT_MODIFIED);

Ok(())
}
#[tokio::test]
async fn incorrect_etag() -> Result<()> {
// tracing_subscriber::fmt::init();
let app = app().await.unwrap();
// send get request for the first time
let rep = app
.get("/")
.add_header(HOST, HeaderValue::from_static("example.com"))
.await;
rep.assert_status_ok();
// wait for the cache to save the entry.
sleep(Duration::from_millis(100)).await;
// resend same request with the etag
let etag = Uuid::new_v4().to_string();
let rep = app
.get("/")
.add_header(HOST, HeaderValue::from_static("example.com"))
.add_header(ETAG, HeaderValue::from_str(&etag).unwrap())
.await;
// reponse should only contains header not modified without the body

Check warning on line 191 in src/main.rs

View workflow job for this annotation

GitHub Actions / typo

"reponse" should be "response".
rep.assert_status(StatusCode::OK);
Ok(())
}
#[tokio::test]
async fn cache_served() -> Result<()> {
// tracing_subscriber::fmt::init();
let app = app().await.unwrap();
// send get request for the first time
let rep = app
.get("/")
.add_header(HOST, HeaderValue::from_static("example.com"))
.await;
rep.assert_status_ok();
// wait for the cache to save the entry.
sleep(Duration::from_millis(100)).await;
// check that cache has the entry.
let etag = rep.headers().get(ETAG).unwrap();
let uri = format!("/api/1/cache/{}", etag.to_str().unwrap());
app.get(&uri).await.assert_status_ok();
// resend request. response should be served from cache.
app.get("/")
.add_header(HOST, HeaderValue::from_static("example.com"))
.await
.assert_status_ok();
// reponse should only contains header not modified without the body

Check warning on line 216 in src/main.rs

View workflow job for this annotation

GitHub Actions / typo

"reponse" should be "response".
Ok(())
}
#[tokio::test]
async fn cache_must_be_empty() -> Result<()> {
// tracing_subscriber::fmt::init();
let app = app().await.unwrap();
// send get request for the first time
let rep = app
.get("/")
.add_header(HOST, HeaderValue::from_static("example.com"))
.await;
rep.assert_status_ok();
// wait for the cache to save the entry.
sleep(Duration::from_millis(100)).await;
// delete the entry
let etag = rep.headers().get(ETAG).unwrap();
let uri = format!("/api/1/cache/{}", etag.to_str().unwrap());
app.delete(&uri).await.assert_status_ok();
app.get(&uri).await.assert_status_not_found();
// resend request. response should be served from cache.
app.get("/")
.add_header(HOST, HeaderValue::from_static("example.com"))
.await
.assert_status_ok();
// reponse should only contains header not modified without the body

Check warning on line 241 in src/main.rs

View workflow job for this annotation

GitHub Actions / typo

"reponse" should be "response".
Ok(())
}
}

0 comments on commit de9f9a1

Please sign in to comment.