rediska 0.0.11 → 0.1.0
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.
- checksums.yaml +4 -4
- data/Gemfile.lock +18 -14
- data/lib/rediska/command_executor.rb +25 -0
- data/lib/rediska/connection.rb +8 -1
- data/lib/rediska/driver.rb +30 -56
- data/lib/rediska/sort_method.rb +108 -0
- data/lib/rediska/transaction_commands.rb +83 -0
- data/lib/rediska/version.rb +1 -1
- data/rediska.gemspec +1 -1
- data/spec/lib/rediska/driver_spec.rb +5 -5
- data/spec/redis_spec.rb +3 -0
- data/spec/support/connection.rb +15 -15
- data/spec/support/hashes.rb +51 -51
- data/spec/support/keys.rb +106 -61
- data/spec/support/lists.rb +37 -30
- data/spec/support/server.rb +23 -23
- data/spec/support/sets.rb +44 -44
- data/spec/support/sorted_method.rb +136 -0
- data/spec/support/sorted_sets.rb +140 -136
- data/spec/support/strings.rb +74 -74
- data/spec/support/transactions.rb +65 -12
- data/spec/support/upcase_method_names.rb +2 -2
- metadata +22 -17
data/lib/rediska/version.rb
CHANGED
data/rediska.gemspec
CHANGED
@@ -19,7 +19,7 @@ Gem::Specification.new do |s|
|
|
19
19
|
s.require_paths = ['lib']
|
20
20
|
|
21
21
|
s.add_runtime_dependency 'redis', '~> 3.0.0'
|
22
|
-
s.add_development_dependency 'rspec'
|
22
|
+
s.add_development_dependency 'rspec'
|
23
23
|
s.add_development_dependency 'coveralls'
|
24
24
|
s.add_development_dependency 'rake'
|
25
25
|
end
|
@@ -5,23 +5,23 @@ describe Rediska::Driver do
|
|
5
5
|
|
6
6
|
describe '#time' do
|
7
7
|
before(:each) do
|
8
|
-
Time.
|
8
|
+
allow(Time).to receive_message_chain(:now, :to_f).and_return(1397845595.5139461)
|
9
9
|
end
|
10
10
|
|
11
11
|
it 'is an array' do
|
12
|
-
subject.time.
|
12
|
+
expect(subject.time).to be_an_instance_of(Array)
|
13
13
|
end
|
14
14
|
|
15
15
|
it 'has two elements' do
|
16
|
-
subject.time.count.
|
16
|
+
expect(subject.time.count).to eq(2)
|
17
17
|
end
|
18
18
|
|
19
19
|
it 'has the current time in seconds' do
|
20
|
-
subject.time.first.
|
20
|
+
expect(subject.time.first).to eq(1397845595)
|
21
21
|
end
|
22
22
|
|
23
23
|
it 'has the current leftover microseconds' do
|
24
|
-
subject.time.last.
|
24
|
+
expect(subject.time.last).to eq(513946)
|
25
25
|
end
|
26
26
|
end
|
27
27
|
end
|
data/spec/redis_spec.rb
CHANGED
@@ -27,6 +27,7 @@ describe 'Rediska' do
|
|
27
27
|
context 'memory' do
|
28
28
|
before do
|
29
29
|
subject.flushall
|
30
|
+
subject.discard rescue nil
|
30
31
|
end
|
31
32
|
|
32
33
|
it_behaves_like 'redis'
|
@@ -39,6 +40,7 @@ describe 'Rediska' do
|
|
39
40
|
end
|
40
41
|
|
41
42
|
subject.flushall
|
43
|
+
subject.discard rescue nil
|
42
44
|
end
|
43
45
|
|
44
46
|
it_behaves_like 'redis'
|
@@ -48,6 +50,7 @@ describe 'Rediska' do
|
|
48
50
|
pending 'real redis (interoperability)' do
|
49
51
|
before do
|
50
52
|
subject.flushall
|
53
|
+
subject.discard rescue nil
|
51
54
|
end
|
52
55
|
|
53
56
|
before(:all) do
|
data/spec/support/connection.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
shared_examples 'connection' do
|
2
2
|
it 'should authenticate to the server' do
|
3
3
|
begin
|
4
|
-
subject.auth('pass').
|
4
|
+
expect(subject.auth('pass')).to eq('OK')
|
5
5
|
rescue Redis::CommandError => e
|
6
6
|
raise unless e.message == 'ERR Client sent AUTH, but no password is set'
|
7
7
|
end
|
@@ -12,28 +12,28 @@ shared_examples 'connection' do
|
|
12
12
|
subject2 = Redis.new(host: '127.0.0.1', port: 6379)
|
13
13
|
|
14
14
|
subject1.set('key1', '1')
|
15
|
-
subject2.get('key1').
|
15
|
+
expect(subject2.get('key1')).to eq('1')
|
16
16
|
|
17
17
|
subject2.set('key2', '2')
|
18
|
-
subject1.get('key2').
|
18
|
+
expect(subject1.get('key2')).to eq('2')
|
19
19
|
|
20
|
-
subject1.get('key3').
|
21
|
-
subject2.get('key3').
|
20
|
+
expect(subject1.get('key3')).to be_nil
|
21
|
+
expect(subject2.get('key3')).to be_nil
|
22
22
|
|
23
|
-
subject1.dbsize.
|
24
|
-
subject2.dbsize.
|
23
|
+
expect(subject1.dbsize).to eq(2)
|
24
|
+
expect(subject2.dbsize).to eq(2)
|
25
25
|
end
|
26
26
|
|
27
27
|
it 'should connect to a specific database' do
|
28
28
|
subject1 = Redis.new(host: '127.0.0.1', port: 6379, db: 0)
|
29
29
|
subject1.set('key1', '1')
|
30
30
|
subject1.select(0)
|
31
|
-
subject1.get('key1').
|
31
|
+
expect(subject1.get('key1')).to eq('1')
|
32
32
|
|
33
33
|
subject2 = Redis.new(host: '127.0.0.1', port: 6379, db: 1)
|
34
34
|
subject2.set('key1', '1')
|
35
35
|
subject2.select(1)
|
36
|
-
subject2.get('key1').
|
36
|
+
expect(subject2.get('key1')).to eq('1')
|
37
37
|
end
|
38
38
|
|
39
39
|
it 'should handle multiple clients using the same db instance' do
|
@@ -41,25 +41,25 @@ shared_examples 'connection' do
|
|
41
41
|
subject2 = Redis.new(host: '127.0.0.1', port: 6379, db: 2)
|
42
42
|
|
43
43
|
subject1.set('key1', 'one')
|
44
|
-
subject1.get('key1').
|
44
|
+
expect(subject1.get('key1')).to eq('one')
|
45
45
|
|
46
46
|
subject2.set('key2', 'two')
|
47
|
-
subject2.get('key2').
|
47
|
+
expect(subject2.get('key2')).to eq('two')
|
48
48
|
|
49
|
-
subject1.get('key1').
|
49
|
+
expect(subject1.get('key1')).to eq('one')
|
50
50
|
end
|
51
51
|
|
52
52
|
it 'should not error with a disconnected client' do
|
53
53
|
subject1 = Redis.new
|
54
54
|
subject1.client.disconnect
|
55
|
-
subject1.get('key1').
|
55
|
+
expect(subject1.get('key1')).to be_nil
|
56
56
|
end
|
57
57
|
|
58
58
|
it 'should echo the given string' do
|
59
|
-
subject.echo('something').
|
59
|
+
expect(subject.echo('something')).to eq('something')
|
60
60
|
end
|
61
61
|
|
62
62
|
it 'should ping the server' do
|
63
|
-
subject.ping.
|
63
|
+
expect(subject.ping).to eq('PONG')
|
64
64
|
end
|
65
65
|
end
|
data/spec/support/hashes.rb
CHANGED
@@ -2,102 +2,102 @@ shared_examples 'hashes' do
|
|
2
2
|
it 'should delete a hash field' do
|
3
3
|
subject.hset('key1', 'k1', 'val1')
|
4
4
|
subject.hset('key1', 'k2', 'val2')
|
5
|
-
subject.hdel('key1', 'k1')
|
5
|
+
expect(subject.hdel('key1', 'k1')).to eq(1)
|
6
6
|
|
7
|
-
subject.hget('key1', 'k1').
|
8
|
-
subject.hget('key1', 'k2').
|
7
|
+
expect(subject.hget('key1', 'k1')).to be_nil
|
8
|
+
expect(subject.hget('key1', 'k2')).to eq('val2')
|
9
9
|
end
|
10
10
|
|
11
11
|
it 'should remove a hash with no keys left' do
|
12
12
|
subject.hset('key1', 'k1', 'val1')
|
13
13
|
subject.hset('key1', 'k2', 'val2')
|
14
|
-
subject.hdel('key1', 'k1')
|
15
|
-
subject.hdel('key1', 'k2')
|
14
|
+
expect(subject.hdel('key1', 'k1')).to eq(1)
|
15
|
+
expect(subject.hdel('key1', 'k2')).to eq(1)
|
16
16
|
|
17
|
-
subject.exists('key1').
|
17
|
+
expect(subject.exists('key1')).to be_falsey
|
18
18
|
end
|
19
19
|
|
20
20
|
it 'should convert key to a string for hset' do
|
21
21
|
m = double('key')
|
22
|
-
m.
|
22
|
+
allow(m).to receive(:to_s).and_return('foo')
|
23
23
|
|
24
24
|
subject.hset('key1', m, 'bar')
|
25
|
-
subject.hget('key1', 'foo').
|
25
|
+
expect(subject.hget('key1', 'foo')).to eq('bar')
|
26
26
|
end
|
27
27
|
|
28
28
|
it 'should convert key to a string for hget' do
|
29
29
|
m = double('key')
|
30
|
-
m.
|
30
|
+
allow(m).to receive(:to_s).and_return('foo')
|
31
31
|
|
32
32
|
subject.hset('key1', 'foo', 'bar')
|
33
|
-
subject.hget('key1', m).
|
33
|
+
expect(subject.hget('key1', m)).to eq('bar')
|
34
34
|
end
|
35
35
|
|
36
36
|
it 'should determine if a hash field exists' do
|
37
37
|
subject.hset('key1', 'index', 'value')
|
38
38
|
|
39
|
-
subject.hexists('key1', 'index').
|
40
|
-
subject.hexists('key2', 'i2').
|
39
|
+
expect(subject.hexists('key1', 'index')).to be_truthy
|
40
|
+
expect(subject.hexists('key2', 'i2')).to be_falsey
|
41
41
|
end
|
42
42
|
|
43
43
|
it 'should get the value of a hash field' do
|
44
44
|
subject.hset('key1', 'index', 'value')
|
45
45
|
|
46
|
-
subject.hget('key1', 'index').
|
46
|
+
expect(subject.hget('key1', 'index')).to eq('value')
|
47
47
|
end
|
48
48
|
|
49
49
|
it 'should get all the fields and values in a hash' do
|
50
50
|
subject.hset('key1', 'i1', 'val1')
|
51
51
|
subject.hset('key1', 'i2', 'val2')
|
52
52
|
|
53
|
-
subject.hgetall('key1').
|
53
|
+
expect(subject.hgetall('key1')).to eq({'i1' => 'val1', 'i2' => 'val2'})
|
54
54
|
end
|
55
55
|
|
56
56
|
it 'should increment the integer value of a hash field by the given number' do
|
57
57
|
subject.hset('key1', 'cont1', '5')
|
58
|
-
subject.hincrby('key1', 'cont1', '5').
|
59
|
-
subject.hget('key1', 'cont1').
|
58
|
+
expect(subject.hincrby('key1', 'cont1', '5')).to eq(10)
|
59
|
+
expect(subject.hget('key1', 'cont1')).to eq('10')
|
60
60
|
end
|
61
61
|
|
62
62
|
it 'should increment non existing hash keys' do
|
63
|
-
subject.hget('key1', 'cont2').
|
64
|
-
subject.hincrby('key1', 'cont2', '5').
|
63
|
+
expect(subject.hget('key1', 'cont2')).to be_nil
|
64
|
+
expect(subject.hincrby('key1', 'cont2', '5')).to eq(5)
|
65
65
|
end
|
66
66
|
|
67
67
|
it 'should increment the float value of a hash field by the given float' do
|
68
68
|
subject.hset('key1', 'cont1', 5.0)
|
69
|
-
subject.hincrbyfloat('key1', 'cont1', 4.1).
|
70
|
-
subject.hget('key1', 'cont1').
|
69
|
+
expect(subject.hincrbyfloat('key1', 'cont1', 4.1)).to eq(9.1)
|
70
|
+
expect(subject.hget('key1', 'cont1')).to eq('9.1')
|
71
71
|
end
|
72
72
|
|
73
73
|
it 'should increment non existing hash keys' do
|
74
|
-
subject.hget('key1', 'cont2').
|
75
|
-
subject.hincrbyfloat('key1', 'cont2', 5.5).
|
74
|
+
expect(subject.hget('key1', 'cont2')).to be_nil
|
75
|
+
expect(subject.hincrbyfloat('key1', 'cont2', 5.5)).to eq(5.5)
|
76
76
|
end
|
77
77
|
|
78
78
|
it 'should get all the fields in a hash' do
|
79
79
|
subject.hset('key1', 'i1', 'val1')
|
80
80
|
subject.hset('key1', 'i2', 'val2')
|
81
81
|
|
82
|
-
subject.hkeys('key1').
|
83
|
-
subject.hkeys('key2').
|
82
|
+
expect(subject.hkeys('key1')).to eq(['i1', 'i2'])
|
83
|
+
expect(subject.hkeys('key2')).to be_empty
|
84
84
|
end
|
85
85
|
|
86
86
|
it 'should get the number of fields in a hash' do
|
87
87
|
subject.hset('key1', 'i1', 'val1')
|
88
88
|
subject.hset('key1', 'i2', 'val2')
|
89
89
|
|
90
|
-
subject.hlen('key1').
|
90
|
+
expect(subject.hlen('key1')).to eq(2)
|
91
91
|
end
|
92
92
|
|
93
93
|
it 'should get the values of all the given hash fields' do
|
94
94
|
subject.hset('key1', 'i1', 'val1')
|
95
95
|
subject.hset('key1', 'i2', 'val2')
|
96
96
|
|
97
|
-
subject.hmget('key1', 'i1', 'i2', 'i3').
|
98
|
-
subject.hmget('key1', ['i1', 'i2', 'i3']).
|
97
|
+
expect(subject.hmget('key1', 'i1', 'i2', 'i3')).to eq(['val1', 'val2', nil])
|
98
|
+
expect(subject.hmget('key1', ['i1', 'i2', 'i3'])).to match_array(['val1', 'val2', nil])
|
99
99
|
|
100
|
-
subject.hmget('key2', 'i1', 'i2').
|
100
|
+
expect(subject.hmget('key2', 'i1', 'i2')).to eq([nil, nil])
|
101
101
|
end
|
102
102
|
|
103
103
|
it 'should throw an argument error when you do not ask for any keys' do
|
@@ -111,7 +111,7 @@ shared_examples 'hashes' do
|
|
111
111
|
subject.hmset('key')
|
112
112
|
}.to raise_error(Redis::CommandError)
|
113
113
|
|
114
|
-
subject.exists('key').
|
114
|
+
expect(subject.exists('key')).to be_falsey
|
115
115
|
end
|
116
116
|
|
117
117
|
it 'rejects an insert with a key but no value' do
|
@@ -123,7 +123,7 @@ shared_examples 'hashes' do
|
|
123
123
|
subject.hmset('key', 'foo', 3, 'bar')
|
124
124
|
}.to raise_error(Redis::CommandError)
|
125
125
|
|
126
|
-
subject.exists('key').
|
126
|
+
expect(subject.exists('key')).to be_falsey
|
127
127
|
end
|
128
128
|
|
129
129
|
it 'should reject the wrong number of arguments' do
|
@@ -135,48 +135,48 @@ shared_examples 'hashes' do
|
|
135
135
|
it 'should set multiple hash fields to multiple values' do
|
136
136
|
subject.hmset('key', 'k1', 'value1', 'k2', 'value2')
|
137
137
|
|
138
|
-
subject.hget('key', 'k1').
|
139
|
-
subject.hget('key', 'k2').
|
138
|
+
expect(subject.hget('key', 'k1')).to eq('value1')
|
139
|
+
expect(subject.hget('key', 'k2')).to eq('value2')
|
140
140
|
end
|
141
141
|
|
142
142
|
it 'should set multiple hash fields from a ruby hash to multiple values' do
|
143
143
|
subject.mapped_hmset('foo', k1: 'value1', k2: 'value2')
|
144
144
|
|
145
|
-
subject.hget('foo', 'k1').
|
146
|
-
subject.hget('foo', 'k2').
|
145
|
+
expect(subject.hget('foo', 'k1')).to eq('value1')
|
146
|
+
expect(subject.hget('foo', 'k2')).to eq('value2')
|
147
147
|
end
|
148
148
|
|
149
149
|
it 'should set the string value of a hash field' do
|
150
|
-
subject.hset('key1', 'k1', 'val1').
|
151
|
-
subject.hset('key1', 'k1', 'val1').
|
150
|
+
expect(subject.hset('key1', 'k1', 'val1')).to be_truthy
|
151
|
+
expect(subject.hset('key1', 'k1', 'val1')).to be_falsey
|
152
152
|
|
153
|
-
subject.hget('key1', 'k1').
|
153
|
+
expect(subject.hget('key1', 'k1')).to eq('val1')
|
154
154
|
end
|
155
155
|
|
156
156
|
it 'should set the value of a hash field, only if the field does not exist' do
|
157
157
|
subject.hset('key1', 'k1', 'val1')
|
158
|
-
subject.hsetnx('key1', 'k1', 'value').
|
159
|
-
subject.hsetnx('key1', 'k2', 'val2').
|
160
|
-
subject.hsetnx('key1', :k1, 'value').
|
161
|
-
subject.hsetnx('key1', :k3, 'val3').
|
158
|
+
expect(subject.hsetnx('key1', 'k1', 'value')).to be_falsey
|
159
|
+
expect(subject.hsetnx('key1', 'k2', 'val2')).to be_truthy
|
160
|
+
expect(subject.hsetnx('key1', :k1, 'value')).to be_falsey
|
161
|
+
expect(subject.hsetnx('key1', :k3, 'val3')).to be_truthy
|
162
162
|
|
163
|
-
subject.hget('key1', 'k1').
|
164
|
-
subject.hget('key1', 'k2').
|
165
|
-
subject.hget('key1', 'k3').
|
163
|
+
expect(subject.hget('key1', 'k1')).to eq('val1')
|
164
|
+
expect(subject.hget('key1', 'k2')).to eq('val2')
|
165
|
+
expect(subject.hget('key1', 'k3')).to eq('val3')
|
166
166
|
end
|
167
167
|
|
168
168
|
it 'should get all the values in a hash' do
|
169
169
|
subject.hset('key1', 'k1', 'val1')
|
170
170
|
subject.hset('key1', 'k2', 'val2')
|
171
171
|
|
172
|
-
subject.hvals('key1').
|
172
|
+
expect(subject.hvals('key1')).to eq(['val1', 'val2'])
|
173
173
|
end
|
174
174
|
|
175
175
|
it 'should accept a list of array pairs as arguments and not throw an invalid argument number error' do
|
176
176
|
subject.hmset('key1', [:k1, 'val1'], [:k2, 'val2'], [:k3, 'val3'])
|
177
|
-
subject.hget('key1', :k1).
|
178
|
-
subject.hget('key1', :k2).
|
179
|
-
subject.hget('key1', :k3).
|
177
|
+
expect(subject.hget('key1', :k1)).to eq('val1')
|
178
|
+
expect(subject.hget('key1', :k2)).to eq('val2')
|
179
|
+
expect(subject.hget('key1', :k3)).to eq('val3')
|
180
180
|
end
|
181
181
|
|
182
182
|
it 'should reject a list of arrays that contain an invalid number of arguments' do
|
@@ -187,16 +187,16 @@ shared_examples 'hashes' do
|
|
187
187
|
|
188
188
|
it 'should convert a integer field name to string for hdel' do
|
189
189
|
subject.hset('key1', '1', 1)
|
190
|
-
subject.hdel('key1', 1).
|
190
|
+
expect(subject.hdel('key1', 1)).to eq(1)
|
191
191
|
end
|
192
192
|
|
193
193
|
it 'should convert a integer field name to string for hexists' do
|
194
194
|
subject.hset('key1', '1', 1)
|
195
|
-
subject.hexists('key1', 1).
|
195
|
+
expect(subject.hexists('key1', 1)).to be_truthy
|
196
196
|
end
|
197
197
|
|
198
198
|
it 'should convert a integer field name to string for hincrby' do
|
199
199
|
subject.hset('key1', 1, 0)
|
200
|
-
subject.hincrby('key1', 1, 1).
|
200
|
+
expect(subject.hincrby('key1', 1, 1)).to eq(1)
|
201
201
|
end
|
202
202
|
end
|
data/spec/support/keys.rb
CHANGED
@@ -4,7 +4,7 @@ shared_examples 'keys' do
|
|
4
4
|
subject.set('key2', '2')
|
5
5
|
subject.del('key1', 'key2')
|
6
6
|
|
7
|
-
subject.get('key1').
|
7
|
+
expect(subject.get('key1')).to be_nil
|
8
8
|
end
|
9
9
|
|
10
10
|
it 'should delete multiple keys' do
|
@@ -12,8 +12,8 @@ shared_examples 'keys' do
|
|
12
12
|
subject.set('key2', '2')
|
13
13
|
subject.del(['key1', 'key2'])
|
14
14
|
|
15
|
-
subject.get('key1').
|
16
|
-
subject.get('key2').
|
15
|
+
expect(subject.get('key1')).to be_nil
|
16
|
+
expect(subject.get('key2')).to be_nil
|
17
17
|
end
|
18
18
|
|
19
19
|
it 'should error deleting no keys' do
|
@@ -29,22 +29,22 @@ shared_examples 'keys' do
|
|
29
29
|
it 'should determine if a key exists' do
|
30
30
|
subject.set('key1', '1')
|
31
31
|
|
32
|
-
subject.exists('key1').
|
33
|
-
subject.exists('key2').
|
32
|
+
expect(subject.exists('key1')).to be_truthy
|
33
|
+
expect(subject.exists('key2')).to be_falsey
|
34
34
|
end
|
35
35
|
|
36
36
|
it "should set a key's time to live in seconds" do
|
37
37
|
subject.set('key1', '1')
|
38
38
|
subject.expire('key1', 1)
|
39
39
|
|
40
|
-
subject.ttl('key1').
|
40
|
+
expect(subject.ttl('key1')).to eq(1)
|
41
41
|
end
|
42
42
|
|
43
43
|
it "should set the expiration for a key as a UNIX timestamp" do
|
44
44
|
subject.set('key1', '1')
|
45
45
|
subject.expireat('key1', Time.now.to_i + 100)
|
46
46
|
|
47
|
-
subject.ttl('key1').
|
47
|
+
expect(subject.ttl('key1')).not_to eq(-1)
|
48
48
|
end
|
49
49
|
|
50
50
|
it 'should not have an expiration after re-set' do
|
@@ -52,21 +52,21 @@ shared_examples 'keys' do
|
|
52
52
|
subject.expireat('key1', Time.now.to_i + 2)
|
53
53
|
subject.set('key1', '1')
|
54
54
|
|
55
|
-
subject.ttl('key1').
|
55
|
+
expect(subject.ttl('key1')).to eq(-1)
|
56
56
|
end
|
57
57
|
|
58
58
|
it 'should not have a ttl if expired (and thus key does not exist)' do
|
59
59
|
subject.set('key1', '1')
|
60
60
|
subject.expireat('key1', Time.now.to_i)
|
61
61
|
|
62
|
-
subject.ttl('key1').
|
62
|
+
expect(subject.ttl('key1')).to eq(-2)
|
63
63
|
end
|
64
64
|
|
65
65
|
it 'should not find a key if expired' do
|
66
66
|
subject.set('key1', '1')
|
67
67
|
subject.expireat('key1', Time.now.to_i)
|
68
68
|
|
69
|
-
subject.get('key1').
|
69
|
+
expect(subject.get('key1')).to be_nil
|
70
70
|
end
|
71
71
|
|
72
72
|
it 'should not find multiple keys if expired' do
|
@@ -74,7 +74,7 @@ shared_examples 'keys' do
|
|
74
74
|
subject.set('key2', '2')
|
75
75
|
subject.expireat('key1', Time.now.to_i)
|
76
76
|
|
77
|
-
subject.mget('key1', 'key2').
|
77
|
+
expect(subject.mget('key1', 'key2')).to eq([nil, '2'])
|
78
78
|
end
|
79
79
|
|
80
80
|
it 'should only find keys that are not expired' do
|
@@ -82,14 +82,14 @@ shared_examples 'keys' do
|
|
82
82
|
subject.set('key2', '2')
|
83
83
|
subject.expireat('key1', Time.now.to_i)
|
84
84
|
|
85
|
-
subject.keys.
|
85
|
+
expect(subject.keys).to eq(['key2'])
|
86
86
|
end
|
87
87
|
|
88
88
|
it 'should not exist if expired' do
|
89
89
|
subject.set('key1', '1')
|
90
90
|
subject.expireat('key1', Time.now.to_i)
|
91
91
|
|
92
|
-
subject.exists('key1').
|
92
|
+
expect(subject.exists('key1')).to be_falsey
|
93
93
|
end
|
94
94
|
|
95
95
|
it 'should find all keys matching the given pattern' do
|
@@ -101,32 +101,32 @@ shared_examples 'keys' do
|
|
101
101
|
|
102
102
|
subject.mset('database', 1, 'above', 2, 'suitability', 3, 'able', 4)
|
103
103
|
|
104
|
-
subject.keys('key:*').
|
105
|
-
subject.keys('ab*').
|
104
|
+
expect(subject.keys('key:*')).to match_array(['key:a', 'key:b', 'key:c'])
|
105
|
+
expect(subject.keys('ab*')).to match_array(['above', 'able'])
|
106
106
|
end
|
107
107
|
|
108
108
|
it 'should remove the expiration from a key' do
|
109
109
|
subject.set('key1', '1')
|
110
110
|
subject.expireat('key1', Time.now.to_i + 1)
|
111
|
-
subject.persist('key1').
|
112
|
-
subject.persist('key1').
|
111
|
+
expect(subject.persist('key1')).to be_truthy
|
112
|
+
expect(subject.persist('key1')).to be_falsey
|
113
113
|
|
114
|
-
subject.ttl('key1').
|
114
|
+
expect(subject.ttl('key1')).to eq(-1)
|
115
115
|
end
|
116
116
|
|
117
117
|
it 'should return a random key from the keyspace' do
|
118
118
|
subject.set('key1', '1')
|
119
119
|
subject.set('key2', '2')
|
120
120
|
|
121
|
-
['key1', 'key2'].
|
121
|
+
expect(['key1', 'key2']).to include(subject.randomkey)
|
122
122
|
end
|
123
123
|
|
124
124
|
it 'should rename a key' do
|
125
125
|
subject.set('key1', '2')
|
126
126
|
subject.rename('key1', 'key2')
|
127
127
|
|
128
|
-
subject.get('key1').
|
129
|
-
subject.get('key2').
|
128
|
+
expect(subject.get('key1')).to be_nil
|
129
|
+
expect(subject.get('key2')).to eq('2')
|
130
130
|
end
|
131
131
|
|
132
132
|
it 'should rename a key, only if new key does not exist' do
|
@@ -136,71 +136,67 @@ shared_examples 'keys' do
|
|
136
136
|
subject.renamenx('key1', 'key2')
|
137
137
|
subject.renamenx('key3', 'key4')
|
138
138
|
|
139
|
-
subject.get('key1').
|
140
|
-
subject.get('key2').
|
141
|
-
subject.get('key3').
|
142
|
-
subject.get('key4').
|
143
|
-
end
|
144
|
-
|
145
|
-
it 'should sort the elements in a list, set or sorted set' do
|
146
|
-
pending 'SORT Command not implemented yet'
|
139
|
+
expect(subject.get('key1')).to eq('1')
|
140
|
+
expect(subject.get('key2')).to eq('2')
|
141
|
+
expect(subject.get('key3')).to be_nil
|
142
|
+
expect(subject.get('key4')).to eq('3')
|
147
143
|
end
|
148
144
|
|
149
145
|
it 'should determine the type stored at key' do
|
150
146
|
subject.set('key1', '1')
|
151
147
|
|
152
148
|
# Non-existing key.
|
153
|
-
subject.type('key0').
|
149
|
+
expect(subject.type('key0')).to eq('none')
|
154
150
|
|
155
151
|
# String.
|
156
152
|
subject.set('key1', '1')
|
157
|
-
subject.type('key1').
|
153
|
+
expect(subject.type('key1')).to eq('string')
|
158
154
|
|
159
155
|
|
160
156
|
# List.
|
161
157
|
subject.lpush('key2', '1')
|
162
|
-
subject.type('key2').
|
158
|
+
expect(subject.type('key2')).to eq('list')
|
163
159
|
|
164
160
|
# Set.
|
165
161
|
subject.sadd('key3', '1')
|
166
|
-
subject.type('key3').
|
162
|
+
expect(subject.type('key3')).to eq('set')
|
167
163
|
|
168
164
|
# Sorted Set.
|
169
165
|
subject.zadd('key4', 1.0, '1')
|
170
|
-
subject.type('key4').
|
166
|
+
expect(subject.type('key4')).to eq('zset')
|
171
167
|
|
172
168
|
# Hash.
|
173
169
|
subject.hset('key5', 'a', '1')
|
174
|
-
subject.type('key5').
|
170
|
+
expect(subject.type('key5')).to eq('hash')
|
175
171
|
end
|
176
172
|
|
177
173
|
it 'should convert the value into a string before storing' do
|
178
174
|
subject.set('key1', 1)
|
179
|
-
subject.get('key1').
|
175
|
+
expect(subject.get('key1')).to eq('1')
|
180
176
|
|
181
177
|
subject.setex('key2', 30, 1)
|
182
|
-
subject.get('key2').
|
178
|
+
expect(subject.get('key2')).to eq('1')
|
183
179
|
|
184
180
|
subject.getset('key3', 1)
|
185
|
-
subject.get('key3').
|
181
|
+
expect(subject.get('key3')).to eq('1')
|
186
182
|
end
|
187
183
|
|
188
184
|
it "should return 'OK' for the setex command" do
|
189
|
-
subject.setex('key4', 30, 1).
|
185
|
+
expect(subject.setex('key4', 30, 1)).to eq('OK')
|
190
186
|
end
|
191
187
|
|
192
188
|
it 'should convert the key into a string before storing' do
|
193
189
|
subject.set(123, 'foo')
|
194
|
-
subject.keys.
|
195
|
-
subject.get('123').
|
190
|
+
expect(subject.keys).to include('123')
|
191
|
+
expect(subject.get('123')).to eq('foo')
|
196
192
|
|
197
193
|
subject.setex(456, 30, 'foo')
|
198
|
-
subject.keys.
|
199
|
-
subject.get('456').
|
194
|
+
expect(subject.keys).to include('456')
|
195
|
+
expect(subject.get('456')).to eq('foo')
|
200
196
|
|
201
197
|
subject.getset(789, 'foo')
|
202
|
-
subject.keys.
|
203
|
-
subject.get('789').
|
198
|
+
expect(subject.keys).to include('789')
|
199
|
+
expect(subject.get('789')).to eq('foo')
|
204
200
|
end
|
205
201
|
|
206
202
|
it 'should only operate against keys containing string values' do
|
@@ -229,26 +225,26 @@ shared_examples 'keys' do
|
|
229
225
|
subject.select(0)
|
230
226
|
subject.set('key1', '1')
|
231
227
|
|
232
|
-
subject.move('key1', 1).
|
228
|
+
expect(subject.move('key1', 1)).to be_truthy
|
233
229
|
|
234
230
|
subject.select(0)
|
235
|
-
subject.get('key1').
|
231
|
+
expect(subject.get('key1')).to be_nil
|
236
232
|
|
237
233
|
subject.select(1)
|
238
|
-
subject.get('key1').
|
234
|
+
expect(subject.get('key1')).to eq('1')
|
239
235
|
end
|
240
236
|
|
241
237
|
it 'should fail to move a key that does not exist in the source database' do
|
242
238
|
subject.select(0)
|
243
|
-
subject.get('key1').
|
239
|
+
expect(subject.get('key1')).to be_nil
|
244
240
|
|
245
|
-
subject.move('key1', 1).
|
241
|
+
expect(subject.move('key1', 1)).to be_falsey
|
246
242
|
|
247
243
|
subject.select(0)
|
248
|
-
subject.get('key1').
|
244
|
+
expect(subject.get('key1')).to be_nil
|
249
245
|
|
250
246
|
subject.select(1)
|
251
|
-
subject.get('key1').
|
247
|
+
expect(subject.get('key1')).to be_nil
|
252
248
|
end
|
253
249
|
|
254
250
|
it 'should fail to move a key that exists in the destination database' do
|
@@ -259,13 +255,13 @@ shared_examples 'keys' do
|
|
259
255
|
subject.set('key1', '2')
|
260
256
|
|
261
257
|
subject.select(0)
|
262
|
-
subject.move('key1', 1).
|
258
|
+
expect(subject.move('key1', 1)).to be_falsey
|
263
259
|
|
264
260
|
subject.select(0)
|
265
|
-
subject.get('key1').
|
261
|
+
expect(subject.get('key1')).to eq('1')
|
266
262
|
|
267
263
|
subject.select(1)
|
268
|
-
subject.get('key1').
|
264
|
+
expect(subject.get('key1')).to eq('2')
|
269
265
|
end
|
270
266
|
|
271
267
|
it 'should fail to move a key to the same database' do
|
@@ -277,7 +273,7 @@ shared_examples 'keys' do
|
|
277
273
|
}.to raise_error(Redis::CommandError, 'ERR source and destination objects are the same')
|
278
274
|
|
279
275
|
subject.select(0)
|
280
|
-
subject.get('key1').
|
276
|
+
expect(subject.get('key1')).to eq('1')
|
281
277
|
end
|
282
278
|
|
283
279
|
it 'should scan all keys in the database' do
|
@@ -293,8 +289,8 @@ shared_examples 'keys' do
|
|
293
289
|
break if cursor == '0'
|
294
290
|
end
|
295
291
|
|
296
|
-
all_keys.uniq.
|
297
|
-
all_keys[0].
|
292
|
+
expect(all_keys.uniq.size).to eq(100)
|
293
|
+
expect(all_keys[0]).to match(/key\d+/)
|
298
294
|
end
|
299
295
|
|
300
296
|
it "should match keys to a pattern when scanning" do
|
@@ -313,7 +309,7 @@ shared_examples 'keys' do
|
|
313
309
|
break if cursor == '0'
|
314
310
|
end
|
315
311
|
|
316
|
-
all_keys.uniq.
|
312
|
+
expect(all_keys.uniq.size).to eq(50)
|
317
313
|
end
|
318
314
|
|
319
315
|
it 'should specify doing more work when scanning' do
|
@@ -323,7 +319,56 @@ shared_examples 'keys' do
|
|
323
319
|
|
324
320
|
cursor, all_keys = subject.scan(cursor, count: 100)
|
325
321
|
|
326
|
-
cursor.
|
327
|
-
all_keys.uniq.
|
322
|
+
expect(cursor).to eq('0')
|
323
|
+
expect(all_keys.uniq.size).to eq(100)
|
324
|
+
end
|
325
|
+
|
326
|
+
context 'with extended options' do
|
327
|
+
it 'uses ex option to set the expire time, in seconds' do
|
328
|
+
ttl = 7
|
329
|
+
|
330
|
+
expect(subject.set('key1', '1', ex: ttl)).to eq('OK')
|
331
|
+
expect(subject.ttl('key1')).to eq(ttl)
|
332
|
+
end
|
333
|
+
|
334
|
+
it 'uses px option to set the expire time, in miliseconds' do
|
335
|
+
ttl = 7000
|
336
|
+
|
337
|
+
expect(subject.set('key1', '1', px: ttl)).to eq('OK')
|
338
|
+
expect(subject.ttl('key1')).to eq(ttl / 1000)
|
339
|
+
end
|
340
|
+
|
341
|
+
# Note that the redis-rb implementation will always give PX last.
|
342
|
+
# Redis seems to process each expiration option and the last one wins.
|
343
|
+
it 'prefers the finer-grained PX expiration option over EX' do
|
344
|
+
ttl_px = 6000
|
345
|
+
ttl_ex = 10
|
346
|
+
|
347
|
+
subject.set('key1', '1', px: ttl_px, ex: ttl_ex)
|
348
|
+
expect(subject.ttl('key1')).to eq(ttl_px / 1000)
|
349
|
+
|
350
|
+
subject.set('key1', '1', ex: ttl_ex, px: ttl_px)
|
351
|
+
expect(subject.ttl('key1')).to eq(ttl_px / 1000)
|
352
|
+
end
|
353
|
+
|
354
|
+
it 'uses nx option to only set the key if it does not already exist' do
|
355
|
+
expect(subject.set('key1', '1', nx: true)).to be_truthy
|
356
|
+
expect(subject.set('key1', '2', nx: true)).to be_falsey
|
357
|
+
|
358
|
+
expect(subject.get('key1')).to eq('1')
|
359
|
+
end
|
360
|
+
|
361
|
+
it 'uses xx option to only set the key if it already exists' do
|
362
|
+
expect(subject.set('key2', '1', xx: true)).to be_falsey
|
363
|
+
subject.set('key2', '2')
|
364
|
+
expect(subject.set('key2', '1', xx: true)).to be_truthy
|
365
|
+
|
366
|
+
expect(subject.get('key2')).to eq('1')
|
367
|
+
end
|
368
|
+
|
369
|
+
it 'does not set the key if both xx and nx option are specified' do
|
370
|
+
expect(subject.set('key2', '1', nx: true, xx: true)).to be_falsey
|
371
|
+
expect(subject.get('key2')).to be_nil
|
372
|
+
end
|
328
373
|
end
|
329
374
|
end
|