Add comprehensive testing for preview clip and status handling
- Implement unit tests for PreviewClipRequest/PreviewStatusRequest serialization and deserialization. - Add tests for PreviewDao (insert, update, batch retrieval, and status-based queries). - Extend Actix-web integration tests for `/video/preview/status` endpoint scenarios. - Introduce in-memory TestPreviewDao for mock database interactions. - Update README with new config parameters for preview clips.
This commit is contained in:
@@ -3,9 +3,12 @@ use actix_web::{
|
||||
body::{BoxBody, MessageBody},
|
||||
};
|
||||
|
||||
use crate::database::{UserDao, models::User};
|
||||
use crate::database::models::{User, VideoPreviewClip};
|
||||
use crate::database::{DbError, DbErrorKind, PreviewDao, UserDao};
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::option::Option;
|
||||
use std::sync::Mutex as StdMutex;
|
||||
|
||||
pub struct TestUserDao {
|
||||
pub user_map: RefCell<Vec<User>>,
|
||||
@@ -62,3 +65,106 @@ impl BodyReader for HttpResponse<BoxBody> {
|
||||
std::str::from_utf8(&body).unwrap().to_string()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TestPreviewDao {
|
||||
pub clips: StdMutex<HashMap<String, VideoPreviewClip>>,
|
||||
next_id: StdMutex<i32>,
|
||||
}
|
||||
|
||||
impl TestPreviewDao {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
clips: StdMutex::new(HashMap::new()),
|
||||
next_id: StdMutex::new(1),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PreviewDao for TestPreviewDao {
|
||||
fn insert_preview(
|
||||
&mut self,
|
||||
_context: &opentelemetry::Context,
|
||||
file_path_val: &str,
|
||||
status_val: &str,
|
||||
) -> Result<(), DbError> {
|
||||
let mut clips = self.clips.lock().unwrap();
|
||||
// insert_or_ignore semantics: skip if key already exists
|
||||
if clips.contains_key(file_path_val) {
|
||||
return Ok(());
|
||||
}
|
||||
let mut id = self.next_id.lock().unwrap();
|
||||
let now = chrono::Utc::now().to_rfc3339();
|
||||
clips.insert(
|
||||
file_path_val.to_string(),
|
||||
VideoPreviewClip {
|
||||
id: *id,
|
||||
file_path: file_path_val.to_string(),
|
||||
status: status_val.to_string(),
|
||||
duration_seconds: None,
|
||||
file_size_bytes: None,
|
||||
error_message: None,
|
||||
created_at: now.clone(),
|
||||
updated_at: now,
|
||||
},
|
||||
);
|
||||
*id += 1;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn update_status(
|
||||
&mut self,
|
||||
_context: &opentelemetry::Context,
|
||||
file_path_val: &str,
|
||||
status_val: &str,
|
||||
duration: Option<f32>,
|
||||
size: Option<i32>,
|
||||
error: Option<&str>,
|
||||
) -> Result<(), DbError> {
|
||||
let mut clips = self.clips.lock().unwrap();
|
||||
if let Some(clip) = clips.get_mut(file_path_val) {
|
||||
clip.status = status_val.to_string();
|
||||
clip.duration_seconds = duration;
|
||||
clip.file_size_bytes = size;
|
||||
clip.error_message = error.map(|s| s.to_string());
|
||||
clip.updated_at = chrono::Utc::now().to_rfc3339();
|
||||
Ok(())
|
||||
} else {
|
||||
Err(DbError {
|
||||
kind: DbErrorKind::UpdateError,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn get_preview(
|
||||
&mut self,
|
||||
_context: &opentelemetry::Context,
|
||||
file_path_val: &str,
|
||||
) -> Result<Option<VideoPreviewClip>, DbError> {
|
||||
Ok(self.clips.lock().unwrap().get(file_path_val).cloned())
|
||||
}
|
||||
|
||||
fn get_previews_batch(
|
||||
&mut self,
|
||||
_context: &opentelemetry::Context,
|
||||
file_paths: &[String],
|
||||
) -> Result<Vec<VideoPreviewClip>, DbError> {
|
||||
let clips = self.clips.lock().unwrap();
|
||||
Ok(file_paths
|
||||
.iter()
|
||||
.filter_map(|p| clips.get(p).cloned())
|
||||
.collect())
|
||||
}
|
||||
|
||||
fn get_by_status(
|
||||
&mut self,
|
||||
_context: &opentelemetry::Context,
|
||||
status_val: &str,
|
||||
) -> Result<Vec<VideoPreviewClip>, DbError> {
|
||||
let clips = self.clips.lock().unwrap();
|
||||
Ok(clips
|
||||
.values()
|
||||
.filter(|c| c.status == status_val)
|
||||
.cloned()
|
||||
.collect())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user