use mockforge_core::conditions::{evaluate_condition, ConditionContext};
use mockforge_core::routing::{HttpMethod, Route, RouteRegistry};
use mockforge_core::templating::expand_str;
use mockforge_core::validation::validate_json_schema;
use serde_json::json;
use std::sync::{Arc, Mutex};
use std::thread;
#[cfg(test)]
mod route_registry_concurrency {
use super::*;
#[test]
fn concurrent_route_addition() {
let registry = Arc::new(Mutex::new(RouteRegistry::new()));
let mut handles = vec![];
for i in 0..20 {
let registry_clone = Arc::clone(®istry);
let handle = thread::spawn(move || {
for j in 0..50 {
let route = Route::new(HttpMethod::GET, format!("/api/route_{}_{}", i, j));
let mut reg = registry_clone.lock().unwrap();
let _ = reg.add_http_route(route);
}
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
let reg = registry.lock().unwrap();
let _ = reg.find_http_routes(&HttpMethod::GET, "/api/route_0_0");
}
#[test]
fn concurrent_route_addition_and_lookup() {
let registry = Arc::new(Mutex::new(RouteRegistry::new()));
let mut handles = vec![];
for i in 0..10 {
let registry_clone = Arc::clone(®istry);
let handle = thread::spawn(move || {
for j in 0..100 {
let route = Route::new(HttpMethod::GET, format!("/api/add_{}_{}", i, j));
let mut reg = registry_clone.lock().unwrap();
let _ = reg.add_http_route(route);
}
});
handles.push(handle);
}
for _ in 0..10 {
let registry_clone = Arc::clone(®istry);
let handle = thread::spawn(move || {
for _ in 0..100 {
let reg = registry_clone.lock().unwrap();
let _ = reg.find_http_routes(&HttpMethod::GET, "/api/add_0_0");
}
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
}
#[test]
fn concurrent_route_clear_and_add() {
let registry = Arc::new(Mutex::new(RouteRegistry::new()));
let mut handles = vec![];
{
let mut reg = registry.lock().unwrap();
for i in 0..10 {
let route = Route::new(HttpMethod::GET, format!("/api/route_{}", i));
let _ = reg.add_http_route(route);
}
}
for i in 0..5 {
let registry_clone = Arc::clone(®istry);
let handle = thread::spawn(move || {
{
let mut reg = registry_clone.lock().unwrap();
reg.clear();
}
for j in 0..20 {
let route = Route::new(HttpMethod::GET, format!("/api/new_{}_{}", i, j));
let mut reg = registry_clone.lock().unwrap();
let _ = reg.add_http_route(route);
}
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
}
#[test]
fn concurrent_wildcard_route_matching() {
let registry = Arc::new(Mutex::new(RouteRegistry::new()));
{
let mut reg = registry.lock().unwrap();
let route1 = Route::new(HttpMethod::GET, "/api/*/users".to_string());
let route2 = Route::new(HttpMethod::GET, "/api/users/*".to_string());
let route3 = Route::new(HttpMethod::GET, "/api/*/users/*".to_string());
let _ = reg.add_http_route(route1);
let _ = reg.add_http_route(route2);
let _ = reg.add_http_route(route3);
}
let mut handles = vec![];
for _ in 0..20 {
let registry_clone = Arc::clone(®istry);
let handle = thread::spawn(move || {
for _ in 0..100 {
let reg = registry_clone.lock().unwrap();
let _ = reg.find_http_routes(&HttpMethod::GET, "/api/v1/users");
let _ = reg.find_http_routes(&HttpMethod::GET, "/api/users/123");
let _ = reg.find_http_routes(&HttpMethod::GET, "/api/v1/users/123");
}
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
}
}
#[cfg(test)]
mod condition_evaluation_concurrency {
use super::*;
#[test]
fn concurrent_condition_evaluation() {
let context = Arc::new(ConditionContext::new());
let mut handles = vec![];
for _ in 0..20 {
let context_clone = Arc::clone(&context);
let handle = thread::spawn(move || {
for _ in 0..100 {
let _ = evaluate_condition("true", &context_clone);
let _ = evaluate_condition("false", &context_clone);
let _ = evaluate_condition("$.field == value", &context_clone);
let _ = evaluate_condition("headers.test.exists", &context_clone);
}
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
}
#[test]
fn concurrent_condition_evaluation_with_shared_context() {
let context = Arc::new(
ConditionContext::new()
.with_request_body(json!({"id": 123, "name": "test"}))
.with_response_body(json!({"status": "ok"})),
);
let mut handles = vec![];
for i in 0..20 {
let context_clone = Arc::clone(&context);
let handle = thread::spawn(move || {
for j in 0..50 {
let condition = format!("$.id == {}", i * 50 + j);
let _ = evaluate_condition(&condition, &context_clone);
}
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
}
#[test]
fn concurrent_complex_condition_evaluation() {
let context = Arc::new(ConditionContext::new().with_request_body(json!({
"user": {"id": 123, "name": "test"},
"items": [1, 2, 3, 4, 5]
})));
let mut handles = vec![];
for _ in 0..10 {
let context_clone = Arc::clone(&context);
let handle = thread::spawn(move || {
for _ in 0..100 {
let _ = evaluate_condition("$.user.id == 123", &context_clone);
let _ = evaluate_condition("$.items.length > 0", &context_clone);
let _ = evaluate_condition(
"AND($.user.id == 123, $.items.length > 0)",
&context_clone,
);
let _ = evaluate_condition(
"OR($.user.id == 123, $.items.length == 0)",
&context_clone,
);
}
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
}
}
#[cfg(test)]
mod validation_concurrency {
use super::*;
#[test]
fn concurrent_schema_validation() {
let schema = Arc::new(json!({
"type": "object",
"properties": {
"id": {"type": "integer"},
"name": {"type": "string"}
},
"required": ["id", "name"]
}));
let mut handles = vec![];
for i in 0..20 {
let schema_clone = Arc::clone(&schema);
let handle = thread::spawn(move || {
for j in 0..50 {
let data = json!({
"id": i * 50 + j,
"name": format!("test_{}", j)
});
let _ = validate_json_schema(&data, &schema_clone);
}
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
}
#[test]
fn concurrent_validation_with_different_schemas() {
let mut handles = vec![];
for i in 0..10 {
let handle = thread::spawn(move || {
let schema = json!({
"type": "object",
"properties": {
"value": {"type": "integer", "minimum": 0, "maximum": 1000}
}
});
for j in 0..100 {
let data = json!({
"value": (i * 100 + j) % 1000
});
let _ = validate_json_schema(&data, &schema);
}
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
}
}
#[cfg(test)]
mod template_expansion_concurrency {
use super::*;
#[test]
fn concurrent_template_expansion() {
let mut handles = vec![];
for _i in 0..20 {
let handle = thread::spawn(move || {
for j in 0..50 {
let template = format!("Hello {{name}}_{}", j);
let _ = expand_str(&template);
}
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
}
#[test]
fn concurrent_complex_template_expansion() {
let mut handles = vec![];
for _ in 0..10 {
let handle = thread::spawn(move || {
for _ in 0..100 {
let templates = vec![
"{{field}}",
"{{nested.field}}",
"{{array.0}}",
"{{field}}_{{other}}",
"{{#if condition}}{{value}}{{/if}}",
];
for template in templates {
let _ = expand_str(template);
}
}
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
}
}
#[cfg(test)]
mod mixed_operations_concurrency {
use super::*;
#[test]
fn concurrent_mixed_operations() {
let registry = Arc::new(Mutex::new(RouteRegistry::new()));
let context = Arc::new(ConditionContext::new());
let schema = Arc::new(json!({
"type": "object",
"properties": {
"test": {"type": "string"}
}
}));
let mut handles = vec![];
for i in 0..5 {
let registry_clone = Arc::clone(®istry);
let handle = thread::spawn(move || {
for j in 0..20 {
let route = Route::new(HttpMethod::GET, format!("/api/route_{}_{}", i, j));
let mut reg = registry_clone.lock().unwrap();
let _ = reg.add_http_route(route);
}
});
handles.push(handle);
}
for _ in 0..5 {
let context_clone = Arc::clone(&context);
let handle = thread::spawn(move || {
for _ in 0..100 {
let _ = evaluate_condition("true", &context_clone);
}
});
handles.push(handle);
}
for _ in 0..5 {
let schema_clone = Arc::clone(&schema);
let handle = thread::spawn(move || {
for _ in 0..100 {
let data = json!({"test": "value"});
let _ = validate_json_schema(&data, &schema_clone);
}
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
}
}
#[cfg(test)]
mod stress_tests {
use super::*;
#[test]
fn high_contention_route_registry() {
let registry = Arc::new(Mutex::new(RouteRegistry::new()));
let mut handles = vec![];
for i in 0..50 {
let registry_clone = Arc::clone(®istry);
let handle = thread::spawn(move || {
for j in 0..100 {
{
let route = Route::new(HttpMethod::GET, format!("/api/route_{}_{}", i, j));
let mut reg = registry_clone.lock().unwrap();
let _ = reg.add_http_route(route);
}
{
let reg = registry_clone.lock().unwrap();
let _ = reg.find_http_routes(&HttpMethod::GET, "/api/route_0_0");
}
}
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
let reg = registry.lock().unwrap();
let _ = reg.find_http_routes(&HttpMethod::GET, "/api/route_0_0");
}
#[test]
fn rapid_route_churn() {
let registry = Arc::new(Mutex::new(RouteRegistry::new()));
let mut handles = vec![];
for i in 0..10 {
let registry_clone = Arc::clone(®istry);
let handle = thread::spawn(move || {
for _ in 0..50 {
for j in 0..10 {
let route = Route::new(HttpMethod::GET, format!("/api/route_{}_{}", i, j));
let mut reg = registry_clone.lock().unwrap();
let _ = reg.add_http_route(route);
}
{
let mut reg = registry_clone.lock().unwrap();
reg.clear();
}
}
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
}
}
#[cfg(test)]
mod data_race_prevention {
use super::*;
#[test]
fn verify_no_data_races_in_condition_evaluation() {
let context = Arc::new(ConditionContext::new().with_request_body(json!({"value": 42})));
let mut handles = vec![];
for _ in 0..100 {
let context_clone = Arc::clone(&context);
let handle = thread::spawn(move || {
evaluate_condition("$.value == 42", &context_clone)
});
handles.push(handle);
}
let mut results = vec![];
for handle in handles {
results.push(handle.join().unwrap());
}
let first_result = results[0].as_ref().ok();
for result in results.iter().skip(1) {
let result_bool = result.as_ref().ok();
assert_eq!(
result_bool, first_result,
"Condition evaluation should be consistent across threads"
);
}
}
#[test]
fn verify_route_registry_consistency() {
let registry = Arc::new(Mutex::new(RouteRegistry::new()));
{
let mut reg = registry.lock().unwrap();
for i in 0..10 {
let route = Route::new(HttpMethod::GET, format!("/api/route_{}", i));
let _ = reg.add_http_route(route);
}
}
let mut handles = vec![];
for _ in 0..20 {
let registry_clone = Arc::clone(®istry);
let handle = thread::spawn(move || {
let reg = registry_clone.lock().unwrap();
let routes = reg.find_http_routes(&HttpMethod::GET, "/api/route_0");
assert!(!routes.is_empty());
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
}
}