redis2-namespaced 3.0.7

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.
Files changed (99) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +11 -0
  3. data/.order +170 -0
  4. data/.travis/Gemfile +11 -0
  5. data/.travis.yml +55 -0
  6. data/.yardopts +3 -0
  7. data/CHANGELOG.md +285 -0
  8. data/LICENSE +20 -0
  9. data/README.md +251 -0
  10. data/Rakefile +403 -0
  11. data/benchmarking/logging.rb +71 -0
  12. data/benchmarking/pipeline.rb +51 -0
  13. data/benchmarking/speed.rb +21 -0
  14. data/benchmarking/suite.rb +24 -0
  15. data/benchmarking/worker.rb +71 -0
  16. data/examples/basic.rb +15 -0
  17. data/examples/dist_redis.rb +43 -0
  18. data/examples/incr-decr.rb +17 -0
  19. data/examples/list.rb +26 -0
  20. data/examples/pubsub.rb +37 -0
  21. data/examples/sets.rb +36 -0
  22. data/examples/unicorn/config.ru +3 -0
  23. data/examples/unicorn/unicorn.rb +20 -0
  24. data/lib/redis2/client.rb +419 -0
  25. data/lib/redis2/connection/command_helper.rb +44 -0
  26. data/lib/redis2/connection/hiredis.rb +63 -0
  27. data/lib/redis2/connection/registry.rb +12 -0
  28. data/lib/redis2/connection/ruby.rb +322 -0
  29. data/lib/redis2/connection/synchrony.rb +124 -0
  30. data/lib/redis2/connection.rb +9 -0
  31. data/lib/redis2/distributed.rb +853 -0
  32. data/lib/redis2/errors.rb +40 -0
  33. data/lib/redis2/hash_ring.rb +131 -0
  34. data/lib/redis2/pipeline.rb +141 -0
  35. data/lib/redis2/subscribe.rb +83 -0
  36. data/lib/redis2/version.rb +3 -0
  37. data/lib/redis2.rb +2533 -0
  38. data/redis.gemspec +43 -0
  39. data/test/bitpos_test.rb +69 -0
  40. data/test/blocking_commands_test.rb +42 -0
  41. data/test/command_map_test.rb +30 -0
  42. data/test/commands_on_hashes_test.rb +21 -0
  43. data/test/commands_on_lists_test.rb +20 -0
  44. data/test/commands_on_sets_test.rb +77 -0
  45. data/test/commands_on_sorted_sets_test.rb +109 -0
  46. data/test/commands_on_strings_test.rb +101 -0
  47. data/test/commands_on_value_types_test.rb +131 -0
  48. data/test/connection_handling_test.rb +189 -0
  49. data/test/db/.gitkeep +0 -0
  50. data/test/distributed_blocking_commands_test.rb +46 -0
  51. data/test/distributed_commands_on_hashes_test.rb +10 -0
  52. data/test/distributed_commands_on_lists_test.rb +22 -0
  53. data/test/distributed_commands_on_sets_test.rb +83 -0
  54. data/test/distributed_commands_on_sorted_sets_test.rb +18 -0
  55. data/test/distributed_commands_on_strings_test.rb +59 -0
  56. data/test/distributed_commands_on_value_types_test.rb +95 -0
  57. data/test/distributed_commands_requiring_clustering_test.rb +164 -0
  58. data/test/distributed_connection_handling_test.rb +23 -0
  59. data/test/distributed_internals_test.rb +70 -0
  60. data/test/distributed_key_tags_test.rb +52 -0
  61. data/test/distributed_persistence_control_commands_test.rb +26 -0
  62. data/test/distributed_publish_subscribe_test.rb +92 -0
  63. data/test/distributed_remote_server_control_commands_test.rb +66 -0
  64. data/test/distributed_scripting_test.rb +102 -0
  65. data/test/distributed_sorting_test.rb +20 -0
  66. data/test/distributed_test.rb +58 -0
  67. data/test/distributed_transactions_test.rb +32 -0
  68. data/test/encoding_test.rb +18 -0
  69. data/test/error_replies_test.rb +59 -0
  70. data/test/helper.rb +218 -0
  71. data/test/helper_test.rb +24 -0
  72. data/test/internals_test.rb +410 -0
  73. data/test/lint/blocking_commands.rb +150 -0
  74. data/test/lint/hashes.rb +162 -0
  75. data/test/lint/lists.rb +143 -0
  76. data/test/lint/sets.rb +125 -0
  77. data/test/lint/sorted_sets.rb +238 -0
  78. data/test/lint/strings.rb +260 -0
  79. data/test/lint/value_types.rb +122 -0
  80. data/test/persistence_control_commands_test.rb +26 -0
  81. data/test/pipelining_commands_test.rb +242 -0
  82. data/test/publish_subscribe_test.rb +210 -0
  83. data/test/remote_server_control_commands_test.rb +117 -0
  84. data/test/scanning_test.rb +413 -0
  85. data/test/scripting_test.rb +78 -0
  86. data/test/sorting_test.rb +59 -0
  87. data/test/support/connection/hiredis.rb +1 -0
  88. data/test/support/connection/ruby.rb +1 -0
  89. data/test/support/connection/synchrony.rb +17 -0
  90. data/test/support/redis_mock.rb +115 -0
  91. data/test/support/wire/synchrony.rb +24 -0
  92. data/test/support/wire/thread.rb +5 -0
  93. data/test/synchrony_driver.rb +88 -0
  94. data/test/test.conf +9 -0
  95. data/test/thread_safety_test.rb +32 -0
  96. data/test/transactions_test.rb +264 -0
  97. data/test/unknown_commands_test.rb +14 -0
  98. data/test/url_param_test.rb +132 -0
  99. metadata +226 -0
data/test/helper.rb ADDED
@@ -0,0 +1,218 @@
1
+ $:.unshift File.expand_path("../lib", File.dirname(__FILE__))
2
+ $:.unshift File.expand_path(File.dirname(__FILE__))
3
+
4
+ require "test/unit"
5
+ require "logger"
6
+ require "stringio"
7
+
8
+ begin
9
+ require "ruby-debug"
10
+ rescue LoadError
11
+ end
12
+
13
+ $VERBOSE = true
14
+
15
+ ENV["conn"] ||= "ruby"
16
+
17
+ require "redis"
18
+ require "redis2/distributed"
19
+ require "redis2/connection/#{ENV["conn"]}"
20
+
21
+ require "support/redis_mock"
22
+ require "support/connection/#{ENV["conn"]}"
23
+
24
+ PORT = 6381
25
+ OPTIONS = {:port => PORT, :db => 15, :timeout => Float(ENV["TIMEOUT"] || 0.1)}
26
+ NODES = ["redis://127.0.0.1:#{PORT}/15"]
27
+
28
+ def init(redis)
29
+ begin
30
+ redis.select 14
31
+ redis.flushdb
32
+ redis.select 15
33
+ redis.flushdb
34
+ redis
35
+ rescue Redis2::CannotConnectError
36
+ puts <<-EOS
37
+
38
+ Cannot connect to Redis2.
39
+
40
+ Make sure Redis2 is running on localhost, port #{PORT}.
41
+ This testing suite connects to the database 15.
42
+
43
+ To install redis:
44
+ visit <http://redis.io/download/>.
45
+
46
+ To start the server:
47
+ rake start
48
+
49
+ To stop the server:
50
+ rake stop
51
+
52
+ EOS
53
+ exit 1
54
+ end
55
+ end
56
+
57
+ def driver(*drivers, &blk)
58
+ if drivers.map(&:to_s).include?(ENV["conn"])
59
+ class_eval(&blk)
60
+ end
61
+ end
62
+
63
+ module Helper
64
+
65
+ def run(runner)
66
+ if respond_to?(:around)
67
+ around { super(runner) }
68
+ else
69
+ super
70
+ end
71
+ end
72
+
73
+ def silent
74
+ verbose, $VERBOSE = $VERBOSE, false
75
+
76
+ begin
77
+ yield
78
+ ensure
79
+ $VERBOSE = verbose
80
+ end
81
+ end
82
+
83
+ def with_external_encoding(encoding)
84
+ original_encoding = Encoding.default_external
85
+
86
+ begin
87
+ silent { Encoding.default_external = Encoding.find(encoding) }
88
+ yield
89
+ ensure
90
+ silent { Encoding.default_external = original_encoding }
91
+ end
92
+ end
93
+
94
+ def try_encoding(encoding, &block)
95
+ if defined?(Encoding)
96
+ with_external_encoding(encoding, &block)
97
+ else
98
+ yield
99
+ end
100
+ end
101
+
102
+ class Version
103
+
104
+ include Comparable
105
+
106
+ attr :parts
107
+
108
+ def initialize(v)
109
+ case v
110
+ when Version
111
+ @parts = v.parts
112
+ else
113
+ @parts = v.to_s.split(".")
114
+ end
115
+ end
116
+
117
+ def <=>(other)
118
+ other = Version.new(other)
119
+ length = [self.parts.length, other.parts.length].max
120
+ length.times do |i|
121
+ a, b = self.parts[i], other.parts[i]
122
+
123
+ return -1 if a.nil?
124
+ return +1 if b.nil?
125
+ return a.to_i <=> b.to_i if a != b
126
+ end
127
+
128
+ 0
129
+ end
130
+ end
131
+
132
+ module Generic
133
+
134
+ include Helper
135
+
136
+ attr_reader :log
137
+ attr_reader :redis
138
+
139
+ alias :r :redis
140
+
141
+ def setup
142
+ @log = StringIO.new
143
+ @redis = init _new_client
144
+
145
+ # Run GC to make sure orphaned connections are closed.
146
+ GC.start
147
+ end
148
+
149
+ def teardown
150
+ @redis.quit if @redis
151
+ end
152
+
153
+ def redis_mock(commands, options = {}, &blk)
154
+ Redis2Mock.start(commands, options) do |port|
155
+ yield _new_client(options.merge(:port => port))
156
+ end
157
+ end
158
+
159
+ def redis_mock_with_handler(handler, options = {}, &blk)
160
+ Redis2Mock.start_with_handler(handler, options) do |port|
161
+ yield _new_client(options.merge(:port => port))
162
+ end
163
+ end
164
+
165
+ def assert_in_range(range, value)
166
+ assert range.include?(value), "expected #{value} to be in #{range.inspect}"
167
+ end
168
+
169
+ def target_version(target)
170
+ if version < target
171
+ skip("Requires Redis2 > #{target}") if respond_to?(:skip)
172
+ else
173
+ yield
174
+ end
175
+ end
176
+ end
177
+
178
+ module Client
179
+
180
+ include Generic
181
+
182
+ def version
183
+ Version.new(redis.info["redis_version"])
184
+ end
185
+
186
+ private
187
+
188
+ def _format_options(options)
189
+ OPTIONS.merge(:logger => ::Logger.new(@log)).merge(options)
190
+ end
191
+
192
+ def _new_client(options = {})
193
+ Redis2.new(_format_options(options).merge(:driver => ENV["conn"]))
194
+ end
195
+ end
196
+
197
+ module Distributed
198
+
199
+ include Generic
200
+
201
+ def version
202
+ Version.new(redis.info.first["redis_version"])
203
+ end
204
+
205
+ private
206
+
207
+ def _format_options(options)
208
+ {
209
+ :timeout => OPTIONS[:timeout],
210
+ :logger => ::Logger.new(@log),
211
+ }.merge(options)
212
+ end
213
+
214
+ def _new_client(options = {})
215
+ Redis2::Distributed.new(NODES, _format_options(options).merge(:driver => ENV["conn"]))
216
+ end
217
+ end
218
+ end
@@ -0,0 +1,24 @@
1
+ # encoding: UTF-8
2
+
3
+ require File.expand_path("helper", File.dirname(__FILE__))
4
+
5
+ class TestHelper < Test::Unit::TestCase
6
+
7
+ include Helper
8
+
9
+ def test_version_comparison
10
+ v = Version.new("2.0.1")
11
+
12
+ assert v > "1"
13
+ assert v > "2"
14
+ assert v < "3"
15
+ assert v < "10"
16
+
17
+ assert v < "2.1"
18
+ assert v < "2.0.2"
19
+ assert v < "2.0.1.1"
20
+ assert v < "2.0.10"
21
+
22
+ assert v == "2.0.1"
23
+ end
24
+ end
@@ -0,0 +1,410 @@
1
+ # encoding: UTF-8
2
+
3
+ require File.expand_path("helper", File.dirname(__FILE__))
4
+
5
+ class TestInternals < Test::Unit::TestCase
6
+
7
+ include Helper::Client
8
+
9
+ def test_logger
10
+ r.ping
11
+
12
+ assert log.string =~ /Redis2 >> PING/
13
+ assert log.string =~ /Redis2 >> \d+\.\d+ms/
14
+ end
15
+
16
+ def test_logger_with_pipelining
17
+ r.pipelined do
18
+ r.set "foo", "bar"
19
+ r.get "foo"
20
+ end
21
+
22
+ assert log.string["SET foo bar"]
23
+ assert log.string["GET foo"]
24
+ end
25
+
26
+ def test_recovers_from_failed_commands
27
+ # See https://github.com/redis/redis-rb/issues#issue/28
28
+
29
+ assert_raise(Redis2::CommandError) do
30
+ r.command_that_doesnt_exist
31
+ end
32
+
33
+ assert_nothing_raised do
34
+ r.info
35
+ end
36
+ end
37
+
38
+ def test_raises_on_protocol_errors
39
+ redis_mock(:ping => lambda { |*_| "foo" }) do |redis|
40
+ assert_raise(Redis2::ProtocolError) do
41
+ redis.ping
42
+ end
43
+ end
44
+ end
45
+
46
+ def test_provides_a_meaningful_inspect
47
+ assert_equal "#<Redis2 client v#{Redis2::VERSION} for redis://127.0.0.1:#{PORT}/15>", r.inspect
48
+ end
49
+
50
+ def test_redis_current
51
+ assert_equal "127.0.0.1", Redis2.current.client.host
52
+ assert_equal 6379, Redis2.current.client.port
53
+ assert_equal 0, Redis2.current.client.db
54
+
55
+ Redis2.current = Redis2.new(OPTIONS.merge(:port => 6380, :db => 1))
56
+
57
+ t = Thread.new do
58
+ assert_equal "127.0.0.1", Redis2.current.client.host
59
+ assert_equal 6380, Redis2.current.client.port
60
+ assert_equal 1, Redis2.current.client.db
61
+ end
62
+
63
+ t.join
64
+
65
+ assert_equal "127.0.0.1", Redis2.current.client.host
66
+ assert_equal 6380, Redis2.current.client.port
67
+ assert_equal 1, Redis2.current.client.db
68
+ end
69
+
70
+ def test_redis_connected?
71
+ fresh_client = _new_client
72
+ assert !fresh_client.connected?
73
+
74
+ fresh_client.ping
75
+ assert fresh_client.connected?
76
+
77
+ fresh_client.quit
78
+ assert !fresh_client.connected?
79
+ end
80
+
81
+ def test_default_id_with_host_and_port
82
+ redis = Redis2.new(OPTIONS.merge(:host => "host", :port => "1234", :db => 0))
83
+ assert_equal "redis://host:1234/0", redis.client.id
84
+ end
85
+
86
+ def test_default_id_with_host_and_port_and_explicit_scheme
87
+ redis = Redis2.new(OPTIONS.merge(:host => "host", :port => "1234", :db => 0, :scheme => "foo"))
88
+ assert_equal "redis://host:1234/0", redis.client.id
89
+ end
90
+
91
+ def test_default_id_with_path
92
+ redis = Redis2.new(OPTIONS.merge(:path => "/tmp/redis.sock", :db => 0))
93
+ assert_equal "redis:///tmp/redis.sock/0", redis.client.id
94
+ end
95
+
96
+ def test_default_id_with_path_and_explicit_scheme
97
+ redis = Redis2.new(OPTIONS.merge(:path => "/tmp/redis.sock", :db => 0, :scheme => "foo"))
98
+ assert_equal "redis:///tmp/redis.sock/0", redis.client.id
99
+ end
100
+
101
+ def test_override_id
102
+ redis = Redis2.new(OPTIONS.merge(:id => "test"))
103
+ assert_equal redis.client.id, "test"
104
+ end
105
+
106
+ def test_timeout
107
+ assert_nothing_raised do
108
+ Redis2.new(OPTIONS.merge(:timeout => 0))
109
+ end
110
+ end
111
+
112
+ def test_id_inside_multi
113
+ redis = Redis2.new(OPTIONS)
114
+ id = nil
115
+
116
+ redis.multi do
117
+ id = redis.id
118
+ end
119
+
120
+ assert_equal id, "redis://127.0.0.1:6381/15"
121
+ end
122
+
123
+ driver(:ruby) do
124
+ def test_tcp_keepalive
125
+ keepalive = {:time => 20, :intvl => 10, :probes => 5}
126
+
127
+ redis = Redis2.new(OPTIONS.merge(:tcp_keepalive => keepalive))
128
+ redis.ping
129
+
130
+ connection = redis.client.connection
131
+ actual_keepalive = connection.get_tcp_keepalive
132
+
133
+ [:time, :intvl, :probes].each do |key|
134
+ if actual_keepalive.has_key?(key)
135
+ assert_equal actual_keepalive[key], keepalive[key]
136
+ end
137
+ end
138
+ end
139
+ end
140
+
141
+ def test_time
142
+ target_version "2.5.4" do
143
+ # Test that the difference between the time that Ruby reports and the time
144
+ # that Redis2 reports is minimal (prevents the test from being racy).
145
+ rv = r.time
146
+
147
+ redis_usec = rv[0] * 1_000_000 + rv[1]
148
+ ruby_usec = Integer(Time.now.to_f * 1_000_000)
149
+
150
+ assert 500_000 > (ruby_usec - redis_usec).abs
151
+ end
152
+ end
153
+
154
+ def test_connection_timeout
155
+ assert_raise Redis2::CannotConnectError do
156
+ Redis2.new(OPTIONS.merge(:host => "10.255.255.254", :timeout => 0.1)).ping
157
+ end
158
+ end
159
+
160
+ def close_on_ping(seq)
161
+ $request = 0
162
+
163
+ command = lambda do
164
+ idx = $request
165
+ $request += 1
166
+
167
+ rv = "+%d" % idx
168
+ rv = nil if seq.include?(idx)
169
+ rv
170
+ end
171
+
172
+ redis_mock(:ping => command, :timeout => 0.1) do |redis|
173
+ yield(redis)
174
+ end
175
+ end
176
+
177
+ def test_retry_by_default
178
+ close_on_ping([0]) do |redis|
179
+ assert_equal "1", redis.ping
180
+ end
181
+ end
182
+
183
+ def test_retry_when_wrapped_in_with_reconnect_true
184
+ close_on_ping([0]) do |redis|
185
+ redis.with_reconnect(true) do
186
+ assert_equal "1", redis.ping
187
+ end
188
+ end
189
+ end
190
+
191
+ def test_dont_retry_when_wrapped_in_with_reconnect_false
192
+ close_on_ping([0]) do |redis|
193
+ assert_raise Redis2::ConnectionError do
194
+ redis.with_reconnect(false) do
195
+ redis.ping
196
+ end
197
+ end
198
+ end
199
+ end
200
+
201
+ def test_dont_retry_when_wrapped_in_without_reconnect
202
+ close_on_ping([0]) do |redis|
203
+ assert_raise Redis2::ConnectionError do
204
+ redis.without_reconnect do
205
+ redis.ping
206
+ end
207
+ end
208
+ end
209
+ end
210
+
211
+ def test_retry_only_once_when_read_raises_econnreset
212
+ close_on_ping([0, 1]) do |redis|
213
+ assert_raise Redis2::ConnectionError do
214
+ redis.ping
215
+ end
216
+
217
+ assert !redis.client.connected?
218
+ end
219
+ end
220
+
221
+ def test_don_t_retry_when_second_read_in_pipeline_raises_econnreset
222
+ close_on_ping([1]) do |redis|
223
+ assert_raise Redis2::ConnectionError do
224
+ redis.pipelined do
225
+ redis.ping
226
+ redis.ping # Second #read times out
227
+ end
228
+ end
229
+
230
+ assert !redis.client.connected?
231
+ end
232
+ end
233
+
234
+ def close_on_connection(seq)
235
+ $n = 0
236
+
237
+ read_command = lambda do |session|
238
+ Array.new(session.gets[1..-3].to_i) do
239
+ bytes = session.gets[1..-3].to_i
240
+ arg = session.read(bytes)
241
+ session.read(2) # Discard \r\n
242
+ arg
243
+ end
244
+ end
245
+
246
+ handler = lambda do |session|
247
+ n = $n
248
+ $n += 1
249
+
250
+ select = read_command.call(session)
251
+ if select[0].downcase == "select"
252
+ session.write("+OK\r\n")
253
+ else
254
+ raise "Expected SELECT"
255
+ end
256
+
257
+ if !seq.include?(n)
258
+ while read_command.call(session)
259
+ session.write("+#{n}\r\n")
260
+ end
261
+ end
262
+ end
263
+
264
+ redis_mock_with_handler(handler) do |redis|
265
+ yield(redis)
266
+ end
267
+ end
268
+
269
+ def test_retry_on_write_error_by_default
270
+ close_on_connection([0]) do |redis|
271
+ assert_equal "1", redis.client.call(["x" * 128 * 1024])
272
+ end
273
+ end
274
+
275
+ def test_retry_on_write_error_when_wrapped_in_with_reconnect_true
276
+ close_on_connection([0]) do |redis|
277
+ redis.with_reconnect(true) do
278
+ assert_equal "1", redis.client.call(["x" * 128 * 1024])
279
+ end
280
+ end
281
+ end
282
+
283
+ def test_dont_retry_on_write_error_when_wrapped_in_with_reconnect_false
284
+ close_on_connection([0]) do |redis|
285
+ assert_raise Redis2::ConnectionError do
286
+ redis.with_reconnect(false) do
287
+ redis.client.call(["x" * 128 * 1024])
288
+ end
289
+ end
290
+ end
291
+ end
292
+
293
+ def test_dont_retry_on_write_error_when_wrapped_in_without_reconnect
294
+ close_on_connection([0]) do |redis|
295
+ assert_raise Redis2::ConnectionError do
296
+ redis.without_reconnect do
297
+ redis.client.call(["x" * 128 * 1024])
298
+ end
299
+ end
300
+ end
301
+ end
302
+
303
+ def test_connecting_to_unix_domain_socket
304
+ assert_nothing_raised do
305
+ Redis2.new(OPTIONS.merge(:path => "./test/db/redis.sock")).ping
306
+ end
307
+ end
308
+
309
+ driver(:ruby, :hiredis) do
310
+ def test_bubble_timeout_without_retrying
311
+ serv = TCPServer.new(6380)
312
+
313
+ redis = Redis2.new(:port => 6380, :timeout => 0.1)
314
+
315
+ assert_raise(Redis2::TimeoutError) do
316
+ redis.ping
317
+ end
318
+
319
+ ensure
320
+ serv.close if serv
321
+ end
322
+ end
323
+
324
+ def test_client_options
325
+ redis = Redis2.new(OPTIONS.merge(:host => "host", :port => 1234, :db => 1, :scheme => "foo"))
326
+
327
+ assert_equal "host", redis.client.options[:host]
328
+ assert_equal 1234, redis.client.options[:port]
329
+ assert_equal 1, redis.client.options[:db]
330
+ assert_equal "foo", redis.client.options[:scheme]
331
+ end
332
+
333
+ def test_does_not_change_self_client_options
334
+ redis = Redis2.new(OPTIONS.merge(:host => "host", :port => 1234, :db => 1, :scheme => "foo"))
335
+ options = redis.client.options
336
+
337
+ options[:host] << "new_host"
338
+ options[:scheme] << "bar"
339
+ options.merge!(:db => 0)
340
+
341
+ assert_equal "host", redis.client.options[:host]
342
+ assert_equal 1, redis.client.options[:db]
343
+ assert_equal "foo", redis.client.options[:scheme]
344
+ end
345
+
346
+ def test_resolves_localhost
347
+ assert_nothing_raised do
348
+ Redis2.new(OPTIONS.merge(:host => 'localhost')).ping
349
+ end
350
+ end
351
+
352
+ class << self
353
+ def af_family_supported(af)
354
+ hosts = {
355
+ Socket::AF_INET => "127.0.0.1",
356
+ Socket::AF_INET6 => "::1",
357
+ }
358
+
359
+ begin
360
+ s = Socket.new(af, Socket::SOCK_STREAM, 0)
361
+ begin
362
+ sa = Socket.pack_sockaddr_in(9999, hosts[af])
363
+ s.bind(sa)
364
+ yield
365
+ rescue Errno::EADDRNOTAVAIL
366
+ ensure
367
+ s.close
368
+ end
369
+ rescue Errno::ESOCKTNOSUPPORT
370
+ end
371
+ end
372
+ end
373
+
374
+ def af_test(host)
375
+ commands = {
376
+ :ping => lambda { |*_| "+pong" },
377
+ }
378
+
379
+ redis_mock(commands, :host => host) do |redis|
380
+ assert_nothing_raised do
381
+ redis.ping
382
+ end
383
+ end
384
+ end
385
+
386
+ driver(:ruby) do
387
+ af_family_supported(Socket::AF_INET) do
388
+ def test_connect_ipv4
389
+ af_test("127.0.0.1")
390
+ end
391
+ end
392
+ end
393
+
394
+ driver(:ruby) do
395
+ af_family_supported(Socket::AF_INET6) do
396
+ def test_connect_ipv6
397
+ af_test("::1")
398
+ end
399
+ end
400
+ end
401
+
402
+ def test_can_be_duped_to_create_a_new_connection
403
+ clients = r.info["connected_clients"].to_i
404
+
405
+ r2 = r.dup
406
+ r2.ping
407
+
408
+ assert_equal clients + 1, r.info["connected_clients"].to_i
409
+ end
410
+ end