berater 0.3.0 → 0.6.2

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.
@@ -0,0 +1,46 @@
1
+ require 'berater/dsl'
2
+
3
+ describe Berater do
4
+ using Berater::DSL
5
+
6
+ it 'instatiates an Unlimiter' do
7
+ limiter = Berater.new(:key) { unlimited }
8
+ expect(limiter).to be_a Berater::Unlimiter
9
+ expect(limiter.key).to be :key
10
+ end
11
+
12
+ it 'instatiates an Inhibiter' do
13
+ limiter = Berater.new(:key) { inhibited }
14
+ expect(limiter).to be_a Berater::Inhibitor
15
+ expect(limiter.key).to be :key
16
+ end
17
+
18
+ it 'instatiates a RateLimiter' do
19
+ limiter = Berater.new(:key) { 1.per second }
20
+ expect(limiter).to be_a Berater::RateLimiter
21
+ expect(limiter.key).to be :key
22
+ expect(limiter.capacity).to be 1
23
+ expect(limiter.interval).to be :second
24
+ end
25
+
26
+ it 'instatiates a ConcurrencyLimiter' do
27
+ limiter = Berater.new(:key, timeout: 2) { 1.at_once }
28
+ expect(limiter).to be_a Berater::ConcurrencyLimiter
29
+ expect(limiter.key).to be :key
30
+ expect(limiter.capacity).to be 1
31
+ expect(limiter.timeout).to be 2
32
+ end
33
+
34
+ it 'does not accept args and dsl block' do
35
+ expect {
36
+ Berater.new(:key, 2) { 3.at_once }
37
+ }.to raise_error(ArgumentError)
38
+ end
39
+
40
+ it 'requires either mode or dsl block' do
41
+ expect {
42
+ Berater.new(:key)
43
+ }.to raise_error(ArgumentError)
44
+ end
45
+
46
+ end
data/spec/dsl_spec.rb ADDED
@@ -0,0 +1,72 @@
1
+ require 'berater/dsl'
2
+
3
+ describe Berater::DSL do
4
+ def check(expected, &block)
5
+ expect(Berater::DSL.eval(&block)).to eq expected
6
+ end
7
+
8
+ context 'rate mode' do
9
+ it 'has keywords' do
10
+ check(:second) { second }
11
+ check(:minute) { minute }
12
+ check(:hour) { hour }
13
+ end
14
+
15
+ it 'parses' do
16
+ check([ 1, :second ]) { 1.per second }
17
+ check([ 3, :minute ]) { 3.per minute }
18
+ check([ 5, :hour ]) { 5.every hour }
19
+ end
20
+
21
+ it 'cleans up afterward' do
22
+ check([ 1, :second ]) { 1.per second }
23
+
24
+ expect(Integer).not_to respond_to(:per)
25
+ expect(Integer).not_to respond_to(:every)
26
+ end
27
+
28
+ it 'works with variables' do
29
+ count = 1
30
+ interval = :second
31
+
32
+ check([ count, interval ]) { count.per interval }
33
+ end
34
+ end
35
+
36
+ context 'concurrency mode' do
37
+ it 'parses' do
38
+ check([ 1 ]) { 1.at_once }
39
+ check([ 3 ]) { 3.at_a_time }
40
+ check([ 5 ]) { 5.concurrently }
41
+ end
42
+
43
+ it 'cleans up afterward' do
44
+ check([ 1 ]) { 1.at_once }
45
+
46
+ expect(Integer).not_to respond_to(:at_once)
47
+ expect(Integer).not_to respond_to(:at_a_time)
48
+ expect(Integer).not_to respond_to(:concurrently)
49
+ end
50
+
51
+ it 'works with constants' do
52
+ class Foo
53
+ CAPACITY = 3
54
+ end
55
+
56
+ check([ Foo::CAPACITY ]) { Foo::CAPACITY.at_once }
57
+ end
58
+ end
59
+
60
+ context 'unlimited mode' do
61
+ it 'has keywords' do
62
+ check(:unlimited) { unlimited }
63
+ end
64
+ end
65
+
66
+ context 'inhibited mode' do
67
+ it 'has keywords' do
68
+ check(:inhibited) { inhibited }
69
+ end
70
+ end
71
+
72
+ end
@@ -15,11 +15,9 @@ describe Berater::Inhibitor do
15
15
  end
16
16
 
17
17
  describe '#limit' do
18
- let(:limiter) { described_class.new }
18
+ subject { described_class.new }
19
19
 
20
- it 'always limits' do
21
- expect { limiter.limit }.to be_inhibited
22
- end
20
+ it_behaves_like 'it is overloaded'
23
21
  end
24
22
 
25
23
  end
@@ -0,0 +1,107 @@
1
+ describe Berater::Limiter do
2
+ it 'can not be initialized' do
3
+ expect { described_class.new }.to raise_error(NoMethodError)
4
+ end
5
+
6
+ describe 'abstract methods' do
7
+ let(:limiter) { Class.new(described_class).new(:key, 1) }
8
+
9
+ it do
10
+ expect { limiter.limit }.to raise_error(NotImplementedError)
11
+ expect { limiter.overloaded? }.to raise_error(NotImplementedError)
12
+ end
13
+ end
14
+
15
+ describe '#limit' do
16
+ subject { Berater::Unlimiter.new }
17
+
18
+ context 'with a capacity parameter' do
19
+ it 'overrides the stored value' do
20
+ is_expected.to receive(:acquire_lock).with(3, anything)
21
+
22
+ subject.limit(capacity: 3)
23
+ end
24
+
25
+ it 'validates the type' do
26
+ expect {
27
+ subject.limit(capacity: 'abc')
28
+ }.to raise_error(ArgumentError)
29
+ end
30
+ end
31
+
32
+ context 'with a cost parameter' do
33
+ it 'overrides the stored value' do
34
+ is_expected.to receive(:acquire_lock).with(anything, 2)
35
+
36
+ subject.limit(cost: 2)
37
+ end
38
+
39
+ it 'validates' do
40
+ expect {
41
+ subject.limit(cost: 'abc')
42
+ }.to raise_error(ArgumentError)
43
+
44
+ expect {
45
+ subject.limit(cost: -1)
46
+ }.to raise_error(ArgumentError)
47
+ end
48
+ end
49
+ end
50
+
51
+ describe '#==' do
52
+ let(:limiter) { Berater::RateLimiter.new(:key, 1, :second) }
53
+
54
+ it 'equals itself' do
55
+ expect(limiter).to eq limiter
56
+ end
57
+
58
+ it 'equals something with the same initialization parameters' do
59
+ expect(limiter).to eq(
60
+ Berater::RateLimiter.new(:key, 1, :second)
61
+ )
62
+ end
63
+
64
+ it 'equals something with equvalent initialization parameters' do
65
+ expect(limiter).to eq(
66
+ Berater::RateLimiter.new(:key, 1, 1)
67
+ )
68
+ end
69
+
70
+ it 'does not equal something different' do
71
+ expect(limiter).not_to eq(
72
+ Berater::RateLimiter.new(:key, 2, :second)
73
+ )
74
+
75
+ expect(limiter).not_to eq(
76
+ Berater::RateLimiter.new(:keyz, 1, :second)
77
+ )
78
+
79
+ expect(limiter).not_to eq(
80
+ Berater::RateLimiter.new(:key, 1, :minute)
81
+ )
82
+ end
83
+
84
+ it 'does not equal something altogether different' do
85
+ expect(limiter).not_to eq(
86
+ Berater::ConcurrencyLimiter.new(:key, 1)
87
+ )
88
+ end
89
+
90
+ it 'works for ConcurrencyLimiter too' do
91
+ limiter = Berater::ConcurrencyLimiter.new(:key, 1)
92
+ expect(limiter).to eq limiter
93
+
94
+ expect(limiter).not_to eq(
95
+ Berater::ConcurrencyLimiter.new(:key, 1, timeout: 1)
96
+ )
97
+ end
98
+
99
+ it 'and the others' do
100
+ unlimiter = Berater::Unlimiter.new
101
+ expect(unlimiter).to eq unlimiter
102
+
103
+ expect(unlimiter).not_to eq Berater::Inhibitor.new
104
+ end
105
+ end
106
+
107
+ end
@@ -0,0 +1,97 @@
1
+ describe Berater::LuaScript do
2
+ subject { Berater::LuaScript('return redis.call("PING")') }
3
+
4
+ before { redis.script(:flush) }
5
+
6
+ let(:redis) { Berater.redis }
7
+
8
+ it { is_expected.to be_a Berater::LuaScript }
9
+
10
+ describe '#eval' do
11
+ def ping
12
+ expect(subject.eval(redis)).to eq 'PONG'
13
+ end
14
+
15
+ it { ping }
16
+
17
+ it 'loads the script into redis' do
18
+ expect(redis).to receive(:evalsha).once.and_call_original
19
+ expect(redis).to receive(:eval).once.and_call_original
20
+ ping
21
+ expect(subject.loaded?(redis)).to be true
22
+ end
23
+ end
24
+
25
+ describe '#load' do
26
+ it 'loads script into redis' do
27
+ expect(redis.script(:exists, subject.sha)).to be false
28
+ subject.load(redis)
29
+ expect(redis.script(:exists, subject.sha)).to be true
30
+ end
31
+
32
+ it 'returns the sha' do
33
+ expect(subject.load(redis)).to eq subject.sha
34
+ end
35
+
36
+ it 'validates the returned sha' do
37
+ allow(redis).to receive(:script).with(:flush).and_call_original
38
+ expect(redis).to receive(:script).with(:load, String).and_return('abc')
39
+ expect { subject.load(redis) }.to raise_error(RuntimeError)
40
+ end
41
+ end
42
+
43
+ describe '#loaded?' do
44
+ it do
45
+ expect(subject.loaded?(redis)).to be false
46
+ subject.load(redis)
47
+ expect(subject.loaded?(redis)).to be true
48
+ end
49
+ end
50
+
51
+ describe '#to_s' do
52
+ it { expect(subject.to_s).to be subject.source }
53
+ end
54
+
55
+ describe '#minify' do
56
+ subject do
57
+ expect(
58
+ Berater::LuaScript(lua).send(:minify)
59
+ ).to eq expected
60
+ end
61
+
62
+ context do
63
+ let(:lua) do <<-LUA
64
+ -- this comment gets removed
65
+ redis.call('PING') -- this one too
66
+ LUA
67
+ end
68
+
69
+ let(:expected) { "redis.call('PING')" }
70
+
71
+ it { subject }
72
+ end
73
+
74
+ context 'with if statement' do
75
+ let(:lua) do <<~LUA
76
+ if condition then
77
+ call
78
+ end
79
+
80
+ return 123
81
+ LUA
82
+ end
83
+
84
+ let(:expected) do
85
+ [
86
+ 'if condition then',
87
+ 'call',
88
+ 'end',
89
+ 'return 123'
90
+ ].join "\n"
91
+ end
92
+
93
+ it { subject }
94
+ end
95
+ end
96
+
97
+ end
@@ -1,4 +1,5 @@
1
- describe 'be_overloaded' do
1
+ describe Berater::Matchers::Overloaded do
2
+
2
3
  context 'Berater::Unlimiter' do
3
4
  let(:limiter) { Berater.new(:key, :unlimited) }
4
5
 
@@ -32,7 +33,7 @@ describe 'be_overloaded' do
32
33
  end
33
34
 
34
35
  context 'Berater::RateLimiter' do
35
- let(:limiter) { Berater.new(:key, :rate, 1, :second) }
36
+ let(:limiter) { Berater.new(:key, 1, :second) }
36
37
 
37
38
  it { expect(limiter).not_to be_overloaded }
38
39
  it { expect(limiter).not_to be_inhibited }
@@ -67,7 +68,7 @@ describe 'be_overloaded' do
67
68
  end
68
69
 
69
70
  context 'Berater::ConcurrencyLimiter' do
70
- let(:limiter) { Berater.new(:key, :concurrency, 1) }
71
+ let(:limiter) { Berater.new(:key, 1) }
71
72
 
72
73
  it { expect(limiter).not_to be_overloaded }
73
74
  it { expect(limiter).not_to be_inhibited }
@@ -115,4 +116,71 @@ describe 'be_overloaded' do
115
116
  end
116
117
  end
117
118
  end
119
+
120
+ context 'when matchers fail' do
121
+ let(:unlimiter) { Berater::Unlimiter.new }
122
+ let(:inhibitor) { Berater::Inhibitor.new }
123
+
124
+ it 'catches false negatives' do
125
+ expect {
126
+ expect(unlimiter).to be_overloaded
127
+ }.to fail_including('expected to be overloaded')
128
+
129
+ expect {
130
+ expect { unlimiter }.to be_overloaded
131
+ }.to fail_including('expected to be overloaded')
132
+
133
+ expect {
134
+ expect { unlimiter.limit }.to be_overloaded
135
+ }.to fail_including("expected #{Berater::Overloaded} to be raised")
136
+
137
+ expect {
138
+ expect { 123 }.to be_overloaded
139
+ }.to fail_including("expected #{Berater::Overloaded} to be raised")
140
+ end
141
+
142
+ it 'catches false positives' do
143
+ expect {
144
+ expect(inhibitor).not_to be_overloaded
145
+ }.to fail_including('expected not to be overloaded')
146
+
147
+ expect {
148
+ expect { inhibitor }.not_to be_overloaded
149
+ }.to fail_including('expected not to be overloaded')
150
+
151
+ expect {
152
+ expect { inhibitor.limit }.not_to be_overloaded
153
+ }.to fail_including("did not expect #{Berater::Overloaded} to be raised")
154
+
155
+ expect {
156
+ expect { raise Berater::Overloaded }.not_to be_overloaded
157
+ }.to fail_including("did not expect #{Berater::Overloaded} to be raised")
158
+ end
159
+
160
+ it 'supports different verbs' do
161
+ expect {
162
+ expect { unlimiter }.to be_overrated
163
+ }.to fail_including('expected to be overrated')
164
+
165
+ expect {
166
+ expect { unlimiter }.to be_incapacitated
167
+ }.to fail_including('expected to be incapacitated')
168
+ end
169
+
170
+ it 'supports different exceptions' do
171
+ expect {
172
+ expect { 123 }.to be_overrated
173
+ }.to fail_including(
174
+ "expected #{Berater::RateLimiter::Overrated} to be raised"
175
+ )
176
+
177
+ expect {
178
+ expect {
179
+ raise Berater::ConcurrencyLimiter::Incapacitated
180
+ }.not_to be_incapacitated
181
+ }.to fail_including(
182
+ "did not expect #{Berater::ConcurrencyLimiter::Incapacitated} to be raised"
183
+ )
184
+ end
185
+ end
118
186
  end
@@ -1,12 +1,12 @@
1
1
  describe Berater::RateLimiter do
2
- it_behaves_like 'a limiter', Berater.new(:key, :rate, 3, :second)
2
+ it_behaves_like 'a limiter', Berater.new(:key, 3, :second)
3
3
 
4
4
  describe '.new' do
5
5
  let(:limiter) { described_class.new(:key, 1, :second) }
6
6
 
7
7
  it 'initializes' do
8
8
  expect(limiter.key).to be :key
9
- expect(limiter.count).to eq 1
9
+ expect(limiter.capacity).to eq 1
10
10
  expect(limiter.interval).to eq :second
11
11
  end
12
12
 
@@ -15,82 +15,48 @@ describe Berater::RateLimiter do
15
15
  end
16
16
  end
17
17
 
18
- describe '#count' do
19
- def expect_count(count)
20
- limiter = described_class.new(:key, count, :second)
21
- expect(limiter.count).to eq count
18
+ describe '#capacity' do
19
+ def expect_capacity(capacity)
20
+ limiter = described_class.new(:key, capacity, :second)
21
+ expect(limiter.capacity).to eq capacity
22
22
  end
23
23
 
24
- it { expect_count(0) }
25
- it { expect_count(1) }
26
- it { expect_count(100) }
24
+ it { expect_capacity(0) }
25
+ it { expect_capacity(1) }
26
+ it { expect_capacity(1.5) }
27
+ it { expect_capacity(100) }
27
28
 
28
29
  context 'with erroneous values' do
29
- def expect_bad_count(count)
30
+ def expect_bad_capacity(capacity)
30
31
  expect do
31
- described_class.new(:key, count, :second)
32
+ described_class.new(:key, capacity, :second)
32
33
  end.to raise_error ArgumentError
33
34
  end
34
35
 
35
- it { expect_bad_count(0.5) }
36
- it { expect_bad_count(-1) }
37
- it { expect_bad_count('1') }
38
- it { expect_bad_count(:one) }
36
+ it { expect_bad_capacity(-1) }
37
+ it { expect_bad_capacity('1') }
38
+ it { expect_bad_capacity(:one) }
39
39
  end
40
40
  end
41
41
 
42
42
  describe '#interval' do
43
- def expect_interval(interval, expected)
44
- limiter = described_class.new(:key, 1, interval)
45
- expect(limiter.interval).to eq expected
46
- end
47
-
48
- context 'with ints' do
49
- it { expect_interval(0, 0) }
50
- it { expect_interval(1, 1) }
51
- it { expect_interval(33, 33) }
52
- end
53
-
54
- context 'with symbols' do
55
- it { expect_interval(:sec, :second) }
56
- it { expect_interval(:second, :second) }
57
- it { expect_interval(:seconds, :second) }
58
-
59
- it { expect_interval(:min, :minute) }
60
- it { expect_interval(:minute, :minute) }
61
- it { expect_interval(:minutes, :minute) }
62
-
63
- it { expect_interval(:hour, :hour) }
64
- it { expect_interval(:hours, :hour) }
65
- end
43
+ # see spec/utils_spec.rb for more
66
44
 
67
- context 'with strings' do
68
- it { expect_interval('sec', :second) }
69
- it { expect_interval('minute', :minute) }
70
- it { expect_interval('hours', :hour) }
71
- end
45
+ subject { described_class.new(:key, 1, :second) }
72
46
 
73
- context 'with erroneous values' do
74
- def expect_bad_interval(interval)
75
- expect do
76
- described_class.new(:key, 1, interval)
77
- end.to raise_error(ArgumentError)
78
- end
79
-
80
- it { expect_bad_interval(-1) }
81
- it { expect_bad_interval(:secondz) }
82
- it { expect_bad_interval('huor') }
47
+ it 'saves the interval in original and millisecond format' do
48
+ expect(subject.interval).to be :second
49
+ expect(subject.instance_variable_get(:@interval_msec)).to be 10**3
83
50
  end
84
51
 
85
- context 'interprets values' do
86
- def expect_sec(interval, expected)
87
- limiter = described_class.new(:key, 1, interval)
88
- expect(limiter.instance_variable_get(:@interval_sec)).to eq expected
89
- end
52
+ it 'must be > 0' do
53
+ expect {
54
+ described_class.new(:key, 1, 0)
55
+ }.to raise_error(ArgumentError)
90
56
 
91
- it { expect_sec(:second, 1) }
92
- it { expect_sec(:minute, 60) }
93
- it { expect_sec(:hour, 3600) }
57
+ expect {
58
+ described_class.new(:key, 1, -1)
59
+ }.to raise_error(ArgumentError)
94
60
  end
95
61
  end
96
62
 
@@ -112,50 +78,132 @@ describe Berater::RateLimiter do
112
78
  expect(limiter).to be_overrated
113
79
  end
114
80
 
115
- it 'limit resets over time' do
81
+ it 'resets limit over time' do
116
82
  3.times { limiter.limit }
117
83
  expect(limiter).to be_overrated
118
84
 
119
- # travel forward a second
120
85
  Timecop.freeze(1)
121
86
 
122
87
  3.times { limiter.limit }
123
88
  expect(limiter).to be_overrated
124
89
  end
125
- end
126
90
 
127
- context 'with same key, different limiters' do
128
- let(:limiter_one) { described_class.new(:key, 1, :second) }
129
- let(:limiter_two) { described_class.new(:key, 1, :second) }
91
+ context 'with millisecond precision' do
92
+ it 'resets limit over time' do
93
+ 3.times { limiter.limit }
94
+ expect(limiter).to be_overrated
130
95
 
131
- it 'works as expected' do
132
- expect(limiter_one.limit).not_to be_overrated
96
+ # travel forward to just before the count decrements
97
+ Timecop.freeze(0.333)
98
+ expect(limiter).to be_overrated
133
99
 
134
- expect(limiter_one).to be_overrated
135
- expect(limiter_two).to be_overrated
100
+ # traveling one more millisecond will decrement the count
101
+ Timecop.freeze(0.001)
102
+ limiter.limit
103
+ expect(limiter).to be_overrated
104
+ end
105
+
106
+ it 'works when drip rate is < 1 per millisecond' do
107
+ limiter = described_class.new(:key, 2_000, :second)
108
+
109
+ limiter.capacity.times { limiter.limit }
110
+ expect(limiter).to be_overrated
111
+
112
+ Timecop.freeze(0.001)
113
+ expect(limiter).not_to be_overrated
114
+
115
+ 2.times { limiter.limit }
116
+ end
136
117
  end
137
- end
138
118
 
139
- context 'with different keys, different limiters' do
140
- let(:limiter_one) { described_class.new(:one, 1, :second) }
141
- let(:limiter_two) { described_class.new(:two, 2, :second) }
119
+ context 'when capacity is a Float' do
120
+ let(:limiter) { described_class.new(:key, 1.5, :second) }
121
+
122
+ it 'still works' do
123
+ limiter.limit
124
+ expect(limiter).not_to be_overrated
125
+
126
+ expect { limiter.limit }.to be_overrated
127
+
128
+ limiter.limit(cost: 0.5)
129
+ end
130
+ end
131
+
132
+ it 'accepts a dynamic capacity' do
133
+ limiter = described_class.new(:key, 1, :second)
134
+
135
+ expect { limiter.limit(capacity: 0) }.to be_overrated
136
+ 5.times { limiter.limit(capacity: 10) }
137
+ expect { limiter }.to be_overrated
138
+ end
139
+
140
+ context 'works with cost parameter' do
141
+ it { expect { limiter.limit(cost: 4) }.to be_overrated }
142
+
143
+ it 'works within limit' do
144
+ limiter.limit(cost: 3)
145
+ expect { limiter.limit }.to be_overrated
146
+ end
147
+
148
+ it 'resets over time' do
149
+ limiter.limit(cost: 3)
150
+ expect(limiter).to be_overrated
151
+
152
+ Timecop.freeze(1)
153
+ expect(limiter).not_to be_overrated
154
+ end
155
+
156
+ it 'can be a Float' do
157
+ 2.times { limiter.limit(cost: 1.5) }
158
+ expect(limiter).to be_overrated
159
+ end
160
+ end
161
+
162
+ context 'with same key, different limiters' do
163
+ let(:limiter_one) { described_class.new(:key, 1, :second) }
164
+ let(:limiter_two) { described_class.new(:key, 1, :second) }
165
+
166
+ it 'works as expected' do
167
+ expect(limiter_one.limit).not_to be_overrated
168
+
169
+ expect(limiter_one).to be_overrated
170
+ expect(limiter_two).to be_overrated
171
+ end
172
+ end
173
+
174
+ context 'with different keys, different limiters' do
175
+ let(:limiter_one) { described_class.new(:one, 1, :second) }
176
+ let(:limiter_two) { described_class.new(:two, 2, :second) }
177
+
178
+ it 'works as expected' do
179
+ expect(limiter_one.limit).not_to be_overrated
180
+ expect(limiter_two.limit).not_to be_overrated
181
+
182
+ expect(limiter_one).to be_overrated
183
+ expect(limiter_two.limit).not_to be_overrated
142
184
 
143
- it 'works as expected' do
144
- expect(limiter_one.limit).not_to be_overrated
145
- expect(limiter_two.limit).not_to be_overrated
185
+ expect(limiter_one).to be_overrated
186
+ expect(limiter_two).to be_overrated
187
+ end
188
+ end
189
+ end
146
190
 
147
- expect(limiter_one).to be_overrated
148
- expect(limiter_two.limit).not_to be_overrated
191
+ describe '#overloaded?' do
192
+ let(:limiter) { described_class.new(:key, 1, :second) }
149
193
 
150
- expect(limiter_one).to be_overrated
151
- expect(limiter_two).to be_overrated
194
+ it 'works' do
195
+ expect(limiter.overloaded?).to be false
196
+ limiter.limit
197
+ expect(limiter.overloaded?).to be true
198
+ Timecop.freeze(1)
199
+ expect(limiter.overloaded?).to be false
152
200
  end
153
201
  end
154
202
 
155
203
  describe '#to_s' do
156
- def check(count, interval, expected)
204
+ def check(capacity, interval, expected)
157
205
  expect(
158
- described_class.new(:key, count, interval).to_s
206
+ described_class.new(:key, capacity, interval).to_s
159
207
  ).to match(expected)
160
208
  end
161
209
 
@@ -171,16 +219,6 @@ describe Berater::RateLimiter do
171
219
  check(1, 'hour', /1 per hour/)
172
220
  end
173
221
 
174
- it 'normalizes' do
175
- check(1, :sec, /1 per second/)
176
- check(1, :seconds, /1 per second/)
177
-
178
- check(1, :min, /1 per minute/)
179
- check(1, :minutes, /1 per minute/)
180
-
181
- check(1, :hours, /1 per hour/)
182
- end
183
-
184
222
  it 'works with integers' do
185
223
  check(1, 1, /1 every second/)
186
224
  check(1, 2, /1 every 2 seconds/)