Skip to content

Commit

Permalink
Merge pull request #12 from treasure-data/add-specs
Browse files Browse the repository at this point in the history
Add specs
  • Loading branch information
nurse committed Dec 3, 2015
2 parents 3ba6a01 + f7832c9 commit b4e2657
Show file tree
Hide file tree
Showing 18 changed files with 1,112 additions and 161 deletions.
2 changes: 1 addition & 1 deletion lib/perfectsched/application/decider.rb
Expand Up @@ -40,7 +40,7 @@ def decide!(type, opts={})
begin
m = method(type)
rescue NameError
raise UndefinedDecisionError, "Undefined decision #{type} options=#{opt.inspect}"
raise UndefinedDecisionError, "Undefined decision #{type} options=#{opts.inspect}"
end
m.call(opts)
end
Expand Down
9 changes: 5 additions & 4 deletions lib/perfectsched/backend/rdb_compat.rb
Expand Up @@ -20,6 +20,7 @@ module PerfectSched
module Backend
class RDBCompatBackend
include BackendHelper
MAX_RETRY = 10

class Token < Struct.new(:row_id, :scheduled_time, :cron, :delay, :timezone)
end
Expand Down Expand Up @@ -76,13 +77,13 @@ def initialize(client, config)
def init_database(options)
sql = %[
CREATE TABLE IF NOT EXISTS `#{@table}` (
id VARCHAR(256) NOT NULL,
id VARCHAR(255) NOT NULL,
timeout INT NOT NULL,
next_time INT NOT NULL,
cron VARCHAR(128) NOT NULL,
delay INT NOT NULL,
data BLOB NOT NULL,
timezone VARCHAR(256) NULL,
data LONGBLOB NOT NULL,
timezone VARCHAR(255) NULL,
PRIMARY KEY (id)
);]
connect {
Expand All @@ -97,7 +98,7 @@ def get_schedule_metadata(key, options={})
raise NotFoundError, "schedule key=#{key} does not exist"
end
attributes = create_attributes(row)
return ScheduleMetadata.new(@client, key, attributes)
return ScheduleWithMetadata.new(@client, key, attributes)
}
end

Expand Down
20 changes: 0 additions & 20 deletions lib/perfectsched/schedule_metadata.rb
Expand Up @@ -57,24 +57,4 @@ def message
@attributes[:message]
end
end

class ScheduleMetadata
include Model

def initialize(client, key, attributes)
super(client)
@key = key
end

def schedule
Schedule.new(@client, @key)
end

def inspect
"#<#{self.class} @key=#{@key.inspect} @attributes=#{@attributes.inspect}>"
end

include ScheduleMetadataAccessors
end

end
5 changes: 1 addition & 4 deletions lib/perfectsched/worker.rb
Expand Up @@ -88,10 +88,7 @@ def replace(command=[$0]+ARGV)
begin
return if @replaced_pid
stop
@replaced_pid = Process.fork do
exec(*command)
exit!(127)
end
@replaced_pid = Process.spawn(*command)
rescue
@log.error "failed to replace: #{$!}"
$!.backtrace.each {|bt| @log.warn "\t#{bt}" }
Expand Down
3 changes: 2 additions & 1 deletion perfectsched.gemspec
Expand Up @@ -21,7 +21,8 @@ Gem::Specification.new do |gem|
gem.add_dependency "tzinfo", "~> 1.1"
gem.add_dependency "perfectqueue", "~> 0.8.41"
gem.add_development_dependency "rake", "~> 0.9.2"
gem.add_development_dependency "rspec", "~> 2.10.0"
gem.add_development_dependency "rspec", "~> 3.4.0"
gem.add_development_dependency "simplecov", "~> 0.10.0"
gem.add_development_dependency "sqlite3", "~> 1.3.3"
gem.add_development_dependency "mysql2", "~> 0.3.20"
end
81 changes: 81 additions & 0 deletions spec/application/base_spec.rb
@@ -0,0 +1,81 @@
require 'spec_helper'

describe PerfectSched::Application::Base do
describe '.decider=' do
it 'defines .decider which returns the decider' do
decider_klass = double('decider_klass')
klass = PerfectSched::Application::Base
allow(klass).to receive(:decider).and_call_original
allow(klass).to receive(:decider=).with(decider_klass).and_call_original
expect(klass.decider = decider_klass).to eq(decider_klass)
expect(klass.decider).to eq(decider_klass)
end
end

describe '.decider' do
it 'returns DefaultDecider' do
expect(PerfectSched::Application::Base.decider).to eq(PerfectSched::Application::DefaultDecider)
end
end

describe '#new' do
let (:task){ double('task') }
let (:base) { PerfectSched::Application::Base.new(task) }
it 'calls super and set decider'do
expect(base).to be_an_instance_of(PerfectSched::Application::Base)
expect(base.instance_variable_get(:@task)).to eq(task)
expect(base.instance_variable_get(:@decider)).to be_an_instance_of(Application::DefaultDecider)
end
end

describe '#run' do
let (:base) { PerfectSched::Application::Base.new(double('task')) }
it 'returns nil if before_perform returns false' do
allow(base).to receive(:before_perform).and_return(false)
expect(base.run).to be_nil
end
it 'returns nil' do
expect(base).to receive(:before_perform).exactly(:once).and_call_original
expect(base).to receive(:perform).exactly(:once).and_return(nil)
expect(base).to receive(:after_perform).exactly(:once).and_call_original
expect(base.run).to be_nil
end
it 'calls unexpected_error_raised on error' do
allow(base).to receive(:before_perform).exactly(:once).and_call_original
allow(base).to receive(:perform).exactly(:once) { raise }
allow(base).to receive(:decide!).with(:unexpected_error_raised, error: kind_of(Exception)).exactly(:once)
expect(base.run).to be_nil
end
end

describe '#before_perform' do
let (:base) { PerfectSched::Application::Base.new(double('task')) }
it 'returns true' do
expect(base.before_perform).to be true
end
end

describe '#after_perform' do
let (:base) { PerfectSched::Application::Base.new(double('task')) }
it 'returns nil' do
expect(base.after_perform).to be_nil
end
end

describe '#decide!' do
let (:base) do
decider = double('decider')
expect(decider).to receive(:decide!).with(:type, :option).exactly(:once)
decider_klass = double('decider_klass')
allow(decider_klass).to receive(:new).with(kind_of(PerfectSched::Application::Base)).and_return(decider)
klass = PerfectSched::Application::Base
allow(klass).to receive(:decider).and_call_original
allow(klass).to receive(:decider=).with(decider_klass).and_call_original
klass.decider = decider_klass
klass.new(double('task'))
end
it 'calls decider.decide' do
expect(base.decide!(:type, :option)).to be_nil
end
end
end
54 changes: 54 additions & 0 deletions spec/application/decider_spec.rb
@@ -0,0 +1,54 @@
require 'spec_helper'

describe PerfectSched::Application::UndefinedDecisionError do
it { is_expected.to be_an_instance_of(PerfectSched::Application::UndefinedDecisionError) }
it { is_expected.to be_a(Exception) }
end

describe PerfectSched::Application::Decider do
let (:task){ double('task') }
let (:schedules){ double('schedules') }
let (:base){ double('base', schedules: schedules, task: task) }
let (:decider) { PerfectSched::Application::Decider.new(base) }
describe '#new' do
it 'returns a decider' do
expect(decider).to be_an_instance_of(PerfectSched::Application::Decider)
expect(decider.instance_variable_get(:@base)).to eq(base)
end
end

describe '#schedules' do
it 'returns @base.schedules' do
expect(decider.schedules).to eq(schedules)
end
end

describe '#task' do
let (:decider) do
base = double('base')
allow(base).to receive(:task).exactly(:once).and_return(task)
PerfectSched::Application::Decider.new(base)
end
it 'calls @base.task' do
expect(decider.task).to eq(task)
end
end

describe '#decide!' do
it 'calls the specified method' do
opts = double('opts')
ret = double('ret')
allow(decider).to receive(:foo).exactly(:once).with(opts).and_return(ret)
expect(decider.decide!(:foo, opts)).to eq(ret)
end
it 'raises UndefinedDecisionError on unknown method' do
expect{ decider.decide!(:foo, double) }.to raise_error(PerfectSched::Application::UndefinedDecisionError)
end
end
end

describe PerfectSched::Application::DefaultDecider do
subject { PerfectSched::Application::DefaultDecider.new(nil) }
it { is_expected.to be_a(PerfectSched::Application::Decider) }
it { is_expected.to be_an_instance_of(PerfectSched::Application::DefaultDecider) }
end
122 changes: 122 additions & 0 deletions spec/client_spec.rb
@@ -0,0 +1,122 @@
require 'spec_helper'

describe Client do
let (:config){ {} }
let (:client){ Client.new(config) }
let (:ret){ double('ret') }
let (:backend){ double('backend') }
let (:options){ double('options') }
let (:task_token){ double('task_token') }
let (:key){ double('key') }
before do
allow(Backend).to receive(:new_backend) \
.with(kind_of(Client), config).and_return(backend)
end
describe '.new' do
subject { client }
it {
is_expected.to be_an_instance_of(Client) }
end
describe '#backend' do
subject { client.backend }
it { is_expected.to eq backend }
end
describe '#config' do
subject { client.config }
it { is_expected.to eq config }
end
describe '#init_database' do
subject { client.init_database(options) }
before { expect(backend).to receive(:init_database).with(options).and_return(ret) }
it { is_expected.to eq ret }
end
describe '#get_schedule_metadata' do
subject { client.get_schedule_metadata(key, options) }
before { expect(backend).to receive(:get_schedule_metadata).with(key, options).and_return(ret) }
it { is_expected.to eq ret }
end
describe '#delete' do
subject { client.delete(key, options) }
before { expect(backend).to receive(:delete).with(key, options).and_return(ret) }
it { is_expected.to eq ret }
end
describe '#modify' do
subject { client.modify(key, options) }
before { expect(backend).to receive(:modify).with(key, options).and_return(ret) }
it { is_expected.to eq ret }
end
describe '#list' do
let (:pr){ proc{} }
subject { client.list(key, &pr) }
before { expect(backend).to receive(:list).with(key){|*_, &b| expect(b).to eq pr; ret} }
it { is_expected.to eq ret }
end
describe '#acquire' do
let (:alive_time){ double('alive_time') }
let (:max_acquire){ double('max_acquire') }
subject { client.acquire(options) }
before { expect(backend).to receive(:acquire).with(alive_time, max_acquire, options).and_return(ret) }
context 'options are given' do
let (:options){ {alive_time: alive_time, max_acquire: max_acquire} }
it { is_expected.to eq ret }
end
context 'alive_time options is not given' do
let (:max_acquire){ 1 }
let (:options){ {} }
let (:config){ {alive_time: alive_time} }
it { is_expected.to eq ret }
end
end
describe '#release' do
let (:alive_time){ double('alive_time') }
subject { client.release(task_token, options) }
before { expect(backend).to receive(:release).with(task_token, alive_time, options).and_return(ret) }
context 'alive_time options is given' do
let (:options){ {alive_time: alive_time} }
it { is_expected.to eq ret }
end
context 'alive_time options is not given' do
let (:options){ {} }
let (:config){ {alive_time: alive_time} }
it { is_expected.to eq ret }
end
end
describe '#heartbeat' do
let (:alive_time){ double('alive_time') }
subject { client.heartbeat(task_token, options) }
before { expect(backend).to receive(:heartbeat).with(task_token, alive_time, options).and_return(ret) }
context 'alive_time options is given' do
let (:options){ {alive_time: alive_time} }
it { is_expected.to eq ret }
end
context 'alive_time options is not given' do
let (:options){ {} }
let (:config){ {alive_time: alive_time} }
it { is_expected.to eq ret }
end
end
describe '#retry' do
let (:retry_wait){ double('retry_wait') }
subject { client.retry(task_token, options) }
before { expect(backend).to receive(:heartbeat).with(task_token, retry_wait, options).and_return(ret) }
context 'retry_wait options is given' do
let (:options){ {retry_wait: retry_wait} }
it { is_expected.to eq ret }
end
context 'retry_wait options is not given' do
let (:options){ {} }
let (:config){ {retry_wait: retry_wait} }
it { is_expected.to eq ret }
end
end
describe '#finish' do
subject { client.finish(task_token, options) }
before { expect(backend).to receive(:finish).with(task_token, options).and_return(ret) }
it { is_expected.to eq ret }
end
describe '#close' do
subject { client.close }
before { expect(backend).to receive(:close).with(no_args).and_return(ret) }
it { is_expected.to eq ret }
end
end

0 comments on commit b4e2657

Please sign in to comment.