liangzan-timecop 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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.
@@ -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/
@@ -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
+
@@ -0,0 +1,4 @@
1
+ ---
2
+ :minor: 3
3
+ :patch: 1
4
+ :major: 0
@@ -0,0 +1,2 @@
1
+ # Require Timecop
2
+ require File.join(File.dirname(__FILE__), 'timecop', 'timecop')
@@ -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
@@ -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!!!!!!!!!!!!")
@@ -0,0 +1,2 @@
1
+ require 'test/unit'
2
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'timecop')
@@ -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