require 'rspec_syntax' require Pathname(__dir__) + '../lib/wyrm/hole.rb' describe Wyrm::Hole::Mouth do if RUBY_VERSION == '2.1.0' it 'Queue broken on 2.1.0' else describe '#flush' do it 'calls poison_queue' do subject.should_receive(:poison_queue) subject.flush end it 'sets flag' do subject.instance_variable_get('@flushed').should_not == true subject.flush subject.instance_variable_get('@flushed').should == true end describe 'queue empty with waiters' do THREADS = rand(1..7) def waiters @waiters ||= THREADS.times.map do Thread.new do values = [] begin until subject.eof? values << subject.deq sleep( rand * 0.05 ) end [:eoffed, values] rescue StopIteration [:poisoned, values] end end end end it 'poisons queue' do waiters # wait for thread setup to finish sleep 0.1 subject.flush thread_values = waiters.map {|waiter| waiter.join(4).andand.value } thread_values.map(&:first).should == THREADS.times.map{:poisoned} end it 'eof queue' do 50.times{subject.enq 'hello'} waiters subject.flush thread_values = waiters.map {|waiter| waiter.join(4).andand.value } thread_values.map(&:first).should == THREADS.times.map{:eoffed} end end end describe '#eof?' do describe 'flushed' do before :each do subject.flush end it 'true when queue empty' do subject.queue.should be_empty subject.should be_eof end it 'false when queue empty' do subject.enq( :arg ) subject.should_not be_eof end end describe 'not flushed' do it 'false when queue empty' do subject.queue.should be_empty subject.should_not be_eof end it 'false when queue has items' do rand(25).times{ subject.enq( :arg ) } subject.should_not be_eof end end end describe '#reset' do it 'resets flushed' do subject.instance_variable_set '@flushed', true subject.reset subject.instance_variable_get('@flushed').should == false end it 'clears queue' do rand(1..10).times{subject.enq :some_value} subject.queue.should_not be_empty subject.reset subject.queue.should be_empty end end describe '#deq' do it 'gets value' do subject.enq :montagne subject.deq.should == :montagne end it 'blocks for no values' do subject.queue.should be_empty th = Thread.new{subject.deq} sleep 0.05 th.status.should == 'sleep' th.kill sleep 0.05 th.status.should == false end it 'raise StopIteration on poison' do subject.queue.should be_empty waiter = Thread.new { subject.deq } sleep(0.01) while subject.queue.num_waiting != 1 subject.poison_queue # this is so cool. Thread#value will re-raise the exception it caught ->{waiter.value}.should raise_error(StopIteration) # queue should be empty now subject.queue.should be_empty end it 're-queues poison' do subject.queue << :poison subject.should_receive(:poison_queue) ->{subject.deq}.should raise_error(StopIteration) end end describe '#poison_queue' do it 'poisons when queue empty with waiters' do subject.queue.should be_empty # there has to be a thread waiting for the poison to be added waiter = Thread.new { subject.queue.deq } sleep(0.01) while subject.queue.num_waiting != 1 subject.poison_queue waiter.value.should == :poison # queue should be empty now subject.queue.should be_empty end it 'no poison when queue empty' do subject.queue.should be_empty subject.poison_queue subject.queue.should be_empty end it 'no poison for no waiters' do subject.queue << :hello subject.queue << :there subject.poison_queue subject.queue.size.should == 2 end end describe '#logger' do # this is here because the 2.1.0 without SizeQueue branch # has a logger which nothing else uses it 'works' do Wyrm::Hole::Mouth::RUBY_VERSION = '2.1.0' ->{subject.queue}.should raise_error(/broken in 2.1.0/) Wyrm::Hole::Mouth.send :remove_const, :RUBY_VERSION end end end #unless RUBY_VERSION == '2.1.0' end