continuity 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,191 @@
1
+ require 'helper'
2
+ require 'minitest/autorun'
3
+ require 'continuity'
4
+
5
+ include Continuity
6
+
7
+ describe CronEntry do
8
+ describe "0 * * * * * (every minute)" do
9
+ before do
10
+ @ce_short = CronEntry.new("* * * * *")
11
+ @ce = CronEntry.new("0 * * * * *")
12
+ end
13
+
14
+ it "should run at 2010-12-20 00:00:00" do
15
+ @ce_short.at?(Time.parse("2010-12-20 00:00:00")).must_equal true
16
+ @ce.at?(Time.parse("2010-12-20 00:00:00")).must_equal true
17
+ end
18
+
19
+ it "should not run at 2010-12-20 00:00:01" do
20
+ @ce_short.at?(Time.parse("2010-12-20 00:00:01")).must_equal false
21
+ @ce.at?(Time.parse("2010-12-20 00:00:01")).must_equal false
22
+ end
23
+
24
+ it "should run 60 times in a one hour period" do
25
+ count = 0
26
+ start = Time.parse("2010-12-20 00:00:00").to_i
27
+ start.upto(start + 3599) do |t|
28
+ count += 1 if @ce_short.at?(Time.at(t))
29
+ count += 1 if @ce.at?(Time.at(t))
30
+ end
31
+ count.must_equal 120
32
+ end
33
+ end
34
+
35
+ describe "0 1 * * * * (every hour)" do
36
+ before do
37
+ @ce = CronEntry.new("0 1 * * * *")
38
+ end
39
+
40
+ it "should run at 2010-12-20 01:01:00" do
41
+ @ce.at?(Time.parse("2010-12-20 01:01:00")).must_equal true
42
+ end
43
+
44
+ it "should not run at 2010-12-20 00:01:01" do
45
+ @ce.at?(Time.parse("2010-12-20 00:01:01")).must_equal false
46
+ end
47
+
48
+ it "should run 24 times in a one day period" do
49
+ count = 0
50
+ start = Time.parse("2010-12-20 00:01:00").to_i
51
+ start.upto(start + 86399) do |t|
52
+ count += 1 if @ce.at?(Time.at(t))
53
+ end
54
+ count.must_equal 24
55
+ end
56
+ end
57
+
58
+ describe "0 0 0 1 * * (first of the month)" do
59
+ before do
60
+ @ce = CronEntry.new("0 0 0 1 * *")
61
+ end
62
+
63
+ it "should run at 2010-12-01 00:00:00" do
64
+ @ce.at?(Time.parse("2010-12-01 00:00:00")).must_equal true
65
+ end
66
+
67
+ it "should run at 2010-08-01 00:00:00" do
68
+ @ce.at?(Time.parse("2010-08-01 00:00:00")).must_equal true
69
+ end
70
+
71
+ it "should not run at 2010-12-02 00:00:00" do
72
+ @ce.at?(Time.parse("2010-12-02 00:00:00")).must_equal false
73
+ end
74
+
75
+ it "should not run at 2010-12-01 01:00:00" do
76
+ @ce.at?(Time.parse("2010-12-01 01:00:00")).must_equal false
77
+ end
78
+
79
+ it "should run 12 times in a year" do
80
+ count = 0
81
+ start = Time.parse("2010-01-01 00:00:00").to_i
82
+ year_end = Time.parse("2010-12-31 23:59:59").to_i
83
+ start.step(year_end, 3600) do |t|
84
+ if @ce.at?(Time.at(t))
85
+ count += 1
86
+ end
87
+ end
88
+ count.must_equal 12
89
+ end
90
+ end
91
+
92
+ describe "0 0 0 1 1,4,7,10 * (quarterly months)" do
93
+ before do
94
+ @ce = CronEntry.new("0 0 0 1 1,4,7,10 *")
95
+ end
96
+
97
+ it "should run at 2010-04-01 00:00:00" do
98
+ @ce.at?(Time.parse("2010-04-01 00:00:00")).must_equal true
99
+ end
100
+
101
+ it "should not run at 2010-03-01 00:00:00" do
102
+ @ce.at?(Time.parse("2010-03-01 00:00:00")).must_equal false
103
+ end
104
+
105
+ it "should run 4 times in a year" do
106
+ count = 0
107
+ start = Time.parse("2010-01-01 00:00:00").to_i
108
+ year_end = Time.parse("2010-12-31 23:59:59").to_i
109
+ start.step(year_end, 3600) do |t|
110
+ if @ce.at?(Time.at(t))
111
+ count += 1
112
+ end
113
+ end
114
+ count.must_equal 4
115
+ end
116
+ end
117
+
118
+ describe "0 0 7 * * 0 (sunday @ 7am)" do
119
+ before do
120
+ @ce = CronEntry.new("0 0 7 * * 0")
121
+ end
122
+
123
+ it "should run at 2010-12-19 07:00:00" do
124
+ @ce.at?(Time.parse("2010-12-19 07:00:00")).must_equal true
125
+ end
126
+
127
+ it "should run at 2010-12-26 07:00:00" do
128
+ @ce.at?(Time.parse("2010-12-26 07:00:00")).must_equal true
129
+ end
130
+
131
+ it "should not run at 2010-12-27 07:00:00" do
132
+ @ce.at?(Time.parse("2010-12-27 07:00:00")).must_equal false
133
+ end
134
+
135
+ it "should not run at 2010-12-26 06:00:00" do
136
+ @ce.at?(Time.parse("2010-12-26 06:00:00")).must_equal false
137
+ end
138
+ end
139
+
140
+ describe "ranges w/intervals" do
141
+ before do
142
+ # 10 * 20 * 3 = 600 times in a day
143
+ @ce = CronEntry.new("0-9/2,20-39/4 40-59/1 2,4,8 * * *")
144
+ end
145
+
146
+ it "should run at 2010-12-20 04:40:06" do
147
+ @ce.at?(Time.parse("2010-12-20 04:40:06")).must_equal true
148
+ end
149
+
150
+ it "should run at 2010-12-20 02:50:24" do
151
+ @ce.at?(Time.parse("2010-12-20 02:50:24")).must_equal true
152
+ end
153
+
154
+ it "should not run at 2010-12-20 03:50:22" do
155
+ @ce.at?(Time.parse("2010-12-20 03:50:22")).must_equal false
156
+ end
157
+
158
+ it "should run 600 times in a day" do
159
+ count = 0
160
+ start = Time.parse("2010-12-20 02:40:09").to_i
161
+ start.upto(start + 86399) do |t|
162
+ if @ce.at?(Time.at(t))
163
+ count += 1
164
+ end
165
+ end
166
+ count.must_equal 600
167
+ end
168
+ end
169
+
170
+ describe "invalid intervals" do
171
+ it "should raise CronFormatError on '1 2 3'" do
172
+ lambda { CronEntry.new("1 2 3") }.must_raise CronFormatError
173
+ end
174
+
175
+ it "should raise CronFormatError on '1 2 3 4 5 6 7'" do
176
+ lambda { CronEntry.new("1 2 3 4 5 6 7") }.must_raise CronFormatError
177
+ end
178
+
179
+ it "should raise CronFormatError on 'im not a cron task'" do
180
+ lambda { CronEntry.new("im not a cron task") }.must_raise CronFormatError
181
+ end
182
+
183
+ it "should raise CronFormatError on 'SrslyFake'" do
184
+ lambda { CronEntry.new("SrslyFake") }.must_raise CronFormatError
185
+ end
186
+
187
+ it "should raise CronFormatError on '0 0 0 0 0 0'" do
188
+ lambda { CronEntry.new("0 0 0 0 0 0") }.must_raise CronFormatError
189
+ end
190
+ end
191
+ end
@@ -0,0 +1,109 @@
1
+ require 'helper'
2
+ require 'minitest/autorun'
3
+ require 'continuity'
4
+
5
+ include Continuity
6
+
7
+ describe PeriodicEntry do
8
+ describe "10s" do
9
+ before do
10
+ @pe = PeriodicEntry.new("10s")
11
+ end
12
+
13
+ it "should trigger at Time.at(10)" do
14
+ assert @pe.at?(Time.at(10))
15
+ end
16
+
17
+ it "should trigger 6 times in a minute" do
18
+ times = 0
19
+
20
+ time = Time.parse("2010-12-21 00:01:00").to_i
21
+ time.upto(time + 59) do |n|
22
+ times += 1 if @pe.at?(Time.at(n))
23
+ end
24
+
25
+ times.must_equal 6
26
+ end
27
+ end
28
+
29
+ describe "1m" do
30
+ before do
31
+ @pe = PeriodicEntry.new("1m")
32
+ end
33
+
34
+ it "should trigger on the minute" do
35
+ time = Time.parse("2010-12-21 00:01:00").to_i
36
+
37
+ assert @pe.at?(time)
38
+ end
39
+
40
+ it "should trigger 60 times in a hour" do
41
+ times = 0
42
+
43
+ time = Time.parse("2010-12-21 00:00:00").to_i
44
+ time.upto(time + 3599) do |n|
45
+ times += 1 if @pe.at?(Time.at(n))
46
+ end
47
+
48
+ times.must_equal 60
49
+ end
50
+ end
51
+
52
+ describe "2h" do
53
+ before do
54
+ @pe = PeriodicEntry.new("2h")
55
+ end
56
+
57
+ it "should trigger at 2am" do
58
+ time = Time.parse("2010-12-21 02:00:00").to_i
59
+
60
+ assert @pe.at?(time)
61
+ end
62
+
63
+ it "should trigger 12 times in a 24hour period" do
64
+ times = 0
65
+
66
+ time = Time.parse("2010-12-21 00:00:00").to_i
67
+ time.upto(time + 86399) do |n|
68
+ times += 1 if @pe.at?(Time.at(n))
69
+ end
70
+
71
+ times.must_equal 12
72
+ end
73
+ end
74
+
75
+ describe "2d" do
76
+ before do
77
+ @pe = PeriodicEntry.new("2d")
78
+ end
79
+
80
+ it "should trigger 5 times in a 10day period" do
81
+ times = 0
82
+
83
+ time = Time.parse("2010-12-21 00:00:00").to_i
84
+ time.upto(time + (86400 * 10) - 1) do |n|
85
+ times += 1 if @pe.at?(Time.at(n))
86
+ end
87
+
88
+ times.must_equal 5
89
+ end
90
+ end
91
+
92
+ describe "1w" do
93
+ before do
94
+ @pe = PeriodicEntry.new("1w")
95
+ end
96
+
97
+ it "should trigger 4 times in 28 days" do
98
+ times = 0
99
+
100
+ time = Time.parse("2010-12-01 00:00:00").to_i
101
+ time_end = Time.parse("2010-12-27 23:59:59").to_i
102
+ time.upto(time_end) do |n|
103
+ times += 1 if @pe.at?(Time.at(n))
104
+ end
105
+
106
+ times.must_equal 4
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,62 @@
1
+ require 'helper'
2
+ require 'minitest/autorun'
3
+ require 'continuity'
4
+
5
+ include Continuity
6
+
7
+ def build_scheduler
8
+ redis = Redis.new(:port => 16379)
9
+ scheduler = Continuity::Scheduler.new_using_redis(redis)
10
+ scheduler.cron("*/10 * * * * *") do
11
+ end
12
+
13
+ scheduler.every("1m") do
14
+ end
15
+
16
+ scheduler
17
+ end
18
+
19
+ WORKER_COUNT = 100
20
+ MUTEX = Mutex.new
21
+ TEST_LENGTH = 60
22
+
23
+ describe "simulation" do
24
+ before do
25
+ redis = Redis.new(:port => 16379)
26
+ redis.flushall
27
+ end
28
+
29
+ it "should schedule a continuous range" do
30
+ @workers = []
31
+ last_scheduled = nil
32
+
33
+ WORKER_COUNT.times do
34
+
35
+ @workers << Thread.new do
36
+ s = build_scheduler
37
+
38
+ loop do
39
+ sleep rand(5)
40
+ range = s.maybe_schedule
41
+
42
+ if range
43
+ MUTEX.synchronize do
44
+ if last_scheduled.nil?
45
+ last_scheduled = range.last
46
+ else
47
+ assert_equal (last_scheduled + 1), range.first
48
+ last_scheduled = range.last
49
+ end
50
+ end
51
+ end
52
+ end
53
+
54
+ end
55
+
56
+ end
57
+
58
+ sleep TEST_LENGTH
59
+ @workers.each { |w| w.terminate }
60
+ assert last_scheduled > Time.now.to_i - 20
61
+ end
62
+ end
@@ -0,0 +1,146 @@
1
+ require 'helper'
2
+ require 'minitest/autorun'
3
+ require 'continuity'
4
+
5
+ describe Continuity::RedisBackend do
6
+ before do
7
+ @rb = Continuity::RedisBackend.new(redis_clean, 10, 30)
8
+ end
9
+
10
+ describe "bootstrapping" do
11
+ it "should set current time as the last scheduled at time" do
12
+ now = Time.now.to_i
13
+ @rb.lock_for_scheduling(now) {}
14
+ last_scheduled_at = @rb.lock_for_scheduling(now+1) {}
15
+ last_scheduled_at.must_equal now
16
+ end
17
+
18
+ it "should yield" do
19
+ yielded = false
20
+
21
+ now = Time.now.to_i
22
+ @rb.lock_for_scheduling(now) { yielded = true }
23
+
24
+ yielded.must_equal true
25
+ end
26
+ end
27
+
28
+ describe "trying to lock before scheduling period is over" do
29
+ before do
30
+ now = Time.now.to_i
31
+ @rb.lock_for_scheduling(now) {}
32
+ end
33
+
34
+ it "should not yield" do
35
+ now = Time.now.to_i
36
+ @rb.lock_for_scheduling(now) {}
37
+
38
+ yielded = false
39
+
40
+ @rb.lock_for_scheduling(now+5) { yielded = true }
41
+
42
+ yielded.must_equal false
43
+ end
44
+ end
45
+
46
+ describe "trying to lock while another client holds to lock" do
47
+ it "should not yield" do
48
+ first_yields = false
49
+ second_yields = false
50
+ now = Time.now.to_i
51
+ @rb.lock_for_scheduling(now) {}
52
+
53
+ @rb.lock_for_scheduling(now+30) do
54
+ first_yields = true
55
+ 20.times do
56
+ @rb.lock_for_scheduling(now+35) do
57
+ second_yields = true
58
+ end
59
+ end
60
+ end
61
+
62
+ first_yields.must_equal true
63
+ second_yields.must_equal false
64
+ end
65
+ end
66
+
67
+ describe "throwing exception in the block given to lock" do
68
+ it "should release lock" do
69
+ now = Time.now.to_i
70
+ @rb.lock_for_scheduling(now) {}
71
+
72
+ begin
73
+ @rb.lock_for_scheduling(now+30) do
74
+ raise StandardError
75
+ end
76
+ rescue
77
+ end
78
+
79
+ acquired_lock = false
80
+ @rb.lock_for_scheduling(now+30) do
81
+ acquired_lock = true
82
+ end
83
+
84
+ acquired_lock.must_equal true
85
+ end
86
+ end
87
+
88
+ describe "expired lock" do
89
+ it "should be acquireable" do
90
+ now = Time.now.to_i
91
+ @rb.lock_for_scheduling(now) {}
92
+
93
+ acquired_lock_early = false
94
+ acquired_lock = false
95
+
96
+ @rb.lock_for_scheduling(now+30) do
97
+ @rb.lock_for_scheduling(now+22) do
98
+ acquired_lock_early = true
99
+ end
100
+ @rb.lock_for_scheduling(now+62) do
101
+ acquired_lock = true
102
+ end
103
+ end
104
+
105
+ acquired_lock.must_equal true
106
+ acquired_lock_early.must_equal false
107
+ end
108
+ end
109
+
110
+ describe "locking after waiting period is up" do
111
+ it "should yield" do
112
+ now = Time.now.to_i
113
+ @rb.lock_for_scheduling(now) {}
114
+
115
+ yielded = false
116
+ @rb.lock_for_scheduling(now+15) { yielded = true }
117
+ yielded.must_equal true
118
+ end
119
+
120
+ it "should yield last scheduled time" do
121
+ now = Time.now.to_i
122
+ @rb.lock_for_scheduling(now) {}
123
+
124
+ yielded = false
125
+ @rb.lock_for_scheduling(now+11) { |t|
126
+ t.must_equal now
127
+ yielded = true
128
+ }
129
+ yielded.must_equal true
130
+ end
131
+
132
+ it "should continue to yield as time goes on" do
133
+ yielded_count = 0
134
+ now = Time.now.to_i
135
+ @rb.lock_for_scheduling(now) {}
136
+
137
+ 10.times do |n|
138
+ @rb.lock_for_scheduling(now+((n+1)*30)) do
139
+ yielded_count += 1
140
+ end
141
+ end
142
+
143
+ yielded_count.must_equal 10
144
+ end
145
+ end
146
+ end