use std::time::Duration;
use http::{Request, Response};
use http_body_util::{BodyExt, Full};
use tower::service_fn;
use tower::{Layer, Service, ServiceExt};
use tower_http_cache::backend::memory::InMemoryBackend;
use tower_http_cache::prelude::*;
#[tokio::test]
async fn tag_extractor_populates_the_backend_tag_index() {
let backend = InMemoryBackend::new(32);
let policy = CachePolicy::default()
.with_tag_policy(TagPolicy::new().with_enabled(true))
.with_tag_extractor(|_method: &http::Method, uri: &http::Uri| {
vec![format!("path:{}", uri.path()), "tenant:acme".to_string()]
});
let layer = CacheLayer::builder(backend.clone())
.ttl(Duration::from_secs(60))
.policy(policy)
.build();
let mut service = layer.layer(service_fn(|_req: Request<()>| async move {
Ok::<_, std::convert::Infallible>(Response::new(Full::from("payload")))
}));
let response = service
.ready()
.await
.unwrap()
.call(Request::builder().uri("/api/widgets").body(()).unwrap())
.await
.unwrap();
let _ = response.into_body().collect().await.unwrap();
let mut tags = backend.list_tags().await.unwrap();
tags.sort();
assert_eq!(
tags,
vec!["path:/api/widgets".to_string(), "tenant:acme".to_string()],
"the layer must attach the extracted tags to the stored entry"
);
let keys = backend.get_keys_by_tag("tenant:acme").await.unwrap();
assert_eq!(keys.len(), 1, "the tag must map to the stored key");
let invalidated = backend.invalidate_by_tag("tenant:acme").await.unwrap();
assert_eq!(invalidated, 1);
assert!(backend.get(&keys[0]).await.unwrap().is_none());
}
#[tokio::test]
async fn default_tag_policy_leaves_the_index_empty() {
let backend = InMemoryBackend::new(32);
let policy =
CachePolicy::default().with_tag_extractor(|_method: &http::Method, _uri: &http::Uri| {
vec!["tenant:acme".to_string()]
});
let layer = CacheLayer::builder(backend.clone())
.ttl(Duration::from_secs(60))
.policy(policy)
.build();
let mut service = layer.layer(service_fn(|_req: Request<()>| async move {
Ok::<_, std::convert::Infallible>(Response::new(Full::from("payload")))
}));
let response = service
.ready()
.await
.unwrap()
.call(Request::builder().uri("/api/widgets").body(()).unwrap())
.await
.unwrap();
let _ = response.into_body().collect().await.unwrap();
assert!(
backend.list_tags().await.unwrap().is_empty(),
"tags must stay off unless TagPolicy::enabled is set"
);
}