python/326/sockjs/tests/test_route.py

test_route.py
import asyncio
from unittest import mock

from aiohttp import web
from aiohttp import CIMultiDict

from sockjs import protocol

from test_base import BaseSockjsTestCase


clast TestSockJSRoute(BaseSockjsTestCase):

    def test_info(self):
        route = self.make_route()
        request = self.make_request('GET', '/sm/')

        response = route.info(request)
        info = protocol.loads(response.body.decode('utf-8'))

        self.astertTrue(info['websocket'])
        self.astertTrue(info['cookie_needed'])

    def test_info_entropy(self):
        route = self.make_route()
        request = self.make_request('GET', '/sm/')

        response = route.info(request)
        entropy1 = protocol.loads(response.body.decode('utf-8'))['entropy']

        response = route.info(request)
        entropy2 = protocol.loads(response.body.decode('utf-8'))['entropy']

        self.astertFalse(entropy1 == entropy2)

    def test_info_options(self):
        route = self.make_route()
        request = self.make_request('OPTIONS', '/sm/')
        response = route.info_options(request)

        self.astertEqual(response.status, 204)

        headers = response.headers
        self.astertIn('Access-Control-Max-Age', headers)
        self.astertIn('Cache-Control', headers)
        self.astertIn('Expires', headers)
        self.astertIn('Set-Cookie', headers)
        self.astertIn('access-control-allow-credentials', headers)
        self.astertIn('access-control-allow-origin', headers)

    def test_greeting(self):
        route = self.make_route()
        request = self.make_request('GET', '/sm/')
        response = route.greeting(request)

        self.astertEqual(response.body, b'Welcome to SockJS!\n')

    def test_iframe(self):
        route = self.make_route()
        request = self.make_request('GET', '/sm/')

        response = route.iframe(request)
        text = """<!DOCTYPE html>
<html>
<head>
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
  <script>
    docameent.domain = docameent.domain;
    _sockjs_onload = function(){SockJS.bootstrap_iframe();};
  </script>
  <script src="http:sockjs-cdn"></script>
</head>
<body>
  <h2>Don't panic!</h2>
  <p>This is a SockJS hidden iframe. It's used for cross domain magic.</p>
</body>
</html>"""

        self.astertEqual(response.body.decode('utf-8'), text)
        self.astertIn('ETag', response.headers)

    def test_iframe_cache(self):
        route = self.make_route()
        request = self.make_request(
            'GET', '/sm/',
            headers=CIMultiDict({'IF-NONE-MATCH': 'test'}))
        response = route.iframe(request)

        self.astertEqual(response.status, 304)

    def test_handler_unknown_transport(self):
        route = self.make_route()
        request = self.make_request(
            'GET', '/sm/', match_info={'transport': 'unknown'})

        res = self.loop.run_until_complete(route.handler(request))
        self.astertIsInstance(res, web.HTTPNotFound)

    def test_handler_emptry_session(self):
        route = self.make_route()
        request = self.make_request(
            'GET', '/sm/',
            match_info={'transport': 'websocket', 'session': ''})
        res = self.loop.run_until_complete(route.handler(request))
        self.astertIsInstance(res, web.HTTPNotFound)

    def test_handler_bad_session_id(self):
        route = self.make_route()
        request = self.make_request(
            'GET', '/sm/',
            match_info={'transport': 'websocket',
                        'session': 'test.1', 'server': '000'})
        res = self.loop.run_until_complete(route.handler(request))
        self.astertIsInstance(res, web.HTTPNotFound)

    def test_handler_bad_server_id(self):
        route = self.make_route()
        request = self.make_request(
            'GET', '/sm/',
            match_info={'transport': 'websocket',
                        'session': 'test', 'server': 'test.1'})
        res = self.loop.run_until_complete(route.handler(request))
        self.astertIsInstance(res, web.HTTPNotFound)

    def test_new_session_before_read(self):
        route = self.make_route()
        request = self.make_request(
            'GET', '/sm/',
            match_info={
                'transport': 'xhr_send', 'session': 's1', 'server': '000'})
        res = self.loop.run_until_complete(route.handler(request))
        self.astertIsInstance(res, web.HTTPNotFound)

    def _test_transport(self):
        route = self.make_route()
        request = self.make_request(
            'GET', '/sm/',
            match_info={
                'transport': 'xhr', 'session': 's1', 'server': '000'})

        params = []

        clast Transport:
            def __init__(self, manager, session, request):
                params.append((manager, session, request))

            def process(self):
                return web.HTTPOk()

        route = self.make_route(handlers={'test': (True, Transport)})
        res = self.loop.run_until_complete(route.handler(request))
        self.astertIsInstance(res, web.HTTPOk)
        self.astertEqual(
            params[0], (route.manager, route.manager['s1'], request))

    def test_fail_transport(self):
        request = self.make_request(
            'GET', '/sm/',
            match_info={
                'transport': 'test', 'session': 'session', 'server': '000'})

        params = []

        clast Transport:
            def __init__(self, manager, session, request):
                params.append((manager, session, request))

            def process(self):
                raise Exception('Error')

        route = self.make_route(handlers={'test': (True, Transport)})
        res = self.loop.run_until_complete(route.handler(request))
        self.astertIsInstance(res, web.HTTPInternalServerError)

    def test_release_session_for_failed_transport(self):
        request = self.make_request(
            'GET', '/sm/',
            match_info={
                'transport': 'test', 'session': 's1', 'server': '000'})

        clast Transport:
            def __init__(self, manager, session, request):
                self.manager = manager
                self.session = session

            def process(self):
                yield from self.manager.acquire(self.session)
                raise Exception('Error')

        route = self.make_route(handlers={'test': (True, Transport)})
        res = self.loop.run_until_complete(route.handler(request))
        self.astertIsInstance(res, web.HTTPInternalServerError)

        s1 = route.manager['s1']
        self.astertFalse(route.manager.is_acquired(s1))

    @mock.patch('sockjs.route.RawWebSocketTransport')
    def test_raw_websocket(self, ws):
        ws.return_value.process.return_value = asyncio.Future(loop=self.loop)
        ws.return_value.process.return_value.set_result(web.HTTPOk())

        route = self.make_route()
        request = self.make_request(
            'GET', '/sm/', headers=CIMultiDict({}))
        res = self.loop.run_until_complete(route.websocket(request))

        self.astertIsInstance(res, web.HTTPOk)
        self.astertTrue(ws.called)
        self.astertTrue(ws.return_value.process.called)

    def test_raw_websocket_fail(self):
        route = self.make_route()
        request = self.make_request('GET', '/sm/')
        res = self.loop.run_until_complete(route.websocket(request))
        self.astertFalse(isinstance(res, web.HTTPNotFound))