timecop 0.5.2 → 0.9.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,5 @@
1
1
  require 'singleton'
2
- require 'timecop/time_extensions'
3
- require 'timecop/time_stack_item'
2
+ require File.join(File.dirname(__FILE__), "time_stack_item")
4
3
 
5
4
  # Timecop
6
5
  # * Wrapper class for manipulating the extensions to the Time, Date, and DateTime objects
@@ -14,7 +13,7 @@ class Timecop
14
13
  include Singleton
15
14
 
16
15
  class << self
17
- attr_accessor :active_support
16
+ private :instance
18
17
 
19
18
  # Allows you to run a block of code and "fake" a time throughout the execution of that block.
20
19
  # This is particularly useful for writing test methods where the passage of time is critical to the business
@@ -33,6 +32,7 @@ class Timecop
33
32
  # 3. Timecop.freeze(date_inst)
34
33
  # 4. Timecop.freeze(offset_in_seconds)
35
34
  # 5. Timecop.freeze(year, month, day, hour=0, minute=0, second=0)
35
+ # 6. Timecop.freeze() # Defaults to Time.now
36
36
  #
37
37
  # When a block is also passed, Time.now, DateTime.now and Date.today are all reset to their
38
38
  # previous values after the block has finished executing. This allows us to nest multiple
@@ -47,11 +47,9 @@ class Timecop
47
47
  # which will lead to files being generated with the timestamp set by the Timecop.freeze call
48
48
  # in your dev environment
49
49
  #
50
- # Returns the value of the block or nil.
50
+ # Returns the value of the block if one is given, or the mocked time.
51
51
  def freeze(*args, &block)
52
- val = instance().send(:travel, :freeze, *args, &block)
53
-
54
- block_given? ? val : nil
52
+ send_travel(:freeze, *args, &block)
55
53
  end
56
54
 
57
55
  # Allows you to run a block of code and "fake" a time throughout the execution of that block.
@@ -60,11 +58,9 @@ class Timecop
60
58
  # * Note: Timecop.travel will not freeze time (as opposed to Timecop.freeze). This is a particularly
61
59
  # good candidate for use in environment files in rails projects.
62
60
  #
63
- # Returns the value of the block or nil.
61
+ # Returns the value of the block if one is given, or the mocked time.
64
62
  def travel(*args, &block)
65
- val = instance().send(:travel, :travel, *args, &block)
66
-
67
- block_given? ? val : nil
63
+ send_travel(:travel, *args, &block)
68
64
  end
69
65
 
70
66
  # Allows you to run a block of code and "scale" a time throughout the execution of that block.
@@ -74,74 +70,171 @@ class Timecop
74
70
  # end
75
71
  # See Timecop#freeze for exact usage of the other arguments
76
72
  #
77
- # Returns the value of the block or nil.
73
+ # Returns the value of the block if one is given, or the mocked time.
78
74
  def scale(*args, &block)
79
- val = instance().send(:travel, :scale, *args, &block)
80
-
81
- block_given? ? val : nil
75
+ send_travel(:scale, *args, &block)
82
76
  end
83
77
 
84
78
  def baseline
85
- instance().send(:baseline)
79
+ instance.baseline
86
80
  end
87
81
 
88
82
  def baseline=(baseline)
89
- instance().send(:baseline=, baseline)
83
+ instance.baseline = baseline
90
84
  end
91
85
 
92
- # Reverts back to system's Time.now, Date.today and DateTime.now (if it exists).
93
- def return
94
- instance().send(:unmock!)
95
- nil
86
+ # Reverts back to system's Time.now, Date.today and DateTime.now (if it exists) permamently when
87
+ # no block argument is given, or temporarily reverts back to the system's time temporarily for
88
+ # the given block.
89
+ def return(&block)
90
+ if block_given?
91
+ instance.return(&block)
92
+ else
93
+ instance.unmock!
94
+ nil
95
+ end
96
96
  end
97
+ alias :unfreeze :return
97
98
 
98
99
  def return_to_baseline
99
- instance().send(:return_to_baseline)
100
+ instance.return_to_baseline
100
101
  Time.now
101
102
  end
102
103
 
103
104
  def top_stack_item #:nodoc:
104
- instance().instance_variable_get(:@_stack).last
105
+ instance.stack.last
106
+ end
107
+
108
+ def safe_mode=(safe)
109
+ @safe_mode = safe
110
+ end
111
+
112
+ def safe_mode?
113
+ @safe_mode ||= false
114
+ end
115
+
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/travelled
125
+ def frozen?
126
+ !instance.stack.empty?
127
+ end
128
+
129
+ private
130
+ def send_travel(mock_type, *args, &block)
131
+ val = instance.travel(mock_type, *args, &block)
132
+ block_given? ? val : Time.now
105
133
  end
106
134
  end
107
135
 
108
- protected
136
+ def baseline=(b)
137
+ set_baseline(b)
138
+ stack << TimeStackItem.new(:travel, b)
139
+ end
109
140
 
110
- def baseline=(baseline)
111
- @baseline = baseline
112
- @_stack << TimeStackItem.new(:travel, baseline)
141
+ def baseline
142
+ if @thread_safe
143
+ Thread.current[:timecop_baseline]
144
+ else
145
+ @baseline
113
146
  end
147
+ end
114
148
 
115
- def initialize #:nodoc:
116
- @_stack = []
149
+ def set_baseline(b)
150
+ if @thread_safe
151
+ Thread.current[:timecop_baseline] = b
152
+ else
153
+ @baseline = b
117
154
  end
155
+ end
118
156
 
119
- def travel(mock_type, *args, &block) #:nodoc:
120
- stack_item = TimeStackItem.new(mock_type, *args)
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
121
165
 
122
- # store this time traveling on our stack...
123
- @_stack << stack_item
166
+ def set_stack(s)
167
+ if @thread_safe
168
+ Thread.current[:timecop_stack] = s
169
+ else
170
+ @stack = s
171
+ end
172
+ end
124
173
 
125
- if block_given?
126
- begin
127
- yield stack_item.time
128
- ensure
129
- # pull it off the stack...
130
- @_stack.pop
131
- end
174
+ def initialize #:nodoc:
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
187
+ end
188
+
189
+ def travel(mock_type, *args, &block) #:nodoc:
190
+ raise SafeModeException if Timecop.safe_mode? && !block_given? && !@safe
191
+
192
+ stack_item = TimeStackItem.new(mock_type, *args)
193
+
194
+ stack_backup = stack.dup
195
+ stack << stack_item
196
+
197
+ if block_given?
198
+ safe_backup = @safe
199
+ @safe = true
200
+ begin
201
+ yield stack_item.time
202
+ ensure
203
+ stack.replace stack_backup
204
+ @safe = safe_backup
132
205
  end
133
206
  end
207
+ end
208
+
209
+ def return(&block)
210
+ current_stack = stack
211
+ current_baseline = baseline
212
+ unmock!
213
+ yield
214
+ ensure
215
+ set_stack current_stack
216
+ set_baseline current_baseline
217
+ end
134
218
 
135
- def unmock! #:nodoc:
136
- @baseline = nil
137
- @_stack = []
219
+ def unmock! #:nodoc:
220
+ set_baseline nil
221
+ set_stack []
222
+ end
223
+
224
+ def return_to_baseline
225
+ if baseline
226
+ set_stack [stack.shift]
227
+ else
228
+ unmock!
138
229
  end
230
+ end
139
231
 
140
- def return_to_baseline
141
- if @baseline
142
- @_stack = [@_stack.shift]
143
- else
144
- unmock!
145
- end
232
+ class SafeModeException < StandardError
233
+ def initialize
234
+ super "Safe mode is enabled, only calls passing a block are allowed."
146
235
  end
236
+ end
147
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.5.2"
3
- end
2
+ VERSION = "0.9.5"
3
+ end
data/lib/timecop.rb CHANGED
@@ -1,2 +1,2 @@
1
- require 'timecop/timecop'
2
- require 'timecop/version'
1
+ require File.join(File.dirname(__FILE__), "timecop", "timecop")
2
+ require File.join(File.dirname(__FILE__), "timecop", "version")
data/test/test_helper.rb CHANGED
@@ -1,34 +1,39 @@
1
- require 'rubygems'
2
1
  require 'bundler/setup'
3
- require 'test/unit'
4
- require 'mocha'
2
+ require 'minitest/autorun'
3
+ require 'minitest/rg'
4
+ require 'pry'
5
5
 
6
- class Test::Unit::TestCase
6
+ $VERBOSE = true # enable ruby warnings
7
7
 
8
+ require 'mocha/minitest'
9
+
10
+ class Minitest::Test
8
11
  private
9
12
  # Tests to see that two times are within the given distance,
10
13
  # in seconds, from each other.
11
14
  def times_effectively_equal(time1, time2, seconds_interval = 1)
12
15
  (time1 - time2).abs <= seconds_interval
13
16
  end
14
-
17
+
15
18
  def assert_times_effectively_equal(time1, time2, seconds_interval = 1, msg = nil)
16
19
  assert times_effectively_equal(time1, time2, seconds_interval), "#{msg}: time1 = #{time1.to_s}, time2 = #{time2.to_s}"
17
20
  end
18
-
21
+
19
22
  def assert_times_effectively_not_equal(time1, time2, seconds_interval = 1, msg = nil)
20
23
  assert !times_effectively_equal(time1, time2, seconds_interval), "#{msg}: time1 = #{time1.to_s}, time2 = #{time2.to_s}"
21
24
  end
22
-
23
- def local_offset
24
- DateTime.now_without_mock_time.offset
25
+
26
+ # Gets the local offset (supplied by ENV['TZ'] or your computer's clock)
27
+ # At the given timestamp, or Time.now if not time is given.
28
+ def local_offset(time = Time.now)
29
+ Time.at(time.to_i).to_datetime.offset
25
30
  end
26
-
27
- TIMEZONES = ["Europe/Paris", "UTC", "EDT"]
28
-
31
+
32
+ TIMEZONES = ["Pacific/Midway", "Europe/Paris", "UTC", "America/Chicago"]
33
+
29
34
  def each_timezone
30
35
  old_tz = ENV["TZ"]
31
-
36
+
32
37
  begin
33
38
  TIMEZONES.each do |timezone|
34
39
  ENV["TZ"] = timezone
@@ -38,13 +43,17 @@ class Test::Unit::TestCase
38
43
  ENV["TZ"] = old_tz
39
44
  end
40
45
  end
41
-
46
+
42
47
  def a_time_stack_item
43
48
  Timecop::TimeStackItem.new(:freeze, 2008, 1, 1, 0, 0, 0)
44
49
  end
45
-
50
+
46
51
  def assert_date_times_equal(dt1, dt2)
47
- assert_equal dt1, dt2, "Failed for timezone: #{ENV['TZ']}: #{dt1.to_s} not equal to #{dt2.to_s}"
52
+ 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}"
48
53
  end
49
-
54
+
55
+ def jruby?
56
+ RUBY_PLATFORM == "java"
57
+ end
58
+
50
59
  end