From aeadcc1dd601bef51ab4d6c9e6956f1f8bfdecdd Mon Sep 17 00:00:00 2001 From: bitterb Date: Sat, 2 Feb 2013 11:07:50 +0900 Subject: [PATCH 01/34] Add support for CLIENT commands --- lib/redis.rb | 22 ++++++- lib/redis/distributed.rb | 5 ++ ...ted_remote_server_control_commands_test.rb | 55 +++++++++++++++++ test/remote_server_control_commands_test.rb | 59 +++++++++++++++++++ 4 files changed, 139 insertions(+), 2 deletions(-) diff --git a/lib/redis.rb b/lib/redis.rb index 4f9ca8246..d2aa47c1f 100644 --- a/lib/redis.rb +++ b/lib/redis.rb @@ -7,8 +7,6 @@ def self.deprecate(message, trace = caller[0]) $stderr.puts "\n#{message} (in #{trace})" end - attr :client - # @deprecated The preferred way to create a new client object is using `#new`. # This method does not actually establish a connection to Redis, # in contrary to what you might expect. @@ -138,6 +136,26 @@ def config(action, *args) end end + # Manage client connections. + # + # @param [String, Symbol] subcommand e.g. `kill`, `list`, `getname`, `setname` + # @return [String, Hash] depends on subcommand + def client(subcommand=nil, *args) + return @client if subcommand.nil? # for backward compatibility + synchronize do |client| + client.call([:client, subcommand] + args) do |reply| + if subcommand.to_s == "list" + reply.lines.map do |line| + entries = line.chomp.split(/[ =]/) + Hash[entries.each_slice(2).to_a] + end + else + reply + end + end + end + end + # Return the number of keys in the selected database. # # @return [Fixnum] diff --git a/lib/redis/distributed.rb b/lib/redis/distributed.rb index b474a2127..ffcd07a90 100644 --- a/lib/redis/distributed.rb +++ b/lib/redis/distributed.rb @@ -62,6 +62,11 @@ def bgsave on_each_node :bgsave end + # Manage client connections + def client(subcommand=nil, *args) + on_each_node :client, subcommand, args + end + # Return the number of keys in the selected database. def dbsize on_each_node :dbsize diff --git a/test/distributed_remote_server_control_commands_test.rb b/test/distributed_remote_server_control_commands_test.rb index 830a1e292..9d44a34e3 100644 --- a/test/distributed_remote_server_control_commands_test.rb +++ b/test/distributed_remote_server_control_commands_test.rb @@ -63,4 +63,59 @@ def test_time assert 500_000 > (ruby_usec - redis_usec).abs end end + + def test_client_list + return if version < "2.4.0" + + keys = [ + "addr", + "fd", + "name", + "age", + "idle", + "flags", + "db", + "sub", + "psub", + "multi", + "qbuf", + "qbuf-free", + "obl", + "oll", + "omem", + "events", + "cmd" + ] + + clients = r.client(:list).first + clients.each do |client| + keys.each do |k| + msg = "expected #client(:list) to include #{k}" + assert client.keys.include?(k), msg + end + end + end + + def test_client_kill + return if version < "2.6.9" + + r.client(:setname, 'redis-rb') + clients = r.client(:list).first + i = clients.index {|client| client['name'] == 'redis-rb'} + assert_equal ["OK"], r.client(:kill, clients[i]["addr"]) + + clients = r.client(:list).first + i = clients.index {|client| client['name'] == 'redis-rb'} + assert_equal nil, i + end + + def test_client_getname_and_setname + return if version < "2.6.9" + + assert_equal [nil], r.client(:getname) + + r.client(:setname, 'redis-rb') + names = r.client(:getname) + assert_equal ['redis-rb'], names + end end diff --git a/test/remote_server_control_commands_test.rb b/test/remote_server_control_commands_test.rb index 02bc08c4f..60c2c7259 100644 --- a/test/remote_server_control_commands_test.rb +++ b/test/remote_server_control_commands_test.rb @@ -114,4 +114,63 @@ def test_slowlog result = r.slowlog(:len) assert_equal result, 0 end + + def test_client + assert_equal r.instance_variable_get(:@client), r.client + end + + def test_client_list + return if version < "2.4.0" + + keys = [ + "addr", + "fd", + "name", + "age", + "idle", + "flags", + "db", + "sub", + "psub", + "multi", + "qbuf", + "qbuf-free", + "obl", + "oll", + "omem", + "events", + "cmd" + ] + + clients = r.client(:list) + clients.each do |client| + keys.each do |k| + msg = "expected #client(:list) to include #{k}" + assert client.keys.include?(k), msg + end + end + end + + def test_client_kill + return if version < "2.6.9" + + r.client(:setname, 'redis-rb') + clients = r.client(:list) + i = clients.index {|client| client['name'] == 'redis-rb'} + assert_equal "OK", r.client(:kill, clients[i]["addr"]) + + clients = r.client(:list) + i = clients.index {|client| client['name'] == 'redis-rb'} + assert_equal nil, i + end + + def test_client_getname_and_setname + return if version < "2.6.9" + + assert_equal nil, r.client(:getname) + + r.client(:setname, 'redis-rb') + name = r.client(:getname) + assert_equal 'redis-rb', name + end end From 895cc3211e335a8fd9ba9322cd311c09eea9621f Mon Sep 17 00:00:00 2001 From: Damian Janowski Date: Sat, 31 Oct 2015 15:50:45 -0700 Subject: [PATCH 02/34] Remove Redis.connect. --- CHANGELOG.md | 16 +++------------- lib/redis.rb | 11 ----------- 2 files changed, 3 insertions(+), 24 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6fa7d8dfd..1150ae960 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,16 +1,6 @@ -# 4.x (unreleased) - -## Planned breaking changes: -* `Redis#client` will no longer expose the underlying `Redis::Client`; - it has not yet been determined how 4.0 will expose the underlying - functionality, but we will make every attempt to provide a final minor - release of 3.x that provides the new interfaces in order to facilitate - a smooth transition. - -* Ruby 1.8.7 (and the 1.8 modes of JRuby and Rubinius) will no longer be - supported; 1.8.x entered end-of-life in June of 2012 and stopped receiving - security updates in June of 2013; continuing to support it would prevent - the use of newer features of Ruby. +# 4.0 (unreleased) + +* Removed `Redis.connect`. Use `Redis.new`. # 3.2.1 diff --git a/lib/redis.rb b/lib/redis.rb index 9199c87db..487581bff 100644 --- a/lib/redis.rb +++ b/lib/redis.rb @@ -3,19 +3,8 @@ class Redis - def self.deprecate(message, trace = caller[0]) - $stderr.puts "\n#{message} (in #{trace})" - end - attr :client - # @deprecated The preferred way to create a new client object is using `#new`. - # This method does not actually establish a connection to Redis, - # in contrary to what you might expect. - def self.connect(options = {}) - new(options) - end - def self.current @current ||= Redis.new end From c61ad43e10d2f39c717bfcf94f3b65abeb34f877 Mon Sep 17 00:00:00 2001 From: Damian Janowski Date: Sat, 31 Oct 2015 16:01:29 -0700 Subject: [PATCH 03/34] Remove Redis#[] and Redis#[]=. --- CHANGELOG.md | 2 ++ lib/redis.rb | 4 ---- test/lint/strings.rb | 12 ------------ 3 files changed, 2 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1150ae960..e3f450b4e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ * Removed `Redis.connect`. Use `Redis.new`. +* Removed `Redis#[]` and `Redis#[]=` aliases. + # 3.2.1 * Added support for `PUBSUB` command. diff --git a/lib/redis.rb b/lib/redis.rb index 487581bff..797eaea5f 100644 --- a/lib/redis.rb +++ b/lib/redis.rb @@ -672,8 +672,6 @@ def set(key, value, options = {}) end end - alias :[]= :set - # Set the time to live in seconds of a key. # # @param [String] key @@ -779,8 +777,6 @@ def get(key) end end - alias :[] :get - # Get the values of all the given keys. # # @example diff --git a/test/lint/strings.rb b/test/lint/strings.rb index 381df3cdc..b8e4c84bc 100644 --- a/test/lint/strings.rb +++ b/test/lint/strings.rb @@ -8,18 +8,6 @@ def test_set_and_get assert_equal "s1", r.get("foo") end - def test_set_and_get_with_brackets - r["foo"] = "s1" - - assert_equal "s1", r["foo"] - end - - def test_set_and_get_with_brackets_and_symbol - r[:foo] = "s1" - - assert_equal "s1", r[:foo] - end - def test_set_and_get_with_newline_characters r.set("foo", "1\n") From 5fd26308d6d70e314e9a4c3a2ef4b5c5578cb012 Mon Sep 17 00:00:00 2001 From: Damian Janowski Date: Sat, 31 Oct 2015 15:52:29 -0700 Subject: [PATCH 04/34] Remove 1.8-ism. --- test/fork_safety_test.rb | 1 - test/helper.rb | 13 ------------- 2 files changed, 14 deletions(-) diff --git a/test/fork_safety_test.rb b/test/fork_safety_test.rb index a49d5b46d..e82b70589 100644 --- a/test/fork_safety_test.rb +++ b/test/fork_safety_test.rb @@ -5,7 +5,6 @@ class TestForkSafety < Test::Unit::TestCase include Helper::Client - include Helper::Skipable driver(:ruby, :hiredis) do def test_fork_safety diff --git a/test/helper.rb b/test/helper.rb index 169440728..c281c7625 100644 --- a/test/helper.rb +++ b/test/helper.rb @@ -216,17 +216,4 @@ def _new_client(options = {}) Redis::Distributed.new(NODES, _format_options(options).merge(:driver => ENV["conn"])) end end - - # Basic support for `skip` in 1.8.x - # Note: YOU MUST use `return skip(message)` in order to appropriately bail - # from a running test. - module Skipable - Skipped = Class.new(RuntimeError) - - def skip(message = nil, bt = caller) - return super if defined?(super) - - $stderr.puts("SKIPPED: #{self} #{message || 'no reason given'}") - end - end end From 0e1574f8c632f6eec95d936c55c4e65b95d9fd1f Mon Sep 17 00:00:00 2001 From: Damian Janowski Date: Sat, 31 Oct 2015 16:07:09 -0700 Subject: [PATCH 05/34] Remove checks for Encoding. --- lib/redis/connection/command_helper.rb | 10 ++-------- test/commands_on_strings_test.rb | 2 +- test/encoding_test.rb | 8 +++----- test/helper.rb | 8 -------- test/lint/strings.rb | 14 ++++++-------- 5 files changed, 12 insertions(+), 30 deletions(-) diff --git a/lib/redis/connection/command_helper.rb b/lib/redis/connection/command_helper.rb index 74e89dc10..b1c2d0fd9 100644 --- a/lib/redis/connection/command_helper.rb +++ b/lib/redis/connection/command_helper.rb @@ -30,14 +30,8 @@ def build_command(args) protected - if defined?(Encoding::default_external) - def encode(string) - string.force_encoding(Encoding::default_external) - end - else - def encode(string) - string - end + def encode(string) + string.force_encoding(Encoding.default_external) end end end diff --git a/test/commands_on_strings_test.rb b/test/commands_on_strings_test.rb index 9172aaccd..78fd1ad0b 100644 --- a/test/commands_on_strings_test.rb +++ b/test/commands_on_strings_test.rb @@ -82,7 +82,7 @@ def test_msetnx_mapped end def test_bitop - try_encoding("UTF-8") do + with_external_encoding("UTF-8") do target_version "2.5.10" do r.set("foo", "a") r.set("bar", "b") diff --git a/test/encoding_test.rb b/test/encoding_test.rb index cb54bcb2a..f6bfbff3b 100644 --- a/test/encoding_test.rb +++ b/test/encoding_test.rb @@ -7,12 +7,10 @@ class TestEncoding < Test::Unit::TestCase include Helper::Client def test_returns_properly_encoded_strings - if defined?(Encoding) - with_external_encoding("UTF-8") do - r.set "foo", "שלום" + with_external_encoding("UTF-8") do + r.set "foo", "שלום" - assert_equal "Shalom שלום", "Shalom " + r.get("foo") - end + assert_equal "Shalom שלום", "Shalom " + r.get("foo") end end end diff --git a/test/helper.rb b/test/helper.rb index c281c7625..b93d2c4af 100644 --- a/test/helper.rb +++ b/test/helper.rb @@ -92,14 +92,6 @@ def with_external_encoding(encoding) end end - def try_encoding(encoding, &block) - if defined?(Encoding) - with_external_encoding(encoding, &block) - else - yield - end - end - class Version include Comparable diff --git a/test/lint/strings.rb b/test/lint/strings.rb index b8e4c84bc..e17eaf7fb 100644 --- a/test/lint/strings.rb +++ b/test/lint/strings.rb @@ -23,14 +23,12 @@ def test_set_and_get_with_non_string_value end def test_set_and_get_with_ascii_characters - if defined?(Encoding) - with_external_encoding("ASCII-8BIT") do - (0..255).each do |i| - str = "#{i.chr}---#{i.chr}" - r.set("foo", str) - - assert_equal str, r.get("foo") - end + with_external_encoding("ASCII-8BIT") do + (0..255).each do |i| + str = "#{i.chr}---#{i.chr}" + r.set("foo", str) + + assert_equal str, r.get("foo") end end end From 9d7944e4d48dbf5d7739e009b5f0c6000faa9263 Mon Sep 17 00:00:00 2001 From: Damian Janowski Date: Sat, 31 Oct 2015 16:09:14 -0700 Subject: [PATCH 06/34] Remove encoding mark. --- Gemfile | 1 - redis.gemspec | 2 -- test/bitpos_test.rb | 2 -- test/blocking_commands_test.rb | 2 -- test/command_map_test.rb | 2 -- test/commands_on_hashes_test.rb | 2 -- test/commands_on_hyper_log_log_test.rb | 4 +--- test/commands_on_lists_test.rb | 2 -- test/commands_on_sets_test.rb | 2 -- test/commands_on_sorted_sets_test.rb | 2 -- test/commands_on_strings_test.rb | 2 -- test/commands_on_value_types_test.rb | 2 -- test/connection_handling_test.rb | 2 -- test/distributed_blocking_commands_test.rb | 2 -- test/distributed_commands_on_hashes_test.rb | 2 -- test/distributed_commands_on_hyper_log_log_test.rb | 2 -- test/distributed_commands_on_lists_test.rb | 2 -- test/distributed_commands_on_sets_test.rb | 2 -- test/distributed_commands_on_sorted_sets_test.rb | 2 -- test/distributed_commands_on_strings_test.rb | 2 -- test/distributed_commands_on_value_types_test.rb | 2 -- test/distributed_commands_requiring_clustering_test.rb | 2 -- test/distributed_connection_handling_test.rb | 2 -- test/distributed_internals_test.rb | 2 -- test/distributed_key_tags_test.rb | 2 -- test/distributed_persistence_control_commands_test.rb | 2 -- test/distributed_publish_subscribe_test.rb | 2 -- test/distributed_remote_server_control_commands_test.rb | 2 -- test/distributed_scripting_test.rb | 2 -- test/distributed_sorting_test.rb | 2 -- test/distributed_test.rb | 2 -- test/distributed_transactions_test.rb | 2 -- test/encoding_test.rb | 2 -- test/error_replies_test.rb | 2 -- test/fork_safety_test.rb | 2 -- test/helper_test.rb | 2 -- test/internals_test.rb | 2 -- test/persistence_control_commands_test.rb | 2 -- test/pipelining_commands_test.rb | 2 -- test/publish_subscribe_test.rb | 2 -- test/remote_server_control_commands_test.rb | 2 -- test/scanning_test.rb | 2 -- test/scripting_test.rb | 2 -- test/sentinel_test.rb | 2 -- test/sorting_test.rb | 2 -- test/synchrony_driver.rb | 2 -- test/thread_safety_test.rb | 2 -- test/transactions_test.rb | 2 -- test/unknown_commands_test.rb | 2 -- test/url_param_test.rb | 2 -- 50 files changed, 1 insertion(+), 100 deletions(-) diff --git a/Gemfile b/Gemfile index 73d38bc2e..fa75df156 100644 --- a/Gemfile +++ b/Gemfile @@ -1,4 +1,3 @@ -# encoding: utf-8 source 'https://rubygems.org' gemspec diff --git a/redis.gemspec b/redis.gemspec index 48930251c..33ff33a3c 100644 --- a/redis.gemspec +++ b/redis.gemspec @@ -1,5 +1,3 @@ -# -*- encoding: utf-8 -*- - $:.unshift File.expand_path("../lib", __FILE__) require "redis/version" diff --git a/test/bitpos_test.rb b/test/bitpos_test.rb index 118294da7..11f76437f 100644 --- a/test/bitpos_test.rb +++ b/test/bitpos_test.rb @@ -1,5 +1,3 @@ -# encoding: UTF-8 - require File.expand_path("helper", File.dirname(__FILE__)) unless defined?(Enumerator) diff --git a/test/blocking_commands_test.rb b/test/blocking_commands_test.rb index 4a2a9652d..7d58318fe 100644 --- a/test/blocking_commands_test.rb +++ b/test/blocking_commands_test.rb @@ -1,5 +1,3 @@ -# encoding: UTF-8 - require File.expand_path("helper", File.dirname(__FILE__)) require "lint/blocking_commands" diff --git a/test/command_map_test.rb b/test/command_map_test.rb index cb401db36..94b53f970 100644 --- a/test/command_map_test.rb +++ b/test/command_map_test.rb @@ -1,5 +1,3 @@ -# encoding: UTF-8 - require File.expand_path("helper", File.dirname(__FILE__)) class TestCommandMap < Test::Unit::TestCase diff --git a/test/commands_on_hashes_test.rb b/test/commands_on_hashes_test.rb index f3bbfa5b3..e022a098b 100644 --- a/test/commands_on_hashes_test.rb +++ b/test/commands_on_hashes_test.rb @@ -1,5 +1,3 @@ -# encoding: UTF-8 - require File.expand_path("helper", File.dirname(__FILE__)) require "lint/hashes" diff --git a/test/commands_on_hyper_log_log_test.rb b/test/commands_on_hyper_log_log_test.rb index a2fc95be1..b19366af6 100644 --- a/test/commands_on_hyper_log_log_test.rb +++ b/test/commands_on_hyper_log_log_test.rb @@ -1,5 +1,3 @@ -# encoding: UTF-8 - require File.expand_path("helper", File.dirname(__FILE__)) require "lint/hyper_log_log" @@ -18,4 +16,4 @@ def test_pfmerge end end -end \ No newline at end of file +end diff --git a/test/commands_on_lists_test.rb b/test/commands_on_lists_test.rb index 2916c2854..14893b021 100644 --- a/test/commands_on_lists_test.rb +++ b/test/commands_on_lists_test.rb @@ -1,5 +1,3 @@ -# encoding: UTF-8 - require File.expand_path("helper", File.dirname(__FILE__)) require "lint/lists" diff --git a/test/commands_on_sets_test.rb b/test/commands_on_sets_test.rb index 7ac2f4e03..58a37bcf9 100644 --- a/test/commands_on_sets_test.rb +++ b/test/commands_on_sets_test.rb @@ -1,5 +1,3 @@ -# encoding: UTF-8 - require File.expand_path("helper", File.dirname(__FILE__)) require "lint/sets" diff --git a/test/commands_on_sorted_sets_test.rb b/test/commands_on_sorted_sets_test.rb index 0a424be50..5e17a3fcc 100644 --- a/test/commands_on_sorted_sets_test.rb +++ b/test/commands_on_sorted_sets_test.rb @@ -1,5 +1,3 @@ -# encoding: UTF-8 - require File.expand_path("helper", File.dirname(__FILE__)) require "lint/sorted_sets" diff --git a/test/commands_on_strings_test.rb b/test/commands_on_strings_test.rb index 78fd1ad0b..1465f2d1b 100644 --- a/test/commands_on_strings_test.rb +++ b/test/commands_on_strings_test.rb @@ -1,5 +1,3 @@ -# encoding: UTF-8 - require File.expand_path("helper", File.dirname(__FILE__)) require "lint/strings" diff --git a/test/commands_on_value_types_test.rb b/test/commands_on_value_types_test.rb index 6b2f211ca..6fcf2c4b3 100644 --- a/test/commands_on_value_types_test.rb +++ b/test/commands_on_value_types_test.rb @@ -1,5 +1,3 @@ -# encoding: UTF-8 - require File.expand_path("helper", File.dirname(__FILE__)) require "lint/value_types" diff --git a/test/connection_handling_test.rb b/test/connection_handling_test.rb index cbffa617d..08c8417ce 100644 --- a/test/connection_handling_test.rb +++ b/test/connection_handling_test.rb @@ -1,5 +1,3 @@ -# encoding: UTF-8 - require File.expand_path("helper", File.dirname(__FILE__)) class TestConnectionHandling < Test::Unit::TestCase diff --git a/test/distributed_blocking_commands_test.rb b/test/distributed_blocking_commands_test.rb index b28cf2743..ca9361ac4 100644 --- a/test/distributed_blocking_commands_test.rb +++ b/test/distributed_blocking_commands_test.rb @@ -1,5 +1,3 @@ -# encoding: UTF-8 - require File.expand_path("helper", File.dirname(__FILE__)) require "lint/blocking_commands" diff --git a/test/distributed_commands_on_hashes_test.rb b/test/distributed_commands_on_hashes_test.rb index ffd14f519..b8fe0a3c7 100644 --- a/test/distributed_commands_on_hashes_test.rb +++ b/test/distributed_commands_on_hashes_test.rb @@ -1,5 +1,3 @@ -# encoding: UTF-8 - require File.expand_path("helper", File.dirname(__FILE__)) require "lint/hashes" diff --git a/test/distributed_commands_on_hyper_log_log_test.rb b/test/distributed_commands_on_hyper_log_log_test.rb index c118b9574..f14bfe650 100644 --- a/test/distributed_commands_on_hyper_log_log_test.rb +++ b/test/distributed_commands_on_hyper_log_log_test.rb @@ -1,5 +1,3 @@ -# encoding: UTF-8 - require File.expand_path("helper", File.dirname(__FILE__)) require "lint/hyper_log_log" diff --git a/test/distributed_commands_on_lists_test.rb b/test/distributed_commands_on_lists_test.rb index d22f3be80..d2487956d 100644 --- a/test/distributed_commands_on_lists_test.rb +++ b/test/distributed_commands_on_lists_test.rb @@ -1,5 +1,3 @@ -# encoding: UTF-8 - require File.expand_path("helper", File.dirname(__FILE__)) require "lint/lists" diff --git a/test/distributed_commands_on_sets_test.rb b/test/distributed_commands_on_sets_test.rb index 43a070c8c..93a87d740 100644 --- a/test/distributed_commands_on_sets_test.rb +++ b/test/distributed_commands_on_sets_test.rb @@ -1,5 +1,3 @@ -# encoding: UTF-8 - require File.expand_path("helper", File.dirname(__FILE__)) require "lint/sets" diff --git a/test/distributed_commands_on_sorted_sets_test.rb b/test/distributed_commands_on_sorted_sets_test.rb index a4150b834..6bc18ec2d 100644 --- a/test/distributed_commands_on_sorted_sets_test.rb +++ b/test/distributed_commands_on_sorted_sets_test.rb @@ -1,5 +1,3 @@ -# encoding: UTF-8 - require File.expand_path("helper", File.dirname(__FILE__)) require "lint/sorted_sets" diff --git a/test/distributed_commands_on_strings_test.rb b/test/distributed_commands_on_strings_test.rb index ad83c12e5..50295fc60 100644 --- a/test/distributed_commands_on_strings_test.rb +++ b/test/distributed_commands_on_strings_test.rb @@ -1,5 +1,3 @@ -# encoding: UTF-8 - require File.expand_path("helper", File.dirname(__FILE__)) require "lint/strings" diff --git a/test/distributed_commands_on_value_types_test.rb b/test/distributed_commands_on_value_types_test.rb index 0be9ce298..05feef41f 100644 --- a/test/distributed_commands_on_value_types_test.rb +++ b/test/distributed_commands_on_value_types_test.rb @@ -1,5 +1,3 @@ -# encoding: UTF-8 - require File.expand_path("helper", File.dirname(__FILE__)) require "lint/value_types" diff --git a/test/distributed_commands_requiring_clustering_test.rb b/test/distributed_commands_requiring_clustering_test.rb index da8063c56..c9c051e19 100644 --- a/test/distributed_commands_requiring_clustering_test.rb +++ b/test/distributed_commands_requiring_clustering_test.rb @@ -1,5 +1,3 @@ -# encoding: UTF-8 - require File.expand_path("helper", File.dirname(__FILE__)) class TestDistributedCommandsRequiringClustering < Test::Unit::TestCase diff --git a/test/distributed_connection_handling_test.rb b/test/distributed_connection_handling_test.rb index 330886090..33a14020c 100644 --- a/test/distributed_connection_handling_test.rb +++ b/test/distributed_connection_handling_test.rb @@ -1,5 +1,3 @@ -# encoding: UTF-8 - require File.expand_path("helper", File.dirname(__FILE__)) class TestDistributedConnectionHandling < Test::Unit::TestCase diff --git a/test/distributed_internals_test.rb b/test/distributed_internals_test.rb index d2c421bdb..c94ecd243 100644 --- a/test/distributed_internals_test.rb +++ b/test/distributed_internals_test.rb @@ -1,5 +1,3 @@ -# encoding: UTF-8 - require File.expand_path("helper", File.dirname(__FILE__)) class TestDistributedInternals < Test::Unit::TestCase diff --git a/test/distributed_key_tags_test.rb b/test/distributed_key_tags_test.rb index 5378ceaec..ee4e788c4 100644 --- a/test/distributed_key_tags_test.rb +++ b/test/distributed_key_tags_test.rb @@ -1,5 +1,3 @@ -# encoding: UTF-8 - require File.expand_path("helper", File.dirname(__FILE__)) class TestDistributedKeyTags < Test::Unit::TestCase diff --git a/test/distributed_persistence_control_commands_test.rb b/test/distributed_persistence_control_commands_test.rb index c24360192..029eb83c2 100644 --- a/test/distributed_persistence_control_commands_test.rb +++ b/test/distributed_persistence_control_commands_test.rb @@ -1,5 +1,3 @@ -# encoding: UTF-8 - require File.expand_path("helper", File.dirname(__FILE__)) class TestDistributedPersistenceControlCommands < Test::Unit::TestCase diff --git a/test/distributed_publish_subscribe_test.rb b/test/distributed_publish_subscribe_test.rb index df36506d9..c6661e2eb 100644 --- a/test/distributed_publish_subscribe_test.rb +++ b/test/distributed_publish_subscribe_test.rb @@ -1,5 +1,3 @@ -# encoding: UTF-8 - require File.expand_path("helper", File.dirname(__FILE__)) class TestDistributedPublishSubscribe < Test::Unit::TestCase diff --git a/test/distributed_remote_server_control_commands_test.rb b/test/distributed_remote_server_control_commands_test.rb index 7799d4fce..66e6f384a 100644 --- a/test/distributed_remote_server_control_commands_test.rb +++ b/test/distributed_remote_server_control_commands_test.rb @@ -1,5 +1,3 @@ -# encoding: UTF-8 - require File.expand_path("helper", File.dirname(__FILE__)) class TestDistributedRemoteServerControlCommands < Test::Unit::TestCase diff --git a/test/distributed_scripting_test.rb b/test/distributed_scripting_test.rb index 00bdaa622..3f80727ab 100644 --- a/test/distributed_scripting_test.rb +++ b/test/distributed_scripting_test.rb @@ -1,5 +1,3 @@ -# encoding: UTF-8 - require File.expand_path("helper", File.dirname(__FILE__)) class TestDistributedScripting < Test::Unit::TestCase diff --git a/test/distributed_sorting_test.rb b/test/distributed_sorting_test.rb index 4ae3cf575..2da692feb 100644 --- a/test/distributed_sorting_test.rb +++ b/test/distributed_sorting_test.rb @@ -1,5 +1,3 @@ -# encoding: UTF-8 - require File.expand_path("helper", File.dirname(__FILE__)) class TestDistributedSorting < Test::Unit::TestCase diff --git a/test/distributed_test.rb b/test/distributed_test.rb index da7b653ce..9ecf84128 100644 --- a/test/distributed_test.rb +++ b/test/distributed_test.rb @@ -1,5 +1,3 @@ -# encoding: UTF-8 - require File.expand_path("helper", File.dirname(__FILE__)) class TestDistributed < Test::Unit::TestCase diff --git a/test/distributed_transactions_test.rb b/test/distributed_transactions_test.rb index abfb8aa3c..19a90c951 100644 --- a/test/distributed_transactions_test.rb +++ b/test/distributed_transactions_test.rb @@ -1,5 +1,3 @@ -# encoding: UTF-8 - require File.expand_path("helper", File.dirname(__FILE__)) class TestDistributedTransactions < Test::Unit::TestCase diff --git a/test/encoding_test.rb b/test/encoding_test.rb index f6bfbff3b..bcec42b63 100644 --- a/test/encoding_test.rb +++ b/test/encoding_test.rb @@ -1,5 +1,3 @@ -# encoding: UTF-8 - require File.expand_path("helper", File.dirname(__FILE__)) class TestEncoding < Test::Unit::TestCase diff --git a/test/error_replies_test.rb b/test/error_replies_test.rb index 08ec81e15..8ffb7dec7 100644 --- a/test/error_replies_test.rb +++ b/test/error_replies_test.rb @@ -1,5 +1,3 @@ -# encoding: UTF-8 - require File.expand_path("helper", File.dirname(__FILE__)) class TestErrorReplies < Test::Unit::TestCase diff --git a/test/fork_safety_test.rb b/test/fork_safety_test.rb index e82b70589..c9e73708a 100644 --- a/test/fork_safety_test.rb +++ b/test/fork_safety_test.rb @@ -1,5 +1,3 @@ -# encoding: UTF-8 - require File.expand_path("helper", File.dirname(__FILE__)) class TestForkSafety < Test::Unit::TestCase diff --git a/test/helper_test.rb b/test/helper_test.rb index 23da68dce..83df2b8a9 100644 --- a/test/helper_test.rb +++ b/test/helper_test.rb @@ -1,5 +1,3 @@ -# encoding: UTF-8 - require File.expand_path("helper", File.dirname(__FILE__)) class TestHelper < Test::Unit::TestCase diff --git a/test/internals_test.rb b/test/internals_test.rb index 865c60020..055975677 100644 --- a/test/internals_test.rb +++ b/test/internals_test.rb @@ -1,5 +1,3 @@ -# encoding: UTF-8 - require File.expand_path("helper", File.dirname(__FILE__)) class TestInternals < Test::Unit::TestCase diff --git a/test/persistence_control_commands_test.rb b/test/persistence_control_commands_test.rb index 281657152..66292a41e 100644 --- a/test/persistence_control_commands_test.rb +++ b/test/persistence_control_commands_test.rb @@ -1,5 +1,3 @@ -# encoding: UTF-8 - require File.expand_path("helper", File.dirname(__FILE__)) class TestPersistenceControlCommands < Test::Unit::TestCase diff --git a/test/pipelining_commands_test.rb b/test/pipelining_commands_test.rb index 82cd92f80..898e77fe2 100644 --- a/test/pipelining_commands_test.rb +++ b/test/pipelining_commands_test.rb @@ -1,5 +1,3 @@ -# encoding: UTF-8 - require File.expand_path("helper", File.dirname(__FILE__)) class TestPipeliningCommands < Test::Unit::TestCase diff --git a/test/publish_subscribe_test.rb b/test/publish_subscribe_test.rb index b111c4fa8..ecc83d2a4 100644 --- a/test/publish_subscribe_test.rb +++ b/test/publish_subscribe_test.rb @@ -1,5 +1,3 @@ -# encoding: UTF-8 - require File.expand_path("helper", File.dirname(__FILE__)) class TestPublishSubscribe < Test::Unit::TestCase diff --git a/test/remote_server_control_commands_test.rb b/test/remote_server_control_commands_test.rb index b5cbd452e..a318a786a 100644 --- a/test/remote_server_control_commands_test.rb +++ b/test/remote_server_control_commands_test.rb @@ -1,5 +1,3 @@ -# encoding: UTF-8 - require File.expand_path("helper", File.dirname(__FILE__)) class TestRemoteServerControlCommands < Test::Unit::TestCase diff --git a/test/scanning_test.rb b/test/scanning_test.rb index 9a4cf7dbf..6d602f731 100644 --- a/test/scanning_test.rb +++ b/test/scanning_test.rb @@ -1,5 +1,3 @@ -# encoding: UTF-8 - require File.expand_path("helper", File.dirname(__FILE__)) unless defined?(Enumerator) diff --git a/test/scripting_test.rb b/test/scripting_test.rb index 82d0d89e2..851fa9169 100644 --- a/test/scripting_test.rb +++ b/test/scripting_test.rb @@ -1,5 +1,3 @@ -# encoding: UTF-8 - require File.expand_path("helper", File.dirname(__FILE__)) class TestScripting < Test::Unit::TestCase diff --git a/test/sentinel_test.rb b/test/sentinel_test.rb index bd66aa3b9..ee3a8483e 100644 --- a/test/sentinel_test.rb +++ b/test/sentinel_test.rb @@ -1,5 +1,3 @@ -# encoding: UTF-8 - require File.expand_path("helper", File.dirname(__FILE__)) class SentinalTest < Test::Unit::TestCase diff --git a/test/sorting_test.rb b/test/sorting_test.rb index e8aec56a9..b25b1f3da 100644 --- a/test/sorting_test.rb +++ b/test/sorting_test.rb @@ -1,5 +1,3 @@ -# encoding: UTF-8 - require File.expand_path("helper", File.dirname(__FILE__)) class TestSorting < Test::Unit::TestCase diff --git a/test/synchrony_driver.rb b/test/synchrony_driver.rb index 82b13a794..0078ccd82 100644 --- a/test/synchrony_driver.rb +++ b/test/synchrony_driver.rb @@ -1,5 +1,3 @@ -# encoding: UTF-8 - require 'em-synchrony' require 'em-synchrony/connection_pool' diff --git a/test/thread_safety_test.rb b/test/thread_safety_test.rb index 817f82386..37b670211 100644 --- a/test/thread_safety_test.rb +++ b/test/thread_safety_test.rb @@ -1,5 +1,3 @@ -# encoding: UTF-8 - require File.expand_path("helper", File.dirname(__FILE__)) class TestThreadSafety < Test::Unit::TestCase diff --git a/test/transactions_test.rb b/test/transactions_test.rb index 3f588b29f..ee2174905 100644 --- a/test/transactions_test.rb +++ b/test/transactions_test.rb @@ -1,5 +1,3 @@ -# encoding: UTF-8 - require File.expand_path("helper", File.dirname(__FILE__)) class TestTransactions < Test::Unit::TestCase diff --git a/test/unknown_commands_test.rb b/test/unknown_commands_test.rb index 0d1ca5827..c153fde4d 100644 --- a/test/unknown_commands_test.rb +++ b/test/unknown_commands_test.rb @@ -1,5 +1,3 @@ -# encoding: UTF-8 - require File.expand_path("helper", File.dirname(__FILE__)) class TestUnknownCommands < Test::Unit::TestCase diff --git a/test/url_param_test.rb b/test/url_param_test.rb index 468bbf1f7..ce0af2326 100644 --- a/test/url_param_test.rb +++ b/test/url_param_test.rb @@ -1,5 +1,3 @@ -# encoding: UTF-8 - require File.expand_path("helper", File.dirname(__FILE__)) class TestUrlParam < Test::Unit::TestCase From f3bc68f4305792a14c86556832627e13c9bbd6b0 Mon Sep 17 00:00:00 2001 From: Damian Janowski Date: Sat, 31 Oct 2015 16:28:37 -0700 Subject: [PATCH 07/34] Use require_relative. --- lib/redis.rb | 12 ++++++------ lib/redis/client.rb | 15 ++++++++++----- lib/redis/connection.rb | 4 ++-- lib/redis/connection/ruby.rb | 6 +++--- lib/redis/distributed.rb | 2 +- redis.gemspec | 4 +--- test/bitpos_test.rb | 2 +- test/blocking_commands_test.rb | 4 ++-- test/command_map_test.rb | 2 +- test/commands_on_hashes_test.rb | 4 ++-- test/commands_on_hyper_log_log_test.rb | 4 ++-- test/commands_on_lists_test.rb | 4 ++-- test/commands_on_sets_test.rb | 4 ++-- test/commands_on_sorted_sets_test.rb | 4 ++-- test/commands_on_strings_test.rb | 4 ++-- test/commands_on_value_types_test.rb | 4 ++-- test/connection_handling_test.rb | 2 +- test/distributed_blocking_commands_test.rb | 4 ++-- test/distributed_commands_on_hashes_test.rb | 4 ++-- .../distributed_commands_on_hyper_log_log_test.rb | 4 ++-- test/distributed_commands_on_lists_test.rb | 4 ++-- test/distributed_commands_on_sets_test.rb | 4 ++-- test/distributed_commands_on_sorted_sets_test.rb | 4 ++-- test/distributed_commands_on_strings_test.rb | 4 ++-- test/distributed_commands_on_value_types_test.rb | 4 ++-- ...tributed_commands_requiring_clustering_test.rb | 2 +- test/distributed_connection_handling_test.rb | 2 +- test/distributed_internals_test.rb | 2 +- test/distributed_key_tags_test.rb | 2 +- ...stributed_persistence_control_commands_test.rb | 2 +- test/distributed_publish_subscribe_test.rb | 2 +- ...ributed_remote_server_control_commands_test.rb | 2 +- test/distributed_scripting_test.rb | 2 +- test/distributed_sorting_test.rb | 2 +- test/distributed_test.rb | 2 +- test/distributed_transactions_test.rb | 2 +- test/encoding_test.rb | 2 +- test/error_replies_test.rb | 2 +- test/fork_safety_test.rb | 2 +- test/helper.rb | 13 +++++-------- test/helper_test.rb | 2 +- test/internals_test.rb | 2 +- test/persistence_control_commands_test.rb | 2 +- test/pipelining_commands_test.rb | 2 +- test/publish_subscribe_test.rb | 2 +- test/remote_server_control_commands_test.rb | 2 +- test/scanning_test.rb | 2 +- test/scripting_test.rb | 2 +- test/sentinel_test.rb | 2 +- test/sorting_test.rb | 2 +- test/support/connection/ruby.rb | 2 +- test/synchrony_driver.rb | 2 +- test/thread_safety_test.rb | 2 +- test/transactions_test.rb | 2 +- test/unknown_commands_test.rb | 2 +- test/url_param_test.rb | 2 +- 56 files changed, 93 insertions(+), 93 deletions(-) diff --git a/lib/redis.rb b/lib/redis.rb index 797eaea5f..c9a8ca6ae 100644 --- a/lib/redis.rb +++ b/lib/redis.rb @@ -1,5 +1,5 @@ require "monitor" -require "redis/errors" +require_relative "redis/errors" class Redis @@ -2612,8 +2612,8 @@ def _subscription(method, channels, block) end -require "redis/version" -require "redis/connection" -require "redis/client" -require "redis/pipeline" -require "redis/subscribe" +require_relative "redis/version" +require_relative "redis/connection" +require_relative "redis/client" +require_relative "redis/pipeline" +require_relative "redis/subscribe" diff --git a/lib/redis/client.rb b/lib/redis/client.rb index 26856a469..fff507807 100644 --- a/lib/redis/client.rb +++ b/lib/redis/client.rb @@ -1,4 +1,4 @@ -require "redis/errors" +require_relative "errors" require "socket" require "cgi" @@ -517,11 +517,16 @@ def _parse_driver(driver) if driver.kind_of?(String) begin - require "redis/connection/#{driver}" - driver = Connection.const_get(driver.capitalize) - rescue LoadError, NameError - raise RuntimeError, "Cannot load driver #{driver.inspect}" + require_relative "connection/#{driver}" + rescue LoadError, NameError => e + begin + require "connection/#{driver}" + rescue LoadError, NameError => e + raise RuntimeError, "Cannot load driver #{driver.inspect}: #{e.message}" + end end + + driver = Connection.const_get(driver.capitalize) end driver diff --git a/lib/redis/connection.rb b/lib/redis/connection.rb index badff22b9..d8a51b334 100644 --- a/lib/redis/connection.rb +++ b/lib/redis/connection.rb @@ -1,4 +1,4 @@ -require "redis/connection/registry" +require_relative "connection/registry" # If a connection driver was required before this file, the array # Redis::Connection.drivers will contain one or more classes. The last driver @@ -6,4 +6,4 @@ # the plain Ruby driver as our default. Another driver can be required at a # later point in time, causing it to be the last element of the #drivers array # and therefore be chosen by default. -require "redis/connection/ruby" if Redis::Connection.drivers.empty? \ No newline at end of file +require_relative "connection/ruby" if Redis::Connection.drivers.empty? diff --git a/lib/redis/connection/ruby.rb b/lib/redis/connection/ruby.rb index 61e4c8ab7..24740b844 100644 --- a/lib/redis/connection/ruby.rb +++ b/lib/redis/connection/ruby.rb @@ -1,6 +1,6 @@ -require "redis/connection/registry" -require "redis/connection/command_helper" -require "redis/errors" +require_relative "registry" +require_relative "command_helper" +require_relative "../errors" require "socket" class Redis diff --git a/lib/redis/distributed.rb b/lib/redis/distributed.rb index 4bda232a4..774c754b3 100644 --- a/lib/redis/distributed.rb +++ b/lib/redis/distributed.rb @@ -1,4 +1,4 @@ -require "redis/hash_ring" +require_relative "hash_ring" class Redis class Distributed diff --git a/redis.gemspec b/redis.gemspec index 33ff33a3c..88e634c15 100644 --- a/redis.gemspec +++ b/redis.gemspec @@ -1,6 +1,4 @@ -$:.unshift File.expand_path("../lib", __FILE__) - -require "redis/version" +require_relative "lib/redis/version" Gem::Specification.new do |s| s.name = "redis" diff --git a/test/bitpos_test.rb b/test/bitpos_test.rb index 11f76437f..76d56777a 100644 --- a/test/bitpos_test.rb +++ b/test/bitpos_test.rb @@ -1,4 +1,4 @@ -require File.expand_path("helper", File.dirname(__FILE__)) +require_relative "helper" unless defined?(Enumerator) Enumerator = Enumerable::Enumerator diff --git a/test/blocking_commands_test.rb b/test/blocking_commands_test.rb index 7d58318fe..f5a944b5b 100644 --- a/test/blocking_commands_test.rb +++ b/test/blocking_commands_test.rb @@ -1,5 +1,5 @@ -require File.expand_path("helper", File.dirname(__FILE__)) -require "lint/blocking_commands" +require_relative "helper" +require_relative "lint/blocking_commands" class TestBlockingCommands < Test::Unit::TestCase diff --git a/test/command_map_test.rb b/test/command_map_test.rb index 94b53f970..a37250d17 100644 --- a/test/command_map_test.rb +++ b/test/command_map_test.rb @@ -1,4 +1,4 @@ -require File.expand_path("helper", File.dirname(__FILE__)) +require_relative "helper" class TestCommandMap < Test::Unit::TestCase diff --git a/test/commands_on_hashes_test.rb b/test/commands_on_hashes_test.rb index e022a098b..3e0f7ba4e 100644 --- a/test/commands_on_hashes_test.rb +++ b/test/commands_on_hashes_test.rb @@ -1,5 +1,5 @@ -require File.expand_path("helper", File.dirname(__FILE__)) -require "lint/hashes" +require_relative "helper" +require_relative "lint/hashes" class TestCommandsOnHashes < Test::Unit::TestCase diff --git a/test/commands_on_hyper_log_log_test.rb b/test/commands_on_hyper_log_log_test.rb index b19366af6..194e6d4c6 100644 --- a/test/commands_on_hyper_log_log_test.rb +++ b/test/commands_on_hyper_log_log_test.rb @@ -1,5 +1,5 @@ -require File.expand_path("helper", File.dirname(__FILE__)) -require "lint/hyper_log_log" +require_relative "helper" +require_relative "lint/hyper_log_log" class TestCommandsOnHyperLogLog < Test::Unit::TestCase diff --git a/test/commands_on_lists_test.rb b/test/commands_on_lists_test.rb index 14893b021..5f286706f 100644 --- a/test/commands_on_lists_test.rb +++ b/test/commands_on_lists_test.rb @@ -1,5 +1,5 @@ -require File.expand_path("helper", File.dirname(__FILE__)) -require "lint/lists" +require_relative "helper" +require_relative "lint/lists" class TestCommandsOnLists < Test::Unit::TestCase diff --git a/test/commands_on_sets_test.rb b/test/commands_on_sets_test.rb index 58a37bcf9..cd186cd34 100644 --- a/test/commands_on_sets_test.rb +++ b/test/commands_on_sets_test.rb @@ -1,5 +1,5 @@ -require File.expand_path("helper", File.dirname(__FILE__)) -require "lint/sets" +require_relative "helper" +require_relative "lint/sets" class TestCommandsOnSets < Test::Unit::TestCase diff --git a/test/commands_on_sorted_sets_test.rb b/test/commands_on_sorted_sets_test.rb index 5e17a3fcc..d10252902 100644 --- a/test/commands_on_sorted_sets_test.rb +++ b/test/commands_on_sorted_sets_test.rb @@ -1,5 +1,5 @@ -require File.expand_path("helper", File.dirname(__FILE__)) -require "lint/sorted_sets" +require_relative "helper" +require_relative "lint/sorted_sets" class TestCommandsOnSortedSets < Test::Unit::TestCase diff --git a/test/commands_on_strings_test.rb b/test/commands_on_strings_test.rb index 1465f2d1b..58fe7e510 100644 --- a/test/commands_on_strings_test.rb +++ b/test/commands_on_strings_test.rb @@ -1,5 +1,5 @@ -require File.expand_path("helper", File.dirname(__FILE__)) -require "lint/strings" +require_relative "helper" +require_relative "lint/strings" class TestCommandsOnStrings < Test::Unit::TestCase diff --git a/test/commands_on_value_types_test.rb b/test/commands_on_value_types_test.rb index 6fcf2c4b3..8eb32b56b 100644 --- a/test/commands_on_value_types_test.rb +++ b/test/commands_on_value_types_test.rb @@ -1,5 +1,5 @@ -require File.expand_path("helper", File.dirname(__FILE__)) -require "lint/value_types" +require_relative "helper" +require_relative "lint/value_types" class TestCommandsOnValueTypes < Test::Unit::TestCase diff --git a/test/connection_handling_test.rb b/test/connection_handling_test.rb index 08c8417ce..ebd7b7b95 100644 --- a/test/connection_handling_test.rb +++ b/test/connection_handling_test.rb @@ -1,4 +1,4 @@ -require File.expand_path("helper", File.dirname(__FILE__)) +require_relative "helper" class TestConnectionHandling < Test::Unit::TestCase diff --git a/test/distributed_blocking_commands_test.rb b/test/distributed_blocking_commands_test.rb index ca9361ac4..f03f45b09 100644 --- a/test/distributed_blocking_commands_test.rb +++ b/test/distributed_blocking_commands_test.rb @@ -1,5 +1,5 @@ -require File.expand_path("helper", File.dirname(__FILE__)) -require "lint/blocking_commands" +require_relative "helper" +require_relative "lint/blocking_commands" class TestDistributedBlockingCommands < Test::Unit::TestCase diff --git a/test/distributed_commands_on_hashes_test.rb b/test/distributed_commands_on_hashes_test.rb index b8fe0a3c7..732fef64c 100644 --- a/test/distributed_commands_on_hashes_test.rb +++ b/test/distributed_commands_on_hashes_test.rb @@ -1,5 +1,5 @@ -require File.expand_path("helper", File.dirname(__FILE__)) -require "lint/hashes" +require_relative "helper" +require_relative "lint/hashes" class TestDistributedCommandsOnHashes < Test::Unit::TestCase diff --git a/test/distributed_commands_on_hyper_log_log_test.rb b/test/distributed_commands_on_hyper_log_log_test.rb index f14bfe650..a6b7110f7 100644 --- a/test/distributed_commands_on_hyper_log_log_test.rb +++ b/test/distributed_commands_on_hyper_log_log_test.rb @@ -1,5 +1,5 @@ -require File.expand_path("helper", File.dirname(__FILE__)) -require "lint/hyper_log_log" +require_relative "helper" +require_relative "lint/hyper_log_log" class TestDistributedCommandsOnHyperLogLog < Test::Unit::TestCase diff --git a/test/distributed_commands_on_lists_test.rb b/test/distributed_commands_on_lists_test.rb index d2487956d..dd629bc2f 100644 --- a/test/distributed_commands_on_lists_test.rb +++ b/test/distributed_commands_on_lists_test.rb @@ -1,5 +1,5 @@ -require File.expand_path("helper", File.dirname(__FILE__)) -require "lint/lists" +require_relative "helper" +require_relative "lint/lists" class TestDistributedCommandsOnLists < Test::Unit::TestCase diff --git a/test/distributed_commands_on_sets_test.rb b/test/distributed_commands_on_sets_test.rb index 93a87d740..c7180e6ac 100644 --- a/test/distributed_commands_on_sets_test.rb +++ b/test/distributed_commands_on_sets_test.rb @@ -1,5 +1,5 @@ -require File.expand_path("helper", File.dirname(__FILE__)) -require "lint/sets" +require_relative "helper" +require_relative "lint/sets" class TestDistributedCommandsOnSets < Test::Unit::TestCase diff --git a/test/distributed_commands_on_sorted_sets_test.rb b/test/distributed_commands_on_sorted_sets_test.rb index 6bc18ec2d..ae23a6c83 100644 --- a/test/distributed_commands_on_sorted_sets_test.rb +++ b/test/distributed_commands_on_sorted_sets_test.rb @@ -1,5 +1,5 @@ -require File.expand_path("helper", File.dirname(__FILE__)) -require "lint/sorted_sets" +require_relative "helper" +require_relative "lint/sorted_sets" class TestDistributedCommandsOnSortedSets < Test::Unit::TestCase diff --git a/test/distributed_commands_on_strings_test.rb b/test/distributed_commands_on_strings_test.rb index 50295fc60..5b964684f 100644 --- a/test/distributed_commands_on_strings_test.rb +++ b/test/distributed_commands_on_strings_test.rb @@ -1,5 +1,5 @@ -require File.expand_path("helper", File.dirname(__FILE__)) -require "lint/strings" +require_relative "helper" +require_relative "lint/strings" class TestDistributedCommandsOnStrings < Test::Unit::TestCase diff --git a/test/distributed_commands_on_value_types_test.rb b/test/distributed_commands_on_value_types_test.rb index 05feef41f..b360dbe98 100644 --- a/test/distributed_commands_on_value_types_test.rb +++ b/test/distributed_commands_on_value_types_test.rb @@ -1,5 +1,5 @@ -require File.expand_path("helper", File.dirname(__FILE__)) -require "lint/value_types" +require_relative "helper" +require_relative "lint/value_types" class TestDistributedCommandsOnValueTypes < Test::Unit::TestCase diff --git a/test/distributed_commands_requiring_clustering_test.rb b/test/distributed_commands_requiring_clustering_test.rb index c9c051e19..dc5c6ed3f 100644 --- a/test/distributed_commands_requiring_clustering_test.rb +++ b/test/distributed_commands_requiring_clustering_test.rb @@ -1,4 +1,4 @@ -require File.expand_path("helper", File.dirname(__FILE__)) +require_relative "helper" class TestDistributedCommandsRequiringClustering < Test::Unit::TestCase diff --git a/test/distributed_connection_handling_test.rb b/test/distributed_connection_handling_test.rb index 33a14020c..335046abe 100644 --- a/test/distributed_connection_handling_test.rb +++ b/test/distributed_connection_handling_test.rb @@ -1,4 +1,4 @@ -require File.expand_path("helper", File.dirname(__FILE__)) +require_relative "helper" class TestDistributedConnectionHandling < Test::Unit::TestCase diff --git a/test/distributed_internals_test.rb b/test/distributed_internals_test.rb index c94ecd243..c755a8afd 100644 --- a/test/distributed_internals_test.rb +++ b/test/distributed_internals_test.rb @@ -1,4 +1,4 @@ -require File.expand_path("helper", File.dirname(__FILE__)) +require_relative "helper" class TestDistributedInternals < Test::Unit::TestCase diff --git a/test/distributed_key_tags_test.rb b/test/distributed_key_tags_test.rb index ee4e788c4..a778fec72 100644 --- a/test/distributed_key_tags_test.rb +++ b/test/distributed_key_tags_test.rb @@ -1,4 +1,4 @@ -require File.expand_path("helper", File.dirname(__FILE__)) +require_relative "helper" class TestDistributedKeyTags < Test::Unit::TestCase diff --git a/test/distributed_persistence_control_commands_test.rb b/test/distributed_persistence_control_commands_test.rb index 029eb83c2..2d844258a 100644 --- a/test/distributed_persistence_control_commands_test.rb +++ b/test/distributed_persistence_control_commands_test.rb @@ -1,4 +1,4 @@ -require File.expand_path("helper", File.dirname(__FILE__)) +require_relative "helper" class TestDistributedPersistenceControlCommands < Test::Unit::TestCase diff --git a/test/distributed_publish_subscribe_test.rb b/test/distributed_publish_subscribe_test.rb index c6661e2eb..a5fcfa53f 100644 --- a/test/distributed_publish_subscribe_test.rb +++ b/test/distributed_publish_subscribe_test.rb @@ -1,4 +1,4 @@ -require File.expand_path("helper", File.dirname(__FILE__)) +require_relative "helper" class TestDistributedPublishSubscribe < Test::Unit::TestCase diff --git a/test/distributed_remote_server_control_commands_test.rb b/test/distributed_remote_server_control_commands_test.rb index 66e6f384a..66ec349f8 100644 --- a/test/distributed_remote_server_control_commands_test.rb +++ b/test/distributed_remote_server_control_commands_test.rb @@ -1,4 +1,4 @@ -require File.expand_path("helper", File.dirname(__FILE__)) +require_relative "helper" class TestDistributedRemoteServerControlCommands < Test::Unit::TestCase diff --git a/test/distributed_scripting_test.rb b/test/distributed_scripting_test.rb index 3f80727ab..224ab2b05 100644 --- a/test/distributed_scripting_test.rb +++ b/test/distributed_scripting_test.rb @@ -1,4 +1,4 @@ -require File.expand_path("helper", File.dirname(__FILE__)) +require_relative "helper" class TestDistributedScripting < Test::Unit::TestCase diff --git a/test/distributed_sorting_test.rb b/test/distributed_sorting_test.rb index 2da692feb..7afb670b9 100644 --- a/test/distributed_sorting_test.rb +++ b/test/distributed_sorting_test.rb @@ -1,4 +1,4 @@ -require File.expand_path("helper", File.dirname(__FILE__)) +require_relative "helper" class TestDistributedSorting < Test::Unit::TestCase diff --git a/test/distributed_test.rb b/test/distributed_test.rb index 9ecf84128..14ff47022 100644 --- a/test/distributed_test.rb +++ b/test/distributed_test.rb @@ -1,4 +1,4 @@ -require File.expand_path("helper", File.dirname(__FILE__)) +require_relative "helper" class TestDistributed < Test::Unit::TestCase diff --git a/test/distributed_transactions_test.rb b/test/distributed_transactions_test.rb index 19a90c951..526e96d45 100644 --- a/test/distributed_transactions_test.rb +++ b/test/distributed_transactions_test.rb @@ -1,4 +1,4 @@ -require File.expand_path("helper", File.dirname(__FILE__)) +require_relative "helper" class TestDistributedTransactions < Test::Unit::TestCase diff --git a/test/encoding_test.rb b/test/encoding_test.rb index bcec42b63..195f1e8ad 100644 --- a/test/encoding_test.rb +++ b/test/encoding_test.rb @@ -1,4 +1,4 @@ -require File.expand_path("helper", File.dirname(__FILE__)) +require_relative "helper" class TestEncoding < Test::Unit::TestCase diff --git a/test/error_replies_test.rb b/test/error_replies_test.rb index 8ffb7dec7..de48b0686 100644 --- a/test/error_replies_test.rb +++ b/test/error_replies_test.rb @@ -1,4 +1,4 @@ -require File.expand_path("helper", File.dirname(__FILE__)) +require_relative "helper" class TestErrorReplies < Test::Unit::TestCase diff --git a/test/fork_safety_test.rb b/test/fork_safety_test.rb index c9e73708a..8c35658eb 100644 --- a/test/fork_safety_test.rb +++ b/test/fork_safety_test.rb @@ -1,4 +1,4 @@ -require File.expand_path("helper", File.dirname(__FILE__)) +require_relative "helper" class TestForkSafety < Test::Unit::TestCase diff --git a/test/helper.rb b/test/helper.rb index b93d2c4af..046f8a1fb 100644 --- a/test/helper.rb +++ b/test/helper.rb @@ -1,6 +1,3 @@ -$:.unshift File.expand_path("../lib", File.dirname(__FILE__)) -$:.unshift File.expand_path(File.dirname(__FILE__)) - require "test/unit" require "logger" require "stringio" @@ -16,12 +13,12 @@ ENV["conn"] ||= "ruby" -require "redis" -require "redis/distributed" -require "redis/connection/#{ENV["conn"]}" +require_relative "../lib/redis" +require_relative "../lib/redis/distributed" +require_relative "../lib/redis/connection/#{ENV["conn"]}" -require "support/redis_mock" -require "support/connection/#{ENV["conn"]}" +require_relative "support/redis_mock" +require_relative "support/connection/#{ENV["conn"]}" PORT = 6381 OPTIONS = {:port => PORT, :db => 15, :timeout => Float(ENV["TIMEOUT"] || 0.1)} diff --git a/test/helper_test.rb b/test/helper_test.rb index 83df2b8a9..b4b027ced 100644 --- a/test/helper_test.rb +++ b/test/helper_test.rb @@ -1,4 +1,4 @@ -require File.expand_path("helper", File.dirname(__FILE__)) +require_relative "helper" class TestHelper < Test::Unit::TestCase diff --git a/test/internals_test.rb b/test/internals_test.rb index 055975677..03ee3b6e5 100644 --- a/test/internals_test.rb +++ b/test/internals_test.rb @@ -1,4 +1,4 @@ -require File.expand_path("helper", File.dirname(__FILE__)) +require_relative "helper" class TestInternals < Test::Unit::TestCase diff --git a/test/persistence_control_commands_test.rb b/test/persistence_control_commands_test.rb index 66292a41e..bf7f8e9a3 100644 --- a/test/persistence_control_commands_test.rb +++ b/test/persistence_control_commands_test.rb @@ -1,4 +1,4 @@ -require File.expand_path("helper", File.dirname(__FILE__)) +require_relative "helper" class TestPersistenceControlCommands < Test::Unit::TestCase diff --git a/test/pipelining_commands_test.rb b/test/pipelining_commands_test.rb index 898e77fe2..a248d3911 100644 --- a/test/pipelining_commands_test.rb +++ b/test/pipelining_commands_test.rb @@ -1,4 +1,4 @@ -require File.expand_path("helper", File.dirname(__FILE__)) +require_relative "helper" class TestPipeliningCommands < Test::Unit::TestCase diff --git a/test/publish_subscribe_test.rb b/test/publish_subscribe_test.rb index ecc83d2a4..cc673b142 100644 --- a/test/publish_subscribe_test.rb +++ b/test/publish_subscribe_test.rb @@ -1,4 +1,4 @@ -require File.expand_path("helper", File.dirname(__FILE__)) +require_relative "helper" class TestPublishSubscribe < Test::Unit::TestCase diff --git a/test/remote_server_control_commands_test.rb b/test/remote_server_control_commands_test.rb index a318a786a..4c240dae7 100644 --- a/test/remote_server_control_commands_test.rb +++ b/test/remote_server_control_commands_test.rb @@ -1,4 +1,4 @@ -require File.expand_path("helper", File.dirname(__FILE__)) +require_relative "helper" class TestRemoteServerControlCommands < Test::Unit::TestCase diff --git a/test/scanning_test.rb b/test/scanning_test.rb index 6d602f731..a0aab1152 100644 --- a/test/scanning_test.rb +++ b/test/scanning_test.rb @@ -1,4 +1,4 @@ -require File.expand_path("helper", File.dirname(__FILE__)) +require_relative "helper" unless defined?(Enumerator) Enumerator = Enumerable::Enumerator diff --git a/test/scripting_test.rb b/test/scripting_test.rb index 851fa9169..ea8e1532a 100644 --- a/test/scripting_test.rb +++ b/test/scripting_test.rb @@ -1,4 +1,4 @@ -require File.expand_path("helper", File.dirname(__FILE__)) +require_relative "helper" class TestScripting < Test::Unit::TestCase diff --git a/test/sentinel_test.rb b/test/sentinel_test.rb index ee3a8483e..0581cf2a9 100644 --- a/test/sentinel_test.rb +++ b/test/sentinel_test.rb @@ -1,4 +1,4 @@ -require File.expand_path("helper", File.dirname(__FILE__)) +require_relative "helper" class SentinalTest < Test::Unit::TestCase diff --git a/test/sorting_test.rb b/test/sorting_test.rb index b25b1f3da..c9e583331 100644 --- a/test/sorting_test.rb +++ b/test/sorting_test.rb @@ -1,4 +1,4 @@ -require File.expand_path("helper", File.dirname(__FILE__)) +require_relative "helper" class TestSorting < Test::Unit::TestCase diff --git a/test/support/connection/ruby.rb b/test/support/connection/ruby.rb index f2ccbca5f..46078c1c5 100644 --- a/test/support/connection/ruby.rb +++ b/test/support/connection/ruby.rb @@ -1 +1 @@ -require "support/wire/thread" +require_relative "../wire/thread" diff --git a/test/synchrony_driver.rb b/test/synchrony_driver.rb index 0078ccd82..622edd340 100644 --- a/test/synchrony_driver.rb +++ b/test/synchrony_driver.rb @@ -5,7 +5,7 @@ require 'redis/connection/synchrony' -require File.expand_path("./helper", File.dirname(__FILE__)) +require_relative "./helper" PORT = 6381 OPTIONS = {:port => PORT, :db => 15} diff --git a/test/thread_safety_test.rb b/test/thread_safety_test.rb index 37b670211..93a87fe85 100644 --- a/test/thread_safety_test.rb +++ b/test/thread_safety_test.rb @@ -1,4 +1,4 @@ -require File.expand_path("helper", File.dirname(__FILE__)) +require_relative "helper" class TestThreadSafety < Test::Unit::TestCase diff --git a/test/transactions_test.rb b/test/transactions_test.rb index ee2174905..de916cb80 100644 --- a/test/transactions_test.rb +++ b/test/transactions_test.rb @@ -1,4 +1,4 @@ -require File.expand_path("helper", File.dirname(__FILE__)) +require_relative "helper" class TestTransactions < Test::Unit::TestCase diff --git a/test/unknown_commands_test.rb b/test/unknown_commands_test.rb index c153fde4d..374690bc8 100644 --- a/test/unknown_commands_test.rb +++ b/test/unknown_commands_test.rb @@ -1,4 +1,4 @@ -require File.expand_path("helper", File.dirname(__FILE__)) +require_relative "helper" class TestUnknownCommands < Test::Unit::TestCase diff --git a/test/url_param_test.rb b/test/url_param_test.rb index ce0af2326..48623d837 100644 --- a/test/url_param_test.rb +++ b/test/url_param_test.rb @@ -1,4 +1,4 @@ -require File.expand_path("helper", File.dirname(__FILE__)) +require_relative "helper" class TestUrlParam < Test::Unit::TestCase From c4ebeda2e26d5182b832ad850f06fa2d72e3b77a Mon Sep 17 00:00:00 2001 From: Damian Janowski Date: Sat, 31 Oct 2015 16:44:29 -0700 Subject: [PATCH 08/34] Remove Redis::Distributed. --- CHANGELOG.md | 2 + examples/dist_redis.rb | 43 - lib/redis/distributed.rb | 873 ------------------ lib/redis/hash_ring.rb | 131 --- test/blocking_commands_test.rb | 147 ++- test/commands_on_hashes_test.rb | 159 +++- test/commands_on_hyper_log_log_test.rb | 55 +- test/commands_on_lists_test.rb | 140 ++- test/commands_on_sets_test.rb | 122 ++- test/commands_on_sorted_sets_test.rb | 235 ++++- test/commands_on_strings_test.rb | 243 ++++- test/commands_on_value_types_test.rb | 119 ++- test/distributed_blocking_commands_test.rb | 44 - test/distributed_commands_on_hashes_test.rb | 8 - ...tributed_commands_on_hyper_log_log_test.rb | 31 - test/distributed_commands_on_lists_test.rb | 20 - test/distributed_commands_on_sets_test.rb | 81 -- ...istributed_commands_on_sorted_sets_test.rb | 16 - test/distributed_commands_on_strings_test.rb | 57 -- ...istributed_commands_on_value_types_test.rb | 93 -- ...uted_commands_requiring_clustering_test.rb | 162 ---- test/distributed_connection_handling_test.rb | 21 - test/distributed_internals_test.rb | 68 -- test/distributed_key_tags_test.rb | 50 - ...buted_persistence_control_commands_test.rb | 24 - test/distributed_publish_subscribe_test.rb | 90 -- ...ted_remote_server_control_commands_test.rb | 64 -- test/distributed_scripting_test.rb | 100 -- test/distributed_sorting_test.rb | 18 - test/distributed_test.rb | 56 -- test/distributed_transactions_test.rb | 30 - test/helper.rb | 22 - test/lint/blocking_commands.rb | 150 --- test/lint/hashes.rb | 162 ---- test/lint/hyper_log_log.rb | 60 -- test/lint/lists.rb | 143 --- test/lint/sets.rb | 125 --- test/lint/sorted_sets.rb | 238 ----- test/lint/strings.rb | 246 ----- test/lint/value_types.rb | 122 --- 40 files changed, 1206 insertions(+), 3364 deletions(-) delete mode 100644 examples/dist_redis.rb delete mode 100644 lib/redis/distributed.rb delete mode 100644 lib/redis/hash_ring.rb delete mode 100644 test/distributed_blocking_commands_test.rb delete mode 100644 test/distributed_commands_on_hashes_test.rb delete mode 100644 test/distributed_commands_on_hyper_log_log_test.rb delete mode 100644 test/distributed_commands_on_lists_test.rb delete mode 100644 test/distributed_commands_on_sets_test.rb delete mode 100644 test/distributed_commands_on_sorted_sets_test.rb delete mode 100644 test/distributed_commands_on_strings_test.rb delete mode 100644 test/distributed_commands_on_value_types_test.rb delete mode 100644 test/distributed_commands_requiring_clustering_test.rb delete mode 100644 test/distributed_connection_handling_test.rb delete mode 100644 test/distributed_internals_test.rb delete mode 100644 test/distributed_key_tags_test.rb delete mode 100644 test/distributed_persistence_control_commands_test.rb delete mode 100644 test/distributed_publish_subscribe_test.rb delete mode 100644 test/distributed_remote_server_control_commands_test.rb delete mode 100644 test/distributed_scripting_test.rb delete mode 100644 test/distributed_sorting_test.rb delete mode 100644 test/distributed_test.rb delete mode 100644 test/distributed_transactions_test.rb delete mode 100644 test/lint/blocking_commands.rb delete mode 100644 test/lint/hashes.rb delete mode 100644 test/lint/hyper_log_log.rb delete mode 100644 test/lint/lists.rb delete mode 100644 test/lint/sets.rb delete mode 100644 test/lint/sorted_sets.rb delete mode 100644 test/lint/strings.rb delete mode 100644 test/lint/value_types.rb diff --git a/CHANGELOG.md b/CHANGELOG.md index e3f450b4e..a9867e83d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ * Removed `Redis#[]` and `Redis#[]=` aliases. +* Removed `Redis::Distributed`. + # 3.2.1 * Added support for `PUBSUB` command. diff --git a/examples/dist_redis.rb b/examples/dist_redis.rb deleted file mode 100644 index fe1c5da72..000000000 --- a/examples/dist_redis.rb +++ /dev/null @@ -1,43 +0,0 @@ -require "redis" -require "redis/distributed" - -r = Redis::Distributed.new %w[redis://localhost:6379 redis://localhost:6380 redis://localhost:6381 redis://localhost:6382] - -r.flushdb - -r['urmom'] = 'urmom' -r['urdad'] = 'urdad' -r['urmom1'] = 'urmom1' -r['urdad1'] = 'urdad1' -r['urmom2'] = 'urmom2' -r['urdad2'] = 'urdad2' -r['urmom3'] = 'urmom3' -r['urdad3'] = 'urdad3' -p r['urmom'] -p r['urdad'] -p r['urmom1'] -p r['urdad1'] -p r['urmom2'] -p r['urdad2'] -p r['urmom3'] -p r['urdad3'] - -r.rpush 'listor', 'foo1' -r.rpush 'listor', 'foo2' -r.rpush 'listor', 'foo3' -r.rpush 'listor', 'foo4' -r.rpush 'listor', 'foo5' - -p r.rpop('listor') -p r.rpop('listor') -p r.rpop('listor') -p r.rpop('listor') -p r.rpop('listor') - -puts "key distribution:" - -r.ring.nodes.each do |node| - p [node.client, node.keys("*")] -end -r.flushdb -p r.keys('*') diff --git a/lib/redis/distributed.rb b/lib/redis/distributed.rb deleted file mode 100644 index 774c754b3..000000000 --- a/lib/redis/distributed.rb +++ /dev/null @@ -1,873 +0,0 @@ -require_relative "hash_ring" - -class Redis - class Distributed - - class CannotDistribute < RuntimeError - def initialize(command) - @command = command - end - - def message - "#{@command.to_s.upcase} cannot be used in Redis::Distributed because the keys involved need to be on the same server or because we cannot guarantee that the operation will be atomic." - end - end - - attr_reader :ring - - def initialize(node_configs, options = {}) - @tag = options[:tag] || /^\{(.+?)\}/ - @ring = options[:ring] || HashRing.new - @node_configs = node_configs.dup - @default_options = options.dup - node_configs.each { |node_config| add_node(node_config) } - @subscribed_node = nil - end - - def node_for(key) - @ring.get_node(key_tag(key.to_s) || key.to_s) - end - - def nodes - @ring.nodes - end - - def add_node(options) - options = { :url => options } if options.is_a?(String) - options = @default_options.merge(options) - @ring.add_node Redis.new( options ) - end - - # Change the selected database for the current connection. - def select(db) - on_each_node :select, db - end - - # Ping the server. - def ping - on_each_node :ping - end - - # Echo the given string. - def echo(value) - on_each_node :echo, value - end - - # Close the connection. - def quit - on_each_node :quit - end - - # Asynchronously save the dataset to disk. - def bgsave - on_each_node :bgsave - end - - # Return the number of keys in the selected database. - def dbsize - on_each_node :dbsize - end - - # Remove all keys from all databases. - def flushall - on_each_node :flushall - end - - # Remove all keys from the current database. - def flushdb - on_each_node :flushdb - end - - # Get information and statistics about the server. - def info(cmd = nil) - on_each_node :info, cmd - end - - # Get the UNIX time stamp of the last successful save to disk. - def lastsave - on_each_node :lastsave - end - - # Listen for all requests received by the server in real time. - def monitor - raise NotImplementedError - end - - # Synchronously save the dataset to disk. - def save - on_each_node :save - end - - # Get server time: an UNIX timestamp and the elapsed microseconds in the current second. - def time - on_each_node :time - end - - # Remove the expiration from a key. - def persist(key) - node_for(key).persist(key) - end - - # Set a key's time to live in seconds. - def expire(key, seconds) - node_for(key).expire(key, seconds) - end - - # Set the expiration for a key as a UNIX timestamp. - def expireat(key, unix_time) - node_for(key).expireat(key, unix_time) - end - - # Get the time to live (in seconds) for a key. - def ttl(key) - node_for(key).ttl(key) - end - - # Set a key's time to live in milliseconds. - def pexpire(key, milliseconds) - node_for(key).pexpire(key, milliseconds) - end - - # Set the expiration for a key as number of milliseconds from UNIX Epoch. - def pexpireat(key, ms_unix_time) - node_for(key).pexpireat(key, ms_unix_time) - end - - # Get the time to live (in milliseconds) for a key. - def pttl(key) - node_for(key).pttl(key) - end - - # Return a serialized version of the value stored at a key. - def dump(key) - node_for(key).dump(key) - end - - # Create a key using the serialized value, previously obtained using DUMP. - def restore(key, ttl, serialized_value) - node_for(key).restore(key, ttl, serialized_value) - end - - # Transfer a key from the connected instance to another instance. - def migrate(key, options) - raise CannotDistribute, :migrate - end - - # Delete a key. - def del(*args) - keys_per_node = args.group_by { |key| node_for(key) } - keys_per_node.inject(0) do |sum, (node, keys)| - sum + node.del(*keys) - end - end - - # Determine if a key exists. - def exists(key) - node_for(key).exists(key) - end - - # Find all keys matching the given pattern. - def keys(glob = "*") - on_each_node(:keys, glob).flatten - end - - # Move a key to another database. - def move(key, db) - node_for(key).move(key, db) - end - - # Return a random key from the keyspace. - def randomkey - raise CannotDistribute, :randomkey - end - - # Rename a key. - def rename(old_name, new_name) - ensure_same_node(:rename, [old_name, new_name]) do |node| - node.rename(old_name, new_name) - end - end - - # Rename a key, only if the new key does not exist. - def renamenx(old_name, new_name) - ensure_same_node(:renamenx, [old_name, new_name]) do |node| - node.renamenx(old_name, new_name) - end - end - - # Sort the elements in a list, set or sorted set. - def sort(key, options = {}) - keys = [key, options[:by], options[:store], *Array(options[:get])].compact - - ensure_same_node(:sort, keys) do |node| - node.sort(key, options) - end - end - - # Determine the type stored at key. - def type(key) - node_for(key).type(key) - end - - # Decrement the integer value of a key by one. - def decr(key) - node_for(key).decr(key) - end - - # Decrement the integer value of a key by the given number. - def decrby(key, decrement) - node_for(key).decrby(key, decrement) - end - - # Increment the integer value of a key by one. - def incr(key) - node_for(key).incr(key) - end - - # Increment the integer value of a key by the given integer number. - def incrby(key, increment) - node_for(key).incrby(key, increment) - end - - # Increment the numeric value of a key by the given float number. - def incrbyfloat(key, increment) - node_for(key).incrbyfloat(key, increment) - end - - # Set the string value of a key. - def set(key, value, options = {}) - node_for(key).set(key, value, options) - end - - # Set the time to live in seconds of a key. - def setex(key, ttl, value) - node_for(key).setex(key, ttl, value) - end - - # Set the time to live in milliseconds of a key. - def psetex(key, ttl, value) - node_for(key).psetex(key, ttl, value) - end - - # Set the value of a key, only if the key does not exist. - def setnx(key, value) - node_for(key).setnx(key, value) - end - - # Set multiple keys to multiple values. - def mset(*args) - raise CannotDistribute, :mset - end - - def mapped_mset(hash) - raise CannotDistribute, :mapped_mset - end - - # Set multiple keys to multiple values, only if none of the keys exist. - def msetnx(*args) - raise CannotDistribute, :msetnx - end - - def mapped_msetnx(hash) - raise CannotDistribute, :mapped_msetnx - end - - # Get the value of a key. - def get(key) - node_for(key).get(key) - end - - # Get the values of all the given keys. - def mget(*keys) - raise CannotDistribute, :mget - end - - def mapped_mget(*keys) - raise CannotDistribute, :mapped_mget - end - - # Overwrite part of a string at key starting at the specified offset. - def setrange(key, offset, value) - node_for(key).setrange(key, offset, value) - end - - # Get a substring of the string stored at a key. - def getrange(key, start, stop) - node_for(key).getrange(key, start, stop) - end - - # Sets or clears the bit at offset in the string value stored at key. - def setbit(key, offset, value) - node_for(key).setbit(key, offset, value) - end - - # Returns the bit value at offset in the string value stored at key. - def getbit(key, offset) - node_for(key).getbit(key, offset) - end - - # Append a value to a key. - def append(key, value) - node_for(key).append(key, value) - end - - # Count the number of set bits in a range of the string value stored at key. - def bitcount(key, start = 0, stop = -1) - node_for(key).bitcount(key, start, stop) - end - - # Perform a bitwise operation between strings and store the resulting string in a key. - def bitop(operation, destkey, *keys) - ensure_same_node(:bitop, [destkey] + keys) do |node| - node.bitop(operation, destkey, *keys) - end - end - - # Return the position of the first bit set to 1 or 0 in a string. - def bitpos(key, bit, start=nil, stop=nil) - node_for(key).bitpos(key, bit, start, stop) - end - - # Set the string value of a key and return its old value. - def getset(key, value) - node_for(key).getset(key, value) - end - - # Get the length of the value stored in a key. - def strlen(key) - node_for(key).strlen(key) - end - - def [](key) - get(key) - end - - def []=(key,value) - set(key, value) - end - - # Get the length of a list. - def llen(key) - node_for(key).llen(key) - end - - # Prepend one or more values to a list. - def lpush(key, value) - node_for(key).lpush(key, value) - end - - # Prepend a value to a list, only if the list exists. - def lpushx(key, value) - node_for(key).lpushx(key, value) - end - - # Append one or more values to a list. - def rpush(key, value) - node_for(key).rpush(key, value) - end - - # Append a value to a list, only if the list exists. - def rpushx(key, value) - node_for(key).rpushx(key, value) - end - - # Remove and get the first element in a list. - def lpop(key) - node_for(key).lpop(key) - end - - # Remove and get the last element in a list. - def rpop(key) - node_for(key).rpop(key) - end - - # Remove the last element in a list, append it to another list and return - # it. - def rpoplpush(source, destination) - ensure_same_node(:rpoplpush, [source, destination]) do |node| - node.rpoplpush(source, destination) - end - end - - def _bpop(cmd, args) - options = {} - - case args.last - when Hash - options = args.pop - when Integer - # Issue deprecation notice in obnoxious mode... - options[:timeout] = args.pop - end - - if args.size > 1 - # Issue deprecation notice in obnoxious mode... - end - - keys = args.flatten - - ensure_same_node(cmd, keys) do |node| - node.__send__(cmd, keys, options) - end - end - - # Remove and get the first element in a list, or block until one is - # available. - def blpop(*args) - _bpop(:blpop, args) - end - - # Remove and get the last element in a list, or block until one is - # available. - def brpop(*args) - _bpop(:brpop, args) - end - - # Pop a value from a list, push it to another list and return it; or block - # until one is available. - def brpoplpush(source, destination, options = {}) - case options - when Integer - # Issue deprecation notice in obnoxious mode... - options = { :timeout => options } - end - - ensure_same_node(:brpoplpush, [source, destination]) do |node| - node.brpoplpush(source, destination, options) - end - end - - # Get an element from a list by its index. - def lindex(key, index) - node_for(key).lindex(key, index) - end - - # Insert an element before or after another element in a list. - def linsert(key, where, pivot, value) - node_for(key).linsert(key, where, pivot, value) - end - - # Get a range of elements from a list. - def lrange(key, start, stop) - node_for(key).lrange(key, start, stop) - end - - # Remove elements from a list. - def lrem(key, count, value) - node_for(key).lrem(key, count, value) - end - - # Set the value of an element in a list by its index. - def lset(key, index, value) - node_for(key).lset(key, index, value) - end - - # Trim a list to the specified range. - def ltrim(key, start, stop) - node_for(key).ltrim(key, start, stop) - end - - # Get the number of members in a set. - def scard(key) - node_for(key).scard(key) - end - - # Add one or more members to a set. - def sadd(key, member) - node_for(key).sadd(key, member) - end - - # Remove one or more members from a set. - def srem(key, member) - node_for(key).srem(key, member) - end - - # Remove and return a random member from a set. - def spop(key) - node_for(key).spop(key) - end - - # Get a random member from a set. - def srandmember(key, count = nil) - node_for(key).srandmember(key, count) - end - - # Move a member from one set to another. - def smove(source, destination, member) - ensure_same_node(:smove, [source, destination]) do |node| - node.smove(source, destination, member) - end - end - - # Determine if a given value is a member of a set. - def sismember(key, member) - node_for(key).sismember(key, member) - end - - # Get all the members in a set. - def smembers(key) - node_for(key).smembers(key) - end - - # Subtract multiple sets. - def sdiff(*keys) - ensure_same_node(:sdiff, keys) do |node| - node.sdiff(*keys) - end - end - - # Subtract multiple sets and store the resulting set in a key. - def sdiffstore(destination, *keys) - ensure_same_node(:sdiffstore, [destination] + keys) do |node| - node.sdiffstore(destination, *keys) - end - end - - # Intersect multiple sets. - def sinter(*keys) - ensure_same_node(:sinter, keys) do |node| - node.sinter(*keys) - end - end - - # Intersect multiple sets and store the resulting set in a key. - def sinterstore(destination, *keys) - ensure_same_node(:sinterstore, [destination] + keys) do |node| - node.sinterstore(destination, *keys) - end - end - - # Add multiple sets. - def sunion(*keys) - ensure_same_node(:sunion, keys) do |node| - node.sunion(*keys) - end - end - - # Add multiple sets and store the resulting set in a key. - def sunionstore(destination, *keys) - ensure_same_node(:sunionstore, [destination] + keys) do |node| - node.sunionstore(destination, *keys) - end - end - - # Get the number of members in a sorted set. - def zcard(key) - node_for(key).zcard(key) - end - - # Add one or more members to a sorted set, or update the score for members - # that already exist. - def zadd(key, *args) - node_for(key).zadd(key, *args) - end - - # Increment the score of a member in a sorted set. - def zincrby(key, increment, member) - node_for(key).zincrby(key, increment, member) - end - - # Remove one or more members from a sorted set. - def zrem(key, member) - node_for(key).zrem(key, member) - end - - # Get the score associated with the given member in a sorted set. - def zscore(key, member) - node_for(key).zscore(key, member) - end - - # Return a range of members in a sorted set, by index. - def zrange(key, start, stop, options = {}) - node_for(key).zrange(key, start, stop, options) - end - - # Return a range of members in a sorted set, by index, with scores ordered - # from high to low. - def zrevrange(key, start, stop, options = {}) - node_for(key).zrevrange(key, start, stop, options) - end - - # Determine the index of a member in a sorted set. - def zrank(key, member) - node_for(key).zrank(key, member) - end - - # Determine the index of a member in a sorted set, with scores ordered from - # high to low. - def zrevrank(key, member) - node_for(key).zrevrank(key, member) - end - - # Remove all members in a sorted set within the given indexes. - def zremrangebyrank(key, start, stop) - node_for(key).zremrangebyrank(key, start, stop) - end - - # Return a range of members in a sorted set, by score. - def zrangebyscore(key, min, max, options = {}) - node_for(key).zrangebyscore(key, min, max, options) - end - - # Return a range of members in a sorted set, by score, with scores ordered - # from high to low. - def zrevrangebyscore(key, max, min, options = {}) - node_for(key).zrevrangebyscore(key, max, min, options) - end - - # Remove all members in a sorted set within the given scores. - def zremrangebyscore(key, min, max) - node_for(key).zremrangebyscore(key, min, max) - end - - # Get the number of members in a particular score range. - def zcount(key, min, max) - node_for(key).zcount(key, min, max) - end - - # Intersect multiple sorted sets and store the resulting sorted set in a new - # key. - def zinterstore(destination, keys, options = {}) - ensure_same_node(:zinterstore, [destination] + keys) do |node| - node.zinterstore(destination, keys, options) - end - end - - # Add multiple sorted sets and store the resulting sorted set in a new key. - def zunionstore(destination, keys, options = {}) - ensure_same_node(:zunionstore, [destination] + keys) do |node| - node.zunionstore(destination, keys, options) - end - end - - # Get the number of fields in a hash. - def hlen(key) - node_for(key).hlen(key) - end - - # Set the string value of a hash field. - def hset(key, field, value) - node_for(key).hset(key, field, value) - end - - # Set the value of a hash field, only if the field does not exist. - def hsetnx(key, field, value) - node_for(key).hsetnx(key, field, value) - end - - # Set multiple hash fields to multiple values. - def hmset(key, *attrs) - node_for(key).hmset(key, *attrs) - end - - def mapped_hmset(key, hash) - node_for(key).hmset(key, *hash.to_a.flatten) - end - - # Get the value of a hash field. - def hget(key, field) - node_for(key).hget(key, field) - end - - # Get the values of all the given hash fields. - def hmget(key, *fields) - node_for(key).hmget(key, *fields) - end - - def mapped_hmget(key, *fields) - Hash[*fields.zip(hmget(key, *fields)).flatten] - end - - # Delete one or more hash fields. - def hdel(key, field) - node_for(key).hdel(key, field) - end - - # Determine if a hash field exists. - def hexists(key, field) - node_for(key).hexists(key, field) - end - - # Increment the integer value of a hash field by the given integer number. - def hincrby(key, field, increment) - node_for(key).hincrby(key, field, increment) - end - - # Increment the numeric value of a hash field by the given float number. - def hincrbyfloat(key, field, increment) - node_for(key).hincrbyfloat(key, field, increment) - end - - # Get all the fields in a hash. - def hkeys(key) - node_for(key).hkeys(key) - end - - # Get all the values in a hash. - def hvals(key) - node_for(key).hvals(key) - end - - # Get all the fields and values in a hash. - def hgetall(key) - node_for(key).hgetall(key) - end - - # Post a message to a channel. - def publish(channel, message) - node_for(channel).publish(channel, message) - end - - def subscribed? - !! @subscribed_node - end - - # Listen for messages published to the given channels. - def subscribe(channel, *channels, &block) - if channels.empty? - @subscribed_node = node_for(channel) - @subscribed_node.subscribe(channel, &block) - else - ensure_same_node(:subscribe, [channel] + channels) do |node| - @subscribed_node = node - node.subscribe(channel, *channels, &block) - end - end - end - - # Stop listening for messages posted to the given channels. - def unsubscribe(*channels) - raise RuntimeError, "Can't unsubscribe if not subscribed." unless subscribed? - @subscribed_node.unsubscribe(*channels) - end - - # Listen for messages published to channels matching the given patterns. - def psubscribe(*channels, &block) - raise NotImplementedError - end - - # Stop listening for messages posted to channels matching the given - # patterns. - def punsubscribe(*channels) - raise NotImplementedError - end - - # Watch the given keys to determine execution of the MULTI/EXEC block. - def watch(*keys) - raise CannotDistribute, :watch - end - - # Forget about all watched keys. - def unwatch - raise CannotDistribute, :unwatch - end - - def pipelined - raise CannotDistribute, :pipelined - end - - # Mark the start of a transaction block. - def multi - raise CannotDistribute, :multi - end - - # Execute all commands issued after MULTI. - def exec - raise CannotDistribute, :exec - end - - # Discard all commands issued after MULTI. - def discard - raise CannotDistribute, :discard - end - - # Control remote script registry. - def script(subcommand, *args) - on_each_node(:script, subcommand, *args) - end - - # Add one or more members to a HyperLogLog structure. - def pfadd(key, member) - node_for(key).pfadd(key, member) - end - - # Get the approximate cardinality of members added to HyperLogLog structure. - def pfcount(*keys) - ensure_same_node(:pfcount, keys.flatten(1)) do |node| - node.pfcount(keys) - end - end - - # Merge multiple HyperLogLog values into an unique value that will approximate the cardinality of the union of - # the observed Sets of the source HyperLogLog structures. - def pfmerge(dest_key, *source_key) - ensure_same_node(:pfmerge, [dest_key, *source_key]) do |node| - node.pfmerge(dest_key, *source_key) - end - end - - def _eval(cmd, args) - script = args.shift - options = args.pop if args.last.is_a?(Hash) - options ||= {} - - keys = args.shift || options[:keys] || [] - argv = args.shift || options[:argv] || [] - - ensure_same_node(cmd, keys) do |node| - node.send(cmd, script, keys, argv) - end - end - - # Evaluate Lua script. - def eval(*args) - _eval(:eval, args) - end - - # Evaluate Lua script by its SHA. - def evalsha(*args) - _eval(:evalsha, args) - end - - def inspect - "#" - end - - def dup - self.class.new(@node_configs, @default_options) - end - - protected - - def on_each_node(command, *args) - nodes.map do |node| - node.send(command, *args) - end - end - - def node_index_for(key) - nodes.index(node_for(key)) - end - - def key_tag(key) - key.to_s[@tag, 1] if @tag - end - - def ensure_same_node(command, keys) - all = true - - tags = keys.map do |key| - tag = key_tag(key) - all = false unless tag - tag - end - - if (all && tags.uniq.size != 1) || (!all && keys.uniq.size != 1) - # Not 1 unique tag or not 1 unique key - raise CannotDistribute, command - end - - yield(node_for(keys.first)) - end - end -end diff --git a/lib/redis/hash_ring.rb b/lib/redis/hash_ring.rb deleted file mode 100644 index b9b8d5ddb..000000000 --- a/lib/redis/hash_ring.rb +++ /dev/null @@ -1,131 +0,0 @@ -require 'zlib' - -class Redis - class HashRing - - POINTS_PER_SERVER = 160 # this is the default in libmemcached - - attr_reader :ring, :sorted_keys, :replicas, :nodes - - # nodes is a list of objects that have a proper to_s representation. - # replicas indicates how many virtual points should be used pr. node, - # replicas are required to improve the distribution. - def initialize(nodes=[], replicas=POINTS_PER_SERVER) - @replicas = replicas - @ring = {} - @nodes = [] - @sorted_keys = [] - nodes.each do |node| - add_node(node) - end - end - - # Adds a `node` to the hash ring (including a number of replicas). - def add_node(node) - @nodes << node - @replicas.times do |i| - key = Zlib.crc32("#{node.id}:#{i}") - @ring[key] = node - @sorted_keys << key - end - @sorted_keys.sort! - end - - def remove_node(node) - @nodes.reject!{|n| n.id == node.id} - @replicas.times do |i| - key = Zlib.crc32("#{node.id}:#{i}") - @ring.delete(key) - @sorted_keys.reject! {|k| k == key} - end - end - - # get the node in the hash ring for this key - def get_node(key) - get_node_pos(key)[0] - end - - def get_node_pos(key) - return [nil,nil] if @ring.size == 0 - crc = Zlib.crc32(key) - idx = HashRing.binary_search(@sorted_keys, crc) - return [@ring[@sorted_keys[idx]], idx] - end - - def iter_nodes(key) - return [nil,nil] if @ring.size == 0 - _, pos = get_node_pos(key) - @ring.size.times do |n| - yield @ring[@sorted_keys[(pos+n) % @ring.size]] - end - end - - class << self - - # gem install RubyInline to use this code - # Native extension to perform the binary search within the hashring. - # There's a pure ruby version below so this is purely optional - # for performance. In testing 20k gets and sets, the native - # binary search shaved about 12% off the runtime (9sec -> 8sec). - begin - require 'inline' - inline do |builder| - builder.c <<-EOM - int binary_search(VALUE ary, unsigned int r) { - int upper = RARRAY_LEN(ary) - 1; - int lower = 0; - int idx = 0; - - while (lower <= upper) { - idx = (lower + upper) / 2; - - VALUE continuumValue = RARRAY_PTR(ary)[idx]; - unsigned int l = NUM2UINT(continuumValue); - if (l == r) { - return idx; - } - else if (l > r) { - upper = idx - 1; - } - else { - lower = idx + 1; - } - } - if (upper < 0) { - upper = RARRAY_LEN(ary) - 1; - } - return upper; - } - EOM - end - rescue Exception - # Find the closest index in HashRing with value <= the given value - def binary_search(ary, value, &block) - upper = ary.size - 1 - lower = 0 - idx = 0 - - while(lower <= upper) do - idx = (lower + upper) / 2 - comp = ary[idx] <=> value - - if comp == 0 - return idx - elsif comp > 0 - upper = idx - 1 - else - lower = idx + 1 - end - end - - if upper < 0 - upper = ary.size - 1 - end - return upper - end - - end - end - - end -end diff --git a/test/blocking_commands_test.rb b/test/blocking_commands_test.rb index f5a944b5b..1cd413d52 100644 --- a/test/blocking_commands_test.rb +++ b/test/blocking_commands_test.rb @@ -1,10 +1,153 @@ require_relative "helper" -require_relative "lint/blocking_commands" class TestBlockingCommands < Test::Unit::TestCase include Helper::Client - include Lint::BlockingCommands + + def setup + super + + r.rpush("{zap}foo", "s1") + r.rpush("{zap}foo", "s2") + r.rpush("{zap}bar", "s1") + r.rpush("{zap}bar", "s2") + end + + def to_protocol(obj) + case obj + when String + "$#{obj.length}\r\n#{obj}\r\n" + when Array + "*#{obj.length}\r\n" + obj.map { |e| to_protocol(e) }.join + else + fail + end + end + + def mock(options = {}, &blk) + commands = { + :blpop => lambda do |*args| + sleep options[:delay] if options.has_key?(:delay) + to_protocol([args.first, args.last]) + end, + :brpop => lambda do |*args| + sleep options[:delay] if options.has_key?(:delay) + to_protocol([args.first, args.last]) + end, + :brpoplpush => lambda do |*args| + sleep options[:delay] if options.has_key?(:delay) + to_protocol(args.last) + end, + } + + redis_mock(commands, &blk) + end + + def test_blpop + assert_equal ["{zap}foo", "s1"], r.blpop("{zap}foo") + assert_equal ["{zap}foo", "s2"], r.blpop(["{zap}foo"]) + assert_equal ["{zap}bar", "s1"], r.blpop(["{zap}bar", "{zap}foo"]) + assert_equal ["{zap}bar", "s2"], r.blpop(["{zap}foo", "{zap}bar"]) + end + + def test_blpop_timeout + mock do |r| + assert_equal ["{zap}foo", "0"], r.blpop("{zap}foo") + assert_equal ["{zap}foo", "1"], r.blpop("{zap}foo", :timeout => 1) + end + end + + def test_blpop_with_old_prototype + assert_equal ["{zap}foo", "s1"], r.blpop("{zap}foo", 0) + assert_equal ["{zap}foo", "s2"], r.blpop("{zap}foo", 0) + assert_equal ["{zap}bar", "s1"], r.blpop("{zap}bar", "{zap}foo", 0) + assert_equal ["{zap}bar", "s2"], r.blpop("{zap}foo", "{zap}bar", 0) + end + + def test_blpop_timeout_with_old_prototype + mock do |r| + assert_equal ["{zap}foo", "0"], r.blpop("{zap}foo", 0) + assert_equal ["{zap}foo", "1"], r.blpop("{zap}foo", 1) + end + end + + def test_brpop + assert_equal ["{zap}foo", "s2"], r.brpop("{zap}foo") + assert_equal ["{zap}foo", "s1"], r.brpop(["{zap}foo"]) + assert_equal ["{zap}bar", "s2"], r.brpop(["{zap}bar", "{zap}foo"]) + assert_equal ["{zap}bar", "s1"], r.brpop(["{zap}foo", "{zap}bar"]) + end + + def test_brpop_timeout + mock do |r| + assert_equal ["{zap}foo", "0"], r.brpop("{zap}foo") + assert_equal ["{zap}foo", "1"], r.brpop("{zap}foo", :timeout => 1) + end + end + + def test_brpop_with_old_prototype + assert_equal ["{zap}foo", "s2"], r.brpop("{zap}foo", 0) + assert_equal ["{zap}foo", "s1"], r.brpop("{zap}foo", 0) + assert_equal ["{zap}bar", "s2"], r.brpop("{zap}bar", "{zap}foo", 0) + assert_equal ["{zap}bar", "s1"], r.brpop("{zap}foo", "{zap}bar", 0) + end + + def test_brpop_timeout_with_old_prototype + mock do |r| + assert_equal ["{zap}foo", "0"], r.brpop("{zap}foo", 0) + assert_equal ["{zap}foo", "1"], r.brpop("{zap}foo", 1) + end + end + + def test_brpoplpush + assert_equal "s2", r.brpoplpush("{zap}foo", "{zap}qux") + assert_equal ["s2"], r.lrange("{zap}qux", 0, -1) + end + + def test_brpoplpush_timeout + mock do |r| + assert_equal "0", r.brpoplpush("{zap}foo", "{zap}bar") + assert_equal "1", r.brpoplpush("{zap}foo", "{zap}bar", :timeout => 1) + end + end + + def test_brpoplpush_with_old_prototype + assert_equal "s2", r.brpoplpush("{zap}foo", "{zap}qux", 0) + assert_equal ["s2"], r.lrange("{zap}qux", 0, -1) + end + + def test_brpoplpush_timeout_with_old_prototype + mock do |r| + assert_equal "0", r.brpoplpush("{zap}foo", "{zap}bar", 0) + assert_equal "1", r.brpoplpush("{zap}foo", "{zap}bar", 1) + end + end + + driver(:ruby, :hiredis) do + def test_blpop_socket_timeout + mock(:delay => 1 + OPTIONS[:timeout] * 2) do |r| + assert_raises(Redis::TimeoutError) do + r.blpop("{zap}foo", :timeout => 1) + end + end + end + + def test_brpop_socket_timeout + mock(:delay => 1 + OPTIONS[:timeout] * 2) do |r| + assert_raises(Redis::TimeoutError) do + r.brpop("{zap}foo", :timeout => 1) + end + end + end + + def test_brpoplpush_socket_timeout + mock(:delay => 1 + OPTIONS[:timeout] * 2) do |r| + assert_raises(Redis::TimeoutError) do + r.brpoplpush("{zap}foo", "{zap}bar", :timeout => 1) + end + end + end + end def assert_takes_longer_than_client_timeout timeout = OPTIONS[:timeout] diff --git a/test/commands_on_hashes_test.rb b/test/commands_on_hashes_test.rb index 3e0f7ba4e..198883b49 100644 --- a/test/commands_on_hashes_test.rb +++ b/test/commands_on_hashes_test.rb @@ -1,10 +1,165 @@ require_relative "helper" -require_relative "lint/hashes" class TestCommandsOnHashes < Test::Unit::TestCase include Helper::Client - include Lint::Hashes + + def test_hset_and_hget + r.hset("foo", "f1", "s1") + + assert_equal "s1", r.hget("foo", "f1") + end + + def test_hsetnx + r.hset("foo", "f1", "s1") + r.hsetnx("foo", "f1", "s2") + + assert_equal "s1", r.hget("foo", "f1") + + r.del("foo") + r.hsetnx("foo", "f1", "s2") + + assert_equal "s2", r.hget("foo", "f1") + end + + def test_hdel + r.hset("foo", "f1", "s1") + + assert_equal "s1", r.hget("foo", "f1") + + assert_equal 1, r.hdel("foo", "f1") + + assert_equal nil, r.hget("foo", "f1") + end + + def test_variadic_hdel + target_version "2.3.9" do + r.hset("foo", "f1", "s1") + r.hset("foo", "f2", "s2") + + assert_equal "s1", r.hget("foo", "f1") + assert_equal "s2", r.hget("foo", "f2") + + assert_equal 2, r.hdel("foo", ["f1", "f2"]) + + assert_equal nil, r.hget("foo", "f1") + assert_equal nil, r.hget("foo", "f2") + end + end + + def test_hexists + assert_equal false, r.hexists("foo", "f1") + + r.hset("foo", "f1", "s1") + + assert r.hexists("foo", "f1") + end + + def test_hlen + assert_equal 0, r.hlen("foo") + + r.hset("foo", "f1", "s1") + + assert_equal 1, r.hlen("foo") + + r.hset("foo", "f2", "s2") + + assert_equal 2, r.hlen("foo") + end + + def test_hkeys + assert_equal [], r.hkeys("foo") + + r.hset("foo", "f1", "s1") + r.hset("foo", "f2", "s2") + + assert_equal ["f1", "f2"], r.hkeys("foo") + end + + def test_hvals + assert_equal [], r.hvals("foo") + + r.hset("foo", "f1", "s1") + r.hset("foo", "f2", "s2") + + assert_equal ["s1", "s2"], r.hvals("foo") + end + + def test_hgetall + assert({} == r.hgetall("foo")) + + r.hset("foo", "f1", "s1") + r.hset("foo", "f2", "s2") + + assert({"f1" => "s1", "f2" => "s2"} == r.hgetall("foo")) + end + + def test_hmset + r.hmset("hash", "foo1", "bar1", "foo2", "bar2") + + assert_equal "bar1", r.hget("hash", "foo1") + assert_equal "bar2", r.hget("hash", "foo2") + end + + def test_hmset_with_invalid_arguments + assert_raise(Redis::CommandError) do + r.hmset("hash", "foo1", "bar1", "foo2", "bar2", "foo3") + end + end + + def test_mapped_hmset + r.mapped_hmset("foo", :f1 => "s1", :f2 => "s2") + + assert_equal "s1", r.hget("foo", "f1") + assert_equal "s2", r.hget("foo", "f2") + end + + def test_hmget + r.hset("foo", "f1", "s1") + r.hset("foo", "f2", "s2") + r.hset("foo", "f3", "s3") + + assert_equal ["s2", "s3"], r.hmget("foo", "f2", "f3") + end + + def test_hmget_mapped + r.hset("foo", "f1", "s1") + r.hset("foo", "f2", "s2") + r.hset("foo", "f3", "s3") + + assert({"f1" => "s1"} == r.mapped_hmget("foo", "f1")) + assert({"f1" => "s1", "f2" => "s2"} == r.mapped_hmget("foo", "f1", "f2")) + end + + def test_hincrby + r.hincrby("foo", "f1", 1) + + assert_equal "1", r.hget("foo", "f1") + + r.hincrby("foo", "f1", 2) + + assert_equal "3", r.hget("foo", "f1") + + r.hincrby("foo", "f1", -1) + + assert_equal "2", r.hget("foo", "f1") + end + + def test_hincrbyfloat + target_version "2.5.4" do + r.hincrbyfloat("foo", "f1", 1.23) + + assert_equal "1.23", r.hget("foo", "f1") + + r.hincrbyfloat("foo", "f1", 0.77) + + assert_equal "2", r.hget("foo", "f1") + + r.hincrbyfloat("foo", "f1", -0.1) + + assert_equal "1.9", r.hget("foo", "f1") + end + end def test_mapped_hmget_in_a_pipeline_returns_hash r.hset("foo", "f1", "s1") diff --git a/test/commands_on_hyper_log_log_test.rb b/test/commands_on_hyper_log_log_test.rb index 194e6d4c6..2f39536a4 100644 --- a/test/commands_on_hyper_log_log_test.rb +++ b/test/commands_on_hyper_log_log_test.rb @@ -1,10 +1,61 @@ require_relative "helper" -require_relative "lint/hyper_log_log" class TestCommandsOnHyperLogLog < Test::Unit::TestCase include Helper::Client - include Lint::HyperLogLog + + def test_pfadd + target_version "2.8.9" do + assert_equal true, r.pfadd("foo", "s1") + assert_equal true, r.pfadd("foo", "s2") + assert_equal false, r.pfadd("foo", "s1") + + assert_equal 2, r.pfcount("foo") + end + end + + def test_variadic_pfadd + target_version "2.8.9" do + assert_equal true, r.pfadd("foo", ["s1", "s2"]) + assert_equal true, r.pfadd("foo", ["s1", "s2", "s3"]) + + assert_equal 3, r.pfcount("foo") + end + end + + def test_pfcount + target_version "2.8.9" do + assert_equal 0, r.pfcount("foo") + + assert_equal true, r.pfadd("foo", "s1") + + assert_equal 1, r.pfcount("foo") + end + end + + def test_variadic_pfcount + target_version "2.8.9" do + assert_equal 0, r.pfcount(["{1}foo", "{1}bar"]) + + assert_equal true, r.pfadd("{1}foo", "s1") + assert_equal true, r.pfadd("{1}bar", "s1") + assert_equal true, r.pfadd("{1}bar", "s2") + + assert_equal 2, r.pfcount("{1}foo", "{1}bar") + end + end + + def test_variadic_pfcount_expanded + target_version "2.8.9" do + assert_equal 0, r.pfcount("{1}foo", "{1}bar") + + assert_equal true, r.pfadd("{1}foo", "s1") + assert_equal true, r.pfadd("{1}bar", "s1") + assert_equal true, r.pfadd("{1}bar", "s2") + + assert_equal 2, r.pfcount("{1}foo", "{1}bar") + end + end def test_pfmerge target_version "2.8.9" do diff --git a/test/commands_on_lists_test.rb b/test/commands_on_lists_test.rb index 5f286706f..df2b2ff1f 100644 --- a/test/commands_on_lists_test.rb +++ b/test/commands_on_lists_test.rb @@ -1,10 +1,146 @@ require_relative "helper" -require_relative "lint/lists" class TestCommandsOnLists < Test::Unit::TestCase include Helper::Client - include Lint::Lists + + def test_lpush + r.lpush "foo", "s1" + r.lpush "foo", "s2" + + assert_equal 2, r.llen("foo") + assert_equal "s2", r.lpop("foo") + end + + def test_variadic_lpush + target_version "2.3.9" do # 2.4-rc6 + assert_equal 3, r.lpush("foo", ["s1", "s2", "s3"]) + assert_equal 3, r.llen("foo") + assert_equal "s3", r.lpop("foo") + end + end + + def test_lpushx + r.lpushx "foo", "s1" + r.lpush "foo", "s2" + r.lpushx "foo", "s3" + + assert_equal 2, r.llen("foo") + assert_equal ["s3", "s2"], r.lrange("foo", 0, -1) + end + + def test_rpush + r.rpush "foo", "s1" + r.rpush "foo", "s2" + + assert_equal 2, r.llen("foo") + assert_equal "s2", r.rpop("foo") + end + + def test_variadic_rpush + target_version "2.3.9" do # 2.4-rc6 + assert_equal 3, r.rpush("foo", ["s1", "s2", "s3"]) + assert_equal 3, r.llen("foo") + assert_equal "s3", r.rpop("foo") + end + end + + def test_rpushx + r.rpushx "foo", "s1" + r.rpush "foo", "s2" + r.rpushx "foo", "s3" + + assert_equal 2, r.llen("foo") + assert_equal ["s2", "s3"], r.lrange("foo", 0, -1) + end + + def test_llen + r.rpush "foo", "s1" + r.rpush "foo", "s2" + + assert_equal 2, r.llen("foo") + end + + def test_lrange + r.rpush "foo", "s1" + r.rpush "foo", "s2" + r.rpush "foo", "s3" + + assert_equal ["s2", "s3"], r.lrange("foo", 1, -1) + assert_equal ["s1", "s2"], r.lrange("foo", 0, 1) + + assert_equal [], r.lrange("bar", 0, -1) + end + + def test_ltrim + r.rpush "foo", "s1" + r.rpush "foo", "s2" + r.rpush "foo", "s3" + + r.ltrim "foo", 0, 1 + + assert_equal 2, r.llen("foo") + assert_equal ["s1", "s2"], r.lrange("foo", 0, -1) + end + + def test_lindex + r.rpush "foo", "s1" + r.rpush "foo", "s2" + + assert_equal "s1", r.lindex("foo", 0) + assert_equal "s2", r.lindex("foo", 1) + end + + def test_lset + r.rpush "foo", "s1" + r.rpush "foo", "s2" + + assert_equal "s2", r.lindex("foo", 1) + assert r.lset("foo", 1, "s3") + assert_equal "s3", r.lindex("foo", 1) + + assert_raise Redis::CommandError do + r.lset("foo", 4, "s3") + end + end + + def test_lrem + r.rpush "foo", "s1" + r.rpush "foo", "s2" + + assert_equal 1, r.lrem("foo", 1, "s1") + assert_equal ["s2"], r.lrange("foo", 0, -1) + end + + def test_lpop + r.rpush "foo", "s1" + r.rpush "foo", "s2" + + assert_equal 2, r.llen("foo") + assert_equal "s1", r.lpop("foo") + assert_equal 1, r.llen("foo") + end + + def test_rpop + r.rpush "foo", "s1" + r.rpush "foo", "s2" + + assert_equal 2, r.llen("foo") + assert_equal "s2", r.rpop("foo") + assert_equal 1, r.llen("foo") + end + + def test_linsert + r.rpush "foo", "s1" + r.rpush "foo", "s3" + r.linsert "foo", :before, "s3", "s2" + + assert_equal ["s1", "s2", "s3"], r.lrange("foo", 0, -1) + + assert_raise(Redis::CommandError) do + r.linsert "foo", :anywhere, "s3", "s2" + end + end def test_rpoplpush r.rpush "foo", "s1" diff --git a/test/commands_on_sets_test.rb b/test/commands_on_sets_test.rb index cd186cd34..4a68ae9a5 100644 --- a/test/commands_on_sets_test.rb +++ b/test/commands_on_sets_test.rb @@ -1,10 +1,128 @@ require_relative "helper" -require_relative "lint/sets" class TestCommandsOnSets < Test::Unit::TestCase include Helper::Client - include Lint::Sets + + def test_sadd + assert_equal true, r.sadd("foo", "s1") + assert_equal true, r.sadd("foo", "s2") + assert_equal false, r.sadd("foo", "s1") + + assert_equal ["s1", "s2"], r.smembers("foo").sort + end + + def test_variadic_sadd + target_version "2.3.9" do # 2.4-rc6 + assert_equal 2, r.sadd("foo", ["s1", "s2"]) + assert_equal 1, r.sadd("foo", ["s1", "s2", "s3"]) + + assert_equal ["s1", "s2", "s3"], r.smembers("foo").sort + end + end + + def test_srem + r.sadd("foo", "s1") + r.sadd("foo", "s2") + + assert_equal true, r.srem("foo", "s1") + assert_equal false, r.srem("foo", "s3") + + assert_equal ["s2"], r.smembers("foo") + end + + def test_variadic_srem + target_version "2.3.9" do # 2.4-rc6 + r.sadd("foo", "s1") + r.sadd("foo", "s2") + r.sadd("foo", "s3") + + assert_equal 1, r.srem("foo", ["s1", "aaa"]) + assert_equal 0, r.srem("foo", ["bbb", "ccc" "ddd"]) + assert_equal 1, r.srem("foo", ["eee", "s3"]) + + assert_equal ["s2"], r.smembers("foo") + end + end + + def test_spop + r.sadd "foo", "s1" + r.sadd "foo", "s2" + + assert ["s1", "s2"].include?(r.spop("foo")) + assert ["s1", "s2"].include?(r.spop("foo")) + assert_equal nil, r.spop("foo") + end + + def test_scard + assert_equal 0, r.scard("foo") + + r.sadd "foo", "s1" + + assert_equal 1, r.scard("foo") + + r.sadd "foo", "s2" + + assert_equal 2, r.scard("foo") + end + + def test_sismember + assert_equal false, r.sismember("foo", "s1") + + r.sadd "foo", "s1" + + assert_equal true, r.sismember("foo", "s1") + assert_equal false, r.sismember("foo", "s2") + end + + def test_smembers + assert_equal [], r.smembers("foo") + + r.sadd "foo", "s1" + r.sadd "foo", "s2" + + assert_equal ["s1", "s2"], r.smembers("foo").sort + end + + def test_srandmember + r.sadd "foo", "s1" + r.sadd "foo", "s2" + + 4.times do + assert ["s1", "s2"].include?(r.srandmember("foo")) + end + + assert_equal 2, r.scard("foo") + end + + def test_srandmember_with_positive_count + r.sadd "foo", "s1" + r.sadd "foo", "s2" + r.sadd "foo", "s3" + r.sadd "foo", "s4" + + 4.times do + assert !(["s1", "s2", "s3", "s4"] & r.srandmember("foo", 3)).empty? + + assert_equal 3, r.srandmember("foo", 3).size + end + + assert_equal 4, r.scard("foo") + end + + def test_srandmember_with_negative_count + r.sadd "foo", "s1" + r.sadd "foo", "s2" + r.sadd "foo", "s3" + r.sadd "foo", "s4" + + 4.times do + assert !(["s1", "s2", "s3", "s4"] & r.srandmember("foo", -6)).empty? + assert_equal 6, r.srandmember("foo", -6).size + end + + assert_equal 4, r.scard("foo") + end def test_smove r.sadd "foo", "s1" diff --git a/test/commands_on_sorted_sets_test.rb b/test/commands_on_sorted_sets_test.rb index d10252902..6905690fc 100644 --- a/test/commands_on_sorted_sets_test.rb +++ b/test/commands_on_sorted_sets_test.rb @@ -1,10 +1,241 @@ require_relative "helper" -require_relative "lint/sorted_sets" class TestCommandsOnSortedSets < Test::Unit::TestCase include Helper::Client - include Lint::SortedSets + + Infinity = 1.0/0.0 + + def test_zadd + assert_equal 0, r.zcard("foo") + assert_equal true, r.zadd("foo", 1, "s1") + assert_equal false, r.zadd("foo", 1, "s1") + assert_equal 1, r.zcard("foo") + end + + def test_variadic_zadd + target_version "2.3.9" do # 2.4-rc6 + # Non-nested array with pairs + assert_equal 0, r.zcard("foo") + assert_equal 2, r.zadd("foo", [1, "s1", 2, "s2"]) + assert_equal 1, r.zadd("foo", [4, "s1", 5, "s2", 6, "s3"]) + assert_equal 3, r.zcard("foo") + r.del "foo" + + # Nested array with pairs + assert_equal 0, r.zcard("foo") + assert_equal 2, r.zadd("foo", [[1, "s1"], [2, "s2"]]) + assert_equal 1, r.zadd("foo", [[4, "s1"], [5, "s2"], [6, "s3"]]) + assert_equal 3, r.zcard("foo") + r.del "foo" + + # Wrong number of arguments + assert_raise(Redis::CommandError) { r.zadd("foo", ["bar"]) } + assert_raise(Redis::CommandError) { r.zadd("foo", ["bar", "qux", "zap"]) } + end + end + + def test_zrem + r.zadd("foo", 1, "s1") + r.zadd("foo", 2, "s2") + + assert_equal 2, r.zcard("foo") + assert_equal true, r.zrem("foo", "s1") + assert_equal false, r.zrem("foo", "s1") + assert_equal 1, r.zcard("foo") + end + + def test_variadic_zrem + target_version "2.3.9" do # 2.4-rc6 + r.zadd("foo", 1, "s1") + r.zadd("foo", 2, "s2") + r.zadd("foo", 3, "s3") + + assert_equal 3, r.zcard("foo") + assert_equal 1, r.zrem("foo", ["s1", "aaa"]) + assert_equal 0, r.zrem("foo", ["bbb", "ccc" "ddd"]) + assert_equal 1, r.zrem("foo", ["eee", "s3"]) + assert_equal 1, r.zcard("foo") + end + end + + def test_zincrby + rv = r.zincrby "foo", 1, "s1" + assert_equal 1.0, rv + + rv = r.zincrby "foo", 10, "s1" + assert_equal 11.0, rv + + rv = r.zincrby "bar", "-inf", "s1" + assert_equal(-Infinity, rv) + + rv = r.zincrby "bar", "+inf", "s2" + assert_equal(+Infinity, rv) + end + + def test_zrank + r.zadd "foo", 1, "s1" + r.zadd "foo", 2, "s2" + r.zadd "foo", 3, "s3" + + assert_equal 2, r.zrank("foo", "s3") + end + + def test_zrevrank + r.zadd "foo", 1, "s1" + r.zadd "foo", 2, "s2" + r.zadd "foo", 3, "s3" + + assert_equal 0, r.zrevrank("foo", "s3") + end + + def test_zrange + r.zadd "foo", 1, "s1" + r.zadd "foo", 2, "s2" + r.zadd "foo", 3, "s3" + + assert_equal ["s1", "s2"], r.zrange("foo", 0, 1) + assert_equal [["s1", 1.0], ["s2", 2.0]], r.zrange("foo", 0, 1, :with_scores => true) + assert_equal [["s1", 1.0], ["s2", 2.0]], r.zrange("foo", 0, 1, :withscores => true) + + r.zadd "bar", "-inf", "s1" + r.zadd "bar", "+inf", "s2" + assert_equal [["s1", -Infinity], ["s2", +Infinity]], r.zrange("bar", 0, 1, :with_scores => true) + assert_equal [["s1", -Infinity], ["s2", +Infinity]], r.zrange("bar", 0, 1, :withscores => true) + end + + def test_zrevrange + r.zadd "foo", 1, "s1" + r.zadd "foo", 2, "s2" + r.zadd "foo", 3, "s3" + + assert_equal ["s3", "s2"], r.zrevrange("foo", 0, 1) + assert_equal [["s3", 3.0], ["s2", 2.0]], r.zrevrange("foo", 0, 1, :with_scores => true) + assert_equal [["s3", 3.0], ["s2", 2.0]], r.zrevrange("foo", 0, 1, :withscores => true) + + r.zadd "bar", "-inf", "s1" + r.zadd "bar", "+inf", "s2" + assert_equal [["s2", +Infinity], ["s1", -Infinity]], r.zrevrange("bar", 0, 1, :with_scores => true) + assert_equal [["s2", +Infinity], ["s1", -Infinity]], r.zrevrange("bar", 0, 1, :withscores => true) + end + + def test_zrangebyscore + r.zadd "foo", 1, "s1" + r.zadd "foo", 2, "s2" + r.zadd "foo", 3, "s3" + + assert_equal ["s2", "s3"], r.zrangebyscore("foo", 2, 3) + end + + def test_zrevrangebyscore + r.zadd "foo", 1, "s1" + r.zadd "foo", 2, "s2" + r.zadd "foo", 3, "s3" + + assert_equal ["s3", "s2"], r.zrevrangebyscore("foo", 3, 2) + end + + def test_zrangebyscore_with_limit + r.zadd "foo", 1, "s1" + r.zadd "foo", 2, "s2" + r.zadd "foo", 3, "s3" + r.zadd "foo", 4, "s4" + + assert_equal ["s2"], r.zrangebyscore("foo", 2, 4, :limit => [0, 1]) + assert_equal ["s3"], r.zrangebyscore("foo", 2, 4, :limit => [1, 1]) + assert_equal ["s3", "s4"], r.zrangebyscore("foo", 2, 4, :limit => [1, 2]) + end + + def test_zrevrangebyscore_with_limit + r.zadd "foo", 1, "s1" + r.zadd "foo", 2, "s2" + r.zadd "foo", 3, "s3" + r.zadd "foo", 4, "s4" + + assert_equal ["s4"], r.zrevrangebyscore("foo", 4, 2, :limit => [0, 1]) + assert_equal ["s3"], r.zrevrangebyscore("foo", 4, 2, :limit => [1, 1]) + assert_equal ["s3", "s2"], r.zrevrangebyscore("foo", 4, 2, :limit => [1, 2]) + end + + def test_zrangebyscore_with_withscores + r.zadd "foo", 1, "s1" + r.zadd "foo", 2, "s2" + r.zadd "foo", 3, "s3" + r.zadd "foo", 4, "s4" + + assert_equal [["s2", 2.0]], r.zrangebyscore("foo", 2, 4, :limit => [0, 1], :with_scores => true) + assert_equal [["s3", 3.0]], r.zrangebyscore("foo", 2, 4, :limit => [1, 1], :with_scores => true) + assert_equal [["s2", 2.0]], r.zrangebyscore("foo", 2, 4, :limit => [0, 1], :withscores => true) + assert_equal [["s3", 3.0]], r.zrangebyscore("foo", 2, 4, :limit => [1, 1], :withscores => true) + + r.zadd "bar", "-inf", "s1" + r.zadd "bar", "+inf", "s2" + assert_equal [["s1", -Infinity]], r.zrangebyscore("bar", -Infinity, +Infinity, :limit => [0, 1], :with_scores => true) + assert_equal [["s2", +Infinity]], r.zrangebyscore("bar", -Infinity, +Infinity, :limit => [1, 1], :with_scores => true) + assert_equal [["s1", -Infinity]], r.zrangebyscore("bar", -Infinity, +Infinity, :limit => [0, 1], :withscores => true) + assert_equal [["s2", +Infinity]], r.zrangebyscore("bar", -Infinity, +Infinity, :limit => [1, 1], :withscores => true) + end + + def test_zrevrangebyscore_with_withscores + r.zadd "foo", 1, "s1" + r.zadd "foo", 2, "s2" + r.zadd "foo", 3, "s3" + r.zadd "foo", 4, "s4" + + assert_equal [["s4", 4.0]], r.zrevrangebyscore("foo", 4, 2, :limit => [0, 1], :with_scores => true) + assert_equal [["s3", 3.0]], r.zrevrangebyscore("foo", 4, 2, :limit => [1, 1], :with_scores => true) + assert_equal [["s4", 4.0]], r.zrevrangebyscore("foo", 4, 2, :limit => [0, 1], :withscores => true) + assert_equal [["s3", 3.0]], r.zrevrangebyscore("foo", 4, 2, :limit => [1, 1], :withscores => true) + + r.zadd "bar", "-inf", "s1" + r.zadd "bar", "+inf", "s2" + assert_equal [["s2", +Infinity]], r.zrevrangebyscore("bar", +Infinity, -Infinity, :limit => [0, 1], :with_scores => true) + assert_equal [["s1", -Infinity]], r.zrevrangebyscore("bar", +Infinity, -Infinity, :limit => [1, 1], :with_scores => true) + assert_equal [["s2", +Infinity]], r.zrevrangebyscore("bar", +Infinity, -Infinity, :limit => [0, 1], :withscores => true) + assert_equal [["s1", -Infinity]], r.zrevrangebyscore("bar", +Infinity, -Infinity, :limit => [1, 1], :withscores => true) + end + + def test_zcard + assert_equal 0, r.zcard("foo") + + r.zadd "foo", 1, "s1" + + assert_equal 1, r.zcard("foo") + end + + def test_zscore + r.zadd "foo", 1, "s1" + + assert_equal 1.0, r.zscore("foo", "s1") + + assert_equal nil, r.zscore("foo", "s2") + assert_equal nil, r.zscore("bar", "s1") + + r.zadd "bar", "-inf", "s1" + r.zadd "bar", "+inf", "s2" + assert_equal(-Infinity, r.zscore("bar", "s1")) + assert_equal(+Infinity, r.zscore("bar", "s2")) + end + + def test_zremrangebyrank + r.zadd "foo", 10, "s1" + r.zadd "foo", 20, "s2" + r.zadd "foo", 30, "s3" + r.zadd "foo", 40, "s4" + + assert_equal 3, r.zremrangebyrank("foo", 1, 3) + assert_equal ["s1"], r.zrange("foo", 0, -1) + end + + def test_zremrangebyscore + r.zadd "foo", 1, "s1" + r.zadd "foo", 2, "s2" + r.zadd "foo", 3, "s3" + r.zadd "foo", 4, "s4" + + assert_equal 3, r.zremrangebyscore("foo", 2, 4) + assert_equal ["s1"], r.zrange("foo", 0, -1) + end def test_zrangebylex target_version "2.8.9" do diff --git a/test/commands_on_strings_test.rb b/test/commands_on_strings_test.rb index 58fe7e510..ade13e31a 100644 --- a/test/commands_on_strings_test.rb +++ b/test/commands_on_strings_test.rb @@ -1,10 +1,249 @@ require_relative "helper" -require_relative "lint/strings" class TestCommandsOnStrings < Test::Unit::TestCase include Helper::Client - include Lint::Strings + + def test_set_and_get + r.set("foo", "s1") + + assert_equal "s1", r.get("foo") + end + + def test_set_and_get_with_newline_characters + r.set("foo", "1\n") + + assert_equal "1\n", r.get("foo") + end + + def test_set_and_get_with_non_string_value + value = ["a", "b"] + + r.set("foo", value) + + assert_equal value.to_s, r.get("foo") + end + + def test_set_and_get_with_ascii_characters + with_external_encoding("ASCII-8BIT") do + (0..255).each do |i| + str = "#{i.chr}---#{i.chr}" + r.set("foo", str) + + assert_equal str, r.get("foo") + end + end + end + + def test_set_with_ex + target_version "2.6.12" do + r.set("foo", "bar", :ex => 2) + assert_in_range 0..2, r.ttl("foo") + end + end + + def test_set_with_px + target_version "2.6.12" do + r.set("foo", "bar", :px => 2000) + assert_in_range 0..2, r.ttl("foo") + end + end + + def test_set_with_nx + target_version "2.6.12" do + r.set("foo", "qux", :nx => true) + assert !r.set("foo", "bar", :nx => true) + assert_equal "qux", r.get("foo") + + r.del("foo") + assert r.set("foo", "bar", :nx => true) + assert_equal "bar", r.get("foo") + end + end + + def test_set_with_xx + target_version "2.6.12" do + r.set("foo", "qux") + assert r.set("foo", "bar", :xx => true) + assert_equal "bar", r.get("foo") + + r.del("foo") + assert !r.set("foo", "bar", :xx => true) + end + end + + def test_setex + assert r.setex("foo", 1, "bar") + assert_equal "bar", r.get("foo") + assert [0, 1].include? r.ttl("foo") + end + + def test_setex_with_non_string_value + value = ["b", "a", "r"] + + assert r.setex("foo", 1, value) + assert_equal value.to_s, r.get("foo") + assert [0, 1].include? r.ttl("foo") + end + + def test_psetex + target_version "2.5.4" do + assert r.psetex("foo", 1000, "bar") + assert_equal "bar", r.get("foo") + assert [0, 1].include? r.ttl("foo") + end + end + + def test_psetex_with_non_string_value + target_version "2.5.4" do + value = ["b", "a", "r"] + + assert r.psetex("foo", 1000, value) + assert_equal value.to_s, r.get("foo") + assert [0, 1].include? r.ttl("foo") + end + end + + def test_getset + r.set("foo", "bar") + + assert_equal "bar", r.getset("foo", "baz") + assert_equal "baz", r.get("foo") + end + + def test_getset_with_non_string_value + r.set("foo", "zap") + + value = ["b", "a", "r"] + + assert_equal "zap", r.getset("foo", value) + assert_equal value.to_s, r.get("foo") + end + + def test_setnx + r.set("foo", "qux") + assert !r.setnx("foo", "bar") + assert_equal "qux", r.get("foo") + + r.del("foo") + assert r.setnx("foo", "bar") + assert_equal "bar", r.get("foo") + end + + def test_setnx_with_non_string_value + value = ["b", "a", "r"] + + r.set("foo", "qux") + assert !r.setnx("foo", value) + assert_equal "qux", r.get("foo") + + r.del("foo") + assert r.setnx("foo", value) + assert_equal value.to_s, r.get("foo") + end + + def test_incr + assert_equal 1, r.incr("foo") + assert_equal 2, r.incr("foo") + assert_equal 3, r.incr("foo") + end + + def test_incrby + assert_equal 1, r.incrby("foo", 1) + assert_equal 3, r.incrby("foo", 2) + assert_equal 6, r.incrby("foo", 3) + end + + def test_incrbyfloat + target_version "2.5.4" do + assert_equal 1.23, r.incrbyfloat("foo", 1.23) + assert_equal 2 , r.incrbyfloat("foo", 0.77) + assert_equal 1.9 , r.incrbyfloat("foo", -0.1) + end + end + + def test_decr + r.set("foo", 3) + + assert_equal 2, r.decr("foo") + assert_equal 1, r.decr("foo") + assert_equal 0, r.decr("foo") + end + + def test_decrby + r.set("foo", 6) + + assert_equal 3, r.decrby("foo", 3) + assert_equal 1, r.decrby("foo", 2) + assert_equal 0, r.decrby("foo", 1) + end + + def test_append + r.set "foo", "s" + r.append "foo", "1" + + assert_equal "s1", r.get("foo") + end + + def test_getbit + r.set("foo", "a") + + assert_equal 1, r.getbit("foo", 1) + assert_equal 1, r.getbit("foo", 2) + assert_equal 0, r.getbit("foo", 3) + assert_equal 0, r.getbit("foo", 4) + assert_equal 0, r.getbit("foo", 5) + assert_equal 0, r.getbit("foo", 6) + assert_equal 1, r.getbit("foo", 7) + end + + def test_setbit + r.set("foo", "a") + + r.setbit("foo", 6, 1) + + assert_equal "c", r.get("foo") + end + + def test_bitcount + target_version "2.5.10" do + r.set("foo", "abcde") + + assert_equal 10, r.bitcount("foo", 1, 3) + assert_equal 17, r.bitcount("foo", 0, -1) + end + end + + def test_getrange + r.set("foo", "abcde") + + assert_equal "bcd", r.getrange("foo", 1, 3) + assert_equal "abcde", r.getrange("foo", 0, -1) + end + + def test_setrange + r.set("foo", "abcde") + + r.setrange("foo", 1, "bar") + + assert_equal "abare", r.get("foo") + end + + def test_setrange_with_non_string_value + r.set("foo", "abcde") + + value = ["b", "a", "r"] + + r.setrange("foo", 2, value) + + assert_equal "ab#{value.to_s}", r.get("foo") + end + + def test_strlen + r.set "foo", "lorem" + + assert_equal 5, r.strlen("foo") + end def test_mget r.set("foo", "s1") diff --git a/test/commands_on_value_types_test.rb b/test/commands_on_value_types_test.rb index 8eb32b56b..5241835e7 100644 --- a/test/commands_on_value_types_test.rb +++ b/test/commands_on_value_types_test.rb @@ -1,10 +1,125 @@ require_relative "helper" -require_relative "lint/value_types" class TestCommandsOnValueTypes < Test::Unit::TestCase include Helper::Client - include Lint::ValueTypes + + def test_exists + assert_equal false, r.exists("foo") + + r.set("foo", "s1") + + assert_equal true, r.exists("foo") + end + + def test_type + assert_equal "none", r.type("foo") + + r.set("foo", "s1") + + assert_equal "string", r.type("foo") + end + + def test_keys + r.set("f", "s1") + r.set("fo", "s2") + r.set("foo", "s3") + + assert_equal ["f","fo", "foo"], r.keys("f*").sort + end + + def test_expire + r.set("foo", "s1") + assert r.expire("foo", 2) + assert_in_range 0..2, r.ttl("foo") + end + + def test_pexpire + target_version "2.5.4" do + r.set("foo", "s1") + assert r.pexpire("foo", 2000) + assert_in_range 0..2, r.ttl("foo") + end + end + + def test_expireat + r.set("foo", "s1") + assert r.expireat("foo", (Time.now + 2).to_i) + assert_in_range 0..2, r.ttl("foo") + end + + def test_pexpireat + target_version "2.5.4" do + r.set("foo", "s1") + assert r.pexpireat("foo", (Time.now + 2).to_i * 1_000) + assert_in_range 0..2, r.ttl("foo") + end + end + + def test_persist + r.set("foo", "s1") + r.expire("foo", 1) + r.persist("foo") + + assert(-1 == r.ttl("foo")) + end + + def test_ttl + r.set("foo", "s1") + r.expire("foo", 2) + assert_in_range 0..2, r.ttl("foo") + end + + def test_pttl + target_version "2.5.4" do + r.set("foo", "s1") + r.expire("foo", 2) + assert_in_range 1..2000, r.pttl("foo") + end + end + + def test_dump_and_restore + target_version "2.5.7" do + r.set("foo", "a") + v = r.dump("foo") + r.del("foo") + + assert r.restore("foo", 1000, v) + assert_equal "a", r.get("foo") + assert [0, 1].include? r.ttl("foo") + + r.rpush("bar", ["b", "c", "d"]) + w = r.dump("bar") + r.del("bar") + + assert r.restore("bar", 1000, w) + assert_equal ["b", "c", "d"], r.lrange("bar", 0, -1) + assert [0, 1].include? r.ttl("bar") + end + end + + def test_move + r.select 14 + r.flushdb + + r.set "bar", "s3" + + r.select 15 + + r.set "foo", "s1" + r.set "bar", "s2" + + assert r.move("foo", 14) + assert_equal nil, r.get("foo") + + assert !r.move("bar", 14) + assert_equal "s2", r.get("bar") + + r.select 14 + + assert_equal "s1", r.get("foo") + assert_equal "s3", r.get("bar") + end def test_del r.set "foo", "s1" diff --git a/test/distributed_blocking_commands_test.rb b/test/distributed_blocking_commands_test.rb deleted file mode 100644 index f03f45b09..000000000 --- a/test/distributed_blocking_commands_test.rb +++ /dev/null @@ -1,44 +0,0 @@ -require_relative "helper" -require_relative "lint/blocking_commands" - -class TestDistributedBlockingCommands < Test::Unit::TestCase - - include Helper::Distributed - include Lint::BlockingCommands - - def test_blpop_raises - assert_raises(Redis::Distributed::CannotDistribute) do - r.blpop(["foo", "bar"]) - end - end - - def test_blpop_raises_with_old_prototype - assert_raises(Redis::Distributed::CannotDistribute) do - r.blpop("foo", "bar", 0) - end - end - - def test_brpop_raises - assert_raises(Redis::Distributed::CannotDistribute) do - r.brpop(["foo", "bar"]) - end - end - - def test_brpop_raises_with_old_prototype - assert_raises(Redis::Distributed::CannotDistribute) do - r.brpop("foo", "bar", 0) - end - end - - def test_brpoplpush_raises - assert_raises(Redis::Distributed::CannotDistribute) do - r.brpoplpush("foo", "bar") - end - end - - def test_brpoplpush_raises_with_old_prototype - assert_raises(Redis::Distributed::CannotDistribute) do - r.brpoplpush("foo", "bar", 0) - end - end -end diff --git a/test/distributed_commands_on_hashes_test.rb b/test/distributed_commands_on_hashes_test.rb deleted file mode 100644 index 732fef64c..000000000 --- a/test/distributed_commands_on_hashes_test.rb +++ /dev/null @@ -1,8 +0,0 @@ -require_relative "helper" -require_relative "lint/hashes" - -class TestDistributedCommandsOnHashes < Test::Unit::TestCase - - include Helper::Distributed - include Lint::Hashes -end diff --git a/test/distributed_commands_on_hyper_log_log_test.rb b/test/distributed_commands_on_hyper_log_log_test.rb deleted file mode 100644 index a6b7110f7..000000000 --- a/test/distributed_commands_on_hyper_log_log_test.rb +++ /dev/null @@ -1,31 +0,0 @@ -require_relative "helper" -require_relative "lint/hyper_log_log" - -class TestDistributedCommandsOnHyperLogLog < Test::Unit::TestCase - - include Helper::Distributed - include Lint::HyperLogLog - - def test_pfmerge - target_version "2.8.9" do - assert_raise Redis::Distributed::CannotDistribute do - r.pfadd "foo", "s1" - r.pfadd "bar", "s2" - - assert r.pfmerge("res", "foo", "bar") - end - end - end - - def test_pfcount_multiple_keys_diff_nodes - target_version "2.8.9" do - assert_raise Redis::Distributed::CannotDistribute do - r.pfadd "foo", "s1" - r.pfadd "bar", "s2" - - assert r.pfcount("res", "foo", "bar") - end - end - end - -end diff --git a/test/distributed_commands_on_lists_test.rb b/test/distributed_commands_on_lists_test.rb deleted file mode 100644 index dd629bc2f..000000000 --- a/test/distributed_commands_on_lists_test.rb +++ /dev/null @@ -1,20 +0,0 @@ -require_relative "helper" -require_relative "lint/lists" - -class TestDistributedCommandsOnLists < Test::Unit::TestCase - - include Helper::Distributed - include Lint::Lists - - def test_rpoplpush - assert_raise Redis::Distributed::CannotDistribute do - r.rpoplpush("foo", "bar") - end - end - - def test_brpoplpush - assert_raise Redis::Distributed::CannotDistribute do - r.brpoplpush("foo", "bar", :timeout => 1) - end - end -end diff --git a/test/distributed_commands_on_sets_test.rb b/test/distributed_commands_on_sets_test.rb deleted file mode 100644 index c7180e6ac..000000000 --- a/test/distributed_commands_on_sets_test.rb +++ /dev/null @@ -1,81 +0,0 @@ -require_relative "helper" -require_relative "lint/sets" - -class TestDistributedCommandsOnSets < Test::Unit::TestCase - - include Helper::Distributed - include Lint::Sets - - def test_smove - assert_raise Redis::Distributed::CannotDistribute do - r.sadd "foo", "s1" - r.sadd "bar", "s2" - - r.smove("foo", "bar", "s1") - end - end - - def test_sinter - assert_raise Redis::Distributed::CannotDistribute do - r.sadd "foo", "s1" - r.sadd "foo", "s2" - r.sadd "bar", "s2" - - r.sinter("foo", "bar") - end - end - - def test_sinterstore - assert_raise Redis::Distributed::CannotDistribute do - r.sadd "foo", "s1" - r.sadd "foo", "s2" - r.sadd "bar", "s2" - - r.sinterstore("baz", "foo", "bar") - end - end - - def test_sunion - assert_raise Redis::Distributed::CannotDistribute do - r.sadd "foo", "s1" - r.sadd "foo", "s2" - r.sadd "bar", "s2" - r.sadd "bar", "s3" - - r.sunion("foo", "bar") - end - end - - def test_sunionstore - assert_raise Redis::Distributed::CannotDistribute do - r.sadd "foo", "s1" - r.sadd "foo", "s2" - r.sadd "bar", "s2" - r.sadd "bar", "s3" - - r.sunionstore("baz", "foo", "bar") - end - end - - def test_sdiff - assert_raise Redis::Distributed::CannotDistribute do - r.sadd "foo", "s1" - r.sadd "foo", "s2" - r.sadd "bar", "s2" - r.sadd "bar", "s3" - - r.sdiff("foo", "bar") - end - end - - def test_sdiffstore - assert_raise Redis::Distributed::CannotDistribute do - r.sadd "foo", "s1" - r.sadd "foo", "s2" - r.sadd "bar", "s2" - r.sadd "bar", "s3" - - r.sdiffstore("baz", "foo", "bar") - end - end -end diff --git a/test/distributed_commands_on_sorted_sets_test.rb b/test/distributed_commands_on_sorted_sets_test.rb deleted file mode 100644 index ae23a6c83..000000000 --- a/test/distributed_commands_on_sorted_sets_test.rb +++ /dev/null @@ -1,16 +0,0 @@ -require_relative "helper" -require_relative "lint/sorted_sets" - -class TestDistributedCommandsOnSortedSets < Test::Unit::TestCase - - include Helper::Distributed - include Lint::SortedSets - - def test_zcount - r.zadd "foo", 1, "s1" - r.zadd "foo", 2, "s2" - r.zadd "foo", 3, "s3" - - assert_equal 2, r.zcount("foo", 2, 3) - end -end diff --git a/test/distributed_commands_on_strings_test.rb b/test/distributed_commands_on_strings_test.rb deleted file mode 100644 index 5b964684f..000000000 --- a/test/distributed_commands_on_strings_test.rb +++ /dev/null @@ -1,57 +0,0 @@ -require_relative "helper" -require_relative "lint/strings" - -class TestDistributedCommandsOnStrings < Test::Unit::TestCase - - include Helper::Distributed - include Lint::Strings - - def test_mget - assert_raise Redis::Distributed::CannotDistribute do - r.mget("foo", "bar") - end - end - - def test_mget_mapped - assert_raise Redis::Distributed::CannotDistribute do - r.mapped_mget("foo", "bar") - end - end - - def test_mset - assert_raise Redis::Distributed::CannotDistribute do - r.mset(:foo, "s1", :bar, "s2") - end - end - - def test_mset_mapped - assert_raise Redis::Distributed::CannotDistribute do - r.mapped_mset(:foo => "s1", :bar => "s2") - end - end - - def test_msetnx - assert_raise Redis::Distributed::CannotDistribute do - r.set("foo", "s1") - r.msetnx(:foo, "s2", :bar, "s3") - end - end - - def test_msetnx_mapped - assert_raise Redis::Distributed::CannotDistribute do - r.set("foo", "s1") - r.mapped_msetnx(:foo => "s2", :bar => "s3") - end - end - - def test_bitop - target_version "2.5.10" do - assert_raise Redis::Distributed::CannotDistribute do - r.set("foo", "a") - r.set("bar", "b") - - r.bitop(:and, "foo&bar", "foo", "bar") - end - end - end -end diff --git a/test/distributed_commands_on_value_types_test.rb b/test/distributed_commands_on_value_types_test.rb deleted file mode 100644 index b360dbe98..000000000 --- a/test/distributed_commands_on_value_types_test.rb +++ /dev/null @@ -1,93 +0,0 @@ -require_relative "helper" -require_relative "lint/value_types" - -class TestDistributedCommandsOnValueTypes < Test::Unit::TestCase - - include Helper::Distributed - include Lint::ValueTypes - - def test_del - r.set "foo", "s1" - r.set "bar", "s2" - r.set "baz", "s3" - - assert_equal ["bar", "baz", "foo"], r.keys("*").sort - - assert_equal 1, r.del("foo") - - assert_equal ["bar", "baz"], r.keys("*").sort - - assert_equal 2, r.del("bar", "baz") - - assert_equal [], r.keys("*").sort - end - - def test_del_with_array_argument - r.set "foo", "s1" - r.set "bar", "s2" - r.set "baz", "s3" - - assert_equal ["bar", "baz", "foo"], r.keys("*").sort - - assert_equal 1, r.del(["foo"]) - - assert_equal ["bar", "baz"], r.keys("*").sort - - assert_equal 2, r.del(["bar", "baz"]) - - assert_equal [], r.keys("*").sort - end - - def test_randomkey - assert_raise Redis::Distributed::CannotDistribute do - r.randomkey - end - end - - def test_rename - assert_raise Redis::Distributed::CannotDistribute do - r.set("foo", "s1") - r.rename "foo", "bar" - end - - assert_equal "s1", r.get("foo") - assert_equal nil, r.get("bar") - end - - def test_renamenx - assert_raise Redis::Distributed::CannotDistribute do - r.set("foo", "s1") - r.rename "foo", "bar" - end - - assert_equal "s1", r.get("foo") - assert_equal nil , r.get("bar") - end - - def test_dbsize - assert_equal [0], r.dbsize - - r.set("foo", "s1") - - assert_equal [1], r.dbsize - end - - def test_flushdb - r.set("foo", "s1") - r.set("bar", "s2") - - assert_equal [2], r.dbsize - - r.flushdb - - assert_equal [0], r.dbsize - end - - def test_migrate - r.set("foo", "s1") - - assert_raise Redis::Distributed::CannotDistribute do - r.migrate("foo", {}) - end - end -end diff --git a/test/distributed_commands_requiring_clustering_test.rb b/test/distributed_commands_requiring_clustering_test.rb deleted file mode 100644 index dc5c6ed3f..000000000 --- a/test/distributed_commands_requiring_clustering_test.rb +++ /dev/null @@ -1,162 +0,0 @@ -require_relative "helper" - -class TestDistributedCommandsRequiringClustering < Test::Unit::TestCase - - include Helper::Distributed - - def test_rename - r.set("{qux}foo", "s1") - r.rename "{qux}foo", "{qux}bar" - - assert_equal "s1", r.get("{qux}bar") - assert_equal nil, r.get("{qux}foo") - end - - def test_renamenx - r.set("{qux}foo", "s1") - r.set("{qux}bar", "s2") - - assert_equal false, r.renamenx("{qux}foo", "{qux}bar") - - assert_equal "s1", r.get("{qux}foo") - assert_equal "s2", r.get("{qux}bar") - end - - def test_brpoplpush - r.rpush "{qux}foo", "s1" - r.rpush "{qux}foo", "s2" - - assert_equal "s2", r.brpoplpush("{qux}foo", "{qux}bar", :timeout => 1) - assert_equal ["s2"], r.lrange("{qux}bar", 0, -1) - end - - def test_rpoplpush - r.rpush "{qux}foo", "s1" - r.rpush "{qux}foo", "s2" - - assert_equal "s2", r.rpoplpush("{qux}foo", "{qux}bar") - assert_equal ["s2"], r.lrange("{qux}bar", 0, -1) - assert_equal "s1", r.rpoplpush("{qux}foo", "{qux}bar") - assert_equal ["s1", "s2"], r.lrange("{qux}bar", 0, -1) - end - - def test_smove - r.sadd "{qux}foo", "s1" - r.sadd "{qux}bar", "s2" - - assert r.smove("{qux}foo", "{qux}bar", "s1") - assert r.sismember("{qux}bar", "s1") - end - - def test_sinter - r.sadd "{qux}foo", "s1" - r.sadd "{qux}foo", "s2" - r.sadd "{qux}bar", "s2" - - assert_equal ["s2"], r.sinter("{qux}foo", "{qux}bar") - end - - def test_sinterstore - r.sadd "{qux}foo", "s1" - r.sadd "{qux}foo", "s2" - r.sadd "{qux}bar", "s2" - - r.sinterstore("{qux}baz", "{qux}foo", "{qux}bar") - - assert_equal ["s2"], r.smembers("{qux}baz") - end - - def test_sunion - r.sadd "{qux}foo", "s1" - r.sadd "{qux}foo", "s2" - r.sadd "{qux}bar", "s2" - r.sadd "{qux}bar", "s3" - - assert_equal ["s1", "s2", "s3"], r.sunion("{qux}foo", "{qux}bar").sort - end - - def test_sunionstore - r.sadd "{qux}foo", "s1" - r.sadd "{qux}foo", "s2" - r.sadd "{qux}bar", "s2" - r.sadd "{qux}bar", "s3" - - r.sunionstore("{qux}baz", "{qux}foo", "{qux}bar") - - assert_equal ["s1", "s2", "s3"], r.smembers("{qux}baz").sort - end - - def test_sdiff - r.sadd "{qux}foo", "s1" - r.sadd "{qux}foo", "s2" - r.sadd "{qux}bar", "s2" - r.sadd "{qux}bar", "s3" - - assert_equal ["s1"], r.sdiff("{qux}foo", "{qux}bar") - assert_equal ["s3"], r.sdiff("{qux}bar", "{qux}foo") - end - - def test_sdiffstore - r.sadd "{qux}foo", "s1" - r.sadd "{qux}foo", "s2" - r.sadd "{qux}bar", "s2" - r.sadd "{qux}bar", "s3" - - r.sdiffstore("{qux}baz", "{qux}foo", "{qux}bar") - - assert_equal ["s1"], r.smembers("{qux}baz") - end - - def test_sort - r.set("{qux}foo:1", "s1") - r.set("{qux}foo:2", "s2") - - r.rpush("{qux}bar", "1") - r.rpush("{qux}bar", "2") - - assert_equal ["s1"], r.sort("{qux}bar", :get => "{qux}foo:*", :limit => [0, 1]) - assert_equal ["s2"], r.sort("{qux}bar", :get => "{qux}foo:*", :limit => [0, 1], :order => "desc alpha") - end - - def test_sort_with_an_array_of_gets - r.set("{qux}foo:1:a", "s1a") - r.set("{qux}foo:1:b", "s1b") - - r.set("{qux}foo:2:a", "s2a") - r.set("{qux}foo:2:b", "s2b") - - r.rpush("{qux}bar", "1") - r.rpush("{qux}bar", "2") - - assert_equal [["s1a", "s1b"]], r.sort("{qux}bar", :get => ["{qux}foo:*:a", "{qux}foo:*:b"], :limit => [0, 1]) - assert_equal [["s2a", "s2b"]], r.sort("{qux}bar", :get => ["{qux}foo:*:a", "{qux}foo:*:b"], :limit => [0, 1], :order => "desc alpha") - assert_equal [["s1a", "s1b"], ["s2a", "s2b"]], r.sort("{qux}bar", :get => ["{qux}foo:*:a", "{qux}foo:*:b"]) - end - - def test_sort_with_store - r.set("{qux}foo:1", "s1") - r.set("{qux}foo:2", "s2") - - r.rpush("{qux}bar", "1") - r.rpush("{qux}bar", "2") - - r.sort("{qux}bar", :get => "{qux}foo:*", :store => "{qux}baz") - assert_equal ["s1", "s2"], r.lrange("{qux}baz", 0, -1) - end - - def test_bitop - target_version "2.5.10" do - r.set("{qux}foo", "a") - r.set("{qux}bar", "b") - - r.bitop(:and, "{qux}foo&bar", "{qux}foo", "{qux}bar") - assert_equal "\x60", r.get("{qux}foo&bar") - r.bitop(:or, "{qux}foo|bar", "{qux}foo", "{qux}bar") - assert_equal "\x63", r.get("{qux}foo|bar") - r.bitop(:xor, "{qux}foo^bar", "{qux}foo", "{qux}bar") - assert_equal "\x03", r.get("{qux}foo^bar") - r.bitop(:not, "{qux}~foo", "{qux}foo") - assert_equal "\x9E", r.get("{qux}~foo") - end - end -end diff --git a/test/distributed_connection_handling_test.rb b/test/distributed_connection_handling_test.rb deleted file mode 100644 index 335046abe..000000000 --- a/test/distributed_connection_handling_test.rb +++ /dev/null @@ -1,21 +0,0 @@ -require_relative "helper" - -class TestDistributedConnectionHandling < Test::Unit::TestCase - - include Helper::Distributed - - def test_ping - assert_equal ["PONG"], r.ping - end - - def test_select - r.set "foo", "bar" - - r.select 14 - assert_equal nil, r.get("foo") - - r.select 15 - - assert_equal "bar", r.get("foo") - end -end diff --git a/test/distributed_internals_test.rb b/test/distributed_internals_test.rb deleted file mode 100644 index c755a8afd..000000000 --- a/test/distributed_internals_test.rb +++ /dev/null @@ -1,68 +0,0 @@ -require_relative "helper" - -class TestDistributedInternals < Test::Unit::TestCase - - include Helper::Distributed - - def test_provides_a_meaningful_inspect - nodes = ["redis://127.0.0.1:#{PORT}/15", *NODES] - redis = Redis::Distributed.new nodes - - assert_equal "#", redis.inspect - end - - def test_default_as_urls - nodes = ["redis://127.0.0.1:#{PORT}/15", *NODES] - redis = Redis::Distributed.new nodes - assert_equal ["redis://127.0.0.1:#{PORT}/15", *NODES], redis.nodes.map { |node| node.client.id} - end - - def test_default_as_config_hashes - nodes = [OPTIONS.merge(:host => '127.0.0.1'), OPTIONS.merge(:host => 'somehost', :port => PORT.next)] - redis = Redis::Distributed.new nodes - assert_equal ["redis://127.0.0.1:#{PORT}/15","redis://somehost:#{PORT.next}/15"], redis.nodes.map { |node| node.client.id } - end - - def test_as_mix_and_match - nodes = ["redis://127.0.0.1:7389/15", OPTIONS.merge(:host => 'somehost'), OPTIONS.merge(:host => 'somehost', :port => PORT.next)] - redis = Redis::Distributed.new nodes - assert_equal ["redis://127.0.0.1:7389/15", "redis://somehost:#{PORT}/15", "redis://somehost:#{PORT.next}/15"], redis.nodes.map { |node| node.client.id } - end - - def test_override_id - nodes = [OPTIONS.merge(:host => '127.0.0.1', :id => "test"), OPTIONS.merge( :host => 'somehost', :port => PORT.next, :id => "test1")] - redis = Redis::Distributed.new nodes - assert_equal redis.nodes.first.client.id, "test" - assert_equal redis.nodes.last.client.id, "test1" - assert_equal "#", redis.inspect - end - - def test_can_be_duped_to_create_a_new_connection - redis = Redis::Distributed.new(NODES) - - clients = redis.info[0]["connected_clients"].to_i - - r2 = redis.dup - r2.ping - - assert_equal clients + 1, redis.info[0]["connected_clients"].to_i - end - - def test_keeps_options_after_dup - r1 = Redis::Distributed.new(NODES, :tag => /^(\w+):/) - - assert_raise(Redis::Distributed::CannotDistribute) do - r1.sinter("foo", "bar") - end - - assert_equal [], r1.sinter("baz:foo", "baz:bar") - - r2 = r1.dup - - assert_raise(Redis::Distributed::CannotDistribute) do - r2.sinter("foo", "bar") - end - - assert_equal [], r2.sinter("baz:foo", "baz:bar") - end -end diff --git a/test/distributed_key_tags_test.rb b/test/distributed_key_tags_test.rb deleted file mode 100644 index a778fec72..000000000 --- a/test/distributed_key_tags_test.rb +++ /dev/null @@ -1,50 +0,0 @@ -require_relative "helper" - -class TestDistributedKeyTags < Test::Unit::TestCase - - include Helper - include Helper::Distributed - - def test_hashes_consistently - r1 = Redis::Distributed.new ["redis://127.0.0.1:#{PORT}/15", *NODES] - r2 = Redis::Distributed.new ["redis://127.0.0.1:#{PORT}/15", *NODES] - r3 = Redis::Distributed.new ["redis://127.0.0.1:#{PORT}/15", *NODES] - - assert_equal r1.node_for("foo").id, r2.node_for("foo").id - assert_equal r1.node_for("foo").id, r3.node_for("foo").id - end - - def test_allows_clustering_of_keys - r = Redis::Distributed.new(NODES) - r.add_node("redis://127.0.0.1:#{PORT}/14") - r.flushdb - - 100.times do |i| - r.set "{foo}users:#{i}", i - end - - assert_equal [0, 100], r.nodes.map { |node| node.keys.size } - end - - def test_distributes_keys_if_no_clustering_is_used - r.add_node("redis://127.0.0.1:#{PORT}/14") - r.flushdb - - r.set "users:1", 1 - r.set "users:4", 4 - - assert_equal [1, 1], r.nodes.map { |node| node.keys.size } - end - - def test_allows_passing_a_custom_tag_extractor - r = Redis::Distributed.new(NODES, :tag => /^(.+?):/) - r.add_node("redis://127.0.0.1:#{PORT}/14") - r.flushdb - - 100.times do |i| - r.set "foo:users:#{i}", i - end - - assert_equal [0, 100], r.nodes.map { |node| node.keys.size } - end -end diff --git a/test/distributed_persistence_control_commands_test.rb b/test/distributed_persistence_control_commands_test.rb deleted file mode 100644 index 2d844258a..000000000 --- a/test/distributed_persistence_control_commands_test.rb +++ /dev/null @@ -1,24 +0,0 @@ -require_relative "helper" - -class TestDistributedPersistenceControlCommands < Test::Unit::TestCase - - include Helper::Distributed - - def test_save - redis_mock(:save => lambda { "+SAVE" }) do |redis| - assert_equal ["SAVE"], redis.save - end - end - - def test_bgsave - redis_mock(:bgsave => lambda { "+BGSAVE" }) do |redis| - assert_equal ["BGSAVE"], redis.bgsave - end - end - - def test_lastsave - redis_mock(:lastsave => lambda { "+LASTSAVE" }) do |redis| - assert_equal ["LASTSAVE"], redis.lastsave - end - end -end diff --git a/test/distributed_publish_subscribe_test.rb b/test/distributed_publish_subscribe_test.rb deleted file mode 100644 index a5fcfa53f..000000000 --- a/test/distributed_publish_subscribe_test.rb +++ /dev/null @@ -1,90 +0,0 @@ -require_relative "helper" - -class TestDistributedPublishSubscribe < Test::Unit::TestCase - - include Helper::Distributed - - def test_subscribe_and_unsubscribe - assert_raise Redis::Distributed::CannotDistribute do - r.subscribe("foo", "bar") { } - end - - assert_raise Redis::Distributed::CannotDistribute do - r.subscribe("{qux}foo", "bar") { } - end - end - - def test_subscribe_and_unsubscribe_with_tags - @subscribed = false - @unsubscribed = false - - wire = Wire.new do - r.subscribe("foo") do |on| - on.subscribe do |channel, total| - @subscribed = true - @t1 = total - end - - on.message do |channel, message| - if message == "s1" - r.unsubscribe - @message = message - end - end - - on.unsubscribe do |channel, total| - @unsubscribed = true - @t2 = total - end - end - end - - # Wait until the subscription is active before publishing - Wire.pass while !@subscribed - - Redis::Distributed.new(NODES).publish("foo", "s1") - - wire.join - - assert @subscribed - assert_equal 1, @t1 - assert @unsubscribed - assert_equal 0, @t2 - assert_equal "s1", @message - end - - def test_subscribe_within_subscribe - @channels = [] - - wire = Wire.new do - r.subscribe("foo") do |on| - on.subscribe do |channel, total| - @channels << channel - - r.subscribe("bar") if channel == "foo" - r.unsubscribe if channel == "bar" - end - end - end - - wire.join - - assert_equal ["foo", "bar"], @channels - end - - def test_other_commands_within_a_subscribe - assert_raise Redis::CommandError do - r.subscribe("foo") do |on| - on.subscribe do |channel, total| - r.set("bar", "s2") - end - end - end - end - - def test_subscribe_without_a_block - assert_raise LocalJumpError do - r.subscribe("foo") - end - end -end diff --git a/test/distributed_remote_server_control_commands_test.rb b/test/distributed_remote_server_control_commands_test.rb deleted file mode 100644 index 66ec349f8..000000000 --- a/test/distributed_remote_server_control_commands_test.rb +++ /dev/null @@ -1,64 +0,0 @@ -require_relative "helper" - -class TestDistributedRemoteServerControlCommands < Test::Unit::TestCase - - include Helper::Distributed - - def test_info - keys = [ - "redis_version", - "uptime_in_seconds", - "uptime_in_days", - "connected_clients", - "used_memory", - "total_connections_received", - "total_commands_processed", - ] - - infos = r.info - - infos.each do |info| - keys.each do |k| - msg = "expected #info to include #{k}" - assert info.keys.include?(k), msg - end - end - end - - def test_info_commandstats - target_version "2.5.7" do - r.nodes.each { |n| n.config(:resetstat) } - r.ping # Executed on every node - - r.info(:commandstats).each do |info| - assert_equal "1", info["ping"]["calls"] - end - end - end - - def test_monitor - begin - r.monitor - rescue Exception => ex - ensure - assert ex.kind_of?(NotImplementedError) - end - end - - def test_echo - assert_equal ["foo bar baz\n"], r.echo("foo bar baz\n") - end - - def test_time - target_version "2.5.4" do - # Test that the difference between the time that Ruby reports and the time - # that Redis reports is minimal (prevents the test from being racy). - r.time.each do |rv| - redis_usec = rv[0] * 1_000_000 + rv[1] - ruby_usec = Integer(Time.now.to_f * 1_000_000) - - assert 500_000 > (ruby_usec - redis_usec).abs - end - end - end -end diff --git a/test/distributed_scripting_test.rb b/test/distributed_scripting_test.rb deleted file mode 100644 index 224ab2b05..000000000 --- a/test/distributed_scripting_test.rb +++ /dev/null @@ -1,100 +0,0 @@ -require_relative "helper" - -class TestDistributedScripting < Test::Unit::TestCase - - include Helper::Distributed - - def to_sha(script) - r.script(:load, script).first - end - - def test_script_exists - target_version "2.5.9" do # 2.6-rc1 - a = to_sha("return 1") - b = a.succ - - assert_equal [true], r.script(:exists, a) - assert_equal [false], r.script(:exists, b) - assert_equal [[true]], r.script(:exists, [a]) - assert_equal [[false]], r.script(:exists, [b]) - assert_equal [[true, false]], r.script(:exists, [a, b]) - end - end - - def test_script_flush - target_version "2.5.9" do # 2.6-rc1 - sha = to_sha("return 1") - assert r.script(:exists, sha).first - assert_equal ["OK"], r.script(:flush) - assert !r.script(:exists, sha).first - end - end - - def test_script_kill - target_version "2.5.9" do # 2.6-rc1 - redis_mock(:script => lambda { |arg| "+#{arg.upcase}" }) do |redis| - assert_equal ["KILL"], redis.script(:kill) - end - end - end - - def test_eval - target_version "2.5.9" do # 2.6-rc1 - assert_raises(Redis::Distributed::CannotDistribute) do - r.eval("return #KEYS") - end - - assert_raises(Redis::Distributed::CannotDistribute) do - r.eval("return KEYS", ["k1", "k2"]) - end - - assert_equal ["k1"], r.eval("return KEYS", ["k1"]) - assert_equal ["a1", "a2"], r.eval("return ARGV", ["k1"], ["a1", "a2"]) - end - end - - def test_eval_with_options_hash - target_version "2.5.9" do # 2.6-rc1 - assert_raises(Redis::Distributed::CannotDistribute) do - r.eval("return #KEYS", {}) - end - - assert_raises(Redis::Distributed::CannotDistribute) do - r.eval("return KEYS", { :keys => ["k1", "k2"] }) - end - - assert_equal ["k1"], r.eval("return KEYS", { :keys => ["k1"] }) - assert_equal ["a1", "a2"], r.eval("return ARGV", { :keys => ["k1"], :argv => ["a1", "a2"] }) - end - end - - def test_evalsha - target_version "2.5.9" do # 2.6-rc1 - assert_raises(Redis::Distributed::CannotDistribute) do - r.evalsha(to_sha("return #KEYS")) - end - - assert_raises(Redis::Distributed::CannotDistribute) do - r.evalsha(to_sha("return KEYS"), ["k1", "k2"]) - end - - assert_equal ["k1"], r.evalsha(to_sha("return KEYS"), ["k1"]) - assert_equal ["a1", "a2"], r.evalsha(to_sha("return ARGV"), ["k1"], ["a1", "a2"]) - end - end - - def test_evalsha_with_options_hash - target_version "2.5.9" do # 2.6-rc1 - assert_raises(Redis::Distributed::CannotDistribute) do - r.evalsha(to_sha("return #KEYS"), {}) - end - - assert_raises(Redis::Distributed::CannotDistribute) do - r.evalsha(to_sha("return KEYS"), { :keys => ["k1", "k2"] }) - end - - assert_equal ["k1"], r.evalsha(to_sha("return KEYS"), { :keys => ["k1"] }) - assert_equal ["a1", "a2"], r.evalsha(to_sha("return ARGV"), { :keys => ["k1"], :argv => ["a1", "a2"] }) - end - end -end diff --git a/test/distributed_sorting_test.rb b/test/distributed_sorting_test.rb deleted file mode 100644 index 7afb670b9..000000000 --- a/test/distributed_sorting_test.rb +++ /dev/null @@ -1,18 +0,0 @@ -require_relative "helper" - -class TestDistributedSorting < Test::Unit::TestCase - - include Helper::Distributed - - def test_sort - assert_raise(Redis::Distributed::CannotDistribute) do - r.set("foo:1", "s1") - r.set("foo:2", "s2") - - r.rpush("bar", "1") - r.rpush("bar", "2") - - r.sort("bar", :get => "foo:*", :limit => [0, 1]) - end - end -end diff --git a/test/distributed_test.rb b/test/distributed_test.rb deleted file mode 100644 index 14ff47022..000000000 --- a/test/distributed_test.rb +++ /dev/null @@ -1,56 +0,0 @@ -require_relative "helper" - -class TestDistributed < Test::Unit::TestCase - - include Helper::Distributed - - def test_handle_multiple_servers - @r = Redis::Distributed.new ["redis://127.0.0.1:#{PORT}/15", *NODES] - - 100.times do |idx| - @r.set(idx.to_s, "foo#{idx}") - end - - 100.times do |idx| - assert_equal "foo#{idx}", @r.get(idx.to_s) - end - - assert_equal "0", @r.keys("*").sort.first - assert_equal "string", @r.type("1") - end - - def test_add_nodes - logger = Logger.new("/dev/null") - - @r = Redis::Distributed.new NODES, :logger => logger, :timeout => 10 - - assert_equal "127.0.0.1", @r.nodes[0].client.host - assert_equal PORT, @r.nodes[0].client.port - assert_equal 15, @r.nodes[0].client.db - assert_equal 10, @r.nodes[0].client.timeout - assert_equal logger, @r.nodes[0].client.logger - - @r.add_node("redis://127.0.0.1:6380/14") - - assert_equal "127.0.0.1", @r.nodes[1].client.host - assert_equal 6380, @r.nodes[1].client.port - assert_equal 14, @r.nodes[1].client.db - assert_equal 10, @r.nodes[1].client.timeout - assert_equal logger, @r.nodes[1].client.logger - end - - def test_pipelining_commands_cannot_be_distributed - assert_raise Redis::Distributed::CannotDistribute do - r.pipelined do - r.lpush "foo", "s1" - r.lpush "foo", "s2" - end - end - end - - def test_unknown_commands_does_not_work_by_default - assert_raise NoMethodError do - r.not_yet_implemented_command - end - end -end diff --git a/test/distributed_transactions_test.rb b/test/distributed_transactions_test.rb deleted file mode 100644 index 526e96d45..000000000 --- a/test/distributed_transactions_test.rb +++ /dev/null @@ -1,30 +0,0 @@ -require_relative "helper" - -class TestDistributedTransactions < Test::Unit::TestCase - - include Helper::Distributed - - def test_multi_discard - @foo = nil - - assert_raise Redis::Distributed::CannotDistribute do - r.multi { @foo = 1 } - end - - assert_equal nil, @foo - - assert_raise Redis::Distributed::CannotDistribute do - r.discard - end - end - - def test_watch_unwatch - assert_raise Redis::Distributed::CannotDistribute do - r.watch("foo") - end - - assert_raise Redis::Distributed::CannotDistribute do - r.unwatch - end - end -end diff --git a/test/helper.rb b/test/helper.rb index 046f8a1fb..567b101a2 100644 --- a/test/helper.rb +++ b/test/helper.rb @@ -14,7 +14,6 @@ ENV["conn"] ||= "ruby" require_relative "../lib/redis" -require_relative "../lib/redis/distributed" require_relative "../lib/redis/connection/#{ENV["conn"]}" require_relative "support/redis_mock" @@ -184,25 +183,4 @@ def _new_client(options = {}) end end - module Distributed - - include Generic - - def version - Version.new(redis.info.first["redis_version"]) - end - - private - - def _format_options(options) - { - :timeout => OPTIONS[:timeout], - :logger => ::Logger.new(@log), - }.merge(options) - end - - def _new_client(options = {}) - Redis::Distributed.new(NODES, _format_options(options).merge(:driver => ENV["conn"])) - end - end end diff --git a/test/lint/blocking_commands.rb b/test/lint/blocking_commands.rb deleted file mode 100644 index a4e25d588..000000000 --- a/test/lint/blocking_commands.rb +++ /dev/null @@ -1,150 +0,0 @@ -module Lint - - module BlockingCommands - - def setup - super - - r.rpush("{zap}foo", "s1") - r.rpush("{zap}foo", "s2") - r.rpush("{zap}bar", "s1") - r.rpush("{zap}bar", "s2") - end - - def to_protocol(obj) - case obj - when String - "$#{obj.length}\r\n#{obj}\r\n" - when Array - "*#{obj.length}\r\n" + obj.map { |e| to_protocol(e) }.join - else - fail - end - end - - def mock(options = {}, &blk) - commands = { - :blpop => lambda do |*args| - sleep options[:delay] if options.has_key?(:delay) - to_protocol([args.first, args.last]) - end, - :brpop => lambda do |*args| - sleep options[:delay] if options.has_key?(:delay) - to_protocol([args.first, args.last]) - end, - :brpoplpush => lambda do |*args| - sleep options[:delay] if options.has_key?(:delay) - to_protocol(args.last) - end, - } - - redis_mock(commands, &blk) - end - - def test_blpop - assert_equal ["{zap}foo", "s1"], r.blpop("{zap}foo") - assert_equal ["{zap}foo", "s2"], r.blpop(["{zap}foo"]) - assert_equal ["{zap}bar", "s1"], r.blpop(["{zap}bar", "{zap}foo"]) - assert_equal ["{zap}bar", "s2"], r.blpop(["{zap}foo", "{zap}bar"]) - end - - def test_blpop_timeout - mock do |r| - assert_equal ["{zap}foo", "0"], r.blpop("{zap}foo") - assert_equal ["{zap}foo", "1"], r.blpop("{zap}foo", :timeout => 1) - end - end - - def test_blpop_with_old_prototype - assert_equal ["{zap}foo", "s1"], r.blpop("{zap}foo", 0) - assert_equal ["{zap}foo", "s2"], r.blpop("{zap}foo", 0) - assert_equal ["{zap}bar", "s1"], r.blpop("{zap}bar", "{zap}foo", 0) - assert_equal ["{zap}bar", "s2"], r.blpop("{zap}foo", "{zap}bar", 0) - end - - def test_blpop_timeout_with_old_prototype - mock do |r| - assert_equal ["{zap}foo", "0"], r.blpop("{zap}foo", 0) - assert_equal ["{zap}foo", "1"], r.blpop("{zap}foo", 1) - end - end - - def test_brpop - assert_equal ["{zap}foo", "s2"], r.brpop("{zap}foo") - assert_equal ["{zap}foo", "s1"], r.brpop(["{zap}foo"]) - assert_equal ["{zap}bar", "s2"], r.brpop(["{zap}bar", "{zap}foo"]) - assert_equal ["{zap}bar", "s1"], r.brpop(["{zap}foo", "{zap}bar"]) - end - - def test_brpop_timeout - mock do |r| - assert_equal ["{zap}foo", "0"], r.brpop("{zap}foo") - assert_equal ["{zap}foo", "1"], r.brpop("{zap}foo", :timeout => 1) - end - end - - def test_brpop_with_old_prototype - assert_equal ["{zap}foo", "s2"], r.brpop("{zap}foo", 0) - assert_equal ["{zap}foo", "s1"], r.brpop("{zap}foo", 0) - assert_equal ["{zap}bar", "s2"], r.brpop("{zap}bar", "{zap}foo", 0) - assert_equal ["{zap}bar", "s1"], r.brpop("{zap}foo", "{zap}bar", 0) - end - - def test_brpop_timeout_with_old_prototype - mock do |r| - assert_equal ["{zap}foo", "0"], r.brpop("{zap}foo", 0) - assert_equal ["{zap}foo", "1"], r.brpop("{zap}foo", 1) - end - end - - def test_brpoplpush - assert_equal "s2", r.brpoplpush("{zap}foo", "{zap}qux") - assert_equal ["s2"], r.lrange("{zap}qux", 0, -1) - end - - def test_brpoplpush_timeout - mock do |r| - assert_equal "0", r.brpoplpush("{zap}foo", "{zap}bar") - assert_equal "1", r.brpoplpush("{zap}foo", "{zap}bar", :timeout => 1) - end - end - - def test_brpoplpush_with_old_prototype - assert_equal "s2", r.brpoplpush("{zap}foo", "{zap}qux", 0) - assert_equal ["s2"], r.lrange("{zap}qux", 0, -1) - end - - def test_brpoplpush_timeout_with_old_prototype - mock do |r| - assert_equal "0", r.brpoplpush("{zap}foo", "{zap}bar", 0) - assert_equal "1", r.brpoplpush("{zap}foo", "{zap}bar", 1) - end - end - - driver(:ruby, :hiredis) do - def test_blpop_socket_timeout - mock(:delay => 1 + OPTIONS[:timeout] * 2) do |r| - assert_raises(Redis::TimeoutError) do - r.blpop("{zap}foo", :timeout => 1) - end - end - end - - def test_brpop_socket_timeout - mock(:delay => 1 + OPTIONS[:timeout] * 2) do |r| - assert_raises(Redis::TimeoutError) do - r.brpop("{zap}foo", :timeout => 1) - end - end - end - - def test_brpoplpush_socket_timeout - mock(:delay => 1 + OPTIONS[:timeout] * 2) do |r| - assert_raises(Redis::TimeoutError) do - r.brpoplpush("{zap}foo", "{zap}bar", :timeout => 1) - end - end - end - end - end -end diff --git a/test/lint/hashes.rb b/test/lint/hashes.rb deleted file mode 100644 index 649e6673f..000000000 --- a/test/lint/hashes.rb +++ /dev/null @@ -1,162 +0,0 @@ -module Lint - - module Hashes - - def test_hset_and_hget - r.hset("foo", "f1", "s1") - - assert_equal "s1", r.hget("foo", "f1") - end - - def test_hsetnx - r.hset("foo", "f1", "s1") - r.hsetnx("foo", "f1", "s2") - - assert_equal "s1", r.hget("foo", "f1") - - r.del("foo") - r.hsetnx("foo", "f1", "s2") - - assert_equal "s2", r.hget("foo", "f1") - end - - def test_hdel - r.hset("foo", "f1", "s1") - - assert_equal "s1", r.hget("foo", "f1") - - assert_equal 1, r.hdel("foo", "f1") - - assert_equal nil, r.hget("foo", "f1") - end - - def test_variadic_hdel - target_version "2.3.9" do - r.hset("foo", "f1", "s1") - r.hset("foo", "f2", "s2") - - assert_equal "s1", r.hget("foo", "f1") - assert_equal "s2", r.hget("foo", "f2") - - assert_equal 2, r.hdel("foo", ["f1", "f2"]) - - assert_equal nil, r.hget("foo", "f1") - assert_equal nil, r.hget("foo", "f2") - end - end - - def test_hexists - assert_equal false, r.hexists("foo", "f1") - - r.hset("foo", "f1", "s1") - - assert r.hexists("foo", "f1") - end - - def test_hlen - assert_equal 0, r.hlen("foo") - - r.hset("foo", "f1", "s1") - - assert_equal 1, r.hlen("foo") - - r.hset("foo", "f2", "s2") - - assert_equal 2, r.hlen("foo") - end - - def test_hkeys - assert_equal [], r.hkeys("foo") - - r.hset("foo", "f1", "s1") - r.hset("foo", "f2", "s2") - - assert_equal ["f1", "f2"], r.hkeys("foo") - end - - def test_hvals - assert_equal [], r.hvals("foo") - - r.hset("foo", "f1", "s1") - r.hset("foo", "f2", "s2") - - assert_equal ["s1", "s2"], r.hvals("foo") - end - - def test_hgetall - assert({} == r.hgetall("foo")) - - r.hset("foo", "f1", "s1") - r.hset("foo", "f2", "s2") - - assert({"f1" => "s1", "f2" => "s2"} == r.hgetall("foo")) - end - - def test_hmset - r.hmset("hash", "foo1", "bar1", "foo2", "bar2") - - assert_equal "bar1", r.hget("hash", "foo1") - assert_equal "bar2", r.hget("hash", "foo2") - end - - def test_hmset_with_invalid_arguments - assert_raise(Redis::CommandError) do - r.hmset("hash", "foo1", "bar1", "foo2", "bar2", "foo3") - end - end - - def test_mapped_hmset - r.mapped_hmset("foo", :f1 => "s1", :f2 => "s2") - - assert_equal "s1", r.hget("foo", "f1") - assert_equal "s2", r.hget("foo", "f2") - end - - def test_hmget - r.hset("foo", "f1", "s1") - r.hset("foo", "f2", "s2") - r.hset("foo", "f3", "s3") - - assert_equal ["s2", "s3"], r.hmget("foo", "f2", "f3") - end - - def test_hmget_mapped - r.hset("foo", "f1", "s1") - r.hset("foo", "f2", "s2") - r.hset("foo", "f3", "s3") - - assert({"f1" => "s1"} == r.mapped_hmget("foo", "f1")) - assert({"f1" => "s1", "f2" => "s2"} == r.mapped_hmget("foo", "f1", "f2")) - end - - def test_hincrby - r.hincrby("foo", "f1", 1) - - assert_equal "1", r.hget("foo", "f1") - - r.hincrby("foo", "f1", 2) - - assert_equal "3", r.hget("foo", "f1") - - r.hincrby("foo", "f1", -1) - - assert_equal "2", r.hget("foo", "f1") - end - - def test_hincrbyfloat - target_version "2.5.4" do - r.hincrbyfloat("foo", "f1", 1.23) - - assert_equal "1.23", r.hget("foo", "f1") - - r.hincrbyfloat("foo", "f1", 0.77) - - assert_equal "2", r.hget("foo", "f1") - - r.hincrbyfloat("foo", "f1", -0.1) - - assert_equal "1.9", r.hget("foo", "f1") - end - end - end -end diff --git a/test/lint/hyper_log_log.rb b/test/lint/hyper_log_log.rb deleted file mode 100644 index 5472e22f5..000000000 --- a/test/lint/hyper_log_log.rb +++ /dev/null @@ -1,60 +0,0 @@ -module Lint - - module HyperLogLog - - def test_pfadd - target_version "2.8.9" do - assert_equal true, r.pfadd("foo", "s1") - assert_equal true, r.pfadd("foo", "s2") - assert_equal false, r.pfadd("foo", "s1") - - assert_equal 2, r.pfcount("foo") - end - end - - def test_variadic_pfadd - target_version "2.8.9" do - assert_equal true, r.pfadd("foo", ["s1", "s2"]) - assert_equal true, r.pfadd("foo", ["s1", "s2", "s3"]) - - assert_equal 3, r.pfcount("foo") - end - end - - def test_pfcount - target_version "2.8.9" do - assert_equal 0, r.pfcount("foo") - - assert_equal true, r.pfadd("foo", "s1") - - assert_equal 1, r.pfcount("foo") - end - end - - def test_variadic_pfcount - target_version "2.8.9" do - assert_equal 0, r.pfcount(["{1}foo", "{1}bar"]) - - assert_equal true, r.pfadd("{1}foo", "s1") - assert_equal true, r.pfadd("{1}bar", "s1") - assert_equal true, r.pfadd("{1}bar", "s2") - - assert_equal 2, r.pfcount("{1}foo", "{1}bar") - end - end - - def test_variadic_pfcount_expanded - target_version "2.8.9" do - assert_equal 0, r.pfcount("{1}foo", "{1}bar") - - assert_equal true, r.pfadd("{1}foo", "s1") - assert_equal true, r.pfadd("{1}bar", "s1") - assert_equal true, r.pfadd("{1}bar", "s2") - - assert_equal 2, r.pfcount("{1}foo", "{1}bar") - end - end - - end - -end diff --git a/test/lint/lists.rb b/test/lint/lists.rb deleted file mode 100644 index 3a230f675..000000000 --- a/test/lint/lists.rb +++ /dev/null @@ -1,143 +0,0 @@ -module Lint - - module Lists - - def test_lpush - r.lpush "foo", "s1" - r.lpush "foo", "s2" - - assert_equal 2, r.llen("foo") - assert_equal "s2", r.lpop("foo") - end - - def test_variadic_lpush - target_version "2.3.9" do # 2.4-rc6 - assert_equal 3, r.lpush("foo", ["s1", "s2", "s3"]) - assert_equal 3, r.llen("foo") - assert_equal "s3", r.lpop("foo") - end - end - - def test_lpushx - r.lpushx "foo", "s1" - r.lpush "foo", "s2" - r.lpushx "foo", "s3" - - assert_equal 2, r.llen("foo") - assert_equal ["s3", "s2"], r.lrange("foo", 0, -1) - end - - def test_rpush - r.rpush "foo", "s1" - r.rpush "foo", "s2" - - assert_equal 2, r.llen("foo") - assert_equal "s2", r.rpop("foo") - end - - def test_variadic_rpush - target_version "2.3.9" do # 2.4-rc6 - assert_equal 3, r.rpush("foo", ["s1", "s2", "s3"]) - assert_equal 3, r.llen("foo") - assert_equal "s3", r.rpop("foo") - end - end - - def test_rpushx - r.rpushx "foo", "s1" - r.rpush "foo", "s2" - r.rpushx "foo", "s3" - - assert_equal 2, r.llen("foo") - assert_equal ["s2", "s3"], r.lrange("foo", 0, -1) - end - - def test_llen - r.rpush "foo", "s1" - r.rpush "foo", "s2" - - assert_equal 2, r.llen("foo") - end - - def test_lrange - r.rpush "foo", "s1" - r.rpush "foo", "s2" - r.rpush "foo", "s3" - - assert_equal ["s2", "s3"], r.lrange("foo", 1, -1) - assert_equal ["s1", "s2"], r.lrange("foo", 0, 1) - - assert_equal [], r.lrange("bar", 0, -1) - end - - def test_ltrim - r.rpush "foo", "s1" - r.rpush "foo", "s2" - r.rpush "foo", "s3" - - r.ltrim "foo", 0, 1 - - assert_equal 2, r.llen("foo") - assert_equal ["s1", "s2"], r.lrange("foo", 0, -1) - end - - def test_lindex - r.rpush "foo", "s1" - r.rpush "foo", "s2" - - assert_equal "s1", r.lindex("foo", 0) - assert_equal "s2", r.lindex("foo", 1) - end - - def test_lset - r.rpush "foo", "s1" - r.rpush "foo", "s2" - - assert_equal "s2", r.lindex("foo", 1) - assert r.lset("foo", 1, "s3") - assert_equal "s3", r.lindex("foo", 1) - - assert_raise Redis::CommandError do - r.lset("foo", 4, "s3") - end - end - - def test_lrem - r.rpush "foo", "s1" - r.rpush "foo", "s2" - - assert_equal 1, r.lrem("foo", 1, "s1") - assert_equal ["s2"], r.lrange("foo", 0, -1) - end - - def test_lpop - r.rpush "foo", "s1" - r.rpush "foo", "s2" - - assert_equal 2, r.llen("foo") - assert_equal "s1", r.lpop("foo") - assert_equal 1, r.llen("foo") - end - - def test_rpop - r.rpush "foo", "s1" - r.rpush "foo", "s2" - - assert_equal 2, r.llen("foo") - assert_equal "s2", r.rpop("foo") - assert_equal 1, r.llen("foo") - end - - def test_linsert - r.rpush "foo", "s1" - r.rpush "foo", "s3" - r.linsert "foo", :before, "s3", "s2" - - assert_equal ["s1", "s2", "s3"], r.lrange("foo", 0, -1) - - assert_raise(Redis::CommandError) do - r.linsert "foo", :anywhere, "s3", "s2" - end - end - end -end diff --git a/test/lint/sets.rb b/test/lint/sets.rb deleted file mode 100644 index 7342f138e..000000000 --- a/test/lint/sets.rb +++ /dev/null @@ -1,125 +0,0 @@ -module Lint - - module Sets - - def test_sadd - assert_equal true, r.sadd("foo", "s1") - assert_equal true, r.sadd("foo", "s2") - assert_equal false, r.sadd("foo", "s1") - - assert_equal ["s1", "s2"], r.smembers("foo").sort - end - - def test_variadic_sadd - target_version "2.3.9" do # 2.4-rc6 - assert_equal 2, r.sadd("foo", ["s1", "s2"]) - assert_equal 1, r.sadd("foo", ["s1", "s2", "s3"]) - - assert_equal ["s1", "s2", "s3"], r.smembers("foo").sort - end - end - - def test_srem - r.sadd("foo", "s1") - r.sadd("foo", "s2") - - assert_equal true, r.srem("foo", "s1") - assert_equal false, r.srem("foo", "s3") - - assert_equal ["s2"], r.smembers("foo") - end - - def test_variadic_srem - target_version "2.3.9" do # 2.4-rc6 - r.sadd("foo", "s1") - r.sadd("foo", "s2") - r.sadd("foo", "s3") - - assert_equal 1, r.srem("foo", ["s1", "aaa"]) - assert_equal 0, r.srem("foo", ["bbb", "ccc" "ddd"]) - assert_equal 1, r.srem("foo", ["eee", "s3"]) - - assert_equal ["s2"], r.smembers("foo") - end - end - - def test_spop - r.sadd "foo", "s1" - r.sadd "foo", "s2" - - assert ["s1", "s2"].include?(r.spop("foo")) - assert ["s1", "s2"].include?(r.spop("foo")) - assert_equal nil, r.spop("foo") - end - - def test_scard - assert_equal 0, r.scard("foo") - - r.sadd "foo", "s1" - - assert_equal 1, r.scard("foo") - - r.sadd "foo", "s2" - - assert_equal 2, r.scard("foo") - end - - def test_sismember - assert_equal false, r.sismember("foo", "s1") - - r.sadd "foo", "s1" - - assert_equal true, r.sismember("foo", "s1") - assert_equal false, r.sismember("foo", "s2") - end - - def test_smembers - assert_equal [], r.smembers("foo") - - r.sadd "foo", "s1" - r.sadd "foo", "s2" - - assert_equal ["s1", "s2"], r.smembers("foo").sort - end - - def test_srandmember - r.sadd "foo", "s1" - r.sadd "foo", "s2" - - 4.times do - assert ["s1", "s2"].include?(r.srandmember("foo")) - end - - assert_equal 2, r.scard("foo") - end - - def test_srandmember_with_positive_count - r.sadd "foo", "s1" - r.sadd "foo", "s2" - r.sadd "foo", "s3" - r.sadd "foo", "s4" - - 4.times do - assert !(["s1", "s2", "s3", "s4"] & r.srandmember("foo", 3)).empty? - - assert_equal 3, r.srandmember("foo", 3).size - end - - assert_equal 4, r.scard("foo") - end - - def test_srandmember_with_negative_count - r.sadd "foo", "s1" - r.sadd "foo", "s2" - r.sadd "foo", "s3" - r.sadd "foo", "s4" - - 4.times do - assert !(["s1", "s2", "s3", "s4"] & r.srandmember("foo", -6)).empty? - assert_equal 6, r.srandmember("foo", -6).size - end - - assert_equal 4, r.scard("foo") - end - end -end diff --git a/test/lint/sorted_sets.rb b/test/lint/sorted_sets.rb deleted file mode 100644 index 4700910d3..000000000 --- a/test/lint/sorted_sets.rb +++ /dev/null @@ -1,238 +0,0 @@ -module Lint - - module SortedSets - - Infinity = 1.0/0.0 - - def test_zadd - assert_equal 0, r.zcard("foo") - assert_equal true, r.zadd("foo", 1, "s1") - assert_equal false, r.zadd("foo", 1, "s1") - assert_equal 1, r.zcard("foo") - end - - def test_variadic_zadd - target_version "2.3.9" do # 2.4-rc6 - # Non-nested array with pairs - assert_equal 0, r.zcard("foo") - assert_equal 2, r.zadd("foo", [1, "s1", 2, "s2"]) - assert_equal 1, r.zadd("foo", [4, "s1", 5, "s2", 6, "s3"]) - assert_equal 3, r.zcard("foo") - r.del "foo" - - # Nested array with pairs - assert_equal 0, r.zcard("foo") - assert_equal 2, r.zadd("foo", [[1, "s1"], [2, "s2"]]) - assert_equal 1, r.zadd("foo", [[4, "s1"], [5, "s2"], [6, "s3"]]) - assert_equal 3, r.zcard("foo") - r.del "foo" - - # Wrong number of arguments - assert_raise(Redis::CommandError) { r.zadd("foo", ["bar"]) } - assert_raise(Redis::CommandError) { r.zadd("foo", ["bar", "qux", "zap"]) } - end - end - - def test_zrem - r.zadd("foo", 1, "s1") - r.zadd("foo", 2, "s2") - - assert_equal 2, r.zcard("foo") - assert_equal true, r.zrem("foo", "s1") - assert_equal false, r.zrem("foo", "s1") - assert_equal 1, r.zcard("foo") - end - - def test_variadic_zrem - target_version "2.3.9" do # 2.4-rc6 - r.zadd("foo", 1, "s1") - r.zadd("foo", 2, "s2") - r.zadd("foo", 3, "s3") - - assert_equal 3, r.zcard("foo") - assert_equal 1, r.zrem("foo", ["s1", "aaa"]) - assert_equal 0, r.zrem("foo", ["bbb", "ccc" "ddd"]) - assert_equal 1, r.zrem("foo", ["eee", "s3"]) - assert_equal 1, r.zcard("foo") - end - end - - def test_zincrby - rv = r.zincrby "foo", 1, "s1" - assert_equal 1.0, rv - - rv = r.zincrby "foo", 10, "s1" - assert_equal 11.0, rv - - rv = r.zincrby "bar", "-inf", "s1" - assert_equal(-Infinity, rv) - - rv = r.zincrby "bar", "+inf", "s2" - assert_equal(+Infinity, rv) - end - - def test_zrank - r.zadd "foo", 1, "s1" - r.zadd "foo", 2, "s2" - r.zadd "foo", 3, "s3" - - assert_equal 2, r.zrank("foo", "s3") - end - - def test_zrevrank - r.zadd "foo", 1, "s1" - r.zadd "foo", 2, "s2" - r.zadd "foo", 3, "s3" - - assert_equal 0, r.zrevrank("foo", "s3") - end - - def test_zrange - r.zadd "foo", 1, "s1" - r.zadd "foo", 2, "s2" - r.zadd "foo", 3, "s3" - - assert_equal ["s1", "s2"], r.zrange("foo", 0, 1) - assert_equal [["s1", 1.0], ["s2", 2.0]], r.zrange("foo", 0, 1, :with_scores => true) - assert_equal [["s1", 1.0], ["s2", 2.0]], r.zrange("foo", 0, 1, :withscores => true) - - r.zadd "bar", "-inf", "s1" - r.zadd "bar", "+inf", "s2" - assert_equal [["s1", -Infinity], ["s2", +Infinity]], r.zrange("bar", 0, 1, :with_scores => true) - assert_equal [["s1", -Infinity], ["s2", +Infinity]], r.zrange("bar", 0, 1, :withscores => true) - end - - def test_zrevrange - r.zadd "foo", 1, "s1" - r.zadd "foo", 2, "s2" - r.zadd "foo", 3, "s3" - - assert_equal ["s3", "s2"], r.zrevrange("foo", 0, 1) - assert_equal [["s3", 3.0], ["s2", 2.0]], r.zrevrange("foo", 0, 1, :with_scores => true) - assert_equal [["s3", 3.0], ["s2", 2.0]], r.zrevrange("foo", 0, 1, :withscores => true) - - r.zadd "bar", "-inf", "s1" - r.zadd "bar", "+inf", "s2" - assert_equal [["s2", +Infinity], ["s1", -Infinity]], r.zrevrange("bar", 0, 1, :with_scores => true) - assert_equal [["s2", +Infinity], ["s1", -Infinity]], r.zrevrange("bar", 0, 1, :withscores => true) - end - - def test_zrangebyscore - r.zadd "foo", 1, "s1" - r.zadd "foo", 2, "s2" - r.zadd "foo", 3, "s3" - - assert_equal ["s2", "s3"], r.zrangebyscore("foo", 2, 3) - end - - def test_zrevrangebyscore - r.zadd "foo", 1, "s1" - r.zadd "foo", 2, "s2" - r.zadd "foo", 3, "s3" - - assert_equal ["s3", "s2"], r.zrevrangebyscore("foo", 3, 2) - end - - def test_zrangebyscore_with_limit - r.zadd "foo", 1, "s1" - r.zadd "foo", 2, "s2" - r.zadd "foo", 3, "s3" - r.zadd "foo", 4, "s4" - - assert_equal ["s2"], r.zrangebyscore("foo", 2, 4, :limit => [0, 1]) - assert_equal ["s3"], r.zrangebyscore("foo", 2, 4, :limit => [1, 1]) - assert_equal ["s3", "s4"], r.zrangebyscore("foo", 2, 4, :limit => [1, 2]) - end - - def test_zrevrangebyscore_with_limit - r.zadd "foo", 1, "s1" - r.zadd "foo", 2, "s2" - r.zadd "foo", 3, "s3" - r.zadd "foo", 4, "s4" - - assert_equal ["s4"], r.zrevrangebyscore("foo", 4, 2, :limit => [0, 1]) - assert_equal ["s3"], r.zrevrangebyscore("foo", 4, 2, :limit => [1, 1]) - assert_equal ["s3", "s2"], r.zrevrangebyscore("foo", 4, 2, :limit => [1, 2]) - end - - def test_zrangebyscore_with_withscores - r.zadd "foo", 1, "s1" - r.zadd "foo", 2, "s2" - r.zadd "foo", 3, "s3" - r.zadd "foo", 4, "s4" - - assert_equal [["s2", 2.0]], r.zrangebyscore("foo", 2, 4, :limit => [0, 1], :with_scores => true) - assert_equal [["s3", 3.0]], r.zrangebyscore("foo", 2, 4, :limit => [1, 1], :with_scores => true) - assert_equal [["s2", 2.0]], r.zrangebyscore("foo", 2, 4, :limit => [0, 1], :withscores => true) - assert_equal [["s3", 3.0]], r.zrangebyscore("foo", 2, 4, :limit => [1, 1], :withscores => true) - - r.zadd "bar", "-inf", "s1" - r.zadd "bar", "+inf", "s2" - assert_equal [["s1", -Infinity]], r.zrangebyscore("bar", -Infinity, +Infinity, :limit => [0, 1], :with_scores => true) - assert_equal [["s2", +Infinity]], r.zrangebyscore("bar", -Infinity, +Infinity, :limit => [1, 1], :with_scores => true) - assert_equal [["s1", -Infinity]], r.zrangebyscore("bar", -Infinity, +Infinity, :limit => [0, 1], :withscores => true) - assert_equal [["s2", +Infinity]], r.zrangebyscore("bar", -Infinity, +Infinity, :limit => [1, 1], :withscores => true) - end - - def test_zrevrangebyscore_with_withscores - r.zadd "foo", 1, "s1" - r.zadd "foo", 2, "s2" - r.zadd "foo", 3, "s3" - r.zadd "foo", 4, "s4" - - assert_equal [["s4", 4.0]], r.zrevrangebyscore("foo", 4, 2, :limit => [0, 1], :with_scores => true) - assert_equal [["s3", 3.0]], r.zrevrangebyscore("foo", 4, 2, :limit => [1, 1], :with_scores => true) - assert_equal [["s4", 4.0]], r.zrevrangebyscore("foo", 4, 2, :limit => [0, 1], :withscores => true) - assert_equal [["s3", 3.0]], r.zrevrangebyscore("foo", 4, 2, :limit => [1, 1], :withscores => true) - - r.zadd "bar", "-inf", "s1" - r.zadd "bar", "+inf", "s2" - assert_equal [["s2", +Infinity]], r.zrevrangebyscore("bar", +Infinity, -Infinity, :limit => [0, 1], :with_scores => true) - assert_equal [["s1", -Infinity]], r.zrevrangebyscore("bar", +Infinity, -Infinity, :limit => [1, 1], :with_scores => true) - assert_equal [["s2", +Infinity]], r.zrevrangebyscore("bar", +Infinity, -Infinity, :limit => [0, 1], :withscores => true) - assert_equal [["s1", -Infinity]], r.zrevrangebyscore("bar", +Infinity, -Infinity, :limit => [1, 1], :withscores => true) - end - - def test_zcard - assert_equal 0, r.zcard("foo") - - r.zadd "foo", 1, "s1" - - assert_equal 1, r.zcard("foo") - end - - def test_zscore - r.zadd "foo", 1, "s1" - - assert_equal 1.0, r.zscore("foo", "s1") - - assert_equal nil, r.zscore("foo", "s2") - assert_equal nil, r.zscore("bar", "s1") - - r.zadd "bar", "-inf", "s1" - r.zadd "bar", "+inf", "s2" - assert_equal(-Infinity, r.zscore("bar", "s1")) - assert_equal(+Infinity, r.zscore("bar", "s2")) - end - - def test_zremrangebyrank - r.zadd "foo", 10, "s1" - r.zadd "foo", 20, "s2" - r.zadd "foo", 30, "s3" - r.zadd "foo", 40, "s4" - - assert_equal 3, r.zremrangebyrank("foo", 1, 3) - assert_equal ["s1"], r.zrange("foo", 0, -1) - end - - def test_zremrangebyscore - r.zadd "foo", 1, "s1" - r.zadd "foo", 2, "s2" - r.zadd "foo", 3, "s3" - r.zadd "foo", 4, "s4" - - assert_equal 3, r.zremrangebyscore("foo", 2, 4) - assert_equal ["s1"], r.zrange("foo", 0, -1) - end - end -end diff --git a/test/lint/strings.rb b/test/lint/strings.rb deleted file mode 100644 index e17eaf7fb..000000000 --- a/test/lint/strings.rb +++ /dev/null @@ -1,246 +0,0 @@ -module Lint - - module Strings - - def test_set_and_get - r.set("foo", "s1") - - assert_equal "s1", r.get("foo") - end - - def test_set_and_get_with_newline_characters - r.set("foo", "1\n") - - assert_equal "1\n", r.get("foo") - end - - def test_set_and_get_with_non_string_value - value = ["a", "b"] - - r.set("foo", value) - - assert_equal value.to_s, r.get("foo") - end - - def test_set_and_get_with_ascii_characters - with_external_encoding("ASCII-8BIT") do - (0..255).each do |i| - str = "#{i.chr}---#{i.chr}" - r.set("foo", str) - - assert_equal str, r.get("foo") - end - end - end - - def test_set_with_ex - target_version "2.6.12" do - r.set("foo", "bar", :ex => 2) - assert_in_range 0..2, r.ttl("foo") - end - end - - def test_set_with_px - target_version "2.6.12" do - r.set("foo", "bar", :px => 2000) - assert_in_range 0..2, r.ttl("foo") - end - end - - def test_set_with_nx - target_version "2.6.12" do - r.set("foo", "qux", :nx => true) - assert !r.set("foo", "bar", :nx => true) - assert_equal "qux", r.get("foo") - - r.del("foo") - assert r.set("foo", "bar", :nx => true) - assert_equal "bar", r.get("foo") - end - end - - def test_set_with_xx - target_version "2.6.12" do - r.set("foo", "qux") - assert r.set("foo", "bar", :xx => true) - assert_equal "bar", r.get("foo") - - r.del("foo") - assert !r.set("foo", "bar", :xx => true) - end - end - - def test_setex - assert r.setex("foo", 1, "bar") - assert_equal "bar", r.get("foo") - assert [0, 1].include? r.ttl("foo") - end - - def test_setex_with_non_string_value - value = ["b", "a", "r"] - - assert r.setex("foo", 1, value) - assert_equal value.to_s, r.get("foo") - assert [0, 1].include? r.ttl("foo") - end - - def test_psetex - target_version "2.5.4" do - assert r.psetex("foo", 1000, "bar") - assert_equal "bar", r.get("foo") - assert [0, 1].include? r.ttl("foo") - end - end - - def test_psetex_with_non_string_value - target_version "2.5.4" do - value = ["b", "a", "r"] - - assert r.psetex("foo", 1000, value) - assert_equal value.to_s, r.get("foo") - assert [0, 1].include? r.ttl("foo") - end - end - - def test_getset - r.set("foo", "bar") - - assert_equal "bar", r.getset("foo", "baz") - assert_equal "baz", r.get("foo") - end - - def test_getset_with_non_string_value - r.set("foo", "zap") - - value = ["b", "a", "r"] - - assert_equal "zap", r.getset("foo", value) - assert_equal value.to_s, r.get("foo") - end - - def test_setnx - r.set("foo", "qux") - assert !r.setnx("foo", "bar") - assert_equal "qux", r.get("foo") - - r.del("foo") - assert r.setnx("foo", "bar") - assert_equal "bar", r.get("foo") - end - - def test_setnx_with_non_string_value - value = ["b", "a", "r"] - - r.set("foo", "qux") - assert !r.setnx("foo", value) - assert_equal "qux", r.get("foo") - - r.del("foo") - assert r.setnx("foo", value) - assert_equal value.to_s, r.get("foo") - end - - def test_incr - assert_equal 1, r.incr("foo") - assert_equal 2, r.incr("foo") - assert_equal 3, r.incr("foo") - end - - def test_incrby - assert_equal 1, r.incrby("foo", 1) - assert_equal 3, r.incrby("foo", 2) - assert_equal 6, r.incrby("foo", 3) - end - - def test_incrbyfloat - target_version "2.5.4" do - assert_equal 1.23, r.incrbyfloat("foo", 1.23) - assert_equal 2 , r.incrbyfloat("foo", 0.77) - assert_equal 1.9 , r.incrbyfloat("foo", -0.1) - end - end - - def test_decr - r.set("foo", 3) - - assert_equal 2, r.decr("foo") - assert_equal 1, r.decr("foo") - assert_equal 0, r.decr("foo") - end - - def test_decrby - r.set("foo", 6) - - assert_equal 3, r.decrby("foo", 3) - assert_equal 1, r.decrby("foo", 2) - assert_equal 0, r.decrby("foo", 1) - end - - def test_append - r.set "foo", "s" - r.append "foo", "1" - - assert_equal "s1", r.get("foo") - end - - def test_getbit - r.set("foo", "a") - - assert_equal 1, r.getbit("foo", 1) - assert_equal 1, r.getbit("foo", 2) - assert_equal 0, r.getbit("foo", 3) - assert_equal 0, r.getbit("foo", 4) - assert_equal 0, r.getbit("foo", 5) - assert_equal 0, r.getbit("foo", 6) - assert_equal 1, r.getbit("foo", 7) - end - - def test_setbit - r.set("foo", "a") - - r.setbit("foo", 6, 1) - - assert_equal "c", r.get("foo") - end - - def test_bitcount - target_version "2.5.10" do - r.set("foo", "abcde") - - assert_equal 10, r.bitcount("foo", 1, 3) - assert_equal 17, r.bitcount("foo", 0, -1) - end - end - - def test_getrange - r.set("foo", "abcde") - - assert_equal "bcd", r.getrange("foo", 1, 3) - assert_equal "abcde", r.getrange("foo", 0, -1) - end - - def test_setrange - r.set("foo", "abcde") - - r.setrange("foo", 1, "bar") - - assert_equal "abare", r.get("foo") - end - - def test_setrange_with_non_string_value - r.set("foo", "abcde") - - value = ["b", "a", "r"] - - r.setrange("foo", 2, value) - - assert_equal "ab#{value.to_s}", r.get("foo") - end - - def test_strlen - r.set "foo", "lorem" - - assert_equal 5, r.strlen("foo") - end - end -end diff --git a/test/lint/value_types.rb b/test/lint/value_types.rb deleted file mode 100644 index c4deb233d..000000000 --- a/test/lint/value_types.rb +++ /dev/null @@ -1,122 +0,0 @@ -module Lint - - module ValueTypes - - def test_exists - assert_equal false, r.exists("foo") - - r.set("foo", "s1") - - assert_equal true, r.exists("foo") - end - - def test_type - assert_equal "none", r.type("foo") - - r.set("foo", "s1") - - assert_equal "string", r.type("foo") - end - - def test_keys - r.set("f", "s1") - r.set("fo", "s2") - r.set("foo", "s3") - - assert_equal ["f","fo", "foo"], r.keys("f*").sort - end - - def test_expire - r.set("foo", "s1") - assert r.expire("foo", 2) - assert_in_range 0..2, r.ttl("foo") - end - - def test_pexpire - target_version "2.5.4" do - r.set("foo", "s1") - assert r.pexpire("foo", 2000) - assert_in_range 0..2, r.ttl("foo") - end - end - - def test_expireat - r.set("foo", "s1") - assert r.expireat("foo", (Time.now + 2).to_i) - assert_in_range 0..2, r.ttl("foo") - end - - def test_pexpireat - target_version "2.5.4" do - r.set("foo", "s1") - assert r.pexpireat("foo", (Time.now + 2).to_i * 1_000) - assert_in_range 0..2, r.ttl("foo") - end - end - - def test_persist - r.set("foo", "s1") - r.expire("foo", 1) - r.persist("foo") - - assert(-1 == r.ttl("foo")) - end - - def test_ttl - r.set("foo", "s1") - r.expire("foo", 2) - assert_in_range 0..2, r.ttl("foo") - end - - def test_pttl - target_version "2.5.4" do - r.set("foo", "s1") - r.expire("foo", 2) - assert_in_range 1..2000, r.pttl("foo") - end - end - - def test_dump_and_restore - target_version "2.5.7" do - r.set("foo", "a") - v = r.dump("foo") - r.del("foo") - - assert r.restore("foo", 1000, v) - assert_equal "a", r.get("foo") - assert [0, 1].include? r.ttl("foo") - - r.rpush("bar", ["b", "c", "d"]) - w = r.dump("bar") - r.del("bar") - - assert r.restore("bar", 1000, w) - assert_equal ["b", "c", "d"], r.lrange("bar", 0, -1) - assert [0, 1].include? r.ttl("bar") - end - end - - def test_move - r.select 14 - r.flushdb - - r.set "bar", "s3" - - r.select 15 - - r.set "foo", "s1" - r.set "bar", "s2" - - assert r.move("foo", 14) - assert_equal nil, r.get("foo") - - assert !r.move("bar", 14) - assert_equal "s2", r.get("bar") - - r.select 14 - - assert_equal "s1", r.get("foo") - assert_equal "s3", r.get("bar") - end - end -end From 1feeab7df4fb6f53c1128fc53e0bae487e2747b9 Mon Sep 17 00:00:00 2001 From: Damian Janowski Date: Sun, 1 Nov 2015 00:45:07 -0400 Subject: [PATCH 09/34] Switch to Makefile. --- Rakefile | 87 ------------------------------------------ makefile | 42 ++++++++++++++++++++ test/internals_test.rb | 2 +- 3 files changed, 43 insertions(+), 88 deletions(-) delete mode 100644 Rakefile create mode 100644 makefile diff --git a/Rakefile b/Rakefile deleted file mode 100644 index 2d9e137d8..000000000 --- a/Rakefile +++ /dev/null @@ -1,87 +0,0 @@ -require "rake/testtask" - -ENV["REDIS_BRANCH"] ||= "unstable" - -REDIS_DIR = File.expand_path(File.join("..", "test"), __FILE__) -REDIS_CNF = File.join(REDIS_DIR, "test.conf") -REDIS_CNF_TEMPLATE = File.join(REDIS_DIR, "test.conf.erb") -REDIS_PID = File.join(REDIS_DIR, "db", "redis.pid") -REDIS_LOG = File.join(REDIS_DIR, "db", "redis.log") -REDIS_SOCKET = File.join(REDIS_DIR, "db", "redis.sock") -BINARY = "tmp/redis-#{ENV["REDIS_BRANCH"]}/src/redis-server" - -task :default => :run - -desc "Run tests and manage server start/stop" -task :run => [:start, :test, :stop] - -desc "Start the Redis server" -task :start => [BINARY, REDIS_CNF] do - sh "#{BINARY} --version" - - redis_running = \ - begin - File.exists?(REDIS_PID) && Process.kill(0, File.read(REDIS_PID).to_i) - rescue Errno::ESRCH - FileUtils.rm REDIS_PID - false - end - - unless redis_running - unless system("#{BINARY} #{REDIS_CNF}") - abort "could not start redis-server" - end - end - - at_exit do - Rake::Task["stop"].invoke - end -end - -desc "Stop the Redis server" -task :stop do - if File.exists?(REDIS_PID) - Process.kill "INT", File.read(REDIS_PID).to_i - FileUtils.rm REDIS_PID - end -end - -desc "Clean up testing artifacts" -task :clean do - FileUtils.rm_f(BINARY) - FileUtils.rm_f(REDIS_CNF) -end - -file BINARY do - branch = ENV.fetch("REDIS_BRANCH") - - sh <<-SH - mkdir -p tmp; - cd tmp; - rm -rf redis-#{branch}; - wget https://github.com/antirez/redis/archive/#{branch}.tar.gz -O #{branch}.tar.gz; - tar xf #{branch}.tar.gz; - cd redis-#{branch}; - make - SH -end - -file REDIS_CNF => [REDIS_CNF_TEMPLATE, __FILE__] do |t| - require 'erb' - - erb = t.prerequisites[0] - template = File.read(erb) - - File.open(REDIS_CNF, 'w') do |file| - file.puts "\# This file was auto-generated at #{Time.now}", - "\# from (#{erb})", - "\#" - conf = ERB.new(template).result - file << conf - end -end - -Rake::TestTask.new do |t| - t.options = "-v" if $VERBOSE - t.test_files = FileList["test/*_test.rb"] -end diff --git a/makefile b/makefile new file mode 100644 index 000000000..6ea12e249 --- /dev/null +++ b/makefile @@ -0,0 +1,42 @@ +TEST_FILES := $(shell find test -name *_test.rb -type f) +REDIS_BRANCH := unstable +TMP := tmp +BUILD_DIR := ${TMP}/redis-${REDIS_BRANCH} +TARBALL := ${TMP}/redis-${REDIS_BRANCH}.tar.gz +BINARY := ${BUILD_DIR}/src/redis-server +PID_PATH := ${BUILD_DIR}/redis.pid +SOCKET_PATH := ${BUILD_DIR}/redis.sock +PORT := 6381 + +test: ${TEST_FILES} + make start + env SOCKET_PATH=${SOCKET_PATH} \ + ruby -v $$(echo $? | tr ' ' '\n' | awk '{ print "-r./" $$0 }') -e '' + make stop + +${TMP}: + mkdir $@ + +${TARBALL}: ${TMP} + wget https://github.com/antirez/redis/archive/${REDIS_BRANCH}.tar.gz -O $@ + +${BINARY}: ${TARBALL} ${TMP} + rm -rf ${BUILD_DIR} + mkdir -p ${BUILD_DIR} + tar xf ${TARBALL} -C ${TMP} + cd ${BUILD_DIR} && make + +stop: + (test -f ${PID_PATH} && (kill $$(cat ${PID_PATH}) || true) && rm -f ${PID_PATH}) || true + +start: ${BINARY} + ${BINARY} \ + --daemonize yes \ + --pidfile ${PID_PATH} \ + --port ${PORT} \ + --unixsocket ${SOCKET_PATH} + +clean: + (test -d ${BUILD_DIR} && cd ${BUILD_DIR}/src && make clean distclean) || true + +.PHONY: test start stop diff --git a/test/internals_test.rb b/test/internals_test.rb index 03ee3b6e5..2baba1c3f 100644 --- a/test/internals_test.rb +++ b/test/internals_test.rb @@ -319,7 +319,7 @@ def test_dont_retry_on_write_error_when_wrapped_in_without_reconnect def test_connecting_to_unix_domain_socket assert_nothing_raised do - Redis.new(OPTIONS.merge(:path => "./test/db/redis.sock")).ping + Redis.new(OPTIONS.merge(:path => ENV.fetch("SOCKET_PATH"))).ping end end From 3f966c9458dd364ef3df47a16543e5aba4ec1482 Mon Sep 17 00:00:00 2001 From: Jean Boussier Date: Mon, 16 Nov 2015 13:48:19 -0500 Subject: [PATCH 10/34] Remove the deep dup in Client#options --- lib/redis/client.rb | 4 +--- test/internals_test.rb | 13 ------------- 2 files changed, 1 insertion(+), 16 deletions(-) diff --git a/lib/redis/client.rb b/lib/redis/client.rb index e4d0574a9..8b6677985 100644 --- a/lib/redis/client.rb +++ b/lib/redis/client.rb @@ -22,9 +22,7 @@ class Client :inherit_socket => false } - def options - Marshal.load(Marshal.dump(@options)) - end + attr_reader :options def scheme @options[:scheme] diff --git a/test/internals_test.rb b/test/internals_test.rb index 865c60020..a54356434 100644 --- a/test/internals_test.rb +++ b/test/internals_test.rb @@ -349,19 +349,6 @@ def test_client_options assert_equal "foo", redis.client.options[:scheme] end - def test_does_not_change_self_client_options - redis = Redis.new(OPTIONS.merge(:host => "host", :port => 1234, :db => 1, :scheme => "foo")) - options = redis.client.options - - options[:host] << "new_host" - options[:scheme] << "bar" - options.merge!(:db => 0) - - assert_equal "host", redis.client.options[:host] - assert_equal 1, redis.client.options[:db] - assert_equal "foo", redis.client.options[:scheme] - end - def test_resolves_localhost assert_nothing_raised do Redis.new(OPTIONS.merge(:host => 'localhost')).ping From 5f34d8cdfceb5918cd574d3fd1ccf9203d6eced3 Mon Sep 17 00:00:00 2001 From: Damian Janowski Date: Fri, 14 Oct 2016 18:43:48 -0300 Subject: [PATCH 11/34] Clean up test helper. --- test/helper.rb | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/test/helper.rb b/test/helper.rb index 567b101a2..5242fb878 100644 --- a/test/helper.rb +++ b/test/helper.rb @@ -2,13 +2,6 @@ require "logger" require "stringio" -(class Random; def self.rand(*args) super end; end) unless defined?(Random) - -begin - require "ruby-debug" -rescue LoadError -end - $VERBOSE = true ENV["conn"] ||= "ruby" @@ -40,11 +33,11 @@ def init(redis) Try this once: - $ rake clean + $ make clean Then run the build again: - $ rake + $ make EOS exit 1 From 0c0d5ca6ebdcc43f9323fe68e70ed727108d3eed Mon Sep 17 00:00:00 2001 From: Damian Janowski Date: Fri, 14 Oct 2016 18:44:04 -0300 Subject: [PATCH 12/34] Remove unreliable test. --- test/internals_test.rb | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/test/internals_test.rb b/test/internals_test.rb index ef7eca3c8..2baba1c3f 100644 --- a/test/internals_test.rb +++ b/test/internals_test.rb @@ -3,7 +3,6 @@ class TestInternals < Test::Unit::TestCase include Helper::Client - include Helper::Skipable def test_logger r.ping @@ -159,25 +158,6 @@ def test_connection_timeout assert (Time.now - start_time) <= opts[:timeout] end - driver(:ruby) do - def test_write_timeout - return skip("Relies on buffer sizes, might be unreliable") - - server = TCPServer.new("127.0.0.1", 0) - port = server.addr[1] - - # Hacky, but we need the buffer size - val = TCPSocket.new("127.0.0.1", port).getsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF).unpack("i")[0] - - assert_raise(Redis::TimeoutError) do - Timeout.timeout(1) do - redis = Redis.new(:port => port, :timeout => 5, :write_timeout => 0.1) - redis.set("foo", "1" * val*2) - end - end - end - end - def close_on_ping(seq, options = {}) $request = 0 From c28de9bd003f3292fc52cead2a1a92686cbf5fe8 Mon Sep 17 00:00:00 2001 From: Damian Janowski Date: Wed, 23 Nov 2016 13:00:13 -0300 Subject: [PATCH 13/34] This no longer needed. --- lib/redis/connection/ruby.rb | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/lib/redis/connection/ruby.rb b/lib/redis/connection/ruby.rb index d7b779a74..78bcaff86 100644 --- a/lib/redis/connection/ruby.rb +++ b/lib/redis/connection/ruby.rb @@ -10,16 +10,6 @@ # Not all systems have OpenSSL support end -if RUBY_VERSION < "1.9.3" - class String - # Ruby 1.8.7 does not have byteslice, but it handles encodings differently anyway. - # We can simply slice the string, which is a byte array there. - def byteslice(*args) - slice(*args) - end - end -end - class Redis module Connection module SocketMixin From e8f0311fa370e2bf4d078a601c0ca887b3dbc2c2 Mon Sep 17 00:00:00 2001 From: Damian Janowski Date: Wed, 23 Nov 2016 13:08:31 -0300 Subject: [PATCH 14/34] Not targeting 1.8. --- lib/redis/connection/ruby.rb | 18 ++----- test/bitpos_test.rb | 4 -- test/ssl_test.rb | 92 ++++++++++++++++++------------------ 3 files changed, 49 insertions(+), 65 deletions(-) diff --git a/lib/redis/connection/ruby.rb b/lib/redis/connection/ruby.rb index 78bcaff86..5d4569d5b 100644 --- a/lib/redis/connection/ruby.rb +++ b/lib/redis/connection/ruby.rb @@ -16,15 +16,6 @@ module SocketMixin CRLF = "\r\n".freeze - # Exceptions raised during non-blocking I/O ops that require retrying the op - if RUBY_VERSION >= "1.9.3" - NBIO_READ_EXCEPTIONS = [IO::WaitReadable] - NBIO_WRITE_EXCEPTIONS = [IO::WaitWritable] - else - NBIO_READ_EXCEPTIONS = [Errno::EWOULDBLOCK, Errno::EAGAIN] - NBIO_WRITE_EXCEPTIONS = [Errno::EWOULDBLOCK, Errno::EAGAIN] - end - def initialize(*args) super(*args) @@ -73,13 +64,13 @@ def _read_from_socket(nbytes) begin read_nonblock(nbytes) - rescue *NBIO_READ_EXCEPTIONS + rescue IO::WaitReadable if IO.select([self], nil, nil, @timeout) retry else raise Redis::TimeoutError end - rescue *NBIO_WRITE_EXCEPTIONS + rescue IO::WaitWritable if IO.select(nil, [self], nil, @timeout) retry else @@ -95,13 +86,13 @@ def _write_to_socket(data) begin write_nonblock(data) - rescue *NBIO_WRITE_EXCEPTIONS + rescue IO::WaitWritable if IO.select(nil, [self], nil, @write_timeout) retry else raise Redis::TimeoutError end - rescue *NBIO_READ_EXCEPTIONS + rescue IO::WaitReadable if IO.select([self], nil, nil, @write_timeout) retry else @@ -297,7 +288,6 @@ def self.connect(config) raise ArgumentError, "SSL incompatible with unix sockets" if config[:ssl] sock = UNIXSocket.connect(config[:path], config[:connect_timeout]) elsif config[:scheme] == "rediss" || config[:ssl] - raise ArgumentError, "This library does not support SSL on Ruby < 1.9" if RUBY_VERSION < "1.9.3" sock = SSLSocket.connect(config[:host], config[:port], config[:connect_timeout], config[:ssl_params]) else sock = TCPSocket.connect(config[:host], config[:port], config[:connect_timeout]) diff --git a/test/bitpos_test.rb b/test/bitpos_test.rb index 76d56777a..94c270afc 100644 --- a/test/bitpos_test.rb +++ b/test/bitpos_test.rb @@ -1,9 +1,5 @@ require_relative "helper" -unless defined?(Enumerator) - Enumerator = Enumerable::Enumerator -end - class TestBitpos < Test::Unit::TestCase include Helper::Client diff --git a/test/ssl_test.rb b/test/ssl_test.rb index a92901cae..075e7a74e 100644 --- a/test/ssl_test.rb +++ b/test/ssl_test.rb @@ -1,73 +1,71 @@ # encoding: UTF-8 -if RUBY_VERSION >= "1.9.3" - require File.expand_path("helper", File.dirname(__FILE__)) +require File.expand_path("helper", File.dirname(__FILE__)) - class SslTest < Test::Unit::TestCase +class SslTest < Test::Unit::TestCase - include Helper::Client + include Helper::Client - driver(:ruby) do + driver(:ruby) do - def test_verified_ssl_connection - RedisMock.start({ :ping => proc { "+PONG" } }, ssl_server_opts("trusted")) do |port| - redis = Redis.new(:port => port, :ssl => true, :ssl_params => { :ca_file => ssl_ca_file }) - assert_equal redis.ping, "PONG" - end - end - - def test_unverified_ssl_connection - assert_raise(OpenSSL::SSL::SSLError) do - RedisMock.start({ :ping => proc { "+PONG" } }, ssl_server_opts("untrusted")) do |port| - redis = Redis.new(:port => port, :ssl => true, :ssl_params => { :ca_file => ssl_ca_file }) - redis.ping - end - end + def test_verified_ssl_connection + RedisMock.start({ :ping => proc { "+PONG" } }, ssl_server_opts("trusted")) do |port| + redis = Redis.new(:port => port, :ssl => true, :ssl_params => { :ca_file => ssl_ca_file }) + assert_equal redis.ping, "PONG" end + end - def test_ssl_blocking - RedisMock.start({}, ssl_server_opts("trusted")) do |port| + def test_unverified_ssl_connection + assert_raise(OpenSSL::SSL::SSLError) do + RedisMock.start({ :ping => proc { "+PONG" } }, ssl_server_opts("untrusted")) do |port| redis = Redis.new(:port => port, :ssl => true, :ssl_params => { :ca_file => ssl_ca_file }) - assert_equal redis.set("boom", "a" * 10_000_000), "OK" + redis.ping end end + end + def test_ssl_blocking + RedisMock.start({}, ssl_server_opts("trusted")) do |port| + redis = Redis.new(:port => port, :ssl => true, :ssl_params => { :ca_file => ssl_ca_file }) + assert_equal redis.set("boom", "a" * 10_000_000), "OK" + end end - driver(:hiredis, :synchrony) do + end + + driver(:hiredis, :synchrony) do - def test_ssl_not_implemented_exception - assert_raise(NotImplementedError) do - RedisMock.start({ :ping => proc { "+PONG" } }, ssl_server_opts("trusted")) do |port| - redis = Redis.new(:port => port, :ssl => true, :ssl_params => { :ca_file => ssl_ca_file }) - redis.ping - end + def test_ssl_not_implemented_exception + assert_raise(NotImplementedError) do + RedisMock.start({ :ping => proc { "+PONG" } }, ssl_server_opts("trusted")) do |port| + redis = Redis.new(:port => port, :ssl => true, :ssl_params => { :ca_file => ssl_ca_file }) + redis.ping end end - end - private + end + + private - def ssl_server_opts(prefix) - ssl_cert = File.join(cert_path, "#{prefix}-cert.crt") - ssl_key = File.join(cert_path, "#{prefix}-cert.key") + def ssl_server_opts(prefix) + ssl_cert = File.join(cert_path, "#{prefix}-cert.crt") + ssl_key = File.join(cert_path, "#{prefix}-cert.key") - { - :ssl => true, - :ssl_params => { - :cert => OpenSSL::X509::Certificate.new(File.read(ssl_cert)), - :key => OpenSSL::PKey::RSA.new(File.read(ssl_key)) - } + { + :ssl => true, + :ssl_params => { + :cert => OpenSSL::X509::Certificate.new(File.read(ssl_cert)), + :key => OpenSSL::PKey::RSA.new(File.read(ssl_key)) } - end + } + end - def ssl_ca_file - File.join(cert_path, "trusted-ca.crt") - end + def ssl_ca_file + File.join(cert_path, "trusted-ca.crt") + end - def cert_path - File.expand_path("../support/ssl/", __FILE__) - end + def cert_path + File.expand_path("../support/ssl/", __FILE__) end end From 67429c3fcc7324c8c87eca2941c88cf60ce2f00a Mon Sep 17 00:00:00 2001 From: Damian Janowski Date: Wed, 23 Nov 2016 13:11:40 -0300 Subject: [PATCH 15/34] Fix warnings. --- test/bitpos_test.rb | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/test/bitpos_test.rb b/test/bitpos_test.rb index 94c270afc..d810a7f23 100644 --- a/test/bitpos_test.rb +++ b/test/bitpos_test.rb @@ -7,48 +7,48 @@ class TestBitpos < Test::Unit::TestCase def test_bitpos_empty_zero target_version "2.9.11" do r.del "foo" - assert_equal 0, r.bitpos("foo", 0) + assert_equal(0, r.bitpos("foo", 0)) end end def test_bitpos_empty_one target_version "2.9.11" do r.del "foo" - assert_equal -1, r.bitpos("foo", 1) + assert_equal(-1, r.bitpos("foo", 1)) end end def test_bitpos_zero target_version "2.9.11" do r.set "foo", "\xff\xf0\x00" - assert_equal 12, r.bitpos("foo", 0) + assert_equal(12, r.bitpos("foo", 0)) end end def test_bitpos_one target_version "2.9.11" do r.set "foo", "\x00\x0f\x00" - assert_equal 12, r.bitpos("foo", 1) + assert_equal(12, r.bitpos("foo", 1)) end end def test_bitpos_zero_end_is_given target_version "2.9.11" do r.set "foo", "\xff\xff\xff" - assert_equal 24, r.bitpos("foo", 0) - assert_equal 24, r.bitpos("foo", 0, 0) - assert_equal -1, r.bitpos("foo", 0, 0, -1) + assert_equal(24, r.bitpos("foo", 0)) + assert_equal(24, r.bitpos("foo", 0, 0)) + assert_equal(-1, r.bitpos("foo", 0, 0, -1)) end end def test_bitpos_one_intervals target_version "2.9.11" do r.set "foo", "\x00\xff\x00" - assert_equal 8, r.bitpos("foo", 1, 0, -1) - assert_equal 8, r.bitpos("foo", 1, 1, -1) - assert_equal -1, r.bitpos("foo", 1, 2, -1) - assert_equal -1, r.bitpos("foo", 1, 2, 200) - assert_equal 8, r.bitpos("foo", 1, 1, 1) + assert_equal(8, r.bitpos("foo", 1, 0, -1)) + assert_equal(8, r.bitpos("foo", 1, 1, -1)) + assert_equal(-1, r.bitpos("foo", 1, 2, -1)) + assert_equal(-1, r.bitpos("foo", 1, 2, 200)) + assert_equal(8, r.bitpos("foo", 1, 1, 1)) end end From a98f3a6fe0a3e6bcfe14e1da28e593c3fa49b78b Mon Sep 17 00:00:00 2001 From: Damian Janowski Date: Wed, 23 Nov 2016 13:14:01 -0300 Subject: [PATCH 16/34] More traces of 1.8. --- .travis.yml | 14 -------------- lib/redis/pipeline.rb | 6 ------ test/pipelining_commands_test.rb | 4 +--- test/scanning_test.rb | 4 ---- 4 files changed, 1 insertion(+), 27 deletions(-) diff --git a/.travis.yml b/.travis.yml index 438d89596..5cb10e455 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,13 +1,11 @@ language: ruby rvm: - - 1.8.7 - 1.9.3 - 2.0 - 2.1 - 2.2 - 2.3.0 - - jruby-18mode - jruby-19mode - jruby-9.0.5.0 - rbx-2 @@ -36,12 +34,6 @@ branches: matrix: exclude: # hiredis - - rvm: jruby-18mode - gemfile: .travis/Gemfile - env: conn=hiredis REDIS_BRANCH=3.0 - - rvm: jruby-18mode - gemfile: .travis/Gemfile - env: conn=hiredis REDIS_BRANCH=3.2 - rvm: jruby-19mode gemfile: .travis/Gemfile env: conn=hiredis REDIS_BRANCH=3.0 @@ -56,12 +48,6 @@ matrix: env: conn=hiredis REDIS_BRANCH=3.2 # synchrony - - rvm: 1.8.7 - gemfile: .travis/Gemfile - env: conn=synchrony REDIS_BRANCH=3.0 - - rvm: 1.8.7 - gemfile: .travis/Gemfile - env: conn=synchrony REDIS_BRANCH=3.2 - rvm: jruby-18mode gemfile: .travis/Gemfile env: conn=synchrony REDIS_BRANCH=3.0 diff --git a/lib/redis/pipeline.rb b/lib/redis/pipeline.rb index a77f86d9b..3af1e2af9 100644 --- a/lib/redis/pipeline.rb +++ b/lib/redis/pipeline.rb @@ -1,10 +1,4 @@ class Redis - unless defined?(::BasicObject) - class BasicObject - instance_methods.each { |meth| undef_method(meth) unless meth =~ /\A(__|instance_eval)/ } - end - end - class Pipeline attr_accessor :db diff --git a/test/pipelining_commands_test.rb b/test/pipelining_commands_test.rb index a248d3911..2a5115fe7 100644 --- a/test/pipelining_commands_test.rb +++ b/test/pipelining_commands_test.rb @@ -134,9 +134,7 @@ def test_futures_can_be_identified end assert_equal true, @result.is_a?(Redis::Future) - if defined?(::BasicObject) - assert_equal true, @result.is_a?(::BasicObject) - end + assert_equal true, @result.is_a?(::BasicObject) assert_equal Redis::Future, @result.class end diff --git a/test/scanning_test.rb b/test/scanning_test.rb index a0aab1152..8ec0f28c0 100644 --- a/test/scanning_test.rb +++ b/test/scanning_test.rb @@ -1,9 +1,5 @@ require_relative "helper" -unless defined?(Enumerator) - Enumerator = Enumerable::Enumerator -end - class TestScanning < Test::Unit::TestCase include Helper::Client From 50f130d7cac9430a39b9d45171719604cf3fcaae Mon Sep 17 00:00:00 2001 From: Damian Janowski Date: Wed, 23 Nov 2016 22:10:32 -0300 Subject: [PATCH 17/34] Apparently require_relative doesn't work in gemspec. --- redis.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/redis.gemspec b/redis.gemspec index f17159507..8d7c25d97 100644 --- a/redis.gemspec +++ b/redis.gemspec @@ -1,4 +1,4 @@ -require_relative "lib/redis/version" +require "./lib/redis/version" Gem::Specification.new do |s| s.name = "redis" From c239abb43c2dce99468bf94652a3c48b31a1041a Mon Sep 17 00:00:00 2001 From: Damian Janowski Date: Wed, 23 Nov 2016 22:33:59 -0300 Subject: [PATCH 18/34] The underlying client is now `_client`. --- benchmarking/logging.rb | 2 +- lib/redis.rb | 10 ++-- test/blocking_commands_test.rb | 2 +- test/command_map_test.rb | 4 +- test/commands_on_value_types_test.rb | 4 +- test/connection_handling_test.rb | 8 +-- test/error_replies_test.rb | 2 +- test/internals_test.rb | 60 +++++++++---------- test/pipelining_commands_test.rb | 4 +- test/synchrony_driver.rb | 2 +- test/url_param_test.rb | 86 ++++++++++++++-------------- 11 files changed, 93 insertions(+), 91 deletions(-) diff --git a/benchmarking/logging.rb b/benchmarking/logging.rb index 353e91bd0..702ee28ee 100644 --- a/benchmarking/logging.rb +++ b/benchmarking/logging.rb @@ -54,7 +54,7 @@ def stress(redis) end logging_redises.each do |redis| - logger = redis.client.logger + logger = redis._client.logger case logger when Logger diff --git a/lib/redis.rb b/lib/redis.rb index b3a3a06f7..b910761f6 100644 --- a/lib/redis.rb +++ b/lib/redis.rb @@ -3,8 +3,6 @@ class Redis - attr :client - def self.current @current ||= Redis.new end @@ -108,6 +106,10 @@ def commit end end + def _client + @client + end + # Authenticate to the server. # # @param [String] password must match the password specified in the @@ -466,8 +468,8 @@ def restore(key, ttl, serialized_value) def migrate(key, options) host = options[:host] || raise(RuntimeError, ":host not specified") port = options[:port] || raise(RuntimeError, ":port not specified") - db = (options[:db] || client.db).to_i - timeout = (options[:timeout] || client.timeout).to_i + db = (options[:db] || @client.db).to_i + timeout = (options[:timeout] || @client.timeout).to_i synchronize do |client| client.call([:migrate, host, port, key, db, timeout]) diff --git a/test/blocking_commands_test.rb b/test/blocking_commands_test.rb index 233ac04ca..35c0b88d2 100644 --- a/test/blocking_commands_test.rb +++ b/test/blocking_commands_test.rb @@ -158,7 +158,7 @@ def assert_takes_longer_than_client_timeout yield(r) t2 = Time.now - assert timeout == r.client.timeout + assert timeout == r._client.timeout assert delay <= (t2 - t1) end end diff --git a/test/command_map_test.rb b/test/command_map_test.rb index a37250d17..a85163b2e 100644 --- a/test/command_map_test.rb +++ b/test/command_map_test.rb @@ -9,7 +9,7 @@ def test_override_existing_commands assert_equal 2, r.incr("counter") - r.client.command_map[:incr] = :decr + r._client.command_map[:incr] = :decr assert_equal 1, r.incr("counter") end @@ -21,7 +21,7 @@ def test_override_non_existing_commands r.idontexist("key") end - r.client.command_map[:idontexist] = :get + r._client.command_map[:idontexist] = :get assert_equal "value", r.idontexist("key") end diff --git a/test/commands_on_value_types_test.rb b/test/commands_on_value_types_test.rb index 5241835e7..e0a1b3c5a 100644 --- a/test/commands_on_value_types_test.rb +++ b/test/commands_on_value_types_test.rb @@ -224,8 +224,8 @@ def test_migrate end assert ex.message =~ /port not specified/ - default_db = redis.client.db.to_i - default_timeout = redis.client.timeout.to_i + default_db = redis._client.db.to_i + default_timeout = redis._client.timeout.to_i # Test defaults actual = redis.migrate("foo", options) diff --git a/test/connection_handling_test.rb b/test/connection_handling_test.rb index 588b71439..cc9fd5129 100644 --- a/test/connection_handling_test.rb +++ b/test/connection_handling_test.rb @@ -38,7 +38,7 @@ def test_select r.select 14 assert_equal nil, r.get("foo") - r.client.disconnect + r._client.disconnect assert_equal nil, r.get("foo") end @@ -46,7 +46,7 @@ def test_select def test_quit r.quit - assert !r.client.connected? + assert !r._client.connected? end def test_close @@ -146,7 +146,7 @@ def test_shutdown_from_pipeline end assert_equal nil, result - assert !redis.client.connected? + assert !redis._client.connected? end end @@ -186,7 +186,7 @@ def test_shutdown_from_multi_exec end assert_equal nil, result - assert !redis.client.connected? + assert !redis._client.connected? end end diff --git a/test/error_replies_test.rb b/test/error_replies_test.rb index de48b0686..a5f4694ff 100644 --- a/test/error_replies_test.rb +++ b/test/error_replies_test.rb @@ -45,7 +45,7 @@ def test_raise_first_error_reply_in_pipeline def test_recover_from_raise_in__call_loop with_reconnection_check do begin - r.client.call_loop([:invalid_monitor]) do + r._client.call_loop([:invalid_monitor]) do assert false # Should never be executed end rescue => ex diff --git a/test/internals_test.rb b/test/internals_test.rb index 2baba1c3f..c81abb4e4 100644 --- a/test/internals_test.rb +++ b/test/internals_test.rb @@ -46,23 +46,23 @@ def test_provides_a_meaningful_inspect end def test_redis_current - assert_equal "127.0.0.1", Redis.current.client.host - assert_equal 6379, Redis.current.client.port - assert_equal 0, Redis.current.client.db + assert_equal "127.0.0.1", Redis.current._client.host + assert_equal 6379, Redis.current._client.port + assert_equal 0, Redis.current._client.db Redis.current = Redis.new(OPTIONS.merge(:port => 6380, :db => 1)) t = Thread.new do - assert_equal "127.0.0.1", Redis.current.client.host - assert_equal 6380, Redis.current.client.port - assert_equal 1, Redis.current.client.db + assert_equal "127.0.0.1", Redis.current._client.host + assert_equal 6380, Redis.current._client.port + assert_equal 1, Redis.current._client.db end t.join - assert_equal "127.0.0.1", Redis.current.client.host - assert_equal 6380, Redis.current.client.port - assert_equal 1, Redis.current.client.db + assert_equal "127.0.0.1", Redis.current._client.host + assert_equal 6380, Redis.current._client.port + assert_equal 1, Redis.current._client.db end def test_redis_connected? @@ -78,27 +78,27 @@ def test_redis_connected? def test_default_id_with_host_and_port redis = Redis.new(OPTIONS.merge(:host => "host", :port => "1234", :db => 0)) - assert_equal "redis://host:1234/0", redis.client.id + assert_equal "redis://host:1234/0", redis._client.id end def test_default_id_with_host_and_port_and_explicit_scheme redis = Redis.new(OPTIONS.merge(:host => "host", :port => "1234", :db => 0, :scheme => "foo")) - assert_equal "redis://host:1234/0", redis.client.id + assert_equal "redis://host:1234/0", redis._client.id end def test_default_id_with_path redis = Redis.new(OPTIONS.merge(:path => "/tmp/redis.sock", :db => 0)) - assert_equal "redis:///tmp/redis.sock/0", redis.client.id + assert_equal "redis:///tmp/redis.sock/0", redis._client.id end def test_default_id_with_path_and_explicit_scheme redis = Redis.new(OPTIONS.merge(:path => "/tmp/redis.sock", :db => 0, :scheme => "foo")) - assert_equal "redis:///tmp/redis.sock/0", redis.client.id + assert_equal "redis:///tmp/redis.sock/0", redis._client.id end def test_override_id redis = Redis.new(OPTIONS.merge(:id => "test")) - assert_equal redis.client.id, "test" + assert_equal redis._client.id, "test" end def test_timeout @@ -125,7 +125,7 @@ def test_tcp_keepalive redis = Redis.new(OPTIONS.merge(:tcp_keepalive => keepalive)) redis.ping - connection = redis.client.connection + connection = redis._client.connection actual_keepalive = connection.get_tcp_keepalive [:time, :intvl, :probes].each do |key| @@ -215,7 +215,7 @@ def test_retry_only_once_when_read_raises_econnreset redis.ping end - assert !redis.client.connected? + assert !redis._client.connected? end end @@ -231,7 +231,7 @@ def test_retry_with_custom_reconnect_attempts_can_still_fail redis.ping end - assert !redis.client.connected? + assert !redis._client.connected? end end @@ -244,7 +244,7 @@ def test_don_t_retry_when_second_read_in_pipeline_raises_econnreset end end - assert !redis.client.connected? + assert !redis._client.connected? end end @@ -285,14 +285,14 @@ def close_on_connection(seq) def test_retry_on_write_error_by_default close_on_connection([0]) do |redis| - assert_equal "1", redis.client.call(["x" * 128 * 1024]) + assert_equal "1", redis._client.call(["x" * 128 * 1024]) end end def test_retry_on_write_error_when_wrapped_in_with_reconnect_true close_on_connection([0]) do |redis| redis.with_reconnect(true) do - assert_equal "1", redis.client.call(["x" * 128 * 1024]) + assert_equal "1", redis._client.call(["x" * 128 * 1024]) end end end @@ -301,7 +301,7 @@ def test_dont_retry_on_write_error_when_wrapped_in_with_reconnect_false close_on_connection([0]) do |redis| assert_raise Redis::ConnectionError do redis.with_reconnect(false) do - redis.client.call(["x" * 128 * 1024]) + redis._client.call(["x" * 128 * 1024]) end end end @@ -311,7 +311,7 @@ def test_dont_retry_on_write_error_when_wrapped_in_without_reconnect close_on_connection([0]) do |redis| assert_raise Redis::ConnectionError do redis.without_reconnect do - redis.client.call(["x" * 128 * 1024]) + redis._client.call(["x" * 128 * 1024]) end end end @@ -341,23 +341,23 @@ def test_bubble_timeout_without_retrying def test_client_options redis = Redis.new(OPTIONS.merge(:host => "host", :port => 1234, :db => 1, :scheme => "foo")) - assert_equal "host", redis.client.options[:host] - assert_equal 1234, redis.client.options[:port] - assert_equal 1, redis.client.options[:db] - assert_equal "foo", redis.client.options[:scheme] + assert_equal "host", redis._client.options[:host] + assert_equal 1234, redis._client.options[:port] + assert_equal 1, redis._client.options[:db] + assert_equal "foo", redis._client.options[:scheme] end def test_does_not_change_self_client_options redis = Redis.new(OPTIONS.merge(:host => "host", :port => 1234, :db => 1, :scheme => "foo")) - options = redis.client.options + options = redis._client.options options[:host] << "new_host" options[:scheme] << "bar" options.merge!(:db => 0) - assert_equal "host", redis.client.options[:host] - assert_equal 1, redis.client.options[:db] - assert_equal "foo", redis.client.options[:scheme] + assert_equal "host", redis._client.options[:host] + assert_equal 1, redis._client.options[:db] + assert_equal "foo", redis._client.options[:scheme] end def test_resolves_localhost diff --git a/test/pipelining_commands_test.rb b/test/pipelining_commands_test.rb index 2a5115fe7..3f07d15e2 100644 --- a/test/pipelining_commands_test.rb +++ b/test/pipelining_commands_test.rb @@ -221,7 +221,7 @@ def test_pipeline_select_client_db p2.select 2 end - assert_equal 2, r.client.db + assert_equal 2, r._client.db end def test_nested_pipeline_select_client_db @@ -233,6 +233,6 @@ def test_nested_pipeline_select_client_db end end - assert_equal 3, r.client.db + assert_equal 3, r._client.db end end diff --git a/test/synchrony_driver.rb b/test/synchrony_driver.rb index 622edd340..325876a20 100644 --- a/test/synchrony_driver.rb +++ b/test/synchrony_driver.rb @@ -53,7 +53,7 @@ assert_equal "s2", r.lpop("foo") assert_equal "s1", r.lpop("foo") - assert_equal "OK", r.client.call(:quit) + assert_equal "OK", r._client.call(:quit) assert_equal "PONG", r.ping diff --git a/test/url_param_test.rb b/test/url_param_test.rb index 48623d837..a30167c5e 100644 --- a/test/url_param_test.rb +++ b/test/url_param_test.rb @@ -7,104 +7,104 @@ class TestUrlParam < Test::Unit::TestCase def test_url_defaults_to_______________ redis = Redis.new - assert_equal "127.0.0.1", redis.client.host - assert_equal 6379, redis.client.port - assert_equal 0, redis.client.db - assert_equal nil, redis.client.password + assert_equal "127.0.0.1", redis._client.host + assert_equal 6379, redis._client.port + assert_equal 0, redis._client.db + assert_equal nil, redis._client.password end def test_allows_to_pass_in_a_url redis = Redis.new :url => "redis://:secr3t@foo.com:999/2" - assert_equal "foo.com", redis.client.host - assert_equal 999, redis.client.port - assert_equal 2, redis.client.db - assert_equal "secr3t", redis.client.password + assert_equal "foo.com", redis._client.host + assert_equal 999, redis._client.port + assert_equal 2, redis._client.db + assert_equal "secr3t", redis._client.password end def test_allows_to_pass_in_a_url_with_string_key redis = Redis.new "url" => "redis://:secr3t@foo.com:999/2" - assert_equal "foo.com", redis.client.host - assert_equal 999, redis.client.port - assert_equal 2, redis.client.db - assert_equal "secr3t", redis.client.password + assert_equal "foo.com", redis._client.host + assert_equal 999, redis._client.port + assert_equal 2, redis._client.db + assert_equal "secr3t", redis._client.password end def test_unescape_password_from_url redis = Redis.new :url => "redis://:secr3t%3A@foo.com:999/2" - assert_equal "secr3t:", redis.client.password + assert_equal "secr3t:", redis._client.password end def test_unescape_password_from_url_with_string_key redis = Redis.new "url" => "redis://:secr3t%3A@foo.com:999/2" - assert_equal "secr3t:", redis.client.password + assert_equal "secr3t:", redis._client.password end def test_does_not_unescape_password_when_explicitly_passed redis = Redis.new :url => "redis://:secr3t%3A@foo.com:999/2", :password => "secr3t%3A" - assert_equal "secr3t%3A", redis.client.password + assert_equal "secr3t%3A", redis._client.password end def test_does_not_unescape_password_when_explicitly_passed_with_string_key redis = Redis.new :url => "redis://:secr3t%3A@foo.com:999/2", "password" => "secr3t%3A" - assert_equal "secr3t%3A", redis.client.password + assert_equal "secr3t%3A", redis._client.password end def test_override_url_if_path_option_is_passed redis = Redis.new :url => "redis://:secr3t@foo.com/foo:999/2", :path => "/tmp/redis.sock" - assert_equal "/tmp/redis.sock", redis.client.path - assert_equal nil, redis.client.host - assert_equal nil, redis.client.port + assert_equal "/tmp/redis.sock", redis._client.path + assert_equal nil, redis._client.host + assert_equal nil, redis._client.port end def test_override_url_if_path_option_is_passed_with_string_key redis = Redis.new :url => "redis://:secr3t@foo.com/foo:999/2", "path" => "/tmp/redis.sock" - assert_equal "/tmp/redis.sock", redis.client.path - assert_equal nil, redis.client.host - assert_equal nil, redis.client.port + assert_equal "/tmp/redis.sock", redis._client.path + assert_equal nil, redis._client.host + assert_equal nil, redis._client.port end def test_overrides_url_if_another_connection_option_is_passed redis = Redis.new :url => "redis://:secr3t@foo.com:999/2", :port => 1000 - assert_equal "foo.com", redis.client.host - assert_equal 1000, redis.client.port - assert_equal 2, redis.client.db - assert_equal "secr3t", redis.client.password + assert_equal "foo.com", redis._client.host + assert_equal 1000, redis._client.port + assert_equal 2, redis._client.db + assert_equal "secr3t", redis._client.password end def test_overrides_url_if_another_connection_option_is_passed_with_string_key redis = Redis.new :url => "redis://:secr3t@foo.com:999/2", "port" => 1000 - assert_equal "foo.com", redis.client.host - assert_equal 1000, redis.client.port - assert_equal 2, redis.client.db - assert_equal "secr3t", redis.client.password + assert_equal "foo.com", redis._client.host + assert_equal 1000, redis._client.port + assert_equal 2, redis._client.db + assert_equal "secr3t", redis._client.password end def test_does_not_overrides_url_if_a_nil_option_is_passed redis = Redis.new :url => "redis://:secr3t@foo.com:999/2", :port => nil - assert_equal "foo.com", redis.client.host - assert_equal 999, redis.client.port - assert_equal 2, redis.client.db - assert_equal "secr3t", redis.client.password + assert_equal "foo.com", redis._client.host + assert_equal 999, redis._client.port + assert_equal 2, redis._client.db + assert_equal "secr3t", redis._client.password end def test_does_not_overrides_url_if_a_nil_option_is_passed_with_string_key redis = Redis.new :url => "redis://:secr3t@foo.com:999/2", "port" => nil - assert_equal "foo.com", redis.client.host - assert_equal 999, redis.client.port - assert_equal 2, redis.client.db - assert_equal "secr3t", redis.client.password + assert_equal "foo.com", redis._client.host + assert_equal 999, redis._client.port + assert_equal 2, redis._client.db + assert_equal "secr3t", redis._client.password end def test_does_not_modify_the_passed_options @@ -120,10 +120,10 @@ def test_uses_redis_url_over_default_if_available redis = Redis.new - assert_equal "foo.com", redis.client.host - assert_equal 999, redis.client.port - assert_equal 2, redis.client.db - assert_equal "secr3t", redis.client.password + assert_equal "foo.com", redis._client.host + assert_equal 999, redis._client.port + assert_equal 2, redis._client.db + assert_equal "secr3t", redis._client.password ENV.delete("REDIS_URL") end @@ -131,6 +131,6 @@ def test_uses_redis_url_over_default_if_available def test_defaults_to_localhost redis = Redis.new(:url => "redis:///") - assert_equal "127.0.0.1", redis.client.host + assert_equal "127.0.0.1", redis._client.host end end From 31385074b6bbeef7e1f9849b0b1149b9ef870e2d Mon Sep 17 00:00:00 2001 From: Damian Janowski Date: Wed, 23 Nov 2016 22:43:08 -0300 Subject: [PATCH 19/34] No longer caring about backwards compatibility for Redis#client. --- lib/redis.rb | 3 +-- test/remote_server_control_commands_test.rb | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/redis.rb b/lib/redis.rb index 27021ef10..261cb3034 100644 --- a/lib/redis.rb +++ b/lib/redis.rb @@ -204,8 +204,7 @@ def config(action, *args) # # @param [String, Symbol] subcommand e.g. `kill`, `list`, `getname`, `setname` # @return [String, Hash] depends on subcommand - def client(subcommand=nil, *args) - return @client if subcommand.nil? # for backward compatibility + def client(subcommand = nil, *args) synchronize do |client| client.call([:client, subcommand] + args) do |reply| if subcommand.to_s == "list" diff --git a/test/remote_server_control_commands_test.rb b/test/remote_server_control_commands_test.rb index 67dc620c2..9040579e7 100644 --- a/test/remote_server_control_commands_test.rb +++ b/test/remote_server_control_commands_test.rb @@ -115,7 +115,7 @@ def test_slowlog end def test_client - assert_equal r.instance_variable_get(:@client), r.client + assert_equal r.instance_variable_get(:@client), r._client end def test_client_list From 5ec801ddfc71658d88a53c6bc46d31bb3ab43ede Mon Sep 17 00:00:00 2001 From: Damian Janowski Date: Wed, 23 Nov 2016 22:43:59 -0300 Subject: [PATCH 20/34] Update changelog for CLIENT commands. --- CHANGELOG.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4b0960bb1..5e8ab4b76 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,9 +6,12 @@ * Removed `Redis::Distributed`. +* Added support for `CLIENT` commands. The lower-level client can be + accessed via `Redis#_client`. + # 3.3.2 -* Added support for SPOP with COUNT. See #628. +* Added support for `SPOP` with COUNT. See #628. * Fixed connection glitches when using SSL. See #644. From 1529bda04f44bb87d9ee7f8de24246ab5bbb44e4 Mon Sep 17 00:00:00 2001 From: Damian Janowski Date: Wed, 23 Nov 2016 22:47:30 -0300 Subject: [PATCH 21/34] Using make. --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 5cb10e455..982cf1bea 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,7 @@ language: ruby +script: make test + rvm: - 1.9.3 - 2.0 From 8a1e6c860174110f7bf0295ef321c1a044a545c9 Mon Sep 17 00:00:00 2001 From: Damian Janowski Date: Wed, 23 Nov 2016 23:00:40 -0300 Subject: [PATCH 22/34] Our new support matrix. --- .travis.yml | 33 ++++++++++++--------------------- 1 file changed, 12 insertions(+), 21 deletions(-) diff --git a/.travis.yml b/.travis.yml index 982cf1bea..72488d957 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,14 +3,11 @@ language: ruby script: make test rvm: - - 1.9.3 - - 2.0 - 2.1 - 2.2 - - 2.3.0 - - jruby-19mode - - jruby-9.0.5.0 - - rbx-2 + - 2.3 + - jruby-9 + - rbx-3 gemfile: ".travis/Gemfile" @@ -36,40 +33,34 @@ branches: matrix: exclude: # hiredis - - rvm: jruby-19mode + - rvm: jruby-9 gemfile: .travis/Gemfile env: conn=hiredis REDIS_BRANCH=3.0 - - rvm: jruby-19mode + - rvm: jruby-9 gemfile: .travis/Gemfile env: conn=hiredis REDIS_BRANCH=3.2 - - rvm: jruby-9.0.5.0 + - rvm: jruby-9 gemfile: .travis/Gemfile env: conn=hiredis REDIS_BRANCH=3.0 - - rvm: jruby-9.0.5.0 + - rvm: jruby-9 gemfile: .travis/Gemfile env: conn=hiredis REDIS_BRANCH=3.2 # synchrony - - rvm: jruby-18mode + - rvm: jruby-9 gemfile: .travis/Gemfile env: conn=synchrony REDIS_BRANCH=3.0 - - rvm: jruby-18mode + - rvm: jruby-9 gemfile: .travis/Gemfile env: conn=synchrony REDIS_BRANCH=3.2 - - rvm: jruby-19mode + - rvm: jruby-9 gemfile: .travis/Gemfile env: conn=synchrony REDIS_BRANCH=3.0 - - rvm: jruby-19mode - gemfile: .travis/Gemfile - env: conn=synchrony REDIS_BRANCH=3.2 - - rvm: jruby-9.0.5.0 - gemfile: .travis/Gemfile - env: conn=synchrony REDIS_BRANCH=3.0 - - rvm: jruby-9.0.5.0 + - rvm: jruby-9 gemfile: .travis/Gemfile env: conn=synchrony REDIS_BRANCH=3.2 allow_failures: - - rvm: rbx-2 + - rvm: rbx-3 notifications: irc: From 39fa0f792f8fb2e1028be19e381a6c9634e75e75 Mon Sep 17 00:00:00 2001 From: Damian Janowski Date: Wed, 23 Nov 2016 23:07:27 -0300 Subject: [PATCH 23/34] Fix requires. --- lib/redis/connection/hiredis.rb | 4 ++-- lib/redis/connection/synchrony.rb | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/redis/connection/hiredis.rb b/lib/redis/connection/hiredis.rb index f4056d386..f7baf31b6 100644 --- a/lib/redis/connection/hiredis.rb +++ b/lib/redis/connection/hiredis.rb @@ -1,5 +1,5 @@ -require "redis/connection/registry" -require "redis/errors" +require_relative "registry" +require_relative "../errors" require "hiredis/connection" require "timeout" diff --git a/lib/redis/connection/synchrony.rb b/lib/redis/connection/synchrony.rb index 9f0b67cdc..c8b3dab9b 100644 --- a/lib/redis/connection/synchrony.rb +++ b/lib/redis/connection/synchrony.rb @@ -1,6 +1,6 @@ -require "redis/connection/command_helper" -require "redis/connection/registry" -require "redis/errors" +require_relative "command_helper" +require_relative "registry" +require_relative "../errors" require "em-synchrony" require "hiredis/reader" From 9cd7510cb19be29e65518ef7a1298a0d1a79f5be Mon Sep 17 00:00:00 2001 From: Damian Janowski Date: Wed, 23 Nov 2016 23:29:02 -0300 Subject: [PATCH 24/34] Refreshments. --- README.md | 106 +++++++++++++++----------------------------------- redis.gemspec | 4 +- 2 files changed, 32 insertions(+), 78 deletions(-) diff --git a/README.md b/README.md index 138bf9c15..a18525e87 100644 --- a/README.md +++ b/README.md @@ -1,46 +1,17 @@ # redis-rb [![Build Status][travis-image]][travis-link] [![Inline docs][inchpages-image]][inchpages-link] -[travis-image]: https://secure.travis-ci.org/redis/redis-rb.png?branch=master -[travis-link]: http://travis-ci.org/redis/redis-rb -[travis-home]: http://travis-ci.org/ -[inchpages-image]: http://inch-ci.org/github/redis/redis-rb.png -[inchpages-link]: http://inch-ci.org/github/redis/redis-rb +A Ruby client that tries to match [Redis][redis-home]' API one-to-one, while still +providing an idiomatic interface. -A Ruby client library for [Redis][redis-home]. - -[redis-home]: http://redis.io - -A Ruby client that tries to match Redis' API one-to-one, while still -providing an idiomatic interface. It features thread-safety, client-side -sharding, pipelining, and an obsession for performance. - -## Upgrading from 2.x to 3.0 - -Please refer to the [CHANGELOG][changelog-3.0.0] for a summary of the -most important changes, as well as a full list of changes. - -[changelog-3.0.0]: https://github.com/redis/redis-rb/blob/master/CHANGELOG.md#300 ## Getting started -To install **redis-rb**, run the following command: - -``` - gem install redis -``` - -Or if you are using **bundler**, add +Install with: ``` - gem 'redis', '~>3.2' +$ gem install redis ``` -to your `Gemfile`, and run `bundle install` - -As of version 2.0 this client only targets Redis version 2.0 and higher. -You can use an older version of this client if you need to interface -with a Redis instance older than 2.0, but this is no longer supported. - You can connect to Redis by instantiating the `Redis` class: ```ruby @@ -54,17 +25,15 @@ listening on `localhost`, port 6379. If you need to connect to a remote server or a different port, try: ```ruby -redis = Redis.new(:host => "10.0.1.1", :port => 6380, :db => 15) +redis = Redis.new(host: "10.0.1.1", port: 6380, db: 15) ``` You can also specify connection options as a [`redis://` URL][redis-url]: ```ruby -redis = Redis.new(:url => "redis://:p4ssw0rd@10.0.1.1:6380/15") +redis = Redis.new(url: "redis://:p4ssw0rd@10.0.1.1:6380/15") ``` -[redis-url]: http://www.iana.org/assignments/uri-schemes/prov/redis - By default, the client will try to read the `REDIS_URL` environment variable and use that as URL to connect to. The above statement is therefore equivalent to setting this environment variable and calling `Redis.new` without arguments. @@ -72,13 +41,13 @@ to setting this environment variable and calling `Redis.new` without arguments. To connect to Redis listening on a Unix socket, try: ```ruby -redis = Redis.new(:path => "/tmp/redis.sock") +redis = Redis.new(path: "/tmp/redis.sock") ``` To connect to a password protected Redis instance, use: ```ruby -redis = Redis.new(:password => "mysecret") +redis = Redis.new(password: "mysecret") ``` The Redis class exports methods that are named identical to the commands @@ -86,8 +55,6 @@ they execute. The arguments these methods accept are often identical to the arguments specified on the [Redis website][redis-commands]. For instance, the `SET` and `GET` commands can be called like this: -[redis-commands]: http://redis.io/commands - ```ruby redis.set("mykey", "hello world") # => "OK" @@ -96,24 +63,22 @@ redis.get("mykey") # => "hello world" ``` -All commands, their arguments and return values are documented, and -available on [rdoc.info][rdoc]. - -[rdoc]: http://rdoc.info/github/redis/redis-rb/ +All commands, their arguments, and return values are documented and +available on [RubyDoc.info][rubydoc]. ## Sentinel support -The client is able to perform automatic failovers by using [Redis +The client is able to perform automatic failover by using [Redis Sentinel](http://redis.io/topics/sentinel). Make sure to run Redis 2.8+ if you want to use this feature. To connect using Sentinel, use: ```ruby -SENTINELS = [{:host => "127.0.0.1", :port => 26380}, - {:host => "127.0.0.1", :port => 26381}] +SENTINELS = [{ host: "127.0.0.1", port: 26380 }, + { host: "127.0.0.1", port: 26381 }] -redis = Redis.new(:url => "redis://mymaster", :sentinels => SENTINELS, :role => :master) +redis = Redis.new(url: "redis://mymaster", sentinels: SENTINELS, role: :master) ``` * The master name identifies a group of Redis instances composed of a master @@ -374,37 +339,28 @@ redis = Redis.new(:driver => :synchrony) ## Testing -This library is tested using [Travis][travis-home], where it is tested -against the following interpreters and drivers: - -* MRI 1.8.7 (drivers: ruby, hiredis) -* MRI 1.9.3 (drivers: ruby, hiredis, synchrony) -* MRI 2.0 (drivers: ruby, hiredis, synchrony) -* MRI 2.1 (drivers: ruby, hiredis, synchrony) -* MRI 2.2 (drivers: ruby, hiredis, synchrony) -* MRI 2.3 (drivers: ruby, hiredis, synchrony) -* JRuby 1.7 (1.8 mode) (drivers: ruby) -* JRuby 1.7 (1.9 mode) (drivers: ruby) +This library is tested against recent Ruby and Redis versions. +Check [Travis][travis-link] for the exact versions supported. ## Contributors -(ordered chronologically with more than 5 commits, see `git shortlog -sn` for -all contributors) - -* Ezra Zygmuntowicz -* Taylor Weibley -* Matthew Clark -* Brian McKinney -* Luca Guidi -* Salvatore Sanfilippo -* Chris Wanstrath -* Damian Janowski -* Michel Martens -* Nick Quaranto -* Pieter Noordhuis -* Ilya Grigorik +Several people contributed to redis-rb, but we would like to especially +mention Ezra Zygmuntowicz. Ezra introduced the Ruby community to many +new cool technologies, like Redis. He wrote the first version of this +client and evangelized Redis in Rubyland. Thank you, Ezra. ## Contributing [Fork the project](https://github.com/redis/redis-rb) and send pull requests. You can also ask for help at `#redis-rb` on Freenode. + + +[inchpages-image]: https://inch-ci.org/github/redis/redis-rb.png +[inchpages-link]: https://inch-ci.org/github/redis/redis-rb +[redis-commands]: http://redis.io/commands +[redis-home]: http://redis.io +[redis-url]: http://www.iana.org/assignments/uri-schemes/prov/redis +[travis-home]: https://travis-ci.org/ +[travis-image]: https://secure.travis-ci.org/redis/redis-rb.png?branch=master +[travis-link]: https://travis-ci.org/redis/redis-rb +[rubydoc]: http://www.rubydoc.info/gems/redis diff --git a/redis.gemspec b/redis.gemspec index 8d7c25d97..85d5d2dfe 100644 --- a/redis.gemspec +++ b/redis.gemspec @@ -11,8 +11,7 @@ Gem::Specification.new do |s| s.description = <<-EOS A Ruby client that tries to match Redis' API one-to-one, while still - providing an idiomatic interface. It features thread-safety, - client-side sharding, pipelining, and an obsession for performance. + providing an idiomatic interface. EOS s.license = "MIT" @@ -35,6 +34,5 @@ Gem::Specification.new do |s| s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) } - s.add_development_dependency("rake", "<11.0.0") s.add_development_dependency("test-unit", "3.1.5") end From 36af4743aa7b2b900bef893213e83d7c12e0b332 Mon Sep 17 00:00:00 2001 From: Damian Janowski Date: Wed, 23 Nov 2016 23:40:32 -0300 Subject: [PATCH 25/34] Fix up requires and confusing environment variable names. --- .travis.yml | 30 ++++++++++++++-------------- redis.gemspec | 2 ++ test/client_test.rb | 2 +- test/helper.rb | 10 +++++----- test/sentinel_command_test.rb | 4 +--- test/ssl_test.rb | 4 +--- test/support/connection/hiredis.rb | 2 +- test/support/connection/synchrony.rb | 2 +- test/synchrony_driver.rb | 11 +++++----- 9 files changed, 32 insertions(+), 35 deletions(-) diff --git a/.travis.yml b/.travis.yml index 72488d957..824e107af 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,13 +18,13 @@ env: - VERBOSE=true - TIMEOUT=1 matrix: - - conn=ruby REDIS_BRANCH=3.0 - - conn=ruby REDIS_BRANCH=3.2 - - conn=hiredis REDIS_BRANCH=3.0 - - conn=hiredis REDIS_BRANCH=3.2 - - conn=synchrony REDIS_BRANCH=3.0 - - conn=synchrony REDIS_BRANCH=3.2 - - conn=ruby REDIS_BRANCH=unstable + - DRIVER=ruby REDIS_BRANCH=3.0 + - DRIVER=ruby REDIS_BRANCH=3.2 + - DRIVER=hiredis REDIS_BRANCH=3.0 + - DRIVER=hiredis REDIS_BRANCH=3.2 + - DRIVER=synchrony REDIS_BRANCH=3.0 + - DRIVER=synchrony REDIS_BRANCH=3.2 + - DRIVER=ruby REDIS_BRANCH=unstable branches: only: @@ -35,30 +35,30 @@ matrix: # hiredis - rvm: jruby-9 gemfile: .travis/Gemfile - env: conn=hiredis REDIS_BRANCH=3.0 + env: DRIVER=hiredis REDIS_BRANCH=3.0 - rvm: jruby-9 gemfile: .travis/Gemfile - env: conn=hiredis REDIS_BRANCH=3.2 + env: DRIVER=hiredis REDIS_BRANCH=3.2 - rvm: jruby-9 gemfile: .travis/Gemfile - env: conn=hiredis REDIS_BRANCH=3.0 + env: DRIVER=hiredis REDIS_BRANCH=3.0 - rvm: jruby-9 gemfile: .travis/Gemfile - env: conn=hiredis REDIS_BRANCH=3.2 + env: DRIVER=hiredis REDIS_BRANCH=3.2 # synchrony - rvm: jruby-9 gemfile: .travis/Gemfile - env: conn=synchrony REDIS_BRANCH=3.0 + env: DRIVER=synchrony REDIS_BRANCH=3.0 - rvm: jruby-9 gemfile: .travis/Gemfile - env: conn=synchrony REDIS_BRANCH=3.2 + env: DRIVER=synchrony REDIS_BRANCH=3.2 - rvm: jruby-9 gemfile: .travis/Gemfile - env: conn=synchrony REDIS_BRANCH=3.0 + env: DRIVER=synchrony REDIS_BRANCH=3.0 - rvm: jruby-9 gemfile: .travis/Gemfile - env: conn=synchrony REDIS_BRANCH=3.2 + env: DRIVER=synchrony REDIS_BRANCH=3.2 allow_failures: - rvm: rbx-3 diff --git a/redis.gemspec b/redis.gemspec index 85d5d2dfe..85efaa80d 100644 --- a/redis.gemspec +++ b/redis.gemspec @@ -35,4 +35,6 @@ Gem::Specification.new do |s| s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) } s.add_development_dependency("test-unit", "3.1.5") + s.add_development_dependency("hiredis") + s.add_development_dependency("em-synchrony") end diff --git a/test/client_test.rb b/test/client_test.rb index 1d0b8d3a6..b8244b429 100644 --- a/test/client_test.rb +++ b/test/client_test.rb @@ -1,4 +1,4 @@ -require File.expand_path("helper", File.dirname(__FILE__)) +require_relative "helper" class TestClient < Test::Unit::TestCase diff --git a/test/helper.rb b/test/helper.rb index 5242fb878..bb3b213d4 100644 --- a/test/helper.rb +++ b/test/helper.rb @@ -4,13 +4,13 @@ $VERBOSE = true -ENV["conn"] ||= "ruby" +ENV["DRIVER"] ||= "ruby" require_relative "../lib/redis" -require_relative "../lib/redis/connection/#{ENV["conn"]}" +require_relative "../lib/redis/connection/#{ENV["DRIVER"]}" require_relative "support/redis_mock" -require_relative "support/connection/#{ENV["conn"]}" +require_relative "support/connection/#{ENV["DRIVER"]}" PORT = 6381 OPTIONS = {:port => PORT, :db => 15, :timeout => Float(ENV["TIMEOUT"] || 0.1)} @@ -45,7 +45,7 @@ def init(redis) end def driver(*drivers, &blk) - if drivers.map(&:to_s).include?(ENV["conn"]) + if drivers.map(&:to_s).include?(ENV["DRIVER"]) class_eval(&blk) end end @@ -172,7 +172,7 @@ def _format_options(options) end def _new_client(options = {}) - Redis.new(_format_options(options).merge(:driver => ENV["conn"])) + Redis.new(_format_options(options).merge(:driver => ENV["DRIVER"])) end end diff --git a/test/sentinel_command_test.rb b/test/sentinel_command_test.rb index 1b57b1ded..50153712a 100644 --- a/test/sentinel_command_test.rb +++ b/test/sentinel_command_test.rb @@ -1,6 +1,4 @@ -# encoding: UTF-8 - -require File.expand_path("helper", File.dirname(__FILE__)) +require_relative "helper" class SentinelCommandsTest < Test::Unit::TestCase diff --git a/test/ssl_test.rb b/test/ssl_test.rb index 075e7a74e..1523c99a4 100644 --- a/test/ssl_test.rb +++ b/test/ssl_test.rb @@ -1,6 +1,4 @@ -# encoding: UTF-8 - -require File.expand_path("helper", File.dirname(__FILE__)) +require_relative "helper" class SslTest < Test::Unit::TestCase diff --git a/test/support/connection/hiredis.rb b/test/support/connection/hiredis.rb index f2ccbca5f..46078c1c5 100644 --- a/test/support/connection/hiredis.rb +++ b/test/support/connection/hiredis.rb @@ -1 +1 @@ -require "support/wire/thread" +require_relative "../wire/thread" diff --git a/test/support/connection/synchrony.rb b/test/support/connection/synchrony.rb index 80acb0afe..90b516b5f 100644 --- a/test/support/connection/synchrony.rb +++ b/test/support/connection/synchrony.rb @@ -1,4 +1,4 @@ -require "support/wire/synchrony" +require_relative "../wire/synchrony" module Helper def around diff --git a/test/synchrony_driver.rb b/test/synchrony_driver.rb index 325876a20..842c74504 100644 --- a/test/synchrony_driver.rb +++ b/test/synchrony_driver.rb @@ -1,11 +1,10 @@ -require 'em-synchrony' -require 'em-synchrony/connection_pool' +require "em-synchrony" +require "em-synchrony/connection_pool" -require 'redis' -require 'redis/connection/synchrony' +require_relative "../lib/redis" +require_relative "../lib/redis/connection/synchrony" - -require_relative "./helper" +require_relative "helper" PORT = 6381 OPTIONS = {:port => PORT, :db => 15} From 31919c20b9e75570820ee396746e1dcdd22a34f7 Mon Sep 17 00:00:00 2001 From: Damian Janowski Date: Wed, 23 Nov 2016 23:52:00 -0300 Subject: [PATCH 26/34] Try Ruby 2.3 with latest rvm. --- .travis.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index 824e107af..a6f665751 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,6 +2,9 @@ language: ruby script: make test +before_install: + - rvm get stable + rvm: - 2.1 - 2.2 From 06d383ff954b3e962f78b87dfaac4136d89865aa Mon Sep 17 00:00:00 2001 From: Damian Janowski Date: Thu, 24 Nov 2016 00:02:01 -0300 Subject: [PATCH 27/34] No skip. --- test/fork_safety_test.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/fork_safety_test.rb b/test/fork_safety_test.rb index 8c35658eb..73b541f74 100644 --- a/test/fork_safety_test.rb +++ b/test/fork_safety_test.rb @@ -29,7 +29,6 @@ def test_fork_safety rescue NotImplementedError => error raise unless error.message =~ /fork is not available/ - return skip(error.message) end def test_fork_safety_with_enabled_inherited_socket @@ -56,7 +55,6 @@ def test_fork_safety_with_enabled_inherited_socket rescue NotImplementedError => error raise unless error.message =~ /fork is not available/ - return skip(error.message) end end end From 113ad0cf12c3735f0d28f7f5db50c9b8c120187d Mon Sep 17 00:00:00 2001 From: Damian Janowski Date: Thu, 24 Nov 2016 00:03:01 -0300 Subject: [PATCH 28/34] 4.0.0 RC1. --- lib/redis/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/redis/version.rb b/lib/redis/version.rb index 0cf976a23..b5610308b 100644 --- a/lib/redis/version.rb +++ b/lib/redis/version.rb @@ -1,3 +1,3 @@ class Redis - VERSION = "3.3.2" + VERSION = "4.0.0.rc1" end From e8317bcc64bffc47ac402211dcda67d7c8223fb8 Mon Sep 17 00:00:00 2001 From: Damian Janowski Date: Thu, 24 Nov 2016 00:25:38 -0300 Subject: [PATCH 29/34] Travis, let's try specifying the exact 2.3 version. --- .travis.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index a6f665751..f4e7a4534 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,13 +2,10 @@ language: ruby script: make test -before_install: - - rvm get stable - rvm: - 2.1 - 2.2 - - 2.3 + - 2.3.3 - jruby-9 - rbx-3 From c6a7a6c48948b60c801cd14a9a4be65b2082679d Mon Sep 17 00:00:00 2001 From: Connor McEntee Date: Wed, 30 Nov 2016 09:06:34 -0800 Subject: [PATCH 30/34] Wrap exceptions for missing socket with CannotConnectError --- lib/redis/client.rb | 1 + test/internals_test.rb | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/lib/redis/client.rb b/lib/redis/client.rb index 4f8b53b08..798787e42 100644 --- a/lib/redis/client.rb +++ b/lib/redis/client.rb @@ -340,6 +340,7 @@ def establish_connection Errno::EHOSTDOWN, Errno::EHOSTUNREACH, Errno::ENETUNREACH, + Errno::ENOENT, Errno::ETIMEDOUT raise CannotConnectError, "Error connecting to Redis on #{location} (#{$!.class})" diff --git a/test/internals_test.rb b/test/internals_test.rb index c81abb4e4..8333618bd 100644 --- a/test/internals_test.rb +++ b/test/internals_test.rb @@ -158,6 +158,13 @@ def test_connection_timeout assert (Time.now - start_time) <= opts[:timeout] end + def test_missing_socket + opts = { :path => '/missing.sock' } + assert_raise Redis::CannotConnectError do + Redis.new(opts).ping + end + end + def close_on_ping(seq, options = {}) $request = 0 From ac5fbde5107ceb7837d179ed75216c69abf21901 Mon Sep 17 00:00:00 2001 From: Damian Janowski Date: Fri, 25 Aug 2017 12:10:55 -0300 Subject: [PATCH 31/34] Bring back Redis::Distributed. This reverts commit c4ebeda2e26d5182b832ad850f06fa2d72e3b77a. --- CHANGELOG.md | 2 - examples/dist_redis.rb | 43 + lib/redis/distributed.rb | 873 ++++++++++++++++++ lib/redis/hash_ring.rb | 131 +++ test/blocking_commands_test.rb | 147 +-- test/commands_on_hashes_test.rb | 159 +--- test/commands_on_hyper_log_log_test.rb | 55 +- test/commands_on_lists_test.rb | 140 +-- test/commands_on_sets_test.rb | 137 +-- test/commands_on_sorted_sets_test.rb | 313 +------ test/commands_on_strings_test.rb | 243 +---- test/commands_on_value_types_test.rb | 119 +-- test/distributed_blocking_commands_test.rb | 44 + test/distributed_commands_on_hashes_test.rb | 8 + ...tributed_commands_on_hyper_log_log_test.rb | 31 + test/distributed_commands_on_lists_test.rb | 20 + test/distributed_commands_on_sets_test.rb | 81 ++ ...istributed_commands_on_sorted_sets_test.rb | 16 + test/distributed_commands_on_strings_test.rb | 57 ++ ...istributed_commands_on_value_types_test.rb | 93 ++ ...uted_commands_requiring_clustering_test.rb | 162 ++++ test/distributed_connection_handling_test.rb | 21 + test/distributed_internals_test.rb | 68 ++ test/distributed_key_tags_test.rb | 50 + ...buted_persistence_control_commands_test.rb | 24 + test/distributed_publish_subscribe_test.rb | 90 ++ ...ted_remote_server_control_commands_test.rb | 64 ++ test/distributed_scripting_test.rb | 100 ++ test/distributed_sorting_test.rb | 18 + test/distributed_test.rb | 56 ++ test/distributed_transactions_test.rb | 30 + test/helper.rb | 22 + test/lint/blocking_commands.rb | 150 +++ test/lint/hashes.rb | 162 ++++ test/lint/hyper_log_log.rb | 60 ++ test/lint/lists.rb | 143 +++ test/lint/sets.rb | 140 +++ test/lint/sorted_sets.rb | 316 +++++++ test/lint/strings.rb | 246 +++++ test/lint/value_types.rb | 122 +++ 40 files changed, 3457 insertions(+), 1299 deletions(-) create mode 100644 examples/dist_redis.rb create mode 100644 lib/redis/distributed.rb create mode 100644 lib/redis/hash_ring.rb create mode 100644 test/distributed_blocking_commands_test.rb create mode 100644 test/distributed_commands_on_hashes_test.rb create mode 100644 test/distributed_commands_on_hyper_log_log_test.rb create mode 100644 test/distributed_commands_on_lists_test.rb create mode 100644 test/distributed_commands_on_sets_test.rb create mode 100644 test/distributed_commands_on_sorted_sets_test.rb create mode 100644 test/distributed_commands_on_strings_test.rb create mode 100644 test/distributed_commands_on_value_types_test.rb create mode 100644 test/distributed_commands_requiring_clustering_test.rb create mode 100644 test/distributed_connection_handling_test.rb create mode 100644 test/distributed_internals_test.rb create mode 100644 test/distributed_key_tags_test.rb create mode 100644 test/distributed_persistence_control_commands_test.rb create mode 100644 test/distributed_publish_subscribe_test.rb create mode 100644 test/distributed_remote_server_control_commands_test.rb create mode 100644 test/distributed_scripting_test.rb create mode 100644 test/distributed_sorting_test.rb create mode 100644 test/distributed_test.rb create mode 100644 test/distributed_transactions_test.rb create mode 100644 test/lint/blocking_commands.rb create mode 100644 test/lint/hashes.rb create mode 100644 test/lint/hyper_log_log.rb create mode 100644 test/lint/lists.rb create mode 100644 test/lint/sets.rb create mode 100644 test/lint/sorted_sets.rb create mode 100644 test/lint/strings.rb create mode 100644 test/lint/value_types.rb diff --git a/CHANGELOG.md b/CHANGELOG.md index 5e8ab4b76..362c03a6d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,8 +4,6 @@ * Removed `Redis#[]` and `Redis#[]=` aliases. -* Removed `Redis::Distributed`. - * Added support for `CLIENT` commands. The lower-level client can be accessed via `Redis#_client`. diff --git a/examples/dist_redis.rb b/examples/dist_redis.rb new file mode 100644 index 000000000..fe1c5da72 --- /dev/null +++ b/examples/dist_redis.rb @@ -0,0 +1,43 @@ +require "redis" +require "redis/distributed" + +r = Redis::Distributed.new %w[redis://localhost:6379 redis://localhost:6380 redis://localhost:6381 redis://localhost:6382] + +r.flushdb + +r['urmom'] = 'urmom' +r['urdad'] = 'urdad' +r['urmom1'] = 'urmom1' +r['urdad1'] = 'urdad1' +r['urmom2'] = 'urmom2' +r['urdad2'] = 'urdad2' +r['urmom3'] = 'urmom3' +r['urdad3'] = 'urdad3' +p r['urmom'] +p r['urdad'] +p r['urmom1'] +p r['urdad1'] +p r['urmom2'] +p r['urdad2'] +p r['urmom3'] +p r['urdad3'] + +r.rpush 'listor', 'foo1' +r.rpush 'listor', 'foo2' +r.rpush 'listor', 'foo3' +r.rpush 'listor', 'foo4' +r.rpush 'listor', 'foo5' + +p r.rpop('listor') +p r.rpop('listor') +p r.rpop('listor') +p r.rpop('listor') +p r.rpop('listor') + +puts "key distribution:" + +r.ring.nodes.each do |node| + p [node.client, node.keys("*")] +end +r.flushdb +p r.keys('*') diff --git a/lib/redis/distributed.rb b/lib/redis/distributed.rb new file mode 100644 index 000000000..1af18383a --- /dev/null +++ b/lib/redis/distributed.rb @@ -0,0 +1,873 @@ +require_relative "hash_ring" + +class Redis + class Distributed + + class CannotDistribute < RuntimeError + def initialize(command) + @command = command + end + + def message + "#{@command.to_s.upcase} cannot be used in Redis::Distributed because the keys involved need to be on the same server or because we cannot guarantee that the operation will be atomic." + end + end + + attr_reader :ring + + def initialize(node_configs, options = {}) + @tag = options[:tag] || /^\{(.+?)\}/ + @ring = options[:ring] || HashRing.new + @node_configs = node_configs.dup + @default_options = options.dup + node_configs.each { |node_config| add_node(node_config) } + @subscribed_node = nil + end + + def node_for(key) + @ring.get_node(key_tag(key.to_s) || key.to_s) + end + + def nodes + @ring.nodes + end + + def add_node(options) + options = { :url => options } if options.is_a?(String) + options = @default_options.merge(options) + @ring.add_node Redis.new( options ) + end + + # Change the selected database for the current connection. + def select(db) + on_each_node :select, db + end + + # Ping the server. + def ping + on_each_node :ping + end + + # Echo the given string. + def echo(value) + on_each_node :echo, value + end + + # Close the connection. + def quit + on_each_node :quit + end + + # Asynchronously save the dataset to disk. + def bgsave + on_each_node :bgsave + end + + # Return the number of keys in the selected database. + def dbsize + on_each_node :dbsize + end + + # Remove all keys from all databases. + def flushall + on_each_node :flushall + end + + # Remove all keys from the current database. + def flushdb + on_each_node :flushdb + end + + # Get information and statistics about the server. + def info(cmd = nil) + on_each_node :info, cmd + end + + # Get the UNIX time stamp of the last successful save to disk. + def lastsave + on_each_node :lastsave + end + + # Listen for all requests received by the server in real time. + def monitor + raise NotImplementedError + end + + # Synchronously save the dataset to disk. + def save + on_each_node :save + end + + # Get server time: an UNIX timestamp and the elapsed microseconds in the current second. + def time + on_each_node :time + end + + # Remove the expiration from a key. + def persist(key) + node_for(key).persist(key) + end + + # Set a key's time to live in seconds. + def expire(key, seconds) + node_for(key).expire(key, seconds) + end + + # Set the expiration for a key as a UNIX timestamp. + def expireat(key, unix_time) + node_for(key).expireat(key, unix_time) + end + + # Get the time to live (in seconds) for a key. + def ttl(key) + node_for(key).ttl(key) + end + + # Set a key's time to live in milliseconds. + def pexpire(key, milliseconds) + node_for(key).pexpire(key, milliseconds) + end + + # Set the expiration for a key as number of milliseconds from UNIX Epoch. + def pexpireat(key, ms_unix_time) + node_for(key).pexpireat(key, ms_unix_time) + end + + # Get the time to live (in milliseconds) for a key. + def pttl(key) + node_for(key).pttl(key) + end + + # Return a serialized version of the value stored at a key. + def dump(key) + node_for(key).dump(key) + end + + # Create a key using the serialized value, previously obtained using DUMP. + def restore(key, ttl, serialized_value) + node_for(key).restore(key, ttl, serialized_value) + end + + # Transfer a key from the connected instance to another instance. + def migrate(key, options) + raise CannotDistribute, :migrate + end + + # Delete a key. + def del(*args) + keys_per_node = args.group_by { |key| node_for(key) } + keys_per_node.inject(0) do |sum, (node, keys)| + sum + node.del(*keys) + end + end + + # Determine if a key exists. + def exists(key) + node_for(key).exists(key) + end + + # Find all keys matching the given pattern. + def keys(glob = "*") + on_each_node(:keys, glob).flatten + end + + # Move a key to another database. + def move(key, db) + node_for(key).move(key, db) + end + + # Return a random key from the keyspace. + def randomkey + raise CannotDistribute, :randomkey + end + + # Rename a key. + def rename(old_name, new_name) + ensure_same_node(:rename, [old_name, new_name]) do |node| + node.rename(old_name, new_name) + end + end + + # Rename a key, only if the new key does not exist. + def renamenx(old_name, new_name) + ensure_same_node(:renamenx, [old_name, new_name]) do |node| + node.renamenx(old_name, new_name) + end + end + + # Sort the elements in a list, set or sorted set. + def sort(key, options = {}) + keys = [key, options[:by], options[:store], *Array(options[:get])].compact + + ensure_same_node(:sort, keys) do |node| + node.sort(key, options) + end + end + + # Determine the type stored at key. + def type(key) + node_for(key).type(key) + end + + # Decrement the integer value of a key by one. + def decr(key) + node_for(key).decr(key) + end + + # Decrement the integer value of a key by the given number. + def decrby(key, decrement) + node_for(key).decrby(key, decrement) + end + + # Increment the integer value of a key by one. + def incr(key) + node_for(key).incr(key) + end + + # Increment the integer value of a key by the given integer number. + def incrby(key, increment) + node_for(key).incrby(key, increment) + end + + # Increment the numeric value of a key by the given float number. + def incrbyfloat(key, increment) + node_for(key).incrbyfloat(key, increment) + end + + # Set the string value of a key. + def set(key, value, options = {}) + node_for(key).set(key, value, options) + end + + # Set the time to live in seconds of a key. + def setex(key, ttl, value) + node_for(key).setex(key, ttl, value) + end + + # Set the time to live in milliseconds of a key. + def psetex(key, ttl, value) + node_for(key).psetex(key, ttl, value) + end + + # Set the value of a key, only if the key does not exist. + def setnx(key, value) + node_for(key).setnx(key, value) + end + + # Set multiple keys to multiple values. + def mset(*args) + raise CannotDistribute, :mset + end + + def mapped_mset(hash) + raise CannotDistribute, :mapped_mset + end + + # Set multiple keys to multiple values, only if none of the keys exist. + def msetnx(*args) + raise CannotDistribute, :msetnx + end + + def mapped_msetnx(hash) + raise CannotDistribute, :mapped_msetnx + end + + # Get the value of a key. + def get(key) + node_for(key).get(key) + end + + # Get the values of all the given keys. + def mget(*keys) + raise CannotDistribute, :mget + end + + def mapped_mget(*keys) + raise CannotDistribute, :mapped_mget + end + + # Overwrite part of a string at key starting at the specified offset. + def setrange(key, offset, value) + node_for(key).setrange(key, offset, value) + end + + # Get a substring of the string stored at a key. + def getrange(key, start, stop) + node_for(key).getrange(key, start, stop) + end + + # Sets or clears the bit at offset in the string value stored at key. + def setbit(key, offset, value) + node_for(key).setbit(key, offset, value) + end + + # Returns the bit value at offset in the string value stored at key. + def getbit(key, offset) + node_for(key).getbit(key, offset) + end + + # Append a value to a key. + def append(key, value) + node_for(key).append(key, value) + end + + # Count the number of set bits in a range of the string value stored at key. + def bitcount(key, start = 0, stop = -1) + node_for(key).bitcount(key, start, stop) + end + + # Perform a bitwise operation between strings and store the resulting string in a key. + def bitop(operation, destkey, *keys) + ensure_same_node(:bitop, [destkey] + keys) do |node| + node.bitop(operation, destkey, *keys) + end + end + + # Return the position of the first bit set to 1 or 0 in a string. + def bitpos(key, bit, start=nil, stop=nil) + node_for(key).bitpos(key, bit, start, stop) + end + + # Set the string value of a key and return its old value. + def getset(key, value) + node_for(key).getset(key, value) + end + + # Get the length of the value stored in a key. + def strlen(key) + node_for(key).strlen(key) + end + + def [](key) + get(key) + end + + def []=(key,value) + set(key, value) + end + + # Get the length of a list. + def llen(key) + node_for(key).llen(key) + end + + # Prepend one or more values to a list. + def lpush(key, value) + node_for(key).lpush(key, value) + end + + # Prepend a value to a list, only if the list exists. + def lpushx(key, value) + node_for(key).lpushx(key, value) + end + + # Append one or more values to a list. + def rpush(key, value) + node_for(key).rpush(key, value) + end + + # Append a value to a list, only if the list exists. + def rpushx(key, value) + node_for(key).rpushx(key, value) + end + + # Remove and get the first element in a list. + def lpop(key) + node_for(key).lpop(key) + end + + # Remove and get the last element in a list. + def rpop(key) + node_for(key).rpop(key) + end + + # Remove the last element in a list, append it to another list and return + # it. + def rpoplpush(source, destination) + ensure_same_node(:rpoplpush, [source, destination]) do |node| + node.rpoplpush(source, destination) + end + end + + def _bpop(cmd, args) + options = {} + + case args.last + when Hash + options = args.pop + when Integer + # Issue deprecation notice in obnoxious mode... + options[:timeout] = args.pop + end + + if args.size > 1 + # Issue deprecation notice in obnoxious mode... + end + + keys = args.flatten + + ensure_same_node(cmd, keys) do |node| + node.__send__(cmd, keys, options) + end + end + + # Remove and get the first element in a list, or block until one is + # available. + def blpop(*args) + _bpop(:blpop, args) + end + + # Remove and get the last element in a list, or block until one is + # available. + def brpop(*args) + _bpop(:brpop, args) + end + + # Pop a value from a list, push it to another list and return it; or block + # until one is available. + def brpoplpush(source, destination, options = {}) + case options + when Integer + # Issue deprecation notice in obnoxious mode... + options = { :timeout => options } + end + + ensure_same_node(:brpoplpush, [source, destination]) do |node| + node.brpoplpush(source, destination, options) + end + end + + # Get an element from a list by its index. + def lindex(key, index) + node_for(key).lindex(key, index) + end + + # Insert an element before or after another element in a list. + def linsert(key, where, pivot, value) + node_for(key).linsert(key, where, pivot, value) + end + + # Get a range of elements from a list. + def lrange(key, start, stop) + node_for(key).lrange(key, start, stop) + end + + # Remove elements from a list. + def lrem(key, count, value) + node_for(key).lrem(key, count, value) + end + + # Set the value of an element in a list by its index. + def lset(key, index, value) + node_for(key).lset(key, index, value) + end + + # Trim a list to the specified range. + def ltrim(key, start, stop) + node_for(key).ltrim(key, start, stop) + end + + # Get the number of members in a set. + def scard(key) + node_for(key).scard(key) + end + + # Add one or more members to a set. + def sadd(key, member) + node_for(key).sadd(key, member) + end + + # Remove one or more members from a set. + def srem(key, member) + node_for(key).srem(key, member) + end + + # Remove and return a random member from a set. + def spop(key, count = nil) + node_for(key).spop(key, count) + end + + # Get a random member from a set. + def srandmember(key, count = nil) + node_for(key).srandmember(key, count) + end + + # Move a member from one set to another. + def smove(source, destination, member) + ensure_same_node(:smove, [source, destination]) do |node| + node.smove(source, destination, member) + end + end + + # Determine if a given value is a member of a set. + def sismember(key, member) + node_for(key).sismember(key, member) + end + + # Get all the members in a set. + def smembers(key) + node_for(key).smembers(key) + end + + # Subtract multiple sets. + def sdiff(*keys) + ensure_same_node(:sdiff, keys) do |node| + node.sdiff(*keys) + end + end + + # Subtract multiple sets and store the resulting set in a key. + def sdiffstore(destination, *keys) + ensure_same_node(:sdiffstore, [destination] + keys) do |node| + node.sdiffstore(destination, *keys) + end + end + + # Intersect multiple sets. + def sinter(*keys) + ensure_same_node(:sinter, keys) do |node| + node.sinter(*keys) + end + end + + # Intersect multiple sets and store the resulting set in a key. + def sinterstore(destination, *keys) + ensure_same_node(:sinterstore, [destination] + keys) do |node| + node.sinterstore(destination, *keys) + end + end + + # Add multiple sets. + def sunion(*keys) + ensure_same_node(:sunion, keys) do |node| + node.sunion(*keys) + end + end + + # Add multiple sets and store the resulting set in a key. + def sunionstore(destination, *keys) + ensure_same_node(:sunionstore, [destination] + keys) do |node| + node.sunionstore(destination, *keys) + end + end + + # Get the number of members in a sorted set. + def zcard(key) + node_for(key).zcard(key) + end + + # Add one or more members to a sorted set, or update the score for members + # that already exist. + def zadd(key, *args) + node_for(key).zadd(key, *args) + end + + # Increment the score of a member in a sorted set. + def zincrby(key, increment, member) + node_for(key).zincrby(key, increment, member) + end + + # Remove one or more members from a sorted set. + def zrem(key, member) + node_for(key).zrem(key, member) + end + + # Get the score associated with the given member in a sorted set. + def zscore(key, member) + node_for(key).zscore(key, member) + end + + # Return a range of members in a sorted set, by index. + def zrange(key, start, stop, options = {}) + node_for(key).zrange(key, start, stop, options) + end + + # Return a range of members in a sorted set, by index, with scores ordered + # from high to low. + def zrevrange(key, start, stop, options = {}) + node_for(key).zrevrange(key, start, stop, options) + end + + # Determine the index of a member in a sorted set. + def zrank(key, member) + node_for(key).zrank(key, member) + end + + # Determine the index of a member in a sorted set, with scores ordered from + # high to low. + def zrevrank(key, member) + node_for(key).zrevrank(key, member) + end + + # Remove all members in a sorted set within the given indexes. + def zremrangebyrank(key, start, stop) + node_for(key).zremrangebyrank(key, start, stop) + end + + # Return a range of members in a sorted set, by score. + def zrangebyscore(key, min, max, options = {}) + node_for(key).zrangebyscore(key, min, max, options) + end + + # Return a range of members in a sorted set, by score, with scores ordered + # from high to low. + def zrevrangebyscore(key, max, min, options = {}) + node_for(key).zrevrangebyscore(key, max, min, options) + end + + # Remove all members in a sorted set within the given scores. + def zremrangebyscore(key, min, max) + node_for(key).zremrangebyscore(key, min, max) + end + + # Get the number of members in a particular score range. + def zcount(key, min, max) + node_for(key).zcount(key, min, max) + end + + # Intersect multiple sorted sets and store the resulting sorted set in a new + # key. + def zinterstore(destination, keys, options = {}) + ensure_same_node(:zinterstore, [destination] + keys) do |node| + node.zinterstore(destination, keys, options) + end + end + + # Add multiple sorted sets and store the resulting sorted set in a new key. + def zunionstore(destination, keys, options = {}) + ensure_same_node(:zunionstore, [destination] + keys) do |node| + node.zunionstore(destination, keys, options) + end + end + + # Get the number of fields in a hash. + def hlen(key) + node_for(key).hlen(key) + end + + # Set the string value of a hash field. + def hset(key, field, value) + node_for(key).hset(key, field, value) + end + + # Set the value of a hash field, only if the field does not exist. + def hsetnx(key, field, value) + node_for(key).hsetnx(key, field, value) + end + + # Set multiple hash fields to multiple values. + def hmset(key, *attrs) + node_for(key).hmset(key, *attrs) + end + + def mapped_hmset(key, hash) + node_for(key).hmset(key, *hash.to_a.flatten) + end + + # Get the value of a hash field. + def hget(key, field) + node_for(key).hget(key, field) + end + + # Get the values of all the given hash fields. + def hmget(key, *fields) + node_for(key).hmget(key, *fields) + end + + def mapped_hmget(key, *fields) + Hash[*fields.zip(hmget(key, *fields)).flatten] + end + + # Delete one or more hash fields. + def hdel(key, field) + node_for(key).hdel(key, field) + end + + # Determine if a hash field exists. + def hexists(key, field) + node_for(key).hexists(key, field) + end + + # Increment the integer value of a hash field by the given integer number. + def hincrby(key, field, increment) + node_for(key).hincrby(key, field, increment) + end + + # Increment the numeric value of a hash field by the given float number. + def hincrbyfloat(key, field, increment) + node_for(key).hincrbyfloat(key, field, increment) + end + + # Get all the fields in a hash. + def hkeys(key) + node_for(key).hkeys(key) + end + + # Get all the values in a hash. + def hvals(key) + node_for(key).hvals(key) + end + + # Get all the fields and values in a hash. + def hgetall(key) + node_for(key).hgetall(key) + end + + # Post a message to a channel. + def publish(channel, message) + node_for(channel).publish(channel, message) + end + + def subscribed? + !! @subscribed_node + end + + # Listen for messages published to the given channels. + def subscribe(channel, *channels, &block) + if channels.empty? + @subscribed_node = node_for(channel) + @subscribed_node.subscribe(channel, &block) + else + ensure_same_node(:subscribe, [channel] + channels) do |node| + @subscribed_node = node + node.subscribe(channel, *channels, &block) + end + end + end + + # Stop listening for messages posted to the given channels. + def unsubscribe(*channels) + raise RuntimeError, "Can't unsubscribe if not subscribed." unless subscribed? + @subscribed_node.unsubscribe(*channels) + end + + # Listen for messages published to channels matching the given patterns. + def psubscribe(*channels, &block) + raise NotImplementedError + end + + # Stop listening for messages posted to channels matching the given + # patterns. + def punsubscribe(*channels) + raise NotImplementedError + end + + # Watch the given keys to determine execution of the MULTI/EXEC block. + def watch(*keys) + raise CannotDistribute, :watch + end + + # Forget about all watched keys. + def unwatch + raise CannotDistribute, :unwatch + end + + def pipelined + raise CannotDistribute, :pipelined + end + + # Mark the start of a transaction block. + def multi + raise CannotDistribute, :multi + end + + # Execute all commands issued after MULTI. + def exec + raise CannotDistribute, :exec + end + + # Discard all commands issued after MULTI. + def discard + raise CannotDistribute, :discard + end + + # Control remote script registry. + def script(subcommand, *args) + on_each_node(:script, subcommand, *args) + end + + # Add one or more members to a HyperLogLog structure. + def pfadd(key, member) + node_for(key).pfadd(key, member) + end + + # Get the approximate cardinality of members added to HyperLogLog structure. + def pfcount(*keys) + ensure_same_node(:pfcount, keys.flatten(1)) do |node| + node.pfcount(keys) + end + end + + # Merge multiple HyperLogLog values into an unique value that will approximate the cardinality of the union of + # the observed Sets of the source HyperLogLog structures. + def pfmerge(dest_key, *source_key) + ensure_same_node(:pfmerge, [dest_key, *source_key]) do |node| + node.pfmerge(dest_key, *source_key) + end + end + + def _eval(cmd, args) + script = args.shift + options = args.pop if args.last.is_a?(Hash) + options ||= {} + + keys = args.shift || options[:keys] || [] + argv = args.shift || options[:argv] || [] + + ensure_same_node(cmd, keys) do |node| + node.send(cmd, script, keys, argv) + end + end + + # Evaluate Lua script. + def eval(*args) + _eval(:eval, args) + end + + # Evaluate Lua script by its SHA. + def evalsha(*args) + _eval(:evalsha, args) + end + + def inspect + "#" + end + + def dup + self.class.new(@node_configs, @default_options) + end + + protected + + def on_each_node(command, *args) + nodes.map do |node| + node.send(command, *args) + end + end + + def node_index_for(key) + nodes.index(node_for(key)) + end + + def key_tag(key) + key.to_s[@tag, 1] if @tag + end + + def ensure_same_node(command, keys) + all = true + + tags = keys.map do |key| + tag = key_tag(key) + all = false unless tag + tag + end + + if (all && tags.uniq.size != 1) || (!all && keys.uniq.size != 1) + # Not 1 unique tag or not 1 unique key + raise CannotDistribute, command + end + + yield(node_for(keys.first)) + end + end +end diff --git a/lib/redis/hash_ring.rb b/lib/redis/hash_ring.rb new file mode 100644 index 000000000..b9b8d5ddb --- /dev/null +++ b/lib/redis/hash_ring.rb @@ -0,0 +1,131 @@ +require 'zlib' + +class Redis + class HashRing + + POINTS_PER_SERVER = 160 # this is the default in libmemcached + + attr_reader :ring, :sorted_keys, :replicas, :nodes + + # nodes is a list of objects that have a proper to_s representation. + # replicas indicates how many virtual points should be used pr. node, + # replicas are required to improve the distribution. + def initialize(nodes=[], replicas=POINTS_PER_SERVER) + @replicas = replicas + @ring = {} + @nodes = [] + @sorted_keys = [] + nodes.each do |node| + add_node(node) + end + end + + # Adds a `node` to the hash ring (including a number of replicas). + def add_node(node) + @nodes << node + @replicas.times do |i| + key = Zlib.crc32("#{node.id}:#{i}") + @ring[key] = node + @sorted_keys << key + end + @sorted_keys.sort! + end + + def remove_node(node) + @nodes.reject!{|n| n.id == node.id} + @replicas.times do |i| + key = Zlib.crc32("#{node.id}:#{i}") + @ring.delete(key) + @sorted_keys.reject! {|k| k == key} + end + end + + # get the node in the hash ring for this key + def get_node(key) + get_node_pos(key)[0] + end + + def get_node_pos(key) + return [nil,nil] if @ring.size == 0 + crc = Zlib.crc32(key) + idx = HashRing.binary_search(@sorted_keys, crc) + return [@ring[@sorted_keys[idx]], idx] + end + + def iter_nodes(key) + return [nil,nil] if @ring.size == 0 + _, pos = get_node_pos(key) + @ring.size.times do |n| + yield @ring[@sorted_keys[(pos+n) % @ring.size]] + end + end + + class << self + + # gem install RubyInline to use this code + # Native extension to perform the binary search within the hashring. + # There's a pure ruby version below so this is purely optional + # for performance. In testing 20k gets and sets, the native + # binary search shaved about 12% off the runtime (9sec -> 8sec). + begin + require 'inline' + inline do |builder| + builder.c <<-EOM + int binary_search(VALUE ary, unsigned int r) { + int upper = RARRAY_LEN(ary) - 1; + int lower = 0; + int idx = 0; + + while (lower <= upper) { + idx = (lower + upper) / 2; + + VALUE continuumValue = RARRAY_PTR(ary)[idx]; + unsigned int l = NUM2UINT(continuumValue); + if (l == r) { + return idx; + } + else if (l > r) { + upper = idx - 1; + } + else { + lower = idx + 1; + } + } + if (upper < 0) { + upper = RARRAY_LEN(ary) - 1; + } + return upper; + } + EOM + end + rescue Exception + # Find the closest index in HashRing with value <= the given value + def binary_search(ary, value, &block) + upper = ary.size - 1 + lower = 0 + idx = 0 + + while(lower <= upper) do + idx = (lower + upper) / 2 + comp = ary[idx] <=> value + + if comp == 0 + return idx + elsif comp > 0 + upper = idx - 1 + else + lower = idx + 1 + end + end + + if upper < 0 + upper = ary.size - 1 + end + return upper + end + + end + end + + end +end diff --git a/test/blocking_commands_test.rb b/test/blocking_commands_test.rb index 35c0b88d2..d9559e675 100644 --- a/test/blocking_commands_test.rb +++ b/test/blocking_commands_test.rb @@ -1,153 +1,10 @@ require_relative "helper" +require_relative "lint/blocking_commands" class TestBlockingCommands < Test::Unit::TestCase include Helper::Client - - def setup - super - - r.rpush("{zap}foo", "s1") - r.rpush("{zap}foo", "s2") - r.rpush("{zap}bar", "s1") - r.rpush("{zap}bar", "s2") - end - - def to_protocol(obj) - case obj - when String - "$#{obj.length}\r\n#{obj}\r\n" - when Array - "*#{obj.length}\r\n" + obj.map { |e| to_protocol(e) }.join - else - fail - end - end - - def mock(options = {}, &blk) - commands = { - :blpop => lambda do |*args| - sleep options[:delay] if options.has_key?(:delay) - to_protocol([args.first, args.last]) - end, - :brpop => lambda do |*args| - sleep options[:delay] if options.has_key?(:delay) - to_protocol([args.first, args.last]) - end, - :brpoplpush => lambda do |*args| - sleep options[:delay] if options.has_key?(:delay) - to_protocol(args.last) - end - } - - redis_mock(commands, &blk) - end - - def test_blpop - assert_equal ["{zap}foo", "s1"], r.blpop("{zap}foo") - assert_equal ["{zap}foo", "s2"], r.blpop(["{zap}foo"]) - assert_equal ["{zap}bar", "s1"], r.blpop(["{zap}bar", "{zap}foo"]) - assert_equal ["{zap}bar", "s2"], r.blpop(["{zap}foo", "{zap}bar"]) - end - - def test_blpop_timeout - mock do |r| - assert_equal ["{zap}foo", "0"], r.blpop("{zap}foo") - assert_equal ["{zap}foo", "1"], r.blpop("{zap}foo", :timeout => 1) - end - end - - def test_blpop_with_old_prototype - assert_equal ["{zap}foo", "s1"], r.blpop("{zap}foo", 0) - assert_equal ["{zap}foo", "s2"], r.blpop("{zap}foo", 0) - assert_equal ["{zap}bar", "s1"], r.blpop("{zap}bar", "{zap}foo", 0) - assert_equal ["{zap}bar", "s2"], r.blpop("{zap}foo", "{zap}bar", 0) - end - - def test_blpop_timeout_with_old_prototype - mock do |r| - assert_equal ["{zap}foo", "0"], r.blpop("{zap}foo", 0) - assert_equal ["{zap}foo", "1"], r.blpop("{zap}foo", 1) - end - end - - def test_brpop - assert_equal ["{zap}foo", "s2"], r.brpop("{zap}foo") - assert_equal ["{zap}foo", "s1"], r.brpop(["{zap}foo"]) - assert_equal ["{zap}bar", "s2"], r.brpop(["{zap}bar", "{zap}foo"]) - assert_equal ["{zap}bar", "s1"], r.brpop(["{zap}foo", "{zap}bar"]) - end - - def test_brpop_timeout - mock do |r| - assert_equal ["{zap}foo", "0"], r.brpop("{zap}foo") - assert_equal ["{zap}foo", "1"], r.brpop("{zap}foo", :timeout => 1) - end - end - - def test_brpop_with_old_prototype - assert_equal ["{zap}foo", "s2"], r.brpop("{zap}foo", 0) - assert_equal ["{zap}foo", "s1"], r.brpop("{zap}foo", 0) - assert_equal ["{zap}bar", "s2"], r.brpop("{zap}bar", "{zap}foo", 0) - assert_equal ["{zap}bar", "s1"], r.brpop("{zap}foo", "{zap}bar", 0) - end - - def test_brpop_timeout_with_old_prototype - mock do |r| - assert_equal ["{zap}foo", "0"], r.brpop("{zap}foo", 0) - assert_equal ["{zap}foo", "1"], r.brpop("{zap}foo", 1) - end - end - - def test_brpoplpush - assert_equal "s2", r.brpoplpush("{zap}foo", "{zap}qux") - assert_equal ["s2"], r.lrange("{zap}qux", 0, -1) - end - - def test_brpoplpush_timeout - mock do |r| - assert_equal "0", r.brpoplpush("{zap}foo", "{zap}bar") - assert_equal "1", r.brpoplpush("{zap}foo", "{zap}bar", :timeout => 1) - end - end - - def test_brpoplpush_with_old_prototype - assert_equal "s2", r.brpoplpush("{zap}foo", "{zap}qux", 0) - assert_equal ["s2"], r.lrange("{zap}qux", 0, -1) - end - - def test_brpoplpush_timeout_with_old_prototype - mock do |r| - assert_equal "0", r.brpoplpush("{zap}foo", "{zap}bar", 0) - assert_equal "1", r.brpoplpush("{zap}foo", "{zap}bar", 1) - end - end - - driver(:ruby, :hiredis) do - def test_blpop_socket_timeout - mock(:delay => 1 + OPTIONS[:timeout] * 2) do |r| - assert_raises(Redis::TimeoutError) do - r.blpop("{zap}foo", :timeout => 1) - end - end - end - - def test_brpop_socket_timeout - mock(:delay => 1 + OPTIONS[:timeout] * 2) do |r| - assert_raises(Redis::TimeoutError) do - r.brpop("{zap}foo", :timeout => 1) - end - end - end - - def test_brpoplpush_socket_timeout - mock(:delay => 1 + OPTIONS[:timeout] * 2) do |r| - assert_raises(Redis::TimeoutError) do - r.brpoplpush("{zap}foo", "{zap}bar", :timeout => 1) - end - end - end - end + include Lint::BlockingCommands def assert_takes_longer_than_client_timeout timeout = OPTIONS[:timeout] diff --git a/test/commands_on_hashes_test.rb b/test/commands_on_hashes_test.rb index 198883b49..3e0f7ba4e 100644 --- a/test/commands_on_hashes_test.rb +++ b/test/commands_on_hashes_test.rb @@ -1,165 +1,10 @@ require_relative "helper" +require_relative "lint/hashes" class TestCommandsOnHashes < Test::Unit::TestCase include Helper::Client - - def test_hset_and_hget - r.hset("foo", "f1", "s1") - - assert_equal "s1", r.hget("foo", "f1") - end - - def test_hsetnx - r.hset("foo", "f1", "s1") - r.hsetnx("foo", "f1", "s2") - - assert_equal "s1", r.hget("foo", "f1") - - r.del("foo") - r.hsetnx("foo", "f1", "s2") - - assert_equal "s2", r.hget("foo", "f1") - end - - def test_hdel - r.hset("foo", "f1", "s1") - - assert_equal "s1", r.hget("foo", "f1") - - assert_equal 1, r.hdel("foo", "f1") - - assert_equal nil, r.hget("foo", "f1") - end - - def test_variadic_hdel - target_version "2.3.9" do - r.hset("foo", "f1", "s1") - r.hset("foo", "f2", "s2") - - assert_equal "s1", r.hget("foo", "f1") - assert_equal "s2", r.hget("foo", "f2") - - assert_equal 2, r.hdel("foo", ["f1", "f2"]) - - assert_equal nil, r.hget("foo", "f1") - assert_equal nil, r.hget("foo", "f2") - end - end - - def test_hexists - assert_equal false, r.hexists("foo", "f1") - - r.hset("foo", "f1", "s1") - - assert r.hexists("foo", "f1") - end - - def test_hlen - assert_equal 0, r.hlen("foo") - - r.hset("foo", "f1", "s1") - - assert_equal 1, r.hlen("foo") - - r.hset("foo", "f2", "s2") - - assert_equal 2, r.hlen("foo") - end - - def test_hkeys - assert_equal [], r.hkeys("foo") - - r.hset("foo", "f1", "s1") - r.hset("foo", "f2", "s2") - - assert_equal ["f1", "f2"], r.hkeys("foo") - end - - def test_hvals - assert_equal [], r.hvals("foo") - - r.hset("foo", "f1", "s1") - r.hset("foo", "f2", "s2") - - assert_equal ["s1", "s2"], r.hvals("foo") - end - - def test_hgetall - assert({} == r.hgetall("foo")) - - r.hset("foo", "f1", "s1") - r.hset("foo", "f2", "s2") - - assert({"f1" => "s1", "f2" => "s2"} == r.hgetall("foo")) - end - - def test_hmset - r.hmset("hash", "foo1", "bar1", "foo2", "bar2") - - assert_equal "bar1", r.hget("hash", "foo1") - assert_equal "bar2", r.hget("hash", "foo2") - end - - def test_hmset_with_invalid_arguments - assert_raise(Redis::CommandError) do - r.hmset("hash", "foo1", "bar1", "foo2", "bar2", "foo3") - end - end - - def test_mapped_hmset - r.mapped_hmset("foo", :f1 => "s1", :f2 => "s2") - - assert_equal "s1", r.hget("foo", "f1") - assert_equal "s2", r.hget("foo", "f2") - end - - def test_hmget - r.hset("foo", "f1", "s1") - r.hset("foo", "f2", "s2") - r.hset("foo", "f3", "s3") - - assert_equal ["s2", "s3"], r.hmget("foo", "f2", "f3") - end - - def test_hmget_mapped - r.hset("foo", "f1", "s1") - r.hset("foo", "f2", "s2") - r.hset("foo", "f3", "s3") - - assert({"f1" => "s1"} == r.mapped_hmget("foo", "f1")) - assert({"f1" => "s1", "f2" => "s2"} == r.mapped_hmget("foo", "f1", "f2")) - end - - def test_hincrby - r.hincrby("foo", "f1", 1) - - assert_equal "1", r.hget("foo", "f1") - - r.hincrby("foo", "f1", 2) - - assert_equal "3", r.hget("foo", "f1") - - r.hincrby("foo", "f1", -1) - - assert_equal "2", r.hget("foo", "f1") - end - - def test_hincrbyfloat - target_version "2.5.4" do - r.hincrbyfloat("foo", "f1", 1.23) - - assert_equal "1.23", r.hget("foo", "f1") - - r.hincrbyfloat("foo", "f1", 0.77) - - assert_equal "2", r.hget("foo", "f1") - - r.hincrbyfloat("foo", "f1", -0.1) - - assert_equal "1.9", r.hget("foo", "f1") - end - end + include Lint::Hashes def test_mapped_hmget_in_a_pipeline_returns_hash r.hset("foo", "f1", "s1") diff --git a/test/commands_on_hyper_log_log_test.rb b/test/commands_on_hyper_log_log_test.rb index 2f39536a4..194e6d4c6 100644 --- a/test/commands_on_hyper_log_log_test.rb +++ b/test/commands_on_hyper_log_log_test.rb @@ -1,61 +1,10 @@ require_relative "helper" +require_relative "lint/hyper_log_log" class TestCommandsOnHyperLogLog < Test::Unit::TestCase include Helper::Client - - def test_pfadd - target_version "2.8.9" do - assert_equal true, r.pfadd("foo", "s1") - assert_equal true, r.pfadd("foo", "s2") - assert_equal false, r.pfadd("foo", "s1") - - assert_equal 2, r.pfcount("foo") - end - end - - def test_variadic_pfadd - target_version "2.8.9" do - assert_equal true, r.pfadd("foo", ["s1", "s2"]) - assert_equal true, r.pfadd("foo", ["s1", "s2", "s3"]) - - assert_equal 3, r.pfcount("foo") - end - end - - def test_pfcount - target_version "2.8.9" do - assert_equal 0, r.pfcount("foo") - - assert_equal true, r.pfadd("foo", "s1") - - assert_equal 1, r.pfcount("foo") - end - end - - def test_variadic_pfcount - target_version "2.8.9" do - assert_equal 0, r.pfcount(["{1}foo", "{1}bar"]) - - assert_equal true, r.pfadd("{1}foo", "s1") - assert_equal true, r.pfadd("{1}bar", "s1") - assert_equal true, r.pfadd("{1}bar", "s2") - - assert_equal 2, r.pfcount("{1}foo", "{1}bar") - end - end - - def test_variadic_pfcount_expanded - target_version "2.8.9" do - assert_equal 0, r.pfcount("{1}foo", "{1}bar") - - assert_equal true, r.pfadd("{1}foo", "s1") - assert_equal true, r.pfadd("{1}bar", "s1") - assert_equal true, r.pfadd("{1}bar", "s2") - - assert_equal 2, r.pfcount("{1}foo", "{1}bar") - end - end + include Lint::HyperLogLog def test_pfmerge target_version "2.8.9" do diff --git a/test/commands_on_lists_test.rb b/test/commands_on_lists_test.rb index df2b2ff1f..5f286706f 100644 --- a/test/commands_on_lists_test.rb +++ b/test/commands_on_lists_test.rb @@ -1,146 +1,10 @@ require_relative "helper" +require_relative "lint/lists" class TestCommandsOnLists < Test::Unit::TestCase include Helper::Client - - def test_lpush - r.lpush "foo", "s1" - r.lpush "foo", "s2" - - assert_equal 2, r.llen("foo") - assert_equal "s2", r.lpop("foo") - end - - def test_variadic_lpush - target_version "2.3.9" do # 2.4-rc6 - assert_equal 3, r.lpush("foo", ["s1", "s2", "s3"]) - assert_equal 3, r.llen("foo") - assert_equal "s3", r.lpop("foo") - end - end - - def test_lpushx - r.lpushx "foo", "s1" - r.lpush "foo", "s2" - r.lpushx "foo", "s3" - - assert_equal 2, r.llen("foo") - assert_equal ["s3", "s2"], r.lrange("foo", 0, -1) - end - - def test_rpush - r.rpush "foo", "s1" - r.rpush "foo", "s2" - - assert_equal 2, r.llen("foo") - assert_equal "s2", r.rpop("foo") - end - - def test_variadic_rpush - target_version "2.3.9" do # 2.4-rc6 - assert_equal 3, r.rpush("foo", ["s1", "s2", "s3"]) - assert_equal 3, r.llen("foo") - assert_equal "s3", r.rpop("foo") - end - end - - def test_rpushx - r.rpushx "foo", "s1" - r.rpush "foo", "s2" - r.rpushx "foo", "s3" - - assert_equal 2, r.llen("foo") - assert_equal ["s2", "s3"], r.lrange("foo", 0, -1) - end - - def test_llen - r.rpush "foo", "s1" - r.rpush "foo", "s2" - - assert_equal 2, r.llen("foo") - end - - def test_lrange - r.rpush "foo", "s1" - r.rpush "foo", "s2" - r.rpush "foo", "s3" - - assert_equal ["s2", "s3"], r.lrange("foo", 1, -1) - assert_equal ["s1", "s2"], r.lrange("foo", 0, 1) - - assert_equal [], r.lrange("bar", 0, -1) - end - - def test_ltrim - r.rpush "foo", "s1" - r.rpush "foo", "s2" - r.rpush "foo", "s3" - - r.ltrim "foo", 0, 1 - - assert_equal 2, r.llen("foo") - assert_equal ["s1", "s2"], r.lrange("foo", 0, -1) - end - - def test_lindex - r.rpush "foo", "s1" - r.rpush "foo", "s2" - - assert_equal "s1", r.lindex("foo", 0) - assert_equal "s2", r.lindex("foo", 1) - end - - def test_lset - r.rpush "foo", "s1" - r.rpush "foo", "s2" - - assert_equal "s2", r.lindex("foo", 1) - assert r.lset("foo", 1, "s3") - assert_equal "s3", r.lindex("foo", 1) - - assert_raise Redis::CommandError do - r.lset("foo", 4, "s3") - end - end - - def test_lrem - r.rpush "foo", "s1" - r.rpush "foo", "s2" - - assert_equal 1, r.lrem("foo", 1, "s1") - assert_equal ["s2"], r.lrange("foo", 0, -1) - end - - def test_lpop - r.rpush "foo", "s1" - r.rpush "foo", "s2" - - assert_equal 2, r.llen("foo") - assert_equal "s1", r.lpop("foo") - assert_equal 1, r.llen("foo") - end - - def test_rpop - r.rpush "foo", "s1" - r.rpush "foo", "s2" - - assert_equal 2, r.llen("foo") - assert_equal "s2", r.rpop("foo") - assert_equal 1, r.llen("foo") - end - - def test_linsert - r.rpush "foo", "s1" - r.rpush "foo", "s3" - r.linsert "foo", :before, "s3", "s2" - - assert_equal ["s1", "s2", "s3"], r.lrange("foo", 0, -1) - - assert_raise(Redis::CommandError) do - r.linsert "foo", :anywhere, "s3", "s2" - end - end + include Lint::Lists def test_rpoplpush r.rpush "foo", "s1" diff --git a/test/commands_on_sets_test.rb b/test/commands_on_sets_test.rb index 6b2167a88..cd186cd34 100644 --- a/test/commands_on_sets_test.rb +++ b/test/commands_on_sets_test.rb @@ -1,143 +1,10 @@ require_relative "helper" +require_relative "lint/sets" class TestCommandsOnSets < Test::Unit::TestCase include Helper::Client - - def test_sadd - assert_equal true, r.sadd("foo", "s1") - assert_equal true, r.sadd("foo", "s2") - assert_equal false, r.sadd("foo", "s1") - - assert_equal ["s1", "s2"], r.smembers("foo").sort - end - - def test_variadic_sadd - target_version "2.3.9" do # 2.4-rc6 - assert_equal 2, r.sadd("foo", ["s1", "s2"]) - assert_equal 1, r.sadd("foo", ["s1", "s2", "s3"]) - - assert_equal ["s1", "s2", "s3"], r.smembers("foo").sort - end - end - - def test_srem - r.sadd("foo", "s1") - r.sadd("foo", "s2") - - assert_equal true, r.srem("foo", "s1") - assert_equal false, r.srem("foo", "s3") - - assert_equal ["s2"], r.smembers("foo") - end - - def test_variadic_srem - target_version "2.3.9" do # 2.4-rc6 - r.sadd("foo", "s1") - r.sadd("foo", "s2") - r.sadd("foo", "s3") - - assert_equal 1, r.srem("foo", ["s1", "aaa"]) - assert_equal 0, r.srem("foo", ["bbb", "ccc" "ddd"]) - assert_equal 1, r.srem("foo", ["eee", "s3"]) - - assert_equal ["s2"], r.smembers("foo") - end - end - - def test_spop - r.sadd "foo", "s1" - r.sadd "foo", "s2" - - assert ["s1", "s2"].include?(r.spop("foo")) - assert ["s1", "s2"].include?(r.spop("foo")) - assert_equal nil, r.spop("foo") - end - - def test_spop_with_positive_count - target_version "3.2.0" do - r.sadd "foo", "s1" - r.sadd "foo", "s2" - r.sadd "foo", "s3" - r.sadd "foo", "s4" - - pops = r.spop("foo", 3) - - assert !(["s1", "s2", "s3", "s4"] & pops).empty? - assert_equal 3, pops.size - assert_equal 1, r.scard("foo") - end - end - - def test_scard - assert_equal 0, r.scard("foo") - - r.sadd "foo", "s1" - - assert_equal 1, r.scard("foo") - - r.sadd "foo", "s2" - - assert_equal 2, r.scard("foo") - end - - def test_sismember - assert_equal false, r.sismember("foo", "s1") - - r.sadd "foo", "s1" - - assert_equal true, r.sismember("foo", "s1") - assert_equal false, r.sismember("foo", "s2") - end - - def test_smembers - assert_equal [], r.smembers("foo") - - r.sadd "foo", "s1" - r.sadd "foo", "s2" - - assert_equal ["s1", "s2"], r.smembers("foo").sort - end - - def test_srandmember - r.sadd "foo", "s1" - r.sadd "foo", "s2" - - 4.times do - assert ["s1", "s2"].include?(r.srandmember("foo")) - end - - assert_equal 2, r.scard("foo") - end - - def test_srandmember_with_positive_count - r.sadd "foo", "s1" - r.sadd "foo", "s2" - r.sadd "foo", "s3" - r.sadd "foo", "s4" - - 4.times do - assert !(["s1", "s2", "s3", "s4"] & r.srandmember("foo", 3)).empty? - - assert_equal 3, r.srandmember("foo", 3).size - end - - assert_equal 4, r.scard("foo") - end - - def test_srandmember_with_negative_count - r.sadd "foo", "s1" - r.sadd "foo", "s2" - r.sadd "foo", "s3" - r.sadd "foo", "s4" - - 4.times do - assert !(["s1", "s2", "s3", "s4"] & r.srandmember("foo", -6)).empty? - assert_equal 6, r.srandmember("foo", -6).size - end - - assert_equal 4, r.scard("foo") - end + include Lint::Sets def test_smove r.sadd "foo", "s1" diff --git a/test/commands_on_sorted_sets_test.rb b/test/commands_on_sorted_sets_test.rb index db14b218e..d10252902 100644 --- a/test/commands_on_sorted_sets_test.rb +++ b/test/commands_on_sorted_sets_test.rb @@ -1,319 +1,10 @@ require_relative "helper" +require_relative "lint/sorted_sets" class TestCommandsOnSortedSets < Test::Unit::TestCase include Helper::Client - - Infinity = 1.0/0.0 - - def test_zadd - assert_equal 0, r.zcard("foo") - assert_equal true, r.zadd("foo", 1, "s1") - assert_equal false, r.zadd("foo", 1, "s1") - assert_equal 1, r.zcard("foo") - r.del "foo" - - target_version "3.0.2" do - # XX option - assert_equal 0, r.zcard("foo") - assert_equal false, r.zadd("foo", 1, "s1", :xx => true) - r.zadd("foo", 1, "s1") - assert_equal false, r.zadd("foo", 2, "s1", :xx => true) - assert_equal 2, r.zscore("foo", "s1") - r.del "foo" - - # NX option - assert_equal 0, r.zcard("foo") - assert_equal true, r.zadd("foo", 1, "s1", :nx => true) - assert_equal false, r.zadd("foo", 2, "s1", :nx => true) - assert_equal 1, r.zscore("foo", "s1") - assert_equal 1, r.zcard("foo") - r.del "foo" - - # CH option - assert_equal 0, r.zcard("foo") - assert_equal true, r.zadd("foo", 1, "s1", :ch => true) - assert_equal false, r.zadd("foo", 1, "s1", :ch => true) - assert_equal true, r.zadd("foo", 2, "s1", :ch => true) - assert_equal 1, r.zcard("foo") - r.del "foo" - - # INCR option - assert_equal 1.0, r.zadd("foo", 1, "s1", :incr => true) - assert_equal 11.0, r.zadd("foo", 10, "s1", :incr => true) - assert_equal(-Infinity, r.zadd("bar", "-inf", "s1", :incr => true)) - assert_equal(+Infinity, r.zadd("bar", "+inf", "s2", :incr => true)) - r.del "foo", "bar" - - # Incompatible options combination - assert_raise(Redis::CommandError) { r.zadd("foo", 1, "s1", :xx => true, :nx => true) } - end - end - - def test_variadic_zadd - target_version "2.3.9" do # 2.4-rc6 - # Non-nested array with pairs - assert_equal 0, r.zcard("foo") - assert_equal 2, r.zadd("foo", [1, "s1", 2, "s2"]) - assert_equal 1, r.zadd("foo", [4, "s1", 5, "s2", 6, "s3"]) - assert_equal 3, r.zcard("foo") - r.del "foo" - - # Nested array with pairs - assert_equal 0, r.zcard("foo") - assert_equal 2, r.zadd("foo", [[1, "s1"], [2, "s2"]]) - assert_equal 1, r.zadd("foo", [[4, "s1"], [5, "s2"], [6, "s3"]]) - assert_equal 3, r.zcard("foo") - r.del "foo" - - # Wrong number of arguments - assert_raise(Redis::CommandError) { r.zadd("foo", ["bar"]) } - assert_raise(Redis::CommandError) { r.zadd("foo", ["bar", "qux", "zap"]) } - end - - target_version "3.0.2" do - # XX option - assert_equal 0, r.zcard("foo") - assert_equal 0, r.zadd("foo", [1, "s1", 2, "s2"], :xx => true) - r.zadd("foo", [1, "s1", 2, "s2"]) - assert_equal 0, r.zadd("foo", [2, "s1", 3, "s2", 4, "s3"], :xx => true) - assert_equal 2, r.zscore("foo", "s1") - assert_equal 3, r.zscore("foo", "s2") - assert_equal nil, r.zscore("foo", "s3") - assert_equal 2, r.zcard("foo") - r.del "foo" - - # NX option - assert_equal 0, r.zcard("foo") - assert_equal 2, r.zadd("foo", [1, "s1", 2, "s2"], :nx => true) - assert_equal 1, r.zadd("foo", [2, "s1", 3, "s2", 4, "s3"], :nx => true) - assert_equal 1, r.zscore("foo", "s1") - assert_equal 2, r.zscore("foo", "s2") - assert_equal 4, r.zscore("foo", "s3") - assert_equal 3, r.zcard("foo") - r.del "foo" - - # CH option - assert_equal 0, r.zcard("foo") - assert_equal 2, r.zadd("foo", [1, "s1", 2, "s2"], :ch => true) - assert_equal 2, r.zadd("foo", [1, "s1", 3, "s2", 4, "s3"], :ch => true) - assert_equal 3, r.zcard("foo") - r.del "foo" - - # INCR option - assert_equal 1.0, r.zadd("foo", [1, "s1"], :incr => true) - assert_equal 11.0, r.zadd("foo", [10, "s1"], :incr => true) - assert_equal(-Infinity, r.zadd("bar", ["-inf", "s1"], :incr => true)) - assert_equal(+Infinity, r.zadd("bar", ["+inf", "s2"], :incr => true)) - assert_raise(Redis::CommandError) { r.zadd("foo", [1, "s1", 2, "s2"], :incr => true) } - r.del "foo", "bar" - - # Incompatible options combination - assert_raise(Redis::CommandError) { r.zadd("foo", [1, "s1"], :xx => true, :nx => true) } - end - end - - def test_zrem - r.zadd("foo", 1, "s1") - r.zadd("foo", 2, "s2") - - assert_equal 2, r.zcard("foo") - assert_equal true, r.zrem("foo", "s1") - assert_equal false, r.zrem("foo", "s1") - assert_equal 1, r.zcard("foo") - end - - def test_variadic_zrem - target_version "2.3.9" do # 2.4-rc6 - r.zadd("foo", 1, "s1") - r.zadd("foo", 2, "s2") - r.zadd("foo", 3, "s3") - - assert_equal 3, r.zcard("foo") - assert_equal 1, r.zrem("foo", ["s1", "aaa"]) - assert_equal 0, r.zrem("foo", ["bbb", "ccc" "ddd"]) - assert_equal 1, r.zrem("foo", ["eee", "s3"]) - assert_equal 1, r.zcard("foo") - end - end - - def test_zincrby - rv = r.zincrby "foo", 1, "s1" - assert_equal 1.0, rv - - rv = r.zincrby "foo", 10, "s1" - assert_equal 11.0, rv - - rv = r.zincrby "bar", "-inf", "s1" - assert_equal(-Infinity, rv) - - rv = r.zincrby "bar", "+inf", "s2" - assert_equal(+Infinity, rv) - end - - def test_zrank - r.zadd "foo", 1, "s1" - r.zadd "foo", 2, "s2" - r.zadd "foo", 3, "s3" - - assert_equal 2, r.zrank("foo", "s3") - end - - def test_zrevrank - r.zadd "foo", 1, "s1" - r.zadd "foo", 2, "s2" - r.zadd "foo", 3, "s3" - - assert_equal 0, r.zrevrank("foo", "s3") - end - - def test_zrange - r.zadd "foo", 1, "s1" - r.zadd "foo", 2, "s2" - r.zadd "foo", 3, "s3" - - assert_equal ["s1", "s2"], r.zrange("foo", 0, 1) - assert_equal [["s1", 1.0], ["s2", 2.0]], r.zrange("foo", 0, 1, :with_scores => true) - assert_equal [["s1", 1.0], ["s2", 2.0]], r.zrange("foo", 0, 1, :withscores => true) - - r.zadd "bar", "-inf", "s1" - r.zadd "bar", "+inf", "s2" - assert_equal [["s1", -Infinity], ["s2", +Infinity]], r.zrange("bar", 0, 1, :with_scores => true) - assert_equal [["s1", -Infinity], ["s2", +Infinity]], r.zrange("bar", 0, 1, :withscores => true) - end - - def test_zrevrange - r.zadd "foo", 1, "s1" - r.zadd "foo", 2, "s2" - r.zadd "foo", 3, "s3" - - assert_equal ["s3", "s2"], r.zrevrange("foo", 0, 1) - assert_equal [["s3", 3.0], ["s2", 2.0]], r.zrevrange("foo", 0, 1, :with_scores => true) - assert_equal [["s3", 3.0], ["s2", 2.0]], r.zrevrange("foo", 0, 1, :withscores => true) - - r.zadd "bar", "-inf", "s1" - r.zadd "bar", "+inf", "s2" - assert_equal [["s2", +Infinity], ["s1", -Infinity]], r.zrevrange("bar", 0, 1, :with_scores => true) - assert_equal [["s2", +Infinity], ["s1", -Infinity]], r.zrevrange("bar", 0, 1, :withscores => true) - end - - def test_zrangebyscore - r.zadd "foo", 1, "s1" - r.zadd "foo", 2, "s2" - r.zadd "foo", 3, "s3" - - assert_equal ["s2", "s3"], r.zrangebyscore("foo", 2, 3) - end - - def test_zrevrangebyscore - r.zadd "foo", 1, "s1" - r.zadd "foo", 2, "s2" - r.zadd "foo", 3, "s3" - - assert_equal ["s3", "s2"], r.zrevrangebyscore("foo", 3, 2) - end - - def test_zrangebyscore_with_limit - r.zadd "foo", 1, "s1" - r.zadd "foo", 2, "s2" - r.zadd "foo", 3, "s3" - r.zadd "foo", 4, "s4" - - assert_equal ["s2"], r.zrangebyscore("foo", 2, 4, :limit => [0, 1]) - assert_equal ["s3"], r.zrangebyscore("foo", 2, 4, :limit => [1, 1]) - assert_equal ["s3", "s4"], r.zrangebyscore("foo", 2, 4, :limit => [1, 2]) - end - - def test_zrevrangebyscore_with_limit - r.zadd "foo", 1, "s1" - r.zadd "foo", 2, "s2" - r.zadd "foo", 3, "s3" - r.zadd "foo", 4, "s4" - - assert_equal ["s4"], r.zrevrangebyscore("foo", 4, 2, :limit => [0, 1]) - assert_equal ["s3"], r.zrevrangebyscore("foo", 4, 2, :limit => [1, 1]) - assert_equal ["s3", "s2"], r.zrevrangebyscore("foo", 4, 2, :limit => [1, 2]) - end - - def test_zrangebyscore_with_withscores - r.zadd "foo", 1, "s1" - r.zadd "foo", 2, "s2" - r.zadd "foo", 3, "s3" - r.zadd "foo", 4, "s4" - - assert_equal [["s2", 2.0]], r.zrangebyscore("foo", 2, 4, :limit => [0, 1], :with_scores => true) - assert_equal [["s3", 3.0]], r.zrangebyscore("foo", 2, 4, :limit => [1, 1], :with_scores => true) - assert_equal [["s2", 2.0]], r.zrangebyscore("foo", 2, 4, :limit => [0, 1], :withscores => true) - assert_equal [["s3", 3.0]], r.zrangebyscore("foo", 2, 4, :limit => [1, 1], :withscores => true) - - r.zadd "bar", "-inf", "s1" - r.zadd "bar", "+inf", "s2" - assert_equal [["s1", -Infinity]], r.zrangebyscore("bar", -Infinity, +Infinity, :limit => [0, 1], :with_scores => true) - assert_equal [["s2", +Infinity]], r.zrangebyscore("bar", -Infinity, +Infinity, :limit => [1, 1], :with_scores => true) - assert_equal [["s1", -Infinity]], r.zrangebyscore("bar", -Infinity, +Infinity, :limit => [0, 1], :withscores => true) - assert_equal [["s2", +Infinity]], r.zrangebyscore("bar", -Infinity, +Infinity, :limit => [1, 1], :withscores => true) - end - - def test_zrevrangebyscore_with_withscores - r.zadd "foo", 1, "s1" - r.zadd "foo", 2, "s2" - r.zadd "foo", 3, "s3" - r.zadd "foo", 4, "s4" - - assert_equal [["s4", 4.0]], r.zrevrangebyscore("foo", 4, 2, :limit => [0, 1], :with_scores => true) - assert_equal [["s3", 3.0]], r.zrevrangebyscore("foo", 4, 2, :limit => [1, 1], :with_scores => true) - assert_equal [["s4", 4.0]], r.zrevrangebyscore("foo", 4, 2, :limit => [0, 1], :withscores => true) - assert_equal [["s3", 3.0]], r.zrevrangebyscore("foo", 4, 2, :limit => [1, 1], :withscores => true) - - r.zadd "bar", "-inf", "s1" - r.zadd "bar", "+inf", "s2" - assert_equal [["s2", +Infinity]], r.zrevrangebyscore("bar", +Infinity, -Infinity, :limit => [0, 1], :with_scores => true) - assert_equal [["s1", -Infinity]], r.zrevrangebyscore("bar", +Infinity, -Infinity, :limit => [1, 1], :with_scores => true) - assert_equal [["s2", +Infinity]], r.zrevrangebyscore("bar", +Infinity, -Infinity, :limit => [0, 1], :withscores => true) - assert_equal [["s1", -Infinity]], r.zrevrangebyscore("bar", +Infinity, -Infinity, :limit => [1, 1], :withscores => true) - end - - def test_zcard - assert_equal 0, r.zcard("foo") - - r.zadd "foo", 1, "s1" - - assert_equal 1, r.zcard("foo") - end - - def test_zscore - r.zadd "foo", 1, "s1" - - assert_equal 1.0, r.zscore("foo", "s1") - - assert_equal nil, r.zscore("foo", "s2") - assert_equal nil, r.zscore("bar", "s1") - - r.zadd "bar", "-inf", "s1" - r.zadd "bar", "+inf", "s2" - assert_equal(-Infinity, r.zscore("bar", "s1")) - assert_equal(+Infinity, r.zscore("bar", "s2")) - end - - def test_zremrangebyrank - r.zadd "foo", 10, "s1" - r.zadd "foo", 20, "s2" - r.zadd "foo", 30, "s3" - r.zadd "foo", 40, "s4" - - assert_equal 3, r.zremrangebyrank("foo", 1, 3) - assert_equal ["s1"], r.zrange("foo", 0, -1) - end - - def test_zremrangebyscore - r.zadd "foo", 1, "s1" - r.zadd "foo", 2, "s2" - r.zadd "foo", 3, "s3" - r.zadd "foo", 4, "s4" - - assert_equal 3, r.zremrangebyscore("foo", 2, 4) - assert_equal ["s1"], r.zrange("foo", 0, -1) - end + include Lint::SortedSets def test_zrangebylex target_version "2.8.9" do diff --git a/test/commands_on_strings_test.rb b/test/commands_on_strings_test.rb index ade13e31a..58fe7e510 100644 --- a/test/commands_on_strings_test.rb +++ b/test/commands_on_strings_test.rb @@ -1,249 +1,10 @@ require_relative "helper" +require_relative "lint/strings" class TestCommandsOnStrings < Test::Unit::TestCase include Helper::Client - - def test_set_and_get - r.set("foo", "s1") - - assert_equal "s1", r.get("foo") - end - - def test_set_and_get_with_newline_characters - r.set("foo", "1\n") - - assert_equal "1\n", r.get("foo") - end - - def test_set_and_get_with_non_string_value - value = ["a", "b"] - - r.set("foo", value) - - assert_equal value.to_s, r.get("foo") - end - - def test_set_and_get_with_ascii_characters - with_external_encoding("ASCII-8BIT") do - (0..255).each do |i| - str = "#{i.chr}---#{i.chr}" - r.set("foo", str) - - assert_equal str, r.get("foo") - end - end - end - - def test_set_with_ex - target_version "2.6.12" do - r.set("foo", "bar", :ex => 2) - assert_in_range 0..2, r.ttl("foo") - end - end - - def test_set_with_px - target_version "2.6.12" do - r.set("foo", "bar", :px => 2000) - assert_in_range 0..2, r.ttl("foo") - end - end - - def test_set_with_nx - target_version "2.6.12" do - r.set("foo", "qux", :nx => true) - assert !r.set("foo", "bar", :nx => true) - assert_equal "qux", r.get("foo") - - r.del("foo") - assert r.set("foo", "bar", :nx => true) - assert_equal "bar", r.get("foo") - end - end - - def test_set_with_xx - target_version "2.6.12" do - r.set("foo", "qux") - assert r.set("foo", "bar", :xx => true) - assert_equal "bar", r.get("foo") - - r.del("foo") - assert !r.set("foo", "bar", :xx => true) - end - end - - def test_setex - assert r.setex("foo", 1, "bar") - assert_equal "bar", r.get("foo") - assert [0, 1].include? r.ttl("foo") - end - - def test_setex_with_non_string_value - value = ["b", "a", "r"] - - assert r.setex("foo", 1, value) - assert_equal value.to_s, r.get("foo") - assert [0, 1].include? r.ttl("foo") - end - - def test_psetex - target_version "2.5.4" do - assert r.psetex("foo", 1000, "bar") - assert_equal "bar", r.get("foo") - assert [0, 1].include? r.ttl("foo") - end - end - - def test_psetex_with_non_string_value - target_version "2.5.4" do - value = ["b", "a", "r"] - - assert r.psetex("foo", 1000, value) - assert_equal value.to_s, r.get("foo") - assert [0, 1].include? r.ttl("foo") - end - end - - def test_getset - r.set("foo", "bar") - - assert_equal "bar", r.getset("foo", "baz") - assert_equal "baz", r.get("foo") - end - - def test_getset_with_non_string_value - r.set("foo", "zap") - - value = ["b", "a", "r"] - - assert_equal "zap", r.getset("foo", value) - assert_equal value.to_s, r.get("foo") - end - - def test_setnx - r.set("foo", "qux") - assert !r.setnx("foo", "bar") - assert_equal "qux", r.get("foo") - - r.del("foo") - assert r.setnx("foo", "bar") - assert_equal "bar", r.get("foo") - end - - def test_setnx_with_non_string_value - value = ["b", "a", "r"] - - r.set("foo", "qux") - assert !r.setnx("foo", value) - assert_equal "qux", r.get("foo") - - r.del("foo") - assert r.setnx("foo", value) - assert_equal value.to_s, r.get("foo") - end - - def test_incr - assert_equal 1, r.incr("foo") - assert_equal 2, r.incr("foo") - assert_equal 3, r.incr("foo") - end - - def test_incrby - assert_equal 1, r.incrby("foo", 1) - assert_equal 3, r.incrby("foo", 2) - assert_equal 6, r.incrby("foo", 3) - end - - def test_incrbyfloat - target_version "2.5.4" do - assert_equal 1.23, r.incrbyfloat("foo", 1.23) - assert_equal 2 , r.incrbyfloat("foo", 0.77) - assert_equal 1.9 , r.incrbyfloat("foo", -0.1) - end - end - - def test_decr - r.set("foo", 3) - - assert_equal 2, r.decr("foo") - assert_equal 1, r.decr("foo") - assert_equal 0, r.decr("foo") - end - - def test_decrby - r.set("foo", 6) - - assert_equal 3, r.decrby("foo", 3) - assert_equal 1, r.decrby("foo", 2) - assert_equal 0, r.decrby("foo", 1) - end - - def test_append - r.set "foo", "s" - r.append "foo", "1" - - assert_equal "s1", r.get("foo") - end - - def test_getbit - r.set("foo", "a") - - assert_equal 1, r.getbit("foo", 1) - assert_equal 1, r.getbit("foo", 2) - assert_equal 0, r.getbit("foo", 3) - assert_equal 0, r.getbit("foo", 4) - assert_equal 0, r.getbit("foo", 5) - assert_equal 0, r.getbit("foo", 6) - assert_equal 1, r.getbit("foo", 7) - end - - def test_setbit - r.set("foo", "a") - - r.setbit("foo", 6, 1) - - assert_equal "c", r.get("foo") - end - - def test_bitcount - target_version "2.5.10" do - r.set("foo", "abcde") - - assert_equal 10, r.bitcount("foo", 1, 3) - assert_equal 17, r.bitcount("foo", 0, -1) - end - end - - def test_getrange - r.set("foo", "abcde") - - assert_equal "bcd", r.getrange("foo", 1, 3) - assert_equal "abcde", r.getrange("foo", 0, -1) - end - - def test_setrange - r.set("foo", "abcde") - - r.setrange("foo", 1, "bar") - - assert_equal "abare", r.get("foo") - end - - def test_setrange_with_non_string_value - r.set("foo", "abcde") - - value = ["b", "a", "r"] - - r.setrange("foo", 2, value) - - assert_equal "ab#{value.to_s}", r.get("foo") - end - - def test_strlen - r.set "foo", "lorem" - - assert_equal 5, r.strlen("foo") - end + include Lint::Strings def test_mget r.set("foo", "s1") diff --git a/test/commands_on_value_types_test.rb b/test/commands_on_value_types_test.rb index e0a1b3c5a..1967c1755 100644 --- a/test/commands_on_value_types_test.rb +++ b/test/commands_on_value_types_test.rb @@ -1,125 +1,10 @@ require_relative "helper" +require_relative "lint/value_types" class TestCommandsOnValueTypes < Test::Unit::TestCase include Helper::Client - - def test_exists - assert_equal false, r.exists("foo") - - r.set("foo", "s1") - - assert_equal true, r.exists("foo") - end - - def test_type - assert_equal "none", r.type("foo") - - r.set("foo", "s1") - - assert_equal "string", r.type("foo") - end - - def test_keys - r.set("f", "s1") - r.set("fo", "s2") - r.set("foo", "s3") - - assert_equal ["f","fo", "foo"], r.keys("f*").sort - end - - def test_expire - r.set("foo", "s1") - assert r.expire("foo", 2) - assert_in_range 0..2, r.ttl("foo") - end - - def test_pexpire - target_version "2.5.4" do - r.set("foo", "s1") - assert r.pexpire("foo", 2000) - assert_in_range 0..2, r.ttl("foo") - end - end - - def test_expireat - r.set("foo", "s1") - assert r.expireat("foo", (Time.now + 2).to_i) - assert_in_range 0..2, r.ttl("foo") - end - - def test_pexpireat - target_version "2.5.4" do - r.set("foo", "s1") - assert r.pexpireat("foo", (Time.now + 2).to_i * 1_000) - assert_in_range 0..2, r.ttl("foo") - end - end - - def test_persist - r.set("foo", "s1") - r.expire("foo", 1) - r.persist("foo") - - assert(-1 == r.ttl("foo")) - end - - def test_ttl - r.set("foo", "s1") - r.expire("foo", 2) - assert_in_range 0..2, r.ttl("foo") - end - - def test_pttl - target_version "2.5.4" do - r.set("foo", "s1") - r.expire("foo", 2) - assert_in_range 1..2000, r.pttl("foo") - end - end - - def test_dump_and_restore - target_version "2.5.7" do - r.set("foo", "a") - v = r.dump("foo") - r.del("foo") - - assert r.restore("foo", 1000, v) - assert_equal "a", r.get("foo") - assert [0, 1].include? r.ttl("foo") - - r.rpush("bar", ["b", "c", "d"]) - w = r.dump("bar") - r.del("bar") - - assert r.restore("bar", 1000, w) - assert_equal ["b", "c", "d"], r.lrange("bar", 0, -1) - assert [0, 1].include? r.ttl("bar") - end - end - - def test_move - r.select 14 - r.flushdb - - r.set "bar", "s3" - - r.select 15 - - r.set "foo", "s1" - r.set "bar", "s2" - - assert r.move("foo", 14) - assert_equal nil, r.get("foo") - - assert !r.move("bar", 14) - assert_equal "s2", r.get("bar") - - r.select 14 - - assert_equal "s1", r.get("foo") - assert_equal "s3", r.get("bar") - end + include Lint::ValueTypes def test_del r.set "foo", "s1" diff --git a/test/distributed_blocking_commands_test.rb b/test/distributed_blocking_commands_test.rb new file mode 100644 index 000000000..f03f45b09 --- /dev/null +++ b/test/distributed_blocking_commands_test.rb @@ -0,0 +1,44 @@ +require_relative "helper" +require_relative "lint/blocking_commands" + +class TestDistributedBlockingCommands < Test::Unit::TestCase + + include Helper::Distributed + include Lint::BlockingCommands + + def test_blpop_raises + assert_raises(Redis::Distributed::CannotDistribute) do + r.blpop(["foo", "bar"]) + end + end + + def test_blpop_raises_with_old_prototype + assert_raises(Redis::Distributed::CannotDistribute) do + r.blpop("foo", "bar", 0) + end + end + + def test_brpop_raises + assert_raises(Redis::Distributed::CannotDistribute) do + r.brpop(["foo", "bar"]) + end + end + + def test_brpop_raises_with_old_prototype + assert_raises(Redis::Distributed::CannotDistribute) do + r.brpop("foo", "bar", 0) + end + end + + def test_brpoplpush_raises + assert_raises(Redis::Distributed::CannotDistribute) do + r.brpoplpush("foo", "bar") + end + end + + def test_brpoplpush_raises_with_old_prototype + assert_raises(Redis::Distributed::CannotDistribute) do + r.brpoplpush("foo", "bar", 0) + end + end +end diff --git a/test/distributed_commands_on_hashes_test.rb b/test/distributed_commands_on_hashes_test.rb new file mode 100644 index 000000000..732fef64c --- /dev/null +++ b/test/distributed_commands_on_hashes_test.rb @@ -0,0 +1,8 @@ +require_relative "helper" +require_relative "lint/hashes" + +class TestDistributedCommandsOnHashes < Test::Unit::TestCase + + include Helper::Distributed + include Lint::Hashes +end diff --git a/test/distributed_commands_on_hyper_log_log_test.rb b/test/distributed_commands_on_hyper_log_log_test.rb new file mode 100644 index 000000000..a6b7110f7 --- /dev/null +++ b/test/distributed_commands_on_hyper_log_log_test.rb @@ -0,0 +1,31 @@ +require_relative "helper" +require_relative "lint/hyper_log_log" + +class TestDistributedCommandsOnHyperLogLog < Test::Unit::TestCase + + include Helper::Distributed + include Lint::HyperLogLog + + def test_pfmerge + target_version "2.8.9" do + assert_raise Redis::Distributed::CannotDistribute do + r.pfadd "foo", "s1" + r.pfadd "bar", "s2" + + assert r.pfmerge("res", "foo", "bar") + end + end + end + + def test_pfcount_multiple_keys_diff_nodes + target_version "2.8.9" do + assert_raise Redis::Distributed::CannotDistribute do + r.pfadd "foo", "s1" + r.pfadd "bar", "s2" + + assert r.pfcount("res", "foo", "bar") + end + end + end + +end diff --git a/test/distributed_commands_on_lists_test.rb b/test/distributed_commands_on_lists_test.rb new file mode 100644 index 000000000..dd629bc2f --- /dev/null +++ b/test/distributed_commands_on_lists_test.rb @@ -0,0 +1,20 @@ +require_relative "helper" +require_relative "lint/lists" + +class TestDistributedCommandsOnLists < Test::Unit::TestCase + + include Helper::Distributed + include Lint::Lists + + def test_rpoplpush + assert_raise Redis::Distributed::CannotDistribute do + r.rpoplpush("foo", "bar") + end + end + + def test_brpoplpush + assert_raise Redis::Distributed::CannotDistribute do + r.brpoplpush("foo", "bar", :timeout => 1) + end + end +end diff --git a/test/distributed_commands_on_sets_test.rb b/test/distributed_commands_on_sets_test.rb new file mode 100644 index 000000000..c7180e6ac --- /dev/null +++ b/test/distributed_commands_on_sets_test.rb @@ -0,0 +1,81 @@ +require_relative "helper" +require_relative "lint/sets" + +class TestDistributedCommandsOnSets < Test::Unit::TestCase + + include Helper::Distributed + include Lint::Sets + + def test_smove + assert_raise Redis::Distributed::CannotDistribute do + r.sadd "foo", "s1" + r.sadd "bar", "s2" + + r.smove("foo", "bar", "s1") + end + end + + def test_sinter + assert_raise Redis::Distributed::CannotDistribute do + r.sadd "foo", "s1" + r.sadd "foo", "s2" + r.sadd "bar", "s2" + + r.sinter("foo", "bar") + end + end + + def test_sinterstore + assert_raise Redis::Distributed::CannotDistribute do + r.sadd "foo", "s1" + r.sadd "foo", "s2" + r.sadd "bar", "s2" + + r.sinterstore("baz", "foo", "bar") + end + end + + def test_sunion + assert_raise Redis::Distributed::CannotDistribute do + r.sadd "foo", "s1" + r.sadd "foo", "s2" + r.sadd "bar", "s2" + r.sadd "bar", "s3" + + r.sunion("foo", "bar") + end + end + + def test_sunionstore + assert_raise Redis::Distributed::CannotDistribute do + r.sadd "foo", "s1" + r.sadd "foo", "s2" + r.sadd "bar", "s2" + r.sadd "bar", "s3" + + r.sunionstore("baz", "foo", "bar") + end + end + + def test_sdiff + assert_raise Redis::Distributed::CannotDistribute do + r.sadd "foo", "s1" + r.sadd "foo", "s2" + r.sadd "bar", "s2" + r.sadd "bar", "s3" + + r.sdiff("foo", "bar") + end + end + + def test_sdiffstore + assert_raise Redis::Distributed::CannotDistribute do + r.sadd "foo", "s1" + r.sadd "foo", "s2" + r.sadd "bar", "s2" + r.sadd "bar", "s3" + + r.sdiffstore("baz", "foo", "bar") + end + end +end diff --git a/test/distributed_commands_on_sorted_sets_test.rb b/test/distributed_commands_on_sorted_sets_test.rb new file mode 100644 index 000000000..ae23a6c83 --- /dev/null +++ b/test/distributed_commands_on_sorted_sets_test.rb @@ -0,0 +1,16 @@ +require_relative "helper" +require_relative "lint/sorted_sets" + +class TestDistributedCommandsOnSortedSets < Test::Unit::TestCase + + include Helper::Distributed + include Lint::SortedSets + + def test_zcount + r.zadd "foo", 1, "s1" + r.zadd "foo", 2, "s2" + r.zadd "foo", 3, "s3" + + assert_equal 2, r.zcount("foo", 2, 3) + end +end diff --git a/test/distributed_commands_on_strings_test.rb b/test/distributed_commands_on_strings_test.rb new file mode 100644 index 000000000..5b964684f --- /dev/null +++ b/test/distributed_commands_on_strings_test.rb @@ -0,0 +1,57 @@ +require_relative "helper" +require_relative "lint/strings" + +class TestDistributedCommandsOnStrings < Test::Unit::TestCase + + include Helper::Distributed + include Lint::Strings + + def test_mget + assert_raise Redis::Distributed::CannotDistribute do + r.mget("foo", "bar") + end + end + + def test_mget_mapped + assert_raise Redis::Distributed::CannotDistribute do + r.mapped_mget("foo", "bar") + end + end + + def test_mset + assert_raise Redis::Distributed::CannotDistribute do + r.mset(:foo, "s1", :bar, "s2") + end + end + + def test_mset_mapped + assert_raise Redis::Distributed::CannotDistribute do + r.mapped_mset(:foo => "s1", :bar => "s2") + end + end + + def test_msetnx + assert_raise Redis::Distributed::CannotDistribute do + r.set("foo", "s1") + r.msetnx(:foo, "s2", :bar, "s3") + end + end + + def test_msetnx_mapped + assert_raise Redis::Distributed::CannotDistribute do + r.set("foo", "s1") + r.mapped_msetnx(:foo => "s2", :bar => "s3") + end + end + + def test_bitop + target_version "2.5.10" do + assert_raise Redis::Distributed::CannotDistribute do + r.set("foo", "a") + r.set("bar", "b") + + r.bitop(:and, "foo&bar", "foo", "bar") + end + end + end +end diff --git a/test/distributed_commands_on_value_types_test.rb b/test/distributed_commands_on_value_types_test.rb new file mode 100644 index 000000000..b360dbe98 --- /dev/null +++ b/test/distributed_commands_on_value_types_test.rb @@ -0,0 +1,93 @@ +require_relative "helper" +require_relative "lint/value_types" + +class TestDistributedCommandsOnValueTypes < Test::Unit::TestCase + + include Helper::Distributed + include Lint::ValueTypes + + def test_del + r.set "foo", "s1" + r.set "bar", "s2" + r.set "baz", "s3" + + assert_equal ["bar", "baz", "foo"], r.keys("*").sort + + assert_equal 1, r.del("foo") + + assert_equal ["bar", "baz"], r.keys("*").sort + + assert_equal 2, r.del("bar", "baz") + + assert_equal [], r.keys("*").sort + end + + def test_del_with_array_argument + r.set "foo", "s1" + r.set "bar", "s2" + r.set "baz", "s3" + + assert_equal ["bar", "baz", "foo"], r.keys("*").sort + + assert_equal 1, r.del(["foo"]) + + assert_equal ["bar", "baz"], r.keys("*").sort + + assert_equal 2, r.del(["bar", "baz"]) + + assert_equal [], r.keys("*").sort + end + + def test_randomkey + assert_raise Redis::Distributed::CannotDistribute do + r.randomkey + end + end + + def test_rename + assert_raise Redis::Distributed::CannotDistribute do + r.set("foo", "s1") + r.rename "foo", "bar" + end + + assert_equal "s1", r.get("foo") + assert_equal nil, r.get("bar") + end + + def test_renamenx + assert_raise Redis::Distributed::CannotDistribute do + r.set("foo", "s1") + r.rename "foo", "bar" + end + + assert_equal "s1", r.get("foo") + assert_equal nil , r.get("bar") + end + + def test_dbsize + assert_equal [0], r.dbsize + + r.set("foo", "s1") + + assert_equal [1], r.dbsize + end + + def test_flushdb + r.set("foo", "s1") + r.set("bar", "s2") + + assert_equal [2], r.dbsize + + r.flushdb + + assert_equal [0], r.dbsize + end + + def test_migrate + r.set("foo", "s1") + + assert_raise Redis::Distributed::CannotDistribute do + r.migrate("foo", {}) + end + end +end diff --git a/test/distributed_commands_requiring_clustering_test.rb b/test/distributed_commands_requiring_clustering_test.rb new file mode 100644 index 000000000..dc5c6ed3f --- /dev/null +++ b/test/distributed_commands_requiring_clustering_test.rb @@ -0,0 +1,162 @@ +require_relative "helper" + +class TestDistributedCommandsRequiringClustering < Test::Unit::TestCase + + include Helper::Distributed + + def test_rename + r.set("{qux}foo", "s1") + r.rename "{qux}foo", "{qux}bar" + + assert_equal "s1", r.get("{qux}bar") + assert_equal nil, r.get("{qux}foo") + end + + def test_renamenx + r.set("{qux}foo", "s1") + r.set("{qux}bar", "s2") + + assert_equal false, r.renamenx("{qux}foo", "{qux}bar") + + assert_equal "s1", r.get("{qux}foo") + assert_equal "s2", r.get("{qux}bar") + end + + def test_brpoplpush + r.rpush "{qux}foo", "s1" + r.rpush "{qux}foo", "s2" + + assert_equal "s2", r.brpoplpush("{qux}foo", "{qux}bar", :timeout => 1) + assert_equal ["s2"], r.lrange("{qux}bar", 0, -1) + end + + def test_rpoplpush + r.rpush "{qux}foo", "s1" + r.rpush "{qux}foo", "s2" + + assert_equal "s2", r.rpoplpush("{qux}foo", "{qux}bar") + assert_equal ["s2"], r.lrange("{qux}bar", 0, -1) + assert_equal "s1", r.rpoplpush("{qux}foo", "{qux}bar") + assert_equal ["s1", "s2"], r.lrange("{qux}bar", 0, -1) + end + + def test_smove + r.sadd "{qux}foo", "s1" + r.sadd "{qux}bar", "s2" + + assert r.smove("{qux}foo", "{qux}bar", "s1") + assert r.sismember("{qux}bar", "s1") + end + + def test_sinter + r.sadd "{qux}foo", "s1" + r.sadd "{qux}foo", "s2" + r.sadd "{qux}bar", "s2" + + assert_equal ["s2"], r.sinter("{qux}foo", "{qux}bar") + end + + def test_sinterstore + r.sadd "{qux}foo", "s1" + r.sadd "{qux}foo", "s2" + r.sadd "{qux}bar", "s2" + + r.sinterstore("{qux}baz", "{qux}foo", "{qux}bar") + + assert_equal ["s2"], r.smembers("{qux}baz") + end + + def test_sunion + r.sadd "{qux}foo", "s1" + r.sadd "{qux}foo", "s2" + r.sadd "{qux}bar", "s2" + r.sadd "{qux}bar", "s3" + + assert_equal ["s1", "s2", "s3"], r.sunion("{qux}foo", "{qux}bar").sort + end + + def test_sunionstore + r.sadd "{qux}foo", "s1" + r.sadd "{qux}foo", "s2" + r.sadd "{qux}bar", "s2" + r.sadd "{qux}bar", "s3" + + r.sunionstore("{qux}baz", "{qux}foo", "{qux}bar") + + assert_equal ["s1", "s2", "s3"], r.smembers("{qux}baz").sort + end + + def test_sdiff + r.sadd "{qux}foo", "s1" + r.sadd "{qux}foo", "s2" + r.sadd "{qux}bar", "s2" + r.sadd "{qux}bar", "s3" + + assert_equal ["s1"], r.sdiff("{qux}foo", "{qux}bar") + assert_equal ["s3"], r.sdiff("{qux}bar", "{qux}foo") + end + + def test_sdiffstore + r.sadd "{qux}foo", "s1" + r.sadd "{qux}foo", "s2" + r.sadd "{qux}bar", "s2" + r.sadd "{qux}bar", "s3" + + r.sdiffstore("{qux}baz", "{qux}foo", "{qux}bar") + + assert_equal ["s1"], r.smembers("{qux}baz") + end + + def test_sort + r.set("{qux}foo:1", "s1") + r.set("{qux}foo:2", "s2") + + r.rpush("{qux}bar", "1") + r.rpush("{qux}bar", "2") + + assert_equal ["s1"], r.sort("{qux}bar", :get => "{qux}foo:*", :limit => [0, 1]) + assert_equal ["s2"], r.sort("{qux}bar", :get => "{qux}foo:*", :limit => [0, 1], :order => "desc alpha") + end + + def test_sort_with_an_array_of_gets + r.set("{qux}foo:1:a", "s1a") + r.set("{qux}foo:1:b", "s1b") + + r.set("{qux}foo:2:a", "s2a") + r.set("{qux}foo:2:b", "s2b") + + r.rpush("{qux}bar", "1") + r.rpush("{qux}bar", "2") + + assert_equal [["s1a", "s1b"]], r.sort("{qux}bar", :get => ["{qux}foo:*:a", "{qux}foo:*:b"], :limit => [0, 1]) + assert_equal [["s2a", "s2b"]], r.sort("{qux}bar", :get => ["{qux}foo:*:a", "{qux}foo:*:b"], :limit => [0, 1], :order => "desc alpha") + assert_equal [["s1a", "s1b"], ["s2a", "s2b"]], r.sort("{qux}bar", :get => ["{qux}foo:*:a", "{qux}foo:*:b"]) + end + + def test_sort_with_store + r.set("{qux}foo:1", "s1") + r.set("{qux}foo:2", "s2") + + r.rpush("{qux}bar", "1") + r.rpush("{qux}bar", "2") + + r.sort("{qux}bar", :get => "{qux}foo:*", :store => "{qux}baz") + assert_equal ["s1", "s2"], r.lrange("{qux}baz", 0, -1) + end + + def test_bitop + target_version "2.5.10" do + r.set("{qux}foo", "a") + r.set("{qux}bar", "b") + + r.bitop(:and, "{qux}foo&bar", "{qux}foo", "{qux}bar") + assert_equal "\x60", r.get("{qux}foo&bar") + r.bitop(:or, "{qux}foo|bar", "{qux}foo", "{qux}bar") + assert_equal "\x63", r.get("{qux}foo|bar") + r.bitop(:xor, "{qux}foo^bar", "{qux}foo", "{qux}bar") + assert_equal "\x03", r.get("{qux}foo^bar") + r.bitop(:not, "{qux}~foo", "{qux}foo") + assert_equal "\x9E", r.get("{qux}~foo") + end + end +end diff --git a/test/distributed_connection_handling_test.rb b/test/distributed_connection_handling_test.rb new file mode 100644 index 000000000..335046abe --- /dev/null +++ b/test/distributed_connection_handling_test.rb @@ -0,0 +1,21 @@ +require_relative "helper" + +class TestDistributedConnectionHandling < Test::Unit::TestCase + + include Helper::Distributed + + def test_ping + assert_equal ["PONG"], r.ping + end + + def test_select + r.set "foo", "bar" + + r.select 14 + assert_equal nil, r.get("foo") + + r.select 15 + + assert_equal "bar", r.get("foo") + end +end diff --git a/test/distributed_internals_test.rb b/test/distributed_internals_test.rb new file mode 100644 index 000000000..82b9df3ea --- /dev/null +++ b/test/distributed_internals_test.rb @@ -0,0 +1,68 @@ +require_relative "helper" + +class TestDistributedInternals < Test::Unit::TestCase + + include Helper::Distributed + + def test_provides_a_meaningful_inspect + nodes = ["redis://127.0.0.1:#{PORT}/15", *NODES] + redis = Redis::Distributed.new nodes + + assert_equal "#", redis.inspect + end + + def test_default_as_urls + nodes = ["redis://127.0.0.1:#{PORT}/15", *NODES] + redis = Redis::Distributed.new nodes + assert_equal ["redis://127.0.0.1:#{PORT}/15", *NODES], redis.nodes.map { |node| node._client.id } + end + + def test_default_as_config_hashes + nodes = [OPTIONS.merge(:host => '127.0.0.1'), OPTIONS.merge(:host => 'somehost', :port => PORT.next)] + redis = Redis::Distributed.new nodes + assert_equal ["redis://127.0.0.1:#{PORT}/15","redis://somehost:#{PORT.next}/15"], redis.nodes.map { |node| node._client.id } + end + + def test_as_mix_and_match + nodes = ["redis://127.0.0.1:7389/15", OPTIONS.merge(:host => 'somehost'), OPTIONS.merge(:host => 'somehost', :port => PORT.next)] + redis = Redis::Distributed.new nodes + assert_equal ["redis://127.0.0.1:7389/15", "redis://somehost:#{PORT}/15", "redis://somehost:#{PORT.next}/15"], redis.nodes.map { |node| node._client.id } + end + + def test_override_id + nodes = [OPTIONS.merge(:host => '127.0.0.1', :id => "test"), OPTIONS.merge( :host => 'somehost', :port => PORT.next, :id => "test1")] + redis = Redis::Distributed.new nodes + assert_equal redis.nodes.first._client.id, "test" + assert_equal redis.nodes.last._client.id, "test1" + assert_equal "#", redis.inspect + end + + def test_can_be_duped_to_create_a_new_connection + redis = Redis::Distributed.new(NODES) + + clients = redis.info[0]["connected_clients"].to_i + + r2 = redis.dup + r2.ping + + assert_equal clients + 1, redis.info[0]["connected_clients"].to_i + end + + def test_keeps_options_after_dup + r1 = Redis::Distributed.new(NODES, :tag => /^(\w+):/) + + assert_raise(Redis::Distributed::CannotDistribute) do + r1.sinter("foo", "bar") + end + + assert_equal [], r1.sinter("baz:foo", "baz:bar") + + r2 = r1.dup + + assert_raise(Redis::Distributed::CannotDistribute) do + r2.sinter("foo", "bar") + end + + assert_equal [], r2.sinter("baz:foo", "baz:bar") + end +end diff --git a/test/distributed_key_tags_test.rb b/test/distributed_key_tags_test.rb new file mode 100644 index 000000000..a778fec72 --- /dev/null +++ b/test/distributed_key_tags_test.rb @@ -0,0 +1,50 @@ +require_relative "helper" + +class TestDistributedKeyTags < Test::Unit::TestCase + + include Helper + include Helper::Distributed + + def test_hashes_consistently + r1 = Redis::Distributed.new ["redis://127.0.0.1:#{PORT}/15", *NODES] + r2 = Redis::Distributed.new ["redis://127.0.0.1:#{PORT}/15", *NODES] + r3 = Redis::Distributed.new ["redis://127.0.0.1:#{PORT}/15", *NODES] + + assert_equal r1.node_for("foo").id, r2.node_for("foo").id + assert_equal r1.node_for("foo").id, r3.node_for("foo").id + end + + def test_allows_clustering_of_keys + r = Redis::Distributed.new(NODES) + r.add_node("redis://127.0.0.1:#{PORT}/14") + r.flushdb + + 100.times do |i| + r.set "{foo}users:#{i}", i + end + + assert_equal [0, 100], r.nodes.map { |node| node.keys.size } + end + + def test_distributes_keys_if_no_clustering_is_used + r.add_node("redis://127.0.0.1:#{PORT}/14") + r.flushdb + + r.set "users:1", 1 + r.set "users:4", 4 + + assert_equal [1, 1], r.nodes.map { |node| node.keys.size } + end + + def test_allows_passing_a_custom_tag_extractor + r = Redis::Distributed.new(NODES, :tag => /^(.+?):/) + r.add_node("redis://127.0.0.1:#{PORT}/14") + r.flushdb + + 100.times do |i| + r.set "foo:users:#{i}", i + end + + assert_equal [0, 100], r.nodes.map { |node| node.keys.size } + end +end diff --git a/test/distributed_persistence_control_commands_test.rb b/test/distributed_persistence_control_commands_test.rb new file mode 100644 index 000000000..2d844258a --- /dev/null +++ b/test/distributed_persistence_control_commands_test.rb @@ -0,0 +1,24 @@ +require_relative "helper" + +class TestDistributedPersistenceControlCommands < Test::Unit::TestCase + + include Helper::Distributed + + def test_save + redis_mock(:save => lambda { "+SAVE" }) do |redis| + assert_equal ["SAVE"], redis.save + end + end + + def test_bgsave + redis_mock(:bgsave => lambda { "+BGSAVE" }) do |redis| + assert_equal ["BGSAVE"], redis.bgsave + end + end + + def test_lastsave + redis_mock(:lastsave => lambda { "+LASTSAVE" }) do |redis| + assert_equal ["LASTSAVE"], redis.lastsave + end + end +end diff --git a/test/distributed_publish_subscribe_test.rb b/test/distributed_publish_subscribe_test.rb new file mode 100644 index 000000000..a5fcfa53f --- /dev/null +++ b/test/distributed_publish_subscribe_test.rb @@ -0,0 +1,90 @@ +require_relative "helper" + +class TestDistributedPublishSubscribe < Test::Unit::TestCase + + include Helper::Distributed + + def test_subscribe_and_unsubscribe + assert_raise Redis::Distributed::CannotDistribute do + r.subscribe("foo", "bar") { } + end + + assert_raise Redis::Distributed::CannotDistribute do + r.subscribe("{qux}foo", "bar") { } + end + end + + def test_subscribe_and_unsubscribe_with_tags + @subscribed = false + @unsubscribed = false + + wire = Wire.new do + r.subscribe("foo") do |on| + on.subscribe do |channel, total| + @subscribed = true + @t1 = total + end + + on.message do |channel, message| + if message == "s1" + r.unsubscribe + @message = message + end + end + + on.unsubscribe do |channel, total| + @unsubscribed = true + @t2 = total + end + end + end + + # Wait until the subscription is active before publishing + Wire.pass while !@subscribed + + Redis::Distributed.new(NODES).publish("foo", "s1") + + wire.join + + assert @subscribed + assert_equal 1, @t1 + assert @unsubscribed + assert_equal 0, @t2 + assert_equal "s1", @message + end + + def test_subscribe_within_subscribe + @channels = [] + + wire = Wire.new do + r.subscribe("foo") do |on| + on.subscribe do |channel, total| + @channels << channel + + r.subscribe("bar") if channel == "foo" + r.unsubscribe if channel == "bar" + end + end + end + + wire.join + + assert_equal ["foo", "bar"], @channels + end + + def test_other_commands_within_a_subscribe + assert_raise Redis::CommandError do + r.subscribe("foo") do |on| + on.subscribe do |channel, total| + r.set("bar", "s2") + end + end + end + end + + def test_subscribe_without_a_block + assert_raise LocalJumpError do + r.subscribe("foo") + end + end +end diff --git a/test/distributed_remote_server_control_commands_test.rb b/test/distributed_remote_server_control_commands_test.rb new file mode 100644 index 000000000..66ec349f8 --- /dev/null +++ b/test/distributed_remote_server_control_commands_test.rb @@ -0,0 +1,64 @@ +require_relative "helper" + +class TestDistributedRemoteServerControlCommands < Test::Unit::TestCase + + include Helper::Distributed + + def test_info + keys = [ + "redis_version", + "uptime_in_seconds", + "uptime_in_days", + "connected_clients", + "used_memory", + "total_connections_received", + "total_commands_processed", + ] + + infos = r.info + + infos.each do |info| + keys.each do |k| + msg = "expected #info to include #{k}" + assert info.keys.include?(k), msg + end + end + end + + def test_info_commandstats + target_version "2.5.7" do + r.nodes.each { |n| n.config(:resetstat) } + r.ping # Executed on every node + + r.info(:commandstats).each do |info| + assert_equal "1", info["ping"]["calls"] + end + end + end + + def test_monitor + begin + r.monitor + rescue Exception => ex + ensure + assert ex.kind_of?(NotImplementedError) + end + end + + def test_echo + assert_equal ["foo bar baz\n"], r.echo("foo bar baz\n") + end + + def test_time + target_version "2.5.4" do + # Test that the difference between the time that Ruby reports and the time + # that Redis reports is minimal (prevents the test from being racy). + r.time.each do |rv| + redis_usec = rv[0] * 1_000_000 + rv[1] + ruby_usec = Integer(Time.now.to_f * 1_000_000) + + assert 500_000 > (ruby_usec - redis_usec).abs + end + end + end +end diff --git a/test/distributed_scripting_test.rb b/test/distributed_scripting_test.rb new file mode 100644 index 000000000..224ab2b05 --- /dev/null +++ b/test/distributed_scripting_test.rb @@ -0,0 +1,100 @@ +require_relative "helper" + +class TestDistributedScripting < Test::Unit::TestCase + + include Helper::Distributed + + def to_sha(script) + r.script(:load, script).first + end + + def test_script_exists + target_version "2.5.9" do # 2.6-rc1 + a = to_sha("return 1") + b = a.succ + + assert_equal [true], r.script(:exists, a) + assert_equal [false], r.script(:exists, b) + assert_equal [[true]], r.script(:exists, [a]) + assert_equal [[false]], r.script(:exists, [b]) + assert_equal [[true, false]], r.script(:exists, [a, b]) + end + end + + def test_script_flush + target_version "2.5.9" do # 2.6-rc1 + sha = to_sha("return 1") + assert r.script(:exists, sha).first + assert_equal ["OK"], r.script(:flush) + assert !r.script(:exists, sha).first + end + end + + def test_script_kill + target_version "2.5.9" do # 2.6-rc1 + redis_mock(:script => lambda { |arg| "+#{arg.upcase}" }) do |redis| + assert_equal ["KILL"], redis.script(:kill) + end + end + end + + def test_eval + target_version "2.5.9" do # 2.6-rc1 + assert_raises(Redis::Distributed::CannotDistribute) do + r.eval("return #KEYS") + end + + assert_raises(Redis::Distributed::CannotDistribute) do + r.eval("return KEYS", ["k1", "k2"]) + end + + assert_equal ["k1"], r.eval("return KEYS", ["k1"]) + assert_equal ["a1", "a2"], r.eval("return ARGV", ["k1"], ["a1", "a2"]) + end + end + + def test_eval_with_options_hash + target_version "2.5.9" do # 2.6-rc1 + assert_raises(Redis::Distributed::CannotDistribute) do + r.eval("return #KEYS", {}) + end + + assert_raises(Redis::Distributed::CannotDistribute) do + r.eval("return KEYS", { :keys => ["k1", "k2"] }) + end + + assert_equal ["k1"], r.eval("return KEYS", { :keys => ["k1"] }) + assert_equal ["a1", "a2"], r.eval("return ARGV", { :keys => ["k1"], :argv => ["a1", "a2"] }) + end + end + + def test_evalsha + target_version "2.5.9" do # 2.6-rc1 + assert_raises(Redis::Distributed::CannotDistribute) do + r.evalsha(to_sha("return #KEYS")) + end + + assert_raises(Redis::Distributed::CannotDistribute) do + r.evalsha(to_sha("return KEYS"), ["k1", "k2"]) + end + + assert_equal ["k1"], r.evalsha(to_sha("return KEYS"), ["k1"]) + assert_equal ["a1", "a2"], r.evalsha(to_sha("return ARGV"), ["k1"], ["a1", "a2"]) + end + end + + def test_evalsha_with_options_hash + target_version "2.5.9" do # 2.6-rc1 + assert_raises(Redis::Distributed::CannotDistribute) do + r.evalsha(to_sha("return #KEYS"), {}) + end + + assert_raises(Redis::Distributed::CannotDistribute) do + r.evalsha(to_sha("return KEYS"), { :keys => ["k1", "k2"] }) + end + + assert_equal ["k1"], r.evalsha(to_sha("return KEYS"), { :keys => ["k1"] }) + assert_equal ["a1", "a2"], r.evalsha(to_sha("return ARGV"), { :keys => ["k1"], :argv => ["a1", "a2"] }) + end + end +end diff --git a/test/distributed_sorting_test.rb b/test/distributed_sorting_test.rb new file mode 100644 index 000000000..7afb670b9 --- /dev/null +++ b/test/distributed_sorting_test.rb @@ -0,0 +1,18 @@ +require_relative "helper" + +class TestDistributedSorting < Test::Unit::TestCase + + include Helper::Distributed + + def test_sort + assert_raise(Redis::Distributed::CannotDistribute) do + r.set("foo:1", "s1") + r.set("foo:2", "s2") + + r.rpush("bar", "1") + r.rpush("bar", "2") + + r.sort("bar", :get => "foo:*", :limit => [0, 1]) + end + end +end diff --git a/test/distributed_test.rb b/test/distributed_test.rb new file mode 100644 index 000000000..b19e5329b --- /dev/null +++ b/test/distributed_test.rb @@ -0,0 +1,56 @@ +require_relative "helper" + +class TestDistributed < Test::Unit::TestCase + + include Helper::Distributed + + def test_handle_multiple_servers + @r = Redis::Distributed.new ["redis://127.0.0.1:#{PORT}/15", *NODES] + + 100.times do |idx| + @r.set(idx.to_s, "foo#{idx}") + end + + 100.times do |idx| + assert_equal "foo#{idx}", @r.get(idx.to_s) + end + + assert_equal "0", @r.keys("*").sort.first + assert_equal "string", @r.type("1") + end + + def test_add_nodes + logger = Logger.new("/dev/null") + + @r = Redis::Distributed.new NODES, :logger => logger, :timeout => 10 + + assert_equal "127.0.0.1", @r.nodes[0]._client.host + assert_equal PORT, @r.nodes[0]._client.port + assert_equal 15, @r.nodes[0]._client.db + assert_equal 10, @r.nodes[0]._client.timeout + assert_equal logger, @r.nodes[0]._client.logger + + @r.add_node("redis://127.0.0.1:6380/14") + + assert_equal "127.0.0.1", @r.nodes[1]._client.host + assert_equal 6380, @r.nodes[1]._client.port + assert_equal 14, @r.nodes[1]._client.db + assert_equal 10, @r.nodes[1]._client.timeout + assert_equal logger, @r.nodes[1]._client.logger + end + + def test_pipelining_commands_cannot_be_distributed + assert_raise Redis::Distributed::CannotDistribute do + r.pipelined do + r.lpush "foo", "s1" + r.lpush "foo", "s2" + end + end + end + + def test_unknown_commands_does_not_work_by_default + assert_raise NoMethodError do + r.not_yet_implemented_command + end + end +end diff --git a/test/distributed_transactions_test.rb b/test/distributed_transactions_test.rb new file mode 100644 index 000000000..526e96d45 --- /dev/null +++ b/test/distributed_transactions_test.rb @@ -0,0 +1,30 @@ +require_relative "helper" + +class TestDistributedTransactions < Test::Unit::TestCase + + include Helper::Distributed + + def test_multi_discard + @foo = nil + + assert_raise Redis::Distributed::CannotDistribute do + r.multi { @foo = 1 } + end + + assert_equal nil, @foo + + assert_raise Redis::Distributed::CannotDistribute do + r.discard + end + end + + def test_watch_unwatch + assert_raise Redis::Distributed::CannotDistribute do + r.watch("foo") + end + + assert_raise Redis::Distributed::CannotDistribute do + r.unwatch + end + end +end diff --git a/test/helper.rb b/test/helper.rb index bb3b213d4..4d3e1610d 100644 --- a/test/helper.rb +++ b/test/helper.rb @@ -7,6 +7,7 @@ ENV["DRIVER"] ||= "ruby" require_relative "../lib/redis" +require_relative "../lib/redis/distributed" require_relative "../lib/redis/connection/#{ENV["DRIVER"]}" require_relative "support/redis_mock" @@ -176,4 +177,25 @@ def _new_client(options = {}) end end + module Distributed + + include Generic + + def version + Version.new(redis.info.first["redis_version"]) + end + + private + + def _format_options(options) + { + :timeout => OPTIONS[:timeout], + :logger => ::Logger.new(@log), + }.merge(options) + end + + def _new_client(options = {}) + Redis::Distributed.new(NODES, _format_options(options).merge(:driver => ENV["conn"])) + end + end end diff --git a/test/lint/blocking_commands.rb b/test/lint/blocking_commands.rb new file mode 100644 index 000000000..531e8d98f --- /dev/null +++ b/test/lint/blocking_commands.rb @@ -0,0 +1,150 @@ +module Lint + + module BlockingCommands + + def setup + super + + r.rpush("{zap}foo", "s1") + r.rpush("{zap}foo", "s2") + r.rpush("{zap}bar", "s1") + r.rpush("{zap}bar", "s2") + end + + def to_protocol(obj) + case obj + when String + "$#{obj.length}\r\n#{obj}\r\n" + when Array + "*#{obj.length}\r\n" + obj.map { |e| to_protocol(e) }.join + else + fail + end + end + + def mock(options = {}, &blk) + commands = { + :blpop => lambda do |*args| + sleep options[:delay] if options.has_key?(:delay) + to_protocol([args.first, args.last]) + end, + :brpop => lambda do |*args| + sleep options[:delay] if options.has_key?(:delay) + to_protocol([args.first, args.last]) + end, + :brpoplpush => lambda do |*args| + sleep options[:delay] if options.has_key?(:delay) + to_protocol(args.last) + end + } + + redis_mock(commands, &blk) + end + + def test_blpop + assert_equal ["{zap}foo", "s1"], r.blpop("{zap}foo") + assert_equal ["{zap}foo", "s2"], r.blpop(["{zap}foo"]) + assert_equal ["{zap}bar", "s1"], r.blpop(["{zap}bar", "{zap}foo"]) + assert_equal ["{zap}bar", "s2"], r.blpop(["{zap}foo", "{zap}bar"]) + end + + def test_blpop_timeout + mock do |r| + assert_equal ["{zap}foo", "0"], r.blpop("{zap}foo") + assert_equal ["{zap}foo", "1"], r.blpop("{zap}foo", :timeout => 1) + end + end + + def test_blpop_with_old_prototype + assert_equal ["{zap}foo", "s1"], r.blpop("{zap}foo", 0) + assert_equal ["{zap}foo", "s2"], r.blpop("{zap}foo", 0) + assert_equal ["{zap}bar", "s1"], r.blpop("{zap}bar", "{zap}foo", 0) + assert_equal ["{zap}bar", "s2"], r.blpop("{zap}foo", "{zap}bar", 0) + end + + def test_blpop_timeout_with_old_prototype + mock do |r| + assert_equal ["{zap}foo", "0"], r.blpop("{zap}foo", 0) + assert_equal ["{zap}foo", "1"], r.blpop("{zap}foo", 1) + end + end + + def test_brpop + assert_equal ["{zap}foo", "s2"], r.brpop("{zap}foo") + assert_equal ["{zap}foo", "s1"], r.brpop(["{zap}foo"]) + assert_equal ["{zap}bar", "s2"], r.brpop(["{zap}bar", "{zap}foo"]) + assert_equal ["{zap}bar", "s1"], r.brpop(["{zap}foo", "{zap}bar"]) + end + + def test_brpop_timeout + mock do |r| + assert_equal ["{zap}foo", "0"], r.brpop("{zap}foo") + assert_equal ["{zap}foo", "1"], r.brpop("{zap}foo", :timeout => 1) + end + end + + def test_brpop_with_old_prototype + assert_equal ["{zap}foo", "s2"], r.brpop("{zap}foo", 0) + assert_equal ["{zap}foo", "s1"], r.brpop("{zap}foo", 0) + assert_equal ["{zap}bar", "s2"], r.brpop("{zap}bar", "{zap}foo", 0) + assert_equal ["{zap}bar", "s1"], r.brpop("{zap}foo", "{zap}bar", 0) + end + + def test_brpop_timeout_with_old_prototype + mock do |r| + assert_equal ["{zap}foo", "0"], r.brpop("{zap}foo", 0) + assert_equal ["{zap}foo", "1"], r.brpop("{zap}foo", 1) + end + end + + def test_brpoplpush + assert_equal "s2", r.brpoplpush("{zap}foo", "{zap}qux") + assert_equal ["s2"], r.lrange("{zap}qux", 0, -1) + end + + def test_brpoplpush_timeout + mock do |r| + assert_equal "0", r.brpoplpush("{zap}foo", "{zap}bar") + assert_equal "1", r.brpoplpush("{zap}foo", "{zap}bar", :timeout => 1) + end + end + + def test_brpoplpush_with_old_prototype + assert_equal "s2", r.brpoplpush("{zap}foo", "{zap}qux", 0) + assert_equal ["s2"], r.lrange("{zap}qux", 0, -1) + end + + def test_brpoplpush_timeout_with_old_prototype + mock do |r| + assert_equal "0", r.brpoplpush("{zap}foo", "{zap}bar", 0) + assert_equal "1", r.brpoplpush("{zap}foo", "{zap}bar", 1) + end + end + + driver(:ruby, :hiredis) do + def test_blpop_socket_timeout + mock(:delay => 1 + OPTIONS[:timeout] * 2) do |r| + assert_raises(Redis::TimeoutError) do + r.blpop("{zap}foo", :timeout => 1) + end + end + end + + def test_brpop_socket_timeout + mock(:delay => 1 + OPTIONS[:timeout] * 2) do |r| + assert_raises(Redis::TimeoutError) do + r.brpop("{zap}foo", :timeout => 1) + end + end + end + + def test_brpoplpush_socket_timeout + mock(:delay => 1 + OPTIONS[:timeout] * 2) do |r| + assert_raises(Redis::TimeoutError) do + r.brpoplpush("{zap}foo", "{zap}bar", :timeout => 1) + end + end + end + end + end +end diff --git a/test/lint/hashes.rb b/test/lint/hashes.rb new file mode 100644 index 000000000..649e6673f --- /dev/null +++ b/test/lint/hashes.rb @@ -0,0 +1,162 @@ +module Lint + + module Hashes + + def test_hset_and_hget + r.hset("foo", "f1", "s1") + + assert_equal "s1", r.hget("foo", "f1") + end + + def test_hsetnx + r.hset("foo", "f1", "s1") + r.hsetnx("foo", "f1", "s2") + + assert_equal "s1", r.hget("foo", "f1") + + r.del("foo") + r.hsetnx("foo", "f1", "s2") + + assert_equal "s2", r.hget("foo", "f1") + end + + def test_hdel + r.hset("foo", "f1", "s1") + + assert_equal "s1", r.hget("foo", "f1") + + assert_equal 1, r.hdel("foo", "f1") + + assert_equal nil, r.hget("foo", "f1") + end + + def test_variadic_hdel + target_version "2.3.9" do + r.hset("foo", "f1", "s1") + r.hset("foo", "f2", "s2") + + assert_equal "s1", r.hget("foo", "f1") + assert_equal "s2", r.hget("foo", "f2") + + assert_equal 2, r.hdel("foo", ["f1", "f2"]) + + assert_equal nil, r.hget("foo", "f1") + assert_equal nil, r.hget("foo", "f2") + end + end + + def test_hexists + assert_equal false, r.hexists("foo", "f1") + + r.hset("foo", "f1", "s1") + + assert r.hexists("foo", "f1") + end + + def test_hlen + assert_equal 0, r.hlen("foo") + + r.hset("foo", "f1", "s1") + + assert_equal 1, r.hlen("foo") + + r.hset("foo", "f2", "s2") + + assert_equal 2, r.hlen("foo") + end + + def test_hkeys + assert_equal [], r.hkeys("foo") + + r.hset("foo", "f1", "s1") + r.hset("foo", "f2", "s2") + + assert_equal ["f1", "f2"], r.hkeys("foo") + end + + def test_hvals + assert_equal [], r.hvals("foo") + + r.hset("foo", "f1", "s1") + r.hset("foo", "f2", "s2") + + assert_equal ["s1", "s2"], r.hvals("foo") + end + + def test_hgetall + assert({} == r.hgetall("foo")) + + r.hset("foo", "f1", "s1") + r.hset("foo", "f2", "s2") + + assert({"f1" => "s1", "f2" => "s2"} == r.hgetall("foo")) + end + + def test_hmset + r.hmset("hash", "foo1", "bar1", "foo2", "bar2") + + assert_equal "bar1", r.hget("hash", "foo1") + assert_equal "bar2", r.hget("hash", "foo2") + end + + def test_hmset_with_invalid_arguments + assert_raise(Redis::CommandError) do + r.hmset("hash", "foo1", "bar1", "foo2", "bar2", "foo3") + end + end + + def test_mapped_hmset + r.mapped_hmset("foo", :f1 => "s1", :f2 => "s2") + + assert_equal "s1", r.hget("foo", "f1") + assert_equal "s2", r.hget("foo", "f2") + end + + def test_hmget + r.hset("foo", "f1", "s1") + r.hset("foo", "f2", "s2") + r.hset("foo", "f3", "s3") + + assert_equal ["s2", "s3"], r.hmget("foo", "f2", "f3") + end + + def test_hmget_mapped + r.hset("foo", "f1", "s1") + r.hset("foo", "f2", "s2") + r.hset("foo", "f3", "s3") + + assert({"f1" => "s1"} == r.mapped_hmget("foo", "f1")) + assert({"f1" => "s1", "f2" => "s2"} == r.mapped_hmget("foo", "f1", "f2")) + end + + def test_hincrby + r.hincrby("foo", "f1", 1) + + assert_equal "1", r.hget("foo", "f1") + + r.hincrby("foo", "f1", 2) + + assert_equal "3", r.hget("foo", "f1") + + r.hincrby("foo", "f1", -1) + + assert_equal "2", r.hget("foo", "f1") + end + + def test_hincrbyfloat + target_version "2.5.4" do + r.hincrbyfloat("foo", "f1", 1.23) + + assert_equal "1.23", r.hget("foo", "f1") + + r.hincrbyfloat("foo", "f1", 0.77) + + assert_equal "2", r.hget("foo", "f1") + + r.hincrbyfloat("foo", "f1", -0.1) + + assert_equal "1.9", r.hget("foo", "f1") + end + end + end +end diff --git a/test/lint/hyper_log_log.rb b/test/lint/hyper_log_log.rb new file mode 100644 index 000000000..5472e22f5 --- /dev/null +++ b/test/lint/hyper_log_log.rb @@ -0,0 +1,60 @@ +module Lint + + module HyperLogLog + + def test_pfadd + target_version "2.8.9" do + assert_equal true, r.pfadd("foo", "s1") + assert_equal true, r.pfadd("foo", "s2") + assert_equal false, r.pfadd("foo", "s1") + + assert_equal 2, r.pfcount("foo") + end + end + + def test_variadic_pfadd + target_version "2.8.9" do + assert_equal true, r.pfadd("foo", ["s1", "s2"]) + assert_equal true, r.pfadd("foo", ["s1", "s2", "s3"]) + + assert_equal 3, r.pfcount("foo") + end + end + + def test_pfcount + target_version "2.8.9" do + assert_equal 0, r.pfcount("foo") + + assert_equal true, r.pfadd("foo", "s1") + + assert_equal 1, r.pfcount("foo") + end + end + + def test_variadic_pfcount + target_version "2.8.9" do + assert_equal 0, r.pfcount(["{1}foo", "{1}bar"]) + + assert_equal true, r.pfadd("{1}foo", "s1") + assert_equal true, r.pfadd("{1}bar", "s1") + assert_equal true, r.pfadd("{1}bar", "s2") + + assert_equal 2, r.pfcount("{1}foo", "{1}bar") + end + end + + def test_variadic_pfcount_expanded + target_version "2.8.9" do + assert_equal 0, r.pfcount("{1}foo", "{1}bar") + + assert_equal true, r.pfadd("{1}foo", "s1") + assert_equal true, r.pfadd("{1}bar", "s1") + assert_equal true, r.pfadd("{1}bar", "s2") + + assert_equal 2, r.pfcount("{1}foo", "{1}bar") + end + end + + end + +end diff --git a/test/lint/lists.rb b/test/lint/lists.rb new file mode 100644 index 000000000..3a230f675 --- /dev/null +++ b/test/lint/lists.rb @@ -0,0 +1,143 @@ +module Lint + + module Lists + + def test_lpush + r.lpush "foo", "s1" + r.lpush "foo", "s2" + + assert_equal 2, r.llen("foo") + assert_equal "s2", r.lpop("foo") + end + + def test_variadic_lpush + target_version "2.3.9" do # 2.4-rc6 + assert_equal 3, r.lpush("foo", ["s1", "s2", "s3"]) + assert_equal 3, r.llen("foo") + assert_equal "s3", r.lpop("foo") + end + end + + def test_lpushx + r.lpushx "foo", "s1" + r.lpush "foo", "s2" + r.lpushx "foo", "s3" + + assert_equal 2, r.llen("foo") + assert_equal ["s3", "s2"], r.lrange("foo", 0, -1) + end + + def test_rpush + r.rpush "foo", "s1" + r.rpush "foo", "s2" + + assert_equal 2, r.llen("foo") + assert_equal "s2", r.rpop("foo") + end + + def test_variadic_rpush + target_version "2.3.9" do # 2.4-rc6 + assert_equal 3, r.rpush("foo", ["s1", "s2", "s3"]) + assert_equal 3, r.llen("foo") + assert_equal "s3", r.rpop("foo") + end + end + + def test_rpushx + r.rpushx "foo", "s1" + r.rpush "foo", "s2" + r.rpushx "foo", "s3" + + assert_equal 2, r.llen("foo") + assert_equal ["s2", "s3"], r.lrange("foo", 0, -1) + end + + def test_llen + r.rpush "foo", "s1" + r.rpush "foo", "s2" + + assert_equal 2, r.llen("foo") + end + + def test_lrange + r.rpush "foo", "s1" + r.rpush "foo", "s2" + r.rpush "foo", "s3" + + assert_equal ["s2", "s3"], r.lrange("foo", 1, -1) + assert_equal ["s1", "s2"], r.lrange("foo", 0, 1) + + assert_equal [], r.lrange("bar", 0, -1) + end + + def test_ltrim + r.rpush "foo", "s1" + r.rpush "foo", "s2" + r.rpush "foo", "s3" + + r.ltrim "foo", 0, 1 + + assert_equal 2, r.llen("foo") + assert_equal ["s1", "s2"], r.lrange("foo", 0, -1) + end + + def test_lindex + r.rpush "foo", "s1" + r.rpush "foo", "s2" + + assert_equal "s1", r.lindex("foo", 0) + assert_equal "s2", r.lindex("foo", 1) + end + + def test_lset + r.rpush "foo", "s1" + r.rpush "foo", "s2" + + assert_equal "s2", r.lindex("foo", 1) + assert r.lset("foo", 1, "s3") + assert_equal "s3", r.lindex("foo", 1) + + assert_raise Redis::CommandError do + r.lset("foo", 4, "s3") + end + end + + def test_lrem + r.rpush "foo", "s1" + r.rpush "foo", "s2" + + assert_equal 1, r.lrem("foo", 1, "s1") + assert_equal ["s2"], r.lrange("foo", 0, -1) + end + + def test_lpop + r.rpush "foo", "s1" + r.rpush "foo", "s2" + + assert_equal 2, r.llen("foo") + assert_equal "s1", r.lpop("foo") + assert_equal 1, r.llen("foo") + end + + def test_rpop + r.rpush "foo", "s1" + r.rpush "foo", "s2" + + assert_equal 2, r.llen("foo") + assert_equal "s2", r.rpop("foo") + assert_equal 1, r.llen("foo") + end + + def test_linsert + r.rpush "foo", "s1" + r.rpush "foo", "s3" + r.linsert "foo", :before, "s3", "s2" + + assert_equal ["s1", "s2", "s3"], r.lrange("foo", 0, -1) + + assert_raise(Redis::CommandError) do + r.linsert "foo", :anywhere, "s3", "s2" + end + end + end +end diff --git a/test/lint/sets.rb b/test/lint/sets.rb new file mode 100644 index 000000000..f32b1de0e --- /dev/null +++ b/test/lint/sets.rb @@ -0,0 +1,140 @@ +module Lint + + module Sets + + def test_sadd + assert_equal true, r.sadd("foo", "s1") + assert_equal true, r.sadd("foo", "s2") + assert_equal false, r.sadd("foo", "s1") + + assert_equal ["s1", "s2"], r.smembers("foo").sort + end + + def test_variadic_sadd + target_version "2.3.9" do # 2.4-rc6 + assert_equal 2, r.sadd("foo", ["s1", "s2"]) + assert_equal 1, r.sadd("foo", ["s1", "s2", "s3"]) + + assert_equal ["s1", "s2", "s3"], r.smembers("foo").sort + end + end + + def test_srem + r.sadd("foo", "s1") + r.sadd("foo", "s2") + + assert_equal true, r.srem("foo", "s1") + assert_equal false, r.srem("foo", "s3") + + assert_equal ["s2"], r.smembers("foo") + end + + def test_variadic_srem + target_version "2.3.9" do # 2.4-rc6 + r.sadd("foo", "s1") + r.sadd("foo", "s2") + r.sadd("foo", "s3") + + assert_equal 1, r.srem("foo", ["s1", "aaa"]) + assert_equal 0, r.srem("foo", ["bbb", "ccc" "ddd"]) + assert_equal 1, r.srem("foo", ["eee", "s3"]) + + assert_equal ["s2"], r.smembers("foo") + end + end + + def test_spop + r.sadd "foo", "s1" + r.sadd "foo", "s2" + + assert ["s1", "s2"].include?(r.spop("foo")) + assert ["s1", "s2"].include?(r.spop("foo")) + assert_equal nil, r.spop("foo") + end + + def test_spop_with_positive_count + target_version "3.2.0" do + r.sadd "foo", "s1" + r.sadd "foo", "s2" + r.sadd "foo", "s3" + r.sadd "foo", "s4" + + pops = r.spop("foo", 3) + + assert !(["s1", "s2", "s3", "s4"] & pops).empty? + assert_equal 3, pops.size + assert_equal 1, r.scard("foo") + end + end + + def test_scard + assert_equal 0, r.scard("foo") + + r.sadd "foo", "s1" + + assert_equal 1, r.scard("foo") + + r.sadd "foo", "s2" + + assert_equal 2, r.scard("foo") + end + + def test_sismember + assert_equal false, r.sismember("foo", "s1") + + r.sadd "foo", "s1" + + assert_equal true, r.sismember("foo", "s1") + assert_equal false, r.sismember("foo", "s2") + end + + def test_smembers + assert_equal [], r.smembers("foo") + + r.sadd "foo", "s1" + r.sadd "foo", "s2" + + assert_equal ["s1", "s2"], r.smembers("foo").sort + end + + def test_srandmember + r.sadd "foo", "s1" + r.sadd "foo", "s2" + + 4.times do + assert ["s1", "s2"].include?(r.srandmember("foo")) + end + + assert_equal 2, r.scard("foo") + end + + def test_srandmember_with_positive_count + r.sadd "foo", "s1" + r.sadd "foo", "s2" + r.sadd "foo", "s3" + r.sadd "foo", "s4" + + 4.times do + assert !(["s1", "s2", "s3", "s4"] & r.srandmember("foo", 3)).empty? + + assert_equal 3, r.srandmember("foo", 3).size + end + + assert_equal 4, r.scard("foo") + end + + def test_srandmember_with_negative_count + r.sadd "foo", "s1" + r.sadd "foo", "s2" + r.sadd "foo", "s3" + r.sadd "foo", "s4" + + 4.times do + assert !(["s1", "s2", "s3", "s4"] & r.srandmember("foo", -6)).empty? + assert_equal 6, r.srandmember("foo", -6).size + end + + assert_equal 4, r.scard("foo") + end + end +end diff --git a/test/lint/sorted_sets.rb b/test/lint/sorted_sets.rb new file mode 100644 index 000000000..9dc11e218 --- /dev/null +++ b/test/lint/sorted_sets.rb @@ -0,0 +1,316 @@ +module Lint + + module SortedSets + + Infinity = 1.0/0.0 + + def test_zadd + assert_equal 0, r.zcard("foo") + assert_equal true, r.zadd("foo", 1, "s1") + assert_equal false, r.zadd("foo", 1, "s1") + assert_equal 1, r.zcard("foo") + r.del "foo" + + target_version "3.0.2" do + # XX option + assert_equal 0, r.zcard("foo") + assert_equal false, r.zadd("foo", 1, "s1", :xx => true) + r.zadd("foo", 1, "s1") + assert_equal false, r.zadd("foo", 2, "s1", :xx => true) + assert_equal 2, r.zscore("foo", "s1") + r.del "foo" + + # NX option + assert_equal 0, r.zcard("foo") + assert_equal true, r.zadd("foo", 1, "s1", :nx => true) + assert_equal false, r.zadd("foo", 2, "s1", :nx => true) + assert_equal 1, r.zscore("foo", "s1") + assert_equal 1, r.zcard("foo") + r.del "foo" + + # CH option + assert_equal 0, r.zcard("foo") + assert_equal true, r.zadd("foo", 1, "s1", :ch => true) + assert_equal false, r.zadd("foo", 1, "s1", :ch => true) + assert_equal true, r.zadd("foo", 2, "s1", :ch => true) + assert_equal 1, r.zcard("foo") + r.del "foo" + + # INCR option + assert_equal 1.0, r.zadd("foo", 1, "s1", :incr => true) + assert_equal 11.0, r.zadd("foo", 10, "s1", :incr => true) + assert_equal(-Infinity, r.zadd("bar", "-inf", "s1", :incr => true)) + assert_equal(+Infinity, r.zadd("bar", "+inf", "s2", :incr => true)) + r.del "foo", "bar" + + # Incompatible options combination + assert_raise(Redis::CommandError) { r.zadd("foo", 1, "s1", :xx => true, :nx => true) } + end + end + + def test_variadic_zadd + target_version "2.3.9" do # 2.4-rc6 + # Non-nested array with pairs + assert_equal 0, r.zcard("foo") + assert_equal 2, r.zadd("foo", [1, "s1", 2, "s2"]) + assert_equal 1, r.zadd("foo", [4, "s1", 5, "s2", 6, "s3"]) + assert_equal 3, r.zcard("foo") + r.del "foo" + + # Nested array with pairs + assert_equal 0, r.zcard("foo") + assert_equal 2, r.zadd("foo", [[1, "s1"], [2, "s2"]]) + assert_equal 1, r.zadd("foo", [[4, "s1"], [5, "s2"], [6, "s3"]]) + assert_equal 3, r.zcard("foo") + r.del "foo" + + # Wrong number of arguments + assert_raise(Redis::CommandError) { r.zadd("foo", ["bar"]) } + assert_raise(Redis::CommandError) { r.zadd("foo", ["bar", "qux", "zap"]) } + end + + target_version "3.0.2" do + # XX option + assert_equal 0, r.zcard("foo") + assert_equal 0, r.zadd("foo", [1, "s1", 2, "s2"], :xx => true) + r.zadd("foo", [1, "s1", 2, "s2"]) + assert_equal 0, r.zadd("foo", [2, "s1", 3, "s2", 4, "s3"], :xx => true) + assert_equal 2, r.zscore("foo", "s1") + assert_equal 3, r.zscore("foo", "s2") + assert_equal nil, r.zscore("foo", "s3") + assert_equal 2, r.zcard("foo") + r.del "foo" + + # NX option + assert_equal 0, r.zcard("foo") + assert_equal 2, r.zadd("foo", [1, "s1", 2, "s2"], :nx => true) + assert_equal 1, r.zadd("foo", [2, "s1", 3, "s2", 4, "s3"], :nx => true) + assert_equal 1, r.zscore("foo", "s1") + assert_equal 2, r.zscore("foo", "s2") + assert_equal 4, r.zscore("foo", "s3") + assert_equal 3, r.zcard("foo") + r.del "foo" + + # CH option + assert_equal 0, r.zcard("foo") + assert_equal 2, r.zadd("foo", [1, "s1", 2, "s2"], :ch => true) + assert_equal 2, r.zadd("foo", [1, "s1", 3, "s2", 4, "s3"], :ch => true) + assert_equal 3, r.zcard("foo") + r.del "foo" + + # INCR option + assert_equal 1.0, r.zadd("foo", [1, "s1"], :incr => true) + assert_equal 11.0, r.zadd("foo", [10, "s1"], :incr => true) + assert_equal(-Infinity, r.zadd("bar", ["-inf", "s1"], :incr => true)) + assert_equal(+Infinity, r.zadd("bar", ["+inf", "s2"], :incr => true)) + assert_raise(Redis::CommandError) { r.zadd("foo", [1, "s1", 2, "s2"], :incr => true) } + r.del "foo", "bar" + + # Incompatible options combination + assert_raise(Redis::CommandError) { r.zadd("foo", [1, "s1"], :xx => true, :nx => true) } + end + end + + def test_zrem + r.zadd("foo", 1, "s1") + r.zadd("foo", 2, "s2") + + assert_equal 2, r.zcard("foo") + assert_equal true, r.zrem("foo", "s1") + assert_equal false, r.zrem("foo", "s1") + assert_equal 1, r.zcard("foo") + end + + def test_variadic_zrem + target_version "2.3.9" do # 2.4-rc6 + r.zadd("foo", 1, "s1") + r.zadd("foo", 2, "s2") + r.zadd("foo", 3, "s3") + + assert_equal 3, r.zcard("foo") + assert_equal 1, r.zrem("foo", ["s1", "aaa"]) + assert_equal 0, r.zrem("foo", ["bbb", "ccc" "ddd"]) + assert_equal 1, r.zrem("foo", ["eee", "s3"]) + assert_equal 1, r.zcard("foo") + end + end + + def test_zincrby + rv = r.zincrby "foo", 1, "s1" + assert_equal 1.0, rv + + rv = r.zincrby "foo", 10, "s1" + assert_equal 11.0, rv + + rv = r.zincrby "bar", "-inf", "s1" + assert_equal(-Infinity, rv) + + rv = r.zincrby "bar", "+inf", "s2" + assert_equal(+Infinity, rv) + end + + def test_zrank + r.zadd "foo", 1, "s1" + r.zadd "foo", 2, "s2" + r.zadd "foo", 3, "s3" + + assert_equal 2, r.zrank("foo", "s3") + end + + def test_zrevrank + r.zadd "foo", 1, "s1" + r.zadd "foo", 2, "s2" + r.zadd "foo", 3, "s3" + + assert_equal 0, r.zrevrank("foo", "s3") + end + + def test_zrange + r.zadd "foo", 1, "s1" + r.zadd "foo", 2, "s2" + r.zadd "foo", 3, "s3" + + assert_equal ["s1", "s2"], r.zrange("foo", 0, 1) + assert_equal [["s1", 1.0], ["s2", 2.0]], r.zrange("foo", 0, 1, :with_scores => true) + assert_equal [["s1", 1.0], ["s2", 2.0]], r.zrange("foo", 0, 1, :withscores => true) + + r.zadd "bar", "-inf", "s1" + r.zadd "bar", "+inf", "s2" + assert_equal [["s1", -Infinity], ["s2", +Infinity]], r.zrange("bar", 0, 1, :with_scores => true) + assert_equal [["s1", -Infinity], ["s2", +Infinity]], r.zrange("bar", 0, 1, :withscores => true) + end + + def test_zrevrange + r.zadd "foo", 1, "s1" + r.zadd "foo", 2, "s2" + r.zadd "foo", 3, "s3" + + assert_equal ["s3", "s2"], r.zrevrange("foo", 0, 1) + assert_equal [["s3", 3.0], ["s2", 2.0]], r.zrevrange("foo", 0, 1, :with_scores => true) + assert_equal [["s3", 3.0], ["s2", 2.0]], r.zrevrange("foo", 0, 1, :withscores => true) + + r.zadd "bar", "-inf", "s1" + r.zadd "bar", "+inf", "s2" + assert_equal [["s2", +Infinity], ["s1", -Infinity]], r.zrevrange("bar", 0, 1, :with_scores => true) + assert_equal [["s2", +Infinity], ["s1", -Infinity]], r.zrevrange("bar", 0, 1, :withscores => true) + end + + def test_zrangebyscore + r.zadd "foo", 1, "s1" + r.zadd "foo", 2, "s2" + r.zadd "foo", 3, "s3" + + assert_equal ["s2", "s3"], r.zrangebyscore("foo", 2, 3) + end + + def test_zrevrangebyscore + r.zadd "foo", 1, "s1" + r.zadd "foo", 2, "s2" + r.zadd "foo", 3, "s3" + + assert_equal ["s3", "s2"], r.zrevrangebyscore("foo", 3, 2) + end + + def test_zrangebyscore_with_limit + r.zadd "foo", 1, "s1" + r.zadd "foo", 2, "s2" + r.zadd "foo", 3, "s3" + r.zadd "foo", 4, "s4" + + assert_equal ["s2"], r.zrangebyscore("foo", 2, 4, :limit => [0, 1]) + assert_equal ["s3"], r.zrangebyscore("foo", 2, 4, :limit => [1, 1]) + assert_equal ["s3", "s4"], r.zrangebyscore("foo", 2, 4, :limit => [1, 2]) + end + + def test_zrevrangebyscore_with_limit + r.zadd "foo", 1, "s1" + r.zadd "foo", 2, "s2" + r.zadd "foo", 3, "s3" + r.zadd "foo", 4, "s4" + + assert_equal ["s4"], r.zrevrangebyscore("foo", 4, 2, :limit => [0, 1]) + assert_equal ["s3"], r.zrevrangebyscore("foo", 4, 2, :limit => [1, 1]) + assert_equal ["s3", "s2"], r.zrevrangebyscore("foo", 4, 2, :limit => [1, 2]) + end + + def test_zrangebyscore_with_withscores + r.zadd "foo", 1, "s1" + r.zadd "foo", 2, "s2" + r.zadd "foo", 3, "s3" + r.zadd "foo", 4, "s4" + + assert_equal [["s2", 2.0]], r.zrangebyscore("foo", 2, 4, :limit => [0, 1], :with_scores => true) + assert_equal [["s3", 3.0]], r.zrangebyscore("foo", 2, 4, :limit => [1, 1], :with_scores => true) + assert_equal [["s2", 2.0]], r.zrangebyscore("foo", 2, 4, :limit => [0, 1], :withscores => true) + assert_equal [["s3", 3.0]], r.zrangebyscore("foo", 2, 4, :limit => [1, 1], :withscores => true) + + r.zadd "bar", "-inf", "s1" + r.zadd "bar", "+inf", "s2" + assert_equal [["s1", -Infinity]], r.zrangebyscore("bar", -Infinity, +Infinity, :limit => [0, 1], :with_scores => true) + assert_equal [["s2", +Infinity]], r.zrangebyscore("bar", -Infinity, +Infinity, :limit => [1, 1], :with_scores => true) + assert_equal [["s1", -Infinity]], r.zrangebyscore("bar", -Infinity, +Infinity, :limit => [0, 1], :withscores => true) + assert_equal [["s2", +Infinity]], r.zrangebyscore("bar", -Infinity, +Infinity, :limit => [1, 1], :withscores => true) + end + + def test_zrevrangebyscore_with_withscores + r.zadd "foo", 1, "s1" + r.zadd "foo", 2, "s2" + r.zadd "foo", 3, "s3" + r.zadd "foo", 4, "s4" + + assert_equal [["s4", 4.0]], r.zrevrangebyscore("foo", 4, 2, :limit => [0, 1], :with_scores => true) + assert_equal [["s3", 3.0]], r.zrevrangebyscore("foo", 4, 2, :limit => [1, 1], :with_scores => true) + assert_equal [["s4", 4.0]], r.zrevrangebyscore("foo", 4, 2, :limit => [0, 1], :withscores => true) + assert_equal [["s3", 3.0]], r.zrevrangebyscore("foo", 4, 2, :limit => [1, 1], :withscores => true) + + r.zadd "bar", "-inf", "s1" + r.zadd "bar", "+inf", "s2" + assert_equal [["s2", +Infinity]], r.zrevrangebyscore("bar", +Infinity, -Infinity, :limit => [0, 1], :with_scores => true) + assert_equal [["s1", -Infinity]], r.zrevrangebyscore("bar", +Infinity, -Infinity, :limit => [1, 1], :with_scores => true) + assert_equal [["s2", +Infinity]], r.zrevrangebyscore("bar", +Infinity, -Infinity, :limit => [0, 1], :withscores => true) + assert_equal [["s1", -Infinity]], r.zrevrangebyscore("bar", +Infinity, -Infinity, :limit => [1, 1], :withscores => true) + end + + def test_zcard + assert_equal 0, r.zcard("foo") + + r.zadd "foo", 1, "s1" + + assert_equal 1, r.zcard("foo") + end + + def test_zscore + r.zadd "foo", 1, "s1" + + assert_equal 1.0, r.zscore("foo", "s1") + + assert_equal nil, r.zscore("foo", "s2") + assert_equal nil, r.zscore("bar", "s1") + + r.zadd "bar", "-inf", "s1" + r.zadd "bar", "+inf", "s2" + assert_equal(-Infinity, r.zscore("bar", "s1")) + assert_equal(+Infinity, r.zscore("bar", "s2")) + end + + def test_zremrangebyrank + r.zadd "foo", 10, "s1" + r.zadd "foo", 20, "s2" + r.zadd "foo", 30, "s3" + r.zadd "foo", 40, "s4" + + assert_equal 3, r.zremrangebyrank("foo", 1, 3) + assert_equal ["s1"], r.zrange("foo", 0, -1) + end + + def test_zremrangebyscore + r.zadd "foo", 1, "s1" + r.zadd "foo", 2, "s2" + r.zadd "foo", 3, "s3" + r.zadd "foo", 4, "s4" + + assert_equal 3, r.zremrangebyscore("foo", 2, 4) + assert_equal ["s1"], r.zrange("foo", 0, -1) + end + end +end diff --git a/test/lint/strings.rb b/test/lint/strings.rb new file mode 100644 index 000000000..e17eaf7fb --- /dev/null +++ b/test/lint/strings.rb @@ -0,0 +1,246 @@ +module Lint + + module Strings + + def test_set_and_get + r.set("foo", "s1") + + assert_equal "s1", r.get("foo") + end + + def test_set_and_get_with_newline_characters + r.set("foo", "1\n") + + assert_equal "1\n", r.get("foo") + end + + def test_set_and_get_with_non_string_value + value = ["a", "b"] + + r.set("foo", value) + + assert_equal value.to_s, r.get("foo") + end + + def test_set_and_get_with_ascii_characters + with_external_encoding("ASCII-8BIT") do + (0..255).each do |i| + str = "#{i.chr}---#{i.chr}" + r.set("foo", str) + + assert_equal str, r.get("foo") + end + end + end + + def test_set_with_ex + target_version "2.6.12" do + r.set("foo", "bar", :ex => 2) + assert_in_range 0..2, r.ttl("foo") + end + end + + def test_set_with_px + target_version "2.6.12" do + r.set("foo", "bar", :px => 2000) + assert_in_range 0..2, r.ttl("foo") + end + end + + def test_set_with_nx + target_version "2.6.12" do + r.set("foo", "qux", :nx => true) + assert !r.set("foo", "bar", :nx => true) + assert_equal "qux", r.get("foo") + + r.del("foo") + assert r.set("foo", "bar", :nx => true) + assert_equal "bar", r.get("foo") + end + end + + def test_set_with_xx + target_version "2.6.12" do + r.set("foo", "qux") + assert r.set("foo", "bar", :xx => true) + assert_equal "bar", r.get("foo") + + r.del("foo") + assert !r.set("foo", "bar", :xx => true) + end + end + + def test_setex + assert r.setex("foo", 1, "bar") + assert_equal "bar", r.get("foo") + assert [0, 1].include? r.ttl("foo") + end + + def test_setex_with_non_string_value + value = ["b", "a", "r"] + + assert r.setex("foo", 1, value) + assert_equal value.to_s, r.get("foo") + assert [0, 1].include? r.ttl("foo") + end + + def test_psetex + target_version "2.5.4" do + assert r.psetex("foo", 1000, "bar") + assert_equal "bar", r.get("foo") + assert [0, 1].include? r.ttl("foo") + end + end + + def test_psetex_with_non_string_value + target_version "2.5.4" do + value = ["b", "a", "r"] + + assert r.psetex("foo", 1000, value) + assert_equal value.to_s, r.get("foo") + assert [0, 1].include? r.ttl("foo") + end + end + + def test_getset + r.set("foo", "bar") + + assert_equal "bar", r.getset("foo", "baz") + assert_equal "baz", r.get("foo") + end + + def test_getset_with_non_string_value + r.set("foo", "zap") + + value = ["b", "a", "r"] + + assert_equal "zap", r.getset("foo", value) + assert_equal value.to_s, r.get("foo") + end + + def test_setnx + r.set("foo", "qux") + assert !r.setnx("foo", "bar") + assert_equal "qux", r.get("foo") + + r.del("foo") + assert r.setnx("foo", "bar") + assert_equal "bar", r.get("foo") + end + + def test_setnx_with_non_string_value + value = ["b", "a", "r"] + + r.set("foo", "qux") + assert !r.setnx("foo", value) + assert_equal "qux", r.get("foo") + + r.del("foo") + assert r.setnx("foo", value) + assert_equal value.to_s, r.get("foo") + end + + def test_incr + assert_equal 1, r.incr("foo") + assert_equal 2, r.incr("foo") + assert_equal 3, r.incr("foo") + end + + def test_incrby + assert_equal 1, r.incrby("foo", 1) + assert_equal 3, r.incrby("foo", 2) + assert_equal 6, r.incrby("foo", 3) + end + + def test_incrbyfloat + target_version "2.5.4" do + assert_equal 1.23, r.incrbyfloat("foo", 1.23) + assert_equal 2 , r.incrbyfloat("foo", 0.77) + assert_equal 1.9 , r.incrbyfloat("foo", -0.1) + end + end + + def test_decr + r.set("foo", 3) + + assert_equal 2, r.decr("foo") + assert_equal 1, r.decr("foo") + assert_equal 0, r.decr("foo") + end + + def test_decrby + r.set("foo", 6) + + assert_equal 3, r.decrby("foo", 3) + assert_equal 1, r.decrby("foo", 2) + assert_equal 0, r.decrby("foo", 1) + end + + def test_append + r.set "foo", "s" + r.append "foo", "1" + + assert_equal "s1", r.get("foo") + end + + def test_getbit + r.set("foo", "a") + + assert_equal 1, r.getbit("foo", 1) + assert_equal 1, r.getbit("foo", 2) + assert_equal 0, r.getbit("foo", 3) + assert_equal 0, r.getbit("foo", 4) + assert_equal 0, r.getbit("foo", 5) + assert_equal 0, r.getbit("foo", 6) + assert_equal 1, r.getbit("foo", 7) + end + + def test_setbit + r.set("foo", "a") + + r.setbit("foo", 6, 1) + + assert_equal "c", r.get("foo") + end + + def test_bitcount + target_version "2.5.10" do + r.set("foo", "abcde") + + assert_equal 10, r.bitcount("foo", 1, 3) + assert_equal 17, r.bitcount("foo", 0, -1) + end + end + + def test_getrange + r.set("foo", "abcde") + + assert_equal "bcd", r.getrange("foo", 1, 3) + assert_equal "abcde", r.getrange("foo", 0, -1) + end + + def test_setrange + r.set("foo", "abcde") + + r.setrange("foo", 1, "bar") + + assert_equal "abare", r.get("foo") + end + + def test_setrange_with_non_string_value + r.set("foo", "abcde") + + value = ["b", "a", "r"] + + r.setrange("foo", 2, value) + + assert_equal "ab#{value.to_s}", r.get("foo") + end + + def test_strlen + r.set "foo", "lorem" + + assert_equal 5, r.strlen("foo") + end + end +end diff --git a/test/lint/value_types.rb b/test/lint/value_types.rb new file mode 100644 index 000000000..c4deb233d --- /dev/null +++ b/test/lint/value_types.rb @@ -0,0 +1,122 @@ +module Lint + + module ValueTypes + + def test_exists + assert_equal false, r.exists("foo") + + r.set("foo", "s1") + + assert_equal true, r.exists("foo") + end + + def test_type + assert_equal "none", r.type("foo") + + r.set("foo", "s1") + + assert_equal "string", r.type("foo") + end + + def test_keys + r.set("f", "s1") + r.set("fo", "s2") + r.set("foo", "s3") + + assert_equal ["f","fo", "foo"], r.keys("f*").sort + end + + def test_expire + r.set("foo", "s1") + assert r.expire("foo", 2) + assert_in_range 0..2, r.ttl("foo") + end + + def test_pexpire + target_version "2.5.4" do + r.set("foo", "s1") + assert r.pexpire("foo", 2000) + assert_in_range 0..2, r.ttl("foo") + end + end + + def test_expireat + r.set("foo", "s1") + assert r.expireat("foo", (Time.now + 2).to_i) + assert_in_range 0..2, r.ttl("foo") + end + + def test_pexpireat + target_version "2.5.4" do + r.set("foo", "s1") + assert r.pexpireat("foo", (Time.now + 2).to_i * 1_000) + assert_in_range 0..2, r.ttl("foo") + end + end + + def test_persist + r.set("foo", "s1") + r.expire("foo", 1) + r.persist("foo") + + assert(-1 == r.ttl("foo")) + end + + def test_ttl + r.set("foo", "s1") + r.expire("foo", 2) + assert_in_range 0..2, r.ttl("foo") + end + + def test_pttl + target_version "2.5.4" do + r.set("foo", "s1") + r.expire("foo", 2) + assert_in_range 1..2000, r.pttl("foo") + end + end + + def test_dump_and_restore + target_version "2.5.7" do + r.set("foo", "a") + v = r.dump("foo") + r.del("foo") + + assert r.restore("foo", 1000, v) + assert_equal "a", r.get("foo") + assert [0, 1].include? r.ttl("foo") + + r.rpush("bar", ["b", "c", "d"]) + w = r.dump("bar") + r.del("bar") + + assert r.restore("bar", 1000, w) + assert_equal ["b", "c", "d"], r.lrange("bar", 0, -1) + assert [0, 1].include? r.ttl("bar") + end + end + + def test_move + r.select 14 + r.flushdb + + r.set "bar", "s3" + + r.select 15 + + r.set "foo", "s1" + r.set "bar", "s2" + + assert r.move("foo", 14) + assert_equal nil, r.get("foo") + + assert !r.move("bar", 14) + assert_equal "s2", r.get("bar") + + r.select 14 + + assert_equal "s1", r.get("foo") + assert_equal "s3", r.get("bar") + end + end +end From 015a4fb4f6d931a4e72ecd5883267a5685c022ac Mon Sep 17 00:00:00 2001 From: Damian Janowski Date: Fri, 25 Aug 2017 12:14:39 -0300 Subject: [PATCH 32/34] Drop unnecessary C code. --- lib/redis/hash_ring.rb | 83 ++++++++++-------------------------------- 1 file changed, 20 insertions(+), 63 deletions(-) diff --git a/lib/redis/hash_ring.rb b/lib/redis/hash_ring.rb index b9b8d5ddb..e1c93b25a 100644 --- a/lib/redis/hash_ring.rb +++ b/lib/redis/hash_ring.rb @@ -60,72 +60,29 @@ def iter_nodes(key) end end - class << self - - # gem install RubyInline to use this code - # Native extension to perform the binary search within the hashring. - # There's a pure ruby version below so this is purely optional - # for performance. In testing 20k gets and sets, the native - # binary search shaved about 12% off the runtime (9sec -> 8sec). - begin - require 'inline' - inline do |builder| - builder.c <<-EOM - int binary_search(VALUE ary, unsigned int r) { - int upper = RARRAY_LEN(ary) - 1; - int lower = 0; - int idx = 0; - - while (lower <= upper) { - idx = (lower + upper) / 2; - - VALUE continuumValue = RARRAY_PTR(ary)[idx]; - unsigned int l = NUM2UINT(continuumValue); - if (l == r) { - return idx; - } - else if (l > r) { - upper = idx - 1; - } - else { - lower = idx + 1; - } - } - if (upper < 0) { - upper = RARRAY_LEN(ary) - 1; - } - return upper; - } - EOM - end - rescue Exception - # Find the closest index in HashRing with value <= the given value - def binary_search(ary, value, &block) - upper = ary.size - 1 - lower = 0 - idx = 0 - - while(lower <= upper) do - idx = (lower + upper) / 2 - comp = ary[idx] <=> value - - if comp == 0 - return idx - elsif comp > 0 - upper = idx - 1 - else - lower = idx + 1 - end - end - - if upper < 0 - upper = ary.size - 1 - end - return upper + # Find the closest index in HashRing with value <= the given value + def self.binary_search(ary, value, &block) + upper = ary.size - 1 + lower = 0 + idx = 0 + + while(lower <= upper) do + idx = (lower + upper) / 2 + comp = ary[idx] <=> value + + if comp == 0 + return idx + elsif comp > 0 + upper = idx - 1 + else + lower = idx + 1 end + end + if upper < 0 + upper = ary.size - 1 end + return upper end - end end From af499f00578d95cf5acf13ed81502517d576dfcd Mon Sep 17 00:00:00 2001 From: Damian Janowski Date: Fri, 25 Aug 2017 12:43:43 -0300 Subject: [PATCH 33/34] Dropping official support for Ruby < 2.2.2. --- .travis.yml | 3 +-- CHANGELOG.md | 2 ++ redis.gemspec | 2 ++ 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index acea46428..aa82ac9da 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,8 +3,7 @@ language: ruby script: make test rvm: - - 2.1 - - 2.2 + - 2.2.2 - 2.3.3 - 2.4.1 - jruby-9 diff --git a/CHANGELOG.md b/CHANGELOG.md index 3f7c5bb4a..87691c976 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ * Added support for `CLIENT` commands. The lower-level client can be accessed via `Redis#_client`. +* Dropped official support for Ruby < 2.2.2. + # 3.3.3 * Improved timeout handling after dropping Timeout module. diff --git a/redis.gemspec b/redis.gemspec index 8aa9070f7..c05ae5e20 100644 --- a/redis.gemspec +++ b/redis.gemspec @@ -34,6 +34,8 @@ Gem::Specification.new do |s| s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) } + s.required_ruby_version = '>= 2.2.2' + s.add_development_dependency("test-unit", ">= 3.1.5") s.add_development_dependency("hiredis") s.add_development_dependency("em-synchrony") From de19bd9605a7a690b80631b9b5c0286dd1bd4624 Mon Sep 17 00:00:00 2001 From: Damian Janowski Date: Fri, 25 Aug 2017 13:06:35 -0300 Subject: [PATCH 34/34] Fix connection refused error wrapping when using Synchrony. --- lib/redis/connection/synchrony.rb | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/redis/connection/synchrony.rb b/lib/redis/connection/synchrony.rb index c8b3dab9b..e15fd627d 100644 --- a/lib/redis/connection/synchrony.rb +++ b/lib/redis/connection/synchrony.rb @@ -72,7 +72,15 @@ class Synchrony def self.connect(config) if config[:scheme] == "unix" - conn = EventMachine.connect_unix_domain(config[:path], RedisClient) + begin + conn = EventMachine.connect_unix_domain(config[:path], RedisClient) + rescue RuntimeError => e + if e.message == "no connection" + raise Errno::ECONNREFUSED + else + raise e + end + end elsif config[:scheme] == "rediss" || config[:ssl] raise NotImplementedError, "SSL not supported by synchrony driver" else