| OLD | NEW |
| (Empty) |
| 1 # Copyright (c) 2007 Twisted Matrix Laboratories. | |
| 2 # See LICENSE for details | |
| 3 | |
| 4 """ | |
| 5 This module tests twisted.conch.ssh.connection. | |
| 6 """ | |
| 7 import struct | |
| 8 from twisted.conch import error | |
| 9 from twisted.conch.ssh import channel, common, connection | |
| 10 from twisted.trial import unittest | |
| 11 from twisted.conch.test import test_userauth | |
| 12 | |
| 13 class TestChannel(channel.SSHChannel): | |
| 14 """ | |
| 15 A mocked-up version of twisted.conch.ssh.channel.SSHChannel. | |
| 16 | |
| 17 @ivar gotOpen: True if channelOpen has been called. | |
| 18 @type gotOpen: C{bool} | |
| 19 @ivar specificData: the specific channel open data passed to channelOpen. | |
| 20 @type specificData: C{str} | |
| 21 @ivar openFailureReason: the reason passed to openFailed. | |
| 22 @type openFailed: C{error.ConchError} | |
| 23 @ivar inBuffer: a C{list} of strings received by the channel. | |
| 24 @type inBuffer: C{list} | |
| 25 @ivar extBuffer: a C{list} of 2-tuples (type, extended data) of received by | |
| 26 the channel. | |
| 27 @type extBuffer: C{list} | |
| 28 @ivar numberRequests: the number of requests that have been made to this | |
| 29 channel. | |
| 30 @type numberRequests: C{int} | |
| 31 @ivar gotEOF: True if the other side sent EOF. | |
| 32 @type gotEOF: C{bool} | |
| 33 @ivar gotOneClose: True if the other side closed the connection. | |
| 34 @type gotOneClose: C{bool} | |
| 35 @ivar gotClosed: True if the channel is closed. | |
| 36 @type gotClosed: C{bool} | |
| 37 """ | |
| 38 name = "TestChannel" | |
| 39 gotOpen = False | |
| 40 | |
| 41 def logPrefix(self): | |
| 42 return "TestChannel %i" % self.id | |
| 43 | |
| 44 def channelOpen(self, specificData): | |
| 45 """ | |
| 46 The channel is open. Set up the instance variables. | |
| 47 """ | |
| 48 self.gotOpen = True | |
| 49 self.specificData = specificData | |
| 50 self.inBuffer = [] | |
| 51 self.extBuffer = [] | |
| 52 self.numberRequests = 0 | |
| 53 self.gotEOF = False | |
| 54 self.gotOneClose = False | |
| 55 self.gotClosed = False | |
| 56 | |
| 57 def openFailed(self, reason): | |
| 58 """ | |
| 59 Opening the channel failed. Store the reason why. | |
| 60 """ | |
| 61 self.openFailureReason = reason | |
| 62 | |
| 63 def request_test(self, data): | |
| 64 """ | |
| 65 A test request. Return True if data is 'data'. | |
| 66 | |
| 67 @type data: C{str} | |
| 68 """ | |
| 69 self.numberRequests += 1 | |
| 70 return data == 'data' | |
| 71 | |
| 72 def dataReceived(self, data): | |
| 73 """ | |
| 74 Data was received. Store it in the buffer. | |
| 75 """ | |
| 76 self.inBuffer.append(data) | |
| 77 | |
| 78 def extReceived(self, code, data): | |
| 79 """ | |
| 80 Extended data was received. Store it in the buffer. | |
| 81 """ | |
| 82 self.extBuffer.append((code, data)) | |
| 83 | |
| 84 def eofReceived(self): | |
| 85 """ | |
| 86 EOF was received. Remember it. | |
| 87 """ | |
| 88 self.gotEOF = True | |
| 89 | |
| 90 def closeReceived(self): | |
| 91 """ | |
| 92 Close was received. Remember it. | |
| 93 """ | |
| 94 self.gotOneClose = True | |
| 95 | |
| 96 def closed(self): | |
| 97 """ | |
| 98 The channel is closed. Rembember it. | |
| 99 """ | |
| 100 self.gotClosed = True | |
| 101 | |
| 102 class TestAvatar: | |
| 103 """ | |
| 104 A mocked-up version of twisted.conch.avatar.ConchUser | |
| 105 """ | |
| 106 | |
| 107 def lookupChannel(self, channelType, windowSize, maxPacket, data): | |
| 108 """ | |
| 109 The server wants us to return a channel. If the requested channel is | |
| 110 our TestChannel, return it, otherwise return None. | |
| 111 """ | |
| 112 if channelType == TestChannel.name: | |
| 113 return TestChannel(remoteWindow=windowSize, | |
| 114 remoteMaxPacket=maxPacket, | |
| 115 data=data, avatar=self) | |
| 116 | |
| 117 def gotGlobalRequest(self, requestType, data): | |
| 118 """ | |
| 119 The client has made a global request. If the global request is | |
| 120 'TestGlobal', return True. If the global request is 'TestData', | |
| 121 return True and the request-specific data we received. Otherwise, | |
| 122 return False. | |
| 123 """ | |
| 124 if requestType == 'TestGlobal': | |
| 125 return True | |
| 126 elif requestType == 'TestData': | |
| 127 return True, data | |
| 128 else: | |
| 129 return False | |
| 130 | |
| 131 class TestConnection(connection.SSHConnection): | |
| 132 """ | |
| 133 A subclass of SSHConnection for testing. | |
| 134 | |
| 135 @ivar channel: the current channel. | |
| 136 @type channel. C{TestChannel} | |
| 137 """ | |
| 138 | |
| 139 def logPrefix(self): | |
| 140 return "TestConnection" | |
| 141 | |
| 142 def global_TestGlobal(self, data): | |
| 143 """ | |
| 144 The other side made the 'TestGlobal' global request. Return True. | |
| 145 """ | |
| 146 return True | |
| 147 | |
| 148 def global_Test_Data(self, data): | |
| 149 """ | |
| 150 The other side made the 'Test-Data' global request. Return True and | |
| 151 the data we received. | |
| 152 """ | |
| 153 return True, data | |
| 154 | |
| 155 def channel_TestChannel(self, windowSize, maxPacket, data): | |
| 156 """ | |
| 157 The other side is requesting the TestChannel. Create a C{TestChannel} | |
| 158 instance, store it, and return it. | |
| 159 """ | |
| 160 self.channel = TestChannel(remoteWindow=windowSize, | |
| 161 remoteMaxPacket=maxPacket, data=data) | |
| 162 return self.channel | |
| 163 | |
| 164 def channel_ErrorChannel(self, windowSize, maxPacket, data): | |
| 165 """ | |
| 166 The other side is requesting the ErrorChannel. Raise an exception. | |
| 167 """ | |
| 168 raise AssertionError('no such thing') | |
| 169 | |
| 170 class ConnectionTestCase(unittest.TestCase): | |
| 171 | |
| 172 def setUp(self): | |
| 173 self.transport = test_userauth.FakeTransport(None) | |
| 174 self.transport.avatar = TestAvatar() | |
| 175 self.conn = TestConnection() | |
| 176 self.conn.transport = self.transport | |
| 177 self.conn.serviceStarted() | |
| 178 | |
| 179 def _openChannel(self, channel): | |
| 180 """ | |
| 181 Open the channel with the default connection. | |
| 182 """ | |
| 183 self.conn.openChannel(channel) | |
| 184 self.transport.packets = self.transport.packets[:-1] | |
| 185 self.conn.ssh_CHANNEL_OPEN_CONFIRMATION(struct.pack('>2L', | |
| 186 channel.id, 255) + '\x00\x02\x00\x00\x00\x00\x80\x00') | |
| 187 | |
| 188 def tearDown(self): | |
| 189 self.conn.serviceStopped() | |
| 190 | |
| 191 def test_linkAvatar(self): | |
| 192 """ | |
| 193 Test that the connection links itself to the avatar in the | |
| 194 transport. | |
| 195 """ | |
| 196 self.assertIdentical(self.transport.avatar.conn, self.conn) | |
| 197 | |
| 198 def test_serviceStopped(self): | |
| 199 """ | |
| 200 Test that serviceStopped() closes any open channels. | |
| 201 """ | |
| 202 channel1 = TestChannel() | |
| 203 channel2 = TestChannel() | |
| 204 self.conn.openChannel(channel1) | |
| 205 self.conn.openChannel(channel2) | |
| 206 self.conn.ssh_CHANNEL_OPEN_CONFIRMATION('\x00\x00\x00\x00' * 4) | |
| 207 self.assertTrue(channel1.gotOpen) | |
| 208 self.assertFalse(channel2.gotOpen) | |
| 209 self.conn.serviceStopped() | |
| 210 self.assertTrue(channel1.gotClosed) | |
| 211 | |
| 212 def test_GLOBAL_REQUEST(self): | |
| 213 """ | |
| 214 Test that global request packets are dispatched to the global_* | |
| 215 methods and the return values are translated into success or failure | |
| 216 messages. | |
| 217 """ | |
| 218 self.conn.ssh_GLOBAL_REQUEST(common.NS('TestGlobal') + '\xff') | |
| 219 self.assertEquals(self.transport.packets, | |
| 220 [(connection.MSG_REQUEST_SUCCESS, '')]) | |
| 221 self.transport.packets = [] | |
| 222 self.conn.ssh_GLOBAL_REQUEST(common.NS('TestData') + '\xff' + | |
| 223 'test data') | |
| 224 self.assertEquals(self.transport.packets, | |
| 225 [(connection.MSG_REQUEST_SUCCESS, 'test data')]) | |
| 226 self.transport.packets = [] | |
| 227 self.conn.ssh_GLOBAL_REQUEST(common.NS('TestBad') + '\xff') | |
| 228 self.assertEquals(self.transport.packets, | |
| 229 [(connection.MSG_REQUEST_FAILURE, '')]) | |
| 230 self.transport.packets = [] | |
| 231 self.conn.ssh_GLOBAL_REQUEST(common.NS('TestGlobal') + '\x00') | |
| 232 self.assertEquals(self.transport.packets, []) | |
| 233 | |
| 234 def test_REQUEST_SUCCESS(self): | |
| 235 """ | |
| 236 Test that global request success packets cause the Deferred to be | |
| 237 called back. | |
| 238 """ | |
| 239 d = self.conn.sendGlobalRequest('request', 'data', True) | |
| 240 self.conn.ssh_REQUEST_SUCCESS('data') | |
| 241 def check(data): | |
| 242 self.assertEquals(data, 'data') | |
| 243 d.addCallback(check) | |
| 244 d.addErrback(self.fail) | |
| 245 return d | |
| 246 | |
| 247 def test_REQUEST_FAILURE(self): | |
| 248 """ | |
| 249 Test that global request failure packets cause the Deferred to be | |
| 250 erred back. | |
| 251 """ | |
| 252 d = self.conn.sendGlobalRequest('request', 'data', True) | |
| 253 self.conn.ssh_REQUEST_FAILURE('data') | |
| 254 def check(f): | |
| 255 self.assertEquals(f.value.data, 'data') | |
| 256 d.addCallback(self.fail) | |
| 257 d.addErrback(check) | |
| 258 return d | |
| 259 | |
| 260 def test_CHANNEL_OPEN(self): | |
| 261 """ | |
| 262 Test that open channel packets cause a channel to be created and | |
| 263 opened or a failure message to be returned. | |
| 264 """ | |
| 265 del self.transport.avatar | |
| 266 self.conn.ssh_CHANNEL_OPEN(common.NS('TestChannel') + | |
| 267 '\x00\x00\x00\x01' * 4) | |
| 268 self.assertTrue(self.conn.channel.gotOpen) | |
| 269 self.assertEquals(self.conn.channel.conn, self.conn) | |
| 270 self.assertEquals(self.conn.channel.data, '\x00\x00\x00\x01') | |
| 271 self.assertEquals(self.conn.channel.specificData, '\x00\x00\x00\x01') | |
| 272 self.assertEquals(self.conn.channel.remoteWindowLeft, 1) | |
| 273 self.assertEquals(self.conn.channel.remoteMaxPacket, 1) | |
| 274 self.assertEquals(self.transport.packets, | |
| 275 [(connection.MSG_CHANNEL_OPEN_CONFIRMATION, | |
| 276 '\x00\x00\x00\x01\x00\x00\x00\x00\x00\x02\x00\x00' | |
| 277 '\x00\x00\x80\x00')]) | |
| 278 self.transport.packets = [] | |
| 279 self.conn.ssh_CHANNEL_OPEN(common.NS('BadChannel') + | |
| 280 '\x00\x00\x00\x02' * 4) | |
| 281 self.flushLoggedErrors() | |
| 282 self.assertEquals(self.transport.packets, | |
| 283 [(connection.MSG_CHANNEL_OPEN_FAILURE, | |
| 284 '\x00\x00\x00\x02\x00\x00\x00\x03' + common.NS( | |
| 285 'unknown channel') + common.NS(''))]) | |
| 286 self.transport.packets = [] | |
| 287 self.conn.ssh_CHANNEL_OPEN(common.NS('ErrorChannel') + | |
| 288 '\x00\x00\x00\x02' * 4) | |
| 289 self.flushLoggedErrors() | |
| 290 self.assertEquals(self.transport.packets, | |
| 291 [(connection.MSG_CHANNEL_OPEN_FAILURE, | |
| 292 '\x00\x00\x00\x02\x00\x00\x00\x02' + common.NS( | |
| 293 'unknown failure') + common.NS(''))]) | |
| 294 | |
| 295 def test_CHANNEL_OPEN_CONFIRMATION(self): | |
| 296 """ | |
| 297 Test that channel open confirmation packets cause the channel to be | |
| 298 notified that it's open. | |
| 299 """ | |
| 300 channel = TestChannel() | |
| 301 self.conn.openChannel(channel) | |
| 302 self.conn.ssh_CHANNEL_OPEN_CONFIRMATION('\x00\x00\x00\x00'*5) | |
| 303 self.assertEquals(channel.remoteWindowLeft, 0) | |
| 304 self.assertEquals(channel.remoteMaxPacket, 0) | |
| 305 self.assertEquals(channel.specificData, '\x00\x00\x00\x00') | |
| 306 self.assertEquals(self.conn.channelsToRemoteChannel[channel], | |
| 307 0) | |
| 308 self.assertEquals(self.conn.localToRemoteChannel[0], 0) | |
| 309 | |
| 310 def test_CHANNEL_OPEN_FAILURE(self): | |
| 311 """ | |
| 312 Test that channel open failure packets cause the channel to be | |
| 313 notified that its opening failed. | |
| 314 """ | |
| 315 channel = TestChannel() | |
| 316 self.conn.openChannel(channel) | |
| 317 self.conn.ssh_CHANNEL_OPEN_FAILURE('\x00\x00\x00\x00\x00\x00\x00' | |
| 318 '\x01' + common.NS('failure!')) | |
| 319 self.assertEquals(channel.openFailureReason.args, ('failure!', 1)) | |
| 320 self.assertEquals(self.conn.channels.get(channel), None) | |
| 321 | |
| 322 | |
| 323 def test_CHANNEL_WINDOW_ADJUST(self): | |
| 324 """ | |
| 325 Test that channel window adjust messages add bytes to the channel | |
| 326 window. | |
| 327 """ | |
| 328 channel = TestChannel() | |
| 329 self._openChannel(channel) | |
| 330 oldWindowSize = channel.remoteWindowLeft | |
| 331 self.conn.ssh_CHANNEL_WINDOW_ADJUST('\x00\x00\x00\x00\x00\x00\x00' | |
| 332 '\x01') | |
| 333 self.assertEquals(channel.remoteWindowLeft, oldWindowSize + 1) | |
| 334 | |
| 335 def test_CHANNEL_DATA(self): | |
| 336 """ | |
| 337 Test that channel data messages are passed up to the channel, or | |
| 338 cause the channel to be closed if the data is too large. | |
| 339 """ | |
| 340 channel = TestChannel(localWindow=6, localMaxPacket=5) | |
| 341 self._openChannel(channel) | |
| 342 self.conn.ssh_CHANNEL_DATA('\x00\x00\x00\x00' + common.NS('data')) | |
| 343 self.assertEquals(channel.inBuffer, ['data']) | |
| 344 self.assertEquals(self.transport.packets, | |
| 345 [(connection.MSG_CHANNEL_WINDOW_ADJUST, '\x00\x00\x00\xff' | |
| 346 '\x00\x00\x00\x04')]) | |
| 347 self.transport.packets = [] | |
| 348 longData = 'a' * (channel.localWindowLeft + 1) | |
| 349 self.conn.ssh_CHANNEL_DATA('\x00\x00\x00\x00' + common.NS(longData)) | |
| 350 self.assertEquals(channel.inBuffer, ['data']) | |
| 351 self.assertEquals(self.transport.packets, | |
| 352 [(connection.MSG_CHANNEL_CLOSE, '\x00\x00\x00\xff')]) | |
| 353 channel = TestChannel() | |
| 354 self._openChannel(channel) | |
| 355 bigData = 'a' * (channel.localMaxPacket + 1) | |
| 356 self.transport.packets = [] | |
| 357 self.conn.ssh_CHANNEL_DATA('\x00\x00\x00\x01' + common.NS(bigData)) | |
| 358 self.assertEquals(channel.inBuffer, []) | |
| 359 self.assertEquals(self.transport.packets, | |
| 360 [(connection.MSG_CHANNEL_CLOSE, '\x00\x00\x00\xff')]) | |
| 361 | |
| 362 def test_CHANNEL_EXTENDED_DATA(self): | |
| 363 """ | |
| 364 Test that channel extended data messages are passed up to the channel, | |
| 365 or cause the channel to be closed if they're too big. | |
| 366 """ | |
| 367 channel = TestChannel(localWindow=6, localMaxPacket=5) | |
| 368 self._openChannel(channel) | |
| 369 self.conn.ssh_CHANNEL_EXTENDED_DATA('\x00\x00\x00\x00\x00\x00\x00' | |
| 370 '\x00' + common.NS('data')) | |
| 371 self.assertEquals(channel.extBuffer, [(0, 'data')]) | |
| 372 self.assertEquals(self.transport.packets, | |
| 373 [(connection.MSG_CHANNEL_WINDOW_ADJUST, '\x00\x00\x00\xff' | |
| 374 '\x00\x00\x00\x04')]) | |
| 375 self.transport.packets = [] | |
| 376 longData = 'a' * (channel.localWindowLeft + 1) | |
| 377 self.conn.ssh_CHANNEL_EXTENDED_DATA('\x00\x00\x00\x00\x00\x00\x00' | |
| 378 '\x00' + common.NS(longData)) | |
| 379 self.assertEquals(channel.extBuffer, [(0, 'data')]) | |
| 380 self.assertEquals(self.transport.packets, | |
| 381 [(connection.MSG_CHANNEL_CLOSE, '\x00\x00\x00\xff')]) | |
| 382 channel = TestChannel() | |
| 383 self._openChannel(channel) | |
| 384 bigData = 'a' * (channel.localMaxPacket + 1) | |
| 385 self.transport.packets = [] | |
| 386 self.conn.ssh_CHANNEL_EXTENDED_DATA('\x00\x00\x00\x01\x00\x00\x00' | |
| 387 '\x00' + common.NS(bigData)) | |
| 388 self.assertEquals(channel.extBuffer, []) | |
| 389 self.assertEquals(self.transport.packets, | |
| 390 [(connection.MSG_CHANNEL_CLOSE, '\x00\x00\x00\xff')]) | |
| 391 | |
| 392 def test_CHANNEL_EOF(self): | |
| 393 """ | |
| 394 Test that channel eof messages are passed up to the channel. | |
| 395 """ | |
| 396 channel = TestChannel() | |
| 397 self._openChannel(channel) | |
| 398 self.conn.ssh_CHANNEL_EOF('\x00\x00\x00\x00') | |
| 399 self.assertTrue(channel.gotEOF) | |
| 400 | |
| 401 def test_CHANNEL_CLOSE(self): | |
| 402 """ | |
| 403 Test that channel close messages are passed up to the channel. Also, | |
| 404 test that channel.close() is called if both sides are closed when this | |
| 405 message is received. | |
| 406 """ | |
| 407 channel = TestChannel() | |
| 408 self._openChannel(channel) | |
| 409 self.conn.sendClose(channel) | |
| 410 self.conn.ssh_CHANNEL_CLOSE('\x00\x00\x00\x00') | |
| 411 self.assertTrue(channel.gotOneClose) | |
| 412 self.assertTrue(channel.gotClosed) | |
| 413 | |
| 414 def test_CHANNEL_REQUEST_success(self): | |
| 415 """ | |
| 416 Test that channel requests that succeed send MSG_CHANNEL_SUCCESS. | |
| 417 """ | |
| 418 channel = TestChannel() | |
| 419 self._openChannel(channel) | |
| 420 self.conn.ssh_CHANNEL_REQUEST('\x00\x00\x00\x00' + common.NS('test') | |
| 421 + '\x00') | |
| 422 self.assertEquals(channel.numberRequests, 1) | |
| 423 d = self.conn.ssh_CHANNEL_REQUEST('\x00\x00\x00\x00' + common.NS( | |
| 424 'test') + '\xff' + 'data') | |
| 425 def check(result): | |
| 426 self.assertEquals(self.transport.packets, | |
| 427 [(connection.MSG_CHANNEL_SUCCESS, '\x00\x00\x00\xff')]) | |
| 428 d.addCallback(check) | |
| 429 return d | |
| 430 | |
| 431 def test_CHANNEL_REQUEST_failure(self): | |
| 432 """ | |
| 433 Test that channel requests that fail send MSG_CHANNEL_FAILURE. | |
| 434 """ | |
| 435 channel = TestChannel() | |
| 436 self._openChannel(channel) | |
| 437 d = self.conn.ssh_CHANNEL_REQUEST('\x00\x00\x00\x00' + common.NS( | |
| 438 'test') + '\xff') | |
| 439 def check(result): | |
| 440 self.assertEquals(self.transport.packets, | |
| 441 [(connection.MSG_CHANNEL_FAILURE, '\x00\x00\x00\xff' | |
| 442 )]) | |
| 443 d.addCallback(self.fail) | |
| 444 d.addErrback(check) | |
| 445 return d | |
| 446 | |
| 447 def test_CHANNEL_REQUEST_SUCCESS(self): | |
| 448 """ | |
| 449 Test that channel request success messages cause the Deferred to be | |
| 450 called back. | |
| 451 """ | |
| 452 channel = TestChannel() | |
| 453 self._openChannel(channel) | |
| 454 d = self.conn.sendRequest(channel, 'test', 'data', True) | |
| 455 self.conn.ssh_CHANNEL_SUCCESS('\x00\x00\x00\x00') | |
| 456 def check(result): | |
| 457 self.assertTrue(result) | |
| 458 return d | |
| 459 | |
| 460 def test_CHANNEL_REQUEST_FAILURE(self): | |
| 461 """ | |
| 462 Test that channel request failure messages cause the Deferred to be | |
| 463 erred back. | |
| 464 """ | |
| 465 channel = TestChannel() | |
| 466 self._openChannel(channel) | |
| 467 d = self.conn.sendRequest(channel, 'test', '', True) | |
| 468 self.conn.ssh_CHANNEL_FAILURE('\x00\x00\x00\x00') | |
| 469 def check(result): | |
| 470 self.assertEquals(result.value.value, 'channel request failed') | |
| 471 d.addCallback(self.fail) | |
| 472 d.addErrback(check) | |
| 473 return d | |
| 474 | |
| 475 def test_sendGlobalRequest(self): | |
| 476 """ | |
| 477 Test that global request messages are sent in the right format. | |
| 478 """ | |
| 479 d = self.conn.sendGlobalRequest('wantReply', 'data', True) | |
| 480 self.conn.sendGlobalRequest('noReply', '', False) | |
| 481 self.assertEquals(self.transport.packets, | |
| 482 [(connection.MSG_GLOBAL_REQUEST, common.NS('wantReply') + | |
| 483 '\xffdata'), | |
| 484 (connection.MSG_GLOBAL_REQUEST, common.NS('noReply') + | |
| 485 '\x00')]) | |
| 486 self.assertEquals(self.conn.deferreds, {'global':[d]}) | |
| 487 | |
| 488 def test_openChannel(self): | |
| 489 """ | |
| 490 Test that open channel messages are sent in the right format. | |
| 491 """ | |
| 492 channel = TestChannel() | |
| 493 self.conn.openChannel(channel, 'aaaa') | |
| 494 self.assertEquals(self.transport.packets, | |
| 495 [(connection.MSG_CHANNEL_OPEN, common.NS('TestChannel') + | |
| 496 '\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x80\x00aaaa')]) | |
| 497 self.assertEquals(channel.id, 0) | |
| 498 self.assertEquals(self.conn.localChannelID, 1) | |
| 499 | |
| 500 def test_sendRequest(self): | |
| 501 """ | |
| 502 Test that channel request messages are sent in the right format. | |
| 503 """ | |
| 504 channel = TestChannel() | |
| 505 self._openChannel(channel) | |
| 506 d = self.conn.sendRequest(channel, 'test', 'test', True) | |
| 507 self.conn.sendRequest(channel, 'test2', '', False) | |
| 508 channel.localClosed = True # emulate sending a close message | |
| 509 self.conn.sendRequest(channel, 'test3', '', True) | |
| 510 self.assertEquals(self.transport.packets, | |
| 511 [(connection.MSG_CHANNEL_REQUEST, '\x00\x00\x00\xff' + | |
| 512 common.NS('test') + '\x01test'), | |
| 513 (connection.MSG_CHANNEL_REQUEST, '\x00\x00\x00\xff' + | |
| 514 common.NS('test2') + '\x00')]) | |
| 515 self.assertEquals(self.conn.deferreds, {0:[d]}) | |
| 516 | |
| 517 def test_adjustWindow(self): | |
| 518 """ | |
| 519 Test that channel window adjust messages cause bytes to be added | |
| 520 to the window. | |
| 521 """ | |
| 522 channel = TestChannel(localWindow=5) | |
| 523 self._openChannel(channel) | |
| 524 channel.localWindowLeft = 0 | |
| 525 self.conn.adjustWindow(channel, 1) | |
| 526 self.assertEquals(channel.localWindowLeft, 1) | |
| 527 channel.localClosed = True | |
| 528 self.conn.adjustWindow(channel, 2) | |
| 529 self.assertEquals(channel.localWindowLeft, 1) | |
| 530 self.assertEquals(self.transport.packets, | |
| 531 [(connection.MSG_CHANNEL_WINDOW_ADJUST, '\x00\x00\x00\xff' | |
| 532 '\x00\x00\x00\x01')]) | |
| 533 | |
| 534 def test_sendData(self): | |
| 535 """ | |
| 536 Test that channel data messages are sent in the right format. | |
| 537 """ | |
| 538 channel = TestChannel() | |
| 539 self._openChannel(channel) | |
| 540 self.conn.sendData(channel, 'a') | |
| 541 channel.localClosed = True | |
| 542 self.conn.sendData(channel, 'b') | |
| 543 self.assertEquals(self.transport.packets, | |
| 544 [(connection.MSG_CHANNEL_DATA, '\x00\x00\x00\xff' + | |
| 545 common.NS('a'))]) | |
| 546 | |
| 547 def test_sendExtendedData(self): | |
| 548 """ | |
| 549 Test that channel extended data messages are sent in the right format. | |
| 550 """ | |
| 551 channel = TestChannel() | |
| 552 self._openChannel(channel) | |
| 553 self.conn.sendExtendedData(channel, 1, 'test') | |
| 554 channel.localClosed = True | |
| 555 self.conn.sendExtendedData(channel, 2, 'test2') | |
| 556 self.assertEquals(self.transport.packets, | |
| 557 [(connection.MSG_CHANNEL_EXTENDED_DATA, '\x00\x00\x00\xff' + | |
| 558 '\x00\x00\x00\x01' + common.NS('test'))]) | |
| 559 | |
| 560 def test_sendEOF(self): | |
| 561 """ | |
| 562 Test that channel EOF messages are sent in the right format. | |
| 563 """ | |
| 564 channel = TestChannel() | |
| 565 self._openChannel(channel) | |
| 566 self.conn.sendEOF(channel) | |
| 567 self.assertEquals(self.transport.packets, | |
| 568 [(connection.MSG_CHANNEL_EOF, '\x00\x00\x00\xff')]) | |
| 569 channel.localClosed = True | |
| 570 self.conn.sendEOF(channel) | |
| 571 self.assertEquals(self.transport.packets, | |
| 572 [(connection.MSG_CHANNEL_EOF, '\x00\x00\x00\xff')]) | |
| 573 | |
| 574 def test_sendClose(self): | |
| 575 """ | |
| 576 Test that channel close messages are sent in the right format. | |
| 577 """ | |
| 578 channel = TestChannel() | |
| 579 self._openChannel(channel) | |
| 580 self.conn.sendClose(channel) | |
| 581 self.assertTrue(channel.localClosed) | |
| 582 self.assertEquals(self.transport.packets, | |
| 583 [(connection.MSG_CHANNEL_CLOSE, '\x00\x00\x00\xff')]) | |
| 584 self.conn.sendClose(channel) | |
| 585 self.assertEquals(self.transport.packets, | |
| 586 [(connection.MSG_CHANNEL_CLOSE, '\x00\x00\x00\xff')]) | |
| 587 | |
| 588 channel2 = TestChannel() | |
| 589 self._openChannel(channel2) | |
| 590 channel2.remoteClosed = True | |
| 591 self.conn.sendClose(channel2) | |
| 592 self.assertTrue(channel2.gotClosed) | |
| 593 | |
| 594 def test_getChannelWithAvatar(self): | |
| 595 """ | |
| 596 Test that getChannel dispatches to the avatar when an avatar is | |
| 597 present. Correct functioning without the avatar is verified in | |
| 598 test_CHANNEL_OPEN. | |
| 599 """ | |
| 600 channel = self.conn.getChannel('TestChannel', 50, 30, 'data') | |
| 601 self.assertEquals(channel.data, 'data') | |
| 602 self.assertEquals(channel.remoteWindowLeft, 50) | |
| 603 self.assertEquals(channel.remoteMaxPacket, 30) | |
| 604 self.assertRaises(error.ConchError, self.conn.getChannel, | |
| 605 'BadChannel', 50, 30, 'data') | |
| 606 | |
| 607 def test_gotGlobalRequestWithoutAvatar(self): | |
| 608 """ | |
| 609 Test that gotGlobalRequests dispatches to global_* without an avatar. | |
| 610 """ | |
| 611 del self.transport.avatar | |
| 612 self.assertTrue(self.conn.gotGlobalRequest('TestGlobal', 'data')) | |
| 613 self.assertEquals(self.conn.gotGlobalRequest('Test-Data', 'data'), | |
| 614 (True, 'data')) | |
| 615 self.assertFalse(self.conn.gotGlobalRequest('BadGlobal', 'data')) | |
| OLD | NEW |