Skip to content

Commit 959a1e1

Browse files
authored
Add some test cases (#14)
1 parent 48bbfec commit 959a1e1

File tree

3 files changed

+101
-12
lines changed

3 files changed

+101
-12
lines changed

lib/redis_client/cluster.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ def send_cluster_command(method, *command, **kwargs, &block)
179179
case subcommand
180180
when 'addslots', 'delslots', 'failover', 'forget', 'meet', 'replicate',
181181
'reset', 'set-config-epoch', 'setslot'
182-
raise ::RedisClient::Cluster::OrchestrationCommandNotSupported, 'cluster', subcommand
182+
raise ::RedisClient::Cluster::OrchestrationCommandNotSupported, ['cluster', subcommand]
183183
when 'saveconfig' then @node.call_all(method, *command, **kwargs, &block).first
184184
else assign_node(*command).send(method, *command, **kwargs, &block)
185185
end

lib/redis_client/cluster/errors.rb

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,24 @@
44

55
class RedisClient
66
class Cluster
7+
ERR_ARG_NORMALIZATION = ->(arg) { Array[arg].flatten.reject { |e| e.nil? || (e.respond_to?(:empty?) && e.empty?) } }
8+
79
# Raised when client connected to redis as cluster mode
810
# and failed to fetch cluster state information by commands.
911
class InitialSetupError < ::RedisClient::Error
10-
# @param errors [Array<Redis::BaseError>]
1112
def initialize(errors)
12-
super("Redis client could not fetch cluster information: #{errors&.map(&:message)&.uniq&.join(',')}")
13+
msg = ERR_ARG_NORMALIZATION.call(errors).map(&:message).uniq.join(',')
14+
super("Redis client could not fetch cluster information: #{msg}")
1315
end
1416
end
1517

1618
# Raised when client connected to redis as cluster mode
1719
# and some cluster subcommands were called.
1820
class OrchestrationCommandNotSupported < ::RedisClient::Error
19-
def initialize(command, subcommand = '')
20-
str = [command, subcommand].map(&:to_s).reject(&:empty?).join(' ').upcase
21+
def initialize(command)
22+
str = ERR_ARG_NORMALIZATION.call(command).map(&:to_s).join(' ').upcase
2123
msg = "#{str} command should be used with care "\
22-
'only by applications orchestrating Redis Cluster, like redis-trib, '\
24+
'only by applications orchestrating Redis Cluster, like redis-cli, '\
2325
'and the command if used out of the right context can leave the cluster '\
2426
'in a wrong state or cause data loss.'
2527
super(msg)
@@ -30,11 +32,9 @@ def initialize(command, subcommand = '')
3032
class CommandErrorCollection < ::RedisClient::Error
3133
attr_reader :errors
3234

33-
# @param errors [Hash{String => Redis::CommandError}]
34-
# @param error_message [String]
35-
def initialize(errors, error_message = 'Command errors were replied on any node')
36-
@errors = errors
37-
super(error_message)
35+
def initialize(errors)
36+
@errors = ERR_ARG_NORMALIZATION.call(errors)
37+
super("Command errors were replied on any node: #{@errors.map(&:message).uniq.join(',')}")
3838
end
3939
end
4040

@@ -49,7 +49,7 @@ def initialize(command)
4949
class CrossSlotPipeliningError < ::RedisClient::Error
5050
def initialize(keys)
5151
super("Cluster client couldn't send pipelining to single node. "\
52-
"The commands include cross slot keys. #{keys}")
52+
"The commands include cross slot keys: #{ERR_ARG_NORMALIZATION.call(keys).join(',')}")
5353
end
5454
end
5555
end
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# frozen_string_literal: true
2+
3+
require 'testing_helper'
4+
require 'redis_client/cluster/errors'
5+
6+
class RedisClient
7+
class Cluster
8+
class TestErrors < Minitest::Test
9+
DummyError = Struct.new('DummyError', :message)
10+
11+
def test_initial_setup_error
12+
[
13+
{
14+
errors: [DummyError.new('foo')],
15+
want: 'Redis client could not fetch cluster information: foo'
16+
},
17+
{
18+
errors: [DummyError.new('foo'), DummyError.new('bar')],
19+
want: 'Redis client could not fetch cluster information: foo,bar'
20+
},
21+
{ errors: [], want: 'Redis client could not fetch cluster information: ' },
22+
{ errors: '', want: 'Redis client could not fetch cluster information: ' },
23+
{ errors: nil, want: 'Redis client could not fetch cluster information: ' }
24+
].each_with_index do |c, idx|
25+
raise ::RedisClient::Cluster::InitialSetupError, c[:errors]
26+
rescue StandardError => e
27+
assert_equal(c[:want], e.message, "Case: #{idx}")
28+
end
29+
end
30+
31+
def test_orchestration_command_not_supported_error
32+
[
33+
{ command: %w[CLUSTER FORGET], want: 'CLUSTER FORGET command should be' },
34+
{ command: [], want: ' command should be' },
35+
{ command: '', want: ' command should be' },
36+
{ command: nil, want: ' command should be' }
37+
].each_with_index do |c, idx|
38+
raise ::RedisClient::Cluster::OrchestrationCommandNotSupported, c[:command]
39+
rescue StandardError => e
40+
assert(e.message.start_with?(c[:want]), "Case: #{idx}")
41+
end
42+
end
43+
44+
def test_command_error_collection_error
45+
[
46+
{
47+
errors: [DummyError.new('foo')],
48+
want: { msg: 'Command errors were replied on any node: foo', size: 1 }
49+
},
50+
{
51+
errors: [DummyError.new('foo'), DummyError.new('bar')],
52+
want: { msg: 'Command errors were replied on any node: foo,bar', size: 2 }
53+
},
54+
{ errors: [], want: { msg: 'Command errors were replied on any node: ', size: 0 } },
55+
{ errors: '', want: { msg: 'Command errors were replied on any node: ', size: 0 } },
56+
{ errors: nil, want: { msg: 'Command errors were replied on any node: ', size: 0 } }
57+
].each_with_index do |c, idx|
58+
raise ::RedisClient::Cluster::CommandErrorCollection, c[:errors]
59+
rescue StandardError => e
60+
assert_equal(c[:want][:msg], e.message, "Case: #{idx}")
61+
assert_equal(c[:want][:size], e.errors.size, "Case: #{idx}")
62+
end
63+
end
64+
65+
def test_ambiguous_node_error
66+
[
67+
{ command: 'MULTI', want: "Cluster client doesn't know which node the MULTI command should be sent to." },
68+
{ command: nil, want: "Cluster client doesn't know which node the command should be sent to." }
69+
].each_with_index do |c, idx|
70+
raise ::RedisClient::Cluster::AmbiguousNodeError, c[:command]
71+
rescue StandardError => e
72+
assert_equal(e.message, c[:want], "Case: #{idx}")
73+
end
74+
end
75+
76+
def test_cross_slot_pipelining_error
77+
[
78+
{ keys: %w[foo bar baz], want: 'keys: foo,bar,baz' },
79+
{ keys: '', want: 'keys: ' },
80+
{ keys: nil, want: 'keys: ' }
81+
].each_with_index do |c, idx|
82+
raise ::RedisClient::Cluster::CrossSlotPipeliningError, c[:keys]
83+
rescue StandardError => e
84+
assert(e.message.end_with?(c[:want]), "Case: #{idx}")
85+
end
86+
end
87+
end
88+
end
89+
end

0 commit comments

Comments
 (0)