redis 3.2.0 → 4.6.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 +5 -5
- data/CHANGELOG.md +278 -15
- data/README.md +260 -76
- data/lib/redis/client.rb +239 -115
- data/lib/redis/cluster/command.rb +79 -0
- data/lib/redis/cluster/command_loader.rb +33 -0
- data/lib/redis/cluster/key_slot_converter.rb +72 -0
- data/lib/redis/cluster/node.rb +120 -0
- data/lib/redis/cluster/node_key.rb +31 -0
- data/lib/redis/cluster/node_loader.rb +37 -0
- data/lib/redis/cluster/option.rb +93 -0
- data/lib/redis/cluster/slot.rb +86 -0
- data/lib/redis/cluster/slot_loader.rb +49 -0
- data/lib/redis/cluster.rb +315 -0
- data/lib/redis/commands/bitmaps.rb +63 -0
- data/lib/redis/commands/cluster.rb +45 -0
- data/lib/redis/commands/connection.rb +58 -0
- data/lib/redis/commands/geo.rb +84 -0
- data/lib/redis/commands/hashes.rb +251 -0
- data/lib/redis/commands/hyper_log_log.rb +37 -0
- data/lib/redis/commands/keys.rb +411 -0
- data/lib/redis/commands/lists.rb +289 -0
- data/lib/redis/commands/pubsub.rb +72 -0
- data/lib/redis/commands/scripting.rb +114 -0
- data/lib/redis/commands/server.rb +188 -0
- data/lib/redis/commands/sets.rb +207 -0
- data/lib/redis/commands/sorted_sets.rb +804 -0
- data/lib/redis/commands/streams.rb +382 -0
- data/lib/redis/commands/strings.rb +313 -0
- data/lib/redis/commands/transactions.rb +92 -0
- data/lib/redis/commands.rb +242 -0
- data/lib/redis/connection/command_helper.rb +7 -10
- data/lib/redis/connection/hiredis.rb +11 -6
- data/lib/redis/connection/registry.rb +2 -1
- data/lib/redis/connection/ruby.rb +173 -64
- data/lib/redis/connection/synchrony.rb +32 -8
- data/lib/redis/connection.rb +3 -1
- data/lib/redis/distributed.rb +233 -74
- data/lib/redis/errors.rb +48 -0
- data/lib/redis/hash_ring.rb +30 -72
- data/lib/redis/pipeline.rb +145 -12
- data/lib/redis/subscribe.rb +20 -13
- data/lib/redis/version.rb +3 -1
- data/lib/redis.rb +171 -2476
- metadata +71 -165
- data/.gitignore +0 -15
- data/.travis/Gemfile +0 -11
- data/.travis.yml +0 -54
- data/.yardopts +0 -3
- data/Gemfile +0 -4
- data/Rakefile +0 -68
- data/benchmarking/logging.rb +0 -71
- data/benchmarking/pipeline.rb +0 -51
- data/benchmarking/speed.rb +0 -21
- data/benchmarking/suite.rb +0 -24
- data/benchmarking/worker.rb +0 -71
- data/examples/basic.rb +0 -15
- data/examples/consistency.rb +0 -114
- data/examples/dist_redis.rb +0 -43
- data/examples/incr-decr.rb +0 -17
- data/examples/list.rb +0 -26
- data/examples/pubsub.rb +0 -37
- data/examples/sentinel/sentinel.conf +0 -9
- data/examples/sentinel/start +0 -49
- data/examples/sentinel.rb +0 -41
- data/examples/sets.rb +0 -36
- data/examples/unicorn/config.ru +0 -3
- data/examples/unicorn/unicorn.rb +0 -20
- data/redis.gemspec +0 -43
- data/test/bitpos_test.rb +0 -69
- data/test/blocking_commands_test.rb +0 -42
- data/test/command_map_test.rb +0 -30
- data/test/commands_on_hashes_test.rb +0 -21
- data/test/commands_on_hyper_log_log_test.rb +0 -21
- data/test/commands_on_lists_test.rb +0 -20
- data/test/commands_on_sets_test.rb +0 -77
- data/test/commands_on_sorted_sets_test.rb +0 -123
- data/test/commands_on_strings_test.rb +0 -101
- data/test/commands_on_value_types_test.rb +0 -131
- data/test/connection_handling_test.rb +0 -189
- data/test/db/.gitkeep +0 -0
- data/test/distributed_blocking_commands_test.rb +0 -46
- data/test/distributed_commands_on_hashes_test.rb +0 -10
- data/test/distributed_commands_on_hyper_log_log_test.rb +0 -33
- data/test/distributed_commands_on_lists_test.rb +0 -22
- data/test/distributed_commands_on_sets_test.rb +0 -83
- data/test/distributed_commands_on_sorted_sets_test.rb +0 -18
- data/test/distributed_commands_on_strings_test.rb +0 -59
- data/test/distributed_commands_on_value_types_test.rb +0 -95
- data/test/distributed_commands_requiring_clustering_test.rb +0 -164
- data/test/distributed_connection_handling_test.rb +0 -23
- data/test/distributed_internals_test.rb +0 -70
- data/test/distributed_key_tags_test.rb +0 -52
- data/test/distributed_persistence_control_commands_test.rb +0 -26
- data/test/distributed_publish_subscribe_test.rb +0 -92
- data/test/distributed_remote_server_control_commands_test.rb +0 -66
- data/test/distributed_scripting_test.rb +0 -102
- data/test/distributed_sorting_test.rb +0 -20
- data/test/distributed_test.rb +0 -58
- data/test/distributed_transactions_test.rb +0 -32
- data/test/encoding_test.rb +0 -18
- data/test/error_replies_test.rb +0 -59
- data/test/fork_safety_test.rb +0 -65
- data/test/helper.rb +0 -232
- data/test/helper_test.rb +0 -24
- data/test/internals_test.rb +0 -434
- data/test/lint/blocking_commands.rb +0 -150
- data/test/lint/hashes.rb +0 -162
- data/test/lint/hyper_log_log.rb +0 -60
- data/test/lint/lists.rb +0 -143
- data/test/lint/sets.rb +0 -125
- data/test/lint/sorted_sets.rb +0 -238
- data/test/lint/strings.rb +0 -260
- data/test/lint/value_types.rb +0 -122
- data/test/persistence_control_commands_test.rb +0 -26
- data/test/pipelining_commands_test.rb +0 -242
- data/test/publish_subscribe_test.rb +0 -210
- data/test/remote_server_control_commands_test.rb +0 -117
- data/test/scanning_test.rb +0 -413
- data/test/scripting_test.rb +0 -78
- data/test/sorting_test.rb +0 -59
- data/test/support/connection/hiredis.rb +0 -1
- data/test/support/connection/ruby.rb +0 -1
- data/test/support/connection/synchrony.rb +0 -17
- data/test/support/redis_mock.rb +0 -115
- data/test/support/wire/synchrony.rb +0 -24
- data/test/support/wire/thread.rb +0 -5
- data/test/synchrony_driver.rb +0 -88
- data/test/test.conf +0 -9
- data/test/thread_safety_test.rb +0 -32
- data/test/transactions_test.rb +0 -264
- data/test/unknown_commands_test.rb +0 -14
- data/test/url_param_test.rb +0 -132
data/test/scanning_test.rb
DELETED
@@ -1,413 +0,0 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
|
3
|
-
require File.expand_path("helper", File.dirname(__FILE__))
|
4
|
-
|
5
|
-
unless defined?(Enumerator)
|
6
|
-
Enumerator = Enumerable::Enumerator
|
7
|
-
end
|
8
|
-
|
9
|
-
class TestScanning < Test::Unit::TestCase
|
10
|
-
|
11
|
-
include Helper::Client
|
12
|
-
|
13
|
-
def test_scan_basic
|
14
|
-
target_version "2.7.105" do
|
15
|
-
r.debug :populate, 1000
|
16
|
-
|
17
|
-
cursor = 0
|
18
|
-
all_keys = []
|
19
|
-
loop {
|
20
|
-
cursor, keys = r.scan cursor
|
21
|
-
all_keys += keys
|
22
|
-
break if cursor == "0"
|
23
|
-
}
|
24
|
-
|
25
|
-
assert_equal 1000, all_keys.uniq.size
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
def test_scan_count
|
30
|
-
target_version "2.7.105" do
|
31
|
-
r.debug :populate, 1000
|
32
|
-
|
33
|
-
cursor = 0
|
34
|
-
all_keys = []
|
35
|
-
loop {
|
36
|
-
cursor, keys = r.scan cursor, :count => 5
|
37
|
-
all_keys += keys
|
38
|
-
break if cursor == "0"
|
39
|
-
}
|
40
|
-
|
41
|
-
assert_equal 1000, all_keys.uniq.size
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
def test_scan_match
|
46
|
-
target_version "2.7.105" do
|
47
|
-
r.debug :populate, 1000
|
48
|
-
|
49
|
-
cursor = 0
|
50
|
-
all_keys = []
|
51
|
-
loop {
|
52
|
-
cursor, keys = r.scan cursor, :match => "key:1??"
|
53
|
-
all_keys += keys
|
54
|
-
break if cursor == "0"
|
55
|
-
}
|
56
|
-
|
57
|
-
assert_equal 100, all_keys.uniq.size
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
def test_scan_each_enumerator
|
62
|
-
target_version "2.7.105" do
|
63
|
-
|
64
|
-
r.debug :populate, 1000
|
65
|
-
|
66
|
-
scan_enumerator = r.scan_each
|
67
|
-
assert_equal true, scan_enumerator.is_a?(::Enumerator)
|
68
|
-
|
69
|
-
keys_from_scan = scan_enumerator.to_a.uniq
|
70
|
-
all_keys = r.keys "*"
|
71
|
-
|
72
|
-
assert all_keys.sort == keys_from_scan.sort
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
def test_scan_each_enumerator_match
|
77
|
-
target_version "2.7.105" do
|
78
|
-
|
79
|
-
r.debug :populate, 1000
|
80
|
-
|
81
|
-
keys_from_scan = r.scan_each(:match => "key:1??").to_a.uniq
|
82
|
-
all_keys = r.keys "key:1??"
|
83
|
-
|
84
|
-
assert all_keys.sort == keys_from_scan.sort
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
def test_scan_each_block
|
89
|
-
target_version "2.7.105" do
|
90
|
-
|
91
|
-
r.debug :populate, 100
|
92
|
-
|
93
|
-
keys_from_scan = []
|
94
|
-
r.scan_each {|key|
|
95
|
-
keys_from_scan << key
|
96
|
-
}
|
97
|
-
|
98
|
-
all_keys = r.keys "*"
|
99
|
-
|
100
|
-
assert all_keys.sort == keys_from_scan.uniq.sort
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
def test_scan_each_block_match
|
105
|
-
target_version "2.7.105" do
|
106
|
-
|
107
|
-
r.debug :populate, 100
|
108
|
-
|
109
|
-
keys_from_scan = []
|
110
|
-
r.scan_each(:match => "key:1?") {|key|
|
111
|
-
keys_from_scan << key
|
112
|
-
}
|
113
|
-
|
114
|
-
all_keys = r.keys "key:1?"
|
115
|
-
|
116
|
-
assert all_keys.sort == keys_from_scan.uniq.sort
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
120
|
-
def test_sscan_with_encoding
|
121
|
-
target_version "2.7.105" do
|
122
|
-
[:intset, :hashtable].each do |enc|
|
123
|
-
r.del "set"
|
124
|
-
|
125
|
-
prefix = ""
|
126
|
-
prefix = "ele:" if enc == :hashtable
|
127
|
-
|
128
|
-
elements = []
|
129
|
-
100.times { |j| elements << "#{prefix}#{j}" }
|
130
|
-
|
131
|
-
r.sadd "set", elements
|
132
|
-
|
133
|
-
assert_equal enc.to_s, r.object("encoding", "set")
|
134
|
-
|
135
|
-
cursor = 0
|
136
|
-
all_keys = []
|
137
|
-
loop {
|
138
|
-
cursor, keys = r.sscan "set", cursor
|
139
|
-
all_keys += keys
|
140
|
-
break if cursor == "0"
|
141
|
-
}
|
142
|
-
|
143
|
-
assert_equal 100, all_keys.uniq.size
|
144
|
-
end
|
145
|
-
end
|
146
|
-
end
|
147
|
-
|
148
|
-
def test_sscan_each_enumerator
|
149
|
-
target_version "2.7.105" do
|
150
|
-
elements = []
|
151
|
-
100.times { |j| elements << "ele:#{j}" }
|
152
|
-
r.sadd "set", elements
|
153
|
-
|
154
|
-
scan_enumerator = r.sscan_each("set")
|
155
|
-
assert_equal true, scan_enumerator.is_a?(::Enumerator)
|
156
|
-
|
157
|
-
keys_from_scan = scan_enumerator.to_a.uniq
|
158
|
-
all_keys = r.smembers("set")
|
159
|
-
|
160
|
-
assert all_keys.sort == keys_from_scan.sort
|
161
|
-
end
|
162
|
-
end
|
163
|
-
|
164
|
-
def test_sscan_each_enumerator_match
|
165
|
-
target_version "2.7.105" do
|
166
|
-
elements = []
|
167
|
-
100.times { |j| elements << "ele:#{j}" }
|
168
|
-
r.sadd "set", elements
|
169
|
-
|
170
|
-
keys_from_scan = r.sscan_each("set", :match => "ele:1?").to_a.uniq
|
171
|
-
|
172
|
-
all_keys = r.smembers("set").grep(/^ele:1.$/)
|
173
|
-
|
174
|
-
assert all_keys.sort == keys_from_scan.sort
|
175
|
-
end
|
176
|
-
end
|
177
|
-
|
178
|
-
def test_sscan_each_enumerator_block
|
179
|
-
target_version "2.7.105" do
|
180
|
-
elements = []
|
181
|
-
100.times { |j| elements << "ele:#{j}" }
|
182
|
-
r.sadd "set", elements
|
183
|
-
|
184
|
-
keys_from_scan = []
|
185
|
-
r.sscan_each("set") do |key|
|
186
|
-
keys_from_scan << key
|
187
|
-
end
|
188
|
-
|
189
|
-
all_keys = r.smembers("set")
|
190
|
-
|
191
|
-
assert all_keys.sort == keys_from_scan.uniq.sort
|
192
|
-
end
|
193
|
-
end
|
194
|
-
|
195
|
-
def test_sscan_each_enumerator_block_match
|
196
|
-
target_version "2.7.105" do
|
197
|
-
elements = []
|
198
|
-
100.times { |j| elements << "ele:#{j}" }
|
199
|
-
r.sadd "set", elements
|
200
|
-
|
201
|
-
keys_from_scan = []
|
202
|
-
r.sscan_each("set", :match => "ele:1?") do |key|
|
203
|
-
keys_from_scan << key
|
204
|
-
end
|
205
|
-
|
206
|
-
all_keys = r.smembers("set").grep(/^ele:1.$/)
|
207
|
-
|
208
|
-
assert all_keys.sort == keys_from_scan.uniq.sort
|
209
|
-
end
|
210
|
-
end
|
211
|
-
|
212
|
-
def test_hscan_with_encoding
|
213
|
-
target_version "2.7.105" do
|
214
|
-
[:ziplist, :hashtable].each do |enc|
|
215
|
-
r.del "set"
|
216
|
-
|
217
|
-
count = 1000
|
218
|
-
count = 30 if enc == :ziplist
|
219
|
-
|
220
|
-
elements = []
|
221
|
-
count.times { |j| elements << "key:#{j}" << j.to_s }
|
222
|
-
|
223
|
-
r.hmset "hash", *elements
|
224
|
-
|
225
|
-
assert_equal enc.to_s, r.object("encoding", "hash")
|
226
|
-
|
227
|
-
cursor = 0
|
228
|
-
all_key_values = []
|
229
|
-
loop {
|
230
|
-
cursor, key_values = r.hscan "hash", cursor
|
231
|
-
all_key_values.concat key_values
|
232
|
-
break if cursor == "0"
|
233
|
-
}
|
234
|
-
|
235
|
-
keys2 = []
|
236
|
-
all_key_values.each do |k, v|
|
237
|
-
assert_equal "key:#{v}", k
|
238
|
-
keys2 << k
|
239
|
-
end
|
240
|
-
|
241
|
-
assert_equal count, keys2.uniq.size
|
242
|
-
end
|
243
|
-
end
|
244
|
-
end
|
245
|
-
|
246
|
-
def test_hscan_each_enumerator
|
247
|
-
target_version "2.7.105" do
|
248
|
-
count = 1000
|
249
|
-
elements = []
|
250
|
-
count.times { |j| elements << "key:#{j}" << j.to_s }
|
251
|
-
r.hmset "hash", *elements
|
252
|
-
|
253
|
-
scan_enumerator = r.hscan_each("hash")
|
254
|
-
assert_equal true, scan_enumerator.is_a?(::Enumerator)
|
255
|
-
|
256
|
-
keys_from_scan = scan_enumerator.to_a.uniq
|
257
|
-
all_keys = r.hgetall("hash").to_a
|
258
|
-
|
259
|
-
assert all_keys.sort == keys_from_scan.sort
|
260
|
-
end
|
261
|
-
end
|
262
|
-
|
263
|
-
def test_hscan_each_enumerator_match
|
264
|
-
target_version "2.7.105" do
|
265
|
-
count = 100
|
266
|
-
elements = []
|
267
|
-
count.times { |j| elements << "key:#{j}" << j.to_s }
|
268
|
-
r.hmset "hash", *elements
|
269
|
-
|
270
|
-
keys_from_scan = r.hscan_each("hash", :match => "key:1?").to_a.uniq
|
271
|
-
all_keys = r.hgetall("hash").to_a.select{|k,v| k =~ /^key:1.$/}
|
272
|
-
|
273
|
-
assert all_keys.sort == keys_from_scan.sort
|
274
|
-
end
|
275
|
-
end
|
276
|
-
|
277
|
-
def test_hscan_each_block
|
278
|
-
target_version "2.7.105" do
|
279
|
-
count = 1000
|
280
|
-
elements = []
|
281
|
-
count.times { |j| elements << "key:#{j}" << j.to_s }
|
282
|
-
r.hmset "hash", *elements
|
283
|
-
|
284
|
-
keys_from_scan = []
|
285
|
-
r.hscan_each("hash") do |field, value|
|
286
|
-
keys_from_scan << [field, value]
|
287
|
-
end
|
288
|
-
all_keys = r.hgetall("hash").to_a
|
289
|
-
|
290
|
-
assert all_keys.sort == keys_from_scan.uniq.sort
|
291
|
-
end
|
292
|
-
end
|
293
|
-
|
294
|
-
def test_hscan_each_block_match
|
295
|
-
target_version "2.7.105" do
|
296
|
-
count = 1000
|
297
|
-
elements = []
|
298
|
-
count.times { |j| elements << "key:#{j}" << j.to_s }
|
299
|
-
r.hmset "hash", *elements
|
300
|
-
|
301
|
-
keys_from_scan = []
|
302
|
-
r.hscan_each("hash", :match => "key:1?") do |field, value|
|
303
|
-
keys_from_scan << [field, value]
|
304
|
-
end
|
305
|
-
all_keys = r.hgetall("hash").to_a.select{|k,v| k =~ /^key:1.$/}
|
306
|
-
|
307
|
-
assert all_keys.sort == keys_from_scan.uniq.sort
|
308
|
-
end
|
309
|
-
end
|
310
|
-
|
311
|
-
def test_zscan_with_encoding
|
312
|
-
target_version "2.7.105" do
|
313
|
-
[:ziplist, :skiplist].each do |enc|
|
314
|
-
r.del "zset"
|
315
|
-
|
316
|
-
count = 1000
|
317
|
-
count = 30 if enc == :ziplist
|
318
|
-
|
319
|
-
elements = []
|
320
|
-
count.times { |j| elements << j << "key:#{j}" }
|
321
|
-
|
322
|
-
r.zadd "zset", elements
|
323
|
-
|
324
|
-
assert_equal enc.to_s, r.object("encoding", "zset")
|
325
|
-
|
326
|
-
cursor = 0
|
327
|
-
all_key_scores = []
|
328
|
-
loop {
|
329
|
-
cursor, key_scores = r.zscan "zset", cursor
|
330
|
-
all_key_scores.concat key_scores
|
331
|
-
break if cursor == "0"
|
332
|
-
}
|
333
|
-
|
334
|
-
keys2 = []
|
335
|
-
all_key_scores.each do |k, v|
|
336
|
-
assert_equal true, v.is_a?(Float)
|
337
|
-
assert_equal "key:#{Integer(v)}", k
|
338
|
-
keys2 << k
|
339
|
-
end
|
340
|
-
|
341
|
-
assert_equal count, keys2.uniq.size
|
342
|
-
end
|
343
|
-
end
|
344
|
-
end
|
345
|
-
|
346
|
-
def test_zscan_each_enumerator
|
347
|
-
target_version "2.7.105" do
|
348
|
-
count = 1000
|
349
|
-
elements = []
|
350
|
-
count.times { |j| elements << j << "key:#{j}" }
|
351
|
-
r.zadd "zset", elements
|
352
|
-
|
353
|
-
scan_enumerator = r.zscan_each "zset"
|
354
|
-
assert_equal true, scan_enumerator.is_a?(::Enumerator)
|
355
|
-
|
356
|
-
scores_from_scan = scan_enumerator.to_a.uniq
|
357
|
-
member_scores = r.zrange("zset", 0, -1, :with_scores => true)
|
358
|
-
|
359
|
-
assert member_scores.sort == scores_from_scan.sort
|
360
|
-
end
|
361
|
-
end
|
362
|
-
|
363
|
-
def test_zscan_each_enumerator_match
|
364
|
-
target_version "2.7.105" do
|
365
|
-
count = 1000
|
366
|
-
elements = []
|
367
|
-
count.times { |j| elements << j << "key:#{j}" }
|
368
|
-
r.zadd "zset", elements
|
369
|
-
|
370
|
-
scores_from_scan = r.zscan_each("zset", :match => "key:1??").to_a.uniq
|
371
|
-
member_scores = r.zrange("zset", 0, -1, :with_scores => true)
|
372
|
-
filtered_members = member_scores.select{|k,s| k =~ /^key:1..$/}
|
373
|
-
|
374
|
-
assert filtered_members.sort == scores_from_scan.sort
|
375
|
-
end
|
376
|
-
end
|
377
|
-
|
378
|
-
def test_zscan_each_block
|
379
|
-
target_version "2.7.105" do
|
380
|
-
count = 1000
|
381
|
-
elements = []
|
382
|
-
count.times { |j| elements << j << "key:#{j}" }
|
383
|
-
r.zadd "zset", elements
|
384
|
-
|
385
|
-
scores_from_scan = []
|
386
|
-
r.zscan_each("zset") do |member, score|
|
387
|
-
scores_from_scan << [member, score]
|
388
|
-
end
|
389
|
-
member_scores = r.zrange("zset", 0, -1, :with_scores => true)
|
390
|
-
|
391
|
-
assert member_scores.sort == scores_from_scan.sort
|
392
|
-
end
|
393
|
-
end
|
394
|
-
|
395
|
-
def test_zscan_each_block_match
|
396
|
-
target_version "2.7.105" do
|
397
|
-
count = 1000
|
398
|
-
elements = []
|
399
|
-
count.times { |j| elements << j << "key:#{j}" }
|
400
|
-
r.zadd "zset", elements
|
401
|
-
|
402
|
-
scores_from_scan = []
|
403
|
-
r.zscan_each("zset", :match => "key:1??") do |member, score|
|
404
|
-
scores_from_scan << [member, score]
|
405
|
-
end
|
406
|
-
member_scores = r.zrange("zset", 0, -1, :with_scores => true)
|
407
|
-
filtered_members = member_scores.select{|k,s| k =~ /^key:1..$/}
|
408
|
-
|
409
|
-
assert filtered_members.sort == scores_from_scan.sort
|
410
|
-
end
|
411
|
-
end
|
412
|
-
|
413
|
-
end
|
data/test/scripting_test.rb
DELETED
@@ -1,78 +0,0 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
|
3
|
-
require File.expand_path("helper", File.dirname(__FILE__))
|
4
|
-
|
5
|
-
class TestScripting < Test::Unit::TestCase
|
6
|
-
|
7
|
-
include Helper::Client
|
8
|
-
|
9
|
-
def to_sha(script)
|
10
|
-
r.script(:load, script)
|
11
|
-
end
|
12
|
-
|
13
|
-
def test_script_exists
|
14
|
-
target_version "2.5.9" do # 2.6-rc1
|
15
|
-
a = to_sha("return 1")
|
16
|
-
b = a.succ
|
17
|
-
|
18
|
-
assert_equal true, r.script(:exists, a)
|
19
|
-
assert_equal false, r.script(:exists, b)
|
20
|
-
assert_equal [true], r.script(:exists, [a])
|
21
|
-
assert_equal [false], r.script(:exists, [b])
|
22
|
-
assert_equal [true, false], r.script(:exists, [a, b])
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
def test_script_flush
|
27
|
-
target_version "2.5.9" do # 2.6-rc1
|
28
|
-
sha = to_sha("return 1")
|
29
|
-
assert r.script(:exists, sha)
|
30
|
-
assert_equal "OK", r.script(:flush)
|
31
|
-
assert !r.script(:exists, sha)
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
def test_script_kill
|
36
|
-
target_version "2.5.9" do # 2.6-rc1
|
37
|
-
redis_mock(:script => lambda { |arg| "+#{arg.upcase}" }) do |redis|
|
38
|
-
assert_equal "KILL", redis.script(:kill)
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
def test_eval
|
44
|
-
target_version "2.5.9" do # 2.6-rc1
|
45
|
-
assert_equal 0, r.eval("return #KEYS")
|
46
|
-
assert_equal 0, r.eval("return #ARGV")
|
47
|
-
assert_equal ["k1", "k2"], r.eval("return KEYS", ["k1", "k2"])
|
48
|
-
assert_equal ["a1", "a2"], r.eval("return ARGV", [], ["a1", "a2"])
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
def test_eval_with_options_hash
|
53
|
-
target_version "2.5.9" do # 2.6-rc1
|
54
|
-
assert_equal 0, r.eval("return #KEYS", {})
|
55
|
-
assert_equal 0, r.eval("return #ARGV", {})
|
56
|
-
assert_equal ["k1", "k2"], r.eval("return KEYS", { :keys => ["k1", "k2"] })
|
57
|
-
assert_equal ["a1", "a2"], r.eval("return ARGV", { :argv => ["a1", "a2"] })
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
def test_evalsha
|
62
|
-
target_version "2.5.9" do # 2.6-rc1
|
63
|
-
assert_equal 0, r.evalsha(to_sha("return #KEYS"))
|
64
|
-
assert_equal 0, r.evalsha(to_sha("return #ARGV"))
|
65
|
-
assert_equal ["k1", "k2"], r.evalsha(to_sha("return KEYS"), ["k1", "k2"])
|
66
|
-
assert_equal ["a1", "a2"], r.evalsha(to_sha("return ARGV"), [], ["a1", "a2"])
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
def test_evalsha_with_options_hash
|
71
|
-
target_version "2.5.9" do # 2.6-rc1
|
72
|
-
assert_equal 0, r.evalsha(to_sha("return #KEYS"), {})
|
73
|
-
assert_equal 0, r.evalsha(to_sha("return #ARGV"), {})
|
74
|
-
assert_equal ["k1", "k2"], r.evalsha(to_sha("return KEYS"), { :keys => ["k1", "k2"] })
|
75
|
-
assert_equal ["a1", "a2"], r.evalsha(to_sha("return ARGV"), { :argv => ["a1", "a2"] })
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
data/test/sorting_test.rb
DELETED
@@ -1,59 +0,0 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
|
3
|
-
require File.expand_path("helper", File.dirname(__FILE__))
|
4
|
-
|
5
|
-
class TestSorting < Test::Unit::TestCase
|
6
|
-
|
7
|
-
include Helper::Client
|
8
|
-
|
9
|
-
def test_sort
|
10
|
-
r.set("foo:1", "s1")
|
11
|
-
r.set("foo:2", "s2")
|
12
|
-
|
13
|
-
r.rpush("bar", "1")
|
14
|
-
r.rpush("bar", "2")
|
15
|
-
|
16
|
-
assert_equal ["s1"], r.sort("bar", :get => "foo:*", :limit => [0, 1])
|
17
|
-
assert_equal ["s2"], r.sort("bar", :get => "foo:*", :limit => [0, 1], :order => "desc alpha")
|
18
|
-
end
|
19
|
-
|
20
|
-
def test_sort_with_an_array_of_gets
|
21
|
-
r.set("foo:1:a", "s1a")
|
22
|
-
r.set("foo:1:b", "s1b")
|
23
|
-
|
24
|
-
r.set("foo:2:a", "s2a")
|
25
|
-
r.set("foo:2:b", "s2b")
|
26
|
-
|
27
|
-
r.rpush("bar", "1")
|
28
|
-
r.rpush("bar", "2")
|
29
|
-
|
30
|
-
assert_equal [["s1a", "s1b"]], r.sort("bar", :get => ["foo:*:a", "foo:*:b"], :limit => [0, 1])
|
31
|
-
assert_equal [["s2a", "s2b"]], r.sort("bar", :get => ["foo:*:a", "foo:*:b"], :limit => [0, 1], :order => "desc alpha")
|
32
|
-
assert_equal [["s1a", "s1b"], ["s2a", "s2b"]], r.sort("bar", :get => ["foo:*:a", "foo:*:b"])
|
33
|
-
end
|
34
|
-
|
35
|
-
def test_sort_with_store
|
36
|
-
r.set("foo:1", "s1")
|
37
|
-
r.set("foo:2", "s2")
|
38
|
-
|
39
|
-
r.rpush("bar", "1")
|
40
|
-
r.rpush("bar", "2")
|
41
|
-
|
42
|
-
r.sort("bar", :get => "foo:*", :store => "baz")
|
43
|
-
assert_equal ["s1", "s2"], r.lrange("baz", 0, -1)
|
44
|
-
end
|
45
|
-
|
46
|
-
def test_sort_with_an_array_of_gets_and_with_store
|
47
|
-
r.set("foo:1:a", "s1a")
|
48
|
-
r.set("foo:1:b", "s1b")
|
49
|
-
|
50
|
-
r.set("foo:2:a", "s2a")
|
51
|
-
r.set("foo:2:b", "s2b")
|
52
|
-
|
53
|
-
r.rpush("bar", "1")
|
54
|
-
r.rpush("bar", "2")
|
55
|
-
|
56
|
-
r.sort("bar", :get => ["foo:*:a", "foo:*:b"], :store => 'baz')
|
57
|
-
assert_equal ["s1a", "s1b", "s2a", "s2b"], r.lrange("baz", 0, -1)
|
58
|
-
end
|
59
|
-
end
|
@@ -1 +0,0 @@
|
|
1
|
-
require "support/wire/thread"
|
@@ -1 +0,0 @@
|
|
1
|
-
require "support/wire/thread"
|
data/test/support/redis_mock.rb
DELETED
@@ -1,115 +0,0 @@
|
|
1
|
-
require "socket"
|
2
|
-
|
3
|
-
module RedisMock
|
4
|
-
class Server
|
5
|
-
VERBOSE = false
|
6
|
-
|
7
|
-
def initialize(port, options = {}, &block)
|
8
|
-
@server = TCPServer.new(options[:host] || "127.0.0.1", port)
|
9
|
-
@server.setsockopt(Socket::SOL_SOCKET,Socket::SO_REUSEADDR, true)
|
10
|
-
end
|
11
|
-
|
12
|
-
def start(&block)
|
13
|
-
@thread = Thread.new { run(&block) }
|
14
|
-
end
|
15
|
-
|
16
|
-
# Bail out of @server.accept before closing the socket. This is required
|
17
|
-
# to avoid EADDRINUSE after a couple of iterations.
|
18
|
-
def shutdown
|
19
|
-
@thread.terminate if @thread
|
20
|
-
@server.close if @server
|
21
|
-
rescue => ex
|
22
|
-
$stderr.puts "Error closing mock server: #{ex.message}" if VERBOSE
|
23
|
-
$stderr.puts ex.backtrace if VERBOSE
|
24
|
-
end
|
25
|
-
|
26
|
-
def run
|
27
|
-
loop do
|
28
|
-
session = @server.accept
|
29
|
-
|
30
|
-
begin
|
31
|
-
return if yield(session) == :exit
|
32
|
-
ensure
|
33
|
-
session.close
|
34
|
-
end
|
35
|
-
end
|
36
|
-
rescue => ex
|
37
|
-
$stderr.puts "Error running mock server: #{ex.message}" if VERBOSE
|
38
|
-
$stderr.puts ex.backtrace if VERBOSE
|
39
|
-
ensure
|
40
|
-
@server.close
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
MOCK_PORT = 6382
|
45
|
-
|
46
|
-
# Starts a mock Redis server in a thread.
|
47
|
-
#
|
48
|
-
# The server will use the lambda handler passed as argument to handle
|
49
|
-
# connections. For example:
|
50
|
-
#
|
51
|
-
# handler = lambda { |session| session.close }
|
52
|
-
# RedisMock.start_with_handler(handler) do
|
53
|
-
# # Every connection will be closed immediately
|
54
|
-
# end
|
55
|
-
#
|
56
|
-
def self.start_with_handler(blk, options = {})
|
57
|
-
server = Server.new(MOCK_PORT, options)
|
58
|
-
|
59
|
-
begin
|
60
|
-
server.start(&blk)
|
61
|
-
|
62
|
-
yield(MOCK_PORT)
|
63
|
-
|
64
|
-
ensure
|
65
|
-
server.shutdown
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
# Starts a mock Redis server in a thread.
|
70
|
-
#
|
71
|
-
# The server will reply with a `+OK` to all commands, but you can
|
72
|
-
# customize it by providing a hash. For example:
|
73
|
-
#
|
74
|
-
# RedisMock.start(:ping => lambda { "+PONG" }) do
|
75
|
-
# assert_equal "PONG", Redis.new(:port => MOCK_PORT).ping
|
76
|
-
# end
|
77
|
-
#
|
78
|
-
def self.start(commands, options = {}, &blk)
|
79
|
-
handler = lambda do |session|
|
80
|
-
while line = session.gets
|
81
|
-
argv = Array.new(line[1..-3].to_i) do
|
82
|
-
bytes = session.gets[1..-3].to_i
|
83
|
-
arg = session.read(bytes)
|
84
|
-
session.read(2) # Discard \r\n
|
85
|
-
arg
|
86
|
-
end
|
87
|
-
|
88
|
-
command = argv.shift
|
89
|
-
blk = commands[command.to_sym]
|
90
|
-
blk ||= lambda { |*_| "+OK" }
|
91
|
-
|
92
|
-
response = blk.call(*argv)
|
93
|
-
|
94
|
-
# Convert a nil response to :close
|
95
|
-
response ||= :close
|
96
|
-
|
97
|
-
if response == :exit
|
98
|
-
break :exit
|
99
|
-
elsif response == :close
|
100
|
-
break :close
|
101
|
-
elsif response.is_a?(Array)
|
102
|
-
session.write("*%d\r\n" % response.size)
|
103
|
-
response.each do |e|
|
104
|
-
session.write("$%d\r\n%s\r\n" % [e.length, e])
|
105
|
-
end
|
106
|
-
else
|
107
|
-
session.write(response)
|
108
|
-
session.write("\r\n") unless response.end_with?("\r\n")
|
109
|
-
end
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
start_with_handler(handler, options, &blk)
|
114
|
-
end
|
115
|
-
end
|
@@ -1,24 +0,0 @@
|
|
1
|
-
class Wire < Fiber
|
2
|
-
# We cannot run this fiber explicitly because EM schedules it. Resuming the
|
3
|
-
# current fiber on the next tick to let the reactor do work.
|
4
|
-
def self.pass
|
5
|
-
f = Fiber.current
|
6
|
-
EM.next_tick { f.resume }
|
7
|
-
Fiber.yield
|
8
|
-
end
|
9
|
-
|
10
|
-
def self.sleep(sec)
|
11
|
-
EM::Synchrony.sleep(sec)
|
12
|
-
end
|
13
|
-
|
14
|
-
def initialize(&blk)
|
15
|
-
super
|
16
|
-
|
17
|
-
# Schedule run in next tick
|
18
|
-
EM.next_tick { resume }
|
19
|
-
end
|
20
|
-
|
21
|
-
def join
|
22
|
-
self.class.pass while alive?
|
23
|
-
end
|
24
|
-
end
|