Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 115 additions & 0 deletions contract/src/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,3 +134,118 @@ impl InMemoryCache {
Ok(())
}
}

#[cfg(test)]
mod tests {
use super::*;

fn in_memory_backend() -> CacheBackend {
CacheBackend::InMemory(InMemoryCache::new())
}

#[tokio::test]
async fn test_set_and_get_string() {
let cache = in_memory_backend();
cache.set("key1", &"hello".to_string(), 3600).await.unwrap();
let result: Option<String> = cache.get("key1").await.unwrap();
assert_eq!(result, Some("hello".to_string()));
}

#[tokio::test]
async fn test_get_miss_returns_none() {
let cache = in_memory_backend();
let result: Option<String> = cache.get("nonexistent").await.unwrap();
assert_eq!(result, None);
}

#[tokio::test]
async fn test_overwrite_value() {
let cache = in_memory_backend();
cache.set("key1", &"first".to_string(), 3600).await.unwrap();
cache.set("key1", &"second".to_string(), 3600).await.unwrap();
let result: Option<String> = cache.get("key1").await.unwrap();
assert_eq!(result, Some("second".to_string()));
}

#[tokio::test]
async fn test_delete_removes_key() {
let cache = in_memory_backend();
cache.set("key1", &"value".to_string(), 3600).await.unwrap();
cache.delete("key1").await.unwrap();
let result: Option<String> = cache.get("key1").await.unwrap();
assert_eq!(result, None);
}

#[tokio::test]
async fn test_multiple_keys_independent() {
let cache = in_memory_backend();
cache.set("a", &"1".to_string(), 3600).await.unwrap();
cache.set("b", &"2".to_string(), 3600).await.unwrap();
cache.set("c", &"3".to_string(), 3600).await.unwrap();

let a: Option<String> = cache.get("a").await.unwrap();
let b: Option<String> = cache.get("b").await.unwrap();
let c: Option<String> = cache.get("c").await.unwrap();

assert_eq!(a, Some("1".to_string()));
assert_eq!(b, Some("2".to_string()));
assert_eq!(c, Some("3".to_string()));
}

#[tokio::test]
async fn test_get_set_with_vec() {
let cache = in_memory_backend();
let data = vec![1u64, 2, 3, 4, 5];
cache.set("numbers", &data, 3600).await.unwrap();
let result: Option<Vec<u64>> = cache.get("numbers").await.unwrap();
assert_eq!(result, Some(data));
}

#[tokio::test]
async fn test_get_set_with_custom_struct() {
use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize, PartialEq)]
struct TestData {
name: String,
value: i32,
}

let cache = in_memory_backend();
let item = TestData {
name: "test".to_string(),
value: 42,
};
cache.set("struct_key", &item, 3600).await.unwrap();
let result: Option<TestData> = cache.get("struct_key").await.unwrap();
assert_eq!(result, Some(item));
}

#[tokio::test]
async fn test_in_memory_check_connection_always_true() {
let cache = in_memory_backend();
assert!(cache.check_connection().await);
}

#[tokio::test]
async fn test_delete_nonexistent_key_succeeds() {
let cache = in_memory_backend();
assert!(cache.delete("nonexistent").await.is_ok());
}

#[tokio::test]
async fn test_set_raw_and_get_raw() {
let cache = in_memory_backend();
cache.set_raw("raw_key", "raw_value", 3600).await.unwrap();
let result = cache.get_raw("raw_key").await.unwrap();
assert_eq!(result, Some("raw_value".to_string()));
}

#[tokio::test]
async fn test_cache_backend_enum_dispatch() {
let cache = in_memory_backend();
cache.set("enum_key", &"enum_value".to_string(), 3600).await.unwrap();
let result: Option<String> = cache.get("enum_key").await.unwrap();
assert_eq!(result, Some("enum_value".to_string()));
}
}
84 changes: 84 additions & 0 deletions contract/src/metrics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,87 @@ impl MetricsRegistry {
String::from_utf8(buffer).unwrap_or_default()
}
}

#[cfg(test)]
mod tests {
use super::*;
use axum::body::Body;
use axum::http::{Request, StatusCode};
use tower::ServiceExt;

#[test]
fn test_metrics_registry_new() {
let metrics = MetricsRegistry::new();
let output = metrics.render();
assert!(output.contains("requests_total"));
assert!(output.contains("cache_hits_total"));
assert!(output.contains("cache_misses_total"));
assert!(output.contains("errors_total"));
}

#[test]
fn test_increment_request_count() {
let metrics = MetricsRegistry::new();
metrics.increment_request_count();
metrics.increment_request_count();
metrics.increment_request_count();
let output = metrics.render();
assert!(output.contains("requests_total 3"));
}

#[test]
fn test_increment_cache_hits() {
let metrics = MetricsRegistry::new();
metrics.increment_cache_hits();
metrics.increment_cache_hits();
let output = metrics.render();
assert!(output.contains("cache_hits_total 2"));
}

#[test]
fn test_increment_cache_misses() {
let metrics = MetricsRegistry::new();
metrics.increment_cache_misses();
let output = metrics.render();
assert!(output.contains("cache_misses_total 1"));
}

#[test]
fn test_increment_error_count() {
let metrics = MetricsRegistry::new();
metrics.increment_error_count();
metrics.increment_error_count();
metrics.increment_error_count();
metrics.increment_error_count();
let output = metrics.render();
assert!(output.contains("errors_total 4"));
}

#[test]
fn test_default_trait() {
let metrics = MetricsRegistry::default();
let output = metrics.render();
assert!(output.contains("requests_total"));
}

#[test]
fn test_render_returns_valid_prometheus_text() {
let metrics = MetricsRegistry::new();
metrics.increment_request_count();
let output = metrics.render();
let lines: Vec<&str> = output.lines().collect();
assert!(!lines.is_empty());
let has_metric = lines.iter().any(|l| l.starts_with("requests_total"));
assert!(has_metric);
}

#[test]
fn test_multiple_increments_accumulate() {
let metrics = MetricsRegistry::new();
for _ in 0..10 {
metrics.increment_request_count();
}
let output = metrics.render();
assert!(output.contains("requests_total 10"));
}
}
31 changes: 31 additions & 0 deletions contract/src/rate_limit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,34 @@ pub fn build_rate_limiter(per_second: u32, burst: u32) -> DefaultRateLimiter {
.allow_burst(NonZeroU32::new(burst).unwrap());
RateLimiter::direct(quota)
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_build_rate_limiter_does_not_panic() {
let _limiter = build_rate_limiter(10, 10);
}

#[test]
fn test_rate_limiter_allows_first_request() {
let limiter = build_rate_limiter(10, 10);
assert!(limiter.check().is_ok());
}

#[test]
fn test_rate_limiter_allows_burst() {
let limiter = build_rate_limiter(10, 5);
for _ in 0..5 {
assert!(limiter.check().is_ok());
}
}

#[test]
fn test_build_rate_limiter_various_burst_values() {
let _l1 = build_rate_limiter(1, 1);
let _l2 = build_rate_limiter(100, 200);
let _l3 = build_rate_limiter(50, 50);
}
}
Loading