Skip to main content

nitrite/migration/
migration.rs

1use crate::errors::{ErrorKind, NitriteError, NitriteResult};
2use crate::migration::{InstructionSet, InstructionType};
3use std::any::Any;
4use std::collections::VecDeque;
5use std::sync::atomic::AtomicBool;
6use std::sync::{Arc, Mutex};
7
8/// Type-erased migration argument shared across steps.
9type AnyArg = Arc<dyn Any + Send + Sync>;
10/// Boxed migration function executed against an [`InstructionSet`].
11type MigrateFn = Box<dyn Fn(&InstructionSet) -> NitriteResult<()> + Send + Sync>;
12
13/// Represents a single migration step with its type and arguments.
14///
15/// # Purpose
16/// Encapsulates a discrete database schema migration operation with all necessary context
17/// including the operation type, scope (collection/entity), and operation-specific arguments.
18///
19/// # Characteristics
20/// - Immutable after creation (all fields are public and set at construction)
21/// - Clone-able for reuse and sharing across execution contexts
22/// - Stores arguments in type-erased form via MigrationArguments enum
23/// - Scope is optional (database-level operations have None for collection/entity)
24///
25/// # Fields
26/// * `instruction_type` - Type of migration operation (e.g., AddUser, DropCollection)
27/// * `collection_name` - Optional: collection affected by this step (None for database-level ops)
28/// * `entity_name` - Optional: entity type name for repository operations
29/// * `key` - Optional: key field name for repository operations
30/// * `arguments` - Type-erased arguments specific to the operation type
31#[derive(Clone)]
32pub struct MigrationStep {
33    pub instruction_type: InstructionType,
34    pub collection_name: Option<String>,
35    pub entity_name: Option<String>,
36    pub key: Option<String>,
37    pub arguments: MigrationArguments,
38}
39
40impl std::fmt::Debug for MigrationStep {
41    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
42        f.debug_struct("MigrationStep")
43            .field("instruction_type", &self.instruction_type)
44            .field("collection_name", &self.collection_name)
45            .field("entity_name", &self.entity_name)
46            .field("key", &self.key)
47            .field("arguments", &"<arguments>")
48            .finish()
49    }
50}
51
52/// Type-erased arguments container for migration operations.
53///
54/// # Purpose
55/// Provides a flexible mechanism to store arguments of any type (including closures) for
56/// migration operations. Uses Arc and Any trait object pattern for thread-safe type erasure.
57///
58/// # Characteristics
59/// - Supports 0 to 4+ arguments via different variants
60/// - Thread-safe: all Arc contents implement Send + Sync
61/// - Type-erased: arguments must be downcast to correct type when retrieved
62/// - Clone-able: arguments are shared via Arc, not copied
63///
64/// # Variants
65/// * `None` - No arguments (e.g., drop_all_indices)
66/// * `Single(Arc<T>)` - One argument (e.g., field_name: String)
67/// * `Double(Arc<T1>, Arc<T2>)` - Two arguments (e.g., old_name, new_name)
68/// * `Triple(Arc<T1>, Arc<T2>, Arc<T3>)` - Three arguments
69/// * `Quad(Arc<T1>, Arc<T2>, Arc<T3>, Arc<T4>)` - Four arguments
70/// * `Multiple(Vec<Arc<dyn Any>>)` - Variable number of arguments
71#[derive(Clone)]
72pub enum MigrationArguments {
73    None,
74    Single(Arc<dyn Any + Send + Sync>),
75    Double(Arc<dyn Any + Send + Sync>, Arc<dyn Any + Send + Sync>),
76    Triple(Arc<dyn Any + Send + Sync>, Arc<dyn Any + Send + Sync>, Arc<dyn Any + Send + Sync>),
77    Quad(Arc<dyn Any + Send + Sync>, Arc<dyn Any + Send + Sync>, Arc<dyn Any + Send + Sync>, Arc<dyn Any + Send + Sync>),
78    Multiple(Vec<Arc<dyn Any + Send + Sync>>),
79}
80
81impl std::fmt::Debug for MigrationArguments {
82    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
83        match self {
84            MigrationArguments::None => write!(f, "None"),
85            MigrationArguments::Single(_) => write!(f, "Single(<value>)"),
86            MigrationArguments::Double(_, _) => write!(f, "Double(<value>, <value>)"),
87            MigrationArguments::Triple(_, _, _) => write!(f, "Triple(<value>, <value>, <value>)"),
88            MigrationArguments::Quad(_, _, _, _) => write!(f, "Quad(<value>, <value>, <value>, <value>)"),
89            MigrationArguments::Multiple(_) => write!(f, "Multiple(<values>)"),
90        }
91    }
92}
93
94impl MigrationArguments {
95    /// Downcasts single argument to specified type.
96    ///
97    /// # Arguments
98    /// * `T` - Target type for downcast
99    ///
100    /// # Returns
101    /// `Ok(T)` - Cloned value if downcast succeeds
102    /// `Err(NitriteError)` - If variant is not Single or type mismatch
103    pub fn as_single<T: Any + Send + Sync + Clone + 'static>(&self) -> NitriteResult<T> {
104        match self {
105            MigrationArguments::Single(arg) => {
106                arg.downcast_ref::<T>()
107                    .cloned()
108                    .ok_or_else(|| NitriteError::new(
109                        "Failed to downcast single argument",
110                        ErrorKind::ValidationError,
111                    ))
112            }
113            _ => Err(NitriteError::new(
114                "Expected single argument",
115                ErrorKind::ValidationError,
116            )),
117        }
118    }
119
120    /// Downcasts two arguments to specified types.
121    ///
122    /// # Arguments
123    /// * `T1` - Target type for first argument
124    /// * `T2` - Target type for second argument
125    ///
126    /// # Returns
127    /// `Ok((T1, T2))` - Tuple of cloned values if both downcasts succeed
128    /// `Err(NitriteError)` - If variant is not Double or any type mismatch
129    pub fn as_double<T1, T2>(&self) -> NitriteResult<(T1, T2)>
130    where
131        T1: Any + Send + Sync + Clone + 'static,
132        T2: Any + Send + Sync + Clone + 'static,
133    {
134        match self {
135            MigrationArguments::Double(arg1, arg2) => {
136                let a = arg1.downcast_ref::<T1>()
137                    .cloned()
138                    .ok_or_else(|| NitriteError::new(
139                        "Failed to downcast first argument",
140                        ErrorKind::ValidationError,
141                    ))?;
142                let b = arg2.downcast_ref::<T2>()
143                    .cloned()
144                    .ok_or_else(|| NitriteError::new(
145                        "Failed to downcast second argument",
146                        ErrorKind::ValidationError,
147                    ))?;
148                Ok((a, b))
149            }
150            _ => Err(NitriteError::new(
151                "Expected double arguments",
152                ErrorKind::ValidationError,
153            )),
154        }
155    }
156
157    /// Downcasts three arguments to specified types.
158    ///
159    /// # Arguments
160    /// * `T1` - Target type for first argument
161    /// * `T2` - Target type for second argument
162    /// * `T3` - Target type for third argument
163    ///
164    /// # Returns
165    /// `Ok((T1, T2, T3))` - Tuple of cloned values if all downcasts succeed
166    /// `Err(NitriteError)` - If variant is not Triple or any type mismatch
167    pub fn as_triple<T1, T2, T3>(&self) -> NitriteResult<(T1, T2, T3)>
168    where
169        T1: Any + Send + Sync + Clone + 'static,
170        T2: Any + Send + Sync + Clone + 'static,
171        T3: Any + Send + Sync + Clone + 'static,
172    {
173        match self {
174            MigrationArguments::Triple(arg1, arg2, arg3) => {
175                let a = arg1.downcast_ref::<T1>()
176                    .cloned()
177                    .ok_or_else(|| NitriteError::new(
178                        "Failed to downcast first argument",
179                        ErrorKind::ValidationError,
180                    ))?;
181                let b = arg2.downcast_ref::<T2>()
182                    .cloned()
183                    .ok_or_else(|| NitriteError::new(
184                        "Failed to downcast second argument",
185                        ErrorKind::ValidationError,
186                    ))?;
187                let c = arg3.downcast_ref::<T3>()
188                    .cloned()
189                    .ok_or_else(|| NitriteError::new(
190                        "Failed to downcast third argument",
191                        ErrorKind::ValidationError,
192                    ))?;
193                Ok((a, b, c))
194            }
195            _ => Err(NitriteError::new(
196                "Expected triple arguments",
197                ErrorKind::ValidationError,
198            )),
199        }
200    }
201
202    /// Downcasts four arguments to specified types.
203    ///
204    /// # Arguments
205    /// * `T1` - Target type for first argument
206    /// * `T2` - Target type for second argument
207    /// * `T3` - Target type for third argument
208    /// * `T4` - Target type for fourth argument
209    ///
210    /// # Returns
211    /// `Ok((T1, T2, T3, T4))` - Tuple of cloned values if all downcasts succeed
212    /// `Err(NitriteError)` - If variant is not Quad or any type mismatch
213    pub fn as_quad<T1, T2, T3, T4>(&self) -> NitriteResult<(T1, T2, T3, T4)>
214    where
215        T1: Any + Send + Sync + Clone + 'static,
216        T2: Any + Send + Sync + Clone + 'static,
217        T3: Any + Send + Sync + Clone + 'static,
218        T4: Any + Send + Sync + Clone + 'static,
219    {
220        match self {
221            MigrationArguments::Quad(arg1, arg2, arg3, arg4) => {
222                let a = arg1.downcast_ref::<T1>()
223                    .cloned()
224                    .ok_or_else(|| NitriteError::new(
225                        "Failed to downcast first argument",
226                        ErrorKind::ValidationError,
227                    ))?;
228                let b = arg2.downcast_ref::<T2>()
229                    .cloned()
230                    .ok_or_else(|| NitriteError::new(
231                        "Failed to downcast second argument",
232                        ErrorKind::ValidationError,
233                    ))?;
234                let c = arg3.downcast_ref::<T3>()
235                    .cloned()
236                    .ok_or_else(|| NitriteError::new(
237                        "Failed to downcast third argument",
238                        ErrorKind::ValidationError,
239                    ))?;
240                let d = arg4.downcast_ref::<T4>()
241                    .cloned()
242                    .ok_or_else(|| NitriteError::new(
243                        "Failed to downcast fourth argument",
244                        ErrorKind::ValidationError,
245                    ))?;
246                Ok((a, b, c, d))
247            }
248            _ => Err(NitriteError::new(
249                "Expected quad arguments",
250                ErrorKind::ValidationError,
251            )),
252        }
253    }
254
255    /// Downcasts multiple arguments to specified type.
256    ///
257    /// # Arguments
258    /// * `T` - Target type for all arguments (must be same for all)
259    ///
260    /// # Returns
261    /// `Ok(Vec<T>)` - Vector of cloned values if variant is Multiple and all downcast
262    /// `Err(NitriteError)` - If variant is not Multiple or any type mismatch
263    pub fn as_multiple<T: Any + Send + Sync + Clone + 'static>(&self) -> NitriteResult<Vec<T>> {
264        match self {
265            MigrationArguments::Multiple(args) => {
266                args.iter()
267                    .map(|arg| {
268                        arg.downcast_ref::<T>()
269                            .cloned()
270                            .ok_or_else(|| NitriteError::new(
271                                "Failed to downcast argument in multiple",
272                                ErrorKind::ValidationError,
273                            ))
274                    })
275                    .collect()
276            }
277            _ => Err(NitriteError::new(
278                "Expected multiple arguments",
279                ErrorKind::ValidationError,
280            )),
281        }
282    }
283
284    /// Returns single argument as Arc<dyn Any> without downcast.
285    ///
286    /// # Returns
287    /// `Ok(Arc<dyn Any>)` - Arc reference to underlying value
288    /// `Err(NitriteError)` - If variant is not Single
289    pub fn as_any_single(&self) -> NitriteResult<Arc<dyn Any + Send + Sync>> {
290        match self {
291            MigrationArguments::Single(arg) => Ok(Arc::clone(arg)),
292            _ => Err(NitriteError::new(
293                "Expected single argument",
294                ErrorKind::ValidationError,
295            )),
296        }
297    }
298
299    /// Returns two arguments as Arc<dyn Any> without downcast.
300    ///
301    /// # Returns
302    /// `Ok((Arc, Arc))` - Tuple of Arc references
303    /// `Err(NitriteError)` - If variant is not Double
304    pub fn as_any_double(&self) -> NitriteResult<(Arc<dyn Any + Send + Sync>, Arc<dyn Any + Send + Sync>)> {
305        match self {
306            MigrationArguments::Double(arg1, arg2) => Ok((Arc::clone(arg1), Arc::clone(arg2))),
307            _ => Err(NitriteError::new(
308                "Expected double arguments",
309                ErrorKind::ValidationError,
310            )),
311        }
312    }
313
314    /// Returns three arguments as Arc<dyn Any> without downcast.
315    ///
316    /// # Returns
317    /// `Ok((Arc, Arc, Arc))` - Tuple of Arc references
318    /// `Err(NitriteError)` - If variant is not Triple
319    pub fn as_any_triple(&self) -> NitriteResult<(AnyArg, AnyArg, AnyArg)> {
320        match self {
321            MigrationArguments::Triple(arg1, arg2, arg3) => Ok((Arc::clone(arg1), Arc::clone(arg2), Arc::clone(arg3))),
322            _ => Err(NitriteError::new(
323                "Expected triple arguments",
324                ErrorKind::ValidationError,
325            )),
326        }
327    }
328
329    /// Returns multiple arguments as Vec<Arc<dyn Any>> without downcast.
330    ///
331    /// # Returns
332    /// `Ok(Vec<Arc>)` - Vector of Arc references
333    /// `Err(NitriteError)` - If variant is not Multiple
334    pub fn as_any_multiple(&self) -> NitriteResult<Vec<Arc<dyn Any + Send + Sync>>> {
335        match self {
336            MigrationArguments::Multiple(args) => Ok(args.iter().map(Arc::clone).collect()),
337            _ => Err(NitriteError::new(
338                "Expected multiple arguments",
339                ErrorKind::ValidationError,
340            )),
341        }
342    }
343
344    /// Returns count of arguments for this variant.
345    ///
346    /// # Returns
347    /// Count as usize: 0 for None, 1 for Single, 2 for Double, etc.
348    pub fn arg_count(&self) -> usize {
349        match self {
350            MigrationArguments::None => 0,
351            MigrationArguments::Single(_) => 1,
352            MigrationArguments::Double(_, _) => 2,
353            MigrationArguments::Triple(_, _, _) => 3,
354            MigrationArguments::Quad(_, _, _, _) => 4,
355            MigrationArguments::Multiple(args) => args.len(),
356        }
357    }
358}
359
360/// Abstract base class for user-defined migrations.
361///
362/// # Purpose
363/// Represents a versioned database schema migration that can be applied to upgrade
364/// the database from one schema version to another. Encapsulates migration steps
365/// and provides lazy execution semantics.
366///
367/// # Characteristics
368/// - Immutable public API with internal mutable state via Arc<Mutex<>>
369/// - Clone-able: clones share the same underlying migration state via Arc
370/// - Lazy execution: migration steps are generated on first call to steps()
371/// - Idempotent: multiple steps() calls return cached results (execute() called once)
372/// - Closure-based: migration logic defined by user-provided function
373///
374/// # Usage
375/// ```ignore
376/// let migration = Migration::new(1, 2, |instruction| {
377///     instruction.for_database().add_user("admin", "password")
378///         .drop_collection("test");
379///     instruction.for_collection("users").rename("customers");
380///     instruction.for_repository("books", None).delete_field("price");
381///     Ok(())
382/// });
383///
384/// // Apply to database
385/// let db = Nitrite::builder()
386///     .schema_version(2)
387///     .add_migration(migration)
388///     .open_or_create(Some("admin"), Some("password"))?;
389/// ```
390#[derive(Debug, Clone)]
391pub struct Migration {
392    inner: Arc<MigrationInner>,
393}
394
395impl Migration {
396    /// Creates a new migration for upgrading from one schema version to another.
397    ///
398    /// # Arguments
399    /// * `from_version` - Source schema version
400    /// * `to_version` - Target schema version
401    /// * `migrate` - Closure that defines migration operations via InstructionSet
402    ///
403    /// # Returns
404    /// Migration instance wrapping the migration logic
405    ///
406    /// # Behavior
407    /// - The migrate closure is not executed immediately
408    /// - Execution is deferred until first call to steps() or execute()
409    /// - Closure receives immutable InstructionSet reference for building instructions
410    pub fn new(from_version: u32, to_version: u32, migrate: impl Fn(&InstructionSet) -> NitriteResult<()> + Send + Sync + 'static) -> Self {
411        Migration {
412            inner: Arc::new(MigrationInner {
413                from_version,
414                to_version,
415                migration_steps: Mutex::new(VecDeque::new()),
416                executed: AtomicBool::new(false),
417                migrate: Box::new(migrate),
418            }),
419        }
420    }
421
422    /// Returns the source schema version for this migration.
423    ///
424    /// # Returns
425    /// Schema version as u32
426    pub fn from_version(&self) -> u32 {
427        self.inner.from_version
428    }
429
430    /// Returns the target schema version for this migration.
431    ///
432    /// # Returns
433    /// Schema version as u32
434    pub fn to_version(&self) -> u32 {
435        self.inner.to_version
436    }
437
438    /// Returns all migration steps, triggering lazy execution on first call.
439    ///
440    /// # Returns
441    /// `Ok(Vec<MigrationStep>)` - All migration steps generated by the migration closure
442    /// `Err(NitriteError)` - If migration execution fails or state access fails
443    ///
444    /// # Behavior
445    /// - First call executes the migration closure to generate steps
446    /// - Subsequent calls return cached steps without re-execution
447    /// - Executed flag prevents duplicate execution
448    pub fn steps(&self) -> NitriteResult<Vec<MigrationStep>> {
449        let executed = self.inner.executed.load(std::sync::atomic::Ordering::SeqCst);
450        
451        if !executed {
452            self.execute()?;
453        }
454
455        let steps = self.inner.migration_steps.lock()
456            .map_err(|_| NitriteError::new("Failed to acquire lock on migration_steps", ErrorKind::ValidationError))?;
457        Ok(steps.iter().cloned().collect())
458    }
459
460    /// Executes the migration closure to generate and store migration steps.
461    ///
462    /// # Returns
463    /// `Ok(())` - Migration executed successfully
464    /// `Err(NitriteError)` - If migration closure fails or state access fails
465    ///
466    /// # Behavior
467    /// - Creates InstructionSet with empty initial steps
468    /// - Calls user-provided migrate closure with InstructionSet
469    /// - Collects generated steps from InstructionSet
470    /// - Sets executed flag to prevent re-execution
471    pub(crate) fn execute(&self) -> NitriteResult<()> {
472        let steps = self.get_all_steps()?;
473        let instruction_set = InstructionSet::new(steps);
474        (self.inner.migrate)(&instruction_set)?;
475        
476        // Replace migration steps with the steps from InstructionSet (which may have been modified by the closure)
477        let new_steps = instruction_set.get_steps()?;
478        let mut migration_steps = self.inner.migration_steps.lock()
479            .map_err(|_| NitriteError::new("Failed to acquire lock on migration_steps", ErrorKind::ValidationError))?;
480        migration_steps.clear();
481        for step in new_steps {
482            migration_steps.push_back(step);
483        }
484        
485        self.inner.executed.store(true, std::sync::atomic::Ordering::SeqCst);
486        Ok(())        
487    }
488
489    /// Adds a migration step to the internal step queue.
490    ///
491    /// # Arguments
492    /// * `step` - MigrationStep to add
493    ///
494    /// # Returns
495    /// `Ok(())` - Step added successfully
496    /// `Err(NitriteError)` - If state access fails
497    pub(crate) fn add_step(&self, step: MigrationStep) -> NitriteResult<()> {
498        let mut steps = self.inner.migration_steps.lock()
499            .map_err(|_| NitriteError::new("Failed to acquire lock on migration_steps", ErrorKind::ValidationError))?;
500        steps.push_back(step);
501        Ok(())
502    }
503
504    /// Returns all currently stored migration steps without execution.
505    ///
506    /// # Returns
507    /// `Ok(Vec<MigrationStep>)` - All accumulated steps
508    /// `Err(NitriteError)` - If state access fails
509    pub(crate) fn get_all_steps(&self) -> NitriteResult<Vec<MigrationStep>> {
510        let steps = self.inner.migration_steps.lock()
511            .map_err(|_| NitriteError::new("Failed to acquire lock on migration_steps", ErrorKind::ValidationError))?;
512        Ok(steps.iter().cloned().collect())
513    }
514}
515
516/// Internal implementation details for Migration.
517///
518/// # Purpose
519/// Stores the actual state and closure for a migration. Wrapped in Arc for shared ownership
520/// and thread-safe access via Mutex/AtomicBool synchronization primitives.
521///
522/// # Characteristics
523/// - Not directly exposed in public API (wrapped by Migration)
524/// - Thread-safe: mutation through Mutex<VecDeque> and AtomicBool
525/// - Stores user-provided migrate closure as Box trait object
526/// - Immutable version fields for validation
527pub struct MigrationInner {
528    from_version: u32,
529    to_version: u32,
530    migration_steps: Mutex<VecDeque<MigrationStep>>,
531    executed: AtomicBool,
532    migrate: MigrateFn,
533}
534
535impl std::fmt::Debug for MigrationInner {
536    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
537        f.debug_struct("MigrationInner")
538            .field("from_version", &self.from_version)
539            .field("to_version", &self.to_version)
540            .finish()
541    }
542}
543
544#[cfg(test)]
545mod tests {
546    use super::*;
547
548    // ==================== MigrationStep Tests ====================
549
550    #[test]
551    fn test_migration_step_creation() {
552        // Test MigrationStep creation with basic fields
553        let step = MigrationStep {
554            instruction_type: InstructionType::AddUser,
555            collection_name: Some("users".to_string()),
556            entity_name: Some("User".to_string()),
557            key: Some("id".to_string()),
558            arguments: MigrationArguments::None,
559        };
560
561        assert_eq!(step.instruction_type, InstructionType::AddUser);
562        assert_eq!(step.collection_name, Some("users".to_string()));
563        assert_eq!(step.entity_name, Some("User".to_string()));
564        assert_eq!(step.key, Some("id".to_string()));
565    }
566
567    #[test]
568    fn test_migration_step_with_no_optional_fields() {
569        // Test MigrationStep with all None optional fields
570        let step = MigrationStep {
571            instruction_type: InstructionType::CustomInstruction,
572            collection_name: None,
573            entity_name: None,
574            key: None,
575            arguments: MigrationArguments::None,
576        };
577
578        assert_eq!(step.collection_name, None);
579        assert_eq!(step.entity_name, None);
580        assert_eq!(step.key, None);
581    }
582
583    #[test]
584    fn test_migration_step_clone() {
585        // Test that MigrationStep can be cloned
586        let step = MigrationStep {
587            instruction_type: InstructionType::DropCollection,
588            collection_name: Some("test".to_string()),
589            entity_name: None,
590            key: None,
591            arguments: MigrationArguments::None,
592        };
593
594        let cloned = step.clone();
595        assert_eq!(cloned.instruction_type, step.instruction_type);
596        assert_eq!(cloned.collection_name, step.collection_name);
597    }
598
599    #[test]
600    fn test_migration_step_debug_format() {
601        // Test Debug implementation for MigrationStep
602        let step = MigrationStep {
603            instruction_type: InstructionType::AddUser,
604            collection_name: Some("col".to_string()),
605            entity_name: None,
606            key: None,
607            arguments: MigrationArguments::None,
608        };
609
610        let debug_str = format!("{:?}", step);
611        assert!(debug_str.contains("MigrationStep"));
612        assert!(debug_str.contains("AddUser"));
613    }
614
615    // ==================== MigrationArguments::None Tests ====================
616
617    #[test]
618    fn test_migration_arguments_none() {
619        // Test None variant creation and arg_count
620        let args = MigrationArguments::None;
621        assert_eq!(args.arg_count(), 0);
622    }
623
624    #[test]
625    fn test_migration_arguments_none_debug() {
626        // Test Debug format for None
627        let args = MigrationArguments::None;
628        let debug_str = format!("{:?}", args);
629        assert_eq!(debug_str, "None");
630    }
631
632    #[test]
633    fn test_migration_arguments_none_as_single_error() {
634        // Test as_single() returns error for None
635        let args = MigrationArguments::None;
636        let result: NitriteResult<String> = args.as_single();
637        assert!(result.is_err());
638    }
639
640    #[test]
641    fn test_migration_arguments_none_as_double_error() {
642        // Test as_double() returns error for None
643        let args = MigrationArguments::None;
644        let result: NitriteResult<(String, String)> = args.as_double();
645        assert!(result.is_err());
646    }
647
648    #[test]
649    fn test_migration_arguments_none_as_triple_error() {
650        // Test as_triple() returns error for None
651        let args = MigrationArguments::None;
652        let result: NitriteResult<(String, String, String)> = args.as_triple();
653        assert!(result.is_err());
654    }
655
656    #[test]
657    fn test_migration_arguments_none_as_quad_error() {
658        // Test as_quad() returns error for None
659        let args = MigrationArguments::None;
660        let result: NitriteResult<(String, String, String, String)> = args.as_quad();
661        assert!(result.is_err());
662    }
663
664    #[test]
665    fn test_migration_arguments_none_as_multiple_error() {
666        // Test as_multiple() returns error for None
667        let args = MigrationArguments::None;
668        let result: NitriteResult<Vec<String>> = args.as_multiple();
669        assert!(result.is_err());
670    }
671
672    #[test]
673    fn test_migration_arguments_none_as_any_single_error() {
674        // Test as_any_single() returns error for None
675        let args = MigrationArguments::None;
676        let result = args.as_any_single();
677        assert!(result.is_err());
678    }
679
680    #[test]
681    fn test_migration_arguments_none_as_any_double_error() {
682        // Test as_any_double() returns error for None
683        let args = MigrationArguments::None;
684        let result = args.as_any_double();
685        assert!(result.is_err());
686    }
687
688    #[test]
689    fn test_migration_arguments_none_as_any_triple_error() {
690        // Test as_any_triple() returns error for None
691        let args = MigrationArguments::None;
692        let result = args.as_any_triple();
693        assert!(result.is_err());
694    }
695
696    #[test]
697    fn test_migration_arguments_none_as_any_multiple_error() {
698        // Test as_any_multiple() returns error for None
699        let args = MigrationArguments::None;
700        let result = args.as_any_multiple();
701        assert!(result.is_err());
702    }
703
704    // ==================== MigrationArguments::Single Tests ====================
705
706    #[test]
707    fn test_migration_arguments_single_creation() {
708        // Test Single variant creation
709        let value = Arc::new("test" as &str);
710        let args = MigrationArguments::Single(value);
711        assert_eq!(args.arg_count(), 1);
712    }
713
714    #[test]
715    fn test_migration_arguments_single_as_single_success() {
716        // Test successful as_single() for Single variant
717        let value = Arc::new("test".to_string());
718        let args = MigrationArguments::Single(value);
719        let result: NitriteResult<String> = args.as_single();
720        assert!(result.is_ok());
721        assert_eq!(result.unwrap(), "test".to_string());
722    }
723
724    #[test]
725    fn test_migration_arguments_single_as_single_type_mismatch() {
726        // Test as_single() with wrong type
727        let value = Arc::new(42i32);
728        let args = MigrationArguments::Single(value);
729        let result: NitriteResult<String> = args.as_single();
730        assert!(result.is_err());
731    }
732
733    #[test]
734    fn test_migration_arguments_single_as_double_error() {
735        // Test as_double() returns error for Single
736        let value = Arc::new("test".to_string());
737        let args = MigrationArguments::Single(value);
738        let result: NitriteResult<(String, String)> = args.as_double();
739        assert!(result.is_err());
740    }
741
742    #[test]
743    fn test_migration_arguments_single_debug() {
744        // Test Debug format for Single
745        let value = Arc::new("test".to_string());
746        let args = MigrationArguments::Single(value);
747        let debug_str = format!("{:?}", args);
748        assert_eq!(debug_str, "Single(<value>)");
749    }
750
751    #[test]
752    fn test_migration_arguments_single_as_any_single_success() {
753        // Test successful as_any_single()
754        let value = Arc::new("test".to_string());
755        let args = MigrationArguments::Single(value.clone());
756        let result = args.as_any_single();
757        assert!(result.is_ok());
758    }
759
760    #[test]
761    fn test_migration_arguments_single_clone() {
762        // Test clone for Single variant
763        let value = Arc::new("test".to_string());
764        let args = MigrationArguments::Single(value);
765        let cloned = args.clone();
766        assert_eq!(cloned.arg_count(), 1);
767    }
768
769    // ==================== MigrationArguments::Double Tests ====================
770
771    #[test]
772    fn test_migration_arguments_double_creation() {
773        // Test Double variant creation
774        let arg1 = Arc::new("first".to_string());
775        let arg2 = Arc::new("second".to_string());
776        let args = MigrationArguments::Double(arg1, arg2);
777        assert_eq!(args.arg_count(), 2);
778    }
779
780    #[test]
781    fn test_migration_arguments_double_as_double_success() {
782        // Test successful as_double()
783        let arg1 = Arc::new("first".to_string());
784        let arg2 = Arc::new("second".to_string());
785        let args = MigrationArguments::Double(arg1, arg2);
786        let result: NitriteResult<(String, String)> = args.as_double();
787        assert!(result.is_ok());
788        let (a, b) = result.unwrap();
789        assert_eq!(a, "first".to_string());
790        assert_eq!(b, "second".to_string());
791    }
792
793    #[test]
794    fn test_migration_arguments_double_as_double_first_type_mismatch() {
795        // Test as_double() with first argument wrong type
796        let arg1 = Arc::new(42i32);
797        let arg2 = Arc::new("second".to_string());
798        let args = MigrationArguments::Double(arg1, arg2);
799        let result: NitriteResult<(String, String)> = args.as_double();
800        assert!(result.is_err());
801    }
802
803    #[test]
804    fn test_migration_arguments_double_as_double_second_type_mismatch() {
805        // Test as_double() with second argument wrong type
806        let arg1 = Arc::new("first".to_string());
807        let arg2 = Arc::new(42i32);
808        let args = MigrationArguments::Double(arg1, arg2);
809        let result: NitriteResult<(String, String)> = args.as_double();
810        assert!(result.is_err());
811    }
812
813    #[test]
814    fn test_migration_arguments_double_as_triple_error() {
815        // Test as_triple() returns error for Double
816        let arg1 = Arc::new("first".to_string());
817        let arg2 = Arc::new("second".to_string());
818        let args = MigrationArguments::Double(arg1, arg2);
819        let result: NitriteResult<(String, String, String)> = args.as_triple();
820        assert!(result.is_err());
821    }
822
823    #[test]
824    fn test_migration_arguments_double_debug() {
825        // Test Debug format for Double
826        let arg1 = Arc::new("first".to_string());
827        let arg2 = Arc::new("second".to_string());
828        let args = MigrationArguments::Double(arg1, arg2);
829        let debug_str = format!("{:?}", args);
830        assert_eq!(debug_str, "Double(<value>, <value>)");
831    }
832
833    #[test]
834    fn test_migration_arguments_double_as_any_double_success() {
835        // Test successful as_any_double()
836        let arg1 = Arc::new("first".to_string());
837        let arg2 = Arc::new("second".to_string());
838        let args = MigrationArguments::Double(arg1.clone(), arg2.clone());
839        let result = args.as_any_double();
840        assert!(result.is_ok());
841    }
842
843    // ==================== MigrationArguments::Triple Tests ====================
844
845    #[test]
846    fn test_migration_arguments_triple_creation() {
847        // Test Triple variant creation
848        let arg1 = Arc::new("first".to_string());
849        let arg2 = Arc::new("second".to_string());
850        let arg3 = Arc::new("third".to_string());
851        let args = MigrationArguments::Triple(arg1, arg2, arg3);
852        assert_eq!(args.arg_count(), 3);
853    }
854
855    #[test]
856    fn test_migration_arguments_triple_as_triple_success() {
857        // Test successful as_triple()
858        let arg1 = Arc::new("first".to_string());
859        let arg2 = Arc::new("second".to_string());
860        let arg3 = Arc::new("third".to_string());
861        let args = MigrationArguments::Triple(arg1, arg2, arg3);
862        let result: NitriteResult<(String, String, String)> = args.as_triple();
863        assert!(result.is_ok());
864        let (a, b, c) = result.unwrap();
865        assert_eq!(a, "first".to_string());
866        assert_eq!(b, "second".to_string());
867        assert_eq!(c, "third".to_string());
868    }
869
870    #[test]
871    fn test_migration_arguments_triple_as_triple_first_type_mismatch() {
872        // Test as_triple() with first argument wrong type
873        let arg1 = Arc::new(42i32);
874        let arg2 = Arc::new("second".to_string());
875        let arg3 = Arc::new("third".to_string());
876        let args = MigrationArguments::Triple(arg1, arg2, arg3);
877        let result: NitriteResult<(String, String, String)> = args.as_triple();
878        assert!(result.is_err());
879    }
880
881    #[test]
882    fn test_migration_arguments_triple_as_triple_second_type_mismatch() {
883        // Test as_triple() with second argument wrong type
884        let arg1 = Arc::new("first".to_string());
885        let arg2 = Arc::new(42i32);
886        let arg3 = Arc::new("third".to_string());
887        let args = MigrationArguments::Triple(arg1, arg2, arg3);
888        let result: NitriteResult<(String, String, String)> = args.as_triple();
889        assert!(result.is_err());
890    }
891
892    #[test]
893    fn test_migration_arguments_triple_as_triple_third_type_mismatch() {
894        // Test as_triple() with third argument wrong type
895        let arg1 = Arc::new("first".to_string());
896        let arg2 = Arc::new("second".to_string());
897        let arg3 = Arc::new(42i32);
898        let args = MigrationArguments::Triple(arg1, arg2, arg3);
899        let result: NitriteResult<(String, String, String)> = args.as_triple();
900        assert!(result.is_err());
901    }
902
903    #[test]
904    fn test_migration_arguments_triple_as_quad_error() {
905        // Test as_quad() returns error for Triple
906        let arg1 = Arc::new("first".to_string());
907        let arg2 = Arc::new("second".to_string());
908        let arg3 = Arc::new("third".to_string());
909        let args = MigrationArguments::Triple(arg1, arg2, arg3);
910        let result: NitriteResult<(String, String, String, String)> = args.as_quad();
911        assert!(result.is_err());
912    }
913
914    #[test]
915    fn test_migration_arguments_triple_debug() {
916        // Test Debug format for Triple
917        let arg1 = Arc::new("first".to_string());
918        let arg2 = Arc::new("second".to_string());
919        let arg3 = Arc::new("third".to_string());
920        let args = MigrationArguments::Triple(arg1, arg2, arg3);
921        let debug_str = format!("{:?}", args);
922        assert_eq!(debug_str, "Triple(<value>, <value>, <value>)");
923    }
924
925    #[test]
926    fn test_migration_arguments_triple_as_any_triple_success() {
927        // Test successful as_any_triple()
928        let arg1 = Arc::new("first".to_string());
929        let arg2 = Arc::new("second".to_string());
930        let arg3 = Arc::new("third".to_string());
931        let args = MigrationArguments::Triple(arg1.clone(), arg2.clone(), arg3.clone());
932        let result = args.as_any_triple();
933        assert!(result.is_ok());
934    }
935
936    // ==================== MigrationArguments::Quad Tests ====================
937
938    #[test]
939    fn test_migration_arguments_quad_creation() {
940        // Test Quad variant creation
941        let arg1 = Arc::new("first".to_string());
942        let arg2 = Arc::new("second".to_string());
943        let arg3 = Arc::new("third".to_string());
944        let arg4 = Arc::new("fourth".to_string());
945        let args = MigrationArguments::Quad(arg1, arg2, arg3, arg4);
946        assert_eq!(args.arg_count(), 4);
947    }
948
949    #[test]
950    fn test_migration_arguments_quad_as_quad_success() {
951        // Test successful as_quad()
952        let arg1 = Arc::new("first".to_string());
953        let arg2 = Arc::new("second".to_string());
954        let arg3 = Arc::new("third".to_string());
955        let arg4 = Arc::new("fourth".to_string());
956        let args = MigrationArguments::Quad(arg1, arg2, arg3, arg4);
957        let result: NitriteResult<(String, String, String, String)> = args.as_quad();
958        assert!(result.is_ok());
959        let (a, b, c, d) = result.unwrap();
960        assert_eq!(a, "first".to_string());
961        assert_eq!(b, "second".to_string());
962        assert_eq!(c, "third".to_string());
963        assert_eq!(d, "fourth".to_string());
964    }
965
966    #[test]
967    fn test_migration_arguments_quad_as_quad_first_type_mismatch() {
968        // Test as_quad() with first argument wrong type
969        let arg1 = Arc::new(42i32);
970        let arg2 = Arc::new("second".to_string());
971        let arg3 = Arc::new("third".to_string());
972        let arg4 = Arc::new("fourth".to_string());
973        let args = MigrationArguments::Quad(arg1, arg2, arg3, arg4);
974        let result: NitriteResult<(String, String, String, String)> = args.as_quad();
975        assert!(result.is_err());
976    }
977
978    #[test]
979    fn test_migration_arguments_quad_as_quad_second_type_mismatch() {
980        // Test as_quad() with second argument wrong type
981        let arg1 = Arc::new("first".to_string());
982        let arg2 = Arc::new(42i32);
983        let arg3 = Arc::new("third".to_string());
984        let arg4 = Arc::new("fourth".to_string());
985        let args = MigrationArguments::Quad(arg1, arg2, arg3, arg4);
986        let result: NitriteResult<(String, String, String, String)> = args.as_quad();
987        assert!(result.is_err());
988    }
989
990    #[test]
991    fn test_migration_arguments_quad_as_quad_third_type_mismatch() {
992        // Test as_quad() with third argument wrong type
993        let arg1 = Arc::new("first".to_string());
994        let arg2 = Arc::new("second".to_string());
995        let arg3 = Arc::new(42i32);
996        let arg4 = Arc::new("fourth".to_string());
997        let args = MigrationArguments::Quad(arg1, arg2, arg3, arg4);
998        let result: NitriteResult<(String, String, String, String)> = args.as_quad();
999        assert!(result.is_err());
1000    }
1001
1002    #[test]
1003    fn test_migration_arguments_quad_as_quad_fourth_type_mismatch() {
1004        // Test as_quad() with fourth argument wrong type
1005        let arg1 = Arc::new("first".to_string());
1006        let arg2 = Arc::new("second".to_string());
1007        let arg3 = Arc::new("third".to_string());
1008        let arg4 = Arc::new(42i32);
1009        let args = MigrationArguments::Quad(arg1, arg2, arg3, arg4);
1010        let result: NitriteResult<(String, String, String, String)> = args.as_quad();
1011        assert!(result.is_err());
1012    }
1013
1014    #[test]
1015    fn test_migration_arguments_quad_as_multiple_error() {
1016        // Test as_multiple() returns error for Quad
1017        let arg1 = Arc::new("first".to_string());
1018        let arg2 = Arc::new("second".to_string());
1019        let arg3 = Arc::new("third".to_string());
1020        let arg4 = Arc::new("fourth".to_string());
1021        let args = MigrationArguments::Quad(arg1, arg2, arg3, arg4);
1022        let result: NitriteResult<Vec<String>> = args.as_multiple();
1023        assert!(result.is_err());
1024    }
1025
1026    #[test]
1027    fn test_migration_arguments_quad_debug() {
1028        // Test Debug format for Quad
1029        let arg1 = Arc::new("first".to_string());
1030        let arg2 = Arc::new("second".to_string());
1031        let arg3 = Arc::new("third".to_string());
1032        let arg4 = Arc::new("fourth".to_string());
1033        let args = MigrationArguments::Quad(arg1, arg2, arg3, arg4);
1034        let debug_str = format!("{:?}", args);
1035        assert_eq!(debug_str, "Quad(<value>, <value>, <value>, <value>)");
1036    }
1037
1038    // ==================== MigrationArguments::Multiple Tests ====================
1039
1040    #[test]
1041    fn test_migration_arguments_multiple_empty() {
1042        // Test Multiple variant with empty vector
1043        let args = MigrationArguments::Multiple(vec![]);
1044        assert_eq!(args.arg_count(), 0);
1045    }
1046
1047    #[test]
1048    fn test_migration_arguments_multiple_single_item() {
1049        // Test Multiple variant with one item
1050        let arg = Arc::new("value".to_string());
1051        let args = MigrationArguments::Multiple(vec![arg]);
1052        assert_eq!(args.arg_count(), 1);
1053    }
1054
1055    #[test]
1056    fn test_migration_arguments_multiple_multiple_items() {
1057        // Test Multiple variant with multiple items
1058        let args_vec = vec![
1059            Arc::new("first".to_string()) as Arc<dyn Any + Send + Sync>,
1060            Arc::new("second".to_string()) as Arc<dyn Any + Send + Sync>,
1061            Arc::new("third".to_string()) as Arc<dyn Any + Send + Sync>,
1062        ];
1063        let args = MigrationArguments::Multiple(args_vec);
1064        assert_eq!(args.arg_count(), 3);
1065    }
1066
1067    #[test]
1068    fn test_migration_arguments_multiple_as_multiple_success() {
1069        // Test successful as_multiple()
1070        let args_vec = vec![
1071            Arc::new("first".to_string()) as Arc<dyn Any + Send + Sync>,
1072            Arc::new("second".to_string()) as Arc<dyn Any + Send + Sync>,
1073        ];
1074        let args = MigrationArguments::Multiple(args_vec);
1075        let result: NitriteResult<Vec<String>> = args.as_multiple();
1076        assert!(result.is_ok());
1077        let values = result.unwrap();
1078        assert_eq!(values.len(), 2);
1079        assert_eq!(values[0], "first".to_string());
1080        assert_eq!(values[1], "second".to_string());
1081    }
1082
1083    #[test]
1084    fn test_migration_arguments_multiple_as_multiple_type_mismatch() {
1085        // Test as_multiple() with wrong type
1086        let args_vec = vec![
1087            Arc::new(42i32) as Arc<dyn Any + Send + Sync>,
1088        ];
1089        let args = MigrationArguments::Multiple(args_vec);
1090        let result: NitriteResult<Vec<String>> = args.as_multiple();
1091        assert!(result.is_err());
1092    }
1093
1094    #[test]
1095    fn test_migration_arguments_multiple_as_single_error() {
1096        // Test as_single() returns error for Multiple
1097        let args_vec = vec![
1098            Arc::new("value".to_string()) as Arc<dyn Any + Send + Sync>,
1099        ];
1100        let args = MigrationArguments::Multiple(args_vec);
1101        let result: NitriteResult<String> = args.as_single();
1102        assert!(result.is_err());
1103    }
1104
1105    #[test]
1106    fn test_migration_arguments_multiple_debug() {
1107        // Test Debug format for Multiple
1108        let args_vec = vec![
1109            Arc::new("first".to_string()) as Arc<dyn Any + Send + Sync>,
1110        ];
1111        let args = MigrationArguments::Multiple(args_vec);
1112        let debug_str = format!("{:?}", args);
1113        assert_eq!(debug_str, "Multiple(<values>)");
1114    }
1115
1116    #[test]
1117    fn test_migration_arguments_multiple_as_any_multiple_success() {
1118        // Test successful as_any_multiple()
1119        let args_vec = vec![
1120            Arc::new("first".to_string()) as Arc<dyn Any + Send + Sync>,
1121            Arc::new("second".to_string()) as Arc<dyn Any + Send + Sync>,
1122        ];
1123        let args = MigrationArguments::Multiple(args_vec);
1124        let result = args.as_any_multiple();
1125        assert!(result.is_ok());
1126        assert_eq!(result.unwrap().len(), 2);
1127    }
1128
1129    // ==================== Migration Tests ====================
1130
1131    #[test]
1132    fn test_migration_new() {
1133        // Test Migration creation with new()
1134        let migration = Migration::new(1, 2, |_| Ok(()));
1135        assert_eq!(migration.from_version(), 1);
1136        assert_eq!(migration.to_version(), 2);
1137    }
1138
1139    #[test]
1140    fn test_migration_from_version() {
1141        // Test from_version() getter
1142        let migration = Migration::new(5, 10, |_| Ok(()));
1143        assert_eq!(migration.from_version(), 5);
1144    }
1145
1146    #[test]
1147    fn test_migration_to_version() {
1148        // Test to_version() getter
1149        let migration = Migration::new(3, 7, |_| Ok(()));
1150        assert_eq!(migration.to_version(), 7);
1151    }
1152
1153    #[test]
1154    fn test_migration_add_step() {
1155        // Test add_step() adds steps to migration
1156        let migration = Migration::new(1, 2, |_| Ok(()));
1157        
1158        let step = MigrationStep {
1159            instruction_type: InstructionType::AddUser,
1160            collection_name: None,
1161            entity_name: None,
1162            key: None,
1163            arguments: MigrationArguments::None,
1164        };
1165
1166        let result = migration.add_step(step);
1167        assert!(result.is_ok());
1168    }
1169
1170    #[test]
1171    fn test_migration_get_all_steps() {
1172        // Test get_all_steps() returns steps
1173        let migration = Migration::new(1, 2, |_| Ok(()));
1174        
1175        let step = MigrationStep {
1176            instruction_type: InstructionType::ChangePassword,
1177            collection_name: None,
1178            entity_name: None,
1179            key: None,
1180            arguments: MigrationArguments::None,
1181        };
1182
1183        migration.add_step(step).unwrap();
1184        let steps = migration.get_all_steps().unwrap();
1185        assert_eq!(steps.len(), 1);
1186        assert_eq!(steps[0].instruction_type, InstructionType::ChangePassword);
1187    }
1188
1189    #[test]
1190    fn test_migration_get_all_steps_multiple() {
1191        // Test get_all_steps() with multiple steps
1192        let migration = Migration::new(1, 2, |_| Ok(()));
1193        
1194        for i in 0..3 {
1195            let step = MigrationStep {
1196                instruction_type: if i == 0 { InstructionType::AddUser } else { InstructionType::ChangePassword },
1197                collection_name: None,
1198                entity_name: None,
1199                key: None,
1200                arguments: MigrationArguments::None,
1201            };
1202            migration.add_step(step).unwrap();
1203        }
1204
1205        let steps = migration.get_all_steps().unwrap();
1206        assert_eq!(steps.len(), 3);
1207    }
1208
1209    #[test]
1210    fn test_migration_execute_success() {
1211        // Test execute() successfully runs migration
1212        let migration = Migration::new(1, 2, |_| Ok(()));
1213        let result = migration.execute();
1214        assert!(result.is_ok());
1215    }
1216
1217    #[test]
1218    fn test_migration_execute_with_error() {
1219        // Test execute() propagates error from migration function
1220        let migration = Migration::new(1, 2, |_| {
1221            Err(NitriteError::new("Test error", ErrorKind::ValidationError))
1222        });
1223        let result = migration.execute();
1224        assert!(result.is_err());
1225    }
1226
1227    #[test]
1228    fn test_migration_steps_lazy_execution() {
1229        // Test steps() triggers lazy execution on first call
1230        let executed = Arc::new(Mutex::new(false));
1231        let executed_clone = executed.clone();
1232
1233        let migration = Migration::new(1, 2, move |_| {
1234            *executed_clone.lock().unwrap() = true;
1235            Ok(())
1236        });
1237
1238        let result = migration.steps();
1239        assert!(result.is_ok());
1240        assert!(*executed.lock().unwrap());
1241    }
1242
1243    #[test]
1244    fn test_migration_steps_cached() {
1245        // Test steps() doesn't re-execute on subsequent calls
1246        let call_count = Arc::new(Mutex::new(0));
1247        let call_count_clone = call_count.clone();
1248
1249        let migration = Migration::new(1, 2, move |_| {
1250            *call_count_clone.lock().unwrap() += 1;
1251            Ok(())
1252        });
1253
1254        let _ = migration.steps();
1255        let _ = migration.steps();
1256        
1257        // Should only be called once due to caching
1258        assert_eq!(*call_count.lock().unwrap(), 1);
1259    }
1260
1261    #[test]
1262    fn test_migration_steps_with_steps() {
1263        // Test steps() returns added steps
1264        let migration = Migration::new(1, 2, |_| Ok(()));
1265        
1266        let step = MigrationStep {
1267            instruction_type: InstructionType::DropCollection,
1268            collection_name: Some("users".to_string()),
1269            entity_name: None,
1270            key: None,
1271            arguments: MigrationArguments::None,
1272        };
1273
1274        migration.add_step(step).unwrap();
1275        let steps = migration.steps().unwrap();
1276        assert_eq!(steps.len(), 1);
1277        assert_eq!(steps[0].instruction_type, InstructionType::DropCollection);
1278        assert_eq!(steps[0].collection_name, Some("users".to_string()));
1279    }
1280
1281    #[test]
1282    fn test_migration_steps_returns_error() {
1283        // Test steps() returns error from execute()
1284        let migration = Migration::new(1, 2, |_| {
1285            Err(NitriteError::new("Exec error", ErrorKind::ValidationError))
1286        });
1287        let result = migration.steps();
1288        assert!(result.is_err());
1289    }
1290
1291    #[test]
1292    fn test_migration_clone() {
1293        // Test Migration can be cloned (via Arc)
1294        let migration = Migration::new(1, 2, |_| Ok(()));
1295        let cloned = Migration {
1296            inner: Arc::clone(&migration.inner),
1297        };
1298        
1299        assert_eq!(cloned.from_version(), 1);
1300        assert_eq!(cloned.to_version(), 2);
1301    }
1302
1303    #[test]
1304    fn test_migration_debug() {
1305        // Test Debug implementation for Migration
1306        let migration = Migration::new(1, 2, |_| Ok(()));
1307        let debug_str = format!("{:?}", migration);
1308        assert!(debug_str.contains("Migration"));
1309    }
1310
1311    #[test]
1312    fn test_migration_inner_debug() {
1313        // Test Debug implementation for MigrationInner
1314        let migration = Migration::new(3, 4, |_| Ok(()));
1315        let debug_str = format!("{:?}", migration);
1316        assert!(debug_str.contains("3") || debug_str.contains("4"));
1317    }
1318
1319    // ==================== Mixed Type Tests ====================
1320
1321    #[test]
1322    fn test_migration_arguments_single_with_integer() {
1323        // Test Single variant with integer type
1324        let value = Arc::new(42i32);
1325        let args = MigrationArguments::Single(value);
1326        let result: NitriteResult<i32> = args.as_single();
1327        assert!(result.is_ok());
1328        assert_eq!(result.unwrap(), 42);
1329    }
1330
1331    #[test]
1332    fn test_migration_arguments_double_with_mixed_types() {
1333        // Test Double variant with different types
1334        let arg1 = Arc::new("text".to_string());
1335        let arg2 = Arc::new(100i32);
1336        let args = MigrationArguments::Double(arg1, arg2);
1337        let result: NitriteResult<(String, i32)> = args.as_double();
1338        assert!(result.is_ok());
1339        let (text, num) = result.unwrap();
1340        assert_eq!(text, "text".to_string());
1341        assert_eq!(num, 100);
1342    }
1343
1344    #[test]
1345    fn test_migration_arguments_clone() {
1346        // Test clone for all variants
1347        let none_args = MigrationArguments::None;
1348        let cloned_none = none_args.clone();
1349        assert_eq!(cloned_none.arg_count(), 0);
1350
1351        let single_args = MigrationArguments::Single(Arc::new("test".to_string()));
1352        let cloned_single = single_args.clone();
1353        assert_eq!(cloned_single.arg_count(), 1);
1354    }
1355
1356    #[test]
1357    fn test_migration_step_with_all_fields() {
1358        // Test MigrationStep with all fields populated
1359        let step = MigrationStep {
1360            instruction_type: InstructionType::CustomInstruction,
1361            collection_name: Some("col".to_string()),
1362            entity_name: Some("Entity".to_string()),
1363            key: Some("id".to_string()),
1364            arguments: MigrationArguments::Double(
1365                Arc::new("arg1".to_string()),
1366                Arc::new("arg2".to_string()),
1367            ),
1368        };
1369
1370        assert_eq!(step.collection_name, Some("col".to_string()));
1371        assert_eq!(step.entity_name, Some("Entity".to_string()));
1372        assert_eq!(step.key, Some("id".to_string()));
1373        assert_eq!(step.arguments.arg_count(), 2);
1374    }
1375
1376    #[test]
1377    fn test_migration_arguments_single_as_triple_error() {
1378        // Test as_triple() returns error for Single
1379        let value = Arc::new("test".to_string());
1380        let args = MigrationArguments::Single(value);
1381        let result: NitriteResult<(String, String, String)> = args.as_triple();
1382        assert!(result.is_err());
1383    }
1384
1385    #[test]
1386    fn test_migration_arguments_single_as_quad_error() {
1387        // Test as_quad() returns error for Single
1388        let value = Arc::new("test".to_string());
1389        let args = MigrationArguments::Single(value);
1390        let result: NitriteResult<(String, String, String, String)> = args.as_quad();
1391        assert!(result.is_err());
1392    }
1393
1394    #[test]
1395    fn test_migration_arguments_double_as_single_error() {
1396        // Test as_single() returns error for Double
1397        let arg1 = Arc::new("first".to_string());
1398        let arg2 = Arc::new("second".to_string());
1399        let args = MigrationArguments::Double(arg1, arg2);
1400        let result: NitriteResult<String> = args.as_single();
1401        assert!(result.is_err());
1402    }
1403
1404    #[test]
1405    fn test_migration_arguments_triple_as_double_error() {
1406        // Test as_double() returns error for Triple
1407        let arg1 = Arc::new("first".to_string());
1408        let arg2 = Arc::new("second".to_string());
1409        let arg3 = Arc::new("third".to_string());
1410        let args = MigrationArguments::Triple(arg1, arg2, arg3);
1411        let result: NitriteResult<(String, String)> = args.as_double();
1412        assert!(result.is_err());
1413    }
1414
1415    #[test]
1416    fn test_migration_arguments_quad_as_single_error() {
1417        // Test as_single() returns error for Quad
1418        let arg1 = Arc::new("first".to_string());
1419        let arg2 = Arc::new("second".to_string());
1420        let arg3 = Arc::new("third".to_string());
1421        let arg4 = Arc::new("fourth".to_string());
1422        let args = MigrationArguments::Quad(arg1, arg2, arg3, arg4);
1423        let result: NitriteResult<String> = args.as_single();
1424        assert!(result.is_err());
1425    }
1426
1427    #[test]
1428    fn test_migration_arguments_quad_as_triple_error() {
1429        // Test as_triple() returns error for Quad
1430        let arg1 = Arc::new("first".to_string());
1431        let arg2 = Arc::new("second".to_string());
1432        let arg3 = Arc::new("third".to_string());
1433        let arg4 = Arc::new("fourth".to_string());
1434        let args = MigrationArguments::Quad(arg1, arg2, arg3, arg4);
1435        let result: NitriteResult<(String, String, String)> = args.as_triple();
1436        assert!(result.is_err());
1437    }
1438
1439    #[test]
1440    fn test_migration_arguments_multiple_as_double_error() {
1441        // Test as_double() returns error for Multiple
1442        let args_vec = vec![
1443            Arc::new("first".to_string()) as Arc<dyn Any + Send + Sync>,
1444            Arc::new("second".to_string()) as Arc<dyn Any + Send + Sync>,
1445        ];
1446        let args = MigrationArguments::Multiple(args_vec);
1447        let result: NitriteResult<(String, String)> = args.as_double();
1448        assert!(result.is_err());
1449    }
1450
1451    #[test]
1452    fn test_migration_arguments_multiple_partial_match() {
1453        // Test as_multiple() with partial type match (stops at first mismatch)
1454        let args_vec = vec![
1455            Arc::new("first".to_string()) as Arc<dyn Any + Send + Sync>,
1456            Arc::new(42i32) as Arc<dyn Any + Send + Sync>,
1457            Arc::new("third".to_string()) as Arc<dyn Any + Send + Sync>,
1458        ];
1459        let args = MigrationArguments::Multiple(args_vec);
1460        let result: NitriteResult<Vec<String>> = args.as_multiple();
1461        assert!(result.is_err());
1462    }
1463}