tempest/tempest/tests/common/test_compute.py
jianghua wang d22514a522 Handle the case that RFP negotiation message arrived early.
The RFP server will send RFP negotiation message to client once
connection is setup. In some case this message may arrive before
it retrieve the response for WebSocket upgrade. Then it will cause
issues for the following RFP verification as no more RFP negotiation
initial message will arrive.
This commit will cache the data if the above case happened. Defined
a new function _recv() which will read from the cached buff if it has
data, otherwise read from the socket.

Change-Id: Icc3f312156b8d2cee6e0500218edf5d8b991ade7
Closes-Bug: #1691185
2017-06-26 22:37:32 +00:00

107 lines
4.1 KiB
Python

# Copyright 2017 Citrix Systems
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from six.moves.urllib import parse as urlparse
import mock
from tempest.common import compute
from tempest.tests import base
class TestCompute(base.TestCase):
def setUp(self):
super(TestCompute, self).setUp()
self.client_sock = mock.Mock()
self.url = urlparse.urlparse("http://www.fake.com:80")
def test_rfp_frame_not_cached(self):
# rfp negotiation frame arrived separately after upgrade
# response, so it's not cached.
RFP_VERSION = b'RFB.003.003\x0a'
rfp_frame_header = b'\x82\x0c'
self.client_sock.recv.side_effect = [
b'fake response start\r\n',
b'fake response end\r\n\r\n',
rfp_frame_header,
RFP_VERSION]
expect_response = b'fake response start\r\nfake response end\r\n\r\n'
webSocket = compute._WebSocket(self.client_sock, self.url)
self.assertEqual(webSocket.response, expect_response)
# no cache
self.assertEqual(webSocket.cached_stream, b'')
self.client_sock.recv.assert_has_calls([mock.call(4096),
mock.call(4096)])
self.client_sock.recv.reset_mock()
recv_version = webSocket.receive_frame()
self.assertEqual(recv_version, RFP_VERSION)
self.client_sock.recv.assert_has_calls([mock.call(2),
mock.call(12)])
def test_rfp_frame_fully_cached(self):
RFP_VERSION = b'RFB.003.003\x0a'
rfp_version_frame = b'\x82\x0c%s' % RFP_VERSION
self.client_sock.recv.side_effect = [
b'fake response start\r\n',
b'fake response end\r\n\r\n%s' % rfp_version_frame]
expect_response = b'fake response start\r\nfake response end\r\n\r\n'
webSocket = compute._WebSocket(self.client_sock, self.url)
self.client_sock.recv.assert_has_calls([mock.call(4096),
mock.call(4096)])
self.assertEqual(webSocket.response, expect_response)
self.assertEqual(webSocket.cached_stream, rfp_version_frame)
self.client_sock.recv.reset_mock()
recv_version = webSocket.receive_frame()
self.client_sock.recv.assert_not_called()
self.assertEqual(recv_version, RFP_VERSION)
# cached_stream should be empty in the end.
self.assertEqual(webSocket.cached_stream, b'')
def test_rfp_frame_partially_cached(self):
RFP_VERSION = b'RFB.003.003\x0a'
rfp_version_frame = b'\x82\x0c%s' % RFP_VERSION
frame_part1 = rfp_version_frame[:6]
frame_part2 = rfp_version_frame[6:]
self.client_sock.recv.side_effect = [
b'fake response start\r\n',
b'fake response end\r\n\r\n%s' % frame_part1,
frame_part2]
expect_response = b'fake response start\r\nfake response end\r\n\r\n'
webSocket = compute._WebSocket(self.client_sock, self.url)
self.client_sock.recv.assert_has_calls([mock.call(4096),
mock.call(4096)])
self.assertEqual(webSocket.response, expect_response)
self.assertEqual(webSocket.cached_stream, frame_part1)
self.client_sock.recv.reset_mock()
recv_version = webSocket.receive_frame()
self.client_sock.recv.assert_called_once_with(len(frame_part2))
self.assertEqual(recv_version, RFP_VERSION)
# cached_stream should be empty in the end.
self.assertEqual(webSocket.cached_stream, b'')