omega-tariffs-base 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/spec/lib/init.rb ADDED
@@ -0,0 +1,5 @@
1
+ require 'spec'
2
+ require File.expand_path(File.join(File.dirname(__FILE__), 'spec_helper'))
3
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'lib', 'omega-tariffs-base'))
4
+
5
+ include UniqSysOmega::Tariffs
@@ -0,0 +1,9 @@
1
+ require 'mocha'
2
+ require 'timecop'
3
+ require File.expand_path(File.join(File.dirname(__FILE__), 'active_record_classes_stub'))
4
+
5
+ Spec::Runner.configure do |config|
6
+ config.mock_with :mocha
7
+ end
8
+
9
+ DOESNT_MATTER = nil
@@ -0,0 +1,287 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), 'lib', 'init'))
2
+
3
+ describe "PacketFilterRepository" do
4
+ before do
5
+ PacketFilterRepository.reset
6
+ @now = Time.now
7
+ end
8
+
9
+ it "should return nothing for non-existent regions" do
10
+ # yet unregistered region ...
11
+ PacketFilterRepository.region_registered?(1, 2).should == false
12
+ PacketFilterRepository.region_paid?(1, 2).should == false
13
+ end
14
+
15
+ it "should register regions" do
16
+ # register region
17
+ PacketFilterRepository.register_region(1, 2, @now, 3600)
18
+
19
+ # registered but not yet paid region ...
20
+ PacketFilterRepository.region_registered?(1, 2).should == true
21
+ PacketFilterRepository.region_paid?(1, 2).should == false
22
+ end
23
+
24
+ it "should register and commit payments" do
25
+ # register region
26
+ PacketFilterRepository.register_region(1, 2, @now, 3600)
27
+
28
+ # pay for the region ...
29
+ PacketFilterRepository.pay_region(1, 2)
30
+
31
+ # registered and paid region ...
32
+ PacketFilterRepository.region_registered?(1, 2).should == true
33
+ PacketFilterRepository.region_paid?(1, 2).should == true
34
+ end
35
+
36
+ it "should return false for other regions when current is paid" do
37
+ # register region
38
+ PacketFilterRepository.register_region(1, 2, @now, 3600)
39
+
40
+ # pay for the region ...
41
+ PacketFilterRepository.pay_region(1, 2)
42
+
43
+ # this is not the region ...
44
+ PacketFilterRepository.region_registered?(1, 2, @now-1).should == false
45
+ PacketFilterRepository.region_paid?(1, 2, @now-1).should == false
46
+
47
+ # this is still the region ...
48
+ PacketFilterRepository.region_registered?(1, 2, @now+1).should == true
49
+ PacketFilterRepository.region_paid?(1, 2, @now+1).should == true
50
+ end
51
+
52
+ it "should report spanning regions" do
53
+ # register region
54
+ PacketFilterRepository.register_region(1, 2, @now, 3600)
55
+
56
+ # check spanning
57
+ PacketFilterRepository.region_spans?(1, 2, @now, 1000).should == false
58
+ PacketFilterRepository.region_spans?(1, 2, @now, 3599).should == false
59
+ PacketFilterRepository.region_spans?(1, 2, @now, 3600).should == true
60
+ PacketFilterRepository.region_spans?(1, 2, @now, 5000).should == true
61
+ end
62
+
63
+ it "should not end by default" do
64
+ PacketFilterRepository.should_end?(1, 2).should == false
65
+ end
66
+
67
+ it "should_end call should return true" do
68
+ PacketFilterRepository.set_should_end(1, 2, @now+60).should == true
69
+ end
70
+
71
+ it "should end when it's scheduled" do
72
+ PacketFilterRepository.set_should_end(1, 2, @now+60)
73
+ PacketFilterRepository.should_end?(1, 2).should == false
74
+ Timecop.freeze(@now + 60) { PacketFilterRepository.should_end?(1, 2).should == false }
75
+ Timecop.freeze(@now + 61) { PacketFilterRepository.should_end?(1, 2).should == true }
76
+ end
77
+
78
+ it "should not interfere with the other users and tariffs" do
79
+ PacketFilterRepository.set_should_end(1, 2, @now-1)
80
+ PacketFilterRepository.should_end?(1, 2).should == true
81
+ PacketFilterRepository.should_end?(1, 3).should == false
82
+ PacketFilterRepository.should_end?(8, 2).should == false
83
+ end
84
+ end
85
+
86
+ describe "PacketFilter" do
87
+ before do
88
+ @settings = stub()
89
+ @settings.expects(:price).returns(100)
90
+ @settings.expects(:length).returns(3600)
91
+ @filter = PacketFilter.new(@settings, 1)
92
+
93
+ FinTransaction.reset_transactions
94
+ PacketFilterRepository.reset
95
+ Login.set_login_balance(1, 0)
96
+ end
97
+
98
+ describe "start_permitted?" do
99
+ it "should permit login if I have got close to enough money" do
100
+ Login.set_login_balance(1, 100)
101
+ @filter.start_permitted?(2, 1).should == true
102
+ end
103
+
104
+ it "should permit login if I have got enough money" do
105
+ Login.set_login_balance(1, 101)
106
+ @filter.start_permitted?(2, 1).should == true
107
+ end
108
+
109
+ it "should permit login if I haven't got enough money" do
110
+ Login.set_login_balance(1, 99)
111
+ @filter.start_permitted?(2, 1).should == false
112
+ end
113
+ end
114
+
115
+ describe "permitted?" do
116
+ it "should permit work if I have got close to enough money" do
117
+ Login.set_login_balance(1, 100)
118
+ @filter.permitted?(2, 1).should == true
119
+ end
120
+
121
+ it "should permit work if I have got enough money" do
122
+ Login.set_login_balance(1, 101)
123
+ @filter.permitted?(2, 1).should == true
124
+ end
125
+
126
+ it "should permit work if I haven't got enough money" do
127
+ Login.set_login_balance(1, 99)
128
+ @filter.permitted?(2, 1).should == false
129
+ end
130
+ end
131
+
132
+ def make_single_activity_processed
133
+ activity = Activity.new
134
+ activity.created_at = Time.now
135
+ activity.login_id = 1
136
+ activity.amount = 3600
137
+
138
+ ft = FinTransaction.template
139
+ ft.club_id, ft.author_id, ft.src_account_id, ft.dst_account_id = 1, 2, 3, 4
140
+
141
+ @filter.process_activity(activity, ft)
142
+ end
143
+
144
+ describe "calculate_cost" do
145
+ it "should return the price of the region unless paid" do
146
+ @filter.calculate_cost(2, 1, Time.now, 10).should == 100
147
+ @filter.calculate_cost(2, 1, Time.now, 3599).should == 100
148
+ @filter.calculate_cost(2, 1, Time.now, 3600).should == 100
149
+ @filter.calculate_cost(2, 1, Time.now, 3601).should == 100
150
+ end
151
+
152
+ it "should return the zero price of the region if paid and Integer::MAX out of the region" do
153
+ Login.set_login_balance(1, 100)
154
+
155
+ make_single_activity_processed.should == true
156
+
157
+ @filter.calculate_cost(2, 1, Time.now, 10).should == 0
158
+ @filter.calculate_cost(2, 1, Time.now, 3599).should == 0
159
+ @filter.calculate_cost(2, 1, Time.now, 3600).should == Integer::MAX
160
+ @filter.calculate_cost(2, 1, Time.now, 3605).should == Integer::MAX
161
+ end
162
+ end
163
+
164
+ describe "process_activity" do
165
+ it "should return unsuccessful activity processing if no money" do
166
+ Login.set_login_balance(1, 99)
167
+ make_single_activity_processed.should == false
168
+ end
169
+ end
170
+
171
+ describe "packet life time" do
172
+ def actualize_balance!
173
+ Login.set_login_balance(1, Login.find(1).balance - FinTransaction.transactions.sum)
174
+ FinTransaction.reset_transactions
175
+ end
176
+
177
+ def do_several_activities(offsets=[0])
178
+ ft = FinTransaction.template
179
+ ft.club_id, ft.author_id, ft.src_account_id, ft.dst_account_id = 1, 2, 3, 4
180
+
181
+ offsets.each do |offset|
182
+ activity = Activity.new
183
+ activity.created_at = Time.now + offset
184
+ activity.login_id = 1
185
+ activity.amount = 30
186
+ @filter.process_activity(activity, ft).should == true
187
+ end
188
+ end
189
+
190
+ it "should allow the packet to be opened once, if there's exact amount of money on the account as needed" do
191
+ now = Time.now
192
+
193
+ Timecop.freeze(now) do
194
+ Login.set_login_balance(1, 100)
195
+
196
+ @filter.start_permitted?(2, 1).should == true
197
+ @filter.permitted?(2, 1).should == true
198
+
199
+ Login.find(1).balance.should == 100
200
+ do_several_activities [ 0, 30, 60 ]
201
+ actualize_balance!
202
+ Login.find(1).balance.should == 0
203
+ end
204
+
205
+ [ [now + 1, true, true], [now + 3598, true, true], [now + 3599, false, false], [now + 3699, false, false]].each do |variant|
206
+ Timecop.freeze(variant[0]) do
207
+ @filter.start_permitted?(2, 1).should == variant[1]
208
+ @filter.permitted?(2, 1).should == variant[2]
209
+ end
210
+ end
211
+ end
212
+
213
+ it "should allow the packet to be opened once even if there's slightly more money on the account than needed" do
214
+ now = Time.now
215
+
216
+ Timecop.freeze(now) do
217
+ Login.set_login_balance(1, 105)
218
+
219
+ @filter.start_permitted?(2, 1).should == true
220
+ @filter.permitted?(2, 1).should == true
221
+
222
+ Login.find(1).balance.should == 105
223
+ do_several_activities [ 0, 30, 60 ]
224
+ actualize_balance!
225
+ Login.find(1).balance.should == 5
226
+ end
227
+
228
+ [ [now + 1, true, true], [now + 3598, true, true], [now + 3599, false, false], [now + 3699, false, false]].each do |variant|
229
+ Timecop.freeze(variant[0]) do
230
+ @filter.start_permitted?(2, 1).should == variant[1]
231
+ @filter.permitted?(2, 1).should == variant[2]
232
+ end
233
+ end
234
+ end
235
+
236
+ it "should allow the packet to be opened twice if there is enough money, and the user should be charged twice" do
237
+ now = Time.now
238
+
239
+ Timecop.freeze(now) do
240
+ Login.set_login_balance(1, 205)
241
+
242
+ @filter.start_permitted?(2, 1).should == true
243
+ @filter.permitted?(2, 1).should == true
244
+
245
+ Login.find(1).balance.should == 205
246
+ do_several_activities [ 0, 30, 60 ]
247
+ actualize_balance!
248
+ Login.find(1).balance.should == 105
249
+ end
250
+
251
+ # check end of the single session
252
+ [ [now + 1, true], [now + 3600, true], [now + 3601, false], [now + 3699, false]].each do |variant|
253
+ Timecop.freeze(variant[0]) do
254
+ @filter.permitted?(2, 1).should == variant[1]
255
+ end
256
+ end
257
+
258
+ # check if start_permitted? resets permitted? flag
259
+ [ [now + 1, true, true], [now + 3599, true, true], [now + 3600, true, true], [now + 3699, true, true]].each do |variant|
260
+ Timecop.freeze(variant[0]) do
261
+ @filter.start_permitted?(2, 1).should == variant[1]
262
+ @filter.permitted?(2, 1).should == variant[2]
263
+ end
264
+ end
265
+
266
+ now += 3610
267
+
268
+ Timecop.freeze(now) do
269
+ @filter.start_permitted?(2, 1).should == true
270
+ @filter.permitted?(2, 1).should == true
271
+
272
+ Login.find(1).balance.should == 105
273
+ do_several_activities [ 0, 30, 60 ]
274
+ actualize_balance!
275
+ Login.find(1).balance.should == 5
276
+ end
277
+
278
+ # check if permitted? and start_permitted? are in the correct state
279
+ [ [now + 1, true, true], [now + 3598, true, true], [now + 3599, false, false], [now + 3699, false, false]].each do |variant|
280
+ Timecop.freeze(variant[0]) do
281
+ @filter.start_permitted?(2, 1).should == variant[1]
282
+ @filter.permitted?(2, 1).should == variant[2]
283
+ end
284
+ end
285
+ end
286
+ end
287
+ end
@@ -0,0 +1,36 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), 'lib', 'init'))
2
+
3
+ describe "RateFilter" do
4
+ RATE = 123
5
+
6
+ before do
7
+ settings = mock()
8
+ settings.expects(:rate).returns(RATE)
9
+ @filter = RateFilter.new(settings, 0)
10
+ end
11
+
12
+ it "should permit start" do
13
+ @filter.start_permitted?(1, 2, 3).should == true
14
+ end
15
+
16
+ it "should permit going on" do
17
+ @filter.permitted?(1, 2, 3).should == true
18
+ end
19
+
20
+ it "should calculate the correct amount" do
21
+ @filter.calculate_cost(1, 2, 3, 3600).should == RATE
22
+ end
23
+
24
+ it "should process activity correctly" do
25
+ activity = mock()
26
+ activity.expects(:amount).returns(3600)
27
+
28
+ ft = FinTransaction.template
29
+ ft.club_id, ft.author_id, ft.src_account_id, ft.dst_account_id = 1, 2, 3, 4
30
+
31
+ FinTransaction.any_instance.expects(:volume=).with(RATE)
32
+ FinTransaction.any_instance.expects(:valid?).returns(true)
33
+
34
+ @filter.process_activity(activity, ft).should == true
35
+ end
36
+ end
@@ -0,0 +1,250 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), 'lib', 'init'))
2
+
3
+ class RepeatingMockFilter1 < Filter
4
+ def calculate_cost(computer_id, login_id, started_at, amount, options={})
5
+ Rational(amount.to_i*100, 3600)
6
+ end
7
+
8
+ def process_activity(unprocessed_activity, ft, options={})
9
+ ft = ft.dup
10
+ ft.volume = Rational(unprocessed_activity.amount.to_i*100, 3600)
11
+ ft.save!
12
+ true
13
+ end
14
+ end
15
+
16
+ class RepeatingMockFilter2 < Filter
17
+ def calculate_cost(computer_id, login_id, started_at, amount, options={})
18
+ Rational(amount.to_i*200, 3600)
19
+ end
20
+
21
+ def process_activity(unprocessed_activity, ft, options={})
22
+ ft = ft.dup
23
+ ft.volume = Rational(unprocessed_activity.amount.to_i*200, 3600)
24
+ ft.save!
25
+ true
26
+ end
27
+ end
28
+
29
+ class RepeatingMockFilter3 < Filter
30
+ def calculate_cost(computer_id, login_id, started_at, amount, options={})
31
+ Rational(amount.to_i*300, 3600)
32
+ end
33
+
34
+ def process_activity(unprocessed_activity, ft, options={})
35
+ ft = ft.dup
36
+ ft.volume = Rational(unprocessed_activity.amount.to_i*300, 3600)
37
+ ft.save!
38
+ true
39
+ end
40
+ end
41
+
42
+ class RepeatingMockFilterWithOptionsExpectations < Filter
43
+ end
44
+
45
+
46
+ describe "RepeatingFilterPeriod" do
47
+ it "should not allow to create invalid period" do
48
+ lambda {
49
+ RepeatingFilterPeriod.new(Time.now, 300, 200, stub())
50
+ }.should raise_error
51
+ end
52
+
53
+ it "should allow valid period creation" do
54
+ RepeatingFilterPeriod.new(Time.now, 300, 300, stub())
55
+ RepeatingFilterPeriod.new(Time.now, 123, 200, stub())
56
+ end
57
+
58
+ it "should set filter value" do
59
+ filtah = stub()
60
+ RepeatingFilterPeriod.new(Time.now, 300, 300, filtah).filter.should == filtah
61
+ end
62
+
63
+ it "should delegate filter value when generating ranges" do
64
+ filtah, now = stub(), Time.now
65
+ periods = RepeatingFilterPeriod.new(now, 100, 200, filtah).generate_in_range(now-1, now + 410)
66
+ periods.each { |p| p.filter.should == filtah }
67
+ end
68
+
69
+ it "should recur correctly" do
70
+ test_start_time = Time.now
71
+
72
+ period = RepeatingFilterPeriod.new(test_start_time, 2*3600, 86400, stub())
73
+
74
+ # today
75
+ period.includes?(test_start_time).should == true
76
+ period.includes?(test_start_time+123).should == true
77
+ period.includes?(test_start_time+7199).should == true
78
+ period.includes?(test_start_time+7200).should == false
79
+ period.includes?(test_start_time+56124).should == false
80
+ period.includes?(test_start_time+86399).should == false
81
+
82
+ # tomorrow
83
+ period.includes?(test_start_time+86400).should == true
84
+ period.includes?(test_start_time+86400+123).should == true
85
+ period.includes?(test_start_time+86400+7199).should == true
86
+ period.includes?(test_start_time+86400+7200).should == false
87
+ period.includes?(test_start_time+86400+56124).should == false
88
+ period.includes?(test_start_time+86400+86399).should == false
89
+ end
90
+
91
+ it "should support === operator to behave exactly like includes?" do
92
+ period = RepeatingFilterPeriod.new(Time.now, 2*3600, 86400, stub())
93
+ period.expects(:includes?).with(1024).returns(:thats_what_include_returns)
94
+ (period === 1024).should == :thats_what_include_returns
95
+ end
96
+
97
+ it "should generate correct ranges array" do
98
+ test_start_time = Time.now
99
+
100
+ period = RepeatingFilterPeriod.new(test_start_time, 2*3600, 86400, stub())
101
+
102
+ ranges = period.generate_in_range(test_start_time, test_start_time+86400).map { |r| r.as_range }
103
+ ranges.should == [ (test_start_time.to_i ... test_start_time.to_i+2*3600) ]
104
+
105
+ ranges = period.generate_in_range(test_start_time, test_start_time+45000).map { |r| r.as_range }
106
+ ranges.should == [ (test_start_time.to_i ... test_start_time.to_i+2*3600) ]
107
+
108
+ ranges = period.generate_in_range(test_start_time, test_start_time+2*86400).map { |r| r.as_range }
109
+ ranges.should == [ (test_start_time.to_i ... test_start_time.to_i+2*3600), (test_start_time.to_i+86400 ... test_start_time.to_i+86400+2*3600) ]
110
+
111
+ ranges = period.generate_in_range(test_start_time, test_start_time+1024*86400).map { |r| r.as_range }
112
+ ranges.size.should == 1024
113
+ end
114
+
115
+ it "should return correct variant of the localized period" do
116
+ test_start_time = Time.now
117
+ period = RepeatingFilterPeriod.new(test_start_time, 2*3600, 86400, stub())
118
+ period.local_period(test_start_time+30.days+10.seconds).as_range.should ==
119
+ ((test_start_time+30*86400).to_i ... (test_start_time+2*3600+30*86400).to_i)
120
+ end
121
+ end
122
+
123
+ describe "SortableRange" do
124
+ it "should sort the correct way" do
125
+ r_1_3 = SortableRange.new(1, 3)
126
+ r_5_9 = SortableRange.new(5, 9)
127
+ r_16_18= SortableRange.new(16, 18)
128
+ [ r_5_9, r_1_3, r_16_18 ].sort.should == [ r_1_3, r_5_9, r_16_18 ]
129
+ end
130
+
131
+ it "should return corresponding Range object" do
132
+ SortableRange.new(10, 13).as_range.should == Range.new(10,13)
133
+ end
134
+
135
+ it "should have filter field" do
136
+ r = SortableRange.new(10, 13)
137
+ r.filter = 123
138
+ r.filter.should == 123
139
+ end
140
+ end
141
+
142
+ describe "RepeatingFilter" do
143
+ before do
144
+ now = Time.at(0)
145
+ @settings = Settings.new({
146
+ { :starts_at => now, :length => 3600, :period => 10800 } => { :klass => "RepeatingMockFilter1", :settings => { :vasya => "pupkin" } },
147
+ { :starts_at => now+3600, :length => 3600, :period => 10800 } => { :klass => "RepeatingMockFilter2", :settings => { :vasya => "vanin" } },
148
+ { :starts_at => now+7200, :length => 3600, :period => 10800 } => { :klass => "RepeatingMockFilter3", :settings => { :vasya => "vanin" } }
149
+ })
150
+ @filter = RepeatingFilter.new(@settings, 0)
151
+ end
152
+
153
+ it "should not instantinate when periods are not cosistent" do
154
+ now = Time.at(0)
155
+ settings = Settings.new({
156
+ { :starts_at => now, :length => 100, :period => 300 } => { :klass => "RepeatingMockFilter1", :settings => { :vasya => "pupkin" } },
157
+ { :starts_at => now+100, :length => 100, :period => 300 } => { :klass => "RepeatingMockFilter2", :settings => { :vasya => "vanin" } }
158
+ })
159
+
160
+ lambda {
161
+ filter = RepeatingFilter.new(settings, 0)
162
+ }.should raise_error(Exception, /Inconsistent periods/)
163
+ end
164
+
165
+ it "should not instantinate when periods are intersecting" do
166
+ now = Time.at(0)
167
+ settings = Settings.new({
168
+ { :starts_at => now, :length => 95, :period => 301 } => { :klass => "RepeatingMockFilter1", :settings => { :vasya => "pupkin" } },
169
+ { :starts_at => now+100, :length => 100, :period => 300 } => { :klass => "RepeatingMockFilter2", :settings => { :vasya => "vanin" } },
170
+ { :starts_at => now+200, :length => 100, :period => 300 } => { :klass => "RepeatingMockFilter3", :settings => { :vasya => "vanin" } },
171
+ })
172
+
173
+ lambda {
174
+ filter = RepeatingFilter.new(settings, 0)
175
+ }.should raise_error(Exception, /Intersectings periods/)
176
+ end
177
+
178
+ it "should calculate cost correctly" do
179
+ @filter.calculate_cost(1, 2, Time.at(0), 3600).should == 100
180
+ @filter.calculate_cost(1, 2, Time.at(3600), 3600).should == 200
181
+ @filter.calculate_cost(1, 2, Time.at(7200), 3600).should == 300
182
+
183
+ @filter.calculate_cost(1, 2, Time.at(0), 7*24*3600).should == 33600
184
+ @filter.calculate_cost(1, 2, Time.at(3600+1800), 7*24*3600).should == 33600
185
+
186
+ @filter.calculate_cost(1, 2, Time.at(3600+1800), 3600+1800).should == 400
187
+ end
188
+
189
+ it "should process activities correctly spanning them" do
190
+ unprocessed_activity = Activity.new
191
+ unprocessed_activity.expects(:created_at).returns(Time.at(0)).at_least_once
192
+ unprocessed_activity.expects(:amount).returns(7*24*3600).at_least_once
193
+
194
+ ft = FinTransaction.template
195
+ ft.author_id = 1
196
+ ft.club_id = 2
197
+
198
+ FinTransaction.reset_transactions
199
+ @filter.process_activity(unprocessed_activity, ft).should == true
200
+ FinTransaction.transactions.inject(&:+).should == 33600
201
+ end
202
+
203
+ it "should process activities correctly spanning them (strict check)" do
204
+ unprocessed_activity = Activity.new
205
+ unprocessed_activity.expects(:created_at).returns(Time.at(0)).at_least_once
206
+ unprocessed_activity.expects(:amount).returns(3600*4+1800).at_least_once
207
+
208
+ ft = FinTransaction.template
209
+ ft.author_id = 1
210
+ ft.club_id = 2
211
+
212
+ FinTransaction.reset_transactions
213
+ @filter.process_activity(unprocessed_activity, ft).should == true
214
+ FinTransaction.transactions.should == [ 100, 200, 300, 100, 100 ]
215
+ end
216
+
217
+ it "should pass on the options to the underlying filter and add its own" do
218
+ doesnt_matter = nil
219
+ now = Time.at(0)
220
+ settings = Settings.new({
221
+ { :starts_at => now, :length => 3600, :period => 10800 } => { :klass => "RepeatingMockFilterWithOptionsExpectations", :settings => { :vasya => "pupkin" } },
222
+ { :starts_at => now+3600, :length => 3600, :period => 10800 } => { :klass => "RepeatingMockFilter2", :settings => { :vasya => "vanin" } },
223
+ { :starts_at => now+7200, :length => 3600, :period => 10800 } => { :klass => "RepeatingMockFilter3", :settings => { :vasya => "vanin" } }
224
+ })
225
+
226
+ filter = RepeatingFilter.new(settings, 0)
227
+
228
+ [ 0, 3600*3 ].each do |offset|
229
+ RepeatingMockFilterWithOptionsExpectations.any_instance.tap do |it|
230
+ it.expects(:calculate_cost).with(anything, anything, anything, anything, equals({:my => :options, :period => (0+offset...3600+offset)})).returns(0)
231
+ it.expects(:start_permitted?).with(anything, anything, equals({:my => :options, :period => (0+offset...3600+offset)})).returns(true)
232
+ it.expects(:permitted?).with(anything, anything, equals({:my => :options, :period => (0+offset...3600+offset)})).returns(true)
233
+ it.expects(:process_activity).with(anything, anything, equals({:my => :options, :period => (0+offset...3600+offset)})).returns(true)
234
+ end
235
+
236
+ Timecop.freeze(now + offset) do
237
+ ft_doesnt_matter = stub_everything()
238
+
239
+ activity_doesnt_matter = Activity.new
240
+ activity_doesnt_matter.stubs(:created_at).returns(Time.now + 30.seconds).at_least_once
241
+ activity_doesnt_matter.stubs(:amount).returns(3600).at_least_once
242
+
243
+ filter.calculate_cost(doesnt_matter, doesnt_matter, Time.now + 30.seconds, 3600, { :my => :options })
244
+ filter.start_permitted?(doesnt_matter, doesnt_matter, { :my => :options })
245
+ filter.permitted?(doesnt_matter, doesnt_matter, { :my => :options })
246
+ filter.process_activity(activity_doesnt_matter, ft_doesnt_matter, { :my => :options })
247
+ end
248
+ end
249
+ end
250
+ end