timecop 0.8.0 → 0.9.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,4 @@
1
1
  require 'singleton'
2
- require File.join(File.dirname(__FILE__), "time_extensions")
3
2
  require File.join(File.dirname(__FILE__), "time_stack_item")
4
3
 
5
4
  # Timecop
@@ -14,6 +13,8 @@ class Timecop
14
13
  include Singleton
15
14
 
16
15
  class << self
16
+ private :instance
17
+
17
18
  # Allows you to run a block of code and "fake" a time throughout the execution of that block.
18
19
  # This is particularly useful for writing test methods where the passage of time is critical to the business
19
20
  # logic being tested. For example:
@@ -75,11 +76,11 @@ class Timecop
75
76
  end
76
77
 
77
78
  def baseline
78
- instance.send(:baseline)
79
+ instance.baseline
79
80
  end
80
81
 
81
82
  def baseline=(baseline)
82
- instance.send(:baseline=, baseline)
83
+ instance.baseline = baseline
83
84
  end
84
85
 
85
86
  # Reverts back to system's Time.now, Date.today and DateTime.now (if it exists) permamently when
@@ -87,20 +88,21 @@ class Timecop
87
88
  # the given block.
88
89
  def return(&block)
89
90
  if block_given?
90
- instance.send(:return, &block)
91
+ instance.return(&block)
91
92
  else
92
- instance.send(:unmock!)
93
+ instance.unmock!
93
94
  nil
94
95
  end
95
96
  end
97
+ alias :unfreeze :return
96
98
 
97
99
  def return_to_baseline
98
- instance.send(:return_to_baseline)
100
+ instance.return_to_baseline
99
101
  Time.now
100
102
  end
101
103
 
102
104
  def top_stack_item #:nodoc:
103
- instance.instance_variable_get(:@_stack).last
105
+ instance.stack.last
104
106
  end
105
107
 
106
108
  def safe_mode=(safe)
@@ -111,64 +113,117 @@ class Timecop
111
113
  @safe_mode ||= false
112
114
  end
113
115
 
114
- # Returns whether or not Timecop is currently frozen/travelled
116
+ def thread_safe=(t)
117
+ instance.thread_safe = t
118
+ end
119
+
120
+ def thread_safe
121
+ instance.thread_safe
122
+ end
123
+
124
+ # Returns whether or not Timecop is currently frozen
115
125
  def frozen?
116
- !instance.instance_variable_get(:@_stack).empty?
126
+ !instance.stack.empty? && instance.stack.last.mock_type == :freeze
117
127
  end
118
128
 
119
129
  private
120
130
  def send_travel(mock_type, *args, &block)
121
- val = instance.send(:travel, mock_type, *args, &block)
131
+ val = instance.travel(mock_type, *args, &block)
122
132
  block_given? ? val : Time.now
123
133
  end
124
134
  end
125
135
 
126
- private
136
+ def baseline=(b)
137
+ set_baseline(b)
138
+ stack << TimeStackItem.new(:travel, b)
139
+ end
140
+
141
+ def baseline
142
+ if @thread_safe
143
+ Thread.current[:timecop_baseline]
144
+ else
145
+ @baseline
146
+ end
147
+ end
127
148
 
128
- def baseline=(baseline)
129
- @baseline = baseline
130
- @_stack << TimeStackItem.new(:travel, baseline)
149
+ def set_baseline(b)
150
+ if @thread_safe
151
+ Thread.current[:timecop_baseline] = b
152
+ else
153
+ @baseline = b
154
+ end
155
+ end
156
+
157
+ def stack
158
+ if @thread_safe
159
+ Thread.current[:timecop_stack] ||= []
160
+ Thread.current[:timecop_stack]
161
+ else
162
+ @stack
163
+ end
164
+ end
165
+
166
+ def set_stack(s)
167
+ if @thread_safe
168
+ Thread.current[:timecop_stack] = s
169
+ else
170
+ @stack = s
171
+ end
131
172
  end
132
173
 
133
174
  def initialize #:nodoc:
134
- @_stack = []
175
+ @stack = []
176
+ @safe = nil
177
+ @thread_safe = false
178
+ end
179
+
180
+ def thread_safe=(t)
181
+ initialize
182
+ @thread_safe = t
183
+ end
184
+
185
+ def thread_safe
186
+ @thread_safe
135
187
  end
136
188
 
137
189
  def travel(mock_type, *args, &block) #:nodoc:
138
- raise SafeModeException if Timecop.safe_mode? && !block_given?
190
+ raise SafeModeException if Timecop.safe_mode? && !block_given? && !@safe
139
191
 
140
192
  stack_item = TimeStackItem.new(mock_type, *args)
141
193
 
142
- stack_backup = @_stack.dup
143
- @_stack << stack_item
194
+ stack_backup = stack.dup
195
+ stack << stack_item
144
196
 
145
197
  if block_given?
198
+ safe_backup = @safe
199
+ @safe = true
146
200
  begin
147
201
  yield stack_item.time
148
202
  ensure
149
- @_stack.replace stack_backup
203
+ stack.replace stack_backup
204
+ @safe = safe_backup
150
205
  end
151
206
  end
152
207
  end
153
208
 
154
209
  def return(&block)
155
- current_stack = @_stack
156
- current_baseline = @baseline
210
+ current_stack = stack
211
+ current_baseline = baseline
157
212
  unmock!
158
213
  yield
159
214
  ensure
160
- @_stack = current_stack
161
- @baseline = current_baseline
215
+ set_stack current_stack
216
+ set_baseline current_baseline
162
217
  end
163
218
 
164
219
  def unmock! #:nodoc:
165
- @baseline = nil
166
- @_stack = []
220
+ set_baseline nil
221
+ set_stack []
167
222
  end
168
223
 
169
224
  def return_to_baseline
170
- if @baseline
171
- @_stack = [@_stack.shift]
225
+ if baseline
226
+ set_stack [stack.shift]
172
227
  else
173
228
  unmock!
174
229
  end
@@ -180,3 +235,6 @@ class Timecop
180
235
  end
181
236
  end
182
237
  end
238
+
239
+ # This must be done after TimeCop is available
240
+ require File.join(File.dirname(__FILE__), "time_extensions")
@@ -1,3 +1,3 @@
1
1
  class Timecop
2
- VERSION = "0.8.0"
2
+ VERSION = "0.9.8"
3
3
  end
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: timecop
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0
4
+ version: 0.9.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Travis Jeffery
8
8
  - John Trupiano
9
- autorequire:
9
+ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-07-28 00:00:00.000000000 Z
12
+ date: 2023-08-14 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: A gem providing "time travel" and "time freezing" capabilities, making
15
15
  it dead simple to test time-dependent code. It provides a unified method to mock
@@ -27,44 +27,32 @@ files:
27
27
  - lib/timecop.rb
28
28
  - lib/timecop/time_extensions.rb
29
29
  - lib/timecop/time_stack_item.rb
30
- - lib/timecop/version.rb
31
30
  - lib/timecop/timecop.rb
32
- - test/run_tests.sh
33
- - test/test_helper.rb
34
- - test/time_stack_item_test.rb
35
- - test/timecop_test.rb
36
- - test/timecop_without_date_test.rb
37
- - test/timecop_without_date_but_with_time_test.rb
31
+ - lib/timecop/version.rb
38
32
  homepage: https://github.com/travisjeffery/timecop
39
33
  licenses:
40
34
  - MIT
41
35
  metadata: {}
42
- post_install_message:
36
+ post_install_message:
43
37
  rdoc_options:
44
- - --charset=UTF-8
38
+ - "--charset=UTF-8"
45
39
  require_paths:
46
40
  - lib
47
41
  required_ruby_version: !ruby/object:Gem::Requirement
48
42
  requirements:
49
- - - '>='
43
+ - - ">="
50
44
  - !ruby/object:Gem::Version
51
45
  version: 1.9.2
52
46
  required_rubygems_version: !ruby/object:Gem::Requirement
53
47
  requirements:
54
- - - '>='
48
+ - - ">="
55
49
  - !ruby/object:Gem::Version
56
50
  version: '0'
57
51
  requirements: []
58
- rubyforge_project: timecop
59
- rubygems_version: 2.0.14
60
- signing_key:
61
- specification_version: 3
52
+ rubygems_version: 3.2.15
53
+ signing_key:
54
+ specification_version: 4
62
55
  summary: A gem providing "time travel" and "time freezing" capabilities, making it
63
56
  dead simple to test time-dependent code. It provides a unified method to mock Time.now,
64
57
  Date.today, and DateTime.now in a single call.
65
- test_files:
66
- - test/test_helper.rb
67
- - test/time_stack_item_test.rb
68
- - test/timecop_test.rb
69
- - test/timecop_without_date_test.rb
70
- - test/timecop_without_date_but_with_time_test.rb
58
+ test_files: []
data/test/run_tests.sh DELETED
@@ -1,10 +0,0 @@
1
- #!/bin/sh
2
-
3
- FAILEDCASES=0
4
- for f in *_test.rb; do
5
- if ! ${RUBY:-ruby} -I../lib:. $f; then
6
- FAILEDCASES=`expr "$FAILEDCASES" + 1`
7
- fi
8
- done
9
- echo "$FAILEDCASES test cases had failures"
10
- exit $FAILEDCASES
data/test/test_helper.rb DELETED
@@ -1,58 +0,0 @@
1
- require 'rubygems'
2
- require 'bundler/setup'
3
- require 'minitest/autorun'
4
-
5
- $VERBOSE = true # enable ruby warnings
6
-
7
- begin
8
- require 'mocha/setup'
9
- rescue LoadError
10
- require 'mocha'
11
- end
12
-
13
- class Minitest::Unit::TestCase
14
- private
15
- # Tests to see that two times are within the given distance,
16
- # in seconds, from each other.
17
- def times_effectively_equal(time1, time2, seconds_interval = 1)
18
- (time1 - time2).abs <= seconds_interval
19
- end
20
-
21
- def assert_times_effectively_equal(time1, time2, seconds_interval = 1, msg = nil)
22
- assert times_effectively_equal(time1, time2, seconds_interval), "#{msg}: time1 = #{time1.to_s}, time2 = #{time2.to_s}"
23
- end
24
-
25
- def assert_times_effectively_not_equal(time1, time2, seconds_interval = 1, msg = nil)
26
- assert !times_effectively_equal(time1, time2, seconds_interval), "#{msg}: time1 = #{time1.to_s}, time2 = #{time2.to_s}"
27
- end
28
-
29
- # Gets the local offset (supplied by ENV['TZ'] or your computer's clock)
30
- # At the given timestamp, or Time.now if not time is given.
31
- def local_offset(time = Time.now)
32
- Time.at(time.to_i).to_datetime.offset
33
- end
34
-
35
- TIMEZONES = ["Europe/Paris", "UTC", "America/Chicago"]
36
-
37
- def each_timezone
38
- old_tz = ENV["TZ"]
39
-
40
- begin
41
- TIMEZONES.each do |timezone|
42
- ENV["TZ"] = timezone
43
- yield
44
- end
45
- ensure
46
- ENV["TZ"] = old_tz
47
- end
48
- end
49
-
50
- def a_time_stack_item
51
- Timecop::TimeStackItem.new(:freeze, 2008, 1, 1, 0, 0, 0)
52
- end
53
-
54
- def assert_date_times_equal(dt1, dt2)
55
- assert_in_delta dt1.to_time.to_f, dt2.to_time.to_f, 0.01, "Failed for timezone: #{ENV['TZ']}: #{dt1.to_s} not equal to #{dt2.to_s}"
56
- end
57
-
58
- end
@@ -1,277 +0,0 @@
1
- require 'date'
2
- require File.join(File.dirname(__FILE__), "test_helper")
3
- require File.join(File.dirname(__FILE__), '..', 'lib', 'timecop')
4
-
5
- require 'active_support/all'
6
-
7
- class TestTimeStackItem < Minitest::Unit::TestCase
8
- def teardown
9
- Timecop.return
10
- Time.zone = nil
11
- end
12
-
13
- def test_new_with_time
14
- t = Time.now
15
- y, m, d, h, min, s = t.year, t.month, t.day, t.hour, t.min, t.sec
16
- stack_item = Timecop::TimeStackItem.new(:freeze, t)
17
-
18
- assert_equal y, stack_item.year
19
- assert_equal m, stack_item.month
20
- assert_equal d, stack_item.day
21
- assert_equal h, stack_item.hour
22
- assert_equal min, stack_item.min
23
- assert_equal s, stack_item.sec
24
- end
25
-
26
- def test_new_with_time_and_arguments
27
- t = Time.new(2012, 7, 28, 20, 0)
28
- y, m, d, h, min, s = t.year, t.month, t.day, t.hour, t.min, t.sec
29
- stack_item = Timecop::TimeStackItem.new(:freeze, t)
30
-
31
- assert_equal y, stack_item.year
32
- assert_equal m, stack_item.month
33
- assert_equal d, stack_item.day
34
- assert_equal h, stack_item.hour
35
- assert_equal min, stack_item.min
36
- assert_equal s, stack_item.sec
37
- end
38
-
39
- def test_new_with_datetime_now
40
- t = DateTime.now
41
- y, m, d, h, min, s = t.year, t.month, t.day, t.hour, t.min, t.sec
42
- stack_item = Timecop::TimeStackItem.new(:freeze, t)
43
-
44
- assert_equal y, stack_item.year
45
- assert_equal m, stack_item.month
46
- assert_equal d, stack_item.day
47
- assert_equal h, stack_item.hour
48
- assert_equal min, stack_item.min
49
- assert_equal s, stack_item.sec
50
- end
51
-
52
- def test_new_with_datetime_in_different_timezone
53
- each_timezone do
54
- t = DateTime.parse("2009-10-11 00:38:00 +0200")
55
- stack_item = Timecop::TimeStackItem.new(:freeze, t)
56
-
57
- assert_date_times_equal(t, stack_item.datetime)
58
- end
59
- end
60
-
61
- def test_new_with_date
62
- date = Date.today
63
- y, m, d, h, min, s = date.year, date.month, date.day, 0, 0, 0
64
- stack_item = Timecop::TimeStackItem.new(:freeze, date)
65
-
66
- assert_equal y, stack_item.year
67
- assert_equal m, stack_item.month
68
- assert_equal d, stack_item.day
69
- assert_equal h, stack_item.hour
70
- assert_equal min, stack_item.min
71
- assert_equal s, stack_item.sec
72
- end
73
-
74
- # Due to the nature of this test (calling Time.now once in this test and
75
- # once in #new), this test may fail when two subsequent calls
76
- # to Time.now return a different second.
77
- def test_new_with_integer
78
- t = Time.now
79
- y, m, d, h, min, s = t.year, t.month, t.day, t.hour, t.min, t.sec
80
- stack_item = Timecop::TimeStackItem.new(:freeze, 0)
81
-
82
- assert_equal y, stack_item.year
83
- assert_equal m, stack_item.month
84
- assert_equal d, stack_item.day
85
- assert_equal h, stack_item.hour
86
- assert_equal min, stack_item.min
87
- assert_equal s, stack_item.sec
88
- end
89
-
90
- def test_new_with_individual_arguments
91
- y, m, d, h, min, s = 2008, 10, 10, 10, 10, 10
92
- stack_item = Timecop::TimeStackItem.new(:freeze, y, m, d, h, min, s)
93
-
94
- assert_equal y, stack_item.year
95
- assert_equal m, stack_item.month
96
- assert_equal d, stack_item.day
97
- assert_equal h, stack_item.hour
98
- assert_equal min, stack_item.min
99
- assert_equal s, stack_item.sec
100
- end
101
-
102
- def test_rational_to_utc_offset
103
- assert_equal -14400, a_time_stack_item.send(:rational_to_utc_offset, Rational(-1, 6))
104
- assert_equal -18000, a_time_stack_item.send(:rational_to_utc_offset, Rational(-5, 24))
105
- assert_equal 0, a_time_stack_item.send(:rational_to_utc_offset, Rational(0, 1))
106
- assert_equal 3600, a_time_stack_item.send(:rational_to_utc_offset, Rational(1, 24))
107
- end
108
-
109
- def test_utc_offset_to_rational
110
- assert_equal Rational(-1, 6), a_time_stack_item.send(:utc_offset_to_rational, -14400)
111
- assert_equal Rational(-5, 24), a_time_stack_item.send(:utc_offset_to_rational, -18000)
112
- assert_equal Rational(0, 1), a_time_stack_item.send(:utc_offset_to_rational, 0)
113
- assert_equal Rational(1, 24), a_time_stack_item.send(:utc_offset_to_rational, 3600)
114
- end
115
-
116
- def test_datetime_in_presence_of_activesupport_timezone
117
- skip('requires ActiveSupport') unless Time.respond_to? :zone
118
- backed_up_zone, backed_up_tzvar = Time.zone, ENV['TZ']
119
-
120
- Time.zone = ENV['TZ'] = 'America/Los_Angeles'
121
- t = DateTime.new(2001, 2, 28, 23, 59, 59.5)
122
- tsi = Timecop::TimeStackItem.new(:freeze, t)
123
-
124
- assert_date_times_equal t, tsi.datetime
125
- ensure
126
- Time.zone, ENV['TZ'] = backed_up_zone, backed_up_tzvar
127
- end
128
-
129
- # Ensure DateTimes handle changing DST properly
130
- def test_datetime_for_dst_to_non_dst
131
- Timecop.freeze(DateTime.parse("2009-12-1 00:38:00 -0500"))
132
- t = DateTime.parse("2009-10-11 00:00:00 -0400")
133
- tsi = Timecop::TimeStackItem.new(:freeze, t)
134
-
135
- assert_date_times_equal t, tsi.datetime
136
- end
137
-
138
- # Ensure DateTimes handle changing DST properly when changing from DateTime to Time
139
- def test_datetime_for_dst_to_time_for_non_dst
140
- Timecop.freeze(DateTime.parse("2009-12-1 00:38:00 -0500"))
141
- t = DateTime.parse("2009-10-11 00:00:00 -0400")
142
- tsi = Timecop::TimeStackItem.new(:freeze, t)
143
-
144
- assert_date_times_equal t.to_time, tsi.time
145
- end
146
-
147
- def test_datetime_for_non_dst_to_dst
148
- Timecop.freeze(DateTime.parse("2009-10-11 00:00:00 -0400"))
149
- t = DateTime.parse("2009-11-30 23:38:00 -0500")
150
- tsi = Timecop::TimeStackItem.new(:freeze, t)
151
- return if !tsi.time.dst?
152
-
153
- assert_date_times_equal t, tsi.datetime
154
- assert_equal Date.new(2009, 12, 1), tsi.date
155
- end
156
-
157
- def test_set_travel_offset_for_travel
158
- t_now = Time.now
159
- t = Time.local(2009, 10, 1, 0, 0, 30)
160
- expected_offset = t - t_now
161
- tsi = Timecop::TimeStackItem.new(:travel, t)
162
-
163
- assert_times_effectively_equal expected_offset, tsi.send(:travel_offset), 1, "Offset not calculated correctly"
164
- end
165
-
166
- def test_set_travel_offset_for_freeze
167
- Timecop.freeze(2009, 10, 1, 0, 0, 0)
168
- t = Time.local(2009, 10, 1, 0, 0, 30)
169
- tsi = Timecop::TimeStackItem.new(:freeze, t)
170
-
171
- assert_equal nil, tsi.send(:travel_offset)
172
- end
173
-
174
- def test_timezones
175
- Time.zone = "Europe/Zurich"
176
- time = Time.zone.parse("2012-12-27T12:12:12+08:00")
177
- Timecop.freeze(time) do |frozen_time|
178
- assert_equal time, frozen_time
179
- end
180
- end
181
-
182
- def test_timezones_apply_dates
183
- Time.zone = "Central Time (US & Canada)"
184
- time = Time.zone.local(2013,1,3)
185
-
186
- Timecop.freeze(time) do
187
- assert_equal time.to_date, Time.now.to_date
188
- end
189
- end
190
-
191
- def test_set_scaling_factor_for_scale
192
- t_now = Time.now
193
- t = Time.local(2009, 10, 1, 0, 0, 30)
194
- expected_offset = t - t_now
195
- tsi = Timecop::TimeStackItem.new(:scale, 4, t)
196
-
197
- assert_times_effectively_equal expected_offset, tsi.send(:travel_offset), 1, "Offset not calculated correctly"
198
- assert_equal tsi.send(:scaling_factor), 4, "Scaling factor not set"
199
- end
200
-
201
- def test_parse_only_string_with_active_support
202
- Time.expects(:parse).never
203
- Timecop.freeze(2011, 01, 02, hour=0, minute=0, second=0)
204
- end
205
-
206
- def test_parse_date
207
- Timecop.freeze(Date.new(2012, 6, 9))
208
- end
209
-
210
- def test_time_zone_returns_nil
211
- Time.zone = nil
212
- Timecop.freeze
213
- end
214
-
215
- def test_nsecs_are_set
216
- time = Time.now
217
- Timecop.freeze time
218
- assert_equal time, Time.now
219
- assert_equal time.nsec, Time.now.nsec if (Time.now.respond_to?(:nsec))
220
- end
221
-
222
- def test_time_with_different_timezone_keeps_nsec
223
- Time.zone = "Tokyo"
224
- t = Time.now
225
- Timecop.freeze(t) do
226
- assert_equal t, Time.now
227
- assert_equal t.nsec, Time.now.nsec if (Time.now.respond_to?(:nsec))
228
- end
229
- end
230
-
231
- def test_time_now_always_returns_local_time
232
- Time.zone = "Tokyo"
233
- t = Time.utc(2000, 1, 1)
234
- Timecop.freeze(t) do
235
- assert_equal t.getlocal.zone, Time.now.zone
236
- end
237
- end
238
-
239
- def test_time_zone_now_returns_time_in_that_zone
240
- Time.zone = "Hawaii"
241
- t = Time.utc(2000, 1, 1)
242
- Timecop.freeze(t) do
243
- assert_equal t, Time.zone.now
244
- assert_equal 'HST', Time.zone.now.zone
245
- end
246
- end
247
-
248
- def test_freezing_a_time_leaves_timezone_intact
249
- Time.zone = "Tokyo"
250
- t = Time.now
251
- t_dup = t.dup
252
- Timecop.freeze(t) {}
253
- assert_equal t_dup.zone, t.zone
254
- end
255
-
256
- def test_freezing_a_time_with_zone_returns_proper_zones
257
- Time.zone = "Hawaii"
258
- t = ActiveSupport::TimeWithZone.new(Time.utc(2000, 1, 1), ActiveSupport::TimeZone['Tokyo'])
259
- Timecop.freeze(t) do
260
- local_now = Time.now
261
- assert_equal t, local_now
262
- assert_equal t.getlocal.zone, local_now.zone
263
-
264
- zoned_now = Time.zone.now
265
- assert_equal t, zoned_now
266
- assert_equal 'HST', zoned_now.zone
267
- end
268
- end
269
-
270
- def test_datetime_timezones
271
- dt = DateTime.new(2011,1,3,15,25,0,"-6")
272
- Timecop.freeze(dt) do
273
- now = DateTime.now
274
- assert_equal dt, now, "#{dt.to_f}, #{now.to_f}"
275
- end
276
- end
277
- end