net-ssh-multi 1.0.0
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 +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
|