diff --git a/lib/timecop/time_extensions.rb b/lib/timecop/time_extensions.rb index 0de35ca..04632c8 100644 --- a/lib/timecop/time_extensions.rb +++ b/lib/timecop/time_extensions.rb @@ -168,58 +168,56 @@ def mocked_time_stack_item end end -if RUBY_VERSION >= '2.1.0' - module Process #:nodoc: - class << self - alias_method :clock_gettime_without_mock, :clock_gettime - - def clock_gettime_mock_time(clock_id, unit = :float_second) - mock_time = case clock_id - when Process::CLOCK_MONOTONIC - mock_time_monotonic - when Process::CLOCK_REALTIME - mock_time_realtime - end - - return clock_gettime_without_mock(clock_id, unit) unless Timecop.mock_process_clock? && mock_time - - divisor = case unit - when :float_second - 1_000_000_000.0 - when :second - 1_000_000_000 - when :float_millisecond - 1_000_000.0 - when :millisecond - 1_000_000 - when :float_microsecond - 1000.0 - when :microsecond - 1000 - when :nanosecond - 1 +module Process #:nodoc: + class << self + alias_method :clock_gettime_without_mock, :clock_gettime + + def clock_gettime_mock_time(clock_id, unit = :float_second) + mock_time = case clock_id + when Process::CLOCK_MONOTONIC + mock_time_monotonic + when Process::CLOCK_REALTIME + mock_time_realtime end - (mock_time / divisor) - end + return clock_gettime_without_mock(clock_id, unit) unless Timecop.mock_process_clock? && mock_time + + divisor = case unit + when :float_second + 1_000_000_000.0 + when :second + 1_000_000_000 + when :float_millisecond + 1_000_000.0 + when :millisecond + 1_000_000 + when :float_microsecond + 1000.0 + when :microsecond + 1000 + when :nanosecond + 1 + end + + (mock_time / divisor) + end - alias_method :clock_gettime, :clock_gettime_mock_time + alias_method :clock_gettime, :clock_gettime_mock_time - private + private - def mock_time_monotonic - mocked_time_stack_item = Timecop.top_stack_item - mocked_time_stack_item.nil? ? nil : mocked_time_stack_item.monotonic - end + def mock_time_monotonic + mocked_time_stack_item = Timecop.top_stack_item + mocked_time_stack_item.nil? ? nil : mocked_time_stack_item.monotonic + end - def mock_time_realtime - mocked_time_stack_item = Timecop.top_stack_item + def mock_time_realtime + mocked_time_stack_item = Timecop.top_stack_item - return nil if mocked_time_stack_item.nil? + return nil if mocked_time_stack_item.nil? - t = mocked_time_stack_item.time - t.to_i * 1_000_000_000 + t.nsec - end + t = mocked_time_stack_item.time + t.to_i * 1_000_000_000 + t.nsec end end end diff --git a/lib/timecop/time_stack_item.rb b/lib/timecop/time_stack_item.rb index ef49150..6ddd65d 100644 --- a/lib/timecop/time_stack_item.rb +++ b/lib/timecop/time_stack_item.rb @@ -9,7 +9,7 @@ def initialize(mock_type, *args) @travel_offset = @scaling_factor = nil @scaling_factor = args.shift if mock_type == :scale @mock_type = mock_type - @monotonic = parse_monotonic_time(*args) if RUBY_VERSION >= '2.1.0' + @monotonic = parse_monotonic_time(*args) @time = parse_time(*args) @time_was = Time.now_without_mock_time @travel_offset = compute_travel_offset @@ -55,24 +55,22 @@ def scaling_factor @scaling_factor end - if RUBY_VERSION >= '2.1.0' - def monotonic - if travel_offset.nil? - @monotonic - elsif scaling_factor.nil? - current_monotonic + travel_offset * (10 ** 9) - else - (@monotonic + (current_monotonic - @monotonic) * scaling_factor).to_i - end + def monotonic + if travel_offset.nil? + @monotonic + elsif scaling_factor.nil? + current_monotonic + travel_offset * (10 ** 9) + else + (@monotonic + (current_monotonic - @monotonic) * scaling_factor).to_i end + end - def current_monotonic - Process.clock_gettime_without_mock(Process::CLOCK_MONOTONIC, :nanosecond) - end + def current_monotonic + Process.clock_gettime_without_mock(Process::CLOCK_MONOTONIC, :nanosecond) + end - def current_monotonic_with_mock - Process.clock_gettime_mock_time(Process::CLOCK_MONOTONIC, :nanosecond) - end + def current_monotonic_with_mock + Process.clock_gettime_mock_time(Process::CLOCK_MONOTONIC, :nanosecond) end def time(time_klass = Time) #:nodoc: diff --git a/test/timecop_with_process_clock_test.rb b/test/timecop_with_process_clock_test.rb index c131f5b..6e57fbf 100644 --- a/test/timecop_with_process_clock_test.rb +++ b/test/timecop_with_process_clock_test.rb @@ -13,169 +13,167 @@ def teardown Timecop.mock_process_clock = false end - if RUBY_VERSION >= '2.1.0' - def test_process_clock_mock_disabled - Timecop.mock_process_clock = false + def test_process_clock_mock_disabled + Timecop.mock_process_clock = false - Timecop.freeze do - refute_same(*consecutive_monotonic, "CLOCK_MONOTONIC is frozen") - end + Timecop.freeze do + refute_same(*consecutive_monotonic, "CLOCK_MONOTONIC is frozen") end + end - def test_process_clock_gettime_monotonic - Timecop.freeze do - assert_same(*consecutive_monotonic, "CLOCK_MONOTONIC is not frozen") - end + def test_process_clock_gettime_monotonic + Timecop.freeze do + assert_same(*consecutive_monotonic, "CLOCK_MONOTONIC is not frozen") + end - initial_time = monotonic - Timecop.freeze(-0.5) do - assert_operator(monotonic, :<, initial_time, "CLOCK_MONOTONIC is not traveling back in time") - end + initial_time = monotonic + Timecop.freeze(-0.5) do + assert_operator(monotonic, :<, initial_time, "CLOCK_MONOTONIC is not traveling back in time") end + end - def test_process_clock_gettime_monotonic_with_date_freeze - date = Date.new(2024, 6, 1) - monotonic1 = Timecop.freeze(date) { monotonic } - monotonic2 = Timecop.freeze(date) { monotonic } + def test_process_clock_gettime_monotonic_with_date_freeze + date = Date.new(2024, 6, 1) + monotonic1 = Timecop.freeze(date) { monotonic } + monotonic2 = Timecop.freeze(date) { monotonic } - refute_equal(monotonic1, monotonic2, "CLOCK_MONOTONIC is not expected to freeze deterministically with a date") - end + refute_equal(monotonic1, monotonic2, "CLOCK_MONOTONIC is not expected to freeze deterministically with a date") + end - def test_process_clock_gettime_realtime_with_date_freeze - date = Date.new(2024, 6, 1) - realtime_1 = Timecop.freeze(date) { realtime } - realtime_2 = Timecop.freeze(date) { realtime } + def test_process_clock_gettime_realtime_with_date_freeze + date = Date.new(2024, 6, 1) + realtime_1 = Timecop.freeze(date) { realtime } + realtime_2 = Timecop.freeze(date) { realtime } - assert_equal(realtime_1, realtime_2, "CLOCK_REALTIME is expected to support freezing with a date") - end + assert_equal(realtime_1, realtime_2, "CLOCK_REALTIME is expected to support freezing with a date") + end - def test_process_clock_gettime_units_integer - Timecop.freeze do - time_in_nanoseconds = Process.clock_gettime(Process::CLOCK_MONOTONIC, :nanosecond) - time_in_microseconds = Process.clock_gettime(Process::CLOCK_MONOTONIC, :microsecond) - time_in_milliseconds = Process.clock_gettime(Process::CLOCK_MONOTONIC, :millisecond) - time_in_seconds = Process.clock_gettime(Process::CLOCK_MONOTONIC, :second) + def test_process_clock_gettime_units_integer + Timecop.freeze do + time_in_nanoseconds = Process.clock_gettime(Process::CLOCK_MONOTONIC, :nanosecond) + time_in_microseconds = Process.clock_gettime(Process::CLOCK_MONOTONIC, :microsecond) + time_in_milliseconds = Process.clock_gettime(Process::CLOCK_MONOTONIC, :millisecond) + time_in_seconds = Process.clock_gettime(Process::CLOCK_MONOTONIC, :second) - assert_equal(time_in_microseconds, (time_in_nanoseconds / 10**3).to_i) - assert_equal(time_in_milliseconds, (time_in_nanoseconds / 10**6).to_i) - assert_equal(time_in_seconds, (time_in_nanoseconds / 10**9).to_i) - end + assert_equal(time_in_microseconds, (time_in_nanoseconds / 10**3).to_i) + assert_equal(time_in_milliseconds, (time_in_nanoseconds / 10**6).to_i) + assert_equal(time_in_seconds, (time_in_nanoseconds / 10**9).to_i) end + end - def test_process_clock_gettime_units_float - Timecop.freeze do - time_in_nanoseconds = Process.clock_gettime(Process::CLOCK_MONOTONIC, :nanosecond).to_f + def test_process_clock_gettime_units_float + Timecop.freeze do + time_in_nanoseconds = Process.clock_gettime(Process::CLOCK_MONOTONIC, :nanosecond).to_f - float_microseconds = Process.clock_gettime(Process::CLOCK_MONOTONIC, :float_microsecond) - float_milliseconds = Process.clock_gettime(Process::CLOCK_MONOTONIC, :float_millisecond) - float_seconds = Process.clock_gettime(Process::CLOCK_MONOTONIC, :float_second) + float_microseconds = Process.clock_gettime(Process::CLOCK_MONOTONIC, :float_microsecond) + float_milliseconds = Process.clock_gettime(Process::CLOCK_MONOTONIC, :float_millisecond) + float_seconds = Process.clock_gettime(Process::CLOCK_MONOTONIC, :float_second) - delta = 0.000001 - assert_in_delta(float_microseconds, time_in_nanoseconds / 10**3, delta) - assert_in_delta(float_milliseconds, time_in_nanoseconds / 10**6, delta) - assert_in_delta(float_seconds, time_in_nanoseconds / 10**9, delta) - end + delta = 0.000001 + assert_in_delta(float_microseconds, time_in_nanoseconds / 10**3, delta) + assert_in_delta(float_milliseconds, time_in_nanoseconds / 10**6, delta) + assert_in_delta(float_seconds, time_in_nanoseconds / 10**9, delta) end + end - def test_process_clock_gettime_monotonic_nested - Timecop.freeze do - parent = monotonic + def test_process_clock_gettime_monotonic_nested + Timecop.freeze do + parent = monotonic - sleep(TIME_EPSILON) + sleep(TIME_EPSILON) - delta = 0.5 - Timecop.freeze(delta) do - child = monotonic - assert_equal(child, parent + delta, "Nested freeze not working for monotonic time") - end + delta = 0.5 + Timecop.freeze(delta) do + child = monotonic + assert_equal(child, parent + delta, "Nested freeze not working for monotonic time") end end + end - def test_process_clock_gettime_monotonic_travel - initial_time = monotonic - Timecop.travel do - refute_same(*consecutive_monotonic, "CLOCK_MONOTONIC is frozen") - assert_operator(monotonic, :>, initial_time, "CLOCK_MONOTONIC is not moving forward") - end + def test_process_clock_gettime_monotonic_travel + initial_time = monotonic + Timecop.travel do + refute_same(*consecutive_monotonic, "CLOCK_MONOTONIC is frozen") + assert_operator(monotonic, :>, initial_time, "CLOCK_MONOTONIC is not moving forward") + end - Timecop.travel(-0.5) do - refute_same(*consecutive_monotonic, "CLOCK_MONOTONIC is frozen") - assert_operator(monotonic, :<, initial_time, "CLOCK_MONOTONIC is not traveling properly") - end + Timecop.travel(-0.5) do + refute_same(*consecutive_monotonic, "CLOCK_MONOTONIC is frozen") + assert_operator(monotonic, :<, initial_time, "CLOCK_MONOTONIC is not traveling properly") end + end - def test_process_clock_gettime_monotonic_scale - scale = 4 - sleep_length = 0.25 - Timecop.scale(scale) do - initial_time = monotonic - sleep(sleep_length) - expected_time = initial_time + (scale * sleep_length) - assert_times_effectively_equal expected_time, monotonic, 0.1, "CLOCK_MONOTONIC is not scaling" - end + def test_process_clock_gettime_monotonic_scale + scale = 4 + sleep_length = 0.25 + Timecop.scale(scale) do + initial_time = monotonic + sleep(sleep_length) + expected_time = initial_time + (scale * sleep_length) + assert_times_effectively_equal expected_time, monotonic, 0.1, "CLOCK_MONOTONIC is not scaling" end + end - def test_process_clock_gettime_realtime - Timecop.freeze do - assert_same(*consecutive_realtime, "CLOCK_REALTIME is not frozen") - end + def test_process_clock_gettime_realtime + Timecop.freeze do + assert_same(*consecutive_realtime, "CLOCK_REALTIME is not frozen") + end - initial_time = realtime - Timecop.freeze(-20) do - assert_operator(realtime, :<, initial_time, "CLOCK_REALTIME is not traveling back in time") - end + initial_time = realtime + Timecop.freeze(-20) do + assert_operator(realtime, :<, initial_time, "CLOCK_REALTIME is not traveling back in time") end + end - def test_process_clock_gettime_realtime_travel - initial_time = realtime - Timecop.travel do - refute_equal consecutive_realtime, "CLOCK_REALTIME is frozen" - assert_operator(realtime, :>, initial_time, "CLOCK_REALTIME is not moving forward") - end + def test_process_clock_gettime_realtime_travel + initial_time = realtime + Timecop.travel do + refute_equal consecutive_realtime, "CLOCK_REALTIME is frozen" + assert_operator(realtime, :>, initial_time, "CLOCK_REALTIME is not moving forward") + end - delta = 0.1 - Timecop.travel(Time.now - delta) do - refute_equal consecutive_realtime, "CLOCK_REALTIME is frozen" - assert_operator(realtime, :<, initial_time, "CLOCK_REALTIME is not traveling properly") - sleep(delta) - assert_operator(realtime, :>, initial_time, "CLOCK_REALTIME is not traveling properly") - end + delta = 0.1 + Timecop.travel(Time.now - delta) do + refute_equal consecutive_realtime, "CLOCK_REALTIME is frozen" + assert_operator(realtime, :<, initial_time, "CLOCK_REALTIME is not traveling properly") + sleep(delta) + assert_operator(realtime, :>, initial_time, "CLOCK_REALTIME is not traveling properly") end + end - def test_process_clock_gettime_realtime_scale - scale = 4 - sleep_length = 0.25 - Timecop.scale(scale) do - initial_time = realtime - sleep(sleep_length) - assert_operator(initial_time + scale * sleep_length, :<, realtime, "CLOCK_REALTIME is not scaling") - end + def test_process_clock_gettime_realtime_scale + scale = 4 + sleep_length = 0.25 + Timecop.scale(scale) do + initial_time = realtime + sleep(sleep_length) + assert_operator(initial_time + scale * sleep_length, :<, realtime, "CLOCK_REALTIME is not scaling") end + end - private + private - def monotonic - Process.clock_gettime(Process::CLOCK_MONOTONIC) - end + def monotonic + Process.clock_gettime(Process::CLOCK_MONOTONIC) + end - def realtime - Process.clock_gettime(Process::CLOCK_REALTIME) - end + def realtime + Process.clock_gettime(Process::CLOCK_REALTIME) + end - def consecutive_monotonic - consecutive_times(:monotonic) - end + def consecutive_monotonic + consecutive_times(:monotonic) + end - def consecutive_realtime - consecutive_times(:realtime) - end + def consecutive_realtime + consecutive_times(:realtime) + end - def consecutive_times(time_method) - t1 = send(time_method) - sleep(TIME_EPSILON) - t2 = send(time_method) + def consecutive_times(time_method) + t1 = send(time_method) + sleep(TIME_EPSILON) + t2 = send(time_method) - [t1, t2] - end + [t1, t2] end end diff --git a/timecop.gemspec b/timecop.gemspec index 514ba86..c22bcf4 100644 --- a/timecop.gemspec +++ b/timecop.gemspec @@ -3,7 +3,7 @@ require File.expand_path('../lib/timecop/version', __FILE__) Gem::Specification.new do |s| s.name = %q{timecop} s.version = Timecop::VERSION - s.required_ruby_version = Gem::Requirement.new(">= 1.9.2") + s.required_ruby_version = Gem::Requirement.new(">= 2.1.0") s.authors = ["Travis Jeffery", "John Trupiano"] s.description = %q{A gem providing "time travel" and "time freezing" capabilities, making it dead simple to test time-dependent code. It provides a unified method to mock Time.now, Date.today, and DateTime.now in a single call.} s.email = %q{travisjeffery@gmail.com}