net-ssh-multi 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.rdoc +13 -0
- data/Manifest +23 -0
- data/README.rdoc +87 -0
- data/Rakefile +28 -0
- data/lib/net/ssh/multi.rb +71 -0
- data/lib/net/ssh/multi/channel.rb +216 -0
- data/lib/net/ssh/multi/channel_proxy.rb +50 -0
- data/lib/net/ssh/multi/dynamic_server.rb +71 -0
- data/lib/net/ssh/multi/pending_connection.rb +112 -0
- data/lib/net/ssh/multi/server.rb +229 -0
- data/lib/net/ssh/multi/server_list.rb +80 -0
- data/lib/net/ssh/multi/session.rb +546 -0
- data/lib/net/ssh/multi/session_actions.rb +153 -0
- data/lib/net/ssh/multi/subsession.rb +48 -0
- data/lib/net/ssh/multi/version.rb +21 -0
- data/net-ssh-multi.gemspec +59 -0
- data/setup.rb +1585 -0
- data/test/channel_test.rb +152 -0
- data/test/common.rb +2 -0
- data/test/multi_test.rb +20 -0
- data/test/server_test.rb +256 -0
- data/test/session_actions_test.rb +128 -0
- data/test/session_test.rb +201 -0
- data/test/test_all.rb +3 -0
- metadata +93 -0
@@ -0,0 +1,152 @@
|
|
1
|
+
require 'common'
|
2
|
+
require 'net/ssh/multi/channel'
|
3
|
+
|
4
|
+
class ChannelTest < Test::Unit::TestCase
|
5
|
+
def test_each_should_iterate_over_each_component_channel
|
6
|
+
channels = [c1 = mock('channel'), c2 = mock('channel'), c3 = mock('channel')]
|
7
|
+
channel = Net::SSH::Multi::Channel.new(mock('session'), channels)
|
8
|
+
result = []
|
9
|
+
channel.each { |c| result << c }
|
10
|
+
assert_equal channels, result
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_property_accessors
|
14
|
+
channel = Net::SSH::Multi::Channel.new(mock('session'), [])
|
15
|
+
channel[:foo] = "hello"
|
16
|
+
assert_equal "hello", channel[:foo]
|
17
|
+
channel['bar'] = "goodbye"
|
18
|
+
assert_equal "goodbye", channel['bar']
|
19
|
+
assert_nil channel[:bar]
|
20
|
+
assert_nil channel['foo']
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_exec_should_delegate_to_component_channels
|
24
|
+
c1, c2, results = mock('channel'), mock('channel'), []
|
25
|
+
c1.expects(:exec).with('ls -l').yields(c1)
|
26
|
+
c2.expects(:exec).with('ls -l').yields(c2)
|
27
|
+
channel = Net::SSH::Multi::Channel.new(mock('session'), [c1, c2])
|
28
|
+
assert_equal channel, channel.exec('ls -l') { |c| results << c }
|
29
|
+
assert_equal [c1, c2], results
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_request_pty_should_delegate_to_component_channels
|
33
|
+
c1, c2, results = mock('channel'), mock('channel'), []
|
34
|
+
c1.expects(:request_pty).with(:foo => 5).yields(c1)
|
35
|
+
c2.expects(:request_pty).with(:foo => 5).yields(c2)
|
36
|
+
channel = Net::SSH::Multi::Channel.new(mock('session'), [c1, c2])
|
37
|
+
assert_equal channel, channel.request_pty(:foo => 5) { |c| results << c }
|
38
|
+
assert_equal [c1, c2], results
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_send_data_should_delegate_to_component_channels
|
42
|
+
c1, c2 = mock('channel'), mock('channel')
|
43
|
+
c1.expects(:send_data).with("hello\n")
|
44
|
+
c2.expects(:send_data).with("hello\n")
|
45
|
+
channel = Net::SSH::Multi::Channel.new(mock('session'), [c1, c2])
|
46
|
+
assert_equal channel, channel.send_data("hello\n")
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_active_should_be_true_if_all_component_channels_are_active
|
50
|
+
c1, c2, c3 = stub('channel', :active? => true), stub('channel', :active? => true), stub('channel', :active? => true)
|
51
|
+
channel = Net::SSH::Multi::Channel.new(stub('session'), [c1, c2, c3])
|
52
|
+
assert channel.active?
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_active_should_be_true_if_any_component_channels_are_active
|
56
|
+
c1, c2, c3 = stub('channel', :active? => true), stub('channel', :active? => false), stub('channel', :active? => false)
|
57
|
+
channel = Net::SSH::Multi::Channel.new(stub('session'), [c1, c2, c3])
|
58
|
+
assert channel.active?
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_active_should_be_false_if_no_component_channels_are_active
|
62
|
+
c1, c2, c3 = stub('channel', :active? => false), stub('channel', :active? => false), stub('channel', :active? => false)
|
63
|
+
channel = Net::SSH::Multi::Channel.new(stub('session'), [c1, c2, c3])
|
64
|
+
assert !channel.active?
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_wait_should_block_until_active_is_false
|
68
|
+
channel = Net::SSH::Multi::Channel.new(MockSession.new, [])
|
69
|
+
channel.expects(:active?).times(4).returns(true,true,true,false)
|
70
|
+
assert_equal channel, channel.wait
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_close_should_delegate_to_component_channels
|
74
|
+
c1, c2 = mock('channel'), mock('channel')
|
75
|
+
c1.expects(:close)
|
76
|
+
c2.expects(:close)
|
77
|
+
channel = Net::SSH::Multi::Channel.new(mock('session'), [c1, c2])
|
78
|
+
assert_equal channel, channel.close
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_eof_bang_should_delegate_to_component_channels
|
82
|
+
c1, c2 = mock('channel'), mock('channel')
|
83
|
+
c1.expects(:eof!)
|
84
|
+
c2.expects(:eof!)
|
85
|
+
channel = Net::SSH::Multi::Channel.new(mock('session'), [c1, c2])
|
86
|
+
assert_equal channel, channel.eof!
|
87
|
+
end
|
88
|
+
|
89
|
+
def test_on_data_should_delegate_to_component_channels
|
90
|
+
c1, c2, results = mock('channel'), mock('channel'), []
|
91
|
+
c1.expects(:on_data).yields(c1)
|
92
|
+
c2.expects(:on_data).yields(c2)
|
93
|
+
channel = Net::SSH::Multi::Channel.new(mock('session'), [c1, c2])
|
94
|
+
assert_equal channel, channel.on_data { |c| results << c }
|
95
|
+
assert_equal [c1, c2], results
|
96
|
+
end
|
97
|
+
|
98
|
+
def test_on_extended_data_should_delegate_to_component_channels
|
99
|
+
c1, c2, results = mock('channel'), mock('channel'), []
|
100
|
+
c1.expects(:on_extended_data).yields(c1)
|
101
|
+
c2.expects(:on_extended_data).yields(c2)
|
102
|
+
channel = Net::SSH::Multi::Channel.new(mock('session'), [c1, c2])
|
103
|
+
assert_equal channel, channel.on_extended_data { |c| results << c }
|
104
|
+
assert_equal [c1, c2], results
|
105
|
+
end
|
106
|
+
|
107
|
+
def test_on_process_should_delegate_to_component_channels
|
108
|
+
c1, c2, results = mock('channel'), mock('channel'), []
|
109
|
+
c1.expects(:on_process).yields(c1)
|
110
|
+
c2.expects(:on_process).yields(c2)
|
111
|
+
channel = Net::SSH::Multi::Channel.new(mock('session'), [c1, c2])
|
112
|
+
assert_equal channel, channel.on_process { |c| results << c }
|
113
|
+
assert_equal [c1, c2], results
|
114
|
+
end
|
115
|
+
|
116
|
+
def test_on_close_should_delegate_to_component_channels
|
117
|
+
c1, c2, results = mock('channel'), mock('channel'), []
|
118
|
+
c1.expects(:on_close).yields(c1)
|
119
|
+
c2.expects(:on_close).yields(c2)
|
120
|
+
channel = Net::SSH::Multi::Channel.new(mock('session'), [c1, c2])
|
121
|
+
assert_equal channel, channel.on_close { |c| results << c }
|
122
|
+
assert_equal [c1, c2], results
|
123
|
+
end
|
124
|
+
|
125
|
+
def test_on_eof_should_delegate_to_component_channels
|
126
|
+
c1, c2, results = mock('channel'), mock('channel'), []
|
127
|
+
c1.expects(:on_eof).yields(c1)
|
128
|
+
c2.expects(:on_eof).yields(c2)
|
129
|
+
channel = Net::SSH::Multi::Channel.new(mock('session'), [c1, c2])
|
130
|
+
assert_equal channel, channel.on_eof { |c| results << c }
|
131
|
+
assert_equal [c1, c2], results
|
132
|
+
end
|
133
|
+
|
134
|
+
def test_on_request_should_delegate_to_component_channels
|
135
|
+
c1, c2, results = mock('channel'), mock('channel'), []
|
136
|
+
c1.expects(:on_request).with("exit-status").yields(c1)
|
137
|
+
c2.expects(:on_request).with("exit-status").yields(c2)
|
138
|
+
channel = Net::SSH::Multi::Channel.new(mock('session'), [c1, c2])
|
139
|
+
assert_equal channel, channel.on_request("exit-status") { |c| results << c }
|
140
|
+
assert_equal [c1, c2], results
|
141
|
+
end
|
142
|
+
|
143
|
+
private
|
144
|
+
|
145
|
+
class MockSession
|
146
|
+
def loop
|
147
|
+
while true do
|
148
|
+
return if !yield(self)
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
data/test/common.rb
ADDED
data/test/multi_test.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'common'
|
2
|
+
require 'net/ssh/multi'
|
3
|
+
|
4
|
+
class MultiTest < Test::Unit::TestCase
|
5
|
+
def test_start_with_block_should_yield_session_and_then_close
|
6
|
+
Net::SSH::Multi::Session.any_instance.expects(:loop)
|
7
|
+
Net::SSH::Multi::Session.any_instance.expects(:close)
|
8
|
+
yielded = false
|
9
|
+
Net::SSH::Multi.start do |session|
|
10
|
+
yielded = true
|
11
|
+
assert_instance_of Net::SSH::Multi::Session, session
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_start_without_block_should_return_open_session
|
16
|
+
Net::SSH::Multi::Session.any_instance.expects(:loop).never
|
17
|
+
Net::SSH::Multi::Session.any_instance.expects(:close).never
|
18
|
+
assert_instance_of Net::SSH::Multi::Session, Net::SSH::Multi.start
|
19
|
+
end
|
20
|
+
end
|
data/test/server_test.rb
ADDED
@@ -0,0 +1,256 @@
|
|
1
|
+
require 'common'
|
2
|
+
require 'net/ssh/multi/server'
|
3
|
+
|
4
|
+
class ServerTest < Test::Unit::TestCase
|
5
|
+
def setup
|
6
|
+
@master = stub('multi-session', :default_user => "bob")
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_accessor_without_properties_should_access_empty_hash
|
10
|
+
assert_nil server('host')[:foo]
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_accessor_with_properties_should_access_properties
|
14
|
+
assert_equal "hello", server('host', :properties => { :foo => "hello" })[:foo]
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_port_should_return_22_by_default
|
18
|
+
assert_equal 22, server('host').port
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_port_should_return_given_port_when_present
|
22
|
+
assert_equal 1234, server('host', :port => 1234).port
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_port_should_return_parsed_port_when_present
|
26
|
+
assert_equal 1234, server('host:1234', :port => 1235).port
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_user_should_return_default_user_by_default
|
30
|
+
assert_equal "bob", server('host').user
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_user_should_return_given_user_when_present
|
34
|
+
assert_equal "jim", server('host', :user => "jim").user
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_user_should_return_parsed_user_when_present
|
38
|
+
assert_equal "jim", server('jim@host', :user => "john").user
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_equivalence_when_host_and_user_and_port_match
|
42
|
+
s1 = server('user@host:1234')
|
43
|
+
s2 = server('user@host:1234')
|
44
|
+
assert s1.eql?(s2)
|
45
|
+
assert_equal s1.hash, s2.hash
|
46
|
+
assert s1 == s2
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_equivalence_when_host_mismatch
|
50
|
+
s1 = server('user@host1:1234')
|
51
|
+
s2 = server('user@host2:1234')
|
52
|
+
assert !s1.eql?(s2)
|
53
|
+
assert_not_equal s1.hash, s2.hash
|
54
|
+
assert s1 != s2
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_equivalence_when_port_mismatch
|
58
|
+
s1 = server('user@host:1234')
|
59
|
+
s2 = server('user@host:1235')
|
60
|
+
assert !s1.eql?(s2)
|
61
|
+
assert_not_equal s1.hash, s2.hash
|
62
|
+
assert s1 != s2
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_equivalence_when_user_mismatch
|
66
|
+
s1 = server('user1@host:1234')
|
67
|
+
s2 = server('user2@host:1234')
|
68
|
+
assert !s1.eql?(s2)
|
69
|
+
assert_not_equal s1.hash, s2.hash
|
70
|
+
assert s1 != s2
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_to_s_should_include_user_and_host
|
74
|
+
assert_equal "user@host", server('user@host').to_s
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_to_s_should_include_user_and_host_and_port_when_port_is_given
|
78
|
+
assert_equal "user@host:1234", server('user@host:1234').to_s
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_gateway_should_be_nil_by_default
|
82
|
+
assert_nil server('host').gateway
|
83
|
+
end
|
84
|
+
|
85
|
+
def test_gateway_should_be_set_with_the_via_value
|
86
|
+
gateway = mock('gateway')
|
87
|
+
assert_equal gateway, server('host', :via => gateway).gateway
|
88
|
+
end
|
89
|
+
|
90
|
+
def test_session_with_default_argument_should_not_instantiate_session
|
91
|
+
assert_nil server('host').session
|
92
|
+
end
|
93
|
+
|
94
|
+
def test_session_with_true_argument_should_instantiate_and_cache_session
|
95
|
+
srv = server('host')
|
96
|
+
session = expect_connection_to(srv)
|
97
|
+
assert_equal session, srv.session(true)
|
98
|
+
assert_equal session, srv.session(true)
|
99
|
+
assert_equal session, srv.session
|
100
|
+
end
|
101
|
+
|
102
|
+
def test_session_that_cannot_authenticate_adds_host_to_exception_message
|
103
|
+
srv = server('host')
|
104
|
+
Net::SSH.expects(:start).with('host', 'bob', {}).raises(Net::SSH::AuthenticationFailed.new('bob'))
|
105
|
+
|
106
|
+
begin
|
107
|
+
srv.new_session
|
108
|
+
flunk
|
109
|
+
rescue Net::SSH::AuthenticationFailed => e
|
110
|
+
assert_equal "bob@host", e.message
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def test_close_channels_when_session_is_not_open_should_not_do_anything
|
115
|
+
assert_nothing_raised { server('host').close_channels }
|
116
|
+
end
|
117
|
+
|
118
|
+
def test_close_channels_when_session_is_open_should_iterate_over_open_channels_and_close_them
|
119
|
+
srv = server('host')
|
120
|
+
session = expect_connection_to(srv)
|
121
|
+
c1 = mock('channel', :close => nil)
|
122
|
+
c2 = mock('channel', :close => nil)
|
123
|
+
c3 = mock('channel', :close => nil)
|
124
|
+
session.expects(:channels).returns(1 => c1, 2 => c2, 3 => c3)
|
125
|
+
assert_equal session, srv.session(true)
|
126
|
+
srv.close_channels
|
127
|
+
end
|
128
|
+
|
129
|
+
def test_close_when_session_is_not_open_should_not_do_anything
|
130
|
+
assert_nothing_raised { server('host').close }
|
131
|
+
end
|
132
|
+
|
133
|
+
def test_close_when_session_is_open_should_close_session
|
134
|
+
srv = server('host')
|
135
|
+
session = expect_connection_to(srv)
|
136
|
+
session.expects(:close)
|
137
|
+
@master.expects(:server_closed).with(srv)
|
138
|
+
assert_equal session, srv.session(true)
|
139
|
+
srv.close
|
140
|
+
end
|
141
|
+
|
142
|
+
def test_busy_should_be_false_when_session_is_not_open
|
143
|
+
assert !server('host').busy?
|
144
|
+
end
|
145
|
+
|
146
|
+
def test_busy_should_be_false_when_session_is_not_busy
|
147
|
+
srv = server('host')
|
148
|
+
session = expect_connection_to(srv)
|
149
|
+
session.expects(:busy?).returns(false)
|
150
|
+
srv.session(true)
|
151
|
+
assert !srv.busy?
|
152
|
+
end
|
153
|
+
|
154
|
+
def test_busy_should_be_true_when_session_is_busy
|
155
|
+
srv = server('host')
|
156
|
+
session = expect_connection_to(srv)
|
157
|
+
session.expects(:busy?).returns(true)
|
158
|
+
srv.session(true)
|
159
|
+
assert srv.busy?
|
160
|
+
end
|
161
|
+
|
162
|
+
def test_preprocess_should_be_nil_when_session_is_not_open
|
163
|
+
assert_nil server('host').preprocess
|
164
|
+
end
|
165
|
+
|
166
|
+
def test_preprocess_should_return_result_of_session_preprocess
|
167
|
+
srv = server('host')
|
168
|
+
session = expect_connection_to(srv)
|
169
|
+
session.expects(:preprocess).returns(:result)
|
170
|
+
srv.session(true)
|
171
|
+
assert_equal :result, srv.preprocess
|
172
|
+
end
|
173
|
+
|
174
|
+
def test_readers_should_return_empty_array_when_session_is_not_open
|
175
|
+
assert_equal [], server('host').readers
|
176
|
+
end
|
177
|
+
|
178
|
+
def test_readers_should_return_all_listeners_when_session_is_open
|
179
|
+
srv = server('host')
|
180
|
+
session = expect_connection_to(srv)
|
181
|
+
io1, io2, io3, io4 = Reader.new, Reader.new, Reader.new, Reader.new
|
182
|
+
session.expects(:listeners).returns(io1 => 2, io2 => 4, io3 => 6, io4 => 8)
|
183
|
+
srv.session(true)
|
184
|
+
assert_equal [io1, io2, io3, io4], srv.readers.sort
|
185
|
+
end
|
186
|
+
|
187
|
+
def test_writers_should_return_empty_array_when_session_is_not_open
|
188
|
+
assert_equal [], server('host').writers
|
189
|
+
end
|
190
|
+
|
191
|
+
def test_writers_should_return_all_listeners_that_are_pending_writes_when_session_is_open
|
192
|
+
srv = server('host')
|
193
|
+
session = expect_connection_to(srv)
|
194
|
+
listeners = { Reader.new(true) => 1, MockIO.new => 2,
|
195
|
+
MockIO.new => 3, Reader.new => 4, Reader.new(true) => 5 }
|
196
|
+
session.expects(:listeners).returns(listeners)
|
197
|
+
srv.session(true)
|
198
|
+
assert_equal 2, srv.writers.length
|
199
|
+
end
|
200
|
+
|
201
|
+
def test_postprocess_should_return_true_when_session_is_not_open
|
202
|
+
assert_equal true, server('host').postprocess([], [])
|
203
|
+
end
|
204
|
+
|
205
|
+
def test_postprocess_should_call_session_postprocess_with_ios_belonging_to_session
|
206
|
+
srv = server('host')
|
207
|
+
session = expect_connection_to(srv)
|
208
|
+
session.expects(:listeners).returns(1 => 2, 3 => 4, 5 => 6, 7 => 8)
|
209
|
+
session.expects(:postprocess).with([1,3], [7]).returns(:result)
|
210
|
+
srv.session(true)
|
211
|
+
assert_equal :result, srv.postprocess([1,11,3], [18,14,7,12])
|
212
|
+
end
|
213
|
+
|
214
|
+
private
|
215
|
+
|
216
|
+
class MockIO
|
217
|
+
include Comparable
|
218
|
+
|
219
|
+
@@identifier = 0
|
220
|
+
|
221
|
+
attr_reader :id
|
222
|
+
|
223
|
+
def initialize
|
224
|
+
@id = (@@identifier += 1)
|
225
|
+
end
|
226
|
+
|
227
|
+
def <=>(io)
|
228
|
+
@id <=> io.id
|
229
|
+
end
|
230
|
+
|
231
|
+
def closed?
|
232
|
+
false
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
class Reader < MockIO
|
237
|
+
def initialize(ready=false)
|
238
|
+
super()
|
239
|
+
@ready = ready
|
240
|
+
end
|
241
|
+
|
242
|
+
def pending_write?
|
243
|
+
@ready
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
def server(host, options={})
|
248
|
+
Net::SSH::Multi::Server.new(@master, host, options)
|
249
|
+
end
|
250
|
+
|
251
|
+
def expect_connection_to(server)
|
252
|
+
session = {}
|
253
|
+
@master.expects(:next_session).with(server).returns(session)
|
254
|
+
return session
|
255
|
+
end
|
256
|
+
end
|
@@ -0,0 +1,128 @@
|
|
1
|
+
require 'common'
|
2
|
+
require 'net/ssh/multi/server'
|
3
|
+
require 'net/ssh/multi/session_actions'
|
4
|
+
|
5
|
+
class SessionActionsTest < Test::Unit::TestCase
|
6
|
+
class SessionActionsContainer
|
7
|
+
include Net::SSH::Multi::SessionActions
|
8
|
+
|
9
|
+
attr_reader :servers
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
@servers = []
|
13
|
+
end
|
14
|
+
|
15
|
+
def default_user
|
16
|
+
"user"
|
17
|
+
end
|
18
|
+
|
19
|
+
def use(h, o={})
|
20
|
+
server = Net::SSH::Multi::Server.new(self, h, o)
|
21
|
+
servers << server
|
22
|
+
server
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def setup
|
27
|
+
@session = SessionActionsContainer.new
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_busy_should_be_true_if_any_server_is_busy
|
31
|
+
srv1, srv2, srv3 = @session.use('h1'), @session.use('h2'), @session.use('h3')
|
32
|
+
srv1.stubs(:busy?).returns(false)
|
33
|
+
srv2.stubs(:busy?).returns(false)
|
34
|
+
srv3.stubs(:busy?).returns(true)
|
35
|
+
assert @session.busy?
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_busy_should_be_false_if_all_servers_are_not_busy
|
39
|
+
srv1, srv2, srv3 = @session.use('h1'), @session.use('h2'), @session.use('h3')
|
40
|
+
srv1.stubs(:busy?).returns(false)
|
41
|
+
srv2.stubs(:busy?).returns(false)
|
42
|
+
srv3.stubs(:busy?).returns(false)
|
43
|
+
assert !@session.busy?
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_send_global_request_should_delegate_to_sessions
|
47
|
+
s1 = mock('ssh')
|
48
|
+
s2 = mock('ssh')
|
49
|
+
s1.expects(:send_global_request).with("a", "b", "c").yields
|
50
|
+
s2.expects(:send_global_request).with("a", "b", "c").yields
|
51
|
+
@session.expects(:sessions).returns([s1, s2])
|
52
|
+
calls = 0
|
53
|
+
@session.send_global_request("a", "b", "c") { calls += 1 }
|
54
|
+
assert_equal 2, calls
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_open_channel_should_delegate_to_sessions_and_set_accessors_on_each_channel_and_return_multi_channel
|
58
|
+
srv1 = @session.use('h1')
|
59
|
+
srv2 = @session.use('h2')
|
60
|
+
s1 = { :server => srv1 }
|
61
|
+
s2 = { :server => srv2 }
|
62
|
+
c1 = { :stub => :value }
|
63
|
+
c2 = {}
|
64
|
+
c1.stubs(:connection).returns(s1)
|
65
|
+
c2.stubs(:connection).returns(s2)
|
66
|
+
@session.expects(:sessions).returns([s1, s2])
|
67
|
+
s1.expects(:open_channel).with("session").yields(c1).returns(c1)
|
68
|
+
s2.expects(:open_channel).with("session").yields(c2).returns(c2)
|
69
|
+
results = []
|
70
|
+
channel = @session.open_channel do |c|
|
71
|
+
results << c
|
72
|
+
end
|
73
|
+
assert_equal [c1, c2], results
|
74
|
+
assert_equal "h1", c1[:host]
|
75
|
+
assert_equal "h2", c2[:host]
|
76
|
+
assert_equal srv1, c1[:server]
|
77
|
+
assert_equal srv2, c2[:server]
|
78
|
+
assert_instance_of Net::SSH::Multi::Channel, channel
|
79
|
+
assert_equal [c1, c2], channel.channels
|
80
|
+
end
|
81
|
+
|
82
|
+
def test_exec_should_raise_exception_if_channel_cannot_exec_command
|
83
|
+
c = { :host => "host" }
|
84
|
+
@session.expects(:open_channel).yields(c).returns(c)
|
85
|
+
c.expects(:exec).with('something').yields(c, false)
|
86
|
+
assert_raises(RuntimeError) { @session.exec("something") }
|
87
|
+
end
|
88
|
+
|
89
|
+
def test_exec_with_block_should_pass_data_and_extended_data_to_block
|
90
|
+
c = { :host => "host" }
|
91
|
+
@session.expects(:open_channel).yields(c).returns(c)
|
92
|
+
c.expects(:exec).with('something').yields(c, true)
|
93
|
+
c.expects(:on_data).yields(c, "stdout")
|
94
|
+
c.expects(:on_extended_data).yields(c, 1, "stderr")
|
95
|
+
c.expects(:on_request)
|
96
|
+
results = {}
|
97
|
+
@session.exec("something") do |c, stream, data|
|
98
|
+
results[stream] = data
|
99
|
+
end
|
100
|
+
assert_equal({:stdout => "stdout", :stderr => "stderr"}, results)
|
101
|
+
end
|
102
|
+
|
103
|
+
def test_exec_without_block_should_write_data_and_extended_data_lines_to_stdout_and_stderr
|
104
|
+
c = { :host => "host" }
|
105
|
+
@session.expects(:open_channel).yields(c).returns(c)
|
106
|
+
c.expects(:exec).with('something').yields(c, true)
|
107
|
+
c.expects(:on_data).yields(c, "stdout 1\nstdout 2\n")
|
108
|
+
c.expects(:on_extended_data).yields(c, 1, "stderr 1\nstderr 2\n")
|
109
|
+
c.expects(:on_request)
|
110
|
+
$stdout.expects(:puts).with("[host] stdout 1\n")
|
111
|
+
$stdout.expects(:puts).with("[host] stdout 2")
|
112
|
+
$stderr.expects(:puts).with("[host] stderr 1\n")
|
113
|
+
$stderr.expects(:puts).with("[host] stderr 2")
|
114
|
+
@session.exec("something")
|
115
|
+
end
|
116
|
+
|
117
|
+
def test_exec_should_capture_exit_status_of_process
|
118
|
+
c = { :host => "host" }
|
119
|
+
@session.expects(:open_channel).yields(c).returns(c)
|
120
|
+
c.expects(:exec).with('something').yields(c, true)
|
121
|
+
c.expects(:on_data)
|
122
|
+
c.expects(:on_extended_data)
|
123
|
+
c.expects(:on_request).with("exit-status").yields(c, Net::SSH::Buffer.from(:long, 127))
|
124
|
+
@session.exec("something")
|
125
|
+
assert_equal 127, c[:exit_status]
|
126
|
+
end
|
127
|
+
|
128
|
+
end
|