liangzan-timecop 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +63 -0
- data/LICENSE +22 -0
- data/README.rdoc +76 -0
- data/Rakefile +35 -0
- data/VERSION.yml +4 -0
- data/lib/timecop.rb +2 -0
- data/lib/timecop/stack_item.rb +12 -0
- data/lib/timecop/time_extensions.rb +143 -0
- data/lib/timecop/timecop.rb +179 -0
- data/test/run_tests.sh +10 -0
- data/test/test_helper.rb +2 -0
- data/test/test_timecop.rb +228 -0
- data/test/test_timecop_internals.rb +67 -0
- data/test/test_timecop_without_date.rb +118 -0
- metadata +72 -0
data/History.txt
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
=== 0.3.0 / 2009-09-20
|
2
|
+
|
3
|
+
* API
|
4
|
+
* Completely remove Timecop#unset_all (deprecated by Timecop#return in 0.2.0)
|
5
|
+
* Return Time.now from #freeze, #travel and #return -- code contributed by Keith Bennett (keithrbennett)
|
6
|
+
|
7
|
+
* Maintenance
|
8
|
+
* Fix bug that left Time#mock_time set in some instances
|
9
|
+
* Upped build dependency to jeweler ~> 1.2.1
|
10
|
+
* Don't pollute top-level namespace with classes/constants
|
11
|
+
|
12
|
+
* Documentation
|
13
|
+
* Clearer examples in the README, better description in the gemspec
|
14
|
+
* Improve RDoc
|
15
|
+
|
16
|
+
=== 0.2.1 / 2009-03-06
|
17
|
+
* API Changes
|
18
|
+
|
19
|
+
* Introduced a 5th style of arguments to be passed into #travel and #freeze. Now, if you pass in a single integer value,
|
20
|
+
it will be interpreted as a relative offset in seconds from the current Time.now. Previously this was interpreted as
|
21
|
+
only the year, similar to calling Time.local(2008) --> Jan. 1, 2008. This is no longer the case.
|
22
|
+
|
23
|
+
* Documentation
|
24
|
+
|
25
|
+
* Moved to Textile for the README.
|
26
|
+
|
27
|
+
* Added documentation for the new feature, and fixed a few typos.
|
28
|
+
|
29
|
+
=== 0.2.0 / 2008-12-23
|
30
|
+
|
31
|
+
* API Changes
|
32
|
+
|
33
|
+
* Timecop#travel no longer freezes time. Rather, it computes the current offset between the new "now" and the real "now", and
|
34
|
+
returns times as if Time had continued to move forward
|
35
|
+
|
36
|
+
* Timecop#freeze now behaves exactly as the old Timecop#travel behaved. Unless you depended on the actual freezing of time
|
37
|
+
(which I think would be rare), you should be able to continue to use #travel without worry.
|
38
|
+
|
39
|
+
* Timecop#return is now exposed (previously Timecop#unset_all, but not well advertised). It will completely unmock time,
|
40
|
+
and will probably be rarely used outside of the actual implementation of this library.
|
41
|
+
|
42
|
+
* More Test Coverage
|
43
|
+
|
44
|
+
* Tests now explicitly cover the cases when the Date and DateTime objects are not loaded, and ensures proper functionality
|
45
|
+
in their absence and existence.
|
46
|
+
|
47
|
+
* Still haven't done regression testing against anything other than a few version of 1.8.6 (including REE). We should
|
48
|
+
probably try to get this tested on both 1.8.7 and 1.9.1.
|
49
|
+
|
50
|
+
* Documentation
|
51
|
+
|
52
|
+
* Fixed up a lot of the poorly-formatted rdoc syntax. The public API should now be properly published in the rdoc,
|
53
|
+
and the internals are omitted.
|
54
|
+
|
55
|
+
=== 0.1.0 / 2008-11-09
|
56
|
+
|
57
|
+
* Initial Feature Set
|
58
|
+
|
59
|
+
* Temporarily (or permanently if you prefer) change the concept of Time.now, DateTime.now (if defined), and Date.today (if defined)
|
60
|
+
* Timecop#travel api allows an argument to be passed in as one of: 1) Time instance, 2) DateTime instance, 3) Date instance,
|
61
|
+
4) individual arguments (year, month, day, hour, minute, second)
|
62
|
+
* Nested calls to Timecop#travel are supported -- each block will maintain it's interpretation of now.
|
63
|
+
|
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
(The MIT License)
|
2
|
+
|
3
|
+
Copyright (c) 2008
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
'Software'), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
19
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
20
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
21
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
22
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
= timecop
|
2
|
+
|
3
|
+
* http://github.com/jtrupiano/timecop
|
4
|
+
|
5
|
+
== WHAT THIS FORK DOES
|
6
|
+
|
7
|
+
This is a fork of the Timecop gem. This fork make use of file caches to store the offset and values of the mock time objects. This allows different processes to read and write to the mock objects. The motivation is to enable Culerity to use timecop.
|
8
|
+
|
9
|
+
== Cache Files
|
10
|
+
|
11
|
+
Two timecop cache files are created in your home directory. They are .timecop-cache.time.cache and .timecop-cache.offset.cache
|
12
|
+
|
13
|
+
== DESCRIPTION
|
14
|
+
|
15
|
+
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.
|
16
|
+
|
17
|
+
== FEATURES
|
18
|
+
|
19
|
+
* Freeze time to a specific point.
|
20
|
+
* Travel back to a specific point in time, but allow time to continue moving forward from there.
|
21
|
+
* Timecop api allows arguments to be passed into #freeze and #travel as one of the following:
|
22
|
+
* Time instance
|
23
|
+
* DateTime instance
|
24
|
+
* Date instance
|
25
|
+
* individual arguments (year, month, day, hour, minute, second)
|
26
|
+
* a single integer argument that is interpreted as an offset in seconds from Time.now
|
27
|
+
* Nested calls to Timecop#travel and Timecop#freeze are supported -- each block will maintain its interpretation of now.
|
28
|
+
|
29
|
+
== USAGE
|
30
|
+
|
31
|
+
Run a time-sensitive test
|
32
|
+
|
33
|
+
joe = User.find(1)
|
34
|
+
joe.purchase_home()
|
35
|
+
assert !joe.mortgage_due?
|
36
|
+
# move ahead a month and assert that the mortgage is due
|
37
|
+
Timecop.freeze(Date.today + 30) do
|
38
|
+
assert joe.mortgage_due?
|
39
|
+
end
|
40
|
+
|
41
|
+
Set the time for the test environment of a rails app -- this is particularly helpful if your whole application is time-sensitive. It allows you to build your test data at a single point in time, and to move in/out of that time as appropriate (within your tests)
|
42
|
+
|
43
|
+
in config/environments/test.rb
|
44
|
+
|
45
|
+
config.after_initialize do
|
46
|
+
# Set Time.now to September 1, 2008 10:05:00 AM (at this instant), but allow it to move forward
|
47
|
+
t = Time.local(2008, 9, 1, 10, 5, 0)
|
48
|
+
Timecop.travel(t)
|
49
|
+
end
|
50
|
+
|
51
|
+
=== The difference between Timecop.freeze and Timecop.travel
|
52
|
+
|
53
|
+
#freeze is used to statically mock the concept of now. As your program executes, Time.now will not change unless you make subsequent calls into the Timecop API. #travel, on the other hand, computes an offset between what we currently think Time.now is (recall that we support nested traveling) and the time passed in. It uses this offset to simulate the passage of time. To demonstrate, consider the following code snippets:
|
54
|
+
|
55
|
+
new_time = Time.local(2008, 9, 1, 12, 0, 0)
|
56
|
+
Timecop.freeze(new_time)
|
57
|
+
sleep(10)
|
58
|
+
new_time == Time.now # ==> true
|
59
|
+
|
60
|
+
Timecop.return # "turn off" Timecop
|
61
|
+
Timecop.travel(new_time)
|
62
|
+
sleep(10)
|
63
|
+
new_time == Time.now # ==> false
|
64
|
+
|
65
|
+
== DEPENDENCIES
|
66
|
+
|
67
|
+
* None
|
68
|
+
|
69
|
+
== INSTALL
|
70
|
+
|
71
|
+
* sudo gem install timecop-cache
|
72
|
+
|
73
|
+
== REFERENCES
|
74
|
+
|
75
|
+
* "0.2.0 release":http://blog.smartlogicsolutions.com/2008/12/24/timecop-2-released-freeze-and-rebase-time-ruby/
|
76
|
+
* "0.1.0 release":http://blog.smartlogicsolutions.com/2008/11/19/timecop-freeze-time-in-ruby-for-better-testing/
|
data/Rakefile
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'rake/rdoctask'
|
4
|
+
|
5
|
+
gem 'jeweler', '~> 1.2.1'
|
6
|
+
|
7
|
+
begin
|
8
|
+
require 'jeweler'
|
9
|
+
Jeweler::Tasks.new do |s|
|
10
|
+
s.name = "timecop"
|
11
|
+
s.rubyforge_project = 'johntrupiano' # if different than lowercase project name
|
12
|
+
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. This fork uses cache files. Different processes can use time cop. It is meant to be used with Culerity.)
|
13
|
+
s.summary = s.description # More details later??
|
14
|
+
s.email = "zan@liangzan.net"
|
15
|
+
s.homepage = "http://github.com/jtrupiano/timecop"
|
16
|
+
s.authors = ["John Trupiano", "Wong Liang Zan"]
|
17
|
+
s.files = FileList["[A-Z]*", "{bin,lib,test}/**/*"]
|
18
|
+
end
|
19
|
+
Jeweler::RubyforgeTasks.new do |rubyforge|
|
20
|
+
rubyforge.doc_task = "rdoc"
|
21
|
+
rubyforge.remote_doc_path = "timecop"
|
22
|
+
end
|
23
|
+
rescue LoadError
|
24
|
+
puts "Jeweler, or one of its dependencies, is not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
25
|
+
end
|
26
|
+
|
27
|
+
Dir['tasks/**/*.rake'].each do |rake|
|
28
|
+
begin
|
29
|
+
load rake
|
30
|
+
rescue LoadError
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
|
data/VERSION.yml
ADDED
data/lib/timecop.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
|
2
|
+
class Timecop
|
3
|
+
# Simply a data class for carrying around "time movement" objects. Makes it easy to keep track of the time
|
4
|
+
# movements on a simple stack.
|
5
|
+
class StackItem #:nodoc:
|
6
|
+
|
7
|
+
attr_reader :mock_type, :year, :month, :day, :hour, :minute, :second
|
8
|
+
def initialize(mock_type, year, month, day, hour, minute, second)
|
9
|
+
@mock_type, @year, @month, @day, @hour, @minute, @second = mock_type, year, month, day, hour, minute, second
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,143 @@
|
|
1
|
+
#--
|
2
|
+
# 1. Extensions to the Time, Date, and DateTime objects
|
3
|
+
# 2. Allows us to "freeze" time in our Ruby applications.
|
4
|
+
# 3. This is very useful when your app's functionality is dependent on time (e.g.
|
5
|
+
# anything that might expire). This will allow us to alter the return value of
|
6
|
+
# Date.today, Time.now, and DateTime.now, such that our application code _never_ has to change.
|
7
|
+
|
8
|
+
class Time #:nodoc:
|
9
|
+
class << self
|
10
|
+
# Time we might be behaving as
|
11
|
+
#attr_reader :mock_time
|
12
|
+
|
13
|
+
TIME_CACHE_PATH = File.expand_path('~/.timecop-cache.time.cache')
|
14
|
+
OFFSET_CACHE_PATH = File.expand_path('~/.timecop-cache.offset.cache')
|
15
|
+
|
16
|
+
def clear_mock_cache
|
17
|
+
clear_mock_time_cache
|
18
|
+
clear_mock_offset_cache
|
19
|
+
end
|
20
|
+
|
21
|
+
def mock_time_cache
|
22
|
+
if File.exist?(TIME_CACHE_PATH)
|
23
|
+
File.open(TIME_CACHE_PATH,'r') do |f|
|
24
|
+
Marshal.load(f)
|
25
|
+
end
|
26
|
+
else
|
27
|
+
nil
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def set_mock_time_cache(new_now)
|
32
|
+
File.open(TIME_CACHE_PATH,'w') do |f|
|
33
|
+
Marshal.dump(new_now, f)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def clear_mock_time_cache
|
38
|
+
File.delete(TIME_CACHE_PATH) if File.exist?(TIME_CACHE_PATH)
|
39
|
+
end
|
40
|
+
|
41
|
+
def mock_offset_cache
|
42
|
+
if File.exist?(OFFSET_CACHE_PATH)
|
43
|
+
File.open(OFFSET_CACHE_PATH,'r') do |f|
|
44
|
+
Marshal.load(f)
|
45
|
+
end
|
46
|
+
else
|
47
|
+
nil
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def set_mock_offset_cache(new_offset)
|
52
|
+
File.open(OFFSET_CACHE_PATH,'w') do |f|
|
53
|
+
Marshal.dump(new_offset, f)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def clear_mock_offset_cache
|
58
|
+
File.delete(OFFSET_CACHE_PATH) if File.exist?(OFFSET_CACHE_PATH)
|
59
|
+
end
|
60
|
+
|
61
|
+
def mock_time
|
62
|
+
unless mock_offset_cache.nil?
|
63
|
+
now_without_mock_time - mock_offset_cache
|
64
|
+
else
|
65
|
+
mock_time_cache
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# Set new time to pretend we are.
|
70
|
+
def freeze_time(new_now)
|
71
|
+
set_mock_time_cache(new_now)
|
72
|
+
clear_mock_offset_cache
|
73
|
+
end
|
74
|
+
|
75
|
+
def move_time(new_now)
|
76
|
+
mock_offset = new_now.nil? ? nil : (now_without_mock_time - new_now)
|
77
|
+
set_mock_offset_cache(mock_offset)
|
78
|
+
clear_mock_time_cache
|
79
|
+
end
|
80
|
+
|
81
|
+
# Restores Time to system clock
|
82
|
+
def unmock!
|
83
|
+
move_time(nil)
|
84
|
+
end
|
85
|
+
|
86
|
+
# Alias the original now
|
87
|
+
alias_method :now_without_mock_time, :now
|
88
|
+
|
89
|
+
# Define now_with_mock_time
|
90
|
+
def now_with_mock_time
|
91
|
+
mock_time || now_without_mock_time
|
92
|
+
end
|
93
|
+
|
94
|
+
# Alias now to now_with_mock_time
|
95
|
+
alias_method :now, :now_with_mock_time
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
if Object.const_defined?(:Date)
|
100
|
+
class Date #:nodoc:
|
101
|
+
class << self
|
102
|
+
def mock_date
|
103
|
+
now = Time.mock_time
|
104
|
+
return nil if now.nil?
|
105
|
+
Date.new(now.year, now.month, now.day)
|
106
|
+
end
|
107
|
+
|
108
|
+
# Alias the original today
|
109
|
+
alias_method :today_without_mock_date, :today
|
110
|
+
|
111
|
+
# Define today_with_mock_date
|
112
|
+
def today_with_mock_date
|
113
|
+
mock_date || today_without_mock_date
|
114
|
+
end
|
115
|
+
|
116
|
+
# Alias today to today_with_mock_date
|
117
|
+
alias_method :today, :today_with_mock_date
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
if Object.const_defined?(:DateTime)
|
123
|
+
class DateTime #:nodoc:
|
124
|
+
class << self
|
125
|
+
def mock_time
|
126
|
+
t_now = Time.mock_time
|
127
|
+
return nil if t_now.nil?
|
128
|
+
DateTime.new(t_now.year, t_now.month, t_now.day, t_now.hour, t_now.min, t_now.sec)
|
129
|
+
end
|
130
|
+
|
131
|
+
# Alias the original now
|
132
|
+
alias_method :now_without_mock_time, :now
|
133
|
+
|
134
|
+
# Define now_with_mock_time
|
135
|
+
def now_with_mock_time
|
136
|
+
mock_time || now_without_mock_time
|
137
|
+
end
|
138
|
+
|
139
|
+
# Alias now to now_with_mock_time
|
140
|
+
alias_method :now, :now_with_mock_time
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
@@ -0,0 +1,179 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
require File.join(File.dirname(__FILE__), 'time_extensions')
|
3
|
+
require File.join(File.dirname(__FILE__), 'stack_item')
|
4
|
+
|
5
|
+
# Timecop
|
6
|
+
# * Wrapper class for manipulating the extensions to the Time, Date, and DateTime objects
|
7
|
+
# * Allows us to "freeze" time in our Ruby applications.
|
8
|
+
# * Optionally allows time travel to simulate a running clock, such time is not technically frozen.
|
9
|
+
#
|
10
|
+
# This is very useful when your app's functionality is dependent on time (e.g.
|
11
|
+
# anything that might expire). This will allow us to alter the return value of
|
12
|
+
# Date.today, Time.now, and DateTime.now, such that our application code _never_ has to change.
|
13
|
+
class Timecop
|
14
|
+
include Singleton
|
15
|
+
|
16
|
+
# Allows you to run a block of code and "fake" a time throughout the execution of that block.
|
17
|
+
# This is particularly useful for writing test methods where the passage of time is critical to the business
|
18
|
+
# logic being tested. For example:
|
19
|
+
#
|
20
|
+
# joe = User.find(1)
|
21
|
+
# joe.purchase_home()
|
22
|
+
# assert !joe.mortgage_due?
|
23
|
+
# Timecop.freeze(2008, 10, 5) do
|
24
|
+
# assert joe.mortgage_due?
|
25
|
+
# end
|
26
|
+
#
|
27
|
+
# freeze and travel will respond to several different arguments:
|
28
|
+
# 1. Timecop.freeze(time_inst)
|
29
|
+
# 2. Timecop.freeze(datetime_inst)
|
30
|
+
# 3. Timecop.freeze(date_inst)
|
31
|
+
# 4. Timecop.freeze(offset_in_seconds)
|
32
|
+
# 5. Timecop.freeze(year, month, day, hour=0, minute=0, second=0)
|
33
|
+
#
|
34
|
+
# When a block is also passed, Time.now, DateTime.now and Date.today are all reset to their
|
35
|
+
# previous values after the block has finished executing. This allows us to nest multiple
|
36
|
+
# calls to Timecop.travel and have each block maintain it's concept of "now."
|
37
|
+
#
|
38
|
+
# * Note: Timecop.freeze will actually freeze time. This can cause unanticipated problems if
|
39
|
+
# benchmark or other timing calls are executed, which implicitly expect Time to actually move
|
40
|
+
# forward.
|
41
|
+
#
|
42
|
+
# * Rails Users: Be especially careful when setting this in your development environment in a
|
43
|
+
# rails project. Generators will load your environment, including the migration generator,
|
44
|
+
# which will lead to files being generated with the timestamp set by the Timecop.freeze call
|
45
|
+
# in your dev environment
|
46
|
+
#
|
47
|
+
# Returns the frozen time.
|
48
|
+
def self.freeze(*args, &block)
|
49
|
+
instance().send(:travel, :freeze, *args, &block)
|
50
|
+
Time.now
|
51
|
+
end
|
52
|
+
|
53
|
+
# Allows you to run a block of code and "fake" a time throughout the execution of that block.
|
54
|
+
# See Timecop#freeze for a sample of how to use (same exact usage syntax)
|
55
|
+
#
|
56
|
+
# * Note: Timecop.travel will not freeze time (as opposed to Timecop.freeze). This is a particularly
|
57
|
+
# good candidate for use in environment files in rails projects.
|
58
|
+
#
|
59
|
+
# Returns the 'new' current Time.
|
60
|
+
def self.travel(*args, &block)
|
61
|
+
instance().send(:travel, :move, *args, &block)
|
62
|
+
Time.now
|
63
|
+
end
|
64
|
+
|
65
|
+
# Reverts back to system's Time.now, Date.today and DateTime.now (if it exists). If freeze_all or rebase_all
|
66
|
+
# was never called in the first place, this method will have no effect.
|
67
|
+
#
|
68
|
+
# Returns Time.now, which is now the real current time.
|
69
|
+
def self.return
|
70
|
+
instance().send(:unmock!)
|
71
|
+
Time.now
|
72
|
+
end
|
73
|
+
|
74
|
+
protected
|
75
|
+
|
76
|
+
def initialize #:nodoc:
|
77
|
+
@_stack = []
|
78
|
+
Time.clear_mock_cache
|
79
|
+
end
|
80
|
+
|
81
|
+
def travel(mock_type, *args, &block) #:nodoc:
|
82
|
+
# parse the arguments, build our base time units
|
83
|
+
year, month, day, hour, minute, second = parse_travel_args(*args)
|
84
|
+
|
85
|
+
# perform our action
|
86
|
+
if mock_type == :freeze
|
87
|
+
freeze_all(year, month, day, hour, minute, second)
|
88
|
+
else
|
89
|
+
move_all(year, month, day, hour, minute, second)
|
90
|
+
end
|
91
|
+
# store this time traveling on our stack...
|
92
|
+
@_stack << StackItem.new(mock_type, year, month, day, hour, minute, second)
|
93
|
+
|
94
|
+
if block_given?
|
95
|
+
begin
|
96
|
+
yield
|
97
|
+
ensure
|
98
|
+
# pull it off the stack...
|
99
|
+
stack_item = @_stack.pop
|
100
|
+
if @_stack.size == 0
|
101
|
+
# completely unmock if there's nothing to revert back to
|
102
|
+
unmock!
|
103
|
+
else
|
104
|
+
# or reinstantiate the new the top of the stack (could be a :freeze or a :move)
|
105
|
+
new_top = @_stack.last
|
106
|
+
if new_top.mock_type == :freeze
|
107
|
+
freeze_all(new_top.year, new_top.month, new_top.day, new_top.hour, new_top.minute, new_top.second)
|
108
|
+
else
|
109
|
+
move_all(new_top.year, new_top.month, new_top.day, new_top.hour, new_top.minute, new_top.second)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def unmock! #:nodoc:
|
117
|
+
@_stack = []
|
118
|
+
Time.unmock!
|
119
|
+
end
|
120
|
+
|
121
|
+
private
|
122
|
+
|
123
|
+
# Re-bases Time.now, Date.today and DateTime.now (if it exists) to use the time passed in.
|
124
|
+
# When using this method directly, it is up to the developer to call unset_all to return us
|
125
|
+
# to sanity.
|
126
|
+
#
|
127
|
+
# * If being consumed in a rails app, Time.zone.local will be used to instantiate the time.
|
128
|
+
# Otherwise, Time.local will be used.
|
129
|
+
def freeze_all(year, month, day, hour=0, minute=0, second=0)
|
130
|
+
if Time.respond_to?(:zone) && !Time.zone.nil?
|
131
|
+
# ActiveSupport loaded
|
132
|
+
time = Time.zone.local(year, month, day, hour, minute, second)
|
133
|
+
else
|
134
|
+
# ActiveSupport not loaded
|
135
|
+
time = Time.local(year, month, day, hour, minute, second)
|
136
|
+
end
|
137
|
+
|
138
|
+
Time.freeze_time(time)
|
139
|
+
end
|
140
|
+
|
141
|
+
# Re-bases Time.now, Date.today and DateTime.now to use the time passed in and to continue moving time
|
142
|
+
# forward. When using this method directly, it is up to the developer to call return to return us to
|
143
|
+
# sanity.
|
144
|
+
#
|
145
|
+
# * If being consumed in a rails app, Time.zone.local will be used to instantiate the time.
|
146
|
+
# Otherwise, Time.local will be used.
|
147
|
+
def move_all(year, month, day, hour=0, minute=0, second=0)
|
148
|
+
if Time.respond_to?(:zone) && !Time.zone.nil?
|
149
|
+
# ActiveSupport loaded
|
150
|
+
time = Time.zone.local(year, month, day, hour, minute, second)
|
151
|
+
else
|
152
|
+
# ActiveSupport not loaded
|
153
|
+
time = Time.local(year, month, day, hour, minute, second)
|
154
|
+
end
|
155
|
+
|
156
|
+
Time.move_time(time)
|
157
|
+
end
|
158
|
+
|
159
|
+
def parse_travel_args(*args)
|
160
|
+
arg = args.shift
|
161
|
+
if arg.is_a?(Time) || (Object.const_defined?(:DateTime) && arg.is_a?(DateTime))
|
162
|
+
year, month, day, hour, minute, second = arg.year, arg.month, arg.day, arg.hour, arg.min, arg.sec
|
163
|
+
elsif Object.const_defined?(:Date) && arg.is_a?(Date)
|
164
|
+
year, month, day, hour, minute, second = arg.year, arg.month, arg.day, 0, 0, 0
|
165
|
+
#puts "#{year}-#{month}-#{day} #{hour}:#{minute}:#{second}"
|
166
|
+
elsif args.empty? && arg.kind_of?(Integer)
|
167
|
+
t = Time.now + arg
|
168
|
+
year, month, day, hour, minute, second = t.year, t.month, t.day, t.hour, t.min, t.sec
|
169
|
+
else # we'll just assume it's a list of y/m/h/d/m/s
|
170
|
+
year = arg || 0
|
171
|
+
month = args.shift || 1
|
172
|
+
day = args.shift || 1
|
173
|
+
hour = args.shift || 0
|
174
|
+
minute = args.shift || 0
|
175
|
+
second = args.shift || 0
|
176
|
+
end
|
177
|
+
return year, month, day, hour, minute, second
|
178
|
+
end
|
179
|
+
end
|
data/test/run_tests.sh
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
|
3
|
+
echo "\033[1;81m Running test_timecop_internals...\033[0m"
|
4
|
+
ruby test_timecop_internals.rb || (echo "FAILED!!!!!!!!!!!!")
|
5
|
+
|
6
|
+
echo "\033[1;81m Running test_timecop_without_date...\033[0m"
|
7
|
+
ruby test_timecop_without_date.rb || (echo "FAILED!!!!!!!!!!!!")
|
8
|
+
|
9
|
+
echo "\033[1;81m Running test_timecop...\033[0m"
|
10
|
+
ruby test_timecop.rb || (echo "FAILED!!!!!!!!!!!!")
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,228 @@
|
|
1
|
+
require 'date'
|
2
|
+
require File.join(File.dirname(__FILE__), 'test_helper')
|
3
|
+
|
4
|
+
class TestTimecop < Test::Unit::TestCase
|
5
|
+
|
6
|
+
def setup
|
7
|
+
|
8
|
+
end
|
9
|
+
|
10
|
+
# just in case...let's really make sure that Timecop is disabled between tests...
|
11
|
+
def teardown
|
12
|
+
Timecop.return
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_freeze_changes_and_resets_time
|
16
|
+
# depending on how we're invoked (individually or via the rake test suite)
|
17
|
+
assert !Time.respond_to?(:zone) || Time.zone.nil?
|
18
|
+
|
19
|
+
t = Time.local(2008, 10, 10, 10, 10, 10)
|
20
|
+
assert_not_equal t, Time.now
|
21
|
+
Timecop.freeze(2008, 10, 10, 10, 10, 10) do
|
22
|
+
assert_equal t, Time.now
|
23
|
+
end
|
24
|
+
assert_not_equal t, Time.now
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_freeze_then_return_unsets_mock_time
|
28
|
+
Timecop.freeze(1)
|
29
|
+
Timecop.return
|
30
|
+
assert_nil Time.send(:mock_time)
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_travel_then_return_unsets_mock_time
|
34
|
+
Timecop.travel(1)
|
35
|
+
Timecop.return
|
36
|
+
assert_nil Time.send(:mock_time)
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_freeze_with_block_unsets_mock_time
|
40
|
+
assert_nil Time.send(:mock_time), "test is invalid"
|
41
|
+
Timecop.freeze(1) do; end
|
42
|
+
assert_nil Time.send(:mock_time)
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_travel_with_block_unsets_mock_time
|
46
|
+
assert_nil Time.send(:mock_time), "test is invalid"
|
47
|
+
Timecop.travel(1) do; end
|
48
|
+
assert_nil Time.send(:mock_time)
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_recursive_freeze
|
52
|
+
t = Time.local(2008, 10, 10, 10, 10, 10)
|
53
|
+
Timecop.freeze(2008, 10, 10, 10, 10, 10) do
|
54
|
+
assert_equal t, Time.now
|
55
|
+
t2 = Time.local(2008, 9, 9, 9, 9, 9)
|
56
|
+
Timecop.freeze(2008, 9, 9, 9, 9, 9) do
|
57
|
+
assert_equal t2, Time.now
|
58
|
+
end
|
59
|
+
assert_equal t, Time.now
|
60
|
+
end
|
61
|
+
assert_not_equal t, Time.now
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_freeze_with_time_instance_works_as_expected
|
65
|
+
t = Time.local(2008, 10, 10, 10, 10, 10)
|
66
|
+
Timecop.freeze(t) do
|
67
|
+
assert_equal t, Time.now
|
68
|
+
assert_equal DateTime.new(2008, 10, 10, 10, 10, 10), DateTime.now
|
69
|
+
assert_equal Date.new(2008, 10, 10), Date.today
|
70
|
+
end
|
71
|
+
assert_not_equal t, Time.now
|
72
|
+
assert_not_equal DateTime.new(2008, 10, 10, 10, 10, 10), DateTime.now
|
73
|
+
assert_not_equal Date.new(2008, 10, 10), Date.today
|
74
|
+
end
|
75
|
+
|
76
|
+
def test_freeze_with_datetime_instance_works_as_expected
|
77
|
+
t = DateTime.new(2008, 10, 10, 10, 10, 10)
|
78
|
+
Timecop.freeze(t) do
|
79
|
+
assert_equal t, DateTime.now
|
80
|
+
assert_equal Time.local(2008, 10, 10, 10, 10, 10), Time.now
|
81
|
+
assert_equal Date.new(2008, 10, 10), Date.today
|
82
|
+
end
|
83
|
+
assert_not_equal t, DateTime.now
|
84
|
+
assert_not_equal Time.local(2008, 10, 10, 10, 10, 10), Time.now
|
85
|
+
assert_not_equal Date.new(2008, 10, 10), Date.today
|
86
|
+
end
|
87
|
+
|
88
|
+
def test_freeze_with_date_instance_works_as_expected
|
89
|
+
d = Date.new(2008, 10, 10)
|
90
|
+
Timecop.freeze(d) do
|
91
|
+
assert_equal d, Date.today
|
92
|
+
assert_equal Time.local(2008, 10, 10, 0, 0, 0), Time.now
|
93
|
+
assert_equal DateTime.new(2008, 10, 10, 0, 0, 0), DateTime.now
|
94
|
+
end
|
95
|
+
assert_not_equal d, Date.today
|
96
|
+
assert_not_equal Time.local(2008, 10, 10, 0, 0, 0), Time.now
|
97
|
+
assert_not_equal DateTime.new(2008, 10, 10, 0, 0, 0), DateTime.now
|
98
|
+
end
|
99
|
+
|
100
|
+
def test_freeze_with_integer_instance_works_as_expected
|
101
|
+
t = Time.local(2008, 10, 10, 10, 10, 10)
|
102
|
+
Timecop.freeze(t) do
|
103
|
+
assert_equal t, Time.now
|
104
|
+
assert_equal DateTime.new(2008, 10, 10, 10, 10, 10), DateTime.now
|
105
|
+
assert_equal Date.new(2008, 10, 10), Date.today
|
106
|
+
Timecop.freeze(10) do
|
107
|
+
assert_equal t + 10, Time.now
|
108
|
+
assert_equal Time.local(2008, 10, 10, 10, 10, 20), Time.now
|
109
|
+
assert_equal Date.new(2008, 10, 10), Date.today
|
110
|
+
end
|
111
|
+
end
|
112
|
+
assert_not_equal t, Time.now
|
113
|
+
assert_not_equal DateTime.new(2008, 10, 10, 10, 10, 10), DateTime.now
|
114
|
+
assert_not_equal Date.new(2008, 10, 10), Date.today
|
115
|
+
end
|
116
|
+
|
117
|
+
def test_exception_thrown_in_freeze_block_properly_resets_time
|
118
|
+
t = Time.local(2008, 10, 10, 10, 10, 10)
|
119
|
+
begin
|
120
|
+
Timecop.freeze(t) do
|
121
|
+
assert_equal t, Time.now
|
122
|
+
raise "blah exception"
|
123
|
+
end
|
124
|
+
rescue
|
125
|
+
assert_not_equal t, Time.now
|
126
|
+
assert_nil Time.send(:mock_time)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def test_freeze_freezes_time
|
131
|
+
t = Time.local(2008, 10, 10, 10, 10, 10)
|
132
|
+
now = Time.now
|
133
|
+
Timecop.freeze(t) do
|
134
|
+
#assert Time.now < now, "If we had failed to freeze, time would have proceeded, which is what appears to have happened."
|
135
|
+
new_t, new_d, new_dt = Time.now, Date.today, DateTime.now
|
136
|
+
assert_equal t, new_t, "Failed to freeze time." # 2 seconds
|
137
|
+
#sleep(10)
|
138
|
+
assert_equal new_t, Time.now
|
139
|
+
assert_equal new_d, Date.today
|
140
|
+
assert_equal new_dt, DateTime.now
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
def test_travel_keeps_time_moving
|
145
|
+
t = Time.local(2008, 10, 10, 10, 10, 10)
|
146
|
+
now = Time.now
|
147
|
+
Timecop.travel(t) do
|
148
|
+
#assert Time.now < now, "If we had failed to freeze, time would have proceeded, which is what appears to have happened."
|
149
|
+
assert Time.now - t < 2000, "Looks like we failed to actually travel time" # 2 seconds
|
150
|
+
new_t = Time.now
|
151
|
+
#sleep(10)
|
152
|
+
assert_not_equal new_t, Time.now
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
def test_recursive_rebasing_maintains_each_context
|
157
|
+
t = Time.local(2008, 10, 10, 10, 10, 10)
|
158
|
+
Timecop.travel(2008, 10, 10, 10, 10, 10) do
|
159
|
+
assert((t - Time.now).abs < 50, "Failed to travel time.")
|
160
|
+
t2 = Time.local(2008, 9, 9, 9, 9, 9)
|
161
|
+
Timecop.travel(2008, 9, 9, 9, 9, 9) do
|
162
|
+
assert((t2 - Time.now) < 50, "Failed to travel time.")
|
163
|
+
assert((t - Time.now) > 1000, "Failed to travel time.")
|
164
|
+
end
|
165
|
+
assert((t - Time.now).abs < 2000, "Failed to restore previously-traveled time.")
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
def test_recursive_travel_then_freeze
|
170
|
+
t = Time.local(2008, 10, 10, 10, 10, 10)
|
171
|
+
Timecop.travel(2008, 10, 10, 10, 10, 10) do
|
172
|
+
assert((t - Time.now).abs < 50, "Failed to travel time.")
|
173
|
+
t2 = Time.local(2008, 9, 9, 9, 9, 9)
|
174
|
+
Timecop.freeze(2008, 9, 9, 9, 9, 9) do
|
175
|
+
assert_equal t2, Time.now
|
176
|
+
end
|
177
|
+
assert((t - Time.now).abs < 2000, "Failed to restore previously-traveled time.")
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
def test_recursive_freeze_then_travel
|
182
|
+
t = Time.local(2008, 10, 10, 10, 10, 10)
|
183
|
+
Timecop.freeze(t) do
|
184
|
+
assert_equal t, Time.now
|
185
|
+
t2 = Time.local(2008, 9, 9, 9, 9, 9)
|
186
|
+
Timecop.travel(t2) do
|
187
|
+
assert((t2 - Time.now) < 50, "Failed to travel time.")
|
188
|
+
assert((t - Time.now) > 1000, "Failed to travel time.")
|
189
|
+
end
|
190
|
+
assert_equal t, Time.now
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
def test_return_values_are_Time_instances
|
195
|
+
assert Timecop.freeze.is_a?(Time)
|
196
|
+
assert Timecop.travel.is_a?(Time)
|
197
|
+
assert Timecop.return.is_a?(Time)
|
198
|
+
end
|
199
|
+
|
200
|
+
def test_travel_time_returns_passed_value
|
201
|
+
t_future = Time.local(2030, 10, 10, 10, 10, 10)
|
202
|
+
t_travel = Timecop.travel t_future
|
203
|
+
assert times_effectively_equal(t_future, t_travel)
|
204
|
+
end
|
205
|
+
|
206
|
+
def test_freeze_time_returns_passed_value
|
207
|
+
t_future = Time.local(2030, 10, 10, 10, 10, 10)
|
208
|
+
t_frozen = Timecop.freeze t_future
|
209
|
+
assert times_effectively_equal(t_future, t_frozen)
|
210
|
+
end
|
211
|
+
|
212
|
+
def test_return_time_returns_actual_time
|
213
|
+
t_real = Time.now
|
214
|
+
Timecop.freeze Time.local(2030, 10, 10, 10, 10, 10)
|
215
|
+
t_return = Timecop.return
|
216
|
+
assert times_effectively_equal(t_real, t_return)
|
217
|
+
end
|
218
|
+
|
219
|
+
|
220
|
+
private
|
221
|
+
|
222
|
+
# Tests to see that two times are within the given distance,
|
223
|
+
# in seconds, from each other.
|
224
|
+
def times_effectively_equal(time1, time2, seconds_interval = 1)
|
225
|
+
(time1.to_i - time2.to_i).abs <= seconds_interval
|
226
|
+
end
|
227
|
+
|
228
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'date'
|
2
|
+
require File.join(File.dirname(__FILE__), 'test_helper')
|
3
|
+
|
4
|
+
class TestTimecopInternals < Test::Unit::TestCase
|
5
|
+
|
6
|
+
def test_parse_travel_args_with_time
|
7
|
+
t = Time.now
|
8
|
+
y, m, d, h, min, s = t.year, t.month, t.day, t.hour, t.min, t.sec
|
9
|
+
ty, tm, td, th, tmin, ts = Timecop.instance().send(:parse_travel_args, t)
|
10
|
+
assert_equal y, ty
|
11
|
+
assert_equal m, tm
|
12
|
+
assert_equal d, td
|
13
|
+
assert_equal h, th
|
14
|
+
assert_equal min, tmin
|
15
|
+
assert_equal s, ts
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_parse_travel_args_with_datetime
|
19
|
+
t = DateTime.now
|
20
|
+
y, m, d, h, min, s = t.year, t.month, t.day, t.hour, t.min, t.sec
|
21
|
+
ty, tm, td, th, tmin, ts = Timecop.instance().send(:parse_travel_args, t)
|
22
|
+
assert_equal y, ty
|
23
|
+
assert_equal m, tm
|
24
|
+
assert_equal d, td
|
25
|
+
assert_equal h, th
|
26
|
+
assert_equal min, tmin
|
27
|
+
assert_equal s, ts
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_parse_travel_args_with_date
|
31
|
+
date = Date.today
|
32
|
+
y, m, d, h, min, s = date.year, date.month, date.day, 0, 0, 0
|
33
|
+
ty, tm, td, th, tmin, ts = Timecop.instance().send(:parse_travel_args, date)
|
34
|
+
assert_equal y, ty
|
35
|
+
assert_equal m, tm
|
36
|
+
assert_equal d, td
|
37
|
+
assert_equal h, th
|
38
|
+
assert_equal min, tmin
|
39
|
+
assert_equal s, ts
|
40
|
+
end
|
41
|
+
|
42
|
+
# Due to the nature of this test (calling Time.now once in this test and
|
43
|
+
# once in #parse_travel_args), this test may fail when two subsequent calls
|
44
|
+
# to Time.now return a different second.
|
45
|
+
def test_parse_travel_args_with_integer
|
46
|
+
t = Time.now
|
47
|
+
y, m, d, h, min, s = t.year, t.month, t.day, t.hour, t.min, t.sec
|
48
|
+
ty, tm, td, th, tmin, ts = Timecop.instance().send(:parse_travel_args, 0)
|
49
|
+
assert_equal y, ty
|
50
|
+
assert_equal m, tm
|
51
|
+
assert_equal d, td
|
52
|
+
assert_equal h, th
|
53
|
+
assert_equal min, tmin
|
54
|
+
assert_equal s, ts
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_parse_travel_args_with_individual_arguments
|
58
|
+
y, m, d, h, min, s = 2008, 10, 10, 10, 10, 10
|
59
|
+
ty, tm, td, th, tmin, ts = Timecop.instance().send(:parse_travel_args, y, m, d, h, min, s)
|
60
|
+
assert_equal y, ty
|
61
|
+
assert_equal m, tm
|
62
|
+
assert_equal d, td
|
63
|
+
assert_equal h, th
|
64
|
+
assert_equal min, tmin
|
65
|
+
assert_equal s, ts
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'test_helper')
|
2
|
+
|
3
|
+
class TestTimecopWithouDate < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
assert !Object.const_defined?(:Date)
|
7
|
+
assert !Object.const_defined?(:DateTime)
|
8
|
+
end
|
9
|
+
|
10
|
+
# just in case...let's really make sure that Timecop is disabled between tests...
|
11
|
+
def teardown
|
12
|
+
Timecop.return
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_freeze_changes_and_resets_time
|
16
|
+
# depending on how we're invoked (individually or via the rake test suite)
|
17
|
+
assert !Time.respond_to?(:zone) || Time.zone.nil?
|
18
|
+
|
19
|
+
t = Time.local(2008, 10, 10, 10, 10, 10)
|
20
|
+
assert_not_equal t, Time.now
|
21
|
+
Timecop.freeze(2008, 10, 10, 10, 10, 10) do
|
22
|
+
assert_equal t, Time.now
|
23
|
+
end
|
24
|
+
assert_not_equal t, Time.now
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_recursive_freeze
|
28
|
+
t = Time.local(2008, 10, 10, 10, 10, 10)
|
29
|
+
Timecop.freeze(2008, 10, 10, 10, 10, 10) do
|
30
|
+
assert_equal t, Time.now
|
31
|
+
t2 = Time.local(2008, 9, 9, 9, 9, 9)
|
32
|
+
Timecop.freeze(2008, 9, 9, 9, 9, 9) do
|
33
|
+
assert_equal t2, Time.now
|
34
|
+
end
|
35
|
+
assert_equal t, Time.now
|
36
|
+
end
|
37
|
+
assert_nil Time.send(:mock_time)
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_exception_thrown_in_freeze_block_properly_resets_time
|
41
|
+
t = Time.local(2008, 10, 10, 10, 10, 10)
|
42
|
+
begin
|
43
|
+
Timecop.freeze(t) do
|
44
|
+
assert_equal t, Time.now
|
45
|
+
raise "blah exception"
|
46
|
+
end
|
47
|
+
rescue
|
48
|
+
assert_not_equal t, Time.now
|
49
|
+
assert_nil Time.send(:mock_time)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_freeze_freezes_time
|
54
|
+
t = Time.local(2008, 10, 10, 10, 10, 10)
|
55
|
+
now = Time.now
|
56
|
+
Timecop.freeze(t) do
|
57
|
+
#assert Time.now < now, "If we had failed to freeze, time would have proceeded, which is what appears to have happened."
|
58
|
+
new_t = Time.now
|
59
|
+
assert_equal t, new_t, "Failed to change move time." # 2 seconds
|
60
|
+
#sleep(10)
|
61
|
+
assert_equal new_t, Time.now
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_travel_keeps_time_moving
|
66
|
+
t = Time.local(2008, 10, 10, 10, 10, 10)
|
67
|
+
now = Time.now
|
68
|
+
Timecop.travel(t) do
|
69
|
+
#assert Time.now < now, "If we had failed to freeze, time would have proceeded, which is what appears to have happened."
|
70
|
+
assert Time.now - t < 2000, "Looks like we failed to actually travel time" # 2 seconds
|
71
|
+
new_t = Time.now
|
72
|
+
#sleep(10)
|
73
|
+
assert_not_equal new_t, Time.now
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_recursive_rebasing_maintains_each_context
|
78
|
+
t = Time.local(2008, 10, 10, 10, 10, 10)
|
79
|
+
Timecop.travel(2008, 10, 10, 10, 10, 10) do
|
80
|
+
assert((t - Time.now).abs < 50, "Failed to travel time.")
|
81
|
+
t2 = Time.local(2008, 9, 9, 9, 9, 9)
|
82
|
+
Timecop.travel(2008, 9, 9, 9, 9, 9) do
|
83
|
+
assert((t2 - Time.now) < 50, "Failed to travel time.")
|
84
|
+
assert((t - Time.now) > 1000, "Failed to travel time.")
|
85
|
+
end
|
86
|
+
assert((t - Time.now).abs < 2000, "Failed to restore previously-traveled time.")
|
87
|
+
end
|
88
|
+
assert_nil Time.send(:mock_time)
|
89
|
+
end
|
90
|
+
|
91
|
+
def test_recursive_travel_then_freeze
|
92
|
+
t = Time.local(2008, 10, 10, 10, 10, 10)
|
93
|
+
Timecop.travel(2008, 10, 10, 10, 10, 10) do
|
94
|
+
assert((t - Time.now).abs < 50, "Failed to travel time.")
|
95
|
+
t2 = Time.local(2008, 9, 9, 9, 9, 9)
|
96
|
+
Timecop.freeze(2008, 9, 9, 9, 9, 9) do
|
97
|
+
assert_equal t2, Time.now
|
98
|
+
end
|
99
|
+
assert((t - Time.now).abs < 2000, "Failed to restore previously-traveled time.")
|
100
|
+
end
|
101
|
+
assert_nil Time.send(:mock_time)
|
102
|
+
end
|
103
|
+
|
104
|
+
def test_recursive_freeze_then_travel
|
105
|
+
t = Time.local(2008, 10, 10, 10, 10, 10)
|
106
|
+
Timecop.freeze(t) do
|
107
|
+
assert_equal t, Time.now
|
108
|
+
t2 = Time.local(2008, 9, 9, 9, 9, 9)
|
109
|
+
Timecop.travel(t2) do
|
110
|
+
assert((t2 - Time.now) < 50, "Failed to travel time.")
|
111
|
+
assert((t - Time.now) > 1000, "Failed to travel time.")
|
112
|
+
end
|
113
|
+
assert_equal t, Time.now
|
114
|
+
end
|
115
|
+
assert_nil Time.send(:mock_time)
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
metadata
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: liangzan-timecop
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.3.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- John Trupiano
|
8
|
+
- Wong Liang Zan
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2009-09-23 00:00:00 -07:00
|
14
|
+
default_executable:
|
15
|
+
dependencies: []
|
16
|
+
|
17
|
+
description: 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. This fork uses cache files. Different processes can use time cop. It is meant to be used with Culerity.
|
18
|
+
email: zan@liangzan.net
|
19
|
+
executables: []
|
20
|
+
|
21
|
+
extensions: []
|
22
|
+
|
23
|
+
extra_rdoc_files:
|
24
|
+
- LICENSE
|
25
|
+
- README.rdoc
|
26
|
+
files:
|
27
|
+
- History.txt
|
28
|
+
- LICENSE
|
29
|
+
- README.rdoc
|
30
|
+
- Rakefile
|
31
|
+
- VERSION.yml
|
32
|
+
- lib/timecop.rb
|
33
|
+
- lib/timecop/stack_item.rb
|
34
|
+
- lib/timecop/time_extensions.rb
|
35
|
+
- lib/timecop/timecop.rb
|
36
|
+
- test/run_tests.sh
|
37
|
+
- test/test_helper.rb
|
38
|
+
- test/test_timecop.rb
|
39
|
+
- test/test_timecop_internals.rb
|
40
|
+
- test/test_timecop_without_date.rb
|
41
|
+
has_rdoc: false
|
42
|
+
homepage: http://github.com/jtrupiano/timecop
|
43
|
+
licenses:
|
44
|
+
post_install_message:
|
45
|
+
rdoc_options:
|
46
|
+
- --charset=UTF-8
|
47
|
+
require_paths:
|
48
|
+
- lib
|
49
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: "0"
|
54
|
+
version:
|
55
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - ">="
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: "0"
|
60
|
+
version:
|
61
|
+
requirements: []
|
62
|
+
|
63
|
+
rubyforge_project: johntrupiano
|
64
|
+
rubygems_version: 1.3.5
|
65
|
+
signing_key:
|
66
|
+
specification_version: 3
|
67
|
+
summary: 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. This fork uses cache files. Different processes can use time cop. It is meant to be used with Culerity.
|
68
|
+
test_files:
|
69
|
+
- test/test_timecop_internals.rb
|
70
|
+
- test/test_timecop.rb
|
71
|
+
- test/test_timecop_without_date.rb
|
72
|
+
- test/test_helper.rb
|