redis 3.0.2 → 3.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/.order +6 -5
- data/.travis.yml +1 -1
- data/CHANGELOG.md +20 -1
- data/benchmarking/logging.rb +10 -1
- data/lib/redis.rb +68 -13
- data/lib/redis/client.rb +13 -5
- data/lib/redis/connection/ruby.rb +13 -7
- data/lib/redis/distributed.rb +24 -2
- data/lib/redis/hash_ring.rb +2 -2
- data/lib/redis/subscribe.rb +5 -2
- data/lib/redis/version.rb +1 -1
- data/test/commands_on_strings_test.rb +16 -0
- data/test/distributed_commands_on_strings_test.rb +11 -0
- data/test/distributed_commands_requiring_clustering_test.rb +16 -0
- data/test/distributed_remote_server_control_commands_test.rb +2 -2
- data/test/helper.rb +1 -1
- data/test/helper_test.rb +7 -5
- data/test/internals_test.rb +1 -1
- data/test/lint/blocking_commands.rb +26 -0
- data/test/lint/sets.rb +29 -0
- data/test/lint/strings.rb +70 -4
- data/test/lint/value_types.rb +20 -0
- data/test/publish_subscribe_test.rb +0 -2
- data/test/test.conf +1 -1
- metadata +2 -2
data/.order
CHANGED
@@ -22,7 +22,8 @@
|
|
22
22
|
"slaveof",
|
23
23
|
"slowlog",
|
24
24
|
"sync",
|
25
|
-
"time"
|
25
|
+
"time",
|
26
|
+
"client"
|
26
27
|
],
|
27
28
|
"generic": [
|
28
29
|
"persist",
|
@@ -70,7 +71,8 @@
|
|
70
71
|
"append",
|
71
72
|
"bitcount",
|
72
73
|
"getset",
|
73
|
-
"strlen"
|
74
|
+
"strlen",
|
75
|
+
"bitop"
|
74
76
|
],
|
75
77
|
"list": [
|
76
78
|
"llen",
|
@@ -90,8 +92,7 @@
|
|
90
92
|
"lrange",
|
91
93
|
"lrem",
|
92
94
|
"lset",
|
93
|
-
"ltrim"
|
94
|
-
"bitop"
|
95
|
+
"ltrim"
|
95
96
|
],
|
96
97
|
"set": [
|
97
98
|
"scard",
|
@@ -166,4 +167,4 @@
|
|
166
167
|
"eval",
|
167
168
|
"evalsha"
|
168
169
|
]
|
169
|
-
}
|
170
|
+
}
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,4 +1,23 @@
|
|
1
|
-
# 3.0.
|
1
|
+
# 3.0.4 (unreleased)
|
2
|
+
|
3
|
+
* ...
|
4
|
+
|
5
|
+
# 3.0.3
|
6
|
+
|
7
|
+
* Blocking list commands (`BLPOP`, `BRPOP`, `BRPOPLPUSH`) use a socket
|
8
|
+
timeout equal to the sum of the command's timeout and the Redis
|
9
|
+
client's timeout, instead of disabling socket timeout altogether.
|
10
|
+
|
11
|
+
* Ruby 2.0 compatibility.
|
12
|
+
|
13
|
+
* Added support for `DUMP` and `RESTORE` (Redis 2.6).
|
14
|
+
|
15
|
+
* Added support for `BITCOUNT` and `BITOP` (Redis 2.6).
|
16
|
+
|
17
|
+
* Call `#to_s` on value argument for `SET`, `SETEX`, `PSETEX`, `GETSET`,
|
18
|
+
`SETNX`, and `SETRANGE`.
|
19
|
+
|
20
|
+
# 3.0.2
|
2
21
|
|
3
22
|
* Unescape CGI escaped password in URL.
|
4
23
|
|
data/benchmarking/logging.rb
CHANGED
@@ -54,7 +54,16 @@ benchmark "Default options (no logger)" do
|
|
54
54
|
end
|
55
55
|
|
56
56
|
logging_redises.each do |redis|
|
57
|
-
|
57
|
+
logger = redis.client.logger
|
58
|
+
|
59
|
+
case logger
|
60
|
+
when Logger
|
61
|
+
level = Logger::SEV_LABEL[logger.level]
|
62
|
+
when Log4r::Logger
|
63
|
+
level = logger.levels[logger.level]
|
64
|
+
end
|
65
|
+
|
66
|
+
benchmark "#{logger.class} on #{level}" do
|
58
67
|
stress(redis)
|
59
68
|
end
|
60
69
|
end
|
data/lib/redis.rb
CHANGED
@@ -181,7 +181,7 @@ class Redis
|
|
181
181
|
if reply.kind_of?(String)
|
182
182
|
reply = Hash[reply.split("\r\n").map do |line|
|
183
183
|
line.split(":", 2) unless line =~ /^(#|$)/
|
184
|
-
end]
|
184
|
+
end.compact]
|
185
185
|
|
186
186
|
if cmd && cmd.to_s == "commandstats"
|
187
187
|
# Extract nested hashes for INFO COMMANDSTATS
|
@@ -359,6 +359,28 @@ class Redis
|
|
359
359
|
end
|
360
360
|
end
|
361
361
|
|
362
|
+
# Return a serialized version of the value stored at a key.
|
363
|
+
#
|
364
|
+
# @param [String] key
|
365
|
+
# @return [String] serialized_value
|
366
|
+
def dump(key)
|
367
|
+
synchronize do |client|
|
368
|
+
client.call([:dump, key])
|
369
|
+
end
|
370
|
+
end
|
371
|
+
|
372
|
+
# Create a key using the serialized value, previously obtained using DUMP.
|
373
|
+
#
|
374
|
+
# @param [String] key
|
375
|
+
# @param [String] ttl
|
376
|
+
# @param [String] serialized_value
|
377
|
+
# @return `"OK"`
|
378
|
+
def restore(key, ttl, serialized_value)
|
379
|
+
synchronize do |client|
|
380
|
+
client.call([:restore, key, ttl, serialized_value])
|
381
|
+
end
|
382
|
+
end
|
383
|
+
|
362
384
|
# Delete one or more keys.
|
363
385
|
#
|
364
386
|
# @param [String, Array<String>] keys
|
@@ -605,7 +627,7 @@ class Redis
|
|
605
627
|
# @return `"OK"`
|
606
628
|
def set(key, value)
|
607
629
|
synchronize do |client|
|
608
|
-
client.call([:set, key, value])
|
630
|
+
client.call([:set, key, value.to_s])
|
609
631
|
end
|
610
632
|
end
|
611
633
|
|
@@ -619,7 +641,7 @@ class Redis
|
|
619
641
|
# @return `"OK"`
|
620
642
|
def setex(key, ttl, value)
|
621
643
|
synchronize do |client|
|
622
|
-
client.call([:setex, key, ttl, value])
|
644
|
+
client.call([:setex, key, ttl, value.to_s])
|
623
645
|
end
|
624
646
|
end
|
625
647
|
|
@@ -631,7 +653,7 @@ class Redis
|
|
631
653
|
# @return `"OK"`
|
632
654
|
def psetex(key, ttl, value)
|
633
655
|
synchronize do |client|
|
634
|
-
client.call([:psetex, key, ttl, value])
|
656
|
+
client.call([:psetex, key, ttl, value.to_s])
|
635
657
|
end
|
636
658
|
end
|
637
659
|
|
@@ -642,7 +664,7 @@ class Redis
|
|
642
664
|
# @return [Boolean] whether the key was set or not
|
643
665
|
def setnx(key, value)
|
644
666
|
synchronize do |client|
|
645
|
-
client.call([:setnx, key, value], &_boolify)
|
667
|
+
client.call([:setnx, key, value.to_s], &_boolify)
|
646
668
|
end
|
647
669
|
end
|
648
670
|
|
@@ -762,7 +784,7 @@ class Redis
|
|
762
784
|
# @return [Fixnum] length of the string after it was modified
|
763
785
|
def setrange(key, offset, value)
|
764
786
|
synchronize do |client|
|
765
|
-
client.call([:setrange, key, offset, value])
|
787
|
+
client.call([:setrange, key, offset, value.to_s])
|
766
788
|
end
|
767
789
|
end
|
768
790
|
|
@@ -813,6 +835,30 @@ class Redis
|
|
813
835
|
end
|
814
836
|
end
|
815
837
|
|
838
|
+
# Count the number of set bits in a range of the string value stored at key.
|
839
|
+
#
|
840
|
+
# @param [String] key
|
841
|
+
# @param [Fixnum] start start index
|
842
|
+
# @param [Fixnum] stop stop index
|
843
|
+
# @return [Fixnum] the number of bits set to 1
|
844
|
+
def bitcount(key, start = 0, stop = -1)
|
845
|
+
synchronize do |client|
|
846
|
+
client.call([:bitcount, key, start, stop])
|
847
|
+
end
|
848
|
+
end
|
849
|
+
|
850
|
+
# Perform a bitwise operation between strings and store the resulting string in a key.
|
851
|
+
#
|
852
|
+
# @param [String] operation e.g. `and`, `or`, `xor`, `not`
|
853
|
+
# @param [String] destkey destination key
|
854
|
+
# @param [String, Array<String>] keys one or more source keys to perform `operation`
|
855
|
+
# @return [Fixnum] the length of the string stored in `destkey`
|
856
|
+
def bitop(operation, destkey, *keys)
|
857
|
+
synchronize do |client|
|
858
|
+
client.call([:bitop, operation, destkey] + keys)
|
859
|
+
end
|
860
|
+
end
|
861
|
+
|
816
862
|
# Set the string value of a key and return its old value.
|
817
863
|
#
|
818
864
|
# @param [String] key
|
@@ -821,7 +867,7 @@ class Redis
|
|
821
867
|
# did not exist
|
822
868
|
def getset(key, value)
|
823
869
|
synchronize do |client|
|
824
|
-
client.call([:getset, key, value])
|
870
|
+
client.call([:getset, key, value.to_s])
|
825
871
|
end
|
826
872
|
end
|
827
873
|
|
@@ -849,7 +895,7 @@ class Redis
|
|
849
895
|
# Prepend one or more values to a list, creating the list if it doesn't exist
|
850
896
|
#
|
851
897
|
# @param [String] key
|
852
|
-
# @param [String] value
|
898
|
+
# @param [String, Array] string value, or array of string values to push
|
853
899
|
# @return [Fixnum] the length of the list after the push operation
|
854
900
|
def lpush(key, value)
|
855
901
|
synchronize do |client|
|
@@ -940,7 +986,9 @@ class Redis
|
|
940
986
|
timeout = options[:timeout] || 0
|
941
987
|
|
942
988
|
synchronize do |client|
|
943
|
-
|
989
|
+
command = [cmd, keys, timeout]
|
990
|
+
timeout += client.timeout if timeout > 0
|
991
|
+
client.call_with_timeout(command, timeout)
|
944
992
|
end
|
945
993
|
end
|
946
994
|
|
@@ -1006,7 +1054,9 @@ class Redis
|
|
1006
1054
|
timeout = options[:timeout] || 0
|
1007
1055
|
|
1008
1056
|
synchronize do |client|
|
1009
|
-
|
1057
|
+
command = [:brpoplpush, source, destination, timeout]
|
1058
|
+
timeout += client.timeout if timeout > 0
|
1059
|
+
client.call_with_timeout(command, timeout)
|
1010
1060
|
end
|
1011
1061
|
end
|
1012
1062
|
|
@@ -1150,13 +1200,18 @@ class Redis
|
|
1150
1200
|
end
|
1151
1201
|
end
|
1152
1202
|
|
1153
|
-
# Get
|
1203
|
+
# Get one or more random members from a set.
|
1154
1204
|
#
|
1155
1205
|
# @param [String] key
|
1206
|
+
# @param [Fixnum] count
|
1156
1207
|
# @return [String]
|
1157
|
-
def srandmember(key)
|
1208
|
+
def srandmember(key, count = nil)
|
1158
1209
|
synchronize do |client|
|
1159
|
-
|
1210
|
+
if count.nil?
|
1211
|
+
client.call([:srandmember, key])
|
1212
|
+
else
|
1213
|
+
client.call([:srandmember, key, count])
|
1214
|
+
end
|
1160
1215
|
end
|
1161
1216
|
end
|
1162
1217
|
|
data/lib/redis/client.rb
CHANGED
@@ -160,14 +160,18 @@ class Redis
|
|
160
160
|
result
|
161
161
|
end
|
162
162
|
|
163
|
-
def
|
164
|
-
|
163
|
+
def call_with_timeout(command, timeout, &blk)
|
164
|
+
with_socket_timeout(timeout) do
|
165
165
|
call(command, &blk)
|
166
166
|
end
|
167
167
|
rescue ConnectionError
|
168
168
|
retry
|
169
169
|
end
|
170
170
|
|
171
|
+
def call_without_timeout(command, &blk)
|
172
|
+
call_with_timeout(command, 0, &blk)
|
173
|
+
end
|
174
|
+
|
171
175
|
def process(commands)
|
172
176
|
logging(commands) do
|
173
177
|
ensure_connected do
|
@@ -218,17 +222,21 @@ class Redis
|
|
218
222
|
end
|
219
223
|
end
|
220
224
|
|
221
|
-
def
|
225
|
+
def with_socket_timeout(timeout)
|
222
226
|
connect unless connected?
|
223
227
|
|
224
228
|
begin
|
225
|
-
connection.timeout =
|
229
|
+
connection.timeout = timeout
|
226
230
|
yield
|
227
231
|
ensure
|
228
|
-
connection.timeout = timeout if connected?
|
232
|
+
connection.timeout = self.timeout if connected?
|
229
233
|
end
|
230
234
|
end
|
231
235
|
|
236
|
+
def without_socket_timeout(&blk)
|
237
|
+
with_socket_timeout(0, &blk)
|
238
|
+
end
|
239
|
+
|
232
240
|
def with_reconnect(val=true)
|
233
241
|
begin
|
234
242
|
original, @reconnect = @reconnect, val
|
@@ -83,11 +83,7 @@ class Redis
|
|
83
83
|
|
84
84
|
class UNIXSocket < ::UNIXSocket
|
85
85
|
|
86
|
-
|
87
|
-
# Errno::EAGAIN on #read_nonblock even when IO.select says it is
|
88
|
-
# readable. This behavior shows in 1.6.6 in both 1.8 and 1.9 mode.
|
89
|
-
# Therefore, fall back on the default Unix socket implementation,
|
90
|
-
# without timeouts.
|
86
|
+
include SocketMixin
|
91
87
|
|
92
88
|
def self.connect(path, timeout)
|
93
89
|
Timeout.timeout(timeout) do
|
@@ -97,6 +93,17 @@ class Redis
|
|
97
93
|
rescue Timeout::Error
|
98
94
|
raise TimeoutError
|
99
95
|
end
|
96
|
+
|
97
|
+
# JRuby raises Errno::EAGAIN on #read_nonblock even when IO.select
|
98
|
+
# says it is readable (1.6.6, in both 1.8 and 1.9 mode).
|
99
|
+
# Use the blocking #readpartial method instead.
|
100
|
+
|
101
|
+
def _read_from_socket(nbytes)
|
102
|
+
readpartial(nbytes)
|
103
|
+
|
104
|
+
rescue EOFError
|
105
|
+
raise Errno::ECONNRESET
|
106
|
+
end
|
100
107
|
end
|
101
108
|
|
102
109
|
end
|
@@ -132,8 +139,7 @@ class Redis
|
|
132
139
|
|
133
140
|
class UNIXSocket < ::Socket
|
134
141
|
|
135
|
-
|
136
|
-
# with the JRuby implementation.
|
142
|
+
include SocketMixin
|
137
143
|
|
138
144
|
def self.connect(path, timeout)
|
139
145
|
sock = new(::Socket::AF_UNIX, Socket::SOCK_STREAM, 0)
|
data/lib/redis/distributed.rb
CHANGED
@@ -137,6 +137,16 @@ class Redis
|
|
137
137
|
node_for(key).pttl(key)
|
138
138
|
end
|
139
139
|
|
140
|
+
# Return a serialized version of the value stored at a key.
|
141
|
+
def dump(key)
|
142
|
+
node_for(key).dump(key)
|
143
|
+
end
|
144
|
+
|
145
|
+
# Create a key using the serialized value, previously obtained using DUMP.
|
146
|
+
def restore(key, ttl, serialized_value)
|
147
|
+
node_for(key).restore(key, ttl, serialized_value)
|
148
|
+
end
|
149
|
+
|
140
150
|
# Delete a key.
|
141
151
|
def del(*args)
|
142
152
|
keys_per_node = args.group_by { |key| node_for(key) }
|
@@ -295,6 +305,18 @@ class Redis
|
|
295
305
|
node_for(key).append(key, value)
|
296
306
|
end
|
297
307
|
|
308
|
+
# Count the number of set bits in a range of the string value stored at key.
|
309
|
+
def bitcount(key, start = 0, stop = -1)
|
310
|
+
node_for(key).bitcount(key, start, stop)
|
311
|
+
end
|
312
|
+
|
313
|
+
# Perform a bitwise operation between strings and store the resulting string in a key.
|
314
|
+
def bitop(operation, destkey, *keys)
|
315
|
+
ensure_same_node(:bitop, [destkey] + keys) do |node|
|
316
|
+
node.bitop(operation, destkey, *keys)
|
317
|
+
end
|
318
|
+
end
|
319
|
+
|
298
320
|
# Set the string value of a key and return its old value.
|
299
321
|
def getset(key, value)
|
300
322
|
node_for(key).getset(key, value)
|
@@ -455,8 +477,8 @@ class Redis
|
|
455
477
|
end
|
456
478
|
|
457
479
|
# Get a random member from a set.
|
458
|
-
def srandmember(key)
|
459
|
-
node_for(key).srandmember(key)
|
480
|
+
def srandmember(key, count = nil)
|
481
|
+
node_for(key).srandmember(key, count)
|
460
482
|
end
|
461
483
|
|
462
484
|
# Move a member from one set to another.
|
data/lib/redis/hash_ring.rb
CHANGED
data/lib/redis/subscribe.rb
CHANGED
@@ -29,14 +29,17 @@ class Redis
|
|
29
29
|
def subscription(start, stop, channels, block)
|
30
30
|
sub = Subscription.new(&block)
|
31
31
|
|
32
|
+
unsubscribed = false
|
33
|
+
|
32
34
|
begin
|
33
35
|
@client.call_loop([start, *channels]) do |line|
|
34
36
|
type, *rest = line
|
35
37
|
sub.callbacks[type].call(*rest)
|
36
|
-
|
38
|
+
unsubscribed = type == stop && rest.last == 0
|
39
|
+
break if unsubscribed
|
37
40
|
end
|
38
41
|
ensure
|
39
|
-
send(stop)
|
42
|
+
send(stop) if !unsubscribed
|
40
43
|
end
|
41
44
|
end
|
42
45
|
end
|
data/lib/redis/version.rb
CHANGED
@@ -80,4 +80,20 @@ class TestCommandsOnStrings < Test::Unit::TestCase
|
|
80
80
|
assert_equal "s2", r.get("foo")
|
81
81
|
assert_equal "s3", r.get("bar")
|
82
82
|
end
|
83
|
+
|
84
|
+
def test_bitop
|
85
|
+
return if version < "2.5.10"
|
86
|
+
|
87
|
+
r.set("foo", "a")
|
88
|
+
r.set("bar", "b")
|
89
|
+
|
90
|
+
r.bitop(:and, "foo&bar", "foo", "bar")
|
91
|
+
assert_equal "\x60", r.get("foo&bar")
|
92
|
+
r.bitop(:or, "foo|bar", "foo", "bar")
|
93
|
+
assert_equal "\x63", r.get("foo|bar")
|
94
|
+
r.bitop(:xor, "foo^bar", "foo", "bar")
|
95
|
+
assert_equal "\x03", r.get("foo^bar")
|
96
|
+
r.bitop(:not, "~foo", "foo")
|
97
|
+
assert_equal "\x9E", r.get("~foo")
|
98
|
+
end
|
83
99
|
end
|
@@ -45,4 +45,15 @@ class TestDistributedCommandsOnStrings < Test::Unit::TestCase
|
|
45
45
|
r.mapped_msetnx(:foo => "s2", :bar => "s3")
|
46
46
|
end
|
47
47
|
end
|
48
|
+
|
49
|
+
def test_bitop
|
50
|
+
return if version < "2.5.10"
|
51
|
+
|
52
|
+
assert_raise Redis::Distributed::CannotDistribute do
|
53
|
+
r.set("foo", "a")
|
54
|
+
r.set("bar", "b")
|
55
|
+
|
56
|
+
r.bitop(:and, "foo&bar", "foo", "bar")
|
57
|
+
end
|
58
|
+
end
|
48
59
|
end
|
@@ -145,4 +145,20 @@ class TestDistributedCommandsRequiringClustering < Test::Unit::TestCase
|
|
145
145
|
r.sort("{qux}bar", :get => "{qux}foo:*", :store => "{qux}baz")
|
146
146
|
assert_equal ["s1", "s2"], r.lrange("{qux}baz", 0, -1)
|
147
147
|
end
|
148
|
+
|
149
|
+
def test_bitop
|
150
|
+
return if version < "2.5.10"
|
151
|
+
|
152
|
+
r.set("{qux}foo", "a")
|
153
|
+
r.set("{qux}bar", "b")
|
154
|
+
|
155
|
+
r.bitop(:and, "{qux}foo&bar", "{qux}foo", "{qux}bar")
|
156
|
+
assert_equal "\x60", r.get("{qux}foo&bar")
|
157
|
+
r.bitop(:or, "{qux}foo|bar", "{qux}foo", "{qux}bar")
|
158
|
+
assert_equal "\x63", r.get("{qux}foo|bar")
|
159
|
+
r.bitop(:xor, "{qux}foo^bar", "{qux}foo", "{qux}bar")
|
160
|
+
assert_equal "\x03", r.get("{qux}foo^bar")
|
161
|
+
r.bitop(:not, "{qux}~foo", "{qux}foo")
|
162
|
+
assert_equal "\x9E", r.get("{qux}~foo")
|
163
|
+
end
|
148
164
|
end
|
@@ -17,9 +17,9 @@ class TestDistributedRemoteServerControlCommands < Test::Unit::TestCase
|
|
17
17
|
"total_commands_processed",
|
18
18
|
]
|
19
19
|
|
20
|
-
|
20
|
+
infos = r.info
|
21
21
|
|
22
|
-
|
22
|
+
infos.each do |info|
|
23
23
|
keys.each do |k|
|
24
24
|
msg = "expected #info to include #{k}"
|
25
25
|
assert info.keys.include?(k), msg
|
data/test/helper.rb
CHANGED
data/test/helper_test.rb
CHANGED
@@ -7,16 +7,18 @@ class TestHelper < Test::Unit::TestCase
|
|
7
7
|
include Helper
|
8
8
|
|
9
9
|
def test_version_comparison
|
10
|
-
v = Version.new("2.0.
|
10
|
+
v = Version.new("2.0.1")
|
11
11
|
|
12
|
-
assert v < "3"
|
13
12
|
assert v > "1"
|
14
13
|
assert v > "2"
|
14
|
+
assert v < "3"
|
15
|
+
assert v < "10"
|
15
16
|
|
16
17
|
assert v < "2.1"
|
17
|
-
assert v < "2.0.
|
18
|
-
assert v < "2.0.
|
18
|
+
assert v < "2.0.2"
|
19
|
+
assert v < "2.0.1.1"
|
20
|
+
assert v < "2.0.10"
|
19
21
|
|
20
|
-
assert v == "2.0.
|
22
|
+
assert v == "2.0.1"
|
21
23
|
end
|
22
24
|
end
|
data/test/internals_test.rb
CHANGED
@@ -280,7 +280,7 @@ class TestInternals < Test::Unit::TestCase
|
|
280
280
|
|
281
281
|
def test_connecting_to_unix_domain_socket
|
282
282
|
assert_nothing_raised do
|
283
|
-
Redis.new(OPTIONS.merge(:path => "/
|
283
|
+
Redis.new(OPTIONS.merge(:path => "./test/db/redis.sock")).ping
|
284
284
|
end
|
285
285
|
end
|
286
286
|
|
@@ -120,5 +120,31 @@ module Lint
|
|
120
120
|
assert_equal "1", r.brpoplpush("{zap}foo", "{zap}bar", 1)
|
121
121
|
end
|
122
122
|
end
|
123
|
+
|
124
|
+
driver(:ruby, :hiredis) do
|
125
|
+
def test_blpop_socket_timeout
|
126
|
+
mock(:delay => 1 + OPTIONS[:timeout] * 2) do |r|
|
127
|
+
assert_raises(Redis::TimeoutError) do
|
128
|
+
r.blpop("{zap}foo", :timeout => 1)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def test_brpop_socket_timeout
|
134
|
+
mock(:delay => 1 + OPTIONS[:timeout] * 2) do |r|
|
135
|
+
assert_raises(Redis::TimeoutError) do
|
136
|
+
r.brpop("{zap}foo", :timeout => 1)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def test_brpoplpush_socket_timeout
|
142
|
+
mock(:delay => 1 + OPTIONS[:timeout] * 2) do |r|
|
143
|
+
assert_raises(Redis::TimeoutError) do
|
144
|
+
r.brpoplpush("{zap}foo", "{zap}bar", :timeout => 1)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
123
149
|
end
|
124
150
|
end
|
data/test/lint/sets.rb
CHANGED
@@ -92,5 +92,34 @@ module Lint
|
|
92
92
|
|
93
93
|
assert_equal 2, r.scard("foo")
|
94
94
|
end
|
95
|
+
|
96
|
+
def test_srandmember_with_positive_count
|
97
|
+
r.sadd "foo", "s1"
|
98
|
+
r.sadd "foo", "s2"
|
99
|
+
r.sadd "foo", "s3"
|
100
|
+
r.sadd "foo", "s4"
|
101
|
+
|
102
|
+
4.times do
|
103
|
+
assert !(["s1", "s2", "s3", "s4"] & r.srandmember("foo", 3)).empty?
|
104
|
+
|
105
|
+
assert_equal 3, r.srandmember("foo", 3).size
|
106
|
+
end
|
107
|
+
|
108
|
+
assert_equal 4, r.scard("foo")
|
109
|
+
end
|
110
|
+
|
111
|
+
def test_srandmember_with_negative_count
|
112
|
+
r.sadd "foo", "s1"
|
113
|
+
r.sadd "foo", "s2"
|
114
|
+
r.sadd "foo", "s3"
|
115
|
+
r.sadd "foo", "s4"
|
116
|
+
|
117
|
+
4.times do
|
118
|
+
assert !(["s1", "s2", "s3", "s4"] & r.srandmember("foo", -6)).empty?
|
119
|
+
assert_equal 6, r.srandmember("foo", -6).size
|
120
|
+
end
|
121
|
+
|
122
|
+
assert_equal 4, r.scard("foo")
|
123
|
+
end
|
95
124
|
end
|
96
125
|
end
|
data/test/lint/strings.rb
CHANGED
@@ -26,6 +26,14 @@ module Lint
|
|
26
26
|
assert_equal "1\n", r.get("foo")
|
27
27
|
end
|
28
28
|
|
29
|
+
def test_set_and_get_with_non_string_value
|
30
|
+
value = ["a", "b"]
|
31
|
+
|
32
|
+
r.set("foo", value)
|
33
|
+
|
34
|
+
assert_equal value.to_s, r.get("foo")
|
35
|
+
end
|
36
|
+
|
29
37
|
def test_set_and_get_with_ascii_characters
|
30
38
|
if defined?(Encoding)
|
31
39
|
with_external_encoding("ASCII-8BIT") do
|
@@ -45,6 +53,14 @@ module Lint
|
|
45
53
|
assert [0, 1].include? r.ttl("foo")
|
46
54
|
end
|
47
55
|
|
56
|
+
def test_setex_with_non_string_value
|
57
|
+
value = ["b", "a", "r"]
|
58
|
+
|
59
|
+
assert r.setex("foo", 1, value)
|
60
|
+
assert_equal value.to_s, r.get("foo")
|
61
|
+
assert [0, 1].include? r.ttl("foo")
|
62
|
+
end
|
63
|
+
|
48
64
|
def test_psetex
|
49
65
|
return if version < "2.5.4"
|
50
66
|
|
@@ -53,6 +69,16 @@ module Lint
|
|
53
69
|
assert [0, 1].include? r.ttl("foo")
|
54
70
|
end
|
55
71
|
|
72
|
+
def test_psetex_with_non_string_value
|
73
|
+
return if version < "2.5.4"
|
74
|
+
|
75
|
+
value = ["b", "a", "r"]
|
76
|
+
|
77
|
+
assert r.psetex("foo", 1000, value)
|
78
|
+
assert_equal value.to_s, r.get("foo")
|
79
|
+
assert [0, 1].include? r.ttl("foo")
|
80
|
+
end
|
81
|
+
|
56
82
|
def test_getset
|
57
83
|
r.set("foo", "bar")
|
58
84
|
|
@@ -60,14 +86,35 @@ module Lint
|
|
60
86
|
assert_equal "baz", r.get("foo")
|
61
87
|
end
|
62
88
|
|
89
|
+
def test_getset_with_non_string_value
|
90
|
+
r.set("foo", "zap")
|
91
|
+
|
92
|
+
value = ["b", "a", "r"]
|
93
|
+
|
94
|
+
assert_equal "zap", r.getset("foo", value)
|
95
|
+
assert_equal value.to_s, r.get("foo")
|
96
|
+
end
|
97
|
+
|
63
98
|
def test_setnx
|
64
|
-
r.set("foo", "
|
99
|
+
r.set("foo", "qux")
|
100
|
+
assert !r.setnx("foo", "bar")
|
101
|
+
assert_equal "qux", r.get("foo")
|
65
102
|
|
66
|
-
|
103
|
+
r.del("foo")
|
104
|
+
assert r.setnx("foo", "bar")
|
105
|
+
assert_equal "bar", r.get("foo")
|
106
|
+
end
|
67
107
|
|
68
|
-
|
108
|
+
def test_setnx_with_non_string_value
|
109
|
+
value = ["b", "a", "r"]
|
69
110
|
|
70
|
-
|
111
|
+
r.set("foo", "qux")
|
112
|
+
assert !r.setnx("foo", value)
|
113
|
+
assert_equal "qux", r.get("foo")
|
114
|
+
|
115
|
+
r.del("foo")
|
116
|
+
assert r.setnx("foo", value)
|
117
|
+
assert_equal value.to_s, r.get("foo")
|
71
118
|
end
|
72
119
|
|
73
120
|
def test_incr
|
@@ -133,6 +180,15 @@ module Lint
|
|
133
180
|
assert_equal "c", r.get("foo")
|
134
181
|
end
|
135
182
|
|
183
|
+
def test_bitcount
|
184
|
+
return if version < "2.5.10"
|
185
|
+
|
186
|
+
r.set("foo", "abcde")
|
187
|
+
|
188
|
+
assert_equal 10, r.bitcount("foo", 1, 3)
|
189
|
+
assert_equal 17, r.bitcount("foo", 0, -1)
|
190
|
+
end
|
191
|
+
|
136
192
|
def test_getrange
|
137
193
|
r.set("foo", "abcde")
|
138
194
|
|
@@ -148,6 +204,16 @@ module Lint
|
|
148
204
|
assert_equal "abare", r.get("foo")
|
149
205
|
end
|
150
206
|
|
207
|
+
def test_setrange_with_non_string_value
|
208
|
+
r.set("foo", "abcde")
|
209
|
+
|
210
|
+
value = ["b", "a", "r"]
|
211
|
+
|
212
|
+
r.setrange("foo", 2, value)
|
213
|
+
|
214
|
+
assert_equal "ab#{value.to_s}", r.get("foo")
|
215
|
+
end
|
216
|
+
|
151
217
|
def test_strlen
|
152
218
|
r.set "foo", "lorem"
|
153
219
|
|
data/test/lint/value_types.rb
CHANGED
@@ -80,6 +80,26 @@ module Lint
|
|
80
80
|
assert_in_range 1..2000, r.pttl("foo")
|
81
81
|
end
|
82
82
|
|
83
|
+
def test_dump_and_restore
|
84
|
+
return if version < "2.5.7"
|
85
|
+
|
86
|
+
r.set("foo", "a")
|
87
|
+
v = r.dump("foo")
|
88
|
+
r.del("foo")
|
89
|
+
|
90
|
+
assert r.restore("foo", 1000, v)
|
91
|
+
assert_equal "a", r.get("foo")
|
92
|
+
assert [0, 1].include? r.ttl("foo")
|
93
|
+
|
94
|
+
r.rpush("bar", ["b", "c", "d"])
|
95
|
+
w = r.dump("bar")
|
96
|
+
r.del("bar")
|
97
|
+
|
98
|
+
assert r.restore("bar", 1000, w)
|
99
|
+
assert_equal ["b", "c", "d"], r.lrange("bar", 0, -1)
|
100
|
+
assert [0, 1].include? r.ttl("bar")
|
101
|
+
end
|
102
|
+
|
83
103
|
def test_move
|
84
104
|
r.select 14
|
85
105
|
r.flushdb
|
data/test/test.conf
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: redis
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.0.
|
4
|
+
version: 3.0.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -17,7 +17,7 @@ authors:
|
|
17
17
|
autorequire:
|
18
18
|
bindir: bin
|
19
19
|
cert_chain: []
|
20
|
-
date:
|
20
|
+
date: 2013-03-01 00:00:00.000000000 Z
|
21
21
|
dependencies:
|
22
22
|
- !ruby/object:Gem::Dependency
|
23
23
|
name: rake
|