ddollar-net-ssh 2.0.1
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.
- data/CHANGELOG.rdoc +42 -0
- data/Manifest +101 -0
- data/README.rdoc +110 -0
- data/Rakefile +26 -0
- data/THANKS.rdoc +16 -0
- data/lib/net/ssh.rb +199 -0
- data/lib/net/ssh/authentication/agent.rb +175 -0
- data/lib/net/ssh/authentication/constants.rb +18 -0
- data/lib/net/ssh/authentication/key_manager.rb +169 -0
- data/lib/net/ssh/authentication/methods/abstract.rb +60 -0
- data/lib/net/ssh/authentication/methods/hostbased.rb +71 -0
- data/lib/net/ssh/authentication/methods/keyboard_interactive.rb +66 -0
- data/lib/net/ssh/authentication/methods/password.rb +39 -0
- data/lib/net/ssh/authentication/methods/publickey.rb +92 -0
- data/lib/net/ssh/authentication/pageant.rb +176 -0
- data/lib/net/ssh/authentication/session.rb +127 -0
- data/lib/net/ssh/buffer.rb +339 -0
- data/lib/net/ssh/buffered_io.rb +149 -0
- data/lib/net/ssh/config.rb +173 -0
- data/lib/net/ssh/connection/channel.rb +625 -0
- data/lib/net/ssh/connection/constants.rb +33 -0
- data/lib/net/ssh/connection/session.rb +569 -0
- data/lib/net/ssh/connection/term.rb +178 -0
- data/lib/net/ssh/errors.rb +85 -0
- data/lib/net/ssh/key_factory.rb +85 -0
- data/lib/net/ssh/known_hosts.rb +129 -0
- data/lib/net/ssh/loggable.rb +61 -0
- data/lib/net/ssh/packet.rb +102 -0
- data/lib/net/ssh/prompt.rb +93 -0
- data/lib/net/ssh/proxy/errors.rb +14 -0
- data/lib/net/ssh/proxy/http.rb +94 -0
- data/lib/net/ssh/proxy/socks4.rb +70 -0
- data/lib/net/ssh/proxy/socks5.rb +128 -0
- data/lib/net/ssh/service/forward.rb +267 -0
- data/lib/net/ssh/test.rb +89 -0
- data/lib/net/ssh/test/channel.rb +129 -0
- data/lib/net/ssh/test/extensions.rb +152 -0
- data/lib/net/ssh/test/kex.rb +44 -0
- data/lib/net/ssh/test/local_packet.rb +51 -0
- data/lib/net/ssh/test/packet.rb +81 -0
- data/lib/net/ssh/test/remote_packet.rb +38 -0
- data/lib/net/ssh/test/script.rb +157 -0
- data/lib/net/ssh/test/socket.rb +59 -0
- data/lib/net/ssh/transport/algorithms.rb +384 -0
- data/lib/net/ssh/transport/cipher_factory.rb +72 -0
- data/lib/net/ssh/transport/constants.rb +30 -0
- data/lib/net/ssh/transport/hmac.rb +31 -0
- data/lib/net/ssh/transport/hmac/abstract.rb +48 -0
- data/lib/net/ssh/transport/hmac/md5.rb +12 -0
- data/lib/net/ssh/transport/hmac/md5_96.rb +11 -0
- data/lib/net/ssh/transport/hmac/none.rb +15 -0
- data/lib/net/ssh/transport/hmac/sha1.rb +13 -0
- data/lib/net/ssh/transport/hmac/sha1_96.rb +11 -0
- data/lib/net/ssh/transport/identity_cipher.rb +40 -0
- data/lib/net/ssh/transport/kex.rb +13 -0
- data/lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb +208 -0
- data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb +77 -0
- data/lib/net/ssh/transport/openssl.rb +128 -0
- data/lib/net/ssh/transport/packet_stream.rb +230 -0
- data/lib/net/ssh/transport/server_version.rb +61 -0
- data/lib/net/ssh/transport/session.rb +262 -0
- data/lib/net/ssh/transport/state.rb +170 -0
- data/lib/net/ssh/verifiers/lenient.rb +30 -0
- data/lib/net/ssh/verifiers/null.rb +12 -0
- data/lib/net/ssh/verifiers/strict.rb +53 -0
- data/lib/net/ssh/version.rb +60 -0
- data/net-ssh.gemspec +56 -0
- data/setup.rb +1585 -0
- data/test/authentication/methods/common.rb +28 -0
- data/test/authentication/methods/test_abstract.rb +51 -0
- data/test/authentication/methods/test_hostbased.rb +108 -0
- data/test/authentication/methods/test_keyboard_interactive.rb +98 -0
- data/test/authentication/methods/test_password.rb +50 -0
- data/test/authentication/methods/test_publickey.rb +123 -0
- data/test/authentication/test_agent.rb +205 -0
- data/test/authentication/test_key_manager.rb +100 -0
- data/test/authentication/test_session.rb +93 -0
- data/test/common.rb +106 -0
- data/test/configs/exact_match +8 -0
- data/test/configs/wild_cards +14 -0
- data/test/connection/test_channel.rb +452 -0
- data/test/connection/test_session.rb +483 -0
- data/test/test_all.rb +6 -0
- data/test/test_buffer.rb +336 -0
- data/test/test_buffered_io.rb +63 -0
- data/test/test_config.rb +78 -0
- data/test/test_key_factory.rb +67 -0
- data/test/transport/hmac/test_md5.rb +34 -0
- data/test/transport/hmac/test_md5_96.rb +25 -0
- data/test/transport/hmac/test_none.rb +34 -0
- data/test/transport/hmac/test_sha1.rb +34 -0
- data/test/transport/hmac/test_sha1_96.rb +25 -0
- data/test/transport/kex/test_diffie_hellman_group1_sha1.rb +146 -0
- data/test/transport/kex/test_diffie_hellman_group_exchange_sha1.rb +92 -0
- data/test/transport/test_algorithms.rb +302 -0
- data/test/transport/test_cipher_factory.rb +163 -0
- data/test/transport/test_hmac.rb +34 -0
- data/test/transport/test_identity_cipher.rb +40 -0
- data/test/transport/test_packet_stream.rb +433 -0
- data/test/transport/test_server_version.rb +55 -0
- data/test/transport/test_session.rb +312 -0
- data/test/transport/test_state.rb +173 -0
- metadata +222 -0
@@ -0,0 +1,452 @@
|
|
1
|
+
require 'common'
|
2
|
+
require 'net/ssh/connection/channel'
|
3
|
+
|
4
|
+
module Connection
|
5
|
+
|
6
|
+
class TestChannel < Test::Unit::TestCase
|
7
|
+
include Net::SSH::Connection::Constants
|
8
|
+
|
9
|
+
def teardown
|
10
|
+
connection.test!
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_constructor_should_set_defaults
|
14
|
+
assert_equal 0x10000, channel.local_maximum_packet_size
|
15
|
+
assert_equal 0x20000, channel.local_maximum_window_size
|
16
|
+
assert channel.pending_requests.empty?
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_channel_properties
|
20
|
+
channel[:hello] = "some value"
|
21
|
+
assert_equal "some value", channel[:hello]
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_exec_should_be_syntactic_sugar_for_a_channel_request
|
25
|
+
channel.expects(:send_channel_request).with("exec", :string, "ls").yields
|
26
|
+
found_block = false
|
27
|
+
channel.exec("ls") { found_block = true }
|
28
|
+
assert found_block, "expected block to be passed to send_channel_request"
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_subsystem_should_be_syntactic_sugar_for_a_channel_request
|
32
|
+
channel.expects(:send_channel_request).with("subsystem", :string, "sftp").yields
|
33
|
+
found_block = false
|
34
|
+
channel.subsystem("sftp") { found_block = true }
|
35
|
+
assert found_block, "expected block to be passed to send_channel_request"
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_request_pty_with_invalid_option_should_raise_error
|
39
|
+
assert_raises(ArgumentError) do
|
40
|
+
channel.request_pty(:bogus => "thing")
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_request_pty_without_options_should_use_defaults
|
45
|
+
channel.expects(:send_channel_request).with("pty-req", :string, "xterm",
|
46
|
+
:long, 80, :long, 24, :long, 640, :long, 480, :string, "\0").yields
|
47
|
+
found_block = false
|
48
|
+
channel.request_pty { found_block = true }
|
49
|
+
assert found_block, "expected block to be passed to send_channel_request"
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_request_pty_with_options_should_honor_options
|
53
|
+
channel.expects(:send_channel_request).with("pty-req", :string, "vanilla",
|
54
|
+
:long, 60, :long, 15, :long, 400, :long, 200, :string, "\5\0\0\0\1\0")
|
55
|
+
channel.request_pty :term => "vanilla", :chars_wide => 60, :chars_high => 15,
|
56
|
+
:pixels_wide => 400, :pixels_high => 200, :modes => { 5 => 1 }
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_send_data_should_append_to_channels_output_buffer
|
60
|
+
channel.send_data("hello")
|
61
|
+
assert_equal "hello", channel.output.to_s
|
62
|
+
channel.send_data("world")
|
63
|
+
assert_equal "helloworld", channel.output.to_s
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_close_before_channel_has_been_confirmed_should_do_nothing
|
67
|
+
assert !channel.closing?
|
68
|
+
channel.close
|
69
|
+
assert !channel.closing?
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_close_should_set_closing_and_send_message
|
73
|
+
channel.do_open_confirmation(0, 100, 100)
|
74
|
+
assert !channel.closing?
|
75
|
+
|
76
|
+
connection.expect { |t,packet| assert_equal CHANNEL_CLOSE, packet.type }
|
77
|
+
channel.close
|
78
|
+
|
79
|
+
assert channel.closing?
|
80
|
+
end
|
81
|
+
|
82
|
+
def test_close_while_closing_should_do_nothing
|
83
|
+
test_close_should_set_closing_and_send_message
|
84
|
+
assert_nothing_raised { channel.close }
|
85
|
+
end
|
86
|
+
|
87
|
+
def test_process_when_process_callback_is_not_set_should_just_enqueue_data
|
88
|
+
channel.expects(:enqueue_pending_output)
|
89
|
+
channel.process
|
90
|
+
end
|
91
|
+
|
92
|
+
def test_process_when_process_callback_is_set_should_yield_self_before_enqueuing_data
|
93
|
+
channel.expects(:enqueue_pending_output).never
|
94
|
+
channel.on_process { |ch| ch.expects(:enqueue_pending_output).once }
|
95
|
+
channel.process
|
96
|
+
end
|
97
|
+
|
98
|
+
def test_enqueue_pending_output_should_have_no_effect_if_channel_has_not_been_confirmed
|
99
|
+
channel.send_data("hello")
|
100
|
+
assert_nothing_raised { channel.enqueue_pending_output }
|
101
|
+
end
|
102
|
+
|
103
|
+
def test_enqueue_pending_output_should_have_no_effect_if_there_is_no_output
|
104
|
+
channel.do_open_confirmation(0, 100, 100)
|
105
|
+
assert_nothing_raised { channel.enqueue_pending_output }
|
106
|
+
end
|
107
|
+
|
108
|
+
def test_enqueue_pending_output_should_not_enqueue_more_than_output_length
|
109
|
+
channel.do_open_confirmation(0, 100, 100)
|
110
|
+
channel.send_data("hello world")
|
111
|
+
|
112
|
+
connection.expect do |t,packet|
|
113
|
+
assert_equal CHANNEL_DATA, packet.type
|
114
|
+
assert_equal 0, packet[:local_id]
|
115
|
+
assert_equal 11, packet[:data].length
|
116
|
+
end
|
117
|
+
|
118
|
+
channel.enqueue_pending_output
|
119
|
+
end
|
120
|
+
|
121
|
+
def test_enqueue_pending_output_should_not_enqueue_more_than_max_packet_length_at_once
|
122
|
+
channel.do_open_confirmation(0, 100, 8)
|
123
|
+
channel.send_data("hello world")
|
124
|
+
|
125
|
+
connection.expect do |t,packet|
|
126
|
+
assert_equal CHANNEL_DATA, packet.type
|
127
|
+
assert_equal 0, packet[:local_id]
|
128
|
+
assert_equal "hello wo", packet[:data]
|
129
|
+
|
130
|
+
t.expect do |t,packet|
|
131
|
+
assert_equal CHANNEL_DATA, packet.type
|
132
|
+
assert_equal 0, packet[:local_id]
|
133
|
+
assert_equal "rld", packet[:data]
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
channel.enqueue_pending_output
|
138
|
+
end
|
139
|
+
|
140
|
+
def test_enqueue_pending_output_should_not_enqueue_more_than_max_window_size
|
141
|
+
channel.do_open_confirmation(0, 8, 100)
|
142
|
+
channel.send_data("hello world")
|
143
|
+
|
144
|
+
connection.expect do |t,packet|
|
145
|
+
assert_equal CHANNEL_DATA, packet.type
|
146
|
+
assert_equal 0, packet[:local_id]
|
147
|
+
assert_equal "hello wo", packet[:data]
|
148
|
+
end
|
149
|
+
|
150
|
+
channel.enqueue_pending_output
|
151
|
+
end
|
152
|
+
|
153
|
+
def test_on_data_with_block_should_set_callback
|
154
|
+
flag = false
|
155
|
+
channel.on_data { flag = !flag }
|
156
|
+
channel.do_data("")
|
157
|
+
assert(flag, "callback should have been invoked")
|
158
|
+
channel.on_data
|
159
|
+
channel.do_data("")
|
160
|
+
assert(flag, "callback should have been removed")
|
161
|
+
end
|
162
|
+
|
163
|
+
def test_on_extended_data_with_block_should_set_callback
|
164
|
+
flag = false
|
165
|
+
channel.on_extended_data { flag = !flag }
|
166
|
+
channel.do_extended_data(0, "")
|
167
|
+
assert(flag, "callback should have been invoked")
|
168
|
+
channel.on_extended_data
|
169
|
+
channel.do_extended_data(0, "")
|
170
|
+
assert(flag, "callback should have been removed")
|
171
|
+
end
|
172
|
+
|
173
|
+
def test_on_process_with_block_should_set_callback
|
174
|
+
flag = false
|
175
|
+
channel.on_process { flag = !flag }
|
176
|
+
channel.process
|
177
|
+
assert(flag, "callback should have been invoked")
|
178
|
+
channel.on_process
|
179
|
+
channel.process
|
180
|
+
assert(flag, "callback should have been removed")
|
181
|
+
end
|
182
|
+
|
183
|
+
def test_on_close_with_block_should_set_callback
|
184
|
+
flag = false
|
185
|
+
channel.on_close { flag = !flag }
|
186
|
+
channel.do_close
|
187
|
+
assert(flag, "callback should have been invoked")
|
188
|
+
channel.on_close
|
189
|
+
channel.do_close
|
190
|
+
assert(flag, "callback should have been removed")
|
191
|
+
end
|
192
|
+
|
193
|
+
def test_on_eof_with_block_should_set_callback
|
194
|
+
flag = false
|
195
|
+
channel.on_eof { flag = !flag }
|
196
|
+
channel.do_eof
|
197
|
+
assert(flag, "callback should have been invoked")
|
198
|
+
channel.on_eof
|
199
|
+
channel.do_eof
|
200
|
+
assert(flag, "callback should have been removed")
|
201
|
+
end
|
202
|
+
|
203
|
+
def test_do_request_for_unhandled_request_should_do_nothing_if_not_wants_reply
|
204
|
+
channel.do_open_confirmation(0, 100, 100)
|
205
|
+
assert_nothing_raised { channel.do_request "exit-status", false, nil }
|
206
|
+
end
|
207
|
+
|
208
|
+
def test_do_request_for_unhandled_request_should_send_CHANNEL_FAILURE_if_wants_reply
|
209
|
+
channel.do_open_confirmation(0, 100, 100)
|
210
|
+
connection.expect { |t,packet| assert_equal CHANNEL_FAILURE, packet.type }
|
211
|
+
channel.do_request "keepalive@openssh.com", true, nil
|
212
|
+
end
|
213
|
+
|
214
|
+
def test_do_request_for_handled_request_should_invoke_callback_and_do_nothing_if_returns_true_and_not_wants_reply
|
215
|
+
channel.do_open_confirmation(0, 100, 100)
|
216
|
+
flag = false
|
217
|
+
channel.on_request("exit-status") { flag = true; true }
|
218
|
+
assert_nothing_raised { channel.do_request "exit-status", false, nil }
|
219
|
+
assert flag, "callback should have been invoked"
|
220
|
+
end
|
221
|
+
|
222
|
+
def test_do_request_for_handled_request_should_invoke_callback_and_do_nothing_if_fails_and_not_wants_reply
|
223
|
+
channel.do_open_confirmation(0, 100, 100)
|
224
|
+
flag = false
|
225
|
+
channel.on_request("exit-status") { flag = true; raise Net::SSH::ChannelRequestFailed }
|
226
|
+
assert_nothing_raised { channel.do_request "exit-status", false, nil }
|
227
|
+
assert flag, "callback should have been invoked"
|
228
|
+
end
|
229
|
+
|
230
|
+
def test_do_request_for_handled_request_should_invoke_callback_and_send_CHANNEL_SUCCESS_if_returns_true_and_wants_reply
|
231
|
+
channel.do_open_confirmation(0, 100, 100)
|
232
|
+
flag = false
|
233
|
+
channel.on_request("exit-status") { flag = true; true }
|
234
|
+
connection.expect { |t,p| assert_equal CHANNEL_SUCCESS, p.type }
|
235
|
+
assert_nothing_raised { channel.do_request "exit-status", true, nil }
|
236
|
+
assert flag, "callback should have been invoked"
|
237
|
+
end
|
238
|
+
|
239
|
+
def test_do_request_for_handled_request_should_invoke_callback_and_send_CHANNEL_FAILURE_if_returns_false_and_wants_reply
|
240
|
+
channel.do_open_confirmation(0, 100, 100)
|
241
|
+
flag = false
|
242
|
+
channel.on_request("exit-status") { flag = true; raise Net::SSH::ChannelRequestFailed }
|
243
|
+
connection.expect { |t,p| assert_equal CHANNEL_FAILURE, p.type }
|
244
|
+
assert_nothing_raised { channel.do_request "exit-status", true, nil }
|
245
|
+
assert flag, "callback should have been invoked"
|
246
|
+
end
|
247
|
+
|
248
|
+
def test_send_channel_request_without_callback_should_not_want_reply
|
249
|
+
channel.do_open_confirmation(0, 100, 100)
|
250
|
+
connection.expect do |t,p|
|
251
|
+
assert_equal CHANNEL_REQUEST, p.type
|
252
|
+
assert_equal 0, p[:local_id]
|
253
|
+
assert_equal "exec", p[:request]
|
254
|
+
assert_equal false, p[:want_reply]
|
255
|
+
assert_equal "ls", p[:request_data].read_string
|
256
|
+
end
|
257
|
+
channel.send_channel_request("exec", :string, "ls")
|
258
|
+
assert channel.pending_requests.empty?
|
259
|
+
end
|
260
|
+
|
261
|
+
def test_send_channel_request_with_callback_should_want_reply
|
262
|
+
channel.do_open_confirmation(0, 100, 100)
|
263
|
+
connection.expect do |t,p|
|
264
|
+
assert_equal CHANNEL_REQUEST, p.type
|
265
|
+
assert_equal 0, p[:local_id]
|
266
|
+
assert_equal "exec", p[:request]
|
267
|
+
assert_equal true, p[:want_reply]
|
268
|
+
assert_equal "ls", p[:request_data].read_string
|
269
|
+
end
|
270
|
+
callback = Proc.new {}
|
271
|
+
channel.send_channel_request("exec", :string, "ls", &callback)
|
272
|
+
assert_equal [callback], channel.pending_requests
|
273
|
+
end
|
274
|
+
|
275
|
+
def test_do_open_confirmation_should_set_remote_parameters
|
276
|
+
channel.do_open_confirmation(1, 2, 3)
|
277
|
+
assert_equal 1, channel.remote_id
|
278
|
+
assert_equal 2, channel.remote_window_size
|
279
|
+
assert_equal 2, channel.remote_maximum_window_size
|
280
|
+
assert_equal 3, channel.remote_maximum_packet_size
|
281
|
+
end
|
282
|
+
|
283
|
+
def test_do_open_confirmation_should_call_open_confirmation_callback
|
284
|
+
flag = false
|
285
|
+
channel { flag = true }
|
286
|
+
assert !flag, "callback should not have been invoked yet"
|
287
|
+
channel.do_open_confirmation(1,2,3)
|
288
|
+
assert flag, "callback should have been invoked"
|
289
|
+
end
|
290
|
+
|
291
|
+
def test_do_open_confirmation_with_session_channel_should_invoke_agent_forwarding_if_agent_forwarding_requested
|
292
|
+
connection :forward_agent => true
|
293
|
+
forward = mock("forward")
|
294
|
+
forward.expects(:agent).with(channel)
|
295
|
+
connection.expects(:forward).returns(forward)
|
296
|
+
channel.do_open_confirmation(1,2,3)
|
297
|
+
end
|
298
|
+
|
299
|
+
def test_do_open_confirmation_with_non_session_channel_should_not_invoke_agent_forwarding_even_if_agent_forwarding_requested
|
300
|
+
connection :forward_agent => true
|
301
|
+
channel :type => "direct-tcpip"
|
302
|
+
connection.expects(:forward).never
|
303
|
+
channel.do_open_confirmation(1,2,3)
|
304
|
+
end
|
305
|
+
|
306
|
+
def test_do_window_adjust_should_adjust_remote_window_size_by_the_given_amount
|
307
|
+
channel.do_open_confirmation(0, 1000, 1000)
|
308
|
+
assert_equal 1000, channel.remote_window_size
|
309
|
+
assert_equal 1000, channel.remote_maximum_window_size
|
310
|
+
channel.do_window_adjust(500)
|
311
|
+
assert_equal 1500, channel.remote_window_size
|
312
|
+
assert_equal 1500, channel.remote_maximum_window_size
|
313
|
+
end
|
314
|
+
|
315
|
+
def test_do_data_should_update_local_window_size
|
316
|
+
assert_equal 0x20000, channel.local_maximum_window_size
|
317
|
+
assert_equal 0x20000, channel.local_window_size
|
318
|
+
channel.do_data("here is some data")
|
319
|
+
assert_equal 0x20000, channel.local_maximum_window_size
|
320
|
+
assert_equal 0x1FFEF, channel.local_window_size
|
321
|
+
end
|
322
|
+
|
323
|
+
def test_do_extended_data_should_update_local_window_size
|
324
|
+
assert_equal 0x20000, channel.local_maximum_window_size
|
325
|
+
assert_equal 0x20000, channel.local_window_size
|
326
|
+
channel.do_extended_data(1, "here is some data")
|
327
|
+
assert_equal 0x20000, channel.local_maximum_window_size
|
328
|
+
assert_equal 0x1FFEF, channel.local_window_size
|
329
|
+
end
|
330
|
+
|
331
|
+
def test_do_data_when_local_window_size_drops_below_threshold_should_trigger_WINDOW_ADJUST_message
|
332
|
+
channel.do_open_confirmation(0, 1000, 1000)
|
333
|
+
assert_equal 0x20000, channel.local_maximum_window_size
|
334
|
+
assert_equal 0x20000, channel.local_window_size
|
335
|
+
|
336
|
+
connection.expect do |t,p|
|
337
|
+
assert_equal CHANNEL_WINDOW_ADJUST, p.type
|
338
|
+
assert_equal 0, p[:local_id]
|
339
|
+
assert_equal 0x20000, p[:extra_bytes]
|
340
|
+
end
|
341
|
+
|
342
|
+
channel.do_data("." * 0x10001)
|
343
|
+
assert_equal 0x40000, channel.local_maximum_window_size
|
344
|
+
assert_equal 0x2FFFF, channel.local_window_size
|
345
|
+
end
|
346
|
+
|
347
|
+
def test_do_failure_should_grab_next_pending_request_and_call_it
|
348
|
+
result = nil
|
349
|
+
channel.pending_requests << Proc.new { |*args| result = args }
|
350
|
+
channel.do_failure
|
351
|
+
assert_equal [channel, false], result
|
352
|
+
assert channel.pending_requests.empty?
|
353
|
+
end
|
354
|
+
|
355
|
+
def test_do_success_should_grab_next_pending_request_and_call_it
|
356
|
+
result = nil
|
357
|
+
channel.pending_requests << Proc.new { |*args| result = args }
|
358
|
+
channel.do_success
|
359
|
+
assert_equal [channel, true], result
|
360
|
+
assert channel.pending_requests.empty?
|
361
|
+
end
|
362
|
+
|
363
|
+
def test_active_should_be_true_when_channel_appears_in_channel_list
|
364
|
+
connection.channels[channel.local_id] = channel
|
365
|
+
assert channel.active?
|
366
|
+
end
|
367
|
+
|
368
|
+
def test_active_should_be_false_when_channel_is_not_in_channel_list
|
369
|
+
assert !channel.active?
|
370
|
+
end
|
371
|
+
|
372
|
+
def test_wait_should_block_while_channel_is_active?
|
373
|
+
channel.expects(:active?).times(3).returns(true,true,false)
|
374
|
+
channel.wait
|
375
|
+
end
|
376
|
+
|
377
|
+
def test_eof_bang_should_send_eof_to_server
|
378
|
+
channel.do_open_confirmation(0, 1000, 1000)
|
379
|
+
connection.expect { |t,p| assert_equal CHANNEL_EOF, p.type }
|
380
|
+
channel.eof!
|
381
|
+
end
|
382
|
+
|
383
|
+
def test_eof_bang_should_not_send_eof_if_eof_was_already_declared
|
384
|
+
channel.do_open_confirmation(0, 1000, 1000)
|
385
|
+
connection.expect { |t,p| assert_equal CHANNEL_EOF, p.type }
|
386
|
+
channel.eof!
|
387
|
+
assert_nothing_raised { channel.eof! }
|
388
|
+
end
|
389
|
+
|
390
|
+
def test_eof_q_should_return_true_if_eof_declared
|
391
|
+
channel.do_open_confirmation(0, 1000, 1000)
|
392
|
+
connection.expect { |t,p| assert_equal CHANNEL_EOF, p.type }
|
393
|
+
|
394
|
+
assert !channel.eof?
|
395
|
+
channel.eof!
|
396
|
+
assert channel.eof?
|
397
|
+
end
|
398
|
+
|
399
|
+
def test_send_data_should_raise_exception_if_eof_declared
|
400
|
+
channel.do_open_confirmation(0, 1000, 1000)
|
401
|
+
connection.expect { |t,p| assert_equal CHANNEL_EOF, p.type }
|
402
|
+
channel.eof!
|
403
|
+
assert_raises(EOFError) { channel.send_data("die! die! die!") }
|
404
|
+
end
|
405
|
+
|
406
|
+
private
|
407
|
+
|
408
|
+
class MockConnection
|
409
|
+
attr_reader :logger
|
410
|
+
attr_reader :options
|
411
|
+
attr_reader :channels
|
412
|
+
|
413
|
+
def initialize(options={})
|
414
|
+
@expectation = nil
|
415
|
+
@options = options
|
416
|
+
@channels = {}
|
417
|
+
end
|
418
|
+
|
419
|
+
def expect(&block)
|
420
|
+
@expectation = block
|
421
|
+
end
|
422
|
+
|
423
|
+
def send_message(msg)
|
424
|
+
raise "#{msg.to_s.inspect} recieved but no message was expected" unless @expectation
|
425
|
+
packet = Net::SSH::Packet.new(msg.to_s)
|
426
|
+
callback, @expectation = @expectation, nil
|
427
|
+
callback.call(self, packet)
|
428
|
+
end
|
429
|
+
|
430
|
+
alias loop_forever loop
|
431
|
+
def loop(&block)
|
432
|
+
loop_forever { break unless block.call }
|
433
|
+
end
|
434
|
+
|
435
|
+
def test!
|
436
|
+
raise "expected a packet but none were sent" if @expectation
|
437
|
+
end
|
438
|
+
end
|
439
|
+
|
440
|
+
def connection(options={})
|
441
|
+
@connection ||= MockConnection.new(options)
|
442
|
+
end
|
443
|
+
|
444
|
+
def channel(options={}, &block)
|
445
|
+
@channel ||= Net::SSH::Connection::Channel.new(connection(options),
|
446
|
+
options[:type] || "session",
|
447
|
+
options[:local_id] || 0,
|
448
|
+
&block)
|
449
|
+
end
|
450
|
+
end
|
451
|
+
|
452
|
+
end
|