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