Пример #1
0
    def test_server_session_timeout_async(self):
        application = Application()
        with ManagedServerLoop(application) as server:
            doc = document.Document()
            doc.add_root(DictModel())

            client_session = push_session(
                doc,
                session_id='test_server_session_timeout_async',
                url=url(server),
                io_loop=server.io_loop)
            server_session = server.get_session('/', client_session.id)

            result = next(iter(server_session.document.roots))

            @gen.coroutine
            def cb():
                # we're testing that we can modify the doc and be
                # "inside" the document lock
                result.values['a'] = 0
                result.values['b'] = yield self.async_value(1)
                result.values['c'] = yield self.async_value(2)
                result.values['d'] = yield self.async_value(3)
                result.values['e'] = yield self.async_value(4)
                client_session.close()
                raise gen.Return(5)

            cb_id = server_session.document.add_timeout_callback(cb, 10)

            client_session._loop_until_closed()

            with pytest.raises(ValueError) as exc:
                server_session.document.remove_timeout_callback(cb_id)
            assert 'already removed' in repr(exc.value)

            assert dict(a=0, b=1, c=2, d=3, e=4) == result.values
Пример #2
0
    def test_lots_of_concurrent_messages(self, ManagedServerLoop):
        application = Application()

        def setup_stuff(doc):
            m1 = AnotherModelInTestClientServer(bar=43, name='m1')
            m2 = SomeModelInTestClientServer(foo=42, name='m2')
            m3 = SomeModelInTestClientServer(foo=68, name='m3')
            doc.add_root(m1)
            doc.add_root(m2)
            doc.add_root(m3)

            def timeout1():
                m1.bar += 1

            timeout1_cb_id = doc.add_timeout_callback(timeout1, 1)

            def timeout2():
                m2.foo += 1

            timeout2_cb_id = doc.add_timeout_callback(timeout2, 3)

            def periodic1():
                m1.bar += 1
                doc.remove_timeout_callback(timeout1_cb_id)
                doc.add_timeout_callback(timeout1, m1.bar % 7)

            doc.add_periodic_callback(periodic1, 3)

            def periodic2():
                m2.foo += 1
                doc.remove_timeout_callback(timeout2_cb_id)
                doc.add_timeout_callback(timeout2, m2.foo % 7)

            doc.add_periodic_callback(periodic2, 1)

            def server_on_change(event):
                if isinstance(event, ModelChangedEvent) and event.model is m3:
                    return
                m3.foo += 1

            doc.on_change(server_on_change)

        handler = FunctionHandler(setup_stuff)
        application.add(handler)

        # keep_alive_milliseconds=1 sends pings as fast as the OS will let us
        with ManagedServerLoop(application,
                               keep_alive_milliseconds=1) as server:
            session = pull_session(
                session_id='test_lots_of_concurrent_messages',
                url=url(server),
                io_loop=server.io_loop)
            assert session.connected

            server_session = server.get_session('/', session.id)

            def client_timeout():
                m = session.document.roots[0]
                m.name = m.name[::-1]

            cb_id = session.document.add_timeout_callback(client_timeout, 3)

            def client_periodic():
                m = session.document.roots[1]
                m.name = m.name[::-1]
                session.document.remove_timeout_callback(cb_id)
                session.document.add_timeout_callback(client_timeout, 3)

            session.document.add_periodic_callback(client_periodic, 1)

            result = {}

            def end_test():
                result['connected'] = session.connected
                result[
                    'server_connection_count'] = server_session.connection_count
                result['server_close_code'] = next(
                    iter(server._tornado._clients))._socket.close_code
                result['doc'] = session.document.to_json()
                session.close()

            # making this longer is more likely to trigger bugs, but it also
            # makes the test take however much time you put here
            session.document.add_timeout_callback(end_test, 250)

            def client_on_change(event):
                if not isinstance(event, TitleChangedEvent):
                    session.document.title = session.document.title[::-1]

            session.document.on_change(client_on_change)

            session._loop_until_closed()

            assert not session.connected

            # we should have still been connected at the end,
            # if we didn't have any crazy protocol errors
            assert 'connected' in result
            assert result['connected']

            # server should also still have been connected
            assert result['server_connection_count'] == 1
            assert result['server_close_code'] is None
Пример #3
0
    def test_server_changes_go_to_client(self, ManagedServerLoop):
        application = Application()
        with ManagedServerLoop(application) as server:
            doc = document.Document()

            client_session = push_session(
                doc,
                session_id='test_server_changes_go_to_client',
                url=url(server),
                io_loop=server.io_loop)
            server_session = server.get_session('/', client_session.id)

            assert len(client_session.document.roots) == 0
            server_root = SomeModelInTestClientServer(foo=42)

            def do_add_server_root():
                server_session.document.add_root(server_root)

            server.io_loop.spawn_callback(server_session.with_document_locked,
                                          do_add_server_root)

            def client_has_root():
                return len(doc.roots) > 0

            client_session._connection._loop_until(client_has_root)
            client_root = next(iter(client_session.document.roots))

            assert client_root.foo == 42
            assert server_root.foo == 42

            # Now try setting title on server side
            def do_set_server_title():
                server_session.document.title = "Server Title"

            server.io_loop.spawn_callback(server_session.with_document_locked,
                                          do_set_server_title)

            def client_title_set():
                return client_session.document.title != document.DEFAULT_TITLE

            client_session._connection._loop_until(client_title_set)

            assert client_session.document.title == "Server Title"

            # Now modify a model within the server document
            def do_set_property_on_server():
                server_root.foo = 57

            server.io_loop.spawn_callback(server_session.with_document_locked,
                                          do_set_property_on_server)

            # there is no great way to block until the server
            # has applied changes, since patches are sent
            # asynchronously. We use internal _loop_until API.
            def client_change_made():
                return client_root.foo == 57

            client_session._connection._loop_until(client_change_made)
            assert client_root.foo == 57

            def do_remove_server_root():
                server_session.document.remove_root(server_root)

            server.io_loop.spawn_callback(server_session.with_document_locked,
                                          do_remove_server_root)

            def client_lacks_root():
                return len(doc.roots) == 0

            client_session._connection._loop_until(client_lacks_root)
            assert len(client_session.document.roots) == 0

            client_session.close()
            client_session._loop_until_closed()
            assert not client_session.connected
Пример #4
0
 async def check_http_gets(self, server):
     await http_get(server.io_loop, url(server))
     await http_get(server.io_loop,
                    url(server) + "autoload.js?bokeh-autoload-element=foo")
Пример #5
0
def test_unit_spec_changes_do_not_boomerang(monkeypatch, ManagedServerLoop):
    application = Application()
    with ManagedServerLoop(application) as server:
        doc = document.Document()
        client_root = UnitsSpecModel()
        doc.add_root(client_root)

        client_session = push_session(
            doc,
            session_id='test_unit_spec_changes_do_not_boomerang',
            url=url(server),
            io_loop=server.io_loop)
        server_session = server.get_session('/', client_session.id)

        assert len(server_session.document.roots) == 1
        server_root = next(iter(server_session.document.roots))

        assert client_root.distance == 42
        assert server_root.angle == 0

        def change_to(new_distance, new_angle):
            got_angry = {}
            got_angry['result'] = None

            # trap any boomerang
            def get_angry(message):
                got_angry['result'] = message

            monkeypatch.setattr(client_session, '_handle_patch', get_angry)

            server_previous_distance = server_root.distance
            server_previous_angle = server_root.angle

            # Now modify the client document
            client_root.distance = new_distance
            client_root.angle = new_angle

            # wait until server side change made ... but we may not have the
            # boomerang yet
            def server_change_made():
                return server_root.distance != server_previous_distance and \
                    server_root.angle != server_previous_angle

            client_session._connection._loop_until(server_change_made)

            # force a round trip to be sure we get the boomerang if we're going to
            client_session.force_roundtrip()

            assert got_angry['result'] is None

        change_to(57, 1)
        change_to({'value': 58}, {'value': 2})
        change_to({'field': 'foo'}, {'field': 'bar'})
        change_to({
            'value': 59,
            'units': 'screen'
        }, {
            'value': 30,
            'units': 'deg'
        })

        client_session.close()
        client_session._loop_until_closed()
        assert not client_session.connected
        server.unlisten()  # clean up so next test can run
Пример #6
0
 async def check_http_gets_fail(self, server):
     with pytest.raises(HTTPError):
         await http_get(server.io_loop, url(server))
     with pytest.raises(HTTPError):
         await http_get(server.io_loop, url(server) + "autoload.js?bokeh-autoload-element=foo")