@@ -459,4 +459,77 @@ def test_timeout_in_trap_handler
459459 trap ( signal , original_handler )
460460 end
461461 end
462+
463+ if Fiber . respond_to? ( :current_scheduler )
464+ # Stubs Fiber.current_scheduler for the duration of the block, then restores it.
465+ def with_mock_scheduler ( mock )
466+ original = Fiber . method ( :current_scheduler )
467+ Fiber . define_singleton_method ( :current_scheduler ) { mock }
468+ begin
469+ yield
470+ ensure
471+ Fiber . define_singleton_method ( :current_scheduler , original )
472+ end
473+ end
474+
475+ def test_fiber_scheduler_delegates_to_timeout_after
476+ received = nil
477+ mock = Object . new
478+ mock . define_singleton_method ( :timeout_after ) do |sec , exc , msg , &blk |
479+ received = [ sec , exc , msg ]
480+ blk . call ( sec )
481+ end
482+
483+ with_mock_scheduler ( mock ) do
484+ assert_equal :ok , Timeout . timeout ( 5 ) { :ok }
485+ end
486+
487+ assert_equal 5 , received [ 0 ]
488+ assert_instance_of Timeout ::ExitException , received [ 1 ] , "scheduler should receive an ExitException instance when no klass given"
489+ assert_equal "execution expired" , received [ 2 ]
490+ end
491+
492+ def test_fiber_scheduler_delegates_to_timeout_after_with_custom_exception
493+ custom_error = Class . new ( StandardError )
494+ received = nil
495+ mock = Object . new
496+ mock . define_singleton_method ( :timeout_after ) do |sec , exc , msg , &blk |
497+ received = [ sec , exc , msg ]
498+ blk . call ( sec )
499+ end
500+
501+ with_mock_scheduler ( mock ) do
502+ assert_equal :ok , Timeout . timeout ( 5 , custom_error , "custom message" ) { :ok }
503+ end
504+
505+ assert_equal [ 5 , custom_error , "custom message" ] , received
506+ end
507+
508+ def test_fiber_scheduler_timeout_raises_timeout_error
509+ mock = Object . new
510+ mock . define_singleton_method ( :timeout_after ) do |sec , exc , msg , &blk |
511+ raise exc # simulate timeout firing
512+ end
513+
514+ with_mock_scheduler ( mock ) do
515+ assert_raise ( Timeout ::Error ) do
516+ Timeout . timeout ( 5 ) { :should_not_reach }
517+ end
518+ end
519+ end
520+
521+ def test_fiber_scheduler_timeout_raises_custom_error
522+ custom_error = Class . new ( StandardError )
523+ mock = Object . new
524+ mock . define_singleton_method ( :timeout_after ) do |sec , exc , msg , &blk |
525+ raise exc , msg
526+ end
527+
528+ with_mock_scheduler ( mock ) do
529+ assert_raise_with_message ( custom_error , "custom message" ) do
530+ Timeout . timeout ( 5 , custom_error , "custom message" ) { :should_not_reach }
531+ end
532+ end
533+ end
534+ end
462535end
0 commit comments