303 lines
11 KiB
Rust
303 lines
11 KiB
Rust
//! 集成测试
|
||
//!
|
||
//! 注意:这些测试需要有效的OSS凭证才能运行
|
||
//! 设置环境变量 OSS_ACCESS_KEY_ID 和 OSS_ACCESS_KEY_SECRET 来运行实际的OSS操作测试
|
||
|
||
use oss_client::{
|
||
OssClientTrait, OssConfig, OssError, PrivateOssClient, PublicOssClient, defaults,
|
||
};
|
||
use std::time::Duration;
|
||
|
||
fn create_private_client_from_env() -> Result<PrivateOssClient, OssError> {
|
||
let access_key_id = std::env::var("OSS_ACCESS_KEY_ID").unwrap_or_default();
|
||
let access_key_secret = std::env::var("OSS_ACCESS_KEY_SECRET").unwrap_or_default();
|
||
if access_key_id.is_empty() || access_key_secret.is_empty() {
|
||
return Err(OssError::config("缺少OSS凭证环境变量"));
|
||
}
|
||
let bucket =
|
||
std::env::var("OSS_BUCKET").unwrap_or_else(|_| defaults::PRIVATE_BUCKET.to_string());
|
||
let endpoint = std::env::var("OSS_ENDPOINT").unwrap_or_else(|_| defaults::ENDPOINT.to_string());
|
||
let region = std::env::var("OSS_REGION").unwrap_or_else(|_| defaults::REGION.to_string());
|
||
let upload_directory =
|
||
std::env::var("OSS_UPLOAD_DIR").unwrap_or_else(|_| defaults::UPLOAD_DIRECTORY.to_string());
|
||
let config = OssConfig::new(
|
||
endpoint,
|
||
bucket,
|
||
access_key_id,
|
||
access_key_secret,
|
||
region,
|
||
upload_directory,
|
||
);
|
||
PrivateOssClient::new(config)
|
||
}
|
||
|
||
fn create_public_client_from_env() -> Result<PublicOssClient, OssError> {
|
||
let access_key_id = std::env::var("OSS_ACCESS_KEY_ID").unwrap_or_default();
|
||
let access_key_secret = std::env::var("OSS_ACCESS_KEY_SECRET").unwrap_or_default();
|
||
if access_key_id.is_empty() || access_key_secret.is_empty() {
|
||
return Err(OssError::config("缺少OSS凭证环境变量"));
|
||
}
|
||
let bucket =
|
||
std::env::var("OSS_PUBLIC_BUCKET").unwrap_or_else(|_| defaults::PUBLIC_BUCKET.to_string());
|
||
let endpoint = std::env::var("OSS_ENDPOINT").unwrap_or_else(|_| defaults::ENDPOINT.to_string());
|
||
let region = std::env::var("OSS_REGION").unwrap_or_else(|_| defaults::REGION.to_string());
|
||
let upload_directory =
|
||
std::env::var("OSS_UPLOAD_DIR").unwrap_or_else(|_| defaults::UPLOAD_DIRECTORY.to_string());
|
||
let config = OssConfig::new(
|
||
endpoint,
|
||
bucket,
|
||
access_key_id,
|
||
access_key_secret,
|
||
region,
|
||
upload_directory,
|
||
);
|
||
PublicOssClient::new(config)
|
||
}
|
||
|
||
/// 测试客户端创建
|
||
#[test]
|
||
fn test_client_creation() {
|
||
// 测试从环境变量创建私有客户端
|
||
match create_private_client_from_env() {
|
||
Ok(client) => {
|
||
let config = client.get_config();
|
||
assert!(!config.access_key_id.is_empty());
|
||
assert!(!config.access_key_secret.is_empty());
|
||
assert!(!config.endpoint.is_empty());
|
||
assert!(!config.bucket.is_empty());
|
||
}
|
||
Err(e) => {
|
||
assert!(e.is_config_error());
|
||
}
|
||
}
|
||
|
||
// 测试从环境变量创建公有客户端
|
||
match create_public_client_from_env() {
|
||
Ok(client) => {
|
||
let config = client.get_config();
|
||
assert!(!config.access_key_id.is_empty());
|
||
assert!(!config.access_key_secret.is_empty());
|
||
assert!(!config.endpoint.is_empty());
|
||
assert!(!config.bucket.is_empty());
|
||
}
|
||
Err(e) => {
|
||
assert!(e.is_config_error());
|
||
}
|
||
}
|
||
|
||
// 测试使用自定义配置创建公有客户端
|
||
let config = OssConfig::new(
|
||
defaults::ENDPOINT.to_string(),
|
||
defaults::PUBLIC_BUCKET.to_string(),
|
||
"test_key_id".to_string(),
|
||
"test_key_secret".to_string(),
|
||
defaults::REGION.to_string(),
|
||
defaults::UPLOAD_DIRECTORY.to_string(),
|
||
);
|
||
let client = PublicOssClient::new(config).unwrap();
|
||
assert_eq!(client.get_config().access_key_id, "test_key_id");
|
||
assert_eq!(client.get_config().access_key_secret, "test_key_secret");
|
||
}
|
||
|
||
/// 测试配置验证
|
||
#[test]
|
||
fn test_config_validation() {
|
||
// 测试空的access_key_id
|
||
let config = OssConfig::new(
|
||
defaults::ENDPOINT.to_string(),
|
||
defaults::PUBLIC_BUCKET.to_string(),
|
||
"".to_string(),
|
||
"secret".to_string(),
|
||
defaults::REGION.to_string(),
|
||
defaults::UPLOAD_DIRECTORY.to_string(),
|
||
);
|
||
let result = PublicOssClient::new(config);
|
||
assert!(result.is_err());
|
||
assert!(result.unwrap_err().is_config_error());
|
||
|
||
// 测试空的access_key_secret
|
||
let config = OssConfig::new(
|
||
defaults::ENDPOINT.to_string(),
|
||
defaults::PUBLIC_BUCKET.to_string(),
|
||
"key_id".to_string(),
|
||
"".to_string(),
|
||
defaults::REGION.to_string(),
|
||
defaults::UPLOAD_DIRECTORY.to_string(),
|
||
);
|
||
let result = PublicOssClient::new(config);
|
||
assert!(result.is_err());
|
||
assert!(result.unwrap_err().is_config_error());
|
||
}
|
||
|
||
/// 测试签名URL生成(不需要实际OSS连接)
|
||
#[test]
|
||
fn test_signed_url_generation() {
|
||
// 私有客户端:签名上传/下载链接
|
||
let private_config = OssConfig::new(
|
||
defaults::ENDPOINT.to_string(),
|
||
defaults::PRIVATE_BUCKET.to_string(),
|
||
"test_key_id".to_string(),
|
||
"test_key_secret".to_string(),
|
||
defaults::REGION.to_string(),
|
||
defaults::UPLOAD_DIRECTORY.to_string(),
|
||
);
|
||
let private_client = PrivateOssClient::new(private_config).unwrap();
|
||
|
||
let upload_url = private_client.generate_upload_url(
|
||
"test/file.txt",
|
||
Duration::from_secs(3600),
|
||
Some("text/plain"),
|
||
);
|
||
assert!(upload_url.is_ok());
|
||
let url = upload_url.unwrap();
|
||
assert!(
|
||
url.contains("nuwa-packages.oss-rg-china-mainland.aliyuncs.com")
|
||
|| url.contains("edu-nuwa-packages.oss-rg-china-mainland.aliyuncs.com")
|
||
);
|
||
assert!(url.contains("edu/test/file.txt"));
|
||
assert!(url.contains("Expires=") || url.contains("x-oss-expires"));
|
||
assert!(url.contains("Signature=") || url.contains("x-oss-signature"));
|
||
|
||
let download_url =
|
||
private_client.generate_download_url("test/file.txt", Some(Duration::from_secs(3600)));
|
||
assert!(download_url.is_ok());
|
||
let url = download_url.unwrap();
|
||
assert!(url.contains("edu/test/file.txt"));
|
||
assert!(url.contains("Expires=") || url.contains("x-oss-expires"));
|
||
assert!(url.contains("Signature=") || url.contains("x-oss-signature"));
|
||
|
||
// 公有客户端:下载链接不应包含签名
|
||
let public_config = OssConfig::new(
|
||
defaults::ENDPOINT.to_string(),
|
||
defaults::PUBLIC_BUCKET.to_string(),
|
||
"test_key_id".to_string(),
|
||
"test_key_secret".to_string(),
|
||
defaults::REGION.to_string(),
|
||
defaults::UPLOAD_DIRECTORY.to_string(),
|
||
);
|
||
let public_client = PublicOssClient::new(public_config.clone()).unwrap();
|
||
let public_download_url = public_client.generate_download_url("test/file.txt", None);
|
||
let url = public_download_url.unwrap();
|
||
// 验证URL包含正确的路径,但域名可能被替换为自定义域名
|
||
assert!(url.contains("edu/test/file.txt"));
|
||
// 由于 replace_oss_domain 可能替换域名,我们只验证路径部分
|
||
assert!(!url.contains("Expires="));
|
||
assert!(!url.contains("Signature="));
|
||
}
|
||
|
||
/// 测试object key生成
|
||
#[test]
|
||
fn test_object_key_generation() {
|
||
let config = OssConfig::new(
|
||
defaults::ENDPOINT.to_string(),
|
||
defaults::PUBLIC_BUCKET.to_string(),
|
||
"test_key_id".to_string(),
|
||
"test_key_secret".to_string(),
|
||
defaults::REGION.to_string(),
|
||
defaults::UPLOAD_DIRECTORY.to_string(),
|
||
);
|
||
let client = PublicOssClient::new(config).unwrap();
|
||
|
||
// 测试带文件名的object key生成
|
||
let key1 = client.generate_object_key("uploads", Some("document.pdf"));
|
||
assert!(key1.starts_with("uploads/"));
|
||
assert!(key1.contains("document"));
|
||
assert!(key1.ends_with(".pdf"));
|
||
|
||
// 测试不带文件名的object key生成
|
||
let key2 = client.generate_object_key("temp", None);
|
||
assert!(key2.starts_with("temp/"));
|
||
assert!(key2.contains("file_"));
|
||
|
||
// 确保生成的key是唯一的
|
||
let key3 = client.generate_object_key("uploads", Some("document.pdf"));
|
||
assert_ne!(key1, key3);
|
||
}
|
||
|
||
/// 测试错误处理
|
||
#[test]
|
||
fn test_error_handling() {
|
||
// 测试配置错误
|
||
let config_err = OssError::config("test config error");
|
||
assert!(config_err.is_config_error());
|
||
assert!(!config_err.is_network_error());
|
||
|
||
// 测试网络错误
|
||
let network_err = OssError::network("test network error");
|
||
assert!(network_err.is_network_error());
|
||
assert!(!network_err.is_config_error());
|
||
|
||
// 测试文件不存在错误
|
||
let file_err = OssError::file_not_found("test.txt");
|
||
assert!(file_err.is_file_not_found());
|
||
|
||
// 测试权限错误
|
||
let perm_err = OssError::permission("access denied");
|
||
assert!(perm_err.is_permission_error());
|
||
}
|
||
|
||
// 以下测试需要有效的OSS凭证,只有在设置了环境变量时才会运行
|
||
|
||
#[tokio::test]
|
||
async fn test_actual_oss_operations() -> oss_client::Result<()> {
|
||
// 只有在设置了环境变量时才运行
|
||
let client = match create_private_client_from_env() {
|
||
Ok(client) => client,
|
||
Err(_) => {
|
||
println!("Skip actual OSS operation test: environment variables not set");
|
||
return Ok(());
|
||
}
|
||
};
|
||
|
||
println!("Run actual OSS operation test...");
|
||
|
||
// 测试文件存在性检查(对一个不存在的文件)
|
||
let test_key = format!("test/non-existent-{}.txt", chrono::Utc::now().timestamp());
|
||
match client.file_exists(&test_key).await {
|
||
Ok(exists) => {
|
||
assert!(!exists, "不存在的文件应该返回false");
|
||
println!("✓ File existence check test passed");
|
||
}
|
||
Err(e) => {
|
||
println!("File existence check failed: {e}");
|
||
}
|
||
}
|
||
|
||
// 测试上传小文件
|
||
let test_content = b"Hello, OSS!";
|
||
let test_key = format!(
|
||
"test/integration-test-{}.txt",
|
||
chrono::Utc::now().timestamp()
|
||
);
|
||
|
||
match client
|
||
.upload_content(test_content, &test_key, Some("text/plain"))
|
||
.await
|
||
{
|
||
Ok(url) => {
|
||
println!("✓ File uploaded successfully: {url}");
|
||
|
||
// 测试文件存在性
|
||
match client.file_exists(&test_key).await {
|
||
Ok(exists) => {
|
||
assert!(exists, "上传的文件应该存在");
|
||
println!("✓ The file existence check passes after uploading");
|
||
}
|
||
Err(e) => println!("File existence check failed: {e}"),
|
||
}
|
||
|
||
// 清理测试文件
|
||
match client.delete_file(&test_key).await {
|
||
Ok(_) => println!("✓ Test file cleanup successful"),
|
||
Err(e) => println!("Test file cleanup failed: {e}"),
|
||
}
|
||
}
|
||
Err(e) => {
|
||
println!("File upload failed: {e}");
|
||
println!("This may be caused by invalid OSS credentials or insufficient permissions");
|
||
}
|
||
}
|
||
|
||
Ok(())
|
||
}
|