berater 0.5.0 → 0.7.1

Sign up to get free protection for your applications and to get access to all the features.
data/spec/riddle_spec.rb CHANGED
@@ -42,11 +42,15 @@ class ConcurrenyRiddler
42
42
  timeout ||= 1_000 # fake infinity
43
43
 
44
44
  limiter = Berater::RateLimiter.new(:key, capacity, timeout)
45
- limiter.limit
45
+ lock = limiter.limit
46
46
  yield if block_given?
47
47
  ensure
48
48
  # decrement counter
49
- limiter.redis.decr(limiter.send(:cache_key, :key))
49
+ if lock
50
+ key = limiter.send(:cache_key, :key)
51
+ count, ts = limiter.redis.get(key).split ';'
52
+ limiter.redis.set(key, "#{count.to_f - 1};#{ts}")
53
+ end
50
54
  end
51
55
  end
52
56
 
@@ -1,35 +1,24 @@
1
- describe Berater::TestMode, order: :defined do
2
- let(:reset_test_mode) { true }
3
-
1
+ describe Berater::TestMode do
4
2
  after do
5
- Berater.test_mode = nil if reset_test_mode
3
+ Berater.test_mode = nil
6
4
  end
7
5
 
8
- context 'after test_mode.rb was required, but not used' do
9
- let(:reset_test_mode) { false }
10
-
11
- it 'has already been loaded by "berater/rspec", unfortunately' do
12
- expect {
13
- expect { Berater.test_mode }.to raise_error(NoMethodError)
14
- }.to fail
6
+ context 'after test_mode.rb has been loaded' do
7
+ it 'monkey patches Berater' do
8
+ expect(Berater).to respond_to(:test_mode)
15
9
  end
16
10
 
17
11
  it 'defaults to off' do
18
12
  expect(Berater.test_mode).to be nil
19
13
  end
20
14
 
21
- it 'did not prepend .new yet' do
22
- expect(Berater::Limiter.singleton_class.ancestors).not_to include(described_class)
23
- end
24
-
25
- it 'prepends when first turned on' do
26
- Berater.test_mode = :pass
27
-
28
- expect(Berater::Limiter.singleton_class.ancestors).to include(described_class)
15
+ it 'prepends Limiter subclasses' do
16
+ expect(Berater::Unlimiter.ancestors).to include(described_class)
17
+ expect(Berater::Inhibitor.ancestors).to include(described_class)
29
18
  end
30
19
 
31
20
  it 'preserves the original functionality via super' do
32
- expect { Berater::Limiter.new }.to raise_error(NotImplementedError)
21
+ expect { Berater::Limiter.new }.to raise_error(NoMethodError)
33
22
  end
34
23
  end
35
24
 
@@ -50,31 +39,43 @@ describe Berater::TestMode, order: :defined do
50
39
  it 'validates input' do
51
40
  expect { Berater.test_mode = :foo }.to raise_error(ArgumentError)
52
41
  end
53
- end
54
42
 
55
- shared_examples 'it always works, without redis' do
56
- before do
57
- Berater.redis = nil
58
- expect_any_instance_of(Berater::LuaScript).not_to receive(:eval)
59
- end
43
+ it 'works no matter when limiter was created' do
44
+ limiter = Berater::Unlimiter.new
45
+ expect(limiter).not_to be_overloaded
60
46
 
61
- it_behaves_like 'it is not overloaded'
47
+ Berater.test_mode = :fail
48
+ expect(limiter).to be_overloaded
49
+ end
62
50
 
63
- it 'always works' do
64
- 10.times { subject.limit }
51
+ it 'supports a generic expectation' do
52
+ Berater.test_mode = :pass
53
+ expect_any_instance_of(Berater::Limiter).to receive(:limit)
54
+ Berater::Unlimiter.new.limit
65
55
  end
66
56
  end
67
57
 
68
- shared_examples 'it never works, without redis' do
58
+ shared_examples 'it supports test_mode' do
69
59
  before do
60
+ # without hitting Redis
70
61
  Berater.redis = nil
71
62
  expect_any_instance_of(Berater::LuaScript).not_to receive(:eval)
72
63
  end
73
64
 
74
- it_behaves_like 'it is overloaded'
65
+ context 'with test_mode = :pass' do
66
+ before { Berater.test_mode = :pass }
67
+
68
+ it_behaves_like 'it is not overloaded'
69
+
70
+ it 'always works' do
71
+ 10.times { subject.limit }
72
+ end
73
+ end
74
+
75
+ context 'with test_mode = :fail' do
76
+ before { Berater.test_mode = :fail }
75
77
 
76
- it 'never works' do
77
- expect { subject }.to be_overloaded
78
+ it_behaves_like 'it is overloaded'
78
79
  end
79
80
  end
80
81
 
@@ -84,23 +85,10 @@ describe Berater::TestMode, order: :defined do
84
85
  context 'when test_mode = nil' do
85
86
  before { Berater.test_mode = nil }
86
87
 
87
- it { is_expected.to be_a Berater::Unlimiter }
88
- it_behaves_like 'it always works, without redis'
89
- end
90
-
91
- context 'when test_mode = :pass' do
92
- before { Berater.test_mode = :pass }
93
-
94
- it { is_expected.to be_a Berater::Unlimiter }
95
- it_behaves_like 'it always works, without redis'
88
+ it_behaves_like 'it is not overloaded'
96
89
  end
97
90
 
98
- context 'when test_mode = :fail' do
99
- before { Berater.test_mode = :fail }
100
-
101
- it { is_expected.to be_a Berater::Unlimiter }
102
- it_behaves_like 'it never works, without redis'
103
- end
91
+ it_behaves_like 'it supports test_mode'
104
92
  end
105
93
 
106
94
  describe 'Inhibitor' do
@@ -109,42 +97,18 @@ describe Berater::TestMode, order: :defined do
109
97
  context 'when test_mode = nil' do
110
98
  before { Berater.test_mode = nil }
111
99
 
112
- it { is_expected.to be_a Berater::Inhibitor }
113
- it_behaves_like 'it never works, without redis'
100
+ it_behaves_like 'it is overloaded'
114
101
  end
115
102
 
116
- context 'when test_mode = :pass' do
117
- before { Berater.test_mode = :pass }
118
-
119
- it { is_expected.to be_a Berater::Inhibitor }
120
- it_behaves_like 'it always works, without redis'
121
- end
122
-
123
- context 'when test_mode = :fail' do
124
- before { Berater.test_mode = :fail }
125
-
126
- it { is_expected.to be_a Berater::Inhibitor }
127
- it_behaves_like 'it never works, without redis'
128
- end
103
+ it_behaves_like 'it supports test_mode'
129
104
  end
130
105
 
131
106
  describe 'RateLimiter' do
132
107
  subject { Berater::RateLimiter.new(:key, 1, :second) }
133
108
 
134
- shared_examples 'a RateLimiter' do
135
- it { is_expected.to be_a Berater::RateLimiter }
136
-
137
- it 'checks arguments' do
138
- expect {
139
- Berater::RateLimiter.new(:key, 1)
140
- }.to raise_error(ArgumentError)
141
- end
142
- end
143
-
144
109
  context 'when test_mode = nil' do
145
110
  before { Berater.test_mode = nil }
146
111
 
147
- it_behaves_like 'a RateLimiter'
148
112
  it_behaves_like 'it is not overloaded'
149
113
 
150
114
  it 'works per usual' do
@@ -154,38 +118,15 @@ describe Berater::TestMode, order: :defined do
154
118
  end
155
119
  end
156
120
 
157
- context 'when test_mode = :pass' do
158
- before { Berater.test_mode = :pass }
159
-
160
- it_behaves_like 'a RateLimiter'
161
- it_behaves_like 'it always works, without redis'
162
- end
163
-
164
- context 'when test_mode = :fail' do
165
- before { Berater.test_mode = :fail }
166
-
167
- it_behaves_like 'a RateLimiter'
168
- it_behaves_like 'it never works, without redis'
169
- end
121
+ it_behaves_like 'it supports test_mode'
170
122
  end
171
123
 
172
124
  describe 'ConcurrencyLimiter' do
173
125
  subject { Berater::ConcurrencyLimiter.new(:key, 1) }
174
126
 
175
- shared_examples 'a ConcurrencyLimiter' do
176
- it { expect(subject).to be_a Berater::ConcurrencyLimiter }
177
-
178
- it 'checks arguments' do
179
- expect {
180
- Berater::ConcurrencyLimiter.new(:key, 1.0)
181
- }.to raise_error(ArgumentError)
182
- end
183
- end
184
-
185
127
  context 'when test_mode = nil' do
186
128
  before { Berater.test_mode = nil }
187
129
 
188
- it_behaves_like 'a ConcurrencyLimiter'
189
130
  it_behaves_like 'it is not overloaded'
190
131
 
191
132
  it 'works per usual' do
@@ -195,19 +136,7 @@ describe Berater::TestMode, order: :defined do
195
136
  end
196
137
  end
197
138
 
198
- context 'when test_mode = :pass' do
199
- before { Berater.test_mode = :pass }
200
-
201
- it_behaves_like 'a ConcurrencyLimiter'
202
- it_behaves_like 'it always works, without redis'
203
- end
204
-
205
- context 'when test_mode = :fail' do
206
- before { Berater.test_mode = :fail }
207
-
208
- it_behaves_like 'a ConcurrencyLimiter'
209
- it_behaves_like 'it never works, without redis'
210
- end
139
+ it_behaves_like 'it supports test_mode'
211
140
  end
212
141
 
213
142
  end
data/spec/utils_spec.rb CHANGED
@@ -1,63 +1,63 @@
1
1
  describe Berater::Utils do
2
2
  using Berater::Utils
3
3
 
4
- describe '.to_usec' do
4
+ describe '.to_msec' do
5
5
  def f(val)
6
- (val * 10**6).to_i
6
+ (val * 10**3).to_i
7
7
  end
8
8
 
9
9
  it 'works with integers' do
10
- expect(0.to_usec).to be f(0)
11
- expect(3.to_usec).to be f(3)
10
+ expect(0.to_msec).to be f(0)
11
+ expect(3.to_msec).to be f(3)
12
12
  end
13
13
 
14
14
  it 'works with floats' do
15
- expect(0.1.to_usec).to be f(0.1)
16
- expect(3.0.to_usec).to be f(3)
15
+ expect(0.1.to_msec).to be f(0.1)
16
+ expect(3.0.to_msec).to be f(3)
17
17
  end
18
18
 
19
- it 'has great precision' do
20
- expect(0.123456.to_usec).to be 123456
21
- expect(123456.654321.to_usec).to be 123456654321
19
+ it 'truncates excessive precision' do
20
+ expect(0.123456.to_msec).to be 123
21
+ expect(123456.654321.to_msec).to be 123456654
22
22
  end
23
23
 
24
24
  it 'works with symbols that are keywords' do
25
- expect(:sec.to_usec).to be f(1)
26
- expect(:second.to_usec).to be f(1)
27
- expect(:seconds.to_usec).to be f(1)
25
+ expect(:sec.to_msec).to be f(1)
26
+ expect(:second.to_msec).to be f(1)
27
+ expect(:seconds.to_msec).to be f(1)
28
28
 
29
- expect(:min.to_usec).to be f(60)
30
- expect(:minute.to_usec).to be f(60)
31
- expect(:minutes.to_usec).to be f(60)
29
+ expect(:min.to_msec).to be f(60)
30
+ expect(:minute.to_msec).to be f(60)
31
+ expect(:minutes.to_msec).to be f(60)
32
32
 
33
- expect(:hour.to_usec).to be f(60 * 60)
34
- expect(:hours.to_usec).to be f(60 * 60)
33
+ expect(:hour.to_msec).to be f(60 * 60)
34
+ expect(:hours.to_msec).to be f(60 * 60)
35
35
  end
36
36
 
37
37
  it 'works with strings that are keywords' do
38
- expect('sec'.to_usec).to be f(1)
39
- expect('second'.to_usec).to be f(1)
40
- expect('seconds'.to_usec).to be f(1)
38
+ expect('sec'.to_msec).to be f(1)
39
+ expect('second'.to_msec).to be f(1)
40
+ expect('seconds'.to_msec).to be f(1)
41
41
 
42
- expect('min'.to_usec).to be f(60)
43
- expect('minute'.to_usec).to be f(60)
44
- expect('minutes'.to_usec).to be f(60)
42
+ expect('min'.to_msec).to be f(60)
43
+ expect('minute'.to_msec).to be f(60)
44
+ expect('minutes'.to_msec).to be f(60)
45
45
 
46
- expect('hour'.to_usec).to be f(60 * 60)
47
- expect('hours'.to_usec).to be f(60 * 60)
46
+ expect('hour'.to_msec).to be f(60 * 60)
47
+ expect('hours'.to_msec).to be f(60 * 60)
48
48
  end
49
49
 
50
50
  it 'works with strings that are numeric' do
51
- expect('0'.to_usec).to be f(0)
52
- expect('3'.to_usec).to be f(3)
51
+ expect('0'.to_msec).to be f(0)
52
+ expect('3'.to_msec).to be f(3)
53
53
 
54
- expect('0.1'.to_usec).to be f(0.1)
55
- expect('3.0'.to_usec).to be f(3)
54
+ expect('0.1'.to_msec).to be f(0.1)
55
+ expect('3.0'.to_msec).to be f(3)
56
56
  end
57
57
 
58
58
  context 'with erroneous values' do
59
59
  def e(val)
60
- expect { val.to_usec }.to raise_error(ArgumentError)
60
+ expect { val.to_msec }.to raise_error(ArgumentError)
61
61
  end
62
62
 
63
63
  it 'rejects negative numbers' do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: berater
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.7.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Pepper
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-03-06 00:00:00.000000000 Z
11
+ date: 2021-03-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: redis