web-console 2.0.0.beta2 → 2.0.0.beta3

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 (119) hide show
  1. checksums.yaml +4 -4
  2. data/MIT-LICENSE +1 -1
  3. data/README.markdown +304 -19
  4. data/app/assets/javascripts/web_console/application.js +1 -0
  5. data/app/assets/javascripts/web_console/console_sessions.js +172 -0
  6. data/app/assets/stylesheets/web_console/application.css +13 -0
  7. data/app/assets/stylesheets/web_console/console_sessions.css.erb +6 -0
  8. data/app/controllers/web_console/application_controller.rb +13 -0
  9. data/app/controllers/web_console/console_sessions_controller.rb +43 -0
  10. data/app/helpers/web_console/application_helper.rb +4 -0
  11. data/app/helpers/web_console/console_session_helper.rb +4 -0
  12. data/app/models/web_console/console_session.rb +96 -0
  13. data/app/views/layouts/web_console/application.html.erb +14 -0
  14. data/app/views/web_console/console_sessions/index.html.erb +15 -0
  15. data/config/routes.rb +11 -0
  16. data/lib/action_dispatch/debug_exceptions.rb +69 -69
  17. data/lib/action_dispatch/exception_wrapper.rb +2 -1
  18. data/lib/assets/javascripts/web-console.js +1 -0
  19. data/lib/assets/javascripts/web_console.js +41 -0
  20. data/lib/web_console.rb +14 -15
  21. data/lib/web_console/colors.rb +87 -0
  22. data/lib/web_console/colors/light.rb +24 -0
  23. data/lib/web_console/colors/monokai.rb +24 -0
  24. data/lib/web_console/colors/solarized.rb +47 -0
  25. data/lib/web_console/colors/tango.rb +24 -0
  26. data/lib/web_console/colors/xterm.rb +24 -0
  27. data/lib/web_console/engine.rb +95 -0
  28. data/lib/web_console/exception_extension.rb +10 -11
  29. data/lib/web_console/repl_session.rb +5 -3
  30. data/lib/web_console/slave.rb +139 -0
  31. data/lib/web_console/version.rb +1 -1
  32. data/lib/web_console/view_helpers.rb +3 -7
  33. data/test/controllers/web_console/console_sessions_controller_test.rb +95 -0
  34. data/test/dummy/app/controllers/exception_test_controller.rb +4 -0
  35. data/test/dummy/app/views/exception_test/xhr.html.erb +1 -0
  36. data/test/dummy/config/application.rb +37 -1
  37. data/test/dummy/config/environments/test.rb +2 -0
  38. data/test/dummy/config/routes.rb +1 -0
  39. data/test/dummy/db/development.sqlite3 +0 -0
  40. data/test/dummy/log/development.log +61814 -0
  41. data/test/dummy/log/test.log +8621 -3
  42. data/test/dummy/tmp/cache/assets/development/sprockets/038461854af2e8bccdb29768efd4768f +0 -0
  43. data/test/dummy/tmp/cache/assets/development/sprockets/0ec396634a5f6808b026257fd107c355 +0 -0
  44. data/test/dummy/tmp/cache/assets/development/sprockets/127a54171eea8d294e4673599861787d +0 -0
  45. data/test/dummy/tmp/cache/assets/development/sprockets/13fe41fee1fe35b49d145bcc06610705 +0 -0
  46. data/test/dummy/tmp/cache/assets/development/sprockets/17c571144b4e44da39bddb2d2c412414 +0 -0
  47. data/test/dummy/tmp/cache/assets/development/sprockets/1cb77d8cf661ccbc9de08f347c89b9f1 +0 -0
  48. data/test/dummy/tmp/cache/assets/development/sprockets/204edd12a29660722d4e0d8de9bd6652 +0 -0
  49. data/test/dummy/tmp/cache/assets/development/sprockets/2b96b037f3dfeccfe27113eb95b06ea1 +0 -0
  50. data/test/dummy/tmp/cache/assets/development/sprockets/2c853768baf811357d81d41bdfd05dcf +0 -0
  51. data/test/dummy/tmp/cache/assets/development/sprockets/2f5173deea6c795b8fdde723bb4b63af +0 -0
  52. data/test/dummy/tmp/cache/assets/development/sprockets/314d48e543146f617c4d3439a4d8d40d +0 -0
  53. data/test/dummy/tmp/cache/assets/development/sprockets/34f21019a876722b8c24a6da4f0ef50b +0 -0
  54. data/test/dummy/tmp/cache/assets/development/sprockets/357970feca3ac29060c1e3861e2c0953 +0 -0
  55. data/test/dummy/tmp/cache/assets/development/sprockets/36341e42f23669574fa1027d0958ff3e +0 -0
  56. data/test/dummy/tmp/cache/assets/development/sprockets/44117154e909436e7eeaf10cdb18d2b4 +0 -0
  57. data/test/dummy/tmp/cache/assets/development/sprockets/496864a905d53afd8e176f29500f96a8 +0 -0
  58. data/test/dummy/tmp/cache/assets/development/sprockets/55b7b76605fdffe31d737d4ac1f1ef7b +0 -0
  59. data/test/dummy/tmp/cache/assets/development/sprockets/5ac98782fe3dfd0a766f75ce1801f0a0 +0 -0
  60. data/test/dummy/tmp/cache/assets/development/sprockets/6088d6f344b38303cc8028057d69e0f9 +0 -0
  61. data/test/dummy/tmp/cache/assets/development/sprockets/676dcf9b2d01b9dc7bd3183d8da88463 +0 -0
  62. data/test/dummy/tmp/cache/assets/development/sprockets/680381170dc160e358fc28076ea6886c +0 -0
  63. data/test/dummy/tmp/cache/assets/development/sprockets/6ad7acc9a22fe2a67ec24a1fc866c20e +0 -0
  64. data/test/dummy/tmp/cache/assets/development/sprockets/6bdb0d0c602e0e1bc304dc697e2cc6de +0 -0
  65. data/test/dummy/tmp/cache/assets/development/sprockets/6dc8d7aa69668fce85683aaad6615432 +0 -0
  66. data/test/dummy/tmp/cache/assets/development/sprockets/6e4d5b32cc444226f6597198994ccd5e +0 -0
  67. data/test/dummy/tmp/cache/assets/development/sprockets/74db0ca5cb8c8c347c9131a3ff516748 +0 -0
  68. data/test/dummy/tmp/cache/assets/development/sprockets/7999e525c88173c1beb785f002effc1d +0 -0
  69. data/test/dummy/tmp/cache/assets/development/sprockets/7a50a9e605754e99783de95715b976b0 +0 -0
  70. data/test/dummy/tmp/cache/assets/development/sprockets/806b0e33a2fe8e1245534345fa27c30a +0 -0
  71. data/test/dummy/tmp/cache/assets/development/sprockets/8aa4c7aabff23c8089d41e9e54193483 +0 -0
  72. data/test/dummy/tmp/cache/assets/development/sprockets/90396626cba6cbec37e32038e6c54e76 +0 -0
  73. data/test/dummy/tmp/cache/assets/development/sprockets/976b28910aa72c90a3b30c6e940f51df +0 -0
  74. data/test/dummy/tmp/cache/assets/development/sprockets/99e1bd7cbc437505bc8f07bc528c721c +0 -0
  75. data/test/dummy/tmp/cache/assets/development/sprockets/aaccf2c9ae2add0863c9a49e0042a097 +0 -0
  76. data/test/dummy/tmp/cache/assets/development/sprockets/ae4677d24a79d9411f2fced5011d5807 +0 -0
  77. data/test/dummy/tmp/cache/assets/development/sprockets/b2401118729720034b6f3eda0b4c5025 +0 -0
  78. data/test/dummy/tmp/cache/assets/development/sprockets/c649837df826fc310cb80f1adafd6b8d +0 -0
  79. data/test/dummy/tmp/cache/assets/development/sprockets/cac185d59612fae451a12df3fc21bb51 +0 -0
  80. data/test/dummy/tmp/cache/assets/development/sprockets/cb0065359d3b5b296f71d673f4b276e9 +0 -0
  81. data/test/dummy/tmp/cache/assets/development/sprockets/cee8c6b09c33d2b276753e959712724e +0 -0
  82. data/test/dummy/tmp/cache/assets/development/sprockets/cffd775d018f68ce5dba1ee0d951a994 +0 -0
  83. data/test/dummy/tmp/cache/assets/development/sprockets/d1f6e06bc2f112c4ec3a4c3f68351878 +0 -0
  84. data/test/dummy/tmp/cache/assets/development/sprockets/d20d83fd7ffa378b1b2b901786d640f3 +0 -0
  85. data/test/dummy/tmp/cache/assets/development/sprockets/d38c7c3aa1e72b55769ccb3607641ef4 +0 -0
  86. data/test/dummy/tmp/cache/assets/development/sprockets/d6b85d8b0b5c569388b89e56e9f6fed7 +0 -0
  87. data/test/dummy/tmp/cache/assets/development/sprockets/d771ace226fc8215a3572e0aa35bb0d6 +0 -0
  88. data/test/dummy/tmp/cache/assets/development/sprockets/d982412def520c434e2240eae6d29cf2 +0 -0
  89. data/test/dummy/tmp/cache/assets/development/sprockets/df048a8b0897b9c04acdf59c8f95b18f +0 -0
  90. data/test/dummy/tmp/cache/assets/development/sprockets/df600f50f002512c95d93bcfbab891ed +0 -0
  91. data/test/dummy/tmp/cache/assets/development/sprockets/e6d6b8bde546349764be7b44ffcf5807 +0 -0
  92. data/test/dummy/tmp/cache/assets/development/sprockets/eb25265794d2f7afd1684779d84efdac +0 -0
  93. data/test/dummy/tmp/cache/assets/development/sprockets/ee8826b12b7d9bfd717df950b58f82ab +0 -0
  94. data/test/dummy/tmp/cache/assets/development/sprockets/ef9824789c6ed3483590e0564a12e1d1 +0 -0
  95. data/test/dummy/tmp/cache/assets/development/sprockets/f7cbd26ba1d28d48de824f0e94586655 +0 -0
  96. data/test/dummy/tmp/cache/assets/development/sprockets/fc7201c6cbef32453aa4175c520c8eae +0 -0
  97. data/test/dummy/tmp/cache/assets/test/sprockets/17c571144b4e44da39bddb2d2c412414 +0 -0
  98. data/test/dummy/tmp/cache/assets/test/sprockets/36341e42f23669574fa1027d0958ff3e +0 -0
  99. data/test/dummy/tmp/cache/assets/test/sprockets/55b7b76605fdffe31d737d4ac1f1ef7b +0 -0
  100. data/test/dummy/tmp/cache/assets/test/sprockets/5ac98782fe3dfd0a766f75ce1801f0a0 +0 -0
  101. data/test/dummy/tmp/cache/assets/test/sprockets/680381170dc160e358fc28076ea6886c +0 -0
  102. data/test/dummy/tmp/cache/assets/test/sprockets/6ad7acc9a22fe2a67ec24a1fc866c20e +0 -0
  103. data/test/dummy/tmp/cache/assets/test/sprockets/6e4d5b32cc444226f6597198994ccd5e +0 -0
  104. data/test/dummy/tmp/cache/assets/test/sprockets/7a50a9e605754e99783de95715b976b0 +0 -0
  105. data/test/dummy/tmp/cache/assets/test/sprockets/8aa4c7aabff23c8089d41e9e54193483 +0 -0
  106. data/test/dummy/tmp/cache/assets/test/sprockets/b2401118729720034b6f3eda0b4c5025 +0 -0
  107. data/test/dummy/tmp/cache/assets/test/sprockets/cb0065359d3b5b296f71d673f4b276e9 +0 -0
  108. data/test/dummy/tmp/cache/assets/test/sprockets/d1f6e06bc2f112c4ec3a4c3f68351878 +0 -0
  109. data/test/dummy/tmp/cache/assets/test/sprockets/d6b85d8b0b5c569388b89e56e9f6fed7 +0 -0
  110. data/test/dummy/tmp/cache/assets/test/sprockets/d982412def520c434e2240eae6d29cf2 +0 -0
  111. data/test/dummy/tmp/cache/assets/test/sprockets/df048a8b0897b9c04acdf59c8f95b18f +0 -0
  112. data/test/dummy/tmp/cache/assets/test/sprockets/e6d6b8bde546349764be7b44ffcf5807 +0 -0
  113. data/test/models/console_session_test.rb +58 -0
  114. data/test/web_console/colors_test.rb +58 -0
  115. data/test/web_console/engine_test.rb +136 -0
  116. data/test/web_console/slave_test.rb +71 -0
  117. data/vendor/assets/javascripts/term.js +5726 -0
  118. metadata +188 -7
  119. data/lib/web_console/railtie.rb +0 -15
@@ -0,0 +1,58 @@
1
+ require 'test_helper'
2
+
3
+ module WebConsole
4
+ class ConsoleSessionTest < ActionView::TestCase
5
+ include ActiveModel::Lint::Tests
6
+
7
+ setup do
8
+ PTY.stubs(:spawn).returns([StringIO.new, StringIO.new, Random.rand(20000)])
9
+ ConsoleSession::INMEMORY_STORAGE.clear
10
+ @model1 = @model = ConsoleSession.new
11
+ @model2 = ConsoleSession.new
12
+ end
13
+
14
+ test 'raises ConsoleSession::Unavailable on not found sessions' do
15
+ assert_raises(ConsoleSession::Unavailable) { ConsoleSession.find(-1) }
16
+ end
17
+
18
+ test 'find coerces ids' do
19
+ assert_equal @model.persist, ConsoleSession.find("#{@model.pid}")
20
+ end
21
+
22
+ test 'not found exceptions are JSON serializable' do
23
+ exception = assert_raises(ConsoleSession::Unavailable) { ConsoleSession.find(-1) }
24
+ assert_equal '{"error":"Session unavailable"}', exception.to_json
25
+ end
26
+
27
+ test 'can be used as slave as the methods are delegated' do
28
+ slave_methods = Slave.instance_methods - @model.methods
29
+ slave_methods.each { |method| assert @model.respond_to?(method) }
30
+ end
31
+
32
+ test 'slave methods are cached on the singleton' do
33
+ assert_not @model.singleton_methods.include?(:pending_output?)
34
+ @model.pending_output? rescue nil
35
+ assert @model.singleton_methods.include?(:pending_output?)
36
+ end
37
+
38
+ test 'persisted models knows that they are in memory' do
39
+ assert_not @model.persisted?
40
+ @model.persist
41
+ assert @model.persisted?
42
+ end
43
+
44
+ test 'persisted models knows about their keys' do
45
+ assert_nil @model.to_key
46
+ @model.persist
47
+ assert_not_nil @model.to_key
48
+ end
49
+
50
+ test 'create gives already persisted models' do
51
+ assert ConsoleSession.create.persisted?
52
+ end
53
+
54
+ test 'no gives not persisted models' do
55
+ assert_not ConsoleSession.new.persisted?
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,58 @@
1
+ require 'test_helper'
2
+
3
+ module WebConsole
4
+ class ColorsTest < ActiveSupport::TestCase
5
+ setup do
6
+ @colors = Colors.new %w( #7f7f7f #ff0000 #00ff00 #ffff00 #5c5cff #ff00ff #00ffff #ffffff )
7
+ end
8
+
9
+ test '.[] is an alias for .themes#[]' do
10
+ @colors.class.themes.expects(:[]).with(:light).once
11
+ @colors.class[:light]
12
+ end
13
+
14
+ test '.register_theme creates Colors instance for the block' do
15
+ @colors.class.register_theme(:test) { |c| assert c.is_a?(Colors) }
16
+ end
17
+
18
+ test '#background is the first color if not specified' do
19
+ assert_equal '#7f7f7f', @colors.background
20
+ end
21
+
22
+ test '#background can be explicitly specified' do
23
+ @colors.background '#00ff00'
24
+ assert_equal '#00ff00', @colors.background
25
+ end
26
+
27
+ test '#background= is an alias of #background' do
28
+ @colors.background = '#00ff00'
29
+ assert_equal '#00ff00', @colors.background
30
+ end
31
+
32
+ test '#foreground is the last color if not specified' do
33
+ assert_equal '#ffffff', @colors.foreground
34
+ end
35
+
36
+ test '#foreground can be explicitly specified' do
37
+ @colors.foreground '#f0f0f0'
38
+ assert_equal '#f0f0f0', @colors.foreground
39
+ end
40
+
41
+ test '#foreground= is an alias of #foreground' do
42
+ @colors.foreground = '#f0f0f0'
43
+ assert_equal '#f0f0f0', @colors.foreground
44
+ end
45
+
46
+ test '#to_json includes the background and the foreground' do
47
+ @colors.background = '#00ff00'
48
+ @colors.foreground = '#f0f0f0'
49
+
50
+ expected_json = '["#7f7f7f","#ff0000","#00ff00","#ffff00","#5c5cff","#ff00ff","#00ffff","#ffffff","#00ff00","#f0f0f0"]'
51
+ assert_equal expected_json, @colors.to_json
52
+ end
53
+
54
+ test '#default is :light' do
55
+ assert_equal @colors.class.default, @colors.class.themes[:light]
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,136 @@
1
+ require 'test_helper'
2
+
3
+ module WebConsole
4
+ class EngineTest < ActiveSupport::TestCase
5
+ test 'custom default_mount_path' do
6
+ new_uninitialized_app do |app|
7
+ app.config.web_console.default_mount_path = '/shell'
8
+ app.initialize!
9
+
10
+ assert app.routes.named_routes['web_console'].path.match('/shell')
11
+ end
12
+ end
13
+
14
+ test 'disabling automounting' do
15
+ new_uninitialized_app do |app|
16
+ app.config.web_console.automount = false
17
+ app.initialize!
18
+
19
+ assert_not app.routes.named_routes['web_console']
20
+ end
21
+ end
22
+
23
+ test 'blank commands are expanded to the rails console' do
24
+ new_uninitialized_app do |app|
25
+ app.config.web_console.command = ' '
26
+ app.initialize!
27
+
28
+ expected_path = Rails.root.join('bin/rails console').to_s
29
+ assert_equal expected_path, app.config.web_console.command
30
+ end
31
+ end
32
+
33
+ test 'present commands are not processed' do
34
+ new_uninitialized_app do |app|
35
+ app.config.web_console.command = '/bin/login'
36
+ app.initialize!
37
+
38
+ assert_equal '/bin/login', app.config.web_console.command
39
+ end
40
+ end
41
+
42
+ test 'whitelisted ips are courced to IPAddr' do
43
+ new_uninitialized_app do |app|
44
+ app.config.web_console.whitelisted_ips = '127.0.0.1'
45
+ app.initialize!
46
+
47
+ assert_equal [ IPAddr.new('127.0.0.1') ], app.config.web_console.whitelisted_ips
48
+ end
49
+ end
50
+
51
+ test 'whitelisted ips are normalized and unique IPAddr' do
52
+ new_uninitialized_app do |app|
53
+ app.config.web_console.whitelisted_ips = [ '127.0.0.1', '127.0.0.1', nil, '', ' ' ]
54
+ app.initialize!
55
+
56
+ assert_equal [ IPAddr.new('127.0.0.1') ], app.config.web_console.whitelisted_ips
57
+ end
58
+ end
59
+
60
+ test 'whitelisted_ips.include? coerces to IPAddr' do
61
+ new_uninitialized_app do |app|
62
+ app.config.web_console.whitelisted_ips = '127.0.0.1'
63
+ app.initialize!
64
+
65
+ assert app.config.web_console.whitelisted_ips.include?('127.0.0.1')
66
+ end
67
+ end
68
+
69
+ test 'whitelisted_ips.include? works with IPAddr' do
70
+ new_uninitialized_app do |app|
71
+ app.config.web_console.whitelisted_ips = '127.0.0.1'
72
+ app.initialize!
73
+
74
+ assert app.config.web_console.whitelisted_ips.include?(IPAddr.new('127.0.0.1'))
75
+ end
76
+ end
77
+
78
+ test 'whitelist whole networks' do
79
+ new_uninitialized_app do |app|
80
+ app.config.web_console.whitelisted_ips = '172.16.0.0/12'
81
+ app.initialize!
82
+
83
+ 1.upto(255).each do |n|
84
+ assert_includes app.config.web_console.whitelisted_ips, "172.16.0.#{n}"
85
+ end
86
+ end
87
+ end
88
+
89
+ test 'whitelist multiple networks' do
90
+ new_uninitialized_app do |app|
91
+ app.config.web_console.whitelisted_ips = %w( 172.16.0.0/12 192.168.0.0/16 )
92
+ app.initialize!
93
+
94
+ 1.upto(255).each do |n|
95
+ assert_includes app.config.web_console.whitelisted_ips, "172.16.0.#{n}"
96
+ assert_includes app.config.web_console.whitelisted_ips, "192.168.0.#{n}"
97
+ end
98
+ end
99
+ end
100
+
101
+ private
102
+
103
+ def new_uninitialized_app(root = File.expand_path('../../dummy', __FILE__))
104
+ skip if Rails::VERSION::MAJOR == 3
105
+
106
+ old_app = Rails.application
107
+
108
+ FileUtils.mkdir_p(root)
109
+ Dir.chdir(root) do
110
+ Rails.application = nil
111
+
112
+ app = Class.new(Rails::Application)
113
+ app.config.eager_load = false
114
+ app.config.time_zone = 'UTC'
115
+ app.config.middleware ||= Rails::Configuration::MiddlewareStackProxy.new
116
+ app.config.active_support.deprecation = :notify
117
+
118
+ yield app
119
+ end
120
+ ensure
121
+ Rails.application = old_app
122
+ end
123
+
124
+ def teardown_fixtures(*)
125
+ super
126
+ rescue
127
+ # This is nasty hack to prevent a connection to the database in JRuby's
128
+ # activerecord-jdbcsqlite3-adapter. We don't really require a database
129
+ # connection, for the tests to run.
130
+ #
131
+ # The sad thing is that I couldn't figure out why does it only happens
132
+ # on activerecord-jdbcsqlite3-adapter and how to actually prevent it,
133
+ # rather than work-around it.
134
+ end
135
+ end
136
+ end
@@ -0,0 +1,71 @@
1
+ require 'stringio'
2
+ require 'test_helper'
3
+
4
+ module WebConsole
5
+ class SlaveTest < ActiveSupport::TestCase
6
+ setup do
7
+ PTY.stubs(:spawn).returns([StringIO.new, StringIO.new, Random.rand(20000)])
8
+ @slave = Slave.new
9
+ end
10
+
11
+ test '#send_input raises ArgumentError on bad input' do
12
+ assert_raises(ArgumentError) { @slave.send_input(nil) }
13
+ assert_raises(ArgumentError) { @slave.send_input('') }
14
+ end
15
+
16
+ test '#pending_output returns nil on no pending output' do
17
+ @slave.stubs(:pending_output?).returns(false)
18
+ assert_nil @slave.pending_output
19
+ end
20
+
21
+ test '#pending_output returns a string with the current output' do
22
+ @slave.stubs(:pending_output?).returns(true)
23
+ @slave.instance_variable_get(:@output).stubs(:read_nonblock).returns('foo', nil)
24
+ assert_equal 'foo', @slave.pending_output
25
+ end
26
+
27
+ test '#pending_output always encodes output in UTF-8' do
28
+ @slave.stubs(:pending_output?).returns(true)
29
+ @slave.instance_variable_get(:@output).stubs(:read_nonblock).returns('foo', nil)
30
+ assert_equal Encoding::UTF_8, @slave.pending_output.encoding
31
+ end
32
+
33
+ Slave::READING_ON_CLOSED_END_ERRORS.each do |exception|
34
+ test "#pending_output raises Slave::Closed when the end raises #{exception}" do
35
+ @slave.stubs(:pending_output?).returns(true)
36
+ @slave.instance_variable_get(:@output).stubs(:read_nonblock).raises(exception)
37
+
38
+ assert_raises(Slave::Closed) { @slave.pending_output }
39
+ end
40
+ end
41
+
42
+ test '#configure changes @input dimentions' do
43
+ @slave.instance_variable_get(:@input).expects(:winsize=).with([32, 64])
44
+ @slave.configure(height: 32, width: 64)
45
+ end
46
+
47
+ test '#configure only changes the @input dimentions if width is zero' do
48
+ @slave.instance_variable_get(:@input).expects(:winsize=).never
49
+ @slave.configure(height: 32, width: 0)
50
+ end
51
+
52
+ test '#configure only changes the @input dimentions if height is zero' do
53
+ @slave.instance_variable_get(:@input).expects(:winsize=).never
54
+ @slave.configure(height: 0, width: 64)
55
+ end
56
+
57
+ { dispose: :SIGTERM, dispose!: :SIGKILL }.each do |method, signal|
58
+ test "##{method} sends #{signal} to the process and detaches it" do
59
+ Process.expects(:kill).with(signal, @slave.pid)
60
+ @slave.send(method)
61
+ end
62
+
63
+ test "##{method} can reraise Errno::ESRCH if requested" do
64
+ Process.expects(:kill).with(signal, @slave.pid)
65
+ Process.stubs(:detach).raises(Errno::ESRCH)
66
+
67
+ assert_raises(Errno::ESRCH) { @slave.send(method, raise: true) }
68
+ end
69
+ end
70
+ end
71
+ end