@@ -653,20 +653,116 @@ mod tests {
653653 for _ in 0 ..16 {
654654 let cx_guard = Context :: current ( ) . with_value ( ValueA ( 1 ) ) . attach ( ) ;
655655 assert_eq ! ( cx_guard. cx_pos, ContextStack :: MAX_POS ) ;
656- assert_eq ! ( Context :: current( ) . get( ) , Some ( & ValueA ( 2 ) ) ) ;
656+ assert_eq ! ( Context :: current( ) . get:: < ValueA > ( ) , Some ( & ValueA ( 2 ) ) ) ;
657657 assert_eq ! ( Context :: current( ) . get( ) , Some ( & ValueB ( stack_max_pos - 2 ) ) ) ;
658658 guards. push ( cx_guard) ;
659659 }
660660 }
661661
662+
663+
664+ /// Tests that a new ContextStack is created with the correct initial capacity.
665+ #[ test]
666+ fn test_initial_capacity ( ) {
667+ let stack = ContextStack :: default ( ) ;
668+ assert_eq ! ( stack. stack. capacity( ) , ContextStack :: INITIAL_CAPACITY ) ;
669+ }
670+
671+ /// Tests that map_current_cx correctly accesses the current context.
672+
673+ #[ test]
674+ fn test_map_current_cx ( ) {
675+ let mut stack = ContextStack :: default ( ) ;
676+ let test_value = ValueA ( 42 ) ;
677+ stack. current_cx = Context :: new ( ) . with_value ( test_value) ;
678+
679+ let result = stack. map_current_cx ( |cx| {
680+ assert_eq ! ( cx. get:: <ValueA >( ) , Some ( & ValueA ( 42 ) ) ) ;
681+ true
682+ } ) ;
683+ assert ! ( result) ;
684+ }
685+
686+ /// Tests popping contexts in non-sequential order.
687+
688+ #[ test]
689+ fn test_pop_id_out_of_order ( ) {
690+ let mut stack = ContextStack :: default ( ) ;
691+
692+ // Push three contexts
693+ let cx1 = Context :: new ( ) . with_value ( ValueA ( 1 ) ) ;
694+ let cx2 = Context :: new ( ) . with_value ( ValueA ( 2 ) ) ;
695+ let cx3 = Context :: new ( ) . with_value ( ValueA ( 3 ) ) ;
696+
697+ let id1 = stack. push ( cx1) ;
698+ let id2 = stack. push ( cx2) ;
699+ let id3 = stack. push ( cx3) ;
700+
701+ // Pop middle context first - should not affect current context
702+ stack. pop_id ( id2) ;
703+ assert_eq ! ( stack. current_cx. get:: <ValueA >( ) , Some ( & ValueA ( 3 ) ) ) ;
704+ assert_eq ! ( stack. stack. len( ) , 3 ) ; // Length unchanged for middle pops
705+
706+ // Pop last context - should restore previous valid context
707+ stack. pop_id ( id3) ;
708+ assert_eq ! ( stack. current_cx. get:: <ValueA >( ) , Some ( & ValueA ( 1 ) ) ) ;
709+ assert_eq ! ( stack. stack. len( ) , 1 ) ;
710+
711+ // Pop first context - should restore to empty state
712+ stack. pop_id ( id1) ;
713+ assert_eq ! ( stack. current_cx. get:: <ValueA >( ) , None ) ;
714+ assert_eq ! ( stack. stack. len( ) , 0 ) ;
715+ }
716+
717+ /// Tests edge cases in context stack operations. IRL these should log
718+ /// warnings, and definitely not panic.
662719 #[ test]
663- fn context_stack_pop_id ( ) {
664- // This is to get full line coverage of the `pop_id` function.
665- // In real life the `Drop`` implementation of `ContextGuard` ensures that
666- // the ids are valid and inside the bounds.
720+ fn test_pop_id_edge_cases ( ) {
667721 let mut stack = ContextStack :: default ( ) ;
722+
723+ // Test popping BASE_POS - should be no-op
668724 stack. pop_id ( ContextStack :: BASE_POS ) ;
725+ assert_eq ! ( stack. stack. len( ) , 0 ) ;
726+
727+ // Test popping MAX_POS - should be no-op
669728 stack. pop_id ( ContextStack :: MAX_POS ) ;
670- stack. pop_id ( 4711 ) ;
729+ assert_eq ! ( stack. stack. len( ) , 0 ) ;
730+
731+ // Test popping invalid position - should be no-op
732+ stack. pop_id ( 1000 ) ;
733+ assert_eq ! ( stack. stack. len( ) , 0 ) ;
734+
735+ // Test popping from empty stack - should be safe
736+ stack. pop_id ( 1 ) ;
737+ assert_eq ! ( stack. stack. len( ) , 0 ) ;
738+ }
739+
740+ /// Tests stack behavior when reaching maximum capacity.
741+ /// Once we push beyond this point, we should end up with a context
742+ /// that points _somewhere_, but mutating it should not affect the current
743+ /// active context.
744+ #[ test]
745+ fn test_push_overflow ( ) {
746+ let mut stack = ContextStack :: default ( ) ;
747+ let max_pos = ContextStack :: MAX_POS as usize ;
748+
749+ // Fill stack up to max position
750+ for i in 0 ..max_pos {
751+ let cx = Context :: new ( ) . with_value ( ValueA ( i as u64 ) ) ;
752+ let id = stack. push ( cx) ;
753+ assert_eq ! ( id, ( i + 1 ) as u16 ) ;
754+ }
755+
756+ // Try to push beyond capacity
757+ let cx = Context :: new ( ) . with_value ( ValueA ( max_pos as u64 ) ) ;
758+ let id = stack. push ( cx) ;
759+ assert_eq ! ( id, ContextStack :: MAX_POS ) ;
760+
761+ // Verify current context remains unchanged after overflow
762+ assert_eq ! (
763+ stack. current_cx. get:: <ValueA >( ) ,
764+ Some ( & ValueA ( ( max_pos - 2 ) as u64 ) )
765+ ) ;
671766 }
767+
672768}
0 commit comments