diff options
author | Martin Fischer <martin@push-f.com> | 2022-07-29 21:00:37 +0200 |
---|---|---|
committer | Martin Fischer <martin@push-f.com> | 2022-07-30 03:27:59 +0200 |
commit | fb11f305370359f557bb4cefcef6ae7a8b9c9883 (patch) | |
tree | f7048144877635dba838d69729d20bc88f5218e2 /src | |
parent | d9cd7ab6f46ddc71206bb75bb72eb9dc36743cac (diff) |
add some basic tests
Diffstat (limited to 'src')
-rw-r--r-- | src/main.rs | 39 | ||||
-rw-r--r-- | src/tests.rs | 104 |
2 files changed, 132 insertions, 11 deletions
diff --git a/src/main.rs b/src/main.rs index 9251003..f1f9caa 100644 --- a/src/main.rs +++ b/src/main.rs @@ -49,6 +49,7 @@ mod get_routes; mod origins; mod post_routes; mod shares; +mod tests; pub enum Response { Raw(HyperResponse), @@ -94,17 +95,22 @@ struct Args { #[tokio::main] async fn main() { let args = Args::parse(); - let repo = Repository::open_bare(env::current_dir().unwrap()) + let repo_path: &'static _ = Box::leak(Box::new(env::current_dir().unwrap())); + let repo = Repository::open_bare(repo_path) .expect("expected current directory to be a bare Git repository"); if args.multiuser { - serve(MultiUserController::new(&repo), args).await; + serve(repo_path, MultiUserController::new(&repo), args).await; } else { - serve(SoloController::new(&repo), args).await; + serve(repo_path, SoloController::new(&repo), args).await; } } -async fn serve<C: Controller + Send + Sync + 'static>(controller: C, args: Args) { +async fn serve<C: Controller + Send + Sync + 'static>( + repo_path: &'static Path, + controller: C, + args: Args, +) { let controller = Arc::new(controller); #[cfg(unix)] @@ -121,7 +127,7 @@ async fn serve<C: Controller + Send + Sync + 'static>(controller: C, args: Args) async move { Ok::<_, hyper::Error>(service_fn(move |req| { - service(origin, controller.clone(), req) + service_wrapper(repo_path, origin, controller.clone(), req) })) } }); @@ -173,7 +179,7 @@ async fn serve<C: Controller + Send + Sync + 'static>(controller: C, args: Args) async move { Ok::<_, hyper::Error>(service_fn(move |req| { - service(origin, controller.clone(), req) + service_wrapper(repo_path, origin, controller.clone(), req) })) } }); @@ -182,17 +188,27 @@ async fn serve<C: Controller + Send + Sync + 'static>(controller: C, args: Args) server.await.expect("server error"); } -async fn service<C: Controller>( +async fn service_wrapper<C: Controller>( + repo_path: &Path, origin: &HttpOrigin, controller: Arc<C>, request: Request, ) -> Result<HyperResponse, Infallible> { + Ok(service(repo_path, origin, &*controller, request).await) +} + +async fn service<C: Controller>( + repo_path: &Path, + origin: &HttpOrigin, + controller: &C, + request: Request, +) -> HyperResponse { let (mut parts, body) = request.into_parts(); let mut script_csp = "'none'".into(); let mut frame_csp = "'none'"; - let mut resp = build_response(origin, &*controller, &mut parts, body) + let mut resp = build_response(repo_path, origin, controller, &mut parts, body) .await .map(|resp| match resp { Response::Raw(resp) => resp, @@ -205,7 +221,7 @@ async fn service<C: Controller>( } Builder::new() .content_type(mime::TEXT_HTML) - .body(render_page(&page, &*controller, &parts).into()) + .body(render_page(&page, controller, &parts).into()) .unwrap() } }) @@ -224,7 +240,7 @@ async fn service<C: Controller>( .parse() .unwrap() }); - Ok(resp) + resp } #[derive(Default)] @@ -284,6 +300,7 @@ impl Branch { } async fn build_response<C: Controller>( + repo_path: &Path, origin: &HttpOrigin, controller: &C, parts: &mut Parts, @@ -309,7 +326,7 @@ async fn build_response<C: Controller>( .map_err(|_| Error::BadRequest("failed to percent-decode path as UTF-8".into()))? .into_owned(); - let repo = Repository::open_bare(env::current_dir().unwrap()).unwrap(); + let repo = Repository::open_bare(repo_path).unwrap(); let (rev, unsanitized_path) = match controller.parse_url_path(&unsanitized_path, parts, &repo) { Ok(parsed) => parsed, diff --git a/src/tests.rs b/src/tests.rs new file mode 100644 index 0000000..3eb71ec --- /dev/null +++ b/src/tests.rs @@ -0,0 +1,104 @@ +#![cfg(test)] +use std::{future::Future, path::PathBuf, pin::Pin}; + +use crate::controller::Controller; + +use super::{ + controller::{MultiUserController, SoloController}, + origins::HttpOrigin, +}; +use git2::Repository; +use hyper::{body, http::request::Builder, Body, Request, Response}; +use tempdir::TempDir; + +fn temp_repo() -> (PathBuf, Repository) { + let path = TempDir::new("gitpad-test").unwrap().into_path(); + let repo = Repository::init_bare(&path).unwrap(); + (path, repo) +} + +fn origin() -> HttpOrigin { + "http://pad.example.com".parse().unwrap() +} + +struct Server<C> { + repo_path: PathBuf, + repo: Repository, + origin: HttpOrigin, + controller: C, +} + +impl Server<SoloController> { + fn new() -> Self { + let (repo_path, repo) = temp_repo(); + let origin = origin(); + Self { + repo_path, + origin, + controller: SoloController::new(&repo), + repo, + } + } +} + +impl Server<MultiUserController> { + fn new() -> Self { + let (repo_path, repo) = temp_repo(); + let origin = origin(); + Self { + repo_path, + origin, + controller: MultiUserController::new(&repo), + repo, + } + } +} + +impl<C: Controller> Server<C> { + async fn serve(&self, req: Request<Body>) -> Response<Body> { + super::service(&self.repo_path, &self.origin, &self.controller, req).await + } +} + +trait IntoText { + fn into_text(self) -> Pin<Box<dyn Future<Output = String>>>; +} + +impl IntoText for Body { + fn into_text(self) -> Pin<Box<dyn Future<Output = String>>> { + Box::pin(async move { + std::str::from_utf8(&body::to_bytes(self).await.unwrap()) + .unwrap() + .to_string() + }) + } +} + +#[tokio::test] +async fn test_no_host_header() { + let server = Server::<SoloController>::new(); + let res = server.serve(Builder::new().body("".into()).unwrap()).await; + assert_eq!(res.status(), 400); + assert!(res + .into_body() + .into_text() + .await + .contains("Host header required")); +} + +#[tokio::test] +async fn test_missing_branch() { + let server = Server::<SoloController>::new(); + + let res = server + .serve( + Builder::new() + .header("host", server.origin.host()) + .body("".into()) + .unwrap(), + ) + .await; + assert_eq!(res.status(), 404); // branch not found + + // TODO: create commit with file and test that it is retrievable +} |