redis 4.0.1 → 4.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -0
  3. data/.travis.yml +17 -29
  4. data/.travis/Gemfile +5 -0
  5. data/CHANGELOG.md +29 -0
  6. data/Gemfile +5 -0
  7. data/README.md +1 -1
  8. data/bin/build +71 -0
  9. data/lib/redis.rb +198 -12
  10. data/lib/redis/client.rb +26 -12
  11. data/lib/redis/cluster.rb +285 -0
  12. data/lib/redis/cluster/command.rb +81 -0
  13. data/lib/redis/cluster/command_loader.rb +32 -0
  14. data/lib/redis/cluster/key_slot_converter.rb +72 -0
  15. data/lib/redis/cluster/node.rb +104 -0
  16. data/lib/redis/cluster/node_key.rb +35 -0
  17. data/lib/redis/cluster/node_loader.rb +35 -0
  18. data/lib/redis/cluster/option.rb +76 -0
  19. data/lib/redis/cluster/slot.rb +69 -0
  20. data/lib/redis/cluster/slot_loader.rb +47 -0
  21. data/lib/redis/connection/ruby.rb +5 -2
  22. data/lib/redis/distributed.rb +10 -2
  23. data/lib/redis/errors.rb +46 -0
  24. data/lib/redis/pipeline.rb +9 -1
  25. data/lib/redis/version.rb +1 -1
  26. data/makefile +54 -22
  27. data/redis.gemspec +2 -1
  28. data/test/client_test.rb +17 -0
  29. data/test/cluster_abnormal_state_test.rb +38 -0
  30. data/test/cluster_blocking_commands_test.rb +15 -0
  31. data/test/cluster_client_internals_test.rb +77 -0
  32. data/test/cluster_client_key_hash_tags_test.rb +88 -0
  33. data/test/cluster_client_options_test.rb +147 -0
  34. data/test/cluster_client_pipelining_test.rb +59 -0
  35. data/test/cluster_client_replicas_test.rb +36 -0
  36. data/test/cluster_client_slots_test.rb +94 -0
  37. data/test/cluster_client_transactions_test.rb +71 -0
  38. data/test/cluster_commands_on_cluster_test.rb +165 -0
  39. data/test/cluster_commands_on_connection_test.rb +40 -0
  40. data/test/cluster_commands_on_geo_test.rb +74 -0
  41. data/test/cluster_commands_on_hashes_test.rb +11 -0
  42. data/test/cluster_commands_on_hyper_log_log_test.rb +17 -0
  43. data/test/cluster_commands_on_keys_test.rb +134 -0
  44. data/test/cluster_commands_on_lists_test.rb +15 -0
  45. data/test/cluster_commands_on_pub_sub_test.rb +101 -0
  46. data/test/cluster_commands_on_scripting_test.rb +56 -0
  47. data/test/cluster_commands_on_server_test.rb +221 -0
  48. data/test/cluster_commands_on_sets_test.rb +39 -0
  49. data/test/cluster_commands_on_sorted_sets_test.rb +35 -0
  50. data/test/cluster_commands_on_streams_test.rb +196 -0
  51. data/test/cluster_commands_on_strings_test.rb +15 -0
  52. data/test/cluster_commands_on_transactions_test.rb +41 -0
  53. data/test/cluster_commands_on_value_types_test.rb +14 -0
  54. data/test/commands_on_geo_test.rb +116 -0
  55. data/test/commands_on_hashes_test.rb +2 -14
  56. data/test/commands_on_hyper_log_log_test.rb +2 -14
  57. data/test/commands_on_lists_test.rb +2 -13
  58. data/test/commands_on_sets_test.rb +2 -70
  59. data/test/commands_on_sorted_sets_test.rb +2 -145
  60. data/test/commands_on_strings_test.rb +2 -94
  61. data/test/commands_on_value_types_test.rb +36 -0
  62. data/test/distributed_blocking_commands_test.rb +8 -0
  63. data/test/distributed_commands_on_hashes_test.rb +16 -3
  64. data/test/distributed_commands_on_hyper_log_log_test.rb +8 -13
  65. data/test/distributed_commands_on_lists_test.rb +4 -5
  66. data/test/distributed_commands_on_sets_test.rb +45 -46
  67. data/test/distributed_commands_on_sorted_sets_test.rb +51 -8
  68. data/test/distributed_commands_on_strings_test.rb +10 -0
  69. data/test/distributed_commands_on_value_types_test.rb +36 -0
  70. data/test/helper.rb +176 -32
  71. data/test/internals_test.rb +20 -1
  72. data/test/lint/blocking_commands.rb +40 -16
  73. data/test/lint/hashes.rb +41 -0
  74. data/test/lint/hyper_log_log.rb +15 -1
  75. data/test/lint/lists.rb +16 -0
  76. data/test/lint/sets.rb +142 -0
  77. data/test/lint/sorted_sets.rb +183 -2
  78. data/test/lint/strings.rb +102 -0
  79. data/test/pipelining_commands_test.rb +8 -0
  80. data/test/support/cluster/orchestrator.rb +199 -0
  81. data/test/support/redis_mock.rb +1 -1
  82. data/test/transactions_test.rb +10 -0
  83. metadata +81 -2
@@ -0,0 +1,147 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'helper'
4
+
5
+ # ruby -w -Itest test/cluster_client_options_test.rb
6
+ class TestClusterClientOptions < Test::Unit::TestCase
7
+ include Helper::Cluster
8
+
9
+ def test_option_class
10
+ option = Redis::Cluster::Option.new(cluster: %w[rediss://127.0.0.1:7000], replica: true)
11
+ assert_equal({ '127.0.0.1:7000' => { url: 'rediss://127.0.0.1:7000' } }, option.per_node_key)
12
+ assert_equal true, option.secure?
13
+ assert_equal true, option.use_replica?
14
+
15
+ option = Redis::Cluster::Option.new(cluster: %w[redis://127.0.0.1:7000], replica: false)
16
+ assert_equal({ '127.0.0.1:7000' => { url: 'redis://127.0.0.1:7000' } }, option.per_node_key)
17
+ assert_equal false, option.secure?
18
+ assert_equal false, option.use_replica?
19
+
20
+ option = Redis::Cluster::Option.new(cluster: %w[redis://127.0.0.1:7000])
21
+ assert_equal({ '127.0.0.1:7000' => { url: 'redis://127.0.0.1:7000' } }, option.per_node_key)
22
+ assert_equal false, option.secure?
23
+ assert_equal false, option.use_replica?
24
+ end
25
+
26
+ def test_client_accepts_valid_node_configs
27
+ nodes = ['redis://127.0.0.1:7000',
28
+ 'redis://127.0.0.1:7001',
29
+ { host: '127.0.0.1', port: '7002' },
30
+ { 'host' => '127.0.0.1', port: 7003 },
31
+ 'redis://127.0.0.1:7004',
32
+ 'redis://127.0.0.1:7005']
33
+
34
+ assert_nothing_raised do
35
+ build_another_client(cluster: nodes)
36
+ end
37
+ end
38
+
39
+ def test_client_accepts_valid_options
40
+ assert_nothing_raised do
41
+ build_another_client(timeout: 1.0)
42
+ end
43
+ end
44
+
45
+ def test_client_ignores_invalid_options
46
+ assert_nothing_raised do
47
+ build_another_client(invalid_option: true)
48
+ end
49
+ end
50
+
51
+ def test_client_works_even_if_so_many_unavailable_nodes_specified
52
+ nodes = (6001..7005).map { |port| "redis://127.0.0.1:#{port}" }
53
+ redis = build_another_client(cluster: nodes)
54
+
55
+ assert_equal 'PONG', redis.ping
56
+ end
57
+
58
+ def test_client_does_not_accept_db_specified_url
59
+ assert_raise(Redis::CannotConnectError, 'Could not connect to any nodes') do
60
+ build_another_client(cluster: ['redis://127.0.0.1:7000/1/namespace'])
61
+ end
62
+
63
+ assert_raise(Redis::CannotConnectError, 'Could not connect to any nodes') do
64
+ build_another_client(cluster: [{ host: '127.0.0.1', port: '7000' }], db: 1)
65
+ end
66
+ end
67
+
68
+ def test_client_does_not_accept_unconnectable_node_url_only
69
+ nodes = ['redis://127.0.0.1:7006']
70
+
71
+ assert_raise(Redis::CannotConnectError, 'Could not connect to any nodes') do
72
+ build_another_client(cluster: nodes)
73
+ end
74
+ end
75
+
76
+ def test_client_accepts_unconnectable_node_url_included
77
+ nodes = ['redis://127.0.0.1:7000', 'redis://127.0.0.1:7006']
78
+
79
+ assert_nothing_raised(Redis::CannotConnectError, 'Could not connect to any nodes') do
80
+ build_another_client(cluster: nodes)
81
+ end
82
+ end
83
+
84
+ def test_client_does_not_accept_http_scheme_url
85
+ nodes = ['http://127.0.0.1:80']
86
+
87
+ assert_raise(Redis::InvalidClientOptionError, "invalid uri scheme 'http'") do
88
+ build_another_client(cluster: nodes)
89
+ end
90
+ end
91
+
92
+ def test_client_does_not_accept_blank_included_config
93
+ nodes = ['']
94
+
95
+ assert_raise(Redis::InvalidClientOptionError, "invalid uri scheme ''") do
96
+ build_another_client(cluster: nodes)
97
+ end
98
+ end
99
+
100
+ def test_client_does_not_accept_bool_included_config
101
+ nodes = [true]
102
+
103
+ assert_raise(Redis::InvalidClientOptionError, "invalid uri scheme ''") do
104
+ build_another_client(cluster: nodes)
105
+ end
106
+ end
107
+
108
+ def test_client_does_not_accept_nil_included_config
109
+ nodes = [nil]
110
+
111
+ assert_raise(Redis::InvalidClientOptionError, "invalid uri scheme ''") do
112
+ build_another_client(cluster: nodes)
113
+ end
114
+ end
115
+
116
+ def test_client_does_not_accept_array_included_config
117
+ nodes = [[]]
118
+
119
+ assert_raise(Redis::InvalidClientOptionError, "invalid uri scheme ''") do
120
+ build_another_client(cluster: nodes)
121
+ end
122
+ end
123
+
124
+ def test_client_does_not_accept_empty_hash_included_config
125
+ nodes = [{}]
126
+
127
+ assert_raise(Redis::InvalidClientOptionError, 'Redis option of `cluster` must includes `:host` and `:port` keys') do
128
+ build_another_client(cluster: nodes)
129
+ end
130
+ end
131
+
132
+ def test_client_does_not_accept_object_included_config
133
+ nodes = [Object.new]
134
+
135
+ assert_raise(Redis::InvalidClientOptionError, 'Redis Cluster node config must includes String or Hash') do
136
+ build_another_client(cluster: nodes)
137
+ end
138
+ end
139
+
140
+ def test_client_does_not_accept_not_array_config
141
+ nodes = :not_array
142
+
143
+ assert_raise(Redis::InvalidClientOptionError, 'Redis Cluster node config must be Array') do
144
+ build_another_client(cluster: nodes)
145
+ end
146
+ end
147
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'helper'
4
+
5
+ # ruby -w -Itest test/cluster_client_pipelining_test.rb
6
+ class TestClusterClientPipelining < Test::Unit::TestCase
7
+ include Helper::Cluster
8
+
9
+ def test_pipelining_with_a_hash_tag
10
+ p1 = p2 = p3 = p4 = p5 = p6 = nil
11
+
12
+ redis.pipelined do |r|
13
+ r.set('{Presidents.of.USA}:1', 'George Washington')
14
+ r.set('{Presidents.of.USA}:2', 'John Adams')
15
+ r.set('{Presidents.of.USA}:3', 'Thomas Jefferson')
16
+ r.set('{Presidents.of.USA}:4', 'James Madison')
17
+ r.set('{Presidents.of.USA}:5', 'James Monroe')
18
+ r.set('{Presidents.of.USA}:6', 'John Quincy Adams')
19
+
20
+ p1 = r.get('{Presidents.of.USA}:1')
21
+ p2 = r.get('{Presidents.of.USA}:2')
22
+ p3 = r.get('{Presidents.of.USA}:3')
23
+ p4 = r.get('{Presidents.of.USA}:4')
24
+ p5 = r.get('{Presidents.of.USA}:5')
25
+ p6 = r.get('{Presidents.of.USA}:6')
26
+ end
27
+
28
+ [p1, p2, p3, p4, p5, p6].each do |actual|
29
+ assert_true actual.is_a?(Redis::Future)
30
+ end
31
+
32
+ assert_equal('George Washington', p1.value)
33
+ assert_equal('John Adams', p2.value)
34
+ assert_equal('Thomas Jefferson', p3.value)
35
+ assert_equal('James Madison', p4.value)
36
+ assert_equal('James Monroe', p5.value)
37
+ assert_equal('John Quincy Adams', p6.value)
38
+ end
39
+
40
+ def test_pipelining_without_hash_tags
41
+ assert_raise(Redis::Cluster::CrossSlotPipeliningError) do
42
+ redis.pipelined do
43
+ redis.set(:a, 1)
44
+ redis.set(:b, 2)
45
+ redis.set(:c, 3)
46
+ redis.set(:d, 4)
47
+ redis.set(:e, 5)
48
+ redis.set(:f, 6)
49
+
50
+ redis.get(:a)
51
+ redis.get(:b)
52
+ redis.get(:c)
53
+ redis.get(:d)
54
+ redis.get(:e)
55
+ redis.get(:f)
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'helper'
4
+
5
+ # ruby -w -Itest test/cluster_client_replicas_test.rb
6
+ class TestClusterClientReplicas < Test::Unit::TestCase
7
+ include Helper::Cluster
8
+
9
+ def test_client_can_command_with_replica
10
+ r = build_another_client(replica: true)
11
+
12
+ 100.times do |i|
13
+ assert_equal 'OK', r.set("key#{i}", i)
14
+ end
15
+
16
+ 100.times do |i|
17
+ assert_equal i.to_s, r.get("key#{i}")
18
+ end
19
+ end
20
+
21
+ def test_client_can_flush_with_replica
22
+ r = build_another_client(replica: true)
23
+
24
+ assert_equal 'OK', r.flushall
25
+ assert_equal 'OK', r.flushdb
26
+ end
27
+
28
+ def test_some_reference_commands_are_sent_to_slaves_if_needed
29
+ r = build_another_client(replica: true)
30
+
31
+ 5.times { |i| r.set("key#{i}", i) }
32
+
33
+ assert_equal %w[key0 key1 key2 key3 key4], r.keys
34
+ assert_equal 5, r.dbsize
35
+ end
36
+ end
@@ -0,0 +1,94 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'helper'
4
+
5
+ # ruby -w -Itest test/cluster_client_slots_test.rb
6
+ class TestClusterClientSlots < Test::Unit::TestCase
7
+ include Helper::Cluster
8
+
9
+ def test_slot_class
10
+ slot = Redis::Cluster::Slot.new('127.0.0.1:7000' => 1..10)
11
+
12
+ assert_equal false, slot.exists?(0)
13
+ assert_equal true, slot.exists?(1)
14
+ assert_equal true, slot.exists?(10)
15
+ assert_equal false, slot.exists?(11)
16
+
17
+ assert_equal nil, slot.find_node_key_of_master(0)
18
+ assert_equal nil, slot.find_node_key_of_slave(0)
19
+ assert_equal '127.0.0.1:7000', slot.find_node_key_of_master(1)
20
+ assert_equal '127.0.0.1:7000', slot.find_node_key_of_slave(1)
21
+ assert_equal '127.0.0.1:7000', slot.find_node_key_of_master(10)
22
+ assert_equal '127.0.0.1:7000', slot.find_node_key_of_slave(10)
23
+ assert_equal nil, slot.find_node_key_of_master(11)
24
+ assert_equal nil, slot.find_node_key_of_slave(11)
25
+
26
+ assert_equal nil, slot.put(1, '127.0.0.1:7001')
27
+ end
28
+
29
+ def test_slot_class_with_node_flags_and_replicas
30
+ slot = Redis::Cluster::Slot.new({ '127.0.0.1:7000' => 1..10, '127.0.0.1:7001' => 1..10 },
31
+ { '127.0.0.1:7000' => 'master', '127.0.0.1:7001' => 'slave' },
32
+ true)
33
+
34
+ assert_equal false, slot.exists?(0)
35
+ assert_equal true, slot.exists?(1)
36
+ assert_equal true, slot.exists?(10)
37
+ assert_equal false, slot.exists?(11)
38
+
39
+ assert_equal nil, slot.find_node_key_of_master(0)
40
+ assert_equal nil, slot.find_node_key_of_slave(0)
41
+ assert_equal '127.0.0.1:7000', slot.find_node_key_of_master(1)
42
+ assert_equal '127.0.0.1:7001', slot.find_node_key_of_slave(1)
43
+ assert_equal '127.0.0.1:7000', slot.find_node_key_of_master(10)
44
+ assert_equal '127.0.0.1:7001', slot.find_node_key_of_slave(10)
45
+ assert_equal nil, slot.find_node_key_of_master(11)
46
+ assert_equal nil, slot.find_node_key_of_slave(11)
47
+
48
+ assert_equal nil, slot.put(1, '127.0.0.1:7002')
49
+ end
50
+
51
+ def test_slot_class_with_node_flags_and_without_replicas
52
+ slot = Redis::Cluster::Slot.new({ '127.0.0.1:7000' => 1..10, '127.0.0.1:7001' => 1..10 },
53
+ { '127.0.0.1:7000' => 'master', '127.0.0.1:7001' => 'slave' },
54
+ false)
55
+
56
+ assert_equal false, slot.exists?(0)
57
+ assert_equal true, slot.exists?(1)
58
+ assert_equal true, slot.exists?(10)
59
+ assert_equal false, slot.exists?(11)
60
+
61
+ assert_equal nil, slot.find_node_key_of_master(0)
62
+ assert_equal nil, slot.find_node_key_of_slave(0)
63
+ assert_equal '127.0.0.1:7000', slot.find_node_key_of_master(1)
64
+ assert_equal '127.0.0.1:7000', slot.find_node_key_of_slave(1)
65
+ assert_equal '127.0.0.1:7000', slot.find_node_key_of_master(10)
66
+ assert_equal '127.0.0.1:7000', slot.find_node_key_of_slave(10)
67
+ assert_equal nil, slot.find_node_key_of_master(11)
68
+ assert_equal nil, slot.find_node_key_of_slave(11)
69
+
70
+ assert_equal nil, slot.put(1, '127.0.0.1:7002')
71
+ end
72
+
73
+ def test_slot_class_with_empty_slots
74
+ slot = Redis::Cluster::Slot.new({})
75
+
76
+ assert_equal false, slot.exists?(0)
77
+ assert_equal false, slot.exists?(1)
78
+
79
+ assert_equal nil, slot.find_node_key_of_master(0)
80
+ assert_equal nil, slot.find_node_key_of_slave(0)
81
+ assert_equal nil, slot.find_node_key_of_master(1)
82
+ assert_equal nil, slot.find_node_key_of_slave(1)
83
+
84
+ assert_equal nil, slot.put(1, '127.0.0.1:7001')
85
+ end
86
+
87
+ def test_redirection_when_slot_is_resharding
88
+ 100.times { |i| redis.set("{key}#{i}", i) }
89
+
90
+ redis_cluster_resharding(12539, src: '127.0.0.1:7002', dest: '127.0.0.1:7000') do
91
+ 100.times { |i| assert_equal i.to_s, redis.get("{key}#{i}") }
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'helper'
4
+
5
+ # ruby -w -Itest test/cluster_client_transactions_test.rb
6
+ class TestClusterClientTransactions < Test::Unit::TestCase
7
+ include Helper::Cluster
8
+
9
+ def test_transaction_with_hash_tag
10
+ rc1 = redis
11
+ rc2 = build_another_client
12
+
13
+ rc1.multi do |cli|
14
+ 100.times { |i| cli.set("{key}#{i}", i) }
15
+ end
16
+
17
+ 100.times { |i| assert_equal i.to_s, rc1.get("{key}#{i}") }
18
+ 100.times { |i| assert_equal i.to_s, rc2.get("{key}#{i}") }
19
+ end
20
+
21
+ def test_transaction_without_hash_tag
22
+ rc1 = redis
23
+ rc2 = build_another_client
24
+
25
+ assert_raise(Redis::Cluster::CrossSlotPipeliningError) do
26
+ rc1.multi do |cli|
27
+ 100.times { |i| cli.set("key#{i}", i) }
28
+ end
29
+ end
30
+
31
+ 100.times { |i| assert_equal nil, rc1.get("key#{i}") }
32
+ 100.times { |i| assert_equal nil, rc2.get("key#{i}") }
33
+ end
34
+
35
+ def test_transaction_with_replicas
36
+ rc1 = build_another_client(replica: true)
37
+ rc2 = build_another_client(replica: true)
38
+
39
+ rc1.multi do |cli|
40
+ 100.times { |i| cli.set("{key}#{i}", i) }
41
+ end
42
+
43
+ sleep 0.1
44
+
45
+ 100.times { |i| assert_equal i.to_s, rc1.get("{key}#{i}") }
46
+ 100.times { |i| assert_equal i.to_s, rc2.get("{key}#{i}") }
47
+ end
48
+
49
+ def test_transaction_with_watch
50
+ rc1 = redis
51
+ rc2 = build_another_client
52
+
53
+ rc1.set('{key}1', 100)
54
+ rc1.watch('{key}1')
55
+
56
+ rc2.set('{key}1', 200)
57
+ val = rc1.get('{key}1').to_i
58
+ val += 1
59
+
60
+ rc1.multi do |cli|
61
+ cli.set('{key}1', val)
62
+ cli.set('{key}2', 300)
63
+ end
64
+
65
+ assert_equal '200', rc1.get('{key}1')
66
+ assert_equal '200', rc2.get('{key}1')
67
+
68
+ assert_equal nil, rc1.get('{key}2')
69
+ assert_equal nil, rc2.get('{key}2')
70
+ end
71
+ end
@@ -0,0 +1,165 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'helper'
4
+
5
+ # ruby -w -Itest test/cluster_commands_on_cluster_test.rb
6
+ # @see https://redis.io/commands#cluster
7
+ class TestClusterCommandsOnCluster < Test::Unit::TestCase
8
+ include Helper::Cluster
9
+
10
+ def test_cluster_addslots
11
+ assert_raise(Redis::Cluster::OrchestrationCommandNotSupported, 'CLUSTER ADDSLOTS command should be...') do
12
+ redis.cluster(:addslots, 0, 1, 2)
13
+ end
14
+ end
15
+
16
+ def test_cluster_count_failure_reports
17
+ assert_raise(Redis::CommandError, 'ERR Unknown node unknown-node-id') do
18
+ redis.cluster('count-failure-reports', 'unknown-node-id')
19
+ end
20
+
21
+ node_id = redis.cluster(:nodes).first.fetch('node_id')
22
+ assert_true(redis.cluster('count-failure-reports', node_id) >= 0)
23
+ end
24
+
25
+ def test_cluster_countkeysinslot
26
+ assert_true(redis.cluster(:countkeysinslot, 0) >= 0)
27
+ assert_true(redis.cluster(:countkeysinslot, 16383) >= 0)
28
+
29
+ assert_raise(Redis::CommandError, 'ERR Invalid slot') do
30
+ redis.cluster(:countkeysinslot, -1)
31
+ end
32
+
33
+ assert_raise(Redis::CommandError, 'ERR Invalid slot') do
34
+ redis.cluster(:countkeysinslot, 16384)
35
+ end
36
+ end
37
+
38
+ def test_cluster_delslots
39
+ assert_raise(Redis::Cluster::OrchestrationCommandNotSupported, 'CLUSTER DELSLOTS command should be...') do
40
+ redis.cluster(:delslots, 0, 1, 2)
41
+ end
42
+ end
43
+
44
+ def test_cluster_failover
45
+ assert_raise(Redis::Cluster::OrchestrationCommandNotSupported, 'CLUSTER FAILOVER command should be...') do
46
+ redis.cluster(:failover, 'FORCE')
47
+ end
48
+ end
49
+
50
+ def test_cluster_forget
51
+ assert_raise(Redis::Cluster::OrchestrationCommandNotSupported, 'CLUSTER FORGET command should be...') do
52
+ redis.cluster(:forget, 'unknown-node-id')
53
+ end
54
+ end
55
+
56
+ def test_cluster_getkeysinslot
57
+ assert_instance_of Array, redis.cluster(:getkeysinslot, 0, 3)
58
+ end
59
+
60
+ def test_cluster_info
61
+ info = redis.cluster(:info)
62
+
63
+ assert_equal '3', info.fetch('cluster_size')
64
+ end
65
+
66
+ def test_cluster_keyslot
67
+ assert_equal Redis::Cluster::KeySlotConverter.convert('hogehoge'), redis.cluster(:keyslot, 'hogehoge')
68
+ assert_equal Redis::Cluster::KeySlotConverter.convert('12345'), redis.cluster(:keyslot, '12345')
69
+ assert_equal Redis::Cluster::KeySlotConverter.convert('foo'), redis.cluster(:keyslot, 'boo{foo}woo')
70
+ assert_equal Redis::Cluster::KeySlotConverter.convert('antirez.is.cool'), redis.cluster(:keyslot, 'antirez.is.cool')
71
+ assert_equal Redis::Cluster::KeySlotConverter.convert(''), redis.cluster(:keyslot, '')
72
+ end
73
+
74
+ def test_cluster_meet
75
+ assert_raise(Redis::Cluster::OrchestrationCommandNotSupported, 'CLUSTER MEET command should be...') do
76
+ redis.cluster(:meet, '127.0.0.1', 11211)
77
+ end
78
+ end
79
+
80
+ def test_cluster_nodes
81
+ cluster_nodes = redis.cluster(:nodes)
82
+ sample_node = cluster_nodes.first
83
+
84
+ assert_equal 6, cluster_nodes.length
85
+ assert_equal true, sample_node.key?('node_id')
86
+ assert_equal true, sample_node.key?('ip_port')
87
+ assert_equal true, sample_node.key?('flags')
88
+ assert_equal true, sample_node.key?('master_node_id')
89
+ assert_equal true, sample_node.key?('ping_sent')
90
+ assert_equal true, sample_node.key?('pong_recv')
91
+ assert_equal true, sample_node.key?('config_epoch')
92
+ assert_equal true, sample_node.key?('link_state')
93
+ assert_equal true, sample_node.key?('slots')
94
+ end
95
+
96
+ def test_cluster_replicate
97
+ assert_raise(Redis::Cluster::OrchestrationCommandNotSupported, 'CLUSTER REPLICATE command should be...') do
98
+ redis.cluster(:replicate)
99
+ end
100
+ end
101
+
102
+ def test_cluster_reset
103
+ assert_raise(Redis::Cluster::OrchestrationCommandNotSupported, 'CLUSTER RESET command should be...') do
104
+ redis.cluster(:reset)
105
+ end
106
+ end
107
+
108
+ def test_cluster_saveconfig
109
+ assert_equal 'OK', redis.cluster(:saveconfig)
110
+ end
111
+
112
+ def test_cluster_set_config_epoch
113
+ assert_raise(Redis::Cluster::OrchestrationCommandNotSupported, 'CLUSTER SET-CONFIG-EPOCH command should be...') do
114
+ redis.cluster('set-config-epoch')
115
+ end
116
+ end
117
+
118
+ def test_cluster_setslot
119
+ assert_raise(Redis::Cluster::OrchestrationCommandNotSupported, 'CLUSTER SETSLOT command should be...') do
120
+ redis.cluster(:setslot)
121
+ end
122
+ end
123
+
124
+ def test_cluster_slaves
125
+ cluster_nodes = redis.cluster(:nodes)
126
+
127
+ sample_master_node_id = cluster_nodes.find { |n| n.fetch('master_node_id') == '-' }.fetch('node_id')
128
+ sample_slave_node_id = cluster_nodes.find { |n| n.fetch('master_node_id') != '-' }.fetch('node_id')
129
+
130
+ assert_equal 'slave', redis.cluster(:slaves, sample_master_node_id).first.fetch('flags').first
131
+ assert_raise(Redis::CommandError, 'ERR The specified node is not a master') do
132
+ redis.cluster(:slaves, sample_slave_node_id)
133
+ end
134
+ end
135
+
136
+ def test_cluster_slots
137
+ slots = redis.cluster(:slots)
138
+ sample_slot = slots.first
139
+
140
+ assert_equal 3, slots.length
141
+ assert_equal true, sample_slot.key?('start_slot')
142
+ assert_equal true, sample_slot.key?('end_slot')
143
+ assert_equal true, sample_slot.key?('master')
144
+ assert_equal true, sample_slot.fetch('master').key?('ip')
145
+ assert_equal true, sample_slot.fetch('master').key?('port')
146
+ assert_equal true, sample_slot.fetch('master').key?('node_id')
147
+ assert_equal true, sample_slot.key?('replicas')
148
+ assert_equal true, sample_slot.fetch('replicas').is_a?(Array)
149
+ assert_equal true, sample_slot.fetch('replicas').first.key?('ip')
150
+ assert_equal true, sample_slot.fetch('replicas').first.key?('port')
151
+ assert_equal true, sample_slot.fetch('replicas').first.key?('node_id')
152
+ end
153
+
154
+ def test_readonly
155
+ assert_raise(Redis::Cluster::OrchestrationCommandNotSupported, 'READONLY command should be...') do
156
+ redis.readonly
157
+ end
158
+ end
159
+
160
+ def test_readwrite
161
+ assert_raise(Redis::Cluster::OrchestrationCommandNotSupported, 'READWRITE command should be...') do
162
+ redis.readwrite
163
+ end
164
+ end
165
+ end