Created
January 12, 2010 13:53
-
-
Save floehopper/275214 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Yajl | |
class HttpStream | |
class HttpError < StandardError; end | |
def self.get; end | |
end | |
end | |
class Sleeper | |
def sleep(delay) | |
sleep(delay) | |
end | |
end | |
class HttpErrorStrategy | |
def initialize(sleeper = Sleeper.new) | |
@sleeper = sleeper | |
@http_error_delay = 10 | |
end | |
def retry? | |
if @http_error_delay < 240 | |
@http_error_delay *= 2 | |
@sleeper.sleep(@http_error_delay) | |
return true | |
else | |
return false | |
end | |
end | |
end | |
require 'test/unit' | |
require 'mocha' | |
class HttpErrorStrategyTest < Test::Unit::TestCase | |
def setup | |
@sleeper = mock('sleeper') | |
@strategy = HttpErrorStrategy.new(@sleeper) | |
end | |
def test_should_retry_with_exponentially_increasing_delays | |
exponential = sequence('exponential') | |
@sleeper.expects(:sleep).with(20).in_sequence(exponential) | |
@sleeper.expects(:sleep).with(40).in_sequence(exponential) | |
@sleeper.expects(:sleep).with(80).in_sequence(exponential) | |
@sleeper.expects(:sleep).with(160).in_sequence(exponential) | |
@sleeper.expects(:sleep).with(320).in_sequence(exponential) | |
5.times { assert @strategy.retry? } | |
end | |
def test_should_stop_retrying_after_maximum_delay_is_reached | |
@sleeper.expects(:sleep).times(5) | |
5.times { @strategy.retry? } | |
assert !@strategy.retry? | |
end | |
end | |
class IOErrorStrategy | |
def initialize(sleeper = Sleeper.new) | |
@sleeper = sleeper | |
@io_error_delay = 0 | |
end | |
def retry? | |
if @io_error_delay < 16 | |
@io_error_delay += 0.25 | |
@sleeper.sleep(@io_error_delay) | |
return true | |
else | |
return false | |
end | |
end | |
end | |
class IOErrorStrategyTest < Test::Unit::TestCase | |
def setup | |
@sleeper = mock('sleeper') | |
@strategy = IOErrorStrategy.new(@sleeper) | |
end | |
def test_should_retry_with_linearly_increasing_delays | |
linear = sequence('linear') | |
@sleeper.expects(:sleep).with(0.25).in_sequence(linear) | |
@sleeper.expects(:sleep).with(0.50).in_sequence(linear) | |
@sleeper.expects(:sleep).with(0.75).in_sequence(linear) | |
@sleeper.expects(:sleep).with(1.00).in_sequence(linear) | |
4.times { assert @strategy.retry? } | |
end | |
def test_should_stop_retrying_after_maximum_delay_is_reached | |
@sleeper.expects(:sleep).times(64) | |
65.times { @strategy.retry? } | |
assert !@strategy.retry? | |
end | |
end | |
class Statuses | |
def initialize(http_error_strategy = HttpErrorStrategy.new, io_error_strategy = IOErrorStrategy.new) | |
@http_error_strategy = http_error_strategy | |
@io_error_strategy = io_error_strategy | |
end | |
def get | |
begin | |
Yajl::HttpStream.get | |
rescue Yajl::HttpStream::HttpError => e | |
if @http_error_strategy.retry? | |
retry | |
else | |
raise e | |
end | |
rescue IOError => e | |
if @io_error_strategy.retry? | |
retry | |
else | |
raise e | |
end | |
end | |
end | |
end | |
class StatusesTest < Test::Unit::TestCase | |
def setup | |
@http_error_strategy = mock('http_error_strategy') | |
@io_error_strategy = mock('io_error_strategy') | |
@statuses = Statuses.new(@http_error_strategy, @io_error_strategy) | |
end | |
def test_handles_http_error_and_retries | |
exception = Yajl::HttpStream::HttpError.new | |
Yajl::HttpStream.stubs(:get).raises(exception).then.returns('json') | |
@http_error_strategy.stubs(:retry?).returns(true) | |
assert_equal 'json', @statuses.get | |
end | |
def test_handles_http_error_and_raises | |
exception = Yajl::HttpStream::HttpError.new | |
Yajl::HttpStream.stubs(:get).raises(exception).then.returns('json') | |
@http_error_strategy.stubs(:retry?).returns(false) | |
assert_raises(Yajl::HttpStream::HttpError) { @statuses.get } | |
end | |
def test_handles_io_error_and_retries | |
exception = IOError.new | |
Yajl::HttpStream.stubs(:get).raises(exception).then.returns('json') | |
@io_error_strategy.expects(:retry?).returns(true) | |
assert_equal 'json', @statuses.get | |
end | |
def test_handles_io_error_and_raises | |
exception = IOError.new | |
Yajl::HttpStream.stubs(:get).raises(exception) | |
@io_error_strategy.expects(:retry?).returns(false).then.returns('json') | |
assert_raises(IOError) { @statuses.get } | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment