From d099e77eaa8e51eef14cd775234bfd4b12098a4c Mon Sep 17 00:00:00 2001 From: mo khan Date: Wed, 25 Jun 2025 14:20:33 -0600 Subject: test: move cedar_authorizer tests to integration test suite --- tests/authorization/mod.rs | 1 + 1 file changed, 1 insertion(+) create mode 100644 tests/authorization/mod.rs (limited to 'tests/authorization/mod.rs') diff --git a/tests/authorization/mod.rs b/tests/authorization/mod.rs new file mode 100644 index 00000000..a8aab73a --- /dev/null +++ b/tests/authorization/mod.rs @@ -0,0 +1 @@ +mod cedar_authorizer_test; -- cgit v1.2.3 From 86c9564a82f56b7c5ee60f4bff9fb07ca3e4a6eb Mon Sep 17 00:00:00 2001 From: mo khan Date: Wed, 25 Jun 2025 14:24:19 -0600 Subject: test: move unit tests to integration test suite to share code --- src/authorization/check_service.rs | 62 ------------------------------- tests/authorization/check_service_test.rs | 48 ++++++++++++++++++++++++ tests/authorization/mod.rs | 1 + tests/common/mod.rs | 4 ++ 4 files changed, 53 insertions(+), 62 deletions(-) create mode 100644 tests/authorization/check_service_test.rs (limited to 'tests/authorization/mod.rs') diff --git a/src/authorization/check_service.rs b/src/authorization/check_service.rs index c0a05e21..6c6bd9c6 100644 --- a/src/authorization/check_service.rs +++ b/src/authorization/check_service.rs @@ -33,65 +33,3 @@ impl envoy_types::ext_authz::v3::pb::Authorization for CheckService { } } } - -#[cfg(test)] -mod tests { - use super::super::cedar_authorizer::CedarAuthorizer; - use super::*; - use envoy_types::ext_authz::v3::pb::{Authorization, CheckRequest}; - use envoy_types::pb::envoy::service::auth::v3::AttributeContext; - use envoy_types::pb::envoy::service::auth::v3::attribute_context::{HttpRequest, Request}; - use std::collections::HashMap; - use std::sync::Arc; - - pub fn create_request(f: impl std::ops::FnOnce(&mut HttpRequest)) -> CheckRequest { - please::build_with(|item: &mut CheckRequest| { - item.attributes = Some(please::build_with(|item: &mut AttributeContext| { - item.request = Some(please::build_with(|item: &mut Request| { - item.http = Some(please::build_with(|item: &mut HttpRequest| f(item))); - })); - })); - }) - } - - pub fn create_token() -> String { - return String::from("valid-token"); - } - - #[tokio::test] - async fn test_check_allows_valid_bearer_token() { - let token = create_token(); - let server = CheckService::new(Arc::new(CedarAuthorizer::new())); - - let mut headers = HashMap::new(); - headers.insert("authorization".to_string(), format!("Bearer {}", token)); - let request = tonic::Request::new(create_request(|item: &mut HttpRequest| { - item.headers = headers; - })); - - let response = server.check(request).await; - - assert!(response.is_ok()); - let check_response = response.unwrap().into_inner(); - assert!(check_response.status.is_some()); - let status = check_response.status.unwrap(); - assert_eq!(status.code, tonic::Code::Ok as i32); - } - - #[tokio::test] - async fn test_check_denies_invalid_bearer_token() { - let authorizer = Arc::new(CedarAuthorizer::new()); - let server = CheckService::new(authorizer); - let request = tonic::Request::new(create_request(|item: &mut HttpRequest| { - item.headers = HashMap::new(); - })); - - let response = server.check(request).await; - - assert!(response.is_ok()); - let check_response = response.unwrap().into_inner(); - assert!(check_response.status.is_some()); - let status = check_response.status.unwrap(); - assert_eq!(status.code, tonic::Code::Unauthenticated as i32); - } -} diff --git a/tests/authorization/check_service_test.rs b/tests/authorization/check_service_test.rs new file mode 100644 index 00000000..23655ffb --- /dev/null +++ b/tests/authorization/check_service_test.rs @@ -0,0 +1,48 @@ +#[cfg(test)] +mod tests { + use crate::common::create_request; + use crate::common::create_token; + use authzd::CedarAuthorizer; + use authzd::CheckService; + use envoy_types::ext_authz::v3::pb::Authorization; + use envoy_types::pb::envoy::service::auth::v3::attribute_context::HttpRequest; + use std::collections::HashMap; + use std::sync::Arc; + + #[tokio::test] + async fn test_check_allows_valid_bearer_token() { + let token = create_token(); + let server = CheckService::new(Arc::new(CedarAuthorizer::new())); + + let mut headers = HashMap::new(); + headers.insert("authorization".to_string(), format!("Bearer {}", token)); + let request = tonic::Request::new(create_request(|item: &mut HttpRequest| { + item.headers = headers; + })); + + let response = server.check(request).await; + + assert!(response.is_ok()); + let check_response = response.unwrap().into_inner(); + assert!(check_response.status.is_some()); + let status = check_response.status.unwrap(); + assert_eq!(status.code, tonic::Code::Ok as i32); + } + + #[tokio::test] + async fn test_check_denies_invalid_bearer_token() { + let authorizer = Arc::new(CedarAuthorizer::new()); + let server = CheckService::new(authorizer); + let request = tonic::Request::new(create_request(|item: &mut HttpRequest| { + item.headers = HashMap::new(); + })); + + let response = server.check(request).await; + + assert!(response.is_ok()); + let check_response = response.unwrap().into_inner(); + assert!(check_response.status.is_some()); + let status = check_response.status.unwrap(); + assert_eq!(status.code, tonic::Code::Unauthenticated as i32); + } +} diff --git a/tests/authorization/mod.rs b/tests/authorization/mod.rs index a8aab73a..a4ece924 100644 --- a/tests/authorization/mod.rs +++ b/tests/authorization/mod.rs @@ -1 +1,2 @@ mod cedar_authorizer_test; +mod check_service_test; diff --git a/tests/common/mod.rs b/tests/common/mod.rs index 9b2370cb..4e879b6f 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -26,3 +26,7 @@ pub fn create_headers_with_auth(auth_value: &str) -> HashMap { headers.insert("authorization".to_string(), auth_value.to_string()); headers } + +pub fn create_token() -> String { + return String::from("valid-token"); +} -- cgit v1.2.3 From 2f895218df8115d90ba03253024f6974a1c4f21b Mon Sep 17 00:00:00 2001 From: mo khan Date: Fri, 27 Jun 2025 14:50:34 -0600 Subject: test: add tests for grpc server --- Cargo.lock | 1 + Cargo.toml | 1 + tests/authorization/check_service_test.rs | 47 +++++++++++++++++++++--- tests/authorization/mod.rs | 1 + tests/authorization/server_test.rs | 7 ++++ tests/common/factory_bot.rs | 2 +- tests/common/mod.rs | 2 - tests/grpc_server_test.rs | 61 +++++++++++++++++++++++++++++++ tests/integration_test.rs | 2 + tests/main_test.rs | 8 ---- 10 files changed, 116 insertions(+), 16 deletions(-) create mode 100644 tests/authorization/server_test.rs create mode 100644 tests/grpc_server_test.rs create mode 100644 tests/integration_test.rs delete mode 100644 tests/main_test.rs (limited to 'tests/authorization/mod.rs') diff --git a/Cargo.lock b/Cargo.lock index a1c069e6..4c657df8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -110,6 +110,7 @@ dependencies = [ "log", "please", "tokio", + "tokio-stream", "tokio-test", "tonic", "tonic-build", diff --git a/Cargo.toml b/Cargo.toml index 2ac42209..ebacce3b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,5 +24,6 @@ tracing = "0.1" tracing-subscriber = { version = "0.3", features = ["json"] } [dev-dependencies] +tokio-stream = "0.1" tokio-test = "0.4.0" tonic-build = "0.10.0" diff --git a/tests/authorization/check_service_test.rs b/tests/authorization/check_service_test.rs index 4a8f1426..3bdf30c2 100644 --- a/tests/authorization/check_service_test.rs +++ b/tests/authorization/check_service_test.rs @@ -7,12 +7,8 @@ mod tests { use std::collections::HashMap; use std::sync::Arc; - fn authorizer() -> Arc { - Arc::new(build_cedar_authorizer()) - } - fn subject() -> CheckService { - CheckService::new(authorizer()) + CheckService::new(Arc::new(build_cedar_authorizer())) } #[tokio::test] @@ -50,6 +46,47 @@ mod tests { assert_eq!(status.code, tonic::Code::Unauthenticated as i32); } + #[tokio::test] + async fn test_static_assets() { + let static_paths = vec![ + "app.js", + "favicon.ico", + "image.jpg", + "index.html", + "logo.png", + "style.css", + ]; + + for path in static_paths { + let request = tonic::Request::new(build_request(|http| { + http.headers = build_headers(vec![(":path".to_string(), path.to_string())]); + })); + + let response = subject().check(request).await; + assert!(response.is_ok()); + + let check_response = response.unwrap().into_inner(); + assert!(check_response.status.is_some()); + + let status = check_response.status.unwrap(); + assert_eq!(status.code, tonic::Code::Ok as i32); + } + } + + #[tokio::test] + async fn test_no_headers() { + let request = tonic::Request::new(build_request(|_http| {})); + + let response = subject().check(request).await; + assert!(response.is_ok()); + + let check_response = response.unwrap().into_inner(); + assert!(check_response.status.is_some()); + + let status = check_response.status.unwrap(); + assert_eq!(status.code, tonic::Code::Unauthenticated as i32); + } + #[tokio::test] async fn test_table() { let test_cases = vec![ diff --git a/tests/authorization/mod.rs b/tests/authorization/mod.rs index a4ece924..675247d4 100644 --- a/tests/authorization/mod.rs +++ b/tests/authorization/mod.rs @@ -1,2 +1,3 @@ mod cedar_authorizer_test; mod check_service_test; +mod server_test; diff --git a/tests/authorization/server_test.rs b/tests/authorization/server_test.rs new file mode 100644 index 00000000..6001e978 --- /dev/null +++ b/tests/authorization/server_test.rs @@ -0,0 +1,7 @@ +#[cfg(test)] +mod tests { + #[test] + fn test_create_server() { + assert!(authzd::create_server().is_ok()); + } +} diff --git a/tests/common/factory_bot.rs b/tests/common/factory_bot.rs index ea3a7da1..c64b53a2 100644 --- a/tests/common/factory_bot.rs +++ b/tests/common/factory_bot.rs @@ -17,7 +17,7 @@ where } pub fn build_request(f: impl std::ops::FnOnce(&mut HttpRequest)) -> CheckRequest { - crate::common::build_with(|item: &mut CheckRequest| { + build_with(|item: &mut CheckRequest| { item.attributes = Some(please::build_with(|item: &mut AttributeContext| { item.request = Some(please::build_with(|item: &mut Request| { item.http = Some(please::build_with(|item: &mut HttpRequest| f(item))); diff --git a/tests/common/mod.rs b/tests/common/mod.rs index 4db87a2c..5e2a6d78 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -1,3 +1 @@ pub mod factory_bot; - -use factory_bot::*; diff --git a/tests/grpc_server_test.rs b/tests/grpc_server_test.rs new file mode 100644 index 00000000..ec471799 --- /dev/null +++ b/tests/grpc_server_test.rs @@ -0,0 +1,61 @@ +#[cfg(test)] +mod tests { + use authzd::create_server; + use std::net::SocketAddr; + use tokio::net::TcpListener; + use tonic::transport::Channel; + + async fn available_port() -> SocketAddr { + let listener = TcpListener::bind("127.0.0.1:0") + .await + .expect("Failed to bind to random port"); + let addr = listener.local_addr().expect("Failed to get local address"); + drop(listener); + addr + } + + async fn start_server() -> (SocketAddr, tokio::task::JoinHandle<()>) { + let addr = available_port().await; + let server = create_server().expect("Failed to create server"); + + let handle = tokio::spawn(async move { + server.serve(addr).await.expect("Failed to start server"); + }); + + tokio::time::sleep(tokio::time::Duration::from_millis(100)).await; + + (addr, handle) + } + + async fn build_channel(addr: SocketAddr) -> Channel { + Channel::from_shared(format!("http://{}", addr)) + .expect("Failed to create channel") + .connect() + .await + .expect("Failed to connect to server") + } + + async fn build_client( + addr: SocketAddr, + ) -> tonic_health::pb::health_client::HealthClient { + tonic_health::pb::health_client::HealthClient::new(build_channel(addr).await) + } + + #[tokio::test] + async fn test_health_check_service() { + let (addr, server) = start_server().await; + let mut client = build_client(addr).await; + let request = tonic::Request::new(tonic_health::pb::HealthCheckRequest { + service: String::new(), + }); + + let response = client.check(request).await; + assert!(response.is_ok()); + assert_eq!( + response.unwrap().into_inner().status(), + tonic_health::pb::health_check_response::ServingStatus::Serving + ); + + server.abort(); + } +} diff --git a/tests/integration_test.rs b/tests/integration_test.rs new file mode 100644 index 00000000..c1edf36e --- /dev/null +++ b/tests/integration_test.rs @@ -0,0 +1,2 @@ +mod authorization; +mod common; diff --git a/tests/main_test.rs b/tests/main_test.rs deleted file mode 100644 index 69c6eda1..00000000 --- a/tests/main_test.rs +++ /dev/null @@ -1,8 +0,0 @@ -#[cfg(test)] -mod tests { - #[test] - fn test_create_server() { - let result = authzd::create_server(); - assert!(result.is_ok()); - } -} -- cgit v1.2.3