From d0d93c92f2c693ce7debf7cf1a08cd713b51c71d Mon Sep 17 00:00:00 2001 From: Herwin Date: Sun, 1 Oct 2023 16:37:04 +0200 Subject: [PATCH] Tests for Fiber scheduler for Kernel.sleep The test includes a very primitive Fiber scheduler. This one will probably be extended in future tests. --- test/natalie/fiber/scheduler_sleep_test.rb | 48 ++++++++++++++++++++++ test/natalie/fiber/shared/scheduler.rb | 32 +++++++++++++++ 2 files changed, 80 insertions(+) create mode 100755 test/natalie/fiber/scheduler_sleep_test.rb create mode 100644 test/natalie/fiber/shared/scheduler.rb diff --git a/test/natalie/fiber/scheduler_sleep_test.rb b/test/natalie/fiber/scheduler_sleep_test.rb new file mode 100755 index 0000000000..ca5349318d --- /dev/null +++ b/test/natalie/fiber/scheduler_sleep_test.rb @@ -0,0 +1,48 @@ +require_relative '../../spec_helper' +require_relative 'shared/scheduler' + +describe 'Fiber.scheduler with Kernel.sleep' do + it 'Can interleave fibers with Kernel.sleep' do + scheduler = Scheduler.new + Fiber.set_scheduler(scheduler) + events = [] + + sleeper = Fiber.new do + events << 'Going to sleep' + sleep(0.01) + events << 'Woken up' + end + + barista = Fiber.new do + events << 'Coffee' + end + + sleeper.resume + barista.resume + + scheduler.close + + events.should == ['Going to sleep', 'Coffee', 'Woken up'] + end + + it 'Does not interleave fibers without scheduler' do + Fiber.set_scheduler(nil) + events = [] + + sleeper = Fiber.new do + events << 'Going to sleep' + sleep(0.01) + events << 'Woken up' + end + + barista = Fiber.new do + events << 'Coffee' + end + + sleeper.resume + barista.resume + + events.should == ['Going to sleep', 'Woken up', 'Coffee'] + end +end + diff --git a/test/natalie/fiber/shared/scheduler.rb b/test/natalie/fiber/shared/scheduler.rb new file mode 100644 index 0000000000..a8bc6e6688 --- /dev/null +++ b/test/natalie/fiber/shared/scheduler.rb @@ -0,0 +1,32 @@ +class Scheduler + def initialize + @waiting = {} + end + + def run + until @waiting.empty? + fiber, = @waiting.find { |fiber, timeout| fiber.alive? && timeout <= current_time } + next if fiber.nil? + + @waiting.delete(fiber) + fiber.resume + end + end + + def close + run + end + + def kernel_sleep(duration) + @waiting[Fiber.current] = current_time + duration + Fiber.yield + end + + def current_time + Process.clock_gettime(Process::CLOCK_MONOTONIC) + end + + def io_wait(io, events, duration) end + def block(blocker, timeout = nil) end + def unblock(blocker, fiber) end +end