redis 2.1.1 → 2.2.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.
- data/.gitignore +8 -0
- data/CHANGELOG.md +34 -0
- data/README.md +190 -0
- data/Rakefile +194 -79
- data/benchmarking/logging.rb +62 -0
- data/benchmarking/pipeline.rb +51 -0
- data/benchmarking/speed.rb +21 -0
- data/benchmarking/suite.rb +24 -0
- data/benchmarking/thread_safety.rb +38 -0
- data/benchmarking/worker.rb +71 -0
- data/examples/basic.rb +15 -0
- data/examples/dist_redis.rb +43 -0
- data/examples/incr-decr.rb +17 -0
- data/examples/list.rb +26 -0
- data/examples/pubsub.rb +31 -0
- data/examples/sets.rb +36 -0
- data/examples/unicorn/config.ru +3 -0
- data/examples/unicorn/unicorn.rb +20 -0
- data/lib/redis.rb +612 -156
- data/lib/redis/client.rb +98 -57
- data/lib/redis/connection.rb +9 -134
- data/lib/redis/connection/command_helper.rb +45 -0
- data/lib/redis/connection/hiredis.rb +49 -0
- data/lib/redis/connection/registry.rb +12 -0
- data/lib/redis/connection/ruby.rb +131 -0
- data/lib/redis/connection/synchrony.rb +125 -0
- data/lib/redis/distributed.rb +161 -5
- data/lib/redis/pipeline.rb +6 -0
- data/lib/redis/version.rb +3 -0
- data/redis.gemspec +24 -0
- data/test/commands_on_hashes_test.rb +32 -0
- data/test/commands_on_lists_test.rb +60 -0
- data/test/commands_on_sets_test.rb +78 -0
- data/test/commands_on_sorted_sets_test.rb +109 -0
- data/test/commands_on_strings_test.rb +80 -0
- data/test/commands_on_value_types_test.rb +88 -0
- data/test/connection_handling_test.rb +87 -0
- data/test/db/.gitignore +1 -0
- data/test/distributed_blocking_commands_test.rb +53 -0
- data/test/distributed_commands_on_hashes_test.rb +12 -0
- data/test/distributed_commands_on_lists_test.rb +24 -0
- data/test/distributed_commands_on_sets_test.rb +85 -0
- data/test/distributed_commands_on_strings_test.rb +50 -0
- data/test/distributed_commands_on_value_types_test.rb +73 -0
- data/test/distributed_commands_requiring_clustering_test.rb +148 -0
- data/test/distributed_connection_handling_test.rb +25 -0
- data/test/distributed_internals_test.rb +18 -0
- data/test/distributed_key_tags_test.rb +53 -0
- data/test/distributed_persistence_control_commands_test.rb +24 -0
- data/test/distributed_publish_subscribe_test.rb +101 -0
- data/test/distributed_remote_server_control_commands_test.rb +31 -0
- data/test/distributed_sorting_test.rb +21 -0
- data/test/distributed_test.rb +60 -0
- data/test/distributed_transactions_test.rb +34 -0
- data/test/encoding_test.rb +16 -0
- data/test/error_replies_test.rb +53 -0
- data/test/helper.rb +145 -0
- data/test/internals_test.rb +157 -0
- data/test/lint/hashes.rb +114 -0
- data/test/lint/internals.rb +41 -0
- data/test/lint/lists.rb +93 -0
- data/test/lint/sets.rb +66 -0
- data/test/lint/sorted_sets.rb +167 -0
- data/test/lint/strings.rb +137 -0
- data/test/lint/value_types.rb +84 -0
- data/test/persistence_control_commands_test.rb +22 -0
- data/test/pipelining_commands_test.rb +123 -0
- data/test/publish_subscribe_test.rb +158 -0
- data/test/redis_mock.rb +80 -0
- data/test/remote_server_control_commands_test.rb +63 -0
- data/test/sorting_test.rb +44 -0
- data/test/synchrony_driver.rb +57 -0
- data/test/test.conf +8 -0
- data/test/thread_safety_test.rb +30 -0
- data/test/transactions_test.rb +100 -0
- data/test/unknown_commands_test.rb +14 -0
- data/test/url_param_test.rb +60 -0
- metadata +128 -19
- data/README.markdown +0 -129
| @@ -0,0 +1,25 @@ | |
| 1 | 
            +
            # encoding: UTF-8
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require File.expand_path("./helper", File.dirname(__FILE__))
         | 
| 4 | 
            +
            require "redis/distributed"
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            setup do
         | 
| 7 | 
            +
              log = StringIO.new
         | 
| 8 | 
            +
              init Redis::Distributed.new(NODES, :logger => ::Logger.new(log))
         | 
| 9 | 
            +
            end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            test "PING" do |r|
         | 
| 12 | 
            +
              assert ["PONG"] == r.ping
         | 
| 13 | 
            +
            end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            test "SELECT" do |r|
         | 
| 16 | 
            +
              r.set "foo", "bar"
         | 
| 17 | 
            +
             | 
| 18 | 
            +
              r.select 14
         | 
| 19 | 
            +
              assert nil == r.get("foo")
         | 
| 20 | 
            +
             | 
| 21 | 
            +
              r.select 15
         | 
| 22 | 
            +
             | 
| 23 | 
            +
              assert "bar" == r.get("foo")
         | 
| 24 | 
            +
            end
         | 
| 25 | 
            +
             | 
| @@ -0,0 +1,18 @@ | |
| 1 | 
            +
            # encoding: UTF-8
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require File.expand_path("./helper", File.dirname(__FILE__))
         | 
| 4 | 
            +
            require File.expand_path("./redis_mock", File.dirname(__FILE__))
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            include RedisMock::Helper
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            require "redis/distributed"
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            setup do
         | 
| 11 | 
            +
              log = StringIO.new
         | 
| 12 | 
            +
              [init(Redis::Distributed.new(NODES, :logger => ::Logger.new(log))), log]
         | 
| 13 | 
            +
            end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            $TEST_PIPELINING = false
         | 
| 16 | 
            +
            $TEST_INSPECT    = false
         | 
| 17 | 
            +
             | 
| 18 | 
            +
            load File.expand_path("./lint/internals.rb", File.dirname(__FILE__))
         | 
| @@ -0,0 +1,53 @@ | |
| 1 | 
            +
            # encoding: UTF-8
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require File.expand_path("./helper", File.dirname(__FILE__))
         | 
| 4 | 
            +
            require "redis/distributed"
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            setup do
         | 
| 7 | 
            +
              log = StringIO.new
         | 
| 8 | 
            +
              init Redis::Distributed.new(NODES, :logger => ::Logger.new(log))
         | 
| 9 | 
            +
            end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            test "hashes consistently" do
         | 
| 12 | 
            +
              r1 = Redis::Distributed.new ["redis://localhost:6379/15", *NODES]
         | 
| 13 | 
            +
              r2 = Redis::Distributed.new ["redis://localhost:6379/15", *NODES]
         | 
| 14 | 
            +
              r3 = Redis::Distributed.new ["redis://localhost:6379/15", *NODES]
         | 
| 15 | 
            +
             | 
| 16 | 
            +
              assert r1.node_for("foo").id == r2.node_for("foo").id
         | 
| 17 | 
            +
              assert r1.node_for("foo").id == r3.node_for("foo").id
         | 
| 18 | 
            +
            end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
            test "allows clustering of keys" do |r|
         | 
| 21 | 
            +
              r = Redis::Distributed.new(NODES)
         | 
| 22 | 
            +
              r.add_node("redis://localhost:6379/14")
         | 
| 23 | 
            +
              r.flushdb
         | 
| 24 | 
            +
             | 
| 25 | 
            +
              100.times do |i|
         | 
| 26 | 
            +
                r.set "{foo}users:#{i}", i
         | 
| 27 | 
            +
              end
         | 
| 28 | 
            +
             | 
| 29 | 
            +
              assert [0, 100] == r.nodes.map { |node| node.keys.size }
         | 
| 30 | 
            +
            end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
            test "distributes keys if no clustering is used" do |r|
         | 
| 33 | 
            +
              r.add_node("redis://localhost:6379/14")
         | 
| 34 | 
            +
              r.flushdb
         | 
| 35 | 
            +
             | 
| 36 | 
            +
              r.set "users:1", 1
         | 
| 37 | 
            +
              r.set "users:4", 4
         | 
| 38 | 
            +
             | 
| 39 | 
            +
              assert [1, 1] == r.nodes.map { |node| node.keys.size }
         | 
| 40 | 
            +
            end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
            test "allows passing a custom tag extractor" do |r|
         | 
| 43 | 
            +
              r = Redis::Distributed.new(NODES, :tag => /^(.+?):/)
         | 
| 44 | 
            +
              r.add_node("redis://localhost:6379/14")
         | 
| 45 | 
            +
              r.flushdb
         | 
| 46 | 
            +
             | 
| 47 | 
            +
              100.times do |i|
         | 
| 48 | 
            +
                r.set "foo:users:#{i}", i
         | 
| 49 | 
            +
              end
         | 
| 50 | 
            +
             | 
| 51 | 
            +
              assert [0, 100] == r.nodes.map { |node| node.keys.size }
         | 
| 52 | 
            +
            end
         | 
| 53 | 
            +
             | 
| @@ -0,0 +1,24 @@ | |
| 1 | 
            +
            # encoding: UTF-8
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require File.expand_path("./helper", File.dirname(__FILE__))
         | 
| 4 | 
            +
            require "redis/distributed"
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            setup do
         | 
| 7 | 
            +
              log = StringIO.new
         | 
| 8 | 
            +
              init Redis::Distributed.new(NODES, :logger => ::Logger.new(log))
         | 
| 9 | 
            +
            end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            test "SAVE and BGSAVE" do |r|
         | 
| 12 | 
            +
              assert_nothing_raised do
         | 
| 13 | 
            +
                r.save
         | 
| 14 | 
            +
              end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
              assert_nothing_raised do
         | 
| 17 | 
            +
                r.bgsave
         | 
| 18 | 
            +
              end
         | 
| 19 | 
            +
            end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
            test "LASTSAVE" do |r|
         | 
| 22 | 
            +
              assert r.lastsave.all? { |t| Time.at(t) <= Time.now }
         | 
| 23 | 
            +
            end
         | 
| 24 | 
            +
             | 
| @@ -0,0 +1,101 @@ | |
| 1 | 
            +
            # encoding: UTF-8
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require File.expand_path("./helper", File.dirname(__FILE__))
         | 
| 4 | 
            +
            require "redis/distributed"
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            setup do
         | 
| 7 | 
            +
              log = StringIO.new
         | 
| 8 | 
            +
              init Redis::Distributed.new(NODES, :logger => ::Logger.new(log))
         | 
| 9 | 
            +
            end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            test "SUBSCRIBE and UNSUBSCRIBE" do |r|
         | 
| 12 | 
            +
              assert_raise Redis::Distributed::CannotDistribute do
         | 
| 13 | 
            +
                r.subscribe("foo", "bar") { }
         | 
| 14 | 
            +
              end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
              assert_raise Redis::Distributed::CannotDistribute do
         | 
| 17 | 
            +
                r.subscribe("{qux}foo", "bar") { }
         | 
| 18 | 
            +
              end
         | 
| 19 | 
            +
            end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
            test "SUBSCRIBE and UNSUBSCRIBE with tags" do |r|
         | 
| 22 | 
            +
              listening = false
         | 
| 23 | 
            +
             | 
| 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
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                  on.message do |channel, message|
         | 
| 32 | 
            +
                    if message == "s1"
         | 
| 33 | 
            +
                      r.unsubscribe
         | 
| 34 | 
            +
                      @message = message
         | 
| 35 | 
            +
                    end
         | 
| 36 | 
            +
                  end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                  on.unsubscribe do |channel, total|
         | 
| 39 | 
            +
                    @unsubscribed = true
         | 
| 40 | 
            +
                    @t2 = total
         | 
| 41 | 
            +
                  end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                  listening = true
         | 
| 44 | 
            +
                end
         | 
| 45 | 
            +
              end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
              Wire.pass while !listening
         | 
| 48 | 
            +
             | 
| 49 | 
            +
              Redis::Distributed.new(NODES).publish("foo", "s1")
         | 
| 50 | 
            +
             | 
| 51 | 
            +
              wire.join
         | 
| 52 | 
            +
             | 
| 53 | 
            +
              assert @subscribed
         | 
| 54 | 
            +
              assert 1 == @t1
         | 
| 55 | 
            +
              assert @unsubscribed
         | 
| 56 | 
            +
              assert 0 == @t2
         | 
| 57 | 
            +
              assert "s1" == @message
         | 
| 58 | 
            +
            end
         | 
| 59 | 
            +
             | 
| 60 | 
            +
            test "SUBSCRIBE within SUBSCRIBE" do |r|
         | 
| 61 | 
            +
              listening = false
         | 
| 62 | 
            +
              @channels = []
         | 
| 63 | 
            +
             | 
| 64 | 
            +
              wire = Wire.new do
         | 
| 65 | 
            +
                r.subscribe("foo") do |on|
         | 
| 66 | 
            +
                  on.subscribe do |channel, total|
         | 
| 67 | 
            +
                    @channels << channel
         | 
| 68 | 
            +
             | 
| 69 | 
            +
                    r.subscribe("bar") if channel == "foo"
         | 
| 70 | 
            +
                    r.unsubscribe if channel == "bar"
         | 
| 71 | 
            +
                  end
         | 
| 72 | 
            +
             | 
| 73 | 
            +
                  listening = true
         | 
| 74 | 
            +
                end
         | 
| 75 | 
            +
              end
         | 
| 76 | 
            +
             | 
| 77 | 
            +
              Wire.pass while !listening
         | 
| 78 | 
            +
             | 
| 79 | 
            +
              Redis::Distributed.new(NODES).publish("foo", "s1")
         | 
| 80 | 
            +
             | 
| 81 | 
            +
              wire.join
         | 
| 82 | 
            +
             | 
| 83 | 
            +
              assert ["foo", "bar"] == @channels
         | 
| 84 | 
            +
            end
         | 
| 85 | 
            +
             | 
| 86 | 
            +
            test "other commands within a SUBSCRIBE" do |r|
         | 
| 87 | 
            +
              assert_raise RuntimeError do
         | 
| 88 | 
            +
                r.subscribe("foo") do |on|
         | 
| 89 | 
            +
                  on.subscribe do |channel, total|
         | 
| 90 | 
            +
                    r.set("bar", "s2")
         | 
| 91 | 
            +
                  end
         | 
| 92 | 
            +
                end
         | 
| 93 | 
            +
              end
         | 
| 94 | 
            +
            end
         | 
| 95 | 
            +
             | 
| 96 | 
            +
            test "SUBSCRIBE without a block" do |r|
         | 
| 97 | 
            +
              assert_raise LocalJumpError do
         | 
| 98 | 
            +
                r.subscribe("foo")
         | 
| 99 | 
            +
              end
         | 
| 100 | 
            +
            end
         | 
| 101 | 
            +
             | 
| @@ -0,0 +1,31 @@ | |
| 1 | 
            +
            # encoding: UTF-8
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require File.expand_path("./helper", File.dirname(__FILE__))
         | 
| 4 | 
            +
            require "redis/distributed"
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            setup do
         | 
| 7 | 
            +
              log = StringIO.new
         | 
| 8 | 
            +
              init Redis::Distributed.new(NODES, :logger => ::Logger.new(log))
         | 
| 9 | 
            +
            end
         | 
| 10 | 
            +
             | 
| 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)
         | 
| 15 | 
            +
                end
         | 
| 16 | 
            +
              end
         | 
| 17 | 
            +
            end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            test "MONITOR" do |r|
         | 
| 20 | 
            +
              begin
         | 
| 21 | 
            +
                r.monitor
         | 
| 22 | 
            +
              rescue Exception => ex
         | 
| 23 | 
            +
              ensure
         | 
| 24 | 
            +
                assert ex.kind_of?(NotImplementedError)
         | 
| 25 | 
            +
              end
         | 
| 26 | 
            +
            end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
            test "ECHO" do |r|
         | 
| 29 | 
            +
              assert ["foo bar baz\n"] == r.echo("foo bar baz\n")
         | 
| 30 | 
            +
            end
         | 
| 31 | 
            +
             | 
| @@ -0,0 +1,21 @@ | |
| 1 | 
            +
            # encoding: UTF-8
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require File.expand_path("./helper", File.dirname(__FILE__))
         | 
| 4 | 
            +
            require "redis/distributed"
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            setup do
         | 
| 7 | 
            +
              log = StringIO.new
         | 
| 8 | 
            +
              init Redis::Distributed.new(NODES, :logger => ::Logger.new(log))
         | 
| 9 | 
            +
            end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            test "SORT" do |r|
         | 
| 12 | 
            +
              assert_raise Redis::Distributed::CannotDistribute do
         | 
| 13 | 
            +
                r.set("foo:1", "s1")
         | 
| 14 | 
            +
                r.set("foo:2", "s2")
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                r.rpush("bar", "1")
         | 
| 17 | 
            +
                r.rpush("bar", "2")
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                r.sort("bar", :get => "foo:*", :limit => [0, 1])
         | 
| 20 | 
            +
              end
         | 
| 21 | 
            +
            end
         | 
| @@ -0,0 +1,60 @@ | |
| 1 | 
            +
            # encoding: UTF-8
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require File.expand_path("./helper", File.dirname(__FILE__))
         | 
| 4 | 
            +
            require "redis/distributed"
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            setup do
         | 
| 7 | 
            +
              log = StringIO.new
         | 
| 8 | 
            +
              init Redis::Distributed.new(NODES, :logger => ::Logger.new(log))
         | 
| 9 | 
            +
            end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            test "handle multiple servers" do
         | 
| 12 | 
            +
              @r = Redis::Distributed.new ["redis://localhost:6379/15", *NODES]
         | 
| 13 | 
            +
             | 
| 14 | 
            +
              100.times do |idx|
         | 
| 15 | 
            +
                @r.set(idx.to_s, "foo#{idx}")
         | 
| 16 | 
            +
              end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
              100.times do |idx|
         | 
| 19 | 
            +
                assert "foo#{idx}" == @r.get(idx.to_s)
         | 
| 20 | 
            +
              end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
              assert "0" == @r.keys("*").sort.first
         | 
| 23 | 
            +
              assert "string" == @r.type("1")
         | 
| 24 | 
            +
            end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
            test "add nodes" do
         | 
| 27 | 
            +
              logger = Logger.new("/dev/null")
         | 
| 28 | 
            +
             | 
| 29 | 
            +
              @r = Redis::Distributed.new NODES, :logger => logger, :timeout => 10
         | 
| 30 | 
            +
             | 
| 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
         | 
| 36 | 
            +
             | 
| 37 | 
            +
              @r.add_node("redis://localhost:6380/14")
         | 
| 38 | 
            +
             | 
| 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
         | 
| 45 | 
            +
             | 
| 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"
         | 
| 51 | 
            +
                end
         | 
| 52 | 
            +
              end
         | 
| 53 | 
            +
            end
         | 
| 54 | 
            +
             | 
| 55 | 
            +
            test "Unknown commands does not work by default" do |r|
         | 
| 56 | 
            +
              assert_raise NoMethodError do
         | 
| 57 | 
            +
                r.not_yet_implemented_command
         | 
| 58 | 
            +
              end
         | 
| 59 | 
            +
            end
         | 
| 60 | 
            +
             | 
| @@ -0,0 +1,34 @@ | |
| 1 | 
            +
            # encoding: UTF-8
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require File.expand_path("./helper", File.dirname(__FILE__))
         | 
| 4 | 
            +
            require "redis/distributed"
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            setup do
         | 
| 7 | 
            +
              log = StringIO.new
         | 
| 8 | 
            +
              init Redis::Distributed.new(NODES, :logger => ::Logger.new(log))
         | 
| 9 | 
            +
            end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            test "MULTI/DISCARD" do |r|
         | 
| 12 | 
            +
              @foo = nil
         | 
| 13 | 
            +
             | 
| 14 | 
            +
              assert_raise Redis::Distributed::CannotDistribute do
         | 
| 15 | 
            +
                r.multi { @foo = 1 }
         | 
| 16 | 
            +
              end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
              assert nil == @foo
         | 
| 19 | 
            +
             | 
| 20 | 
            +
              assert_raise Redis::Distributed::CannotDistribute do
         | 
| 21 | 
            +
                r.discard
         | 
| 22 | 
            +
              end
         | 
| 23 | 
            +
            end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
            test "WATCH/UNWATCH" do |r|
         | 
| 26 | 
            +
              assert_raise Redis::Distributed::CannotDistribute do
         | 
| 27 | 
            +
                r.watch("foo")
         | 
| 28 | 
            +
              end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
              assert_raise Redis::Distributed::CannotDistribute do
         | 
| 31 | 
            +
                r.unwatch
         | 
| 32 | 
            +
              end
         | 
| 33 | 
            +
            end
         | 
| 34 | 
            +
             | 
| @@ -0,0 +1,16 @@ | |
| 1 | 
            +
            # encoding: UTF-8
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require File.expand_path("./helper", File.dirname(__FILE__))
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            setup do
         | 
| 6 | 
            +
              init Redis.new(OPTIONS)
         | 
| 7 | 
            +
            end
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            test "returns properly encoded strings" do |r|
         | 
| 10 | 
            +
              with_external_encoding("UTF-8") do
         | 
| 11 | 
            +
                r.set "foo", "שלום"
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                assert "Shalom שלום" == "Shalom " + r.get("foo")
         | 
| 14 | 
            +
              end
         | 
| 15 | 
            +
            end if defined?(Encoding)
         | 
| 16 | 
            +
             | 
| @@ -0,0 +1,53 @@ | |
| 1 | 
            +
            # encoding: UTF-8
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require File.expand_path("./helper", File.dirname(__FILE__))
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            setup do
         | 
| 6 | 
            +
              init Redis.new(OPTIONS)
         | 
| 7 | 
            +
            end
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            # Every test shouldn't disconnect from the server. Also, when error replies are
         | 
| 10 | 
            +
            # in play, the protocol should never get into an invalid state where there are
         | 
| 11 | 
            +
            # pending replies in the connection. Calling INFO after every test ensures that
         | 
| 12 | 
            +
            # the protocol is still in a valid state.
         | 
| 13 | 
            +
            def test_with_reconnection_check(title)
         | 
| 14 | 
            +
              test(title) do |r|
         | 
| 15 | 
            +
                before = r.info["total_connections_received"]
         | 
| 16 | 
            +
                yield(r)
         | 
| 17 | 
            +
                after = r.info["total_connections_received"]
         | 
| 18 | 
            +
                assert before == after
         | 
| 19 | 
            +
              end
         | 
| 20 | 
            +
            end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
            test_with_reconnection_check "Error reply for single command" do |r|
         | 
| 23 | 
            +
              begin
         | 
| 24 | 
            +
                r.unknown_command
         | 
| 25 | 
            +
              rescue => ex
         | 
| 26 | 
            +
              ensure
         | 
| 27 | 
            +
                assert ex.message =~ /unknown command/i
         | 
| 28 | 
            +
              end
         | 
| 29 | 
            +
            end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
            test_with_reconnection_check "Raise first error reply in pipeline" do |r|
         | 
| 32 | 
            +
              begin
         | 
| 33 | 
            +
                r.pipelined do
         | 
| 34 | 
            +
                  r.set("foo", "s1")
         | 
| 35 | 
            +
                  r.incr("foo") # not an integer
         | 
| 36 | 
            +
                  r.lpush("foo", "value") # wrong kind of value
         | 
| 37 | 
            +
                end
         | 
| 38 | 
            +
              rescue => ex
         | 
| 39 | 
            +
              ensure
         | 
| 40 | 
            +
                assert ex.message =~ /not an integer/i
         | 
| 41 | 
            +
              end
         | 
| 42 | 
            +
            end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
            test_with_reconnection_check "Recover from raise in #call_loop" do |r|
         | 
| 45 | 
            +
              begin
         | 
| 46 | 
            +
                r.client.call_loop(:invalid_monitor) do
         | 
| 47 | 
            +
                  assert false # Should never be executed
         | 
| 48 | 
            +
                end
         | 
| 49 | 
            +
              rescue => ex
         | 
| 50 | 
            +
              ensure
         | 
| 51 | 
            +
                assert ex.message =~ /unknown command/i
         | 
| 52 | 
            +
              end
         | 
| 53 | 
            +
            end
         |