redis 3.0.0.rc1 → 3.0.0.rc2

Sign up to get free protection for your applications and to get access to all the features.
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