Skip to content

Commit

Permalink
Add Timecop#lens where time can go FASTER
Browse files Browse the repository at this point in the history
  • Loading branch information
David Holcomb & Ken Mayer committed Sep 19, 2012
1 parent 5ec0f05 commit 6942d0e
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 2 deletions.
16 changes: 14 additions & 2 deletions lib/timecop/time_stack_item.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ class TimeStackItem #:nodoc:

attr_reader :mock_type
def initialize(mock_type, *args)
raise "Unknown mock_type #{mock_type}" unless [:freeze, :travel].include?(mock_type)
raise "Unknown mock_type #{mock_type}" unless [:freeze, :travel, :lens].include?(mock_type)
@scaling_factor = args.shift if mock_type == :lens
@mock_type = mock_type
@time = parse_time(*args)
@time_was = Time.now_without_mock_time
@travel_offset = compute_travel_offset
@dst_adjustment = compute_dst_adjustment(@time)
end
Expand Down Expand Up @@ -44,14 +46,24 @@ def utc_offset
def travel_offset
@travel_offset
end

def scaling_factor
@scaling_factor
end

def time(time_klass=Time) #:nodoc:
if travel_offset.nil?
time_klass.at( @time.to_f )
else
elsif scaling_factor.nil?
time_klass.at( ( Time.now_without_mock_time + travel_offset ).to_f )
else
time_klass.at( scaled_time )
end
end

def scaled_time
(@time + (Time.now_without_mock_time - @time_was) * scaling_factor).to_f
end

def date(date_klass=Date)
date_klass.jd(time.__send__(:to_date).jd)
Expand Down
14 changes: 14 additions & 0 deletions lib/timecop/timecop.rb
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,20 @@ def travel(*args, &block)
block_given? ? val : nil
end

# Allows you to run a block of code and "lens" a time throughout the execution of that block.
# The first argument is a scaling factor, for example:
# Timecop.lens(2) do
# ... time will 'go' twice as fast here
# end
# See Timecop#freeze for exact usage of the other arguments
#
# Returns the value of the block or nil.
def lens(*args, &block)
val = instance().send(:travel, :lens, *args, &block)

block_given? ? val : nil
end

def baseline
instance().send(:baseline)
end
Expand Down
9 changes: 9 additions & 0 deletions test/time_stack_item_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,15 @@ def test_set_travel_offset_for_freeze
assert_equal nil, tsi.send(:travel_offset)
end

def test_set_scaling_factor_for_lens
t_now = Time.now
t = Time.local(2009, 10, 1, 0, 0, 30)
expected_offset = t - t_now
tsi = Timecop::TimeStackItem.new(:lens, 4, t)
assert_times_effectively_equal expected_offset, tsi.send(:travel_offset), 1, "Offset not calculated correctly"
assert_equal tsi.send(:scaling_factor), 4, "Scaling factor not set"
end

def test_parse_string_date_with_active_support
date = '2012-01-02'
Time.expects(:parse).with(date).returns(Time.local(2012, 01, 02))
Expand Down
10 changes: 10 additions & 0 deletions test/timecop_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,16 @@ def test_mocked_date_time_now_is_local
end
end

def test_lensing_keeps_time_moving_at_an_accelerated_rate
t = Time.local(2008, 10, 10, 10, 10, 10)
Timecop.lens(4, t) do
start = Time.now
assert_times_effectively_equal start, t, 1, "Looks like we failed to actually travel time"
sleep(0.25)
assert_times_effectively_equal Time.at((start + 4*0.25).to_f), Time.now, 0.25, "Looks like time is not moving at 4x"
end
end

def test_freeze_with_utc_time
each_timezone do
t = Time.utc(2008, 10, 10, 10, 10, 10)
Expand Down

0 comments on commit 6942d0e

Please sign in to comment.