use std::sync::Arc;
use super::config::StorageConfig;
use super::error::StorageResult;
use super::object_store::ObjectStoreProvider;
use super::provider::StorageProvider;
pub struct StorageProviderFactory;
impl StorageProviderFactory {
pub async fn from_config(config: StorageConfig) -> StorageResult<Arc<dyn StorageProvider>> {
let provider = ObjectStoreProvider::new(config).await?;
Ok(Arc::new(provider))
}
}
#[cfg(test)]
mod tests {
use super::*;
use tempfile::TempDir;
#[tokio::test]
async fn test_factory_create_local_provider() {
let temp_dir = TempDir::new().unwrap();
let temp_path = temp_dir.path().to_str().unwrap();
let config = StorageConfig::local().with_option("path", temp_path);
let result = StorageProviderFactory::from_config(config).await;
assert!(result.is_ok());
let provider = result.unwrap();
let base_path = provider
.base_path()
.replace("\\\\?\\", "")
.replace('\\', "/");
let canonical_temp = temp_dir
.path()
.canonicalize()
.unwrap()
.to_str()
.unwrap()
.replace("\\\\?\\", "")
.replace('\\', "/");
assert!(
base_path.contains(&canonical_temp),
"base_path '{}' should contain '{}'",
base_path,
canonical_temp
);
}
#[tokio::test]
async fn test_factory_local_provider_invalid_path() {
let config =
StorageConfig::local().with_option("path", "/nonexistent/path/that/does/not/exist");
let result = StorageProviderFactory::from_config(config).await;
assert!(result.is_err());
match result {
Err(e) => {
let error_msg = e.to_string();
assert!(
error_msg.contains("Failed to resolve path")
|| error_msg.contains("Configuration error")
);
}
Ok(_) => panic!("Expected error for invalid path"),
}
}
#[tokio::test]
async fn test_factory_local_provider_missing_path() {
let config = StorageConfig::local();
let result = StorageProviderFactory::from_config(config).await;
assert!(result.is_err());
match result {
Err(e) => {
assert!(e.to_string().contains("path"));
}
Ok(_) => panic!("Expected error for missing path option"),
}
}
#[tokio::test]
async fn test_factory_returns_arc() {
let temp_dir = TempDir::new().unwrap();
let temp_path = temp_dir.path().to_str().unwrap();
let config = StorageConfig::local().with_option("path", temp_path);
let provider = StorageProviderFactory::from_config(config).await.unwrap();
let provider_clone = Arc::clone(&provider);
assert_eq!(provider.base_path(), provider_clone.base_path());
}
#[tokio::test]
async fn test_factory_provider_implements_trait() {
let temp_dir = TempDir::new().unwrap();
let temp_path = temp_dir.path().to_str().unwrap();
let config = StorageConfig::local().with_option("path", temp_path);
let provider = StorageProviderFactory::from_config(config).await.unwrap();
let base_path = provider.base_path();
assert!(!base_path.is_empty());
let options = provider.options();
assert!(!options.is_empty());
}
#[tokio::test]
async fn test_factory_with_different_storage_types() {
let temp_dir = TempDir::new().unwrap();
let temp_path = temp_dir.path().to_str().unwrap();
let local_config = StorageConfig::local().with_option("path", temp_path);
let local_result = StorageProviderFactory::from_config(local_config).await;
assert!(local_result.is_ok());
let aws_config = StorageConfig::aws();
let aws_result = StorageProviderFactory::from_config(aws_config).await;
assert!(aws_result.is_err());
let azure_config = StorageConfig::azure();
let azure_result = StorageProviderFactory::from_config(azure_config).await;
assert!(azure_result.is_err());
let gcs_config = StorageConfig::gcs();
let gcs_result = StorageProviderFactory::from_config(gcs_config).await;
assert!(gcs_result.is_err());
}
}