discourse-redis 3.2.2

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 (107) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +16 -0
  3. data/.travis.yml +59 -0
  4. data/.travis/Gemfile +11 -0
  5. data/.yardopts +3 -0
  6. data/CHANGELOG.md +349 -0
  7. data/Gemfile +4 -0
  8. data/LICENSE +20 -0
  9. data/README.md +328 -0
  10. data/Rakefile +87 -0
  11. data/benchmarking/logging.rb +71 -0
  12. data/benchmarking/pipeline.rb +51 -0
  13. data/benchmarking/speed.rb +21 -0
  14. data/benchmarking/suite.rb +24 -0
  15. data/benchmarking/worker.rb +71 -0
  16. data/examples/basic.rb +15 -0
  17. data/examples/consistency.rb +114 -0
  18. data/examples/dist_redis.rb +43 -0
  19. data/examples/incr-decr.rb +17 -0
  20. data/examples/list.rb +26 -0
  21. data/examples/pubsub.rb +37 -0
  22. data/examples/sentinel.rb +41 -0
  23. data/examples/sentinel/start +49 -0
  24. data/examples/sets.rb +36 -0
  25. data/examples/unicorn/config.ru +3 -0
  26. data/examples/unicorn/unicorn.rb +20 -0
  27. data/lib/redis.rb +2731 -0
  28. data/lib/redis/client.rb +575 -0
  29. data/lib/redis/connection.rb +9 -0
  30. data/lib/redis/connection/command_helper.rb +44 -0
  31. data/lib/redis/connection/hiredis.rb +64 -0
  32. data/lib/redis/connection/registry.rb +12 -0
  33. data/lib/redis/connection/ruby.rb +322 -0
  34. data/lib/redis/connection/synchrony.rb +124 -0
  35. data/lib/redis/distributed.rb +873 -0
  36. data/lib/redis/errors.rb +40 -0
  37. data/lib/redis/hash_ring.rb +132 -0
  38. data/lib/redis/pipeline.rb +141 -0
  39. data/lib/redis/subscribe.rb +83 -0
  40. data/lib/redis/version.rb +3 -0
  41. data/redis.gemspec +34 -0
  42. data/test/bitpos_test.rb +69 -0
  43. data/test/blocking_commands_test.rb +42 -0
  44. data/test/command_map_test.rb +30 -0
  45. data/test/commands_on_hashes_test.rb +21 -0
  46. data/test/commands_on_hyper_log_log_test.rb +21 -0
  47. data/test/commands_on_lists_test.rb +20 -0
  48. data/test/commands_on_sets_test.rb +77 -0
  49. data/test/commands_on_sorted_sets_test.rb +137 -0
  50. data/test/commands_on_strings_test.rb +101 -0
  51. data/test/commands_on_value_types_test.rb +133 -0
  52. data/test/connection_handling_test.rb +250 -0
  53. data/test/distributed_blocking_commands_test.rb +46 -0
  54. data/test/distributed_commands_on_hashes_test.rb +10 -0
  55. data/test/distributed_commands_on_hyper_log_log_test.rb +33 -0
  56. data/test/distributed_commands_on_lists_test.rb +22 -0
  57. data/test/distributed_commands_on_sets_test.rb +83 -0
  58. data/test/distributed_commands_on_sorted_sets_test.rb +18 -0
  59. data/test/distributed_commands_on_strings_test.rb +59 -0
  60. data/test/distributed_commands_on_value_types_test.rb +95 -0
  61. data/test/distributed_commands_requiring_clustering_test.rb +164 -0
  62. data/test/distributed_connection_handling_test.rb +23 -0
  63. data/test/distributed_internals_test.rb +79 -0
  64. data/test/distributed_key_tags_test.rb +52 -0
  65. data/test/distributed_persistence_control_commands_test.rb +26 -0
  66. data/test/distributed_publish_subscribe_test.rb +92 -0
  67. data/test/distributed_remote_server_control_commands_test.rb +66 -0
  68. data/test/distributed_scripting_test.rb +102 -0
  69. data/test/distributed_sorting_test.rb +20 -0
  70. data/test/distributed_test.rb +58 -0
  71. data/test/distributed_transactions_test.rb +32 -0
  72. data/test/encoding_test.rb +18 -0
  73. data/test/error_replies_test.rb +59 -0
  74. data/test/fork_safety_test.rb +65 -0
  75. data/test/helper.rb +232 -0
  76. data/test/helper_test.rb +24 -0
  77. data/test/internals_test.rb +437 -0
  78. data/test/lint/blocking_commands.rb +150 -0
  79. data/test/lint/hashes.rb +162 -0
  80. data/test/lint/hyper_log_log.rb +60 -0
  81. data/test/lint/lists.rb +143 -0
  82. data/test/lint/sets.rb +125 -0
  83. data/test/lint/sorted_sets.rb +316 -0
  84. data/test/lint/strings.rb +260 -0
  85. data/test/lint/value_types.rb +122 -0
  86. data/test/persistence_control_commands_test.rb +26 -0
  87. data/test/pipelining_commands_test.rb +242 -0
  88. data/test/publish_subscribe_test.rb +254 -0
  89. data/test/remote_server_control_commands_test.rb +118 -0
  90. data/test/scanning_test.rb +413 -0
  91. data/test/scripting_test.rb +78 -0
  92. data/test/sentinel_command_test.rb +80 -0
  93. data/test/sentinel_test.rb +255 -0
  94. data/test/sorting_test.rb +59 -0
  95. data/test/support/connection/hiredis.rb +1 -0
  96. data/test/support/connection/ruby.rb +1 -0
  97. data/test/support/connection/synchrony.rb +17 -0
  98. data/test/support/redis_mock.rb +119 -0
  99. data/test/support/wire/synchrony.rb +24 -0
  100. data/test/support/wire/thread.rb +5 -0
  101. data/test/synchrony_driver.rb +88 -0
  102. data/test/test.conf.erb +9 -0
  103. data/test/thread_safety_test.rb +32 -0
  104. data/test/transactions_test.rb +264 -0
  105. data/test/unknown_commands_test.rb +14 -0
  106. data/test/url_param_test.rb +138 -0
  107. metadata +182 -0
@@ -0,0 +1,79 @@
1
+ # encoding: UTF-8
2
+
3
+ require File.expand_path("helper", File.dirname(__FILE__))
4
+
5
+ class TestDistributedInternals < Test::Unit::TestCase
6
+
7
+ include Helper::Distributed
8
+
9
+ def test_provides_a_meaningful_inspect
10
+ nodes = ["redis://localhost:#{PORT}/15", *NODES]
11
+ redis = Redis::Distributed.new nodes
12
+
13
+ assert_equal "#<Redis client v#{Redis::VERSION} for #{redis.nodes.map(&:id).join(', ')}>", redis.inspect
14
+ end
15
+
16
+ def test_default_as_urls
17
+ nodes = ["redis://localhost:#{PORT}/15", *NODES]
18
+ redis = Redis::Distributed.new nodes
19
+ assert_equal ["redis://localhost:#{PORT}/15", *NODES], redis.nodes.map { |node| node.client.id}
20
+ end
21
+
22
+ def test_default_as_config_hashes
23
+ nodes = [OPTIONS.merge(:host => '127.0.0.1'), OPTIONS.merge(:host => 'somehost', :port => PORT.next)]
24
+ redis = Redis::Distributed.new nodes
25
+ assert_equal ["redis://127.0.0.1:#{PORT}/15","redis://somehost:#{PORT.next}/15"], redis.nodes.map { |node| node.client.id }
26
+ end
27
+
28
+ def test_as_mix_and_match
29
+ nodes = ["redis://127.0.0.1:7389/15", OPTIONS.merge(:host => 'somehost'), OPTIONS.merge(:host => 'somehost', :port => PORT.next)]
30
+ redis = Redis::Distributed.new nodes
31
+ 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 }
32
+ end
33
+
34
+ def test_override_id
35
+ nodes = [OPTIONS.merge(:host => '127.0.0.1', :id => "test"), OPTIONS.merge( :host => 'somehost', :port => PORT.next, :id => "test1")]
36
+ redis = Redis::Distributed.new nodes
37
+ assert_equal redis.nodes.first.client.id, "test"
38
+ assert_equal redis.nodes.last.client.id, "test1"
39
+ assert_equal "#<Redis client v#{Redis::VERSION} for #{redis.nodes.map(&:id).join(', ')}>", redis.inspect
40
+ end
41
+
42
+ def test_can_be_duped_to_create_a_new_connection
43
+ redis = Redis::Distributed.new(NODES)
44
+
45
+ clients = redis.info[0]["connected_clients"].to_i
46
+
47
+ r2 = redis.dup
48
+ r2.ping
49
+
50
+ assert_equal clients + 1, redis.info[0]["connected_clients"].to_i
51
+ end
52
+
53
+ def test_keeps_options_after_dup
54
+ r1 = Redis::Distributed.new(NODES, :tag => /^(\w+):/)
55
+
56
+ assert_raise(Redis::Distributed::CannotDistribute) do
57
+ r1.sinter("foo", "bar")
58
+ end
59
+
60
+ assert_equal [], r1.sinter("baz:foo", "baz:bar")
61
+
62
+ r2 = r1.dup
63
+
64
+ assert_raise(Redis::Distributed::CannotDistribute) do
65
+ r2.sinter("foo", "bar")
66
+ end
67
+
68
+ assert_equal [], r2.sinter("baz:foo", "baz:bar")
69
+ end
70
+
71
+ def test_colliding_node_ids
72
+ nodes = ["redis://localhost:#{PORT}/15", "redis://localhost:#{PORT}/15", *NODES]
73
+
74
+ assert_raise(RuntimeError) do
75
+ redis = Redis::Distributed.new nodes
76
+ end
77
+ end
78
+
79
+ end
@@ -0,0 +1,52 @@
1
+ # encoding: UTF-8
2
+
3
+ require File.expand_path("helper", File.dirname(__FILE__))
4
+
5
+ class TestDistributedKeyTags < Test::Unit::TestCase
6
+
7
+ include Helper
8
+ include Helper::Distributed
9
+
10
+ def test_hashes_consistently
11
+ r1 = Redis::Distributed.new ["redis://localhost:#{PORT}/15", *NODES]
12
+ r2 = Redis::Distributed.new ["redis://localhost:#{PORT}/15", *NODES]
13
+ r3 = Redis::Distributed.new ["redis://localhost:#{PORT}/15", *NODES]
14
+
15
+ assert_equal r1.node_for("foo").id, r2.node_for("foo").id
16
+ assert_equal r1.node_for("foo").id, r3.node_for("foo").id
17
+ end
18
+
19
+ def test_allows_clustering_of_keys
20
+ r = Redis::Distributed.new(NODES)
21
+ r.add_node("redis://127.0.0.1:#{PORT}/14")
22
+ r.flushdb
23
+
24
+ 100.times do |i|
25
+ r.set "{foo}users:#{i}", i
26
+ end
27
+
28
+ assert_equal [0, 100], r.nodes.map { |node| node.keys.size }
29
+ end
30
+
31
+ def test_distributes_keys_if_no_clustering_is_used
32
+ r.add_node("redis://127.0.0.1:#{PORT}/14")
33
+ r.flushdb
34
+
35
+ r.set "users:1", 1
36
+ r.set "users:4", 4
37
+
38
+ assert_equal [1, 1], r.nodes.map { |node| node.keys.size }
39
+ end
40
+
41
+ def test_allows_passing_a_custom_tag_extractor
42
+ r = Redis::Distributed.new(NODES, :tag => /^(.+?):/)
43
+ r.add_node("redis://127.0.0.1:#{PORT}/14")
44
+ r.flushdb
45
+
46
+ 100.times do |i|
47
+ r.set "foo:users:#{i}", i
48
+ end
49
+
50
+ assert_equal [0, 100], r.nodes.map { |node| node.keys.size }
51
+ end
52
+ end
@@ -0,0 +1,26 @@
1
+ # encoding: UTF-8
2
+
3
+ require File.expand_path("helper", File.dirname(__FILE__))
4
+
5
+ class TestDistributedPersistenceControlCommands < Test::Unit::TestCase
6
+
7
+ include Helper::Distributed
8
+
9
+ def test_save
10
+ redis_mock(:save => lambda { "+SAVE" }) do |redis|
11
+ assert_equal ["SAVE"], redis.save
12
+ end
13
+ end
14
+
15
+ def test_bgsave
16
+ redis_mock(:bgsave => lambda { "+BGSAVE" }) do |redis|
17
+ assert_equal ["BGSAVE"], redis.bgsave
18
+ end
19
+ end
20
+
21
+ def test_lastsave
22
+ redis_mock(:lastsave => lambda { "+LASTSAVE" }) do |redis|
23
+ assert_equal ["LASTSAVE"], redis.lastsave
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,92 @@
1
+ # encoding: UTF-8
2
+
3
+ require File.expand_path("helper", File.dirname(__FILE__))
4
+
5
+ class TestDistributedPublishSubscribe < Test::Unit::TestCase
6
+
7
+ include Helper::Distributed
8
+
9
+ def test_subscribe_and_unsubscribe
10
+ assert_raise Redis::Distributed::CannotDistribute do
11
+ r.subscribe("foo", "bar") { }
12
+ end
13
+
14
+ assert_raise Redis::Distributed::CannotDistribute do
15
+ r.subscribe("{qux}foo", "bar") { }
16
+ end
17
+ end
18
+
19
+ def test_subscribe_and_unsubscribe_with_tags
20
+ @subscribed = false
21
+ @unsubscribed = false
22
+
23
+ wire = Wire.new do
24
+ r.subscribe("foo") do |on|
25
+ on.subscribe do |channel, total|
26
+ @subscribed = true
27
+ @t1 = total
28
+ end
29
+
30
+ on.message do |channel, message|
31
+ if message == "s1"
32
+ r.unsubscribe
33
+ @message = message
34
+ end
35
+ end
36
+
37
+ on.unsubscribe do |channel, total|
38
+ @unsubscribed = true
39
+ @t2 = total
40
+ end
41
+ end
42
+ end
43
+
44
+ # Wait until the subscription is active before publishing
45
+ Wire.pass while !@subscribed
46
+
47
+ Redis::Distributed.new(NODES).publish("foo", "s1")
48
+
49
+ wire.join
50
+
51
+ assert @subscribed
52
+ assert_equal 1, @t1
53
+ assert @unsubscribed
54
+ assert_equal 0, @t2
55
+ assert_equal "s1", @message
56
+ end
57
+
58
+ def test_subscribe_within_subscribe
59
+ @channels = []
60
+
61
+ wire = Wire.new do
62
+ r.subscribe("foo") do |on|
63
+ on.subscribe do |channel, total|
64
+ @channels << channel
65
+
66
+ r.subscribe("bar") if channel == "foo"
67
+ r.unsubscribe if channel == "bar"
68
+ end
69
+ end
70
+ end
71
+
72
+ wire.join
73
+
74
+ assert_equal ["foo", "bar"], @channels
75
+ end
76
+
77
+ def test_other_commands_within_a_subscribe
78
+ assert_raise Redis::CommandError do
79
+ r.subscribe("foo") do |on|
80
+ on.subscribe do |channel, total|
81
+ r.set("bar", "s2")
82
+ end
83
+ end
84
+ end
85
+ end
86
+
87
+ def test_subscribe_without_a_block
88
+ assert_raise LocalJumpError do
89
+ r.subscribe("foo")
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,66 @@
1
+ # encoding: UTF-8
2
+
3
+ require File.expand_path("helper", File.dirname(__FILE__))
4
+
5
+ class TestDistributedRemoteServerControlCommands < Test::Unit::TestCase
6
+
7
+ include Helper::Distributed
8
+
9
+ def test_info
10
+ keys = [
11
+ "redis_version",
12
+ "uptime_in_seconds",
13
+ "uptime_in_days",
14
+ "connected_clients",
15
+ "used_memory",
16
+ "total_connections_received",
17
+ "total_commands_processed",
18
+ ]
19
+
20
+ infos = r.info
21
+
22
+ infos.each do |info|
23
+ keys.each do |k|
24
+ msg = "expected #info to include #{k}"
25
+ assert info.keys.include?(k), msg
26
+ end
27
+ end
28
+ end
29
+
30
+ def test_info_commandstats
31
+ target_version "2.5.7" do
32
+ r.nodes.each { |n| n.config(:resetstat) }
33
+ r.ping # Executed on every node
34
+
35
+ r.info(:commandstats).each do |info|
36
+ assert_equal "1", info["ping"]["calls"]
37
+ end
38
+ end
39
+ end
40
+
41
+ def test_monitor
42
+ begin
43
+ r.monitor
44
+ rescue Exception => ex
45
+ ensure
46
+ assert ex.kind_of?(NotImplementedError)
47
+ end
48
+ end
49
+
50
+ def test_echo
51
+ assert_equal ["foo bar baz\n"], r.echo("foo bar baz\n")
52
+ end
53
+
54
+ def test_time
55
+ target_version "2.5.4" do
56
+ # Test that the difference between the time that Ruby reports and the time
57
+ # that Redis reports is minimal (prevents the test from being racy).
58
+ r.time.each do |rv|
59
+ redis_usec = rv[0] * 1_000_000 + rv[1]
60
+ ruby_usec = Integer(Time.now.to_f * 1_000_000)
61
+
62
+ assert 500_000 > (ruby_usec - redis_usec).abs
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,102 @@
1
+ # encoding: UTF-8
2
+
3
+ require File.expand_path("helper", File.dirname(__FILE__))
4
+
5
+ class TestDistributedScripting < Test::Unit::TestCase
6
+
7
+ include Helper::Distributed
8
+
9
+ def to_sha(script)
10
+ r.script(:load, script).first
11
+ end
12
+
13
+ def test_script_exists
14
+ target_version "2.5.9" do # 2.6-rc1
15
+ a = to_sha("return 1")
16
+ b = a.succ
17
+
18
+ assert_equal [true], r.script(:exists, a)
19
+ assert_equal [false], r.script(:exists, b)
20
+ assert_equal [[true]], r.script(:exists, [a])
21
+ assert_equal [[false]], r.script(:exists, [b])
22
+ assert_equal [[true, false]], r.script(:exists, [a, b])
23
+ end
24
+ end
25
+
26
+ def test_script_flush
27
+ target_version "2.5.9" do # 2.6-rc1
28
+ sha = to_sha("return 1")
29
+ assert r.script(:exists, sha).first
30
+ assert_equal ["OK"], r.script(:flush)
31
+ assert !r.script(:exists, sha).first
32
+ end
33
+ end
34
+
35
+ def test_script_kill
36
+ target_version "2.5.9" do # 2.6-rc1
37
+ redis_mock(:script => lambda { |arg| "+#{arg.upcase}" }) do |redis|
38
+ assert_equal ["KILL"], redis.script(:kill)
39
+ end
40
+ end
41
+ end
42
+
43
+ def test_eval
44
+ target_version "2.5.9" do # 2.6-rc1
45
+ assert_raises(Redis::Distributed::CannotDistribute) do
46
+ r.eval("return #KEYS")
47
+ end
48
+
49
+ assert_raises(Redis::Distributed::CannotDistribute) do
50
+ r.eval("return KEYS", ["k1", "k2"])
51
+ end
52
+
53
+ assert_equal ["k1"], r.eval("return KEYS", ["k1"])
54
+ assert_equal ["a1", "a2"], r.eval("return ARGV", ["k1"], ["a1", "a2"])
55
+ end
56
+ end
57
+
58
+ def test_eval_with_options_hash
59
+ target_version "2.5.9" do # 2.6-rc1
60
+ assert_raises(Redis::Distributed::CannotDistribute) do
61
+ r.eval("return #KEYS", {})
62
+ end
63
+
64
+ assert_raises(Redis::Distributed::CannotDistribute) do
65
+ r.eval("return KEYS", { :keys => ["k1", "k2"] })
66
+ end
67
+
68
+ assert_equal ["k1"], r.eval("return KEYS", { :keys => ["k1"] })
69
+ assert_equal ["a1", "a2"], r.eval("return ARGV", { :keys => ["k1"], :argv => ["a1", "a2"] })
70
+ end
71
+ end
72
+
73
+ def test_evalsha
74
+ target_version "2.5.9" do # 2.6-rc1
75
+ assert_raises(Redis::Distributed::CannotDistribute) do
76
+ r.evalsha(to_sha("return #KEYS"))
77
+ end
78
+
79
+ assert_raises(Redis::Distributed::CannotDistribute) do
80
+ r.evalsha(to_sha("return KEYS"), ["k1", "k2"])
81
+ end
82
+
83
+ assert_equal ["k1"], r.evalsha(to_sha("return KEYS"), ["k1"])
84
+ assert_equal ["a1", "a2"], r.evalsha(to_sha("return ARGV"), ["k1"], ["a1", "a2"])
85
+ end
86
+ end
87
+
88
+ def test_evalsha_with_options_hash
89
+ target_version "2.5.9" do # 2.6-rc1
90
+ assert_raises(Redis::Distributed::CannotDistribute) do
91
+ r.evalsha(to_sha("return #KEYS"), {})
92
+ end
93
+
94
+ assert_raises(Redis::Distributed::CannotDistribute) do
95
+ r.evalsha(to_sha("return KEYS"), { :keys => ["k1", "k2"] })
96
+ end
97
+
98
+ assert_equal ["k1"], r.evalsha(to_sha("return KEYS"), { :keys => ["k1"] })
99
+ assert_equal ["a1", "a2"], r.evalsha(to_sha("return ARGV"), { :keys => ["k1"], :argv => ["a1", "a2"] })
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,20 @@
1
+ # encoding: UTF-8
2
+
3
+ require File.expand_path("helper", File.dirname(__FILE__))
4
+
5
+ class TestDistributedSorting < Test::Unit::TestCase
6
+
7
+ include Helper::Distributed
8
+
9
+ def test_sort
10
+ assert_raise(Redis::Distributed::CannotDistribute) do
11
+ r.set("foo:1", "s1")
12
+ r.set("foo:2", "s2")
13
+
14
+ r.rpush("bar", "1")
15
+ r.rpush("bar", "2")
16
+
17
+ r.sort("bar", :get => "foo:*", :limit => [0, 1])
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,58 @@
1
+ # encoding: UTF-8
2
+
3
+ require File.expand_path("helper", File.dirname(__FILE__))
4
+
5
+ class TestDistributed < Test::Unit::TestCase
6
+
7
+ include Helper::Distributed
8
+
9
+ def test_handle_multiple_servers
10
+ @r = Redis::Distributed.new ["redis://localhost:#{PORT}/15", *NODES]
11
+
12
+ 100.times do |idx|
13
+ @r.set(idx.to_s, "foo#{idx}")
14
+ end
15
+
16
+ 100.times do |idx|
17
+ assert_equal "foo#{idx}", @r.get(idx.to_s)
18
+ end
19
+
20
+ assert_equal "0", @r.keys("*").sort.first
21
+ assert_equal "string", @r.type("1")
22
+ end
23
+
24
+ def test_add_nodes
25
+ logger = Logger.new("/dev/null")
26
+
27
+ @r = Redis::Distributed.new NODES, :logger => logger, :timeout => 10
28
+
29
+ assert_equal "127.0.0.1", @r.nodes[0].client.host
30
+ assert_equal PORT, @r.nodes[0].client.port
31
+ assert_equal 15, @r.nodes[0].client.db
32
+ assert_equal 10, @r.nodes[0].client.timeout
33
+ assert_equal logger, @r.nodes[0].client.logger
34
+
35
+ @r.add_node("redis://127.0.0.1:6380/14")
36
+
37
+ assert_equal "127.0.0.1", @r.nodes[1].client.host
38
+ assert_equal 6380, @r.nodes[1].client.port
39
+ assert_equal 14, @r.nodes[1].client.db
40
+ assert_equal 10, @r.nodes[1].client.timeout
41
+ assert_equal logger, @r.nodes[1].client.logger
42
+ end
43
+
44
+ def test_pipelining_commands_cannot_be_distributed
45
+ assert_raise Redis::Distributed::CannotDistribute do
46
+ r.pipelined do
47
+ r.lpush "foo", "s1"
48
+ r.lpush "foo", "s2"
49
+ end
50
+ end
51
+ end
52
+
53
+ def test_unknown_commands_does_not_work_by_default
54
+ assert_raise NoMethodError do
55
+ r.not_yet_implemented_command
56
+ end
57
+ end
58
+ end