use crate::cache::{Cache, CachedResponse, ResponseCache};
use crate::failure_analysis::FailureContextCollector;
use crate::performance::PerformanceMonitor;
use crate::templating::TemplateEngine;
use crate::workspace::core::{EntityId, Folder, MockRequest, MockResponse, Workspace};
use crate::{
routing::{HttpMethod, Route, RouteRegistry},
Error, Result,
};
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::sync::Arc;
use std::time::Duration;
#[derive(Debug, Clone)]
pub struct RequestExecutionResult {
pub request_id: EntityId,
pub response: Option<MockResponse>,
pub duration_ms: u64,
pub success: bool,
pub error: Option<String>,
pub failure_context: Option<crate::failure_analysis::FailureContext>,
}
#[derive(Debug, Clone)]
pub struct RequestMatchCriteria {
pub method: HttpMethod,
pub path: String,
pub query_params: HashMap<String, String>,
pub headers: HashMap<String, String>,
pub body: Option<String>,
}
#[derive(Debug, Clone)]
pub struct RequestProcessor {
_template_engine: TemplateEngine,
environment_manager: Option<crate::workspace::environment::EnvironmentManager>,
performance_monitor: Arc<PerformanceMonitor>,
response_cache: Arc<ResponseCache>,
validation_cache: Arc<Cache<String, RequestValidationResult>>,
optimizations_enabled: bool,
failure_collector: Option<Arc<FailureContextCollector>>,
}
#[derive(Debug, Clone)]
pub struct RequestValidationResult {
pub is_valid: bool,
pub errors: Vec<String>,
pub warnings: Vec<String>,
}
#[derive(Debug, Clone)]
pub struct RequestExecutionContext {
pub workspace_id: EntityId,
pub environment_variables: HashMap<String, String>,
pub global_headers: HashMap<String, String>,
pub timeout_seconds: u64,
pub ssl_verify: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RequestMetrics {
pub total_requests: u64,
pub successful_requests: u64,
pub failed_requests: u64,
pub average_response_time_ms: f64,
pub popular_requests: Vec<(EntityId, u64)>,
pub last_execution: Option<DateTime<Utc>>,
}
impl RequestProcessor {
pub fn new() -> Self {
Self {
_template_engine: TemplateEngine::new(),
environment_manager: None,
performance_monitor: Arc::new(PerformanceMonitor::new()),
response_cache: Arc::new(ResponseCache::new(1000, Duration::from_secs(300))), validation_cache: Arc::new(Cache::with_ttl(500, Duration::from_secs(60))), optimizations_enabled: true,
failure_collector: Some(Arc::new(FailureContextCollector::new())),
}
}
pub fn with_environment_manager(
environment_manager: crate::workspace::environment::EnvironmentManager,
) -> Self {
Self {
_template_engine: TemplateEngine::new(),
environment_manager: Some(environment_manager),
performance_monitor: Arc::new(PerformanceMonitor::new()),
response_cache: Arc::new(ResponseCache::new(1000, Duration::from_secs(300))),
validation_cache: Arc::new(Cache::with_ttl(500, Duration::from_secs(60))),
optimizations_enabled: true,
failure_collector: Some(Arc::new(FailureContextCollector::new())),
}
}
pub fn with_performance_config(
environment_manager: Option<crate::workspace::environment::EnvironmentManager>,
cache_size: usize,
cache_ttl: Duration,
enable_optimizations: bool,
) -> Self {
Self {
_template_engine: TemplateEngine::new(),
environment_manager,
performance_monitor: Arc::new(PerformanceMonitor::new()),
response_cache: Arc::new(ResponseCache::new(cache_size, cache_ttl)),
validation_cache: Arc::new(Cache::with_ttl(cache_size / 2, Duration::from_secs(60))),
optimizations_enabled: enable_optimizations,
failure_collector: Some(Arc::new(FailureContextCollector::new())),
}
}
pub fn performance_monitor(&self) -> Arc<PerformanceMonitor> {
self.performance_monitor.clone()
}
pub fn set_optimizations_enabled(&mut self, enabled: bool) {
self.optimizations_enabled = enabled;
}
pub fn find_matching_request(
&self,
workspace: &Workspace,
criteria: &RequestMatchCriteria,
) -> Option<EntityId> {
for request in &workspace.requests {
if self.request_matches(request, criteria) {
return Some(request.id.clone());
}
}
if let Some(request_id) =
self.find_matching_request_in_folders(&workspace.folders, criteria)
{
return Some(request_id);
}
None
}
fn request_matches(&self, request: &MockRequest, criteria: &RequestMatchCriteria) -> bool {
if request.method != criteria.method {
return false;
}
if !self.url_matches_pattern(&request.url, &criteria.path) {
return false;
}
for (key, expected_value) in &criteria.query_params {
if let Some(actual_value) = request.query_params.get(key) {
if actual_value != expected_value {
return false;
}
} else {
return false;
}
}
for (key, expected_value) in &criteria.headers {
if let Some(actual_value) = request.headers.get(key) {
if actual_value != expected_value {
return false;
}
} else {
return false;
}
}
true
}
pub fn url_matches_pattern(&self, pattern: &str, url: &str) -> bool {
if pattern == url {
return true;
}
if pattern == "*" {
return true;
}
if pattern.contains('*') {
return self.matches_path_pattern(pattern, url);
}
false
}
fn matches_path_pattern(&self, pattern: &str, path: &str) -> bool {
let pattern_parts: Vec<&str> = pattern.split('/').filter(|s| !s.is_empty()).collect();
let path_parts: Vec<&str> = path.split('/').filter(|s| !s.is_empty()).collect();
self.match_segments(&pattern_parts, &path_parts, 0, 0)
}
#[allow(clippy::only_used_in_recursion)]
fn match_segments(
&self,
pattern_parts: &[&str],
path_parts: &[&str],
pattern_idx: usize,
path_idx: usize,
) -> bool {
if pattern_idx == pattern_parts.len() && path_idx == path_parts.len() {
return true;
}
if pattern_idx == pattern_parts.len() {
return false;
}
let current_pattern = pattern_parts[pattern_idx];
match current_pattern {
"*" => {
if path_idx < path_parts.len() {
if self.match_segments(pattern_parts, path_parts, pattern_idx + 1, path_idx + 1)
{
return true;
}
}
false
}
"**" => {
if self.match_segments(pattern_parts, path_parts, pattern_idx + 1, path_idx) {
return true;
}
if path_idx < path_parts.len()
&& self.match_segments(pattern_parts, path_parts, pattern_idx, path_idx + 1)
{
return true;
}
false
}
_ => {
if path_idx < path_parts.len() && current_pattern == path_parts[path_idx] {
return self.match_segments(
pattern_parts,
path_parts,
pattern_idx + 1,
path_idx + 1,
);
}
false
}
}
}
fn find_matching_request_in_folders(
&self,
folders: &[Folder],
criteria: &RequestMatchCriteria,
) -> Option<EntityId> {
for folder in folders {
for request in &folder.requests {
if self.request_matches(request, criteria) {
return Some(request.id.clone());
}
}
if let Some(request_id) =
self.find_matching_request_in_folders(&folder.folders, criteria)
{
return Some(request_id);
}
}
None
}
pub async fn execute_request(
&self,
workspace: &mut Workspace,
request_id: &EntityId,
context: &RequestExecutionContext,
) -> Result<RequestExecutionResult> {
let _perf_guard = if self.optimizations_enabled {
self.performance_monitor.start_tracking_named("execute_request")
} else {
None
};
let cache_key = if self.optimizations_enabled {
self.generate_response_cache_key(request_id, context)
} else {
String::new()
};
if self.optimizations_enabled && !cache_key.is_empty() {
if let Some(cached_response) = self.response_cache.get_response(&cache_key).await {
self.performance_monitor.record_cache_hit();
return Ok(RequestExecutionResult {
request_id: request_id.clone(),
response: Some(self.convert_cached_response_to_mock_response(cached_response)),
duration_ms: 1, success: true,
error: None,
failure_context: None,
});
} else {
self.performance_monitor.record_cache_miss();
}
}
let request = match self.find_request_in_workspace(workspace, request_id) {
Some(req) => req,
None => {
if self.optimizations_enabled {
self.performance_monitor.record_error();
}
let error_msg = format!("Request with ID {} not found", request_id);
if let Some(ref collector) = self.failure_collector {
let _failure_context = collector
.collect_context(
"UNKNOWN",
&request_id.to_string(),
None,
Some(error_msg.clone()),
)
.ok();
}
return Err(Error::internal(error_msg));
}
};
let start_time = std::time::Instant::now();
let method = "GET"; let path = request_id.to_string();
let validation = match self.validate_request_cached(request, context).await {
Ok(v) => v,
Err(e) => {
if self.optimizations_enabled {
self.performance_monitor.record_error();
}
let error_msg = format!("Request validation error: {}", e);
if let Some(ref collector) = self.failure_collector {
let _failure_context = collector
.collect_context(method, &path, None, Some(error_msg.clone()))
.ok();
}
return Err(e);
}
};
if !validation.is_valid {
if self.optimizations_enabled {
self.performance_monitor.record_error();
}
let error_msg = format!("Request validation failed: {:?}", validation.errors);
if let Some(ref collector) = self.failure_collector {
let _failure_context =
collector.collect_context(method, &path, None, Some(error_msg.clone())).ok();
}
return Err(Error::Validation { message: error_msg });
}
let response = match request.active_response() {
Some(resp) => resp,
None => {
if self.optimizations_enabled {
self.performance_monitor.record_error();
}
let error_msg = "No active response found for request".to_string();
if let Some(ref collector) = self.failure_collector {
let _failure_context = collector
.collect_context(method, &path, None, Some(error_msg.clone()))
.ok();
}
return Err(Error::internal(error_msg));
}
};
let processed_response = match self.process_response(response, context).await {
Ok(resp) => resp,
Err(e) => {
if self.optimizations_enabled {
self.performance_monitor.record_error();
}
let error_msg = format!("Failed to process response: {}", e);
if let Some(ref collector) = self.failure_collector {
let _failure_context = collector
.collect_context(method, &path, None, Some(error_msg.clone()))
.ok();
}
return Err(e);
}
};
let duration_ms = start_time.elapsed().as_millis() as u64;
if self.optimizations_enabled && !cache_key.is_empty() {
let cached_response =
self.convert_mock_response_to_cached_response(&processed_response);
self.response_cache.cache_response(cache_key, cached_response).await;
}
if let Some(request_mut) = self.find_request_in_workspace_mut(workspace, request_id) {
if let Some(response_mut) = request_mut.active_response_mut() {
response_mut.record_usage(request_id.clone(), duration_ms);
}
}
Ok(RequestExecutionResult {
request_id: request_id.clone(),
response: Some(processed_response),
duration_ms,
success: true,
error: None,
failure_context: None,
})
}
fn find_request_in_workspace_mut<'a>(
&self,
workspace: &'a mut Workspace,
request_id: &EntityId,
) -> Option<&'a mut MockRequest> {
for request in &mut workspace.requests {
if &request.id == request_id {
return Some(request);
}
}
self.find_request_in_folders_mut(&mut workspace.folders, request_id)
}
#[allow(clippy::only_used_in_recursion)]
fn find_request_in_folders_mut<'a>(
&self,
folders: &'a mut [Folder],
request_id: &EntityId,
) -> Option<&'a mut MockRequest> {
for folder in folders {
for request in &mut folder.requests {
if &request.id == request_id {
return Some(request);
}
}
if let Some(request) = self.find_request_in_folders_mut(&mut folder.folders, request_id)
{
return Some(request);
}
}
None
}
fn find_request_in_workspace<'a>(
&self,
workspace: &'a Workspace,
request_id: &EntityId,
) -> Option<&'a MockRequest> {
workspace
.requests
.iter()
.find(|r| &r.id == request_id)
.or_else(|| self.find_request_in_folders(&workspace.folders, request_id))
}
#[allow(clippy::only_used_in_recursion)]
fn find_request_in_folders<'a>(
&self,
folders: &'a [Folder],
request_id: &EntityId,
) -> Option<&'a MockRequest> {
for folder in folders {
if let Some(request) = folder.requests.iter().find(|r| &r.id == request_id) {
return Some(request);
}
if let Some(request) = self.find_request_in_folders(&folder.folders, request_id) {
return Some(request);
}
}
None
}
pub fn validate_request(
&self,
request: &MockRequest,
_context: &RequestExecutionContext,
) -> RequestValidationResult {
let mut errors = Vec::new();
let mut warnings = Vec::new();
if !request.enabled {
errors.push("Request is disabled".to_string());
}
if request.url.is_empty() {
errors.push("Request URL cannot be empty".to_string());
}
match request.method {
HttpMethod::GET
| HttpMethod::POST
| HttpMethod::PUT
| HttpMethod::DELETE
| HttpMethod::PATCH
| HttpMethod::HEAD
| HttpMethod::OPTIONS => {
}
}
if request.active_response().is_none() {
warnings.push("No active response configured".to_string());
}
for response in &request.responses {
if response.status_code < 100 || response.status_code > 599 {
errors.push(format!("Invalid status code: {}", response.status_code));
}
if response.body.is_empty() {
warnings.push(format!("Response '{}' has empty body", response.name));
}
}
RequestValidationResult {
is_valid: errors.is_empty(),
errors,
warnings,
}
}
async fn process_response(
&self,
response: &MockResponse,
context: &RequestExecutionContext,
) -> Result<MockResponse> {
if response.delay > 0 {
tokio::time::sleep(Duration::from_millis(response.delay)).await;
}
let mut processed_response = response.clone();
if let Some(env_manager) = &self.environment_manager {
if let Some(_env_vars) = self.get_environment_variables(context) {
processed_response.body = env_manager.substitute_variables(&response.body).value;
}
}
Ok(processed_response)
}
fn get_environment_variables(
&self,
context: &RequestExecutionContext,
) -> Option<HashMap<String, String>> {
if let Some(env_manager) = &self.environment_manager {
if let Some(active_env) = env_manager.get_active_environment() {
return Some(active_env.variables.clone());
}
}
Some(context.environment_variables.clone())
}
pub fn get_request_metrics(&self, workspace: &Workspace) -> RequestMetrics {
let mut total_requests = 0u64;
let mut successful_requests = 0u64;
let mut failed_requests = 0u64;
let mut total_response_time = 0u64;
let mut request_counts = HashMap::new();
let mut last_execution: Option<DateTime<Utc>> = None;
for request in &workspace.requests {
total_requests += 1;
for response in &request.responses {
let execution_count = response.history.len() as u64;
*request_counts.entry(request.id.clone()).or_insert(0) += execution_count;
for entry in &response.history {
total_response_time += entry.duration_ms;
if let Some(current_last) = last_execution {
if entry.timestamp > current_last {
last_execution = Some(entry.timestamp);
}
} else {
last_execution = Some(entry.timestamp);
}
if entry.duration_ms < 5000 {
successful_requests += 1;
} else {
failed_requests += 1;
}
}
}
}
self.collect_folder_request_metrics(
&workspace.folders,
&mut total_requests,
&mut successful_requests,
&mut failed_requests,
&mut total_response_time,
&mut request_counts,
&mut last_execution,
);
let average_response_time = if total_requests > 0 {
total_response_time as f64 / total_requests as f64
} else {
0.0
};
let mut popular_requests: Vec<_> = request_counts.into_iter().collect();
popular_requests.sort_by(|a, b| b.1.cmp(&a.1));
popular_requests.truncate(5);
RequestMetrics {
total_requests,
successful_requests,
failed_requests,
average_response_time_ms: average_response_time,
popular_requests,
last_execution,
}
}
#[allow(clippy::only_used_in_recursion)]
#[allow(clippy::too_many_arguments)]
fn collect_folder_request_metrics(
&self,
folders: &[Folder],
total_requests: &mut u64,
successful_requests: &mut u64,
failed_requests: &mut u64,
total_response_time: &mut u64,
request_counts: &mut HashMap<EntityId, u64>,
last_execution: &mut Option<DateTime<Utc>>,
) {
for folder in folders {
for request in &folder.requests {
*total_requests += 1;
for response in &request.responses {
let execution_count = response.history.len() as u64;
*request_counts.entry(request.id.clone()).or_insert(0) += execution_count;
for entry in &response.history {
*total_response_time += entry.duration_ms;
if let Some(current_last) = *last_execution {
if entry.timestamp > current_last {
*last_execution = Some(entry.timestamp);
}
} else {
*last_execution = Some(entry.timestamp);
}
if entry.duration_ms < 5000 {
*successful_requests += 1;
} else {
*failed_requests += 1;
}
}
}
}
self.collect_folder_request_metrics(
&folder.folders,
total_requests,
successful_requests,
failed_requests,
total_response_time,
request_counts,
last_execution,
);
}
}
pub fn create_route_from_request(&self, request: &MockRequest) -> Result<Route> {
if !request.enabled {
return Err(Error::validation("Request is disabled"));
}
let response = request
.active_response()
.ok_or_else(|| Error::validation("No active response found"))?;
let mut route = Route::new(request.method.clone(), request.url.clone());
route.metadata.insert("id".to_string(), serde_json::json!(request.id));
route.metadata.insert("response".to_string(), serde_json::json!(response.body));
route
.metadata
.insert("status_code".to_string(), serde_json::json!(response.status_code));
route.metadata.insert("headers".to_string(), serde_json::json!(request.headers));
route
.metadata
.insert("query_params".to_string(), serde_json::json!(request.query_params));
route.metadata.insert("enabled".to_string(), serde_json::json!(request.enabled));
route
.metadata
.insert("created_at".to_string(), serde_json::json!(request.created_at));
route
.metadata
.insert("updated_at".to_string(), serde_json::json!(request.updated_at));
Ok(route)
}
pub fn update_route_registry(
&self,
workspace: &Workspace,
route_registry: &mut RouteRegistry,
) -> Result<()> {
route_registry.clear();
for request in &workspace.requests {
if request.enabled {
if let Ok(route) = self.create_route_from_request(request) {
let _ = route_registry.add_route(route);
}
}
}
self.add_folder_routes_to_registry(&workspace.folders, route_registry)?;
Ok(())
}
fn add_folder_routes_to_registry(
&self,
folders: &[Folder],
route_registry: &mut RouteRegistry,
) -> Result<()> {
for folder in folders {
for request in &folder.requests {
if request.enabled {
if let Ok(route) = self.create_route_from_request(request) {
let _ = route_registry.add_route(route);
}
}
}
self.add_folder_routes_to_registry(&folder.folders, route_registry)?;
}
Ok(())
}
fn generate_response_cache_key(
&self,
request_id: &EntityId,
context: &RequestExecutionContext,
) -> String {
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};
let mut hasher = DefaultHasher::new();
request_id.hash(&mut hasher);
context.workspace_id.hash(&mut hasher);
for (key, value) in &context.environment_variables {
key.hash(&mut hasher);
value.hash(&mut hasher);
}
for (key, value) in &context.global_headers {
key.hash(&mut hasher);
value.hash(&mut hasher);
}
format!("req_{}_{}", hasher.finish(), request_id)
}
async fn validate_request_cached(
&self,
request: &MockRequest,
context: &RequestExecutionContext,
) -> Result<RequestValidationResult> {
if !self.optimizations_enabled {
return Ok(self.validate_request(request, context));
}
let cache_key = format!("val_{}_{}", request.id, context.workspace_id);
if let Some(cached_result) = self.validation_cache.get(&cache_key).await {
return Ok(cached_result);
}
let result = self.validate_request(request, context);
self.validation_cache.insert(cache_key, result.clone(), None).await;
Ok(result)
}
fn convert_mock_response_to_cached_response(&self, response: &MockResponse) -> CachedResponse {
CachedResponse {
status_code: response.status_code,
headers: response.headers.clone(),
body: response.body.clone(),
content_type: response.headers.get("Content-Type").cloned(),
}
}
fn convert_cached_response_to_mock_response(&self, cached: CachedResponse) -> MockResponse {
MockResponse {
id: EntityId::new(),
name: "Cached Response".to_string(),
status_code: cached.status_code,
headers: cached.headers,
body: cached.body,
delay: 0, active: true,
created_at: Utc::now(),
updated_at: Utc::now(),
history: Vec::new(),
intelligent: None,
drift: None,
}
}
pub async fn get_performance_summary(&self) -> crate::performance::PerformanceSummary {
self.performance_monitor.get_summary().await
}
pub async fn get_cache_stats(&self) -> (crate::cache::CacheStats, crate::cache::CacheStats) {
let response_cache_stats = self.response_cache.stats().await;
let validation_cache_stats = self.validation_cache.stats().await;
(response_cache_stats, validation_cache_stats)
}
pub async fn clear_caches(&self) {
self.response_cache.clear().await;
self.validation_cache.clear().await;
}
}
impl Default for RequestProcessor {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::workspace::core::MockRequest;
use crate::workspace::environment::EnvironmentManager;
#[test]
fn test_request_processor_new() {
let processor = RequestProcessor::new();
let _monitor = processor.performance_monitor(); assert!(processor.optimizations_enabled);
assert!(processor.environment_manager.is_none());
}
#[test]
fn test_request_processor_default() {
let processor = RequestProcessor::default();
let _monitor = processor.performance_monitor(); assert!(processor.optimizations_enabled);
}
#[test]
fn test_request_processor_with_environment_manager() {
let env_manager = EnvironmentManager::new();
let processor = RequestProcessor::with_environment_manager(env_manager);
assert!(processor.environment_manager.is_some());
assert!(processor.optimizations_enabled);
}
#[test]
fn test_request_processor_with_performance_config() {
let processor =
RequestProcessor::with_performance_config(None, 500, Duration::from_secs(120), false);
assert!(!processor.optimizations_enabled);
assert!(processor.environment_manager.is_none());
}
#[test]
fn test_request_processor_with_performance_config_with_env() {
let env_manager = EnvironmentManager::new();
let processor = RequestProcessor::with_performance_config(
Some(env_manager),
2000,
Duration::from_secs(600),
true,
);
assert!(processor.optimizations_enabled);
assert!(processor.environment_manager.is_some());
}
#[test]
fn test_performance_monitor_accessor() {
let processor = RequestProcessor::new();
let monitor = processor.performance_monitor();
assert!(!Arc::ptr_eq(&monitor, &Arc::new(PerformanceMonitor::new())));
}
#[test]
fn test_set_optimizations_enabled() {
let mut processor = RequestProcessor::new();
assert!(processor.optimizations_enabled);
processor.set_optimizations_enabled(false);
assert!(!processor.optimizations_enabled);
processor.set_optimizations_enabled(true);
assert!(processor.optimizations_enabled);
}
#[test]
fn test_request_match_criteria_creation() {
let mut query_params = HashMap::new();
query_params.insert("key".to_string(), "value".to_string());
let mut headers = HashMap::new();
headers.insert("Content-Type".to_string(), "application/json".to_string());
let criteria = RequestMatchCriteria {
method: HttpMethod::GET,
path: "/api/test".to_string(),
query_params,
headers,
body: Some(r#"{"test": "data"}"#.to_string()),
};
assert_eq!(criteria.method, HttpMethod::GET);
assert_eq!(criteria.path, "/api/test");
assert_eq!(criteria.query_params.len(), 1);
assert_eq!(criteria.headers.len(), 1);
assert!(criteria.body.is_some());
}
#[test]
fn test_request_validation_result_creation() {
let result = RequestValidationResult {
is_valid: true,
errors: vec![],
warnings: vec!["Warning message".to_string()],
};
assert!(result.is_valid);
assert!(result.errors.is_empty());
assert_eq!(result.warnings.len(), 1);
}
#[test]
fn test_request_validation_result_with_errors() {
let result = RequestValidationResult {
is_valid: false,
errors: vec!["Error 1".to_string(), "Error 2".to_string()],
warnings: vec![],
};
assert!(!result.is_valid);
assert_eq!(result.errors.len(), 2);
assert!(result.warnings.is_empty());
}
#[test]
fn test_request_execution_context_creation() {
let mut env_vars = HashMap::new();
env_vars.insert("API_KEY".to_string(), "secret123".to_string());
let mut global_headers = HashMap::new();
global_headers.insert("X-Request-ID".to_string(), "req-123".to_string());
let context = RequestExecutionContext {
workspace_id: EntityId::new(),
environment_variables: env_vars,
global_headers,
timeout_seconds: 30,
ssl_verify: true,
};
assert_eq!(context.timeout_seconds, 30);
assert!(context.ssl_verify);
assert_eq!(context.environment_variables.len(), 1);
assert_eq!(context.global_headers.len(), 1);
}
#[test]
fn test_request_metrics_creation() {
let metrics = RequestMetrics {
total_requests: 100,
successful_requests: 95,
failed_requests: 5,
average_response_time_ms: 125.5,
popular_requests: vec![(EntityId::new(), 10), (EntityId::new(), 8)],
last_execution: Some(Utc::now()),
};
assert_eq!(metrics.total_requests, 100);
assert_eq!(metrics.successful_requests, 95);
assert_eq!(metrics.failed_requests, 5);
assert_eq!(metrics.average_response_time_ms, 125.5);
assert_eq!(metrics.popular_requests.len(), 2);
assert!(metrics.last_execution.is_some());
}
#[test]
fn test_request_execution_result_creation() {
let result = RequestExecutionResult {
request_id: EntityId::new(),
response: None,
duration_ms: 150,
success: true,
error: None,
failure_context: None,
};
assert!(result.success);
assert_eq!(result.duration_ms, 150);
assert!(result.error.is_none());
assert!(result.failure_context.is_none());
}
#[test]
fn test_request_execution_result_with_error() {
let result = RequestExecutionResult {
request_id: EntityId::new(),
response: None,
duration_ms: 50,
success: false,
error: Some("Request failed".to_string()),
failure_context: None,
};
assert!(!result.success);
assert!(result.error.is_some());
assert_eq!(result.error.unwrap(), "Request failed");
}
#[tokio::test]
async fn test_clear_caches() {
let processor = RequestProcessor::new();
processor.clear_caches().await;
}
#[test]
fn test_request_execution_result_clone() {
let result1 = RequestExecutionResult {
request_id: EntityId::new(),
response: None,
duration_ms: 100,
success: true,
error: None,
failure_context: None,
};
let result2 = result1.clone();
assert_eq!(result1.success, result2.success);
assert_eq!(result1.duration_ms, result2.duration_ms);
}
#[test]
fn test_request_execution_result_debug() {
let result = RequestExecutionResult {
request_id: EntityId::new(),
response: None,
duration_ms: 100,
success: true,
error: None,
failure_context: None,
};
let debug_str = format!("{:?}", result);
assert!(debug_str.contains("RequestExecutionResult"));
}
#[test]
fn test_request_match_criteria_clone() {
let criteria1 = RequestMatchCriteria {
method: HttpMethod::GET,
path: "/test".to_string(),
query_params: HashMap::new(),
headers: HashMap::new(),
body: None,
};
let criteria2 = criteria1.clone();
assert_eq!(criteria1.method, criteria2.method);
assert_eq!(criteria1.path, criteria2.path);
}
#[test]
fn test_request_match_criteria_debug() {
let criteria = RequestMatchCriteria {
method: HttpMethod::POST,
path: "/api/test".to_string(),
query_params: HashMap::new(),
headers: HashMap::new(),
body: Some("body".to_string()),
};
let debug_str = format!("{:?}", criteria);
assert!(debug_str.contains("RequestMatchCriteria"));
}
#[test]
fn test_request_validation_result_clone() {
let result1 = RequestValidationResult {
is_valid: true,
errors: vec![],
warnings: vec!["Warning".to_string()],
};
let result2 = result1.clone();
assert_eq!(result1.is_valid, result2.is_valid);
assert_eq!(result1.warnings, result2.warnings);
}
#[test]
fn test_request_validation_result_debug() {
let result = RequestValidationResult {
is_valid: false,
errors: vec!["Error".to_string()],
warnings: vec![],
};
let debug_str = format!("{:?}", result);
assert!(debug_str.contains("RequestValidationResult"));
}
#[test]
fn test_request_execution_context_clone() {
let context1 = RequestExecutionContext {
workspace_id: EntityId::new(),
environment_variables: HashMap::new(),
global_headers: HashMap::new(),
timeout_seconds: 30,
ssl_verify: true,
};
let context2 = context1.clone();
assert_eq!(context1.timeout_seconds, context2.timeout_seconds);
assert_eq!(context1.ssl_verify, context2.ssl_verify);
}
#[test]
fn test_request_execution_context_debug() {
let context = RequestExecutionContext {
workspace_id: EntityId::new(),
environment_variables: HashMap::new(),
global_headers: HashMap::new(),
timeout_seconds: 60,
ssl_verify: false,
};
let debug_str = format!("{:?}", context);
assert!(debug_str.contains("RequestExecutionContext"));
}
#[test]
fn test_request_metrics_clone() {
let metrics1 = RequestMetrics {
total_requests: 10,
successful_requests: 8,
failed_requests: 2,
average_response_time_ms: 50.0,
popular_requests: vec![],
last_execution: None,
};
let metrics2 = metrics1.clone();
assert_eq!(metrics1.total_requests, metrics2.total_requests);
}
#[test]
fn test_request_metrics_debug() {
let metrics = RequestMetrics {
total_requests: 5,
successful_requests: 4,
failed_requests: 1,
average_response_time_ms: 100.0,
popular_requests: vec![],
last_execution: Some(Utc::now()),
};
let debug_str = format!("{:?}", metrics);
assert!(debug_str.contains("RequestMetrics"));
}
#[test]
fn test_request_processor_clone() {
let processor1 = RequestProcessor::new();
let processor2 = processor1.clone();
assert_eq!(processor1.optimizations_enabled, processor2.optimizations_enabled);
}
#[test]
fn test_request_processor_debug() {
let processor = RequestProcessor::new();
let debug_str = format!("{:?}", processor);
assert!(debug_str.contains("RequestProcessor"));
}
#[tokio::test]
async fn test_execute_request_success() {
let processor = RequestProcessor::new();
let mut workspace = Workspace::new("Test Workspace".to_string());
let mut request =
MockRequest::new("Test Request".to_string(), HttpMethod::GET, "/api/test".to_string());
let response =
MockResponse::new(200, "Success".to_string(), r#"{"message": "test"}"#.to_string());
request.add_response(response);
workspace.add_request(request.clone());
let context = RequestExecutionContext {
workspace_id: workspace.id.clone(),
environment_variables: HashMap::new(),
global_headers: HashMap::new(),
timeout_seconds: 30,
ssl_verify: true,
};
let result = processor.execute_request(&mut workspace, &request.id, &context).await;
assert!(result.is_ok());
let execution_result = result.unwrap();
assert!(execution_result.success);
assert!(execution_result.response.is_some());
assert_eq!(execution_result.response.unwrap().status_code, 200);
}
#[tokio::test]
async fn test_execute_request_not_found() {
let processor = RequestProcessor::new();
let mut workspace = Workspace::new("Test Workspace".to_string());
let context = RequestExecutionContext {
workspace_id: workspace.id.clone(),
environment_variables: HashMap::new(),
global_headers: HashMap::new(),
timeout_seconds: 30,
ssl_verify: true,
};
let non_existent_id = EntityId::new();
let result = processor.execute_request(&mut workspace, &non_existent_id, &context).await;
assert!(result.is_err());
}
#[tokio::test]
async fn test_execute_request_with_delay() {
let processor = RequestProcessor::new();
let mut workspace = Workspace::new("Test Workspace".to_string());
let mut request =
MockRequest::new("Test Request".to_string(), HttpMethod::GET, "/api/test".to_string());
let mut response =
MockResponse::new(200, "Success".to_string(), r#"{"message": "test"}"#.to_string());
response.delay = 10; request.add_response(response);
workspace.add_request(request.clone());
let context = RequestExecutionContext {
workspace_id: workspace.id.clone(),
environment_variables: HashMap::new(),
global_headers: HashMap::new(),
timeout_seconds: 30,
ssl_verify: true,
};
let start = std::time::Instant::now();
let result = processor.execute_request(&mut workspace, &request.id, &context).await;
let elapsed = start.elapsed();
assert!(result.is_ok());
assert!(elapsed.as_millis() >= 10); }
#[test]
fn test_find_matching_request_exact() {
let processor = RequestProcessor::new();
let mut workspace = Workspace::new("Test Workspace".to_string());
let request =
MockRequest::new("Test Request".to_string(), HttpMethod::GET, "/api/test".to_string());
workspace.add_request(request.clone());
let criteria = RequestMatchCriteria {
method: HttpMethod::GET,
path: "/api/test".to_string(),
query_params: HashMap::new(),
headers: HashMap::new(),
body: None,
};
let matched_id = processor.find_matching_request(&workspace, &criteria);
assert_eq!(matched_id, Some(request.id));
}
#[test]
fn test_find_matching_request_with_query_params() {
let processor = RequestProcessor::new();
let mut workspace = Workspace::new("Test Workspace".to_string());
let mut request =
MockRequest::new("Test Request".to_string(), HttpMethod::GET, "/api/test".to_string());
request.query_params.insert("key".to_string(), "value".to_string());
workspace.add_request(request.clone());
let mut criteria = RequestMatchCriteria {
method: HttpMethod::GET,
path: "/api/test".to_string(),
query_params: HashMap::new(),
headers: HashMap::new(),
body: None,
};
criteria.query_params.insert("key".to_string(), "value".to_string());
let matched_id = processor.find_matching_request(&workspace, &criteria);
assert_eq!(matched_id, Some(request.id));
}
#[test]
fn test_url_matches_pattern_exact() {
let processor = RequestProcessor::new();
assert!(processor.url_matches_pattern("/api/test", "/api/test"));
}
#[test]
fn test_url_matches_pattern_wildcard() {
let processor = RequestProcessor::new();
assert!(processor.url_matches_pattern("*", "/any/path"));
assert!(processor.url_matches_pattern("/api/*", "/api/test"));
assert!(processor.url_matches_pattern("/api/*", "/api/users"));
}
#[test]
fn test_url_matches_pattern_double_wildcard() {
let processor = RequestProcessor::new();
assert!(processor.url_matches_pattern("/api/**", "/api/test"));
assert!(processor.url_matches_pattern("/api/**", "/api/users/123"));
assert!(processor.url_matches_pattern("/api/**", "/api/v1/users/123/posts"));
}
#[test]
fn test_create_route_from_request() {
let processor = RequestProcessor::new();
let mut request =
MockRequest::new("Test Request".to_string(), HttpMethod::GET, "/api/test".to_string());
let response =
MockResponse::new(200, "Success".to_string(), r#"{"message": "test"}"#.to_string());
request.add_response(response);
let route = processor.create_route_from_request(&request).unwrap();
assert_eq!(route.method, HttpMethod::GET);
assert_eq!(route.path, "/api/test");
}
#[test]
fn test_create_route_from_disabled_request() {
let processor = RequestProcessor::new();
let mut request =
MockRequest::new("Test Request".to_string(), HttpMethod::GET, "/api/test".to_string());
request.enabled = false;
let result = processor.create_route_from_request(&request);
assert!(result.is_err());
}
#[test]
fn test_update_route_registry() {
let processor = RequestProcessor::new();
let mut workspace = Workspace::new("Test Workspace".to_string());
let mut request1 =
MockRequest::new("Request 1".to_string(), HttpMethod::GET, "/api/test1".to_string());
let response1 =
MockResponse::new(200, "Success".to_string(), r#"{"message": "test1"}"#.to_string());
request1.add_response(response1);
workspace.add_request(request1);
let mut request2 =
MockRequest::new("Request 2".to_string(), HttpMethod::POST, "/api/test2".to_string());
let response2 =
MockResponse::new(201, "Created".to_string(), r#"{"message": "test2"}"#.to_string());
request2.add_response(response2);
workspace.add_request(request2);
let mut registry = RouteRegistry::new();
processor.update_route_registry(&workspace, &mut registry).unwrap();
let get_routes = registry.find_http_routes(&HttpMethod::GET, "/api/test1");
let post_routes = registry.find_http_routes(&HttpMethod::POST, "/api/test2");
assert!(!get_routes.is_empty() || !post_routes.is_empty());
}
#[test]
fn test_get_request_metrics() {
let processor = RequestProcessor::new();
let mut workspace = Workspace::new("Test Workspace".to_string());
let mut request =
MockRequest::new("Test Request".to_string(), HttpMethod::GET, "/api/test".to_string());
let mut response =
MockResponse::new(200, "Success".to_string(), r#"{"message": "test"}"#.to_string());
response.record_usage(request.id.clone(), 100);
request.add_response(response);
workspace.add_request(request);
let metrics = processor.get_request_metrics(&workspace);
assert_eq!(metrics.total_requests, 1);
assert!(metrics.successful_requests > 0 || metrics.failed_requests > 0);
}
#[test]
fn test_find_matching_request_in_folder() {
let processor = RequestProcessor::new();
let mut workspace = Workspace::new("Test Workspace".to_string());
let mut folder = Folder::new("Test Folder".to_string());
let request =
MockRequest::new("Test Request".to_string(), HttpMethod::GET, "/api/test".to_string());
folder.add_request(request.clone());
workspace.add_folder(folder);
let criteria = RequestMatchCriteria {
method: HttpMethod::GET,
path: "/api/test".to_string(),
query_params: HashMap::new(),
headers: HashMap::new(),
body: None,
};
let matched_id = processor.find_matching_request(&workspace, &criteria);
assert_eq!(matched_id, Some(request.id));
}
#[tokio::test]
async fn test_execute_request_with_cache_hit() {
let processor = RequestProcessor::with_performance_config(
None,
100,
Duration::from_secs(60),
true, );
let mut workspace = Workspace::new("Test Workspace".to_string());
let mut request =
MockRequest::new("Test Request".to_string(), HttpMethod::GET, "/api/test".to_string());
request.add_response(MockResponse::new(
200,
"Success".to_string(),
r#"{"message": "test"}"#.to_string(),
));
workspace.add_request(request.clone());
let context = RequestExecutionContext {
workspace_id: workspace.id.clone(),
environment_variables: HashMap::new(),
global_headers: HashMap::new(),
timeout_seconds: 30,
ssl_verify: true,
};
let result1 =
processor.execute_request(&mut workspace, &request.id, &context).await.unwrap();
assert!(result1.success);
let result2 =
processor.execute_request(&mut workspace, &request.id, &context).await.unwrap();
assert!(result2.success);
assert_eq!(result2.duration_ms, 1);
}
#[tokio::test]
async fn test_execute_request_with_cache_miss() {
let processor = RequestProcessor::with_performance_config(
None,
100,
Duration::from_secs(60),
true, );
let mut workspace = Workspace::new("Test Workspace".to_string());
let mut request =
MockRequest::new("Test Request".to_string(), HttpMethod::GET, "/api/test".to_string());
request.add_response(MockResponse::new(
200,
"Success".to_string(),
r#"{"message": "test"}"#.to_string(),
));
workspace.add_request(request.clone());
let context = RequestExecutionContext {
workspace_id: workspace.id.clone(),
environment_variables: HashMap::new(),
global_headers: HashMap::new(),
timeout_seconds: 30,
ssl_verify: true,
};
let result =
processor.execute_request(&mut workspace, &request.id, &context).await.unwrap();
assert!(result.success);
assert!(result.duration_ms != 1 || result.duration_ms == 0);
}
#[tokio::test]
async fn test_execute_request_not_found_with_optimizations() {
let processor = RequestProcessor::with_performance_config(
None,
100,
Duration::from_secs(60),
true, );
let mut workspace = Workspace::new("Test Workspace".to_string());
let non_existent_id = EntityId::new();
let context = RequestExecutionContext {
workspace_id: workspace.id.clone(),
environment_variables: HashMap::new(),
global_headers: HashMap::new(),
timeout_seconds: 30,
ssl_verify: true,
};
let result = processor.execute_request(&mut workspace, &non_existent_id, &context).await;
assert!(result.is_err());
assert!(result.unwrap_err().to_string().contains("not found"));
}
#[tokio::test]
async fn test_execute_request_caches_response() {
let processor = RequestProcessor::with_performance_config(
None,
100,
Duration::from_secs(60),
true, );
let mut workspace = Workspace::new("Test Workspace".to_string());
let mut request =
MockRequest::new("Test Request".to_string(), HttpMethod::GET, "/api/test".to_string());
request.add_response(MockResponse::new(
200,
"Success".to_string(),
r#"{"message": "test"}"#.to_string(),
));
workspace.add_request(request.clone());
let context = RequestExecutionContext {
workspace_id: workspace.id.clone(),
environment_variables: HashMap::new(),
global_headers: HashMap::new(),
timeout_seconds: 30,
ssl_verify: true,
};
let result1 =
processor.execute_request(&mut workspace, &request.id, &context).await.unwrap();
assert!(result1.success);
let result2 =
processor.execute_request(&mut workspace, &request.id, &context).await.unwrap();
assert!(result2.success);
assert!(result2.duration_ms <= 1);
}
#[tokio::test]
async fn test_execute_request_with_no_active_response() {
let processor = RequestProcessor::new();
let mut workspace = Workspace::new("Test Workspace".to_string());
let request =
MockRequest::new("Test Request".to_string(), HttpMethod::GET, "/api/test".to_string());
workspace.add_request(request.clone());
let context = RequestExecutionContext {
workspace_id: workspace.id.clone(),
environment_variables: HashMap::new(),
global_headers: HashMap::new(),
timeout_seconds: 30,
ssl_verify: true,
};
let result = processor.execute_request(&mut workspace, &request.id, &context).await;
assert!(result.is_err());
assert!(result.unwrap_err().to_string().contains("No active response"));
}
#[tokio::test]
async fn test_execute_request_with_response_processing_error() {
let processor = RequestProcessor::new();
let mut workspace = Workspace::new("Test Workspace".to_string());
let mut request =
MockRequest::new("Test Request".to_string(), HttpMethod::GET, "/api/test".to_string());
let mut response =
MockResponse::new(200, "Success".to_string(), r#"{"message": "test"}"#.to_string());
response.delay = 0; request.add_response(response);
workspace.add_request(request.clone());
let context = RequestExecutionContext {
workspace_id: workspace.id.clone(),
environment_variables: HashMap::new(),
global_headers: HashMap::new(),
timeout_seconds: 30,
ssl_verify: true,
};
let result = processor.execute_request(&mut workspace, &request.id, &context).await;
assert!(result.is_ok());
}
#[tokio::test]
async fn test_execute_request_records_usage() {
let processor = RequestProcessor::new();
let mut workspace = Workspace::new("Test Workspace".to_string());
let mut request =
MockRequest::new("Test Request".to_string(), HttpMethod::GET, "/api/test".to_string());
request.add_response(MockResponse::new(
200,
"Success".to_string(),
r#"{"message": "test"}"#.to_string(),
));
workspace.add_request(request.clone());
let context = RequestExecutionContext {
workspace_id: workspace.id.clone(),
environment_variables: HashMap::new(),
global_headers: HashMap::new(),
timeout_seconds: 30,
ssl_verify: true,
};
let result =
processor.execute_request(&mut workspace, &request.id, &context).await.unwrap();
assert!(result.success);
let request_ref = workspace.requests.iter().find(|r| r.id == request.id).unwrap();
let response_ref = request_ref.active_response().unwrap();
assert!(!response_ref.history.is_empty());
}
#[tokio::test]
async fn test_execute_request_validation_error() {
let processor = RequestProcessor::with_performance_config(
None,
100,
Duration::from_secs(60),
true, );
let mut workspace = Workspace::new("Test Workspace".to_string());
let mut request =
MockRequest::new("Test Request".to_string(), HttpMethod::GET, "/api/test".to_string());
request.enabled = false; request.add_response(MockResponse::new(
200,
"Success".to_string(),
r#"{"message": "test"}"#.to_string(),
));
workspace.add_request(request.clone());
let context = RequestExecutionContext {
workspace_id: workspace.id.clone(),
environment_variables: HashMap::new(),
global_headers: HashMap::new(),
timeout_seconds: 30,
ssl_verify: true,
};
let result = processor.execute_request(&mut workspace, &request.id, &context).await;
assert!(result.is_err());
let error_msg = result.unwrap_err().to_string();
assert!(error_msg.contains("validation") || error_msg.contains("disabled"));
}
#[tokio::test]
async fn test_execute_request_validation_error_with_collector() {
let processor = RequestProcessor::with_performance_config(
None,
100,
Duration::from_secs(60),
true, );
let mut workspace = Workspace::new("Test Workspace".to_string());
let mut request =
MockRequest::new("Test Request".to_string(), HttpMethod::GET, "".to_string());
request.add_response(MockResponse::new(
200,
"Success".to_string(),
r#"{"message": "test"}"#.to_string(),
));
workspace.add_request(request.clone());
let context = RequestExecutionContext {
workspace_id: workspace.id.clone(),
environment_variables: HashMap::new(),
global_headers: HashMap::new(),
timeout_seconds: 30,
ssl_verify: true,
};
let result = processor.execute_request(&mut workspace, &request.id, &context).await;
assert!(result.is_err());
let error_msg = result.unwrap_err().to_string();
assert!(error_msg.contains("validation") || error_msg.contains("empty"));
}
#[tokio::test]
async fn test_execute_request_with_invalid_status_code() {
let processor = RequestProcessor::new();
let mut workspace = Workspace::new("Test Workspace".to_string());
let mut request =
MockRequest::new("Test Request".to_string(), HttpMethod::GET, "/api/test".to_string());
request.add_response(MockResponse::new(
999,
"Invalid".to_string(),
r#"{"message": "test"}"#.to_string(),
));
workspace.add_request(request.clone());
let context = RequestExecutionContext {
workspace_id: workspace.id.clone(),
environment_variables: HashMap::new(),
global_headers: HashMap::new(),
timeout_seconds: 30,
ssl_verify: true,
};
let result = processor.execute_request(&mut workspace, &request.id, &context).await;
assert!(result.is_err());
let error_msg = result.unwrap_err().to_string();
assert!(error_msg.contains("validation") || error_msg.contains("Invalid status"));
}
#[tokio::test]
async fn test_validate_request_cached() {
let processor = RequestProcessor::with_performance_config(
None,
100,
Duration::from_secs(60),
true, );
let mut workspace = Workspace::new("Test Workspace".to_string());
let mut request =
MockRequest::new("Test Request".to_string(), HttpMethod::GET, "/api/test".to_string());
request.add_response(MockResponse::new(
200,
"Success".to_string(),
r#"{"message": "test"}"#.to_string(),
));
workspace.add_request(request.clone());
let context = RequestExecutionContext {
workspace_id: workspace.id.clone(),
environment_variables: HashMap::new(),
global_headers: HashMap::new(),
timeout_seconds: 30,
ssl_verify: true,
};
let validation1 = processor.validate_request_cached(&request, &context).await.unwrap();
assert!(validation1.is_valid);
let validation2 = processor.validate_request_cached(&request, &context).await.unwrap();
assert!(validation2.is_valid);
}
#[test]
fn test_create_route_from_request_with_metadata() {
let processor = RequestProcessor::new();
let mut request =
MockRequest::new("Test Request".to_string(), HttpMethod::GET, "/api/test".to_string());
request.add_response(MockResponse::new(
200,
"Success".to_string(),
r#"{"message": "test"}"#.to_string(),
));
let route = processor.create_route_from_request(&request).unwrap();
assert_eq!(route.method, HttpMethod::GET);
assert_eq!(route.path, "/api/test");
assert_eq!(route.metadata.get("status_code"), Some(&serde_json::json!(200)));
}
#[test]
fn test_create_route_from_request_disabled_error() {
let processor = RequestProcessor::new();
let mut request =
MockRequest::new("Test Request".to_string(), HttpMethod::GET, "/api/test".to_string());
request.enabled = false;
request.add_response(MockResponse::new(
200,
"Success".to_string(),
r#"{"message": "test"}"#.to_string(),
));
let result = processor.create_route_from_request(&request);
assert!(result.is_err());
assert!(result.unwrap_err().to_string().contains("disabled"));
}
#[test]
fn test_create_route_from_request_no_active_response_error() {
let processor = RequestProcessor::new();
let request =
MockRequest::new("Test Request".to_string(), HttpMethod::GET, "/api/test".to_string());
let result = processor.create_route_from_request(&request);
assert!(result.is_err());
assert!(result.unwrap_err().to_string().contains("No active response"));
}
#[test]
fn test_update_route_registry_adds_routes() {
let processor = RequestProcessor::new();
let mut workspace = Workspace::new("Test Workspace".to_string());
let mut registry = RouteRegistry::new();
let mut request =
MockRequest::new("Test Request".to_string(), HttpMethod::GET, "/api/test".to_string());
request.add_response(MockResponse::new(
200,
"Success".to_string(),
r#"{"message": "test"}"#.to_string(),
));
workspace.add_request(request);
processor.update_route_registry(&workspace, &mut registry).unwrap();
let found_routes = registry.find_http_routes(&HttpMethod::GET, "/api/test");
assert!(!found_routes.is_empty());
}
#[test]
fn test_update_route_registry_with_folder_requests() {
let processor = RequestProcessor::new();
let mut workspace = Workspace::new("Test Workspace".to_string());
let mut registry = RouteRegistry::new();
let mut folder = Folder::new("Test Folder".to_string());
let mut request =
MockRequest::new("Test Request".to_string(), HttpMethod::POST, "/api/test".to_string());
request.add_response(MockResponse::new(
201,
"Created".to_string(),
r#"{"message": "created"}"#.to_string(),
));
folder.add_request(request);
workspace.add_folder(folder);
processor.update_route_registry(&workspace, &mut registry).unwrap();
let found_routes = registry.find_http_routes(&HttpMethod::POST, "/api/test");
assert!(!found_routes.is_empty());
}
#[test]
fn test_convert_mock_response_to_cached_response() {
let processor = RequestProcessor::new();
let mut response =
MockResponse::new(200, "Success".to_string(), r#"{"message": "test"}"#.to_string());
response
.headers
.insert("Content-Type".to_string(), "application/json".to_string());
let cached = processor.convert_mock_response_to_cached_response(&response);
assert_eq!(cached.status_code, 200);
assert_eq!(cached.body, r#"{"message": "test"}"#);
assert_eq!(cached.content_type, Some("application/json".to_string()));
}
#[test]
fn test_convert_cached_response_to_mock_response() {
let processor = RequestProcessor::new();
let cached = CachedResponse {
status_code: 200,
headers: HashMap::from([("Content-Type".to_string(), "application/json".to_string())]),
body: r#"{"message": "test"}"#.to_string(),
content_type: Some("application/json".to_string()),
};
let mock_response = processor.convert_cached_response_to_mock_response(cached);
assert_eq!(mock_response.status_code, 200);
assert_eq!(mock_response.body, r#"{"message": "test"}"#);
assert_eq!(mock_response.name, "Cached Response");
assert_eq!(mock_response.delay, 0);
}
#[tokio::test]
async fn test_get_performance_summary() {
let processor = RequestProcessor::new();
let summary = processor.get_performance_summary().await;
let _ = summary.total_requests;
}
#[tokio::test]
async fn test_get_cache_stats() {
let processor = RequestProcessor::new();
let (response_stats, validation_stats) = processor.get_cache_stats().await;
let _ = response_stats.hits;
let _ = validation_stats.hits;
}
}