From 6fa5e2e264656a8e371c6aa532d852a82ddec92b Mon Sep 17 00:00:00 2001 From: Colin Kelley Date: Wed, 13 Jan 2021 16:13:37 -0800 Subject: [PATCH] add tests for waiting max of 5 seconds for startup --- lib/listen/error.rb | 7 +++++++ lib/listen/event/loop.rb | 4 +++- spec/lib/listen/event/loop_spec.rb | 28 +++++++++++++++++++++------- 3 files changed, 31 insertions(+), 8 deletions(-) create mode 100644 lib/listen/error.rb diff --git a/lib/listen/error.rb b/lib/listen/error.rb new file mode 100644 index 00000000..c4b7d1ee --- /dev/null +++ b/lib/listen/error.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +module Listen + class Error < RuntimeError + class NotStarted < Error; end + end +end diff --git a/lib/listen/event/loop.rb b/lib/listen/event/loop.rb index 9b6e2ebf..3a5e74f4 100644 --- a/lib/listen/event/loop.rb +++ b/lib/listen/event/loop.rb @@ -5,6 +5,7 @@ require 'timeout' require 'listen/event/processor' require 'listen/thread' +require 'listen/error' module Listen module Event @@ -12,7 +13,7 @@ class Loop include Listen::FSM class Error < RuntimeError - class NotStarted < Error; end + NotStarted = ::Listen::Error::NotStarted # for backward compatibility end start_state :pre_start @@ -40,6 +41,7 @@ def started? MAX_STARTUP_SECONDS = 5.0 + # @raises Error::NotStarted if background thread hasn't started in MAX_STARTUP_SECONDS def start # TODO: use a Fiber instead? return unless state == :pre_start diff --git a/spec/lib/listen/event/loop_spec.rb b/spec/lib/listen/event/loop_spec.rb index 749d4351..1d2aed7a 100644 --- a/spec/lib/listen/event/loop_spec.rb +++ b/spec/lib/listen/event/loop_spec.rb @@ -45,26 +45,40 @@ end describe '#start' do - before do + it 'is started' do + expect(processor).to receive(:loop_for).with(1.234) expect(Thread).to receive(:new) do |&block| block.call thread end - - expect(processor).to receive(:loop_for).with(1.234) - subject.start - end - - it 'is started' do expect(subject).to be_started end context 'when start is called again' do it 'returns silently' do + expect(processor).to receive(:loop_for).with(1.234) + expect(Thread).to receive(:new) do |&block| + block.call + thread + end + subject.start expect { subject.start }.to_not raise_exception end end + + context 'when state change to :started takes longer than 5 seconds' do + before do + expect(Thread).to receive(:new) { thread } + expect_any_instance_of(::ConditionVariable).to receive(:wait) { } # return immediately + end + + it 'raises Error::NotStarted' do + expect do + subject.start + end.to raise_exception(::Listen::Error::NotStarted, "thread didn't start in 5.0 seconds (in state: :starting)") + end + end end context 'when set up / started' do