rufus-scheduler 2.0.24 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.txt +6 -0
- data/CREDITS.txt +4 -0
- data/README.md +1064 -0
- data/Rakefile +1 -4
- data/TODO.txt +145 -55
- data/lib/rufus/scheduler.rb +502 -26
- data/lib/rufus/{sc → scheduler}/cronline.rb +46 -17
- data/lib/rufus/{sc/version.rb → scheduler/job_array.rb} +56 -4
- data/lib/rufus/scheduler/jobs.rb +548 -0
- data/lib/rufus/scheduler/util.rb +318 -0
- data/rufus-scheduler.gemspec +30 -4
- data/spec/cronline_spec.rb +29 -8
- data/spec/error_spec.rb +116 -0
- data/spec/job_array_spec.rb +39 -0
- data/spec/job_at_spec.rb +58 -0
- data/spec/job_cron_spec.rb +67 -0
- data/spec/job_every_spec.rb +71 -0
- data/spec/job_in_spec.rb +20 -0
- data/spec/job_interval_spec.rb +68 -0
- data/spec/job_repeat_spec.rb +308 -0
- data/spec/job_spec.rb +387 -115
- data/spec/lockfile_spec.rb +61 -0
- data/spec/parse_spec.rb +203 -0
- data/spec/schedule_at_spec.rb +129 -0
- data/spec/schedule_cron_spec.rb +66 -0
- data/spec/schedule_every_spec.rb +109 -0
- data/spec/schedule_in_spec.rb +80 -0
- data/spec/schedule_interval_spec.rb +128 -0
- data/spec/scheduler_spec.rb +831 -124
- data/spec/spec_helper.rb +65 -0
- data/spec/threads_spec.rb +75 -0
- metadata +64 -59
- data/README.rdoc +0 -661
- data/lib/rufus/otime.rb +0 -3
- data/lib/rufus/sc/jobqueues.rb +0 -160
- data/lib/rufus/sc/jobs.rb +0 -471
- data/lib/rufus/sc/rtime.rb +0 -363
- data/lib/rufus/sc/scheduler.rb +0 -636
- data/spec/at_in_spec.rb +0 -47
- data/spec/at_spec.rb +0 -125
- data/spec/blocking_spec.rb +0 -64
- data/spec/cron_spec.rb +0 -134
- data/spec/every_spec.rb +0 -304
- data/spec/exception_spec.rb +0 -113
- data/spec/in_spec.rb +0 -150
- data/spec/mutex_spec.rb +0 -159
- data/spec/rtime_spec.rb +0 -137
- data/spec/schedulable_spec.rb +0 -97
- data/spec/spec_base.rb +0 -87
- data/spec/stress_schedule_unschedule_spec.rb +0 -159
- data/spec/timeout_spec.rb +0 -148
- data/test/kjw.rb +0 -113
- data/test/t.rb +0 -20
data/spec/exception_spec.rb
DELETED
@@ -1,113 +0,0 @@
|
|
1
|
-
#
|
2
|
-
# Specifying rufus-scheduler
|
3
|
-
#
|
4
|
-
# Mon May 4 17:07:17 JST 2009
|
5
|
-
#
|
6
|
-
|
7
|
-
require 'spec_base'
|
8
|
-
|
9
|
-
|
10
|
-
describe SCHEDULER_CLASS do
|
11
|
-
|
12
|
-
before(:each) do
|
13
|
-
@s = start_scheduler
|
14
|
-
end
|
15
|
-
after(:each) do
|
16
|
-
stop_scheduler(@s)
|
17
|
-
end
|
18
|
-
|
19
|
-
it 'emits exception messages to stderr' do
|
20
|
-
|
21
|
-
require 'stringio' unless defined?(StringIO) # ruby 1.9
|
22
|
-
|
23
|
-
stderr = $stderr
|
24
|
-
s = StringIO.new
|
25
|
-
$stderr = s
|
26
|
-
|
27
|
-
@s.in 0.400 do
|
28
|
-
raise 'Houston we have a problem'
|
29
|
-
end
|
30
|
-
|
31
|
-
sleep 0.500
|
32
|
-
sleep 0.500
|
33
|
-
$stderr = stderr
|
34
|
-
s.close
|
35
|
-
|
36
|
-
s.string.should match(/Houston we have a problem/)
|
37
|
-
end
|
38
|
-
|
39
|
-
it 'accepts custom handling of exceptions' do
|
40
|
-
|
41
|
-
$job = nil
|
42
|
-
|
43
|
-
def @s.handle_exception(j, e)
|
44
|
-
$job = j
|
45
|
-
end
|
46
|
-
|
47
|
-
@s.in 0.400 do
|
48
|
-
raise 'Houston we have a problem'
|
49
|
-
end
|
50
|
-
|
51
|
-
sleep 0.500
|
52
|
-
sleep 0.500
|
53
|
-
|
54
|
-
$job.class.should == Rufus::Scheduler::InJob
|
55
|
-
end
|
56
|
-
|
57
|
-
it 'accepts defining #log_exception' do
|
58
|
-
|
59
|
-
$e = nil
|
60
|
-
|
61
|
-
def @s.log_exception(e)
|
62
|
-
$e = e
|
63
|
-
end
|
64
|
-
|
65
|
-
@s.in 0.400 do
|
66
|
-
raise 'Houston we have a problem'
|
67
|
-
end
|
68
|
-
|
69
|
-
sleep 0.500
|
70
|
-
sleep 0.500
|
71
|
-
|
72
|
-
$e.to_s.should == 'Houston we have a problem'
|
73
|
-
end
|
74
|
-
|
75
|
-
it 'accepts defining #on_exception' do
|
76
|
-
|
77
|
-
$j = nil
|
78
|
-
$e = nil
|
79
|
-
|
80
|
-
def @s.on_exception(j, e)
|
81
|
-
$j = j
|
82
|
-
$e = e
|
83
|
-
end
|
84
|
-
|
85
|
-
@s.in 0.400 do
|
86
|
-
raise 'Houston we have a problem'
|
87
|
-
end
|
88
|
-
|
89
|
-
sleep 0.500
|
90
|
-
sleep 0.500
|
91
|
-
|
92
|
-
$j.class.should == Rufus::Scheduler::InJob
|
93
|
-
$e.to_s.should == 'Houston we have a problem'
|
94
|
-
end
|
95
|
-
|
96
|
-
it 'allow custom exception rescue' do
|
97
|
-
@s.options[:exception]= StandardError
|
98
|
-
|
99
|
-
job = @s.in 0 do
|
100
|
-
exit
|
101
|
-
end
|
102
|
-
|
103
|
-
@e= nil
|
104
|
-
begin
|
105
|
-
wait_next_tick
|
106
|
-
rescue SystemExit => e
|
107
|
-
@e= e
|
108
|
-
end
|
109
|
-
|
110
|
-
@e.should_not == nil
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
data/spec/in_spec.rb
DELETED
@@ -1,150 +0,0 @@
|
|
1
|
-
|
2
|
-
#
|
3
|
-
# Specifying rufus-scheduler
|
4
|
-
#
|
5
|
-
# Sat Mar 21 17:36:36 JST 2009
|
6
|
-
#
|
7
|
-
|
8
|
-
require 'spec_base'
|
9
|
-
|
10
|
-
|
11
|
-
describe "#{SCHEDULER_CLASS}#in" do
|
12
|
-
|
13
|
-
before(:each) do
|
14
|
-
@s = start_scheduler
|
15
|
-
end
|
16
|
-
after(:each) do
|
17
|
-
stop_scheduler(@s)
|
18
|
-
end
|
19
|
-
|
20
|
-
it 'has job ids with the class name in it' do
|
21
|
-
|
22
|
-
j0 = @s.in(1) {}
|
23
|
-
j0.job_id.should match(/Rufus::Scheduler::InJob/)
|
24
|
-
end
|
25
|
-
|
26
|
-
it 'tracks scheduled in jobs' do
|
27
|
-
|
28
|
-
@s.in(1) {}
|
29
|
-
|
30
|
-
wait_next_tick
|
31
|
-
@s.jobs.size.should == 1
|
32
|
-
|
33
|
-
sleep 1.5
|
34
|
-
|
35
|
-
@s.jobs.size.should == 0
|
36
|
-
end
|
37
|
-
|
38
|
-
it 'schedules in 1' do
|
39
|
-
|
40
|
-
var = nil
|
41
|
-
|
42
|
-
@s.in 1 do
|
43
|
-
var = true
|
44
|
-
end
|
45
|
-
|
46
|
-
var.should == nil
|
47
|
-
sleep 1.5
|
48
|
-
|
49
|
-
var.should == true
|
50
|
-
end
|
51
|
-
|
52
|
-
it 'schedules in 1.0' do
|
53
|
-
|
54
|
-
var = nil
|
55
|
-
|
56
|
-
@s.in 1.0 do
|
57
|
-
var = true
|
58
|
-
end
|
59
|
-
|
60
|
-
var.should == nil
|
61
|
-
sleep 1.5
|
62
|
-
|
63
|
-
var.should == true
|
64
|
-
end
|
65
|
-
|
66
|
-
it 'schedules in 1s' do
|
67
|
-
|
68
|
-
var = nil
|
69
|
-
|
70
|
-
@s.in '1s' do
|
71
|
-
var = true
|
72
|
-
end
|
73
|
-
|
74
|
-
var.should == nil
|
75
|
-
sleep 1.5
|
76
|
-
|
77
|
-
var.should == true
|
78
|
-
end
|
79
|
-
|
80
|
-
it 'returns the new job' do
|
81
|
-
|
82
|
-
r = @s.in '1s' do
|
83
|
-
end
|
84
|
-
|
85
|
-
r.class.should == Rufus::Scheduler::InJob
|
86
|
-
end
|
87
|
-
|
88
|
-
it 'triggers [almost] immediately jobs in the past' do
|
89
|
-
|
90
|
-
var = nil
|
91
|
-
|
92
|
-
r = @s.in -2 do
|
93
|
-
var = true
|
94
|
-
end
|
95
|
-
|
96
|
-
#wait_next_tick
|
97
|
-
sleep 0.550
|
98
|
-
|
99
|
-
r.class.should == Rufus::Scheduler::InJob
|
100
|
-
var.should == true
|
101
|
-
@s.jobs.should == {}
|
102
|
-
end
|
103
|
-
|
104
|
-
it 'does not trigger jobs in the past when :discard_past => true' do
|
105
|
-
|
106
|
-
var = nil
|
107
|
-
|
108
|
-
r = @s.in -2, :discard_past => true do
|
109
|
-
var = true
|
110
|
-
end
|
111
|
-
|
112
|
-
r.should == nil
|
113
|
-
var.should == nil
|
114
|
-
@s.jobs.should == {}
|
115
|
-
end
|
116
|
-
|
117
|
-
it 'unschedules jobs' do
|
118
|
-
|
119
|
-
job = @s.in '2d' do
|
120
|
-
end
|
121
|
-
|
122
|
-
wait_next_tick
|
123
|
-
|
124
|
-
@s.jobs.size.should == 1
|
125
|
-
|
126
|
-
@s.unschedule(job.job_id)
|
127
|
-
|
128
|
-
@s.jobs.size.should == 0
|
129
|
-
end
|
130
|
-
|
131
|
-
it 'accepts tags for jobs' do
|
132
|
-
|
133
|
-
job = @s.in '2d', :tags => 'spec' do
|
134
|
-
end
|
135
|
-
|
136
|
-
wait_next_tick
|
137
|
-
|
138
|
-
@s.find_by_tag('spec').size.should == 1
|
139
|
-
@s.find_by_tag('spec').first.job_id.should == job.job_id
|
140
|
-
end
|
141
|
-
|
142
|
-
it 'raises on unknown options' do
|
143
|
-
|
144
|
-
lambda {
|
145
|
-
@s.in '2d', :first_at => (Time.now + 3600).to_s do
|
146
|
-
end
|
147
|
-
}.should raise_error(ArgumentError)
|
148
|
-
end
|
149
|
-
end
|
150
|
-
|
data/spec/mutex_spec.rb
DELETED
@@ -1,159 +0,0 @@
|
|
1
|
-
|
2
|
-
#
|
3
|
-
# Specifying rufus-scheduler
|
4
|
-
#
|
5
|
-
# Fri Oct 7 17:30:45 JST 2011
|
6
|
-
#
|
7
|
-
|
8
|
-
require 'spec_base'
|
9
|
-
|
10
|
-
|
11
|
-
describe SCHEDULER_CLASS do
|
12
|
-
|
13
|
-
before(:each) do
|
14
|
-
@s = start_scheduler
|
15
|
-
end
|
16
|
-
after(:each) do
|
17
|
-
stop_scheduler(@s)
|
18
|
-
end
|
19
|
-
|
20
|
-
MJOB = Proc.new do |x|
|
21
|
-
begin
|
22
|
-
$var << "in#{x}"
|
23
|
-
sleep 0.500
|
24
|
-
$var << "out#{x}"
|
25
|
-
rescue Exception => e
|
26
|
-
puts '=' * 80
|
27
|
-
p e
|
28
|
-
puts '=' * 80
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
context ':mutex => String' do
|
33
|
-
|
34
|
-
it 'prevents overlapping' do
|
35
|
-
|
36
|
-
$var = ''
|
37
|
-
|
38
|
-
@s.in('1s', :mutex => 'toto') { MJOB.call(0) }
|
39
|
-
@s.in('1s', :mutex => 'toto') { MJOB.call(1) }
|
40
|
-
|
41
|
-
sleep 3.0
|
42
|
-
|
43
|
-
%w[ in0out0in1out1 in1out1in0out0 ].should include($var)
|
44
|
-
end
|
45
|
-
|
46
|
-
it 'creates a new mutex when the name is first encountered' do
|
47
|
-
|
48
|
-
@s.instance_variable_get(:@mutexes).size.should == 0
|
49
|
-
|
50
|
-
@s.in('1s', :mutex => 'fruit') { sleep 0.1 }
|
51
|
-
|
52
|
-
sleep 1.5
|
53
|
-
|
54
|
-
@s.instance_variable_get(:@mutexes).size.should == 1
|
55
|
-
end
|
56
|
-
|
57
|
-
it 'creates a unique mutex for a given name' do
|
58
|
-
|
59
|
-
@s.in('1s', :mutex => 'gum') { sleep 0.1 }
|
60
|
-
@s.in('1s', :mutex => 'gum') { sleep 0.1 }
|
61
|
-
|
62
|
-
sleep 1.5
|
63
|
-
|
64
|
-
@s.instance_variable_get(:@mutexes).size.should == 1
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
context ':mutex => Mutex' do
|
69
|
-
|
70
|
-
it 'prevents overlapping' do
|
71
|
-
|
72
|
-
$var = ''
|
73
|
-
m = Mutex.new
|
74
|
-
|
75
|
-
@s.in('1s', :mutex => m) { MJOB.call(0) }
|
76
|
-
@s.in('1s', :mutex => m) { MJOB.call(1) }
|
77
|
-
|
78
|
-
sleep 3.0
|
79
|
-
|
80
|
-
%w[ in0out0in1out1 in1out1in0out0 ].should include($var)
|
81
|
-
end
|
82
|
-
|
83
|
-
it 'does not register the mutex' do
|
84
|
-
|
85
|
-
@s.in('1s', :mutex => Mutex.new) { sleep 0.1 }
|
86
|
-
|
87
|
-
sleep 1.5
|
88
|
-
|
89
|
-
@s.instance_variable_get(:@mutexes).size.should == 0
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
context ':mutexes => Array of String' do
|
94
|
-
|
95
|
-
it 'ensure exclusivity' do
|
96
|
-
|
97
|
-
$var = ''
|
98
|
-
m0 = 'm0'
|
99
|
-
m1 = 'm1'
|
100
|
-
|
101
|
-
@s.in('1s', :mutex => m0) { MJOB.call(0) }
|
102
|
-
@s.in('1s', :mutex => m1) { MJOB.call(1) }
|
103
|
-
@s.in('1s', :mutex => [m0, m1]) { MJOB.call(2) }
|
104
|
-
|
105
|
-
sleep 4.5
|
106
|
-
|
107
|
-
$var.should include('in2out2')
|
108
|
-
end
|
109
|
-
|
110
|
-
it 'creates new mutexes when the names are first encountered' do
|
111
|
-
|
112
|
-
@s.instance_variable_get(:@mutexes).size.should == 0
|
113
|
-
|
114
|
-
@s.in('1s', :mutex => ['fruit', 'bread']) { sleep 0.1 }
|
115
|
-
|
116
|
-
sleep 1.5
|
117
|
-
|
118
|
-
@s.instance_variable_get(:@mutexes).size.should == 2
|
119
|
-
end
|
120
|
-
|
121
|
-
it 'creates a unique mutex for a given name' do
|
122
|
-
|
123
|
-
@s.in('1s', :mutex => ['fruit', 'bread']) { sleep 0.1 }
|
124
|
-
@s.in('1s', :mutex => ['fruit', 'bread']) { sleep 0.1 }
|
125
|
-
|
126
|
-
sleep 1.5
|
127
|
-
|
128
|
-
@s.instance_variable_get(:@mutexes).size.should == 2
|
129
|
-
end
|
130
|
-
end
|
131
|
-
|
132
|
-
context ':mutexes => Array of Mutex' do
|
133
|
-
|
134
|
-
it 'ensure exclusivity' do
|
135
|
-
|
136
|
-
$var = ''
|
137
|
-
m0 = Mutex.new
|
138
|
-
m1 = Mutex.new
|
139
|
-
|
140
|
-
@s.in('1s', :mutex => m0) { MJOB.call(0) }
|
141
|
-
@s.in('1s', :mutex => m1) { MJOB.call(1) }
|
142
|
-
@s.in('1s', :mutex => [m0, m1]) { MJOB.call(2) }
|
143
|
-
|
144
|
-
sleep 4.5
|
145
|
-
|
146
|
-
$var.should include('in2out2')
|
147
|
-
end
|
148
|
-
|
149
|
-
it 'does not register the mutexes' do
|
150
|
-
|
151
|
-
@s.in('1s', :mutex => [Mutex.new, Mutex.new]) { sleep 0.1 }
|
152
|
-
|
153
|
-
sleep 1.5
|
154
|
-
|
155
|
-
@s.instance_variable_get(:@mutexes).size.should == 0
|
156
|
-
end
|
157
|
-
end
|
158
|
-
end
|
159
|
-
|
data/spec/rtime_spec.rb
DELETED
@@ -1,137 +0,0 @@
|
|
1
|
-
|
2
|
-
#
|
3
|
-
# Specifying rufus-scheduler
|
4
|
-
#
|
5
|
-
# Fri Mar 20 23:46:32 JST 2009
|
6
|
-
#
|
7
|
-
|
8
|
-
require 'spec_base'
|
9
|
-
|
10
|
-
|
11
|
-
describe 'rufus/rtime' do
|
12
|
-
|
13
|
-
def pts(s)
|
14
|
-
Rufus.parse_time_string(s)
|
15
|
-
end
|
16
|
-
|
17
|
-
def tts(f, opts={})
|
18
|
-
Rufus.to_time_string(f, opts)
|
19
|
-
end
|
20
|
-
|
21
|
-
def tdh(f, opts={})
|
22
|
-
Rufus.to_duration_hash(f, opts)
|
23
|
-
end
|
24
|
-
|
25
|
-
it 'parses duration strings' do
|
26
|
-
|
27
|
-
pts('-1.0d1.0w1.0d').should == -777600.0
|
28
|
-
pts('-1d1w1d').should == -777600.0
|
29
|
-
pts('-1w2d').should == -777600.0
|
30
|
-
pts('-1h10s').should == -3610.0
|
31
|
-
pts('-1h').should == -3600.0
|
32
|
-
pts('-5.').should == -5.0
|
33
|
-
pts('-2.5s').should == -2.5
|
34
|
-
pts('-1s').should == -1.0
|
35
|
-
pts('-500').should == -0.5
|
36
|
-
pts('').should == 0.0
|
37
|
-
pts('5.0').should == 5.0
|
38
|
-
pts('0.5').should == 0.5
|
39
|
-
pts('.5').should == 0.5
|
40
|
-
pts('5.').should == 5.0
|
41
|
-
pts('500').should == 0.5
|
42
|
-
pts('1000').should == 1.0
|
43
|
-
pts('1').should == 0.001
|
44
|
-
pts('1s').should == 1.0
|
45
|
-
pts('2.5s').should == 2.5
|
46
|
-
pts('1h').should == 3600.0
|
47
|
-
pts('1h10s').should == 3610.0
|
48
|
-
pts('1w2d').should == 777600.0
|
49
|
-
pts('1d1w1d').should == 777600.0
|
50
|
-
pts('1.0d1.0w1.0d').should == 777600.0
|
51
|
-
|
52
|
-
pts('.5m').should == 30.0
|
53
|
-
pts('5.m').should == 300.0
|
54
|
-
pts('1m.5s').should == 60.5
|
55
|
-
pts('-.5m').should == -30.0
|
56
|
-
|
57
|
-
pts('1d').should == 86400.0
|
58
|
-
pts('0.1d').should == 8640.0
|
59
|
-
pts('0.1s').should == 0.1
|
60
|
-
|
61
|
-
pts('0.1').should == 0.1
|
62
|
-
pts('1').should == 0.001
|
63
|
-
#
|
64
|
-
# the two evil twins :-(
|
65
|
-
end
|
66
|
-
|
67
|
-
it 'parses duration "strings"' do
|
68
|
-
|
69
|
-
o = Object.new
|
70
|
-
def o.to_s; '-2'; end
|
71
|
-
|
72
|
-
pts(o).should == -0.002
|
73
|
-
end
|
74
|
-
|
75
|
-
it 'raises on wrong duration strings' do
|
76
|
-
|
77
|
-
lambda { pts('-') }.should raise_error(ArgumentError)
|
78
|
-
lambda { pts('h') }.should raise_error(ArgumentError)
|
79
|
-
lambda { pts('whatever') }.should raise_error(ArgumentError)
|
80
|
-
lambda { pts('hms') }.should raise_error(ArgumentError)
|
81
|
-
|
82
|
-
lambda { pts(' 1h ') }.should raise_error(ArgumentError)
|
83
|
-
end
|
84
|
-
|
85
|
-
it 'generates duration strings' do
|
86
|
-
|
87
|
-
tts(0).should == '0s'
|
88
|
-
tts(0, :drop_seconds => true).should == '0m'
|
89
|
-
tts(60).should == '1m'
|
90
|
-
tts(61).should == '1m1s'
|
91
|
-
tts(3661).should == '1h1m1s'
|
92
|
-
tts(24 * 3600).should == '1d'
|
93
|
-
tts(7 * 24 * 3600 + 1).should == '1w1s'
|
94
|
-
tts(30 * 24 * 3600 + 1).should == '4w2d1s'
|
95
|
-
tts(30 * 24 * 3600 + 1, :months => true).should == '1M1s'
|
96
|
-
end
|
97
|
-
|
98
|
-
it 'computes duration hashes' do
|
99
|
-
|
100
|
-
tdh(0).should == {}
|
101
|
-
tdh(0.128).should == { :ms => 128 }
|
102
|
-
tdh(60.127).should == { :m => 1, :ms => 127 }
|
103
|
-
tdh(61.127).should == { :m => 1, :s => 1, :ms => 127 }
|
104
|
-
tdh(61.127, :drop_seconds => true).should == { :m => 1 }
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
describe 'Rufus.at_to_f' do
|
109
|
-
|
110
|
-
def atf(o)
|
111
|
-
Rufus.at_to_f(o)
|
112
|
-
end
|
113
|
-
|
114
|
-
it 'turns Time at values to float' do
|
115
|
-
|
116
|
-
t = Time.now
|
117
|
-
tf = t.to_f.to_i.to_f
|
118
|
-
|
119
|
-
atf(t + 2).to_i.to_f.should == tf + 2
|
120
|
-
end
|
121
|
-
|
122
|
-
it 'turns String at values to float' do
|
123
|
-
|
124
|
-
atf('Sat Mar 21 20:08:01 +0900 2009').should == 1237633681.0
|
125
|
-
atf('Sat Mar 21 20:08:01 -0900 2009').should == 1237698481.0
|
126
|
-
atf('Sat Mar 21 20:08:01 +0000 2009').should == 1237666081.0
|
127
|
-
atf('Sat Mar 21 20:08:01 2009').should == 1237666081.0
|
128
|
-
atf('Mar 21 20:08:01 2009').should == 1237666081.0
|
129
|
-
atf('2009/03/21 20:08').should == 1237666080.0
|
130
|
-
end
|
131
|
-
|
132
|
-
it 'accepts integers' do
|
133
|
-
|
134
|
-
atf(1).should == 1.0
|
135
|
-
end
|
136
|
-
end
|
137
|
-
|