refactor(tests): Add chaos and performance tests, remove obsolete tests, and update dependencies
This commit is contained in:
parent
490ba66c51
commit
d08ebfc094
14 changed files with 253 additions and 89 deletions
10
.vscode/launch.json
vendored
10
.vscode/launch.json
vendored
|
@ -18,7 +18,7 @@
|
|||
"args": [],
|
||||
"cwd": "${workspaceFolder}",
|
||||
"env": {
|
||||
"RUST_LOG": "debug",
|
||||
"RUST_LOG": "info",
|
||||
"DATABASE_URL": "postgres://gbuser:gbpassword@localhost:5432/generalbots",
|
||||
"REDIS_URL": "redis://localhost:6379"
|
||||
}
|
||||
|
@ -42,7 +42,9 @@
|
|||
"args": [
|
||||
"--test-threads=1"
|
||||
],
|
||||
"cwd": "${workspaceFolder}"
|
||||
"cwd": "${workspaceFolder}", "env": {
|
||||
"RUST_LOG": "info"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "lldb",
|
||||
|
@ -61,7 +63,9 @@
|
|||
}
|
||||
},
|
||||
"args": [],
|
||||
"cwd": "${workspaceFolder}"
|
||||
"cwd": "${workspaceFolder}", "env": {
|
||||
"RUST_LOG": "info"
|
||||
}
|
||||
},
|
||||
],
|
||||
"compounds": [
|
||||
|
|
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
|
@ -2,5 +2,6 @@
|
|||
"lldb.executable": "/usr/bin/lldb",
|
||||
"lldb.showDisassembly": "never",
|
||||
"lldb.dereferencePointers": true,
|
||||
"lldb.consoleMode": "commands"
|
||||
"lldb.consoleMode": "commands",
|
||||
"rust-test Explorer.cargoTestExtraArgs": ["--", "--nocapture"]
|
||||
}
|
28
Cargo.lock
generated
28
Cargo.lock
generated
|
@ -2334,6 +2334,19 @@ version = "0.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c7f84e12ccf0a7ddc17a6c41c93326024c42920d7ee630d04950e6926645c0fe"
|
||||
|
||||
[[package]]
|
||||
name = "env_logger"
|
||||
version = "0.10.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580"
|
||||
dependencies = [
|
||||
"humantime",
|
||||
"is-terminal",
|
||||
"log",
|
||||
"regex",
|
||||
"termcolor",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "env_logger"
|
||||
version = "0.11.6"
|
||||
|
@ -2761,6 +2774,7 @@ dependencies = [
|
|||
"thiserror 1.0.69",
|
||||
"tokio",
|
||||
"tokio-openssl",
|
||||
"tokio-stream",
|
||||
"tokio-test",
|
||||
"tower 0.4.13",
|
||||
"tower-http",
|
||||
|
@ -2872,10 +2886,12 @@ dependencies = [
|
|||
"actix-multipart",
|
||||
"actix-web",
|
||||
"async-trait",
|
||||
"env_logger 0.10.2",
|
||||
"futures 0.3.31",
|
||||
"gb-core",
|
||||
"jsonwebtoken",
|
||||
"lettre",
|
||||
"log",
|
||||
"minio",
|
||||
"rstest",
|
||||
"sanitize-filename",
|
||||
|
@ -2884,6 +2900,7 @@ dependencies = [
|
|||
"tempfile",
|
||||
"thiserror 1.0.69",
|
||||
"tokio",
|
||||
"tokio-stream",
|
||||
"tokio-test",
|
||||
"tracing",
|
||||
"uuid",
|
||||
|
@ -3080,6 +3097,7 @@ dependencies = [
|
|||
"sqlx",
|
||||
"tempfile",
|
||||
"tokio",
|
||||
"tokio-stream",
|
||||
"tokio-tungstenite 0.24.0",
|
||||
"tracing",
|
||||
"tungstenite 0.20.1",
|
||||
|
@ -4614,7 +4632,7 @@ dependencies = [
|
|||
"crc",
|
||||
"dashmap 6.1.0",
|
||||
"derivative",
|
||||
"env_logger",
|
||||
"env_logger 0.11.6",
|
||||
"futures-util",
|
||||
"hex",
|
||||
"hmac",
|
||||
|
@ -4724,12 +4742,6 @@ version = "0.8.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a"
|
||||
|
||||
[[package]]
|
||||
name = "multimap"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e1a5d38b9b352dbd913288736af36af41c48d61b1a8cd34bcecd727561b7d511"
|
||||
|
||||
[[package]]
|
||||
name = "multimap"
|
||||
version = "0.10.0"
|
||||
|
@ -6064,7 +6076,7 @@ dependencies = [
|
|||
"heck 0.5.0",
|
||||
"itertools 0.13.0",
|
||||
"log",
|
||||
"multimap 0.9.1",
|
||||
"multimap 0.10.0",
|
||||
"once_cell",
|
||||
"petgraph 0.6.5",
|
||||
"prettyplease 0.2.30",
|
||||
|
|
|
@ -39,6 +39,8 @@ futures = "0.3"
|
|||
futures-util = "0.3" # Add futures-util here
|
||||
parking_lot = "0.12"
|
||||
bytes = "1.0"
|
||||
log = "0.4"
|
||||
env_logger = "0.10"
|
||||
|
||||
# Web framework and servers
|
||||
axum = { version = "0.7.9", features = ["ws", "multipart"] }
|
||||
|
|
|
@ -47,6 +47,7 @@ axum-extra = { version = "0.7" } # Add headers feature
|
|||
tower = "0.4"
|
||||
tower-http = { version = "0.5", features = ["auth", "cors", "trace"] }
|
||||
headers = "0.3"
|
||||
tokio-stream = { workspace = true }
|
||||
|
||||
[dev-dependencies]
|
||||
rstest = "0.18"
|
||||
|
|
|
@ -19,18 +19,16 @@ pub struct CoreError(pub String);
|
|||
pub enum CustomerStatus {
|
||||
Active,
|
||||
Inactive,
|
||||
Suspended
|
||||
Suspended,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub enum SubscriptionTier {
|
||||
Free,
|
||||
Pro,
|
||||
Enterprise
|
||||
Enterprise,
|
||||
}
|
||||
|
||||
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Instance {
|
||||
pub id: Uuid,
|
||||
|
@ -118,7 +116,7 @@ impl FromStr for UserStatus {
|
|||
"active" => Ok(UserStatus::Active),
|
||||
"inactive" => Ok(UserStatus::Inactive),
|
||||
"suspended" => Ok(UserStatus::Suspended),
|
||||
_ => Ok(UserStatus::Inactive)
|
||||
_ => Ok(UserStatus::Inactive),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -146,8 +144,6 @@ pub struct User {
|
|||
pub created_at: DateTime<Utc>,
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Update the Customer struct to include these fields
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Customer {
|
||||
|
@ -155,16 +151,16 @@ pub struct Customer {
|
|||
pub name: String,
|
||||
pub max_instances: u32,
|
||||
pub email: String,
|
||||
pub status: CustomerStatus, // Add this field
|
||||
pub subscription_tier: SubscriptionTier, // Add this field
|
||||
pub status: CustomerStatus, // Add this field
|
||||
pub subscription_tier: SubscriptionTier, // Add this field
|
||||
pub created_at: DateTime<Utc>,
|
||||
pub updated_at: DateTime<Utc>,
|
||||
}
|
||||
|
||||
impl Customer {
|
||||
pub fn new(
|
||||
name: String,
|
||||
email: String,
|
||||
name: String,
|
||||
email: String,
|
||||
subscription_tier: SubscriptionTier,
|
||||
max_instances: u32,
|
||||
) -> Self {
|
||||
|
@ -174,7 +170,7 @@ impl Customer {
|
|||
email,
|
||||
max_instances,
|
||||
subscription_tier,
|
||||
status: CustomerStatus::Active, // Default to Active
|
||||
status: CustomerStatus::Active, // Default to Active
|
||||
created_at: Utc::now(),
|
||||
updated_at: Utc::now(),
|
||||
}
|
||||
|
@ -238,15 +234,17 @@ pub struct FileInfo {
|
|||
pub created_at: DateTime<Utc>,
|
||||
}
|
||||
|
||||
// App state shared across all handlers
|
||||
|
||||
|
||||
// App state shared across all handlers
|
||||
pub struct AppState {
|
||||
pub config: AppConfig,
|
||||
pub db_pool: PgPool,
|
||||
pub redis_pool: RedisConnectionManager,
|
||||
pub kafka_producer: FutureProducer,
|
||||
// pub zitadel_client: AuthServiceClient<tonic::transport::Channel>,
|
||||
pub minio_client: MinioClient,
|
||||
pub minio_client: Option<MinioClient>,
|
||||
pub config: Option<AppConfig>,
|
||||
pub db_pool: Option<PgPool>,
|
||||
pub redis_pool: Option<RedisConnectionManager>,
|
||||
pub kafka_producer: Option<FutureProducer>,
|
||||
//pub zitadel_client: Option<AuthServiceClient><tonic::transport::Channel>,
|
||||
}
|
||||
|
||||
// File models
|
||||
|
@ -288,7 +286,7 @@ pub struct Conversation {
|
|||
pub struct ConversationMember {
|
||||
pub conversation_id: Uuid,
|
||||
pub user_id: Uuid,
|
||||
pub joined_at: DateTime<Utc>
|
||||
pub joined_at: DateTime<Utc>,
|
||||
}
|
||||
|
||||
// Calendar models
|
||||
|
@ -348,36 +346,33 @@ pub struct ApiResponse<T> {
|
|||
pub enum AppError {
|
||||
#[error("Database error: {0}")]
|
||||
Database(#[from] sqlx::Error),
|
||||
|
||||
|
||||
#[error("Redis error: {0}")]
|
||||
Redis(#[from] redis::RedisError),
|
||||
|
||||
|
||||
#[error("Kafka error: {0}")]
|
||||
Kafka(String),
|
||||
|
||||
|
||||
#[error("Zitadel error: {0}")]
|
||||
Zitadel(#[from] tonic::Status),
|
||||
|
||||
|
||||
#[error("Minio error: {0}")]
|
||||
Minio(String),
|
||||
|
||||
|
||||
#[error("Validation error: {0}")]
|
||||
Validation(String),
|
||||
|
||||
|
||||
#[error("Not found: {0}")]
|
||||
NotFound(String),
|
||||
|
||||
|
||||
#[error("Unauthorized: {0}")]
|
||||
Unauthorized(String),
|
||||
|
||||
|
||||
#[error("Forbidden: {0}")]
|
||||
Forbidden(String),
|
||||
|
||||
|
||||
#[error("Internal server error: {0}")]
|
||||
Internal(String),
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
impl actix_web::ResponseError for AppError {
|
||||
|
@ -385,7 +380,9 @@ impl actix_web::ResponseError for AppError {
|
|||
let (status, error_message) = match self {
|
||||
AppError::Validation(_) => (actix_web::http::StatusCode::BAD_REQUEST, self.to_string()),
|
||||
AppError::NotFound(_) => (actix_web::http::StatusCode::NOT_FOUND, self.to_string()),
|
||||
AppError::Unauthorized(_) => (actix_web::http::StatusCode::UNAUTHORIZED, self.to_string()),
|
||||
AppError::Unauthorized(_) => {
|
||||
(actix_web::http::StatusCode::UNAUTHORIZED, self.to_string())
|
||||
}
|
||||
AppError::Forbidden(_) => (actix_web::http::StatusCode::FORBIDDEN, self.to_string()),
|
||||
_ => (
|
||||
actix_web::http::StatusCode::INTERNAL_SERVER_ERROR,
|
||||
|
|
|
@ -22,6 +22,9 @@ actix-web ={ workspace = true }
|
|||
actix-multipart ={ workspace = true }
|
||||
sanitize-filename = { workspace = true }
|
||||
tempfile = { workspace = true }
|
||||
log = { workspace = true }
|
||||
env_logger = { workspace = true }
|
||||
tokio-stream = { workspace = true }
|
||||
|
||||
[dev-dependencies]
|
||||
rstest= { workspace = true }
|
||||
|
|
|
@ -1,13 +1,15 @@
|
|||
use actix_multipart::Multipart;
|
||||
use futures::TryStreamExt;
|
||||
use gb_core::models::AppState;
|
||||
use std::io::Write;
|
||||
use gb_core::models::AppError;
|
||||
use gb_core::utils::{create_response, extract_user_id};
|
||||
use actix_web::{post, web, HttpRequest, HttpResponse};
|
||||
use tempfile::NamedTempFile;
|
||||
use gb_core::models::AppError;
|
||||
use gb_core::models::AppState;
|
||||
use gb_core::utils::{create_response, extract_user_id};
|
||||
use minio::s3::builders::ObjectContent;
|
||||
use minio::s3::Client;
|
||||
use std::io::Write;
|
||||
use tempfile::NamedTempFile;
|
||||
use minio::s3::types::ToStream;
|
||||
use tokio_stream::StreamExt;
|
||||
|
||||
|
||||
#[post("/files/upload/{folder_path}")]
|
||||
pub async fn upload_file(
|
||||
|
@ -17,24 +19,29 @@ pub async fn upload_file(
|
|||
) -> Result<HttpResponse, actix_web::Error> {
|
||||
let folder_path = folder_path.into_inner();
|
||||
|
||||
// Create a temporary file to store the uploaded file
|
||||
// Create a temporary file to store the uploaded file.
|
||||
|
||||
let mut temp_file = NamedTempFile::new().map_err(|e| {
|
||||
actix_web::error::ErrorInternalServerError(format!("Failed to create temp file: {}", e))
|
||||
})?;
|
||||
|
||||
let mut file_name = None;
|
||||
|
||||
// Iterate over the multipart stream
|
||||
// Iterate over the multipart stream.
|
||||
|
||||
while let Some(mut field) = payload.try_next().await? {
|
||||
let content_disposition = field.content_disposition();
|
||||
file_name = content_disposition
|
||||
.get_filename()
|
||||
.map(|name| name.to_string());
|
||||
|
||||
// Write the file content to the temporary file
|
||||
// Write the file content to the temporary file.
|
||||
while let Some(chunk) = field.try_next().await? {
|
||||
temp_file.write_all(&chunk).map_err(|e| {
|
||||
actix_web::error::ErrorInternalServerError(format!("Failed to write to temp file: {}", e))
|
||||
actix_web::error::ErrorInternalServerError(format!(
|
||||
"Failed to write to temp file: {}",
|
||||
e
|
||||
))
|
||||
})?;
|
||||
}
|
||||
}
|
||||
|
@ -46,7 +53,7 @@ pub async fn upload_file(
|
|||
let object_name = format!("{}/{}", folder_path, file_name);
|
||||
|
||||
// Upload the file to the MinIO bucket
|
||||
let client: Client = state.minio_client.clone();
|
||||
let client: Client = state.minio_client.clone().unwrap();
|
||||
let bucket_name = "file-upload-rust-bucket";
|
||||
|
||||
let content = ObjectContent::from(temp_file.path());
|
||||
|
@ -79,10 +86,46 @@ pub async fn delete_file(
|
|||
_file_path: web::Json<String>,
|
||||
) -> Result<HttpResponse, AppError> {
|
||||
let _user_id = extract_user_id(&req)?;
|
||||
|
||||
|
||||
|
||||
Ok(create_response(
|
||||
true,
|
||||
Some("File deleted successfully".to_string()),
|
||||
))
|
||||
}
|
||||
#[post("/files/list/{folder_path}")]
|
||||
pub async fn list_file(
|
||||
folder_path: web::Path<String>,
|
||||
state: web::Data<AppState>,
|
||||
) -> Result<HttpResponse, actix_web::Error> {
|
||||
let folder_path = folder_path.into_inner();
|
||||
|
||||
let client: Client = state.minio_client.clone().unwrap();
|
||||
let bucket_name = "file-upload-rust-bucket";
|
||||
|
||||
// Create the stream using the to_stream() method
|
||||
let mut objects_stream = client
|
||||
.list_objects(bucket_name)
|
||||
.prefix(Some(folder_path))
|
||||
.to_stream()
|
||||
.await;
|
||||
|
||||
let mut file_list = Vec::new();
|
||||
|
||||
// Use StreamExt::next() to iterate through the stream
|
||||
while let Some(items) = objects_stream.next().await {
|
||||
match items {
|
||||
Ok(result) => {
|
||||
for item in result.contents {
|
||||
file_list.push(item.name);
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
return Err(actix_web::error::ErrorInternalServerError(
|
||||
format!("Failed to list files in MinIO: {}", e)
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(HttpResponse::Ok().json(file_list))
|
||||
}
|
|
@ -26,11 +26,11 @@ async fn main() -> std::io::Result<()> {
|
|||
let minio_client = init_minio(&config).await.expect("Failed to initialize Minio");
|
||||
|
||||
let app_state = web::Data::new(models::AppState {
|
||||
config: config.clone(),
|
||||
db_pool,
|
||||
redis_pool,
|
||||
kafka_producer,
|
||||
minio_client,
|
||||
config: Some(config.clone()),
|
||||
db_pool: Some(db_pool),
|
||||
redis_pool: Some(redis_pool),
|
||||
kafka_producer: Some(kafka_producer),
|
||||
minio_client: Some(minio_client),
|
||||
});
|
||||
|
||||
// Start HTTP server
|
||||
|
|
|
@ -27,6 +27,7 @@ criterion = { workspace = true, features = ["async_futures"] }
|
|||
|
||||
# Async Runtime
|
||||
tokio = { workspace = true }
|
||||
tokio-stream= { workspace = true }
|
||||
async-trait = { workspace = true }
|
||||
|
||||
# HTTP Client
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
|
||||
pub struct ChaosTest {
|
||||
namespace: String,
|
||||
}
|
||||
|
||||
impl ChaosTest {
|
||||
pub async fn new(namespace: String) -> anyhow::Result<Self> {
|
||||
// Initialize the ChaosTest struct
|
||||
Ok(ChaosTest { namespace })
|
||||
Ok(ChaosTest { })
|
||||
}
|
||||
|
||||
pub async fn network_partition(&self) -> anyhow::Result<()> {
|
||||
|
|
|
@ -1,14 +1,10 @@
|
|||
use actix_web::{test, web, App};
|
||||
use anyhow::Result;
|
||||
use async_trait::async_trait;
|
||||
use bytes::Bytes;
|
||||
use gb_core::models::AppState;
|
||||
use gb_file::handlers::upload_file;
|
||||
use gb_testing::integration::{IntegrationTest, IntegrationTestCase};
|
||||
use minio::s3::args::{
|
||||
BucketExistsArgs, GetObjectArgs, MakeBucketArgs, RemoveObjectArgs, StatObjectArgs,
|
||||
};
|
||||
use minio::s3::client::{Client as MinioClient, ClientBuilder as MinioClientBuilder};
|
||||
use minio::s3::args::{BucketExistsArgs, GetObjectArgs, MakeBucketArgs, StatObjectArgs};
|
||||
use minio::s3::client::ClientBuilder as MinioClientBuilder;
|
||||
use minio::s3::creds::StaticProvider;
|
||||
use minio::s3::http::BaseUrl;
|
||||
use std::fs::File;
|
||||
|
@ -17,13 +13,10 @@ use std::io::Write;
|
|||
use std::str::FromStr;
|
||||
use tempfile::NamedTempFile;
|
||||
|
||||
|
||||
#[tokio::test]
|
||||
|
||||
async fn test_successful_file_upload() -> Result<()> {
|
||||
|
||||
// Setup test environment and MinIO client
|
||||
let base_url = format!("https://{}", "localhost:9000");
|
||||
let base_url = format!("http://{}", "localhost:9000");
|
||||
let base_url = BaseUrl::from_str(&base_url)?;
|
||||
let credentials = StaticProvider::new(&"minioadmin", &"minioadmin", None);
|
||||
|
||||
|
@ -45,14 +38,16 @@ async fn test_successful_file_upload() -> Result<()> {
|
|||
}
|
||||
|
||||
let app_state = web::Data::new(AppState {
|
||||
minio_client,
|
||||
config: todo!(),
|
||||
db_pool: todo!(),
|
||||
redis_pool: todo!(),
|
||||
kafka_producer: todo!(),
|
||||
minio_client: Some(minio_client.clone()),
|
||||
config: None,
|
||||
db_pool: None,
|
||||
kafka_producer: None,
|
||||
redis_pool: None,
|
||||
});
|
||||
|
||||
let app = test::init_service(App::new().app_data(app_state.clone()).service(upload_file)).await;
|
||||
let app =
|
||||
test::init_service(App::new().app_data(app_state.clone())
|
||||
.service(upload_file)).await;
|
||||
|
||||
// Create a test file with content
|
||||
let mut temp_file = NamedTempFile::new()?;
|
||||
|
@ -91,17 +86,13 @@ async fn test_successful_file_upload() -> Result<()> {
|
|||
|
||||
// Using object-based API for stat_object
|
||||
let stat_object_args = StatObjectArgs::new(bucket_name, object_name)?;
|
||||
let object_exists =
|
||||
minio_client
|
||||
.stat_object(&stat_object_args)
|
||||
.await
|
||||
.is_ok();
|
||||
let object_exists = minio_client.clone().stat_object(&stat_object_args).await.is_ok();
|
||||
|
||||
assert!(object_exists, "Uploaded file should exist in MinIO");
|
||||
|
||||
// Verify file content using object-based API
|
||||
let get_object_args = GetObjectArgs::new(bucket_name, object_name)?;
|
||||
let get_object_result = minio_client.get_object(bucket_name, object_name);
|
||||
// let get_object_args = GetObjectArgs::new(bucket_name, object_name)?;
|
||||
// let get_object_result = minio_client.get_object(bucket_name, object_name);
|
||||
|
||||
// let mut object_content = Vec::new();
|
||||
// get_object_result.read_to_end(&mut object_content)?;
|
||||
|
|
110
gb-testing/tests/int_file_list_test.rs
Normal file
110
gb-testing/tests/int_file_list_test.rs
Normal file
|
@ -0,0 +1,110 @@
|
|||
use actix_web::{test, web, App};
|
||||
use anyhow::Result;
|
||||
use bytes::Bytes;
|
||||
use gb_core::models::AppState;
|
||||
use gb_file::handlers::list_file;
|
||||
use minio::s3::args::{BucketExistsArgs, MakeBucketArgs};
|
||||
use minio::s3::builders::SegmentedBytes;
|
||||
use minio::s3::client::ClientBuilder as MinioClientBuilder;
|
||||
use minio::s3::creds::StaticProvider;
|
||||
use minio::s3::http::BaseUrl;
|
||||
use minio::s3::types::ToStream;
|
||||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
use std::io::Write;
|
||||
use std::str::FromStr;
|
||||
use tempfile::NamedTempFile;
|
||||
use tokio_stream::StreamExt;
|
||||
|
||||
|
||||
#[tokio::test]
|
||||
|
||||
async fn test_successful_file_listing() -> Result<(), Box<dyn std::error::Error>> {
|
||||
// Setup test environment and MinIO client
|
||||
let base_url = format!("http://{}", "localhost:9000");
|
||||
let base_url = BaseUrl::from_str(&base_url)?;
|
||||
let credentials = StaticProvider::new("minioadmin", "minioadmin", None);
|
||||
|
||||
let minio_client = MinioClientBuilder::new(base_url.clone())
|
||||
.provider(Some(Box::new(credentials)))
|
||||
.build()?;
|
||||
|
||||
// Create test bucket if it doesn't exist
|
||||
let bucket_name = "file-upload-rust-bucket";
|
||||
|
||||
// Using object-based API for bucket_exists
|
||||
let bucket_exists_args = BucketExistsArgs::new(bucket_name)?;
|
||||
let bucket_exists = minio_client.bucket_exists(&bucket_exists_args).await?;
|
||||
|
||||
if !bucket_exists {
|
||||
// Using object-based API for make_bucket
|
||||
let make_bucket_args = MakeBucketArgs::new(bucket_name)?;
|
||||
minio_client.make_bucket(&make_bucket_args).await?;
|
||||
}
|
||||
|
||||
// Put a single file in the bucket
|
||||
let folder_path = "test-folder";
|
||||
let file_name = "test.txt";
|
||||
let object_name = format!("{}/{}", folder_path, file_name);
|
||||
|
||||
// Create a temporary file with some content
|
||||
let mut temp_file = NamedTempFile::new()?;
|
||||
writeln!(temp_file, "This is a test file.")?;
|
||||
|
||||
// Upload the file to the bucket
|
||||
let mut file = File::open(temp_file.path())?;
|
||||
let mut buffer = Vec::new();
|
||||
file.read_to_end(&mut buffer)?;
|
||||
let content = SegmentedBytes::from(Bytes::from(buffer));
|
||||
minio_client.put_object(bucket_name, &object_name, content);
|
||||
|
||||
let app_state = web::Data::new(AppState {
|
||||
minio_client: Some(minio_client.clone()),
|
||||
config: None,
|
||||
db_pool: None,
|
||||
kafka_producer: None,
|
||||
redis_pool: None,
|
||||
});
|
||||
|
||||
let app = test::init_service(App::new().app_data(app_state.clone()).service(list_file)).await;
|
||||
|
||||
// Execute request to list files in the folder
|
||||
let req = test::TestRequest::post()
|
||||
.uri(&format!("/files/list/{}", folder_path))
|
||||
.to_request();
|
||||
|
||||
let resp = test::call_service(&app, req).await;
|
||||
|
||||
// Verify response
|
||||
assert_eq!(resp.status(), 200);
|
||||
|
||||
// Parse the response body as JSON
|
||||
let body = test::read_body(resp).await;
|
||||
let file_list: Vec<String> = serde_json::from_slice(&body)?;
|
||||
|
||||
// Verify the uploaded file is in the list
|
||||
assert!(
|
||||
file_list.contains(&object_name),
|
||||
"Uploaded file should be listed"
|
||||
);
|
||||
|
||||
// List all objects in a directory.
|
||||
let mut list_objects = minio_client
|
||||
.list_objects("my-bucket")
|
||||
.use_api_v1(true)
|
||||
.recursive(true)
|
||||
.to_stream()
|
||||
.await;
|
||||
while let Some(result) = list_objects.next().await {
|
||||
match result {
|
||||
Ok(resp) => {
|
||||
for item in resp.contents {
|
||||
println!("{:?}", item);
|
||||
}
|
||||
}
|
||||
Err(e) => println!("Error: {:?}", e),
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
|
@ -1,9 +1,9 @@
|
|||
use gb_testing::load::{LoadTest, LoadTestConfig};
|
||||
use gb_testing::load::LoadTestConfig;
|
||||
use std::time::Duration;
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_auth_load() -> anyhow::Result<()> {
|
||||
let config = LoadTestConfig {
|
||||
let _config = LoadTestConfig {
|
||||
users: 100,
|
||||
duration: Duration::from_secs(300),
|
||||
ramp_up: Duration::from_secs(60),
|
||||
|
|
Loading…
Add table
Reference in a new issue