110 lines
3.0 KiB
Rust
110 lines
3.0 KiB
Rust
|
|
use crate::metrics;
|
||
|
|
use crate::security::AuthInterceptor;
|
||
|
|
use tonic::service::Interceptor;
|
||
|
|
use tonic::Request;
|
||
|
|
// Since counters are lazy statics, we can get their values directly for testing
|
||
|
|
use std::thread::sleep;
|
||
|
|
use std::time::Duration;
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
fn test_metrics_request_timer_ok() {
|
||
|
|
let method = "test_method_ok";
|
||
|
|
let timer = metrics::RequestTimer::new(method);
|
||
|
|
|
||
|
|
// Simulate some work
|
||
|
|
sleep(Duration::from_millis(10));
|
||
|
|
timer.finish_ok();
|
||
|
|
|
||
|
|
// Check counters
|
||
|
|
let started = metrics::GRPC_REQUESTS_TOTAL
|
||
|
|
.with_label_values(&[method, "started"])
|
||
|
|
.get();
|
||
|
|
let ok = metrics::GRPC_REQUESTS_TOTAL
|
||
|
|
.with_label_values(&[method, "ok"])
|
||
|
|
.get();
|
||
|
|
|
||
|
|
assert_eq!(started, 1.0);
|
||
|
|
assert_eq!(ok, 1.0);
|
||
|
|
}
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
fn test_metrics_request_timer_err() {
|
||
|
|
let method = "test_method_err";
|
||
|
|
let timer = metrics::RequestTimer::new(method);
|
||
|
|
|
||
|
|
// Simulate some work
|
||
|
|
sleep(Duration::from_millis(5));
|
||
|
|
timer.finish_err();
|
||
|
|
|
||
|
|
// Check counters
|
||
|
|
let started = metrics::GRPC_REQUESTS_TOTAL
|
||
|
|
.with_label_values(&[method, "started"])
|
||
|
|
.get();
|
||
|
|
let err = metrics::GRPC_REQUESTS_TOTAL
|
||
|
|
.with_label_values(&[method, "error"])
|
||
|
|
.get();
|
||
|
|
|
||
|
|
assert_eq!(started, 1.0);
|
||
|
|
assert_eq!(err, 1.0);
|
||
|
|
}
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
fn test_metrics_render() {
|
||
|
|
// Just trigger a metric to ensure the registry isn't empty
|
||
|
|
metrics::BYTES_READ_TOTAL.inc_by(4096.0);
|
||
|
|
|
||
|
|
let rendered = metrics::render_metrics();
|
||
|
|
assert!(rendered.contains("furumi_bytes_read_total"));
|
||
|
|
assert!(rendered.contains("4096"));
|
||
|
|
}
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
fn test_server_auth_interceptor_valid() {
|
||
|
|
let mut interceptor = AuthInterceptor::new("supersecret".to_string());
|
||
|
|
let mut req = Request::new(());
|
||
|
|
req.metadata_mut()
|
||
|
|
.insert("authorization", "Bearer supersecret".parse().unwrap());
|
||
|
|
|
||
|
|
let res = interceptor.call(req);
|
||
|
|
assert!(res.is_ok(), "Valid token should be accepted");
|
||
|
|
}
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
fn test_server_auth_interceptor_invalid() {
|
||
|
|
let mut interceptor = AuthInterceptor::new("supersecret".to_string());
|
||
|
|
let mut req = Request::new(());
|
||
|
|
req.metadata_mut()
|
||
|
|
.insert("authorization", "Bearer wrongtoken".parse().unwrap());
|
||
|
|
|
||
|
|
let res = interceptor.call(req);
|
||
|
|
assert!(res.is_err(), "Invalid token should be rejected");
|
||
|
|
assert_eq!(res.unwrap_err().code(), tonic::Code::Unauthenticated);
|
||
|
|
}
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
fn test_server_auth_interceptor_missing() {
|
||
|
|
let mut interceptor = AuthInterceptor::new("supersecret".to_string());
|
||
|
|
let req = Request::new(());
|
||
|
|
// Missing metadata entirely
|
||
|
|
|
||
|
|
let res = interceptor.call(req);
|
||
|
|
assert!(
|
||
|
|
res.is_err(),
|
||
|
|
"Missing token should be rejected when auth is enabled"
|
||
|
|
);
|
||
|
|
assert_eq!(res.unwrap_err().code(), tonic::Code::Unauthenticated);
|
||
|
|
}
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
fn test_server_auth_interceptor_disabled() {
|
||
|
|
// Empty string means auth is disabled
|
||
|
|
let mut interceptor = AuthInterceptor::new("".to_string());
|
||
|
|
let req = Request::new(());
|
||
|
|
|
||
|
|
let res = interceptor.call(req);
|
||
|
|
assert!(
|
||
|
|
res.is_ok(),
|
||
|
|
"Request should pass if auth is disabled on server"
|
||
|
|
);
|
||
|
|
}
|