timecop 0.5.2 → 0.9.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -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