docs
This commit is contained in:
322
tests/basic_test.rs
Normal file
322
tests/basic_test.rs
Normal file
@@ -0,0 +1,322 @@
|
||||
use actix_web::{test, web, App, HttpResponse};
|
||||
|
||||
/// Простой тест health check
|
||||
#[actix_web::test]
|
||||
async fn test_health_check() {
|
||||
let app = test::init_service(App::new().route(
|
||||
"/",
|
||||
web::get().to(|req: actix_web::HttpRequest| async move {
|
||||
match req.method().as_str() {
|
||||
"GET" => Ok::<HttpResponse, actix_web::Error>(
|
||||
HttpResponse::Ok().content_type("text/plain").body("ok"),
|
||||
),
|
||||
_ => {
|
||||
Ok::<HttpResponse, actix_web::Error>(HttpResponse::MethodNotAllowed().finish())
|
||||
}
|
||||
}
|
||||
}),
|
||||
))
|
||||
.await;
|
||||
|
||||
// Тестируем GET запрос
|
||||
let req = test::TestRequest::get().uri("/").to_request();
|
||||
|
||||
let resp = test::call_service(&app, req).await;
|
||||
assert!(resp.status().is_success());
|
||||
|
||||
let body = test::read_body(resp).await;
|
||||
assert_eq!(body, "ok");
|
||||
|
||||
// Тестируем POST запрос (должен вернуть 405)
|
||||
let req = test::TestRequest::post().uri("/").to_request();
|
||||
|
||||
let resp = test::call_service(&app, req).await;
|
||||
assert_eq!(resp.status(), actix_web::http::StatusCode::NOT_FOUND);
|
||||
}
|
||||
|
||||
/// Тест для проверки JSON сериализации/десериализации
|
||||
#[test]
|
||||
async fn test_json_serialization() {
|
||||
#[derive(serde::Serialize, serde::Deserialize, PartialEq, Debug)]
|
||||
struct TestStruct {
|
||||
user_id: String,
|
||||
current_quota: u64,
|
||||
max_quota: u64,
|
||||
}
|
||||
|
||||
let test_data = TestStruct {
|
||||
user_id: "test-user-123".to_string(),
|
||||
current_quota: 1024,
|
||||
max_quota: 5368709120, // 5 GB
|
||||
};
|
||||
|
||||
// Сериализация
|
||||
let json_string = serde_json::to_string(&test_data).unwrap();
|
||||
assert!(json_string.contains("test-user-123"));
|
||||
assert!(json_string.contains("1024"));
|
||||
assert!(json_string.contains("5368709120"));
|
||||
|
||||
// Десериализация
|
||||
let deserialized: TestStruct = serde_json::from_str(&json_string).unwrap();
|
||||
assert_eq!(deserialized, test_data);
|
||||
}
|
||||
|
||||
/// Тест для проверки multipart form data
|
||||
#[test]
|
||||
async fn test_multipart_form_data() {
|
||||
let boundary = "test-boundary";
|
||||
let filename = "test.png";
|
||||
let content = b"fake image data";
|
||||
|
||||
let mut form_data = Vec::new();
|
||||
|
||||
// Начало multipart
|
||||
form_data.extend_from_slice(format!("--{}\r\n", boundary).as_bytes());
|
||||
form_data.extend_from_slice(
|
||||
format!(
|
||||
"Content-Disposition: form-data; name=\"file\"; filename=\"{}\"\r\n",
|
||||
filename
|
||||
)
|
||||
.as_bytes(),
|
||||
);
|
||||
form_data.extend_from_slice(b"Content-Type: image/png\r\n\r\n");
|
||||
|
||||
// Содержимое файла
|
||||
form_data.extend_from_slice(content);
|
||||
form_data.extend_from_slice(b"\r\n");
|
||||
|
||||
// Конец multipart
|
||||
form_data.extend_from_slice(format!("--{}--\r\n", boundary).as_bytes());
|
||||
|
||||
// Проверяем, что form_data содержит ожидаемые части
|
||||
let form_data_str = String::from_utf8_lossy(&form_data);
|
||||
assert!(form_data_str.contains(filename));
|
||||
assert!(form_data_str.contains("image/png"));
|
||||
assert!(form_data_str.contains("fake image data"));
|
||||
assert!(form_data_str.contains(&format!("--{}", boundary)));
|
||||
}
|
||||
|
||||
/// Тест для проверки UUID генерации
|
||||
#[test]
|
||||
async fn test_uuid_generation() {
|
||||
use uuid::Uuid;
|
||||
|
||||
let uuid1 = Uuid::new_v4();
|
||||
let uuid2 = Uuid::new_v4();
|
||||
|
||||
// UUID должны быть разными
|
||||
assert_ne!(uuid1, uuid2);
|
||||
|
||||
// UUID должны быть в правильном формате
|
||||
let uuid_str = uuid1.to_string();
|
||||
assert_eq!(uuid_str.len(), 36); // 32 символа + 4 дефиса
|
||||
assert!(uuid_str.contains('-'));
|
||||
|
||||
// Проверяем, что UUID можно парсить обратно
|
||||
let parsed_uuid = Uuid::parse_str(&uuid_str).unwrap();
|
||||
assert_eq!(parsed_uuid, uuid1);
|
||||
}
|
||||
|
||||
/// Тест для проверки MIME типов
|
||||
#[test]
|
||||
async fn test_mime_type_detection() {
|
||||
// Тестируем определение MIME типа по расширению
|
||||
let get_mime_type = |ext: &str| -> Option<&'static str> {
|
||||
match ext.to_lowercase().as_str() {
|
||||
"jpg" | "jpeg" => Some("image/jpeg"),
|
||||
"png" => Some("image/png"),
|
||||
"gif" => Some("image/gif"),
|
||||
"webp" => Some("image/webp"),
|
||||
"mp3" => Some("audio/mpeg"),
|
||||
"wav" => Some("audio/wav"),
|
||||
"mp4" => Some("video/mp4"),
|
||||
_ => None,
|
||||
}
|
||||
};
|
||||
|
||||
assert_eq!(get_mime_type("jpg"), Some("image/jpeg"));
|
||||
assert_eq!(get_mime_type("jpeg"), Some("image/jpeg"));
|
||||
assert_eq!(get_mime_type("png"), Some("image/png"));
|
||||
assert_eq!(get_mime_type("gif"), Some("image/gif"));
|
||||
assert_eq!(get_mime_type("webp"), Some("image/webp"));
|
||||
assert_eq!(get_mime_type("mp3"), Some("audio/mpeg"));
|
||||
assert_eq!(get_mime_type("wav"), Some("audio/wav"));
|
||||
assert_eq!(get_mime_type("mp4"), Some("video/mp4"));
|
||||
assert_eq!(get_mime_type("pdf"), None);
|
||||
assert_eq!(get_mime_type(""), None);
|
||||
}
|
||||
|
||||
/// Тест для проверки парсинга путей файлов
|
||||
#[test]
|
||||
async fn test_file_path_parsing() {
|
||||
fn parse_file_path(path: &str) -> (String, u32, String) {
|
||||
let parts: Vec<&str> = path.split('.').collect();
|
||||
if parts.len() != 2 {
|
||||
return (path.to_string(), 0, "".to_string());
|
||||
}
|
||||
|
||||
let base_with_width = parts[0];
|
||||
let ext = parts[1];
|
||||
|
||||
// Ищем ширину в формате _NUMBER
|
||||
let base_parts: Vec<&str> = base_with_width.split('_').collect();
|
||||
if base_parts.len() >= 2 {
|
||||
if let Ok(width) = base_parts.last().unwrap().parse::<u32>() {
|
||||
let base = base_parts[..base_parts.len() - 1].join("_");
|
||||
return (base, width, ext.to_string());
|
||||
}
|
||||
}
|
||||
|
||||
(base_with_width.to_string(), 0, ext.to_string())
|
||||
}
|
||||
|
||||
let (base, width, ext) = parse_file_path("image_300.jpg");
|
||||
assert_eq!(base, "image");
|
||||
assert_eq!(width, 300);
|
||||
assert_eq!(ext, "jpg");
|
||||
|
||||
let (base, width, ext) = parse_file_path("document.pdf");
|
||||
assert_eq!(base, "document");
|
||||
assert_eq!(width, 0);
|
||||
assert_eq!(ext, "pdf");
|
||||
|
||||
let (base, width, ext) = parse_file_path("file_with_underscore_but_no_width.jpg");
|
||||
assert_eq!(base, "file_with_underscore_but_no_width");
|
||||
assert_eq!(width, 0);
|
||||
assert_eq!(ext, "jpg");
|
||||
}
|
||||
|
||||
/// Тест для проверки расчетов квот
|
||||
#[test]
|
||||
async fn test_quota_calculations() {
|
||||
const MAX_QUOTA_BYTES: u64 = 5 * 1024 * 1024 * 1024; // 5 ГБ
|
||||
const MB: u64 = 1024 * 1024;
|
||||
const GB: u64 = 1024 * 1024 * 1024;
|
||||
|
||||
// Тестируем различные сценарии
|
||||
let test_cases = vec![
|
||||
(0, 1 * MB, true), // Пустая квота + 1MB = OK
|
||||
(1 * GB, 1 * MB, true), // 1GB + 1MB = OK
|
||||
(4 * GB, 1 * GB, true), // 4GB + 1GB = OK
|
||||
(4 * GB, 2 * GB, false), // 4GB + 2GB = превышение
|
||||
(5 * GB, 1 * MB, false), // 5GB + 1MB = превышение
|
||||
];
|
||||
|
||||
for (current_quota, file_size, should_allow) in test_cases {
|
||||
let would_exceed = current_quota + file_size > MAX_QUOTA_BYTES;
|
||||
assert_eq!(
|
||||
would_exceed,
|
||||
!should_allow,
|
||||
"Квота: {} + файл: {} = {}, должно быть разрешено: {}",
|
||||
current_quota,
|
||||
file_size,
|
||||
current_quota + file_size,
|
||||
should_allow
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Тест для проверки форматирования размеров файлов
|
||||
#[test]
|
||||
async fn test_file_size_formatting() {
|
||||
fn format_file_size(bytes: u64) -> String {
|
||||
const KB: u64 = 1024;
|
||||
const MB: u64 = 1024 * 1024;
|
||||
const GB: u64 = 1024 * 1024 * 1024;
|
||||
|
||||
match bytes {
|
||||
0..KB => format!("{} B", bytes),
|
||||
KB..MB => format!("{:.1} KB", bytes as f64 / KB as f64),
|
||||
MB..GB => format!("{:.1} MB", bytes as f64 / MB as f64),
|
||||
_ => format!("{:.1} GB", bytes as f64 / GB as f64),
|
||||
}
|
||||
}
|
||||
|
||||
assert_eq!(format_file_size(512), "512 B");
|
||||
assert_eq!(format_file_size(1024), "1.0 KB");
|
||||
assert_eq!(format_file_size(1536), "1.5 KB");
|
||||
assert_eq!(format_file_size(1024 * 1024), "1.0 MB");
|
||||
assert_eq!(format_file_size(1024 * 1024 * 1024), "1.0 GB");
|
||||
assert_eq!(format_file_size(5 * 1024 * 1024 * 1024), "5.0 GB");
|
||||
}
|
||||
|
||||
/// Тест для проверки обработки ошибок
|
||||
#[test]
|
||||
async fn test_error_handling() {
|
||||
// Тестируем парсинг неверного JSON
|
||||
let invalid_json = "{ invalid json }";
|
||||
let result: Result<serde_json::Value, _> = serde_json::from_str(invalid_json);
|
||||
assert!(result.is_err());
|
||||
|
||||
// Тестируем парсинг неполного JSON
|
||||
let incomplete_json = r#"{"user_id": "test"#;
|
||||
let result: Result<serde_json::Value, _> = serde_json::from_str(incomplete_json);
|
||||
assert!(result.is_err());
|
||||
|
||||
// Тестируем неверный UUID
|
||||
use uuid::Uuid;
|
||||
let invalid_uuid = "not-a-uuid";
|
||||
let result = Uuid::parse_str(invalid_uuid);
|
||||
assert!(result.is_err());
|
||||
|
||||
// Тестируем пустой UUID
|
||||
let empty_uuid = "";
|
||||
let result = Uuid::parse_str(empty_uuid);
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
/// Тест для проверки производительности
|
||||
#[test]
|
||||
async fn test_performance() {
|
||||
use std::time::Instant;
|
||||
|
||||
// Тест UUID генерации
|
||||
let start = Instant::now();
|
||||
let iterations = 10000;
|
||||
|
||||
for _ in 0..iterations {
|
||||
let _uuid = uuid::Uuid::new_v4();
|
||||
}
|
||||
|
||||
let duration = start.elapsed();
|
||||
let avg_time = duration.as_nanos() as f64 / iterations as f64;
|
||||
|
||||
println!(
|
||||
"UUID generation: {} UUIDs in {:?}, avg: {:.2} ns per UUID",
|
||||
iterations, duration, avg_time
|
||||
);
|
||||
|
||||
// Проверяем, что среднее время меньше 1μs
|
||||
assert!(
|
||||
avg_time < 1000.0,
|
||||
"UUID generation too slow: {:.2} ns",
|
||||
avg_time
|
||||
);
|
||||
|
||||
// Тест JSON сериализации
|
||||
let start = Instant::now();
|
||||
|
||||
for _ in 0..iterations {
|
||||
let data = serde_json::json!({
|
||||
"user_id": "test-user-123",
|
||||
"current_quota": 1024,
|
||||
"max_quota": 5368709120u64
|
||||
});
|
||||
let _json_string = serde_json::to_string(&data).unwrap();
|
||||
}
|
||||
|
||||
let duration = start.elapsed();
|
||||
let avg_time = duration.as_micros() as f64 / iterations as f64;
|
||||
|
||||
println!(
|
||||
"JSON serialization: {} operations in {:?}, avg: {:.2} μs per operation",
|
||||
iterations, duration, avg_time
|
||||
);
|
||||
|
||||
// Проверяем, что среднее время меньше 100μs
|
||||
assert!(
|
||||
avg_time < 100.0,
|
||||
"JSON serialization too slow: {:.2} μs",
|
||||
avg_time
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user