# Exercise:
Given this calls:
```ruby
Taskman.queue(2.5) { print 'world!' }
Taskman.queue(1.0) { print 'hello ' }
```
When we do this one:
```ruby
Taskman.work
```
You get the output:
`hello world`
class Taskman
class << self
def queue(delay, &block)
store << [delay, block]
end
def work(thread_provider: Thread)
workers = []
while (item = store.shift) do
delay,task = item
workers << thread_provider.new do
sleep delay
task.call
end
end
workers.each(&:join)
end
private
def store
@queue ||= []
end
end
end
if $PROGRAM_NAME == __FILE__
Taskman.queue(2.5) { print 'world!' }
Taskman.queue(1.0) { print 'hello ' }
Taskman.work # => hello world
end
require "minitest/autorun"
require "minitest/pride"
require_relative "taskman"
class TaskmanTest < Minitest::Spec
subject { Taskman }
describe ".queue" do
it "stores a job" do
job = -> { true }
list = subject.queue(0, &job)
value(list[0][0]).must_equal(0)
value(list[0][1]).must_be_instance_of(Proc)
end
end
describe ".work" do
it "creates a thread" do
class ThreadMock
@instances = []
class << self
attr_accessor :instances
end
def initialize
self.class.instances << self
end
attr_accessor :called_join # accessible for test
def join
@called_join = true # I was called!
end
end
subject.queue(1) { true }
subject.work(thread_provider: ThreadMock)
value(ThreadMock.instances.first.called_join).must_equal(true)
end
# This version suffers race conditions
# it "creates a thread" do
# job = -> { true }
# subject.queue(1, &job)
# thread_mock = Minitest::Mock.new
# r = Object.new
# def r.join;end
# thread_mock.expect(:new, r)
# subject.work(thread_provider: thread_mock)
# thread_mock.verify
# end
it "does the work" do
executed = false
job = -> { executed = true }
subject.queue(0, &job)
subject.work
value(executed).must_equal(true)
end
end
end