redis 3.0.0.rc1 → 3.0.0.rc2

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 (77) hide show
  1. data/.travis.yml +50 -0
  2. data/.travis/Gemfile +11 -0
  3. data/CHANGELOG.md +47 -19
  4. data/README.md +160 -149
  5. data/Rakefile +15 -50
  6. data/examples/pubsub.rb +1 -1
  7. data/examples/unicorn/config.ru +1 -1
  8. data/examples/unicorn/unicorn.rb +1 -1
  9. data/lib/redis.rb +790 -390
  10. data/lib/redis/client.rb +137 -49
  11. data/lib/redis/connection/hiredis.rb +26 -15
  12. data/lib/redis/connection/ruby.rb +170 -53
  13. data/lib/redis/connection/synchrony.rb +23 -35
  14. data/lib/redis/distributed.rb +92 -32
  15. data/lib/redis/errors.rb +4 -2
  16. data/lib/redis/pipeline.rb +17 -6
  17. data/lib/redis/version.rb +1 -1
  18. data/redis.gemspec +4 -6
  19. data/test/blocking_commands_test.rb +42 -0
  20. data/test/command_map_test.rb +18 -17
  21. data/test/commands_on_hashes_test.rb +13 -12
  22. data/test/commands_on_lists_test.rb +35 -45
  23. data/test/commands_on_sets_test.rb +55 -54
  24. data/test/commands_on_sorted_sets_test.rb +106 -105
  25. data/test/commands_on_strings_test.rb +64 -55
  26. data/test/commands_on_value_types_test.rb +66 -54
  27. data/test/connection_handling_test.rb +136 -151
  28. data/test/distributed_blocking_commands_test.rb +33 -40
  29. data/test/distributed_commands_on_hashes_test.rb +6 -7
  30. data/test/distributed_commands_on_lists_test.rb +13 -14
  31. data/test/distributed_commands_on_sets_test.rb +57 -58
  32. data/test/distributed_commands_on_sorted_sets_test.rb +11 -12
  33. data/test/distributed_commands_on_strings_test.rb +31 -32
  34. data/test/distributed_commands_on_value_types_test.rb +61 -46
  35. data/test/distributed_commands_requiring_clustering_test.rb +108 -108
  36. data/test/distributed_connection_handling_test.rb +14 -15
  37. data/test/distributed_internals_test.rb +7 -19
  38. data/test/distributed_key_tags_test.rb +36 -36
  39. data/test/distributed_persistence_control_commands_test.rb +17 -14
  40. data/test/distributed_publish_subscribe_test.rb +61 -69
  41. data/test/distributed_remote_server_control_commands_test.rb +39 -28
  42. data/test/distributed_sorting_test.rb +12 -13
  43. data/test/distributed_test.rb +40 -41
  44. data/test/distributed_transactions_test.rb +20 -21
  45. data/test/encoding_test.rb +12 -9
  46. data/test/error_replies_test.rb +42 -36
  47. data/test/helper.rb +118 -85
  48. data/test/helper_test.rb +20 -6
  49. data/test/internals_test.rb +167 -103
  50. data/test/lint/blocking_commands.rb +124 -0
  51. data/test/lint/hashes.rb +115 -93
  52. data/test/lint/lists.rb +86 -80
  53. data/test/lint/sets.rb +68 -62
  54. data/test/lint/sorted_sets.rb +200 -195
  55. data/test/lint/strings.rb +112 -94
  56. data/test/lint/value_types.rb +76 -55
  57. data/test/persistence_control_commands_test.rb +17 -12
  58. data/test/pipelining_commands_test.rb +135 -126
  59. data/test/publish_subscribe_test.rb +105 -110
  60. data/test/remote_server_control_commands_test.rb +74 -58
  61. data/test/sorting_test.rb +31 -29
  62. data/test/support/connection/hiredis.rb +1 -0
  63. data/test/support/connection/ruby.rb +1 -0
  64. data/test/support/connection/synchrony.rb +17 -0
  65. data/test/{redis_mock.rb → support/redis_mock.rb} +24 -21
  66. data/test/support/wire/synchrony.rb +24 -0
  67. data/test/support/wire/thread.rb +5 -0
  68. data/test/synchrony_driver.rb +9 -9
  69. data/test/test.conf +1 -1
  70. data/test/thread_safety_test.rb +21 -19
  71. data/test/transactions_test.rb +189 -118
  72. data/test/unknown_commands_test.rb +9 -8
  73. data/test/url_param_test.rb +46 -41
  74. metadata +28 -43
  75. data/TODO.md +0 -4
  76. data/benchmarking/thread_safety.rb +0 -38
  77. data/test/lint/internals.rb +0 -36
@@ -1,100 +1,92 @@
1
1
  # encoding: UTF-8
2
2
 
3
- require File.expand_path("./helper", File.dirname(__FILE__))
4
- require "redis/distributed"
3
+ require "helper"
5
4
 
6
- setup do
7
- log = StringIO.new
8
- init Redis::Distributed.new(NODES, :logger => ::Logger.new(log))
9
- end
5
+ class TestDistributedPublishSubscribe < Test::Unit::TestCase
10
6
 
11
- test "SUBSCRIBE and UNSUBSCRIBE" do |r|
12
- assert_raise Redis::Distributed::CannotDistribute do
13
- r.subscribe("foo", "bar") { }
14
- end
7
+ include Helper::Distributed
8
+
9
+ def test_subscribe_and_unsubscribe
10
+ assert_raise Redis::Distributed::CannotDistribute do
11
+ r.subscribe("foo", "bar") { }
12
+ end
15
13
 
16
- assert_raise Redis::Distributed::CannotDistribute do
17
- r.subscribe("{qux}foo", "bar") { }
14
+ assert_raise Redis::Distributed::CannotDistribute do
15
+ r.subscribe("{qux}foo", "bar") { }
16
+ end
18
17
  end
19
- end
20
18
 
21
- test "SUBSCRIBE and UNSUBSCRIBE with tags" do |r|
22
- listening = false
19
+ def test_subscribe_and_unsubscribe_with_tags
20
+ @subscribed = false
21
+ @unsubscribed = false
23
22
 
24
- wire = Wire.new do
25
- r.subscribe("foo") do |on|
26
- on.subscribe do |channel, total|
27
- @subscribed = true
28
- @t1 = total
29
- end
23
+ wire = Wire.new do
24
+ r.subscribe("foo") do |on|
25
+ on.subscribe do |channel, total|
26
+ @subscribed = true
27
+ @t1 = total
28
+ end
30
29
 
31
- on.message do |channel, message|
32
- if message == "s1"
33
- r.unsubscribe
34
- @message = message
30
+ on.message do |channel, message|
31
+ if message == "s1"
32
+ r.unsubscribe
33
+ @message = message
34
+ end
35
35
  end
36
- end
37
36
 
38
- on.unsubscribe do |channel, total|
39
- @unsubscribed = true
40
- @t2 = total
37
+ on.unsubscribe do |channel, total|
38
+ @unsubscribed = true
39
+ @t2 = total
40
+ end
41
41
  end
42
-
43
- listening = true
44
42
  end
45
- end
46
43
 
47
- Wire.pass while !listening
44
+ # Wait until the subscription is active before publishing
45
+ Wire.pass while !@subscribed
48
46
 
49
- Redis::Distributed.new(NODES).publish("foo", "s1")
47
+ Redis::Distributed.new(NODES).publish("foo", "s1")
50
48
 
51
- wire.join
49
+ wire.join
52
50
 
53
- assert @subscribed
54
- assert 1 == @t1
55
- assert @unsubscribed
56
- assert 0 == @t2
57
- assert "s1" == @message
58
- end
51
+ assert @subscribed
52
+ assert_equal 1, @t1
53
+ assert @unsubscribed
54
+ assert_equal 0, @t2
55
+ assert_equal "s1", @message
56
+ end
59
57
 
60
- test "SUBSCRIBE within SUBSCRIBE" do |r|
61
- listening = false
62
- @channels = []
58
+ def test_subscribe_within_subscribe
59
+ @channels = []
63
60
 
64
- wire = Wire.new do
65
- r.subscribe("foo") do |on|
66
- on.subscribe do |channel, total|
67
- @channels << channel
61
+ wire = Wire.new do
62
+ r.subscribe("foo") do |on|
63
+ on.subscribe do |channel, total|
64
+ @channels << channel
68
65
 
69
- r.subscribe("bar") if channel == "foo"
70
- r.unsubscribe if channel == "bar"
66
+ r.subscribe("bar") if channel == "foo"
67
+ r.unsubscribe if channel == "bar"
68
+ end
71
69
  end
72
-
73
- listening = true
74
70
  end
75
- end
76
-
77
- Wire.pass while !listening
78
71
 
79
- Redis::Distributed.new(NODES).publish("foo", "s1")
72
+ wire.join
80
73
 
81
- wire.join
82
-
83
- assert ["foo", "bar"] == @channels
84
- end
74
+ assert_equal ["foo", "bar"], @channels
75
+ end
85
76
 
86
- test "other commands within a SUBSCRIBE" do |r|
87
- assert_raise Redis::CommandError do
88
- r.subscribe("foo") do |on|
89
- on.subscribe do |channel, total|
90
- r.set("bar", "s2")
77
+ def test_other_commands_within_a_subscribe
78
+ assert_raise Redis::CommandError do
79
+ r.subscribe("foo") do |on|
80
+ on.subscribe do |channel, total|
81
+ r.set("bar", "s2")
82
+ end
91
83
  end
92
84
  end
93
85
  end
94
- end
95
86
 
96
- test "SUBSCRIBE without a block" do |r|
97
- assert_raise LocalJumpError do
98
- r.subscribe("foo")
87
+ def test_subscribe_without_a_block
88
+ assert_raise LocalJumpError do
89
+ r.subscribe("foo")
90
+ end
99
91
  end
100
92
  end
@@ -1,42 +1,53 @@
1
1
  # encoding: UTF-8
2
2
 
3
- require File.expand_path("./helper", File.dirname(__FILE__))
4
- require "redis/distributed"
3
+ require "helper"
5
4
 
6
- setup do
7
- log = StringIO.new
8
- init Redis::Distributed.new(NODES, :logger => ::Logger.new(log))
9
- end
5
+ class TestDistributedRemoteServerControlCommands < Test::Unit::TestCase
6
+
7
+ include Helper::Distributed
10
8
 
11
- test "INFO" do |r|
12
- %w(last_save_time redis_version total_connections_received connected_clients total_commands_processed connected_slaves uptime_in_seconds used_memory uptime_in_days changes_since_last_save).each do |x|
13
- r.info.each do |info|
14
- assert info.keys.include?(x)
9
+ def test_info
10
+ %w(last_save_time redis_version total_connections_received connected_clients total_commands_processed connected_slaves uptime_in_seconds used_memory uptime_in_days changes_since_last_save).each do |x|
11
+ r.info.each do |info|
12
+ assert info.keys.include?(x)
13
+ end
15
14
  end
16
15
  end
17
- end
18
16
 
19
- test "INFO COMMANDSTATS" do |r|
20
- # Only available on Redis >= 2.9.0
21
- next if version(r) < 209000
17
+ def test_info_commandstats
18
+ return if version < "2.9.0"
22
19
 
23
- r.nodes.each { |n| n.config(:resetstat) }
24
- r.ping # Executed on every node
20
+ r.nodes.each { |n| n.config(:resetstat) }
21
+ r.ping # Executed on every node
25
22
 
26
- r.info(:commandstats).each do |info|
27
- assert "1" == info["ping"]["calls"]
23
+ r.info(:commandstats).each do |info|
24
+ assert_equal "1", info["ping"]["calls"]
25
+ end
28
26
  end
29
- end
30
27
 
31
- test "MONITOR" do |r|
32
- begin
33
- r.monitor
34
- rescue Exception => ex
35
- ensure
36
- assert ex.kind_of?(NotImplementedError)
28
+ def test_monitor
29
+ begin
30
+ r.monitor
31
+ rescue Exception => ex
32
+ ensure
33
+ assert ex.kind_of?(NotImplementedError)
34
+ end
37
35
  end
38
- end
39
36
 
40
- test "ECHO" do |r|
41
- assert ["foo bar baz\n"] == r.echo("foo bar baz\n")
37
+ def test_echo
38
+ assert_equal ["foo bar baz\n"], r.echo("foo bar baz\n")
39
+ end
40
+
41
+ def test_time
42
+ return if version < "2.5.4"
43
+
44
+ # Test that the difference between the time that Ruby reports and the time
45
+ # that Redis reports is minimal (prevents the test from being racy).
46
+ r.time.each do |rv|
47
+ redis_usec = rv[0] * 1_000_000 + rv[1]
48
+ ruby_usec = Integer(Time.now.to_f * 1_000_000)
49
+
50
+ assert 500_000 > (ruby_usec - redis_usec).abs
51
+ end
52
+ end
42
53
  end
@@ -1,21 +1,20 @@
1
1
  # encoding: UTF-8
2
2
 
3
- require File.expand_path("./helper", File.dirname(__FILE__))
4
- require "redis/distributed"
3
+ require "helper"
5
4
 
6
- setup do
7
- log = StringIO.new
8
- init Redis::Distributed.new(NODES, :logger => ::Logger.new(log))
9
- end
5
+ class TestDistributedSorting < Test::Unit::TestCase
6
+
7
+ include Helper::Distributed
10
8
 
11
- test "SORT" do |r|
12
- assert_raise Redis::Distributed::CannotDistribute do
13
- r.set("foo:1", "s1")
14
- r.set("foo:2", "s2")
9
+ def test_sort
10
+ assert_raise(Redis::Distributed::CannotDistribute) do
11
+ r.set("foo:1", "s1")
12
+ r.set("foo:2", "s2")
15
13
 
16
- r.rpush("bar", "1")
17
- r.rpush("bar", "2")
14
+ r.rpush("bar", "1")
15
+ r.rpush("bar", "2")
18
16
 
19
- r.sort("bar", :get => "foo:*", :limit => [0, 1])
17
+ r.sort("bar", :get => "foo:*", :limit => [0, 1])
18
+ end
20
19
  end
21
20
  end
@@ -1,59 +1,58 @@
1
1
  # encoding: UTF-8
2
2
 
3
- require File.expand_path("./helper", File.dirname(__FILE__))
4
- require "redis/distributed"
3
+ require "helper"
5
4
 
6
- setup do
7
- log = StringIO.new
8
- init Redis::Distributed.new(NODES, :logger => ::Logger.new(log))
9
- end
5
+ class TestDistributed < Test::Unit::TestCase
10
6
 
11
- test "handle multiple servers" do
12
- @r = Redis::Distributed.new ["redis://localhost:6379/15", *NODES]
7
+ include Helper::Distributed
13
8
 
14
- 100.times do |idx|
15
- @r.set(idx.to_s, "foo#{idx}")
16
- end
9
+ def test_handle_multiple_servers
10
+ @r = Redis::Distributed.new ["redis://localhost:#{PORT}/15", *NODES]
17
11
 
18
- 100.times do |idx|
19
- assert "foo#{idx}" == @r.get(idx.to_s)
20
- end
12
+ 100.times do |idx|
13
+ @r.set(idx.to_s, "foo#{idx}")
14
+ end
21
15
 
22
- assert "0" == @r.keys("*").sort.first
23
- assert "string" == @r.type("1")
24
- end
16
+ 100.times do |idx|
17
+ assert_equal "foo#{idx}", @r.get(idx.to_s)
18
+ end
25
19
 
26
- test "add nodes" do
27
- logger = Logger.new("/dev/null")
20
+ assert_equal "0", @r.keys("*").sort.first
21
+ assert_equal "string", @r.type("1")
22
+ end
28
23
 
29
- @r = Redis::Distributed.new NODES, :logger => logger, :timeout => 10
24
+ def test_add_nodes
25
+ logger = Logger.new("/dev/null")
30
26
 
31
- assert "127.0.0.1" == @r.nodes[0].client.host
32
- assert 6379 == @r.nodes[0].client.port
33
- assert 15 == @r.nodes[0].client.db
34
- assert 10 == @r.nodes[0].client.timeout
35
- assert logger == @r.nodes[0].client.logger
27
+ @r = Redis::Distributed.new NODES, :logger => logger, :timeout => 10
36
28
 
37
- @r.add_node("redis://localhost:6380/14")
29
+ assert_equal "127.0.0.1", @r.nodes[0].client.host
30
+ assert_equal PORT, @r.nodes[0].client.port
31
+ assert_equal 15, @r.nodes[0].client.db
32
+ assert_equal 10, @r.nodes[0].client.timeout
33
+ assert_equal logger, @r.nodes[0].client.logger
38
34
 
39
- assert "localhost" == @r.nodes[1].client.host
40
- assert 6380 == @r.nodes[1].client.port
41
- assert 14 == @r.nodes[1].client.db
42
- assert 10 == @r.nodes[1].client.timeout
43
- assert logger == @r.nodes[1].client.logger
44
- end
35
+ @r.add_node("redis://localhost:6380/14")
36
+
37
+ assert_equal "localhost", @r.nodes[1].client.host
38
+ assert_equal 6380, @r.nodes[1].client.port
39
+ assert_equal 14, @r.nodes[1].client.db
40
+ assert_equal 10, @r.nodes[1].client.timeout
41
+ assert_equal logger, @r.nodes[1].client.logger
42
+ end
45
43
 
46
- test "Pipelining commands cannot be distributed" do |r|
47
- assert_raise Redis::Distributed::CannotDistribute do
48
- r.pipelined do
49
- r.lpush "foo", "s1"
50
- r.lpush "foo", "s2"
44
+ def test_pipelining_commands_cannot_be_distributed
45
+ assert_raise Redis::Distributed::CannotDistribute do
46
+ r.pipelined do
47
+ r.lpush "foo", "s1"
48
+ r.lpush "foo", "s2"
49
+ end
51
50
  end
52
51
  end
53
- end
54
52
 
55
- test "Unknown commands does not work by default" do |r|
56
- assert_raise NoMethodError do
57
- r.not_yet_implemented_command
53
+ def test_unknown_commands_does_not_work_by_default
54
+ assert_raise NoMethodError do
55
+ r.not_yet_implemented_command
56
+ end
58
57
  end
59
58
  end
@@ -1,33 +1,32 @@
1
1
  # encoding: UTF-8
2
2
 
3
- require File.expand_path("./helper", File.dirname(__FILE__))
4
- require "redis/distributed"
3
+ require "helper"
5
4
 
6
- setup do
7
- log = StringIO.new
8
- init Redis::Distributed.new(NODES, :logger => ::Logger.new(log))
9
- end
5
+ class TestDistributedTransactions < Test::Unit::TestCase
10
6
 
11
- test "MULTI/DISCARD" do |r|
12
- @foo = nil
7
+ include Helper::Distributed
13
8
 
14
- assert_raise Redis::Distributed::CannotDistribute do
15
- r.multi { @foo = 1 }
16
- end
9
+ def test_multi_discard
10
+ @foo = nil
17
11
 
18
- assert nil == @foo
12
+ assert_raise Redis::Distributed::CannotDistribute do
13
+ r.multi { @foo = 1 }
14
+ end
19
15
 
20
- assert_raise Redis::Distributed::CannotDistribute do
21
- r.discard
22
- end
23
- end
16
+ assert_equal nil, @foo
24
17
 
25
- test "WATCH/UNWATCH" do |r|
26
- assert_raise Redis::Distributed::CannotDistribute do
27
- r.watch("foo")
18
+ assert_raise Redis::Distributed::CannotDistribute do
19
+ r.discard
20
+ end
28
21
  end
29
22
 
30
- assert_raise Redis::Distributed::CannotDistribute do
31
- r.unwatch
23
+ def test_watch_unwatch
24
+ assert_raise Redis::Distributed::CannotDistribute do
25
+ r.watch("foo")
26
+ end
27
+
28
+ assert_raise Redis::Distributed::CannotDistribute do
29
+ r.unwatch
30
+ end
32
31
  end
33
32
  end
@@ -1,15 +1,18 @@
1
1
  # encoding: UTF-8
2
2
 
3
- require File.expand_path("./helper", File.dirname(__FILE__))
3
+ require "helper"
4
4
 
5
- setup do
6
- init Redis.new(OPTIONS)
7
- end
5
+ class TestEncoding < Test::Unit::TestCase
6
+
7
+ include Helper::Client
8
8
 
9
- test "returns properly encoded strings" do |r|
10
- with_external_encoding("UTF-8") do
11
- r.set "foo", "שלום"
9
+ def test_returns_properly_encoded_strings
10
+ if defined?(Encoding)
11
+ with_external_encoding("UTF-8") do
12
+ r.set "foo", "שלום"
12
13
 
13
- assert "Shalom שלום" == "Shalom " + r.get("foo")
14
+ assert_equal "Shalom שלום", "Shalom " + r.get("foo")
15
+ end
16
+ end
14
17
  end
15
- end if defined?(Encoding)
18
+ end