Add hermetic coverage for service boundaries
This commit is contained in:
parent
19ac156f4b
commit
de4f990492
2 changed files with 137 additions and 0 deletions
|
|
@ -332,6 +332,38 @@ fn random_hex<const N: usize>() -> String {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use actix_web::{http::StatusCode, test as actix_test};
|
||||
|
||||
#[actix_web::test]
|
||||
async fn trace_header() {
|
||||
let app = actix_test::init_service(
|
||||
App::new()
|
||||
.wrap(from_fn(trace_request))
|
||||
.route("/", web::get().to(live)),
|
||||
)
|
||||
.await;
|
||||
let trace_id = "4bf92f3577b34da6a3ce929d0e0e4736";
|
||||
let request = actix_test::TestRequest::get()
|
||||
.uri("/")
|
||||
.insert_header(("traceparent", format!("00-{trace_id}-00f067aa0ba902b7-01")))
|
||||
.to_request();
|
||||
let response = actix_test::call_service(&app, request).await;
|
||||
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
let trace = response
|
||||
.headers()
|
||||
.get("traceparent")
|
||||
.unwrap()
|
||||
.to_str()
|
||||
.unwrap();
|
||||
assert!(trace.starts_with(&format!("00-{trace_id}-")));
|
||||
assert!(trace.ends_with("-01"));
|
||||
assert_eq!(trace.len(), 55);
|
||||
assert_eq!(
|
||||
actix_test::read_body(response).await,
|
||||
r#"{"status":"live"}"#
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn escapes_prometheus_labels() {
|
||||
|
|
|
|||
|
|
@ -250,3 +250,69 @@ fn generated_id(prefix: char) -> OpaqueId {
|
|||
}
|
||||
OpaqueId::parse(value).expect("generated identifier is valid")
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
fn response(status: StatusCode) -> Response {
|
||||
http::Response::builder()
|
||||
.status(status)
|
||||
.body(String::new())
|
||||
.unwrap()
|
||||
.into()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn classifies_statuses() {
|
||||
assert!(classify(response(StatusCode::NO_CONTENT)).is_ok());
|
||||
assert!(matches!(
|
||||
classify(response(StatusCode::BAD_REQUEST)),
|
||||
Err(WorkerError::InvalidRequest)
|
||||
));
|
||||
for status in [StatusCode::UNAUTHORIZED, StatusCode::FORBIDDEN] {
|
||||
assert!(matches!(
|
||||
classify(response(status)),
|
||||
Err(WorkerError::Unauthenticated)
|
||||
));
|
||||
}
|
||||
assert!(matches!(
|
||||
classify(response(StatusCode::CONFLICT)),
|
||||
Err(WorkerError::PreconditionFailed)
|
||||
));
|
||||
for status in [
|
||||
StatusCode::NOT_FOUND,
|
||||
StatusCode::TOO_MANY_REQUESTS,
|
||||
StatusCode::SERVICE_UNAVAILABLE,
|
||||
] {
|
||||
assert!(matches!(
|
||||
classify(response(status)),
|
||||
Err(WorkerError::ApiUnavailable)
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn validates_base_url() {
|
||||
let client = Client::new();
|
||||
let valid = WorkerApiClient::new("https://api.example.test/", client.clone()).unwrap();
|
||||
assert_eq!(valid.base_url, "https://api.example.test");
|
||||
for url in ["http://api.example.test", "https://", "not-a-url"] {
|
||||
assert!(matches!(
|
||||
WorkerApiClient::new(url, client.clone()),
|
||||
Err(WorkerError::InvalidConfiguration)
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ids_are_unique() {
|
||||
let operation = operation_id();
|
||||
let second = operation_id();
|
||||
let incarnation = incarnation_id();
|
||||
assert!(operation.as_str().starts_with('o'));
|
||||
assert!(incarnation.as_str().starts_with('w'));
|
||||
assert_ne!(operation, second);
|
||||
assert_ne!(operation, incarnation);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue