Ejemplo n.º 1
0
    def test_enqueue_without_tracer(self, _1, _2, patched_config):
        """Make sure we try to handle execution control requests.
        """
        def get_option(name):
            if name == "server.runOnSave":
                # Just to avoid starting the watcher for no reason.
                return False
            if name == "client.displayEnabled":
                return True
            if name == "runner.installTracer":
                return False
            raise RuntimeError("Unexpected argument to get_option: %s" % name)

        patched_config.get_option.side_effect = get_option

        rs = ReportSession(False, None, "", "", UploadedFileManager())
        mock_script_runner = MagicMock()
        mock_script_runner._install_tracer = ScriptRunner._install_tracer
        rs._scriptrunner = mock_script_runner

        rs.enqueue({"dontcare": 123})

        func = mock_script_runner.maybe_handle_execution_control_request

        # Expect func to be called only once, inside enqueue().
        func.assert_called_once()
Ejemplo n.º 2
0
    def test_enqueue_with_tracer(self, _1, _2, patched_config):
        """Make sure there is no lock contention when tracer is on.

        When the tracer is set up, we want
        maybe_handle_execution_control_request to be executed only once. There
        was a bug in the past where it was called twice: once from the tracer
        and once from the enqueue function. This caused a lock contention.
        """
        def get_option(name):
            if name == "server.runOnSave":
                # Just to avoid starting the watcher for no reason.
                return False
            if name == "client.displayEnabled":
                return True
            if name == "runner.installTracer":
                return True
            raise RuntimeError("Unexpected argument to get_option: %s" % name)

        patched_config.get_option.side_effect = get_option

        rs = ReportSession(False, None, "", "", UploadedFileManager())
        mock_script_runner = MagicMock()
        rs._scriptrunner = mock_script_runner

        rs.enqueue({"dontcare": 123})

        func = mock_script_runner.maybe_handle_execution_control_request

        # In reality, outside of a testing environment func should be called
        # once. But in this test we're actually not installing a tracer here,
        # since Report is mocked. So the correct behavior here is for func to
        # never be called. If you ever see it being called once here it's
        # likely because there's a bug in the enqueue function (which should
        # skip func when installTracer is on).
        func.assert_not_called()
Ejemplo n.º 3
0
    def _add_browser_connection(self, ws):
        """Register a connected browser with the server

        Parameters
        ----------
        ws : _BrowserWebSocketHandler or PREHEATED_REPORT_CONTEXT
            The newly-connected websocket handler

        Returns
        -------
        ReportSession
            The ReportSession associated with this browser connection

        """
        if ws not in self._session_infos:

            if PREHEATED_REPORT_SESSION in self._session_infos:
                assert len(self._session_infos) == 1
                LOGGER.debug("Reusing preheated context for ws %s", ws)
                session = self._session_infos[PREHEATED_REPORT_SESSION].session
                del self._session_infos[PREHEATED_REPORT_SESSION]
            else:
                LOGGER.debug("Creating new context for ws %s", ws)
                session = ReportSession(
                    ioloop=self._ioloop,
                    script_path=self._script_path,
                    command_line=self._command_line,
                )

            self._session_infos[ws] = SessionInfo(session)

            if ws is not PREHEATED_REPORT_SESSION:
                self._set_state(State.ONE_OR_MORE_BROWSERS_CONNECTED)

        return self._session_infos[ws].session
Ejemplo n.º 4
0
    def test_handle_save_request(self, _1):
        """Test that handle_save_request serializes files correctly."""
        # Create a ReportSession with some mocked bits
        rs = ReportSession(False, self.io_loop, "mock_report.py", "",
                           UploadedFileManager())
        rs._report.report_id = "TestReportID"

        orig_ctx = get_report_ctx()
        ctx = ReportContext("TestSessionID", rs._report.enqueue, None, None,
                            None)
        add_report_ctx(ctx=ctx)

        rs._scriptrunner = MagicMock()

        storage = MockStorage()
        rs._storage = storage

        # Send two deltas: empty and markdown
        st.empty()
        st.markdown("Text!")

        yield rs.handle_save_request(_create_mock_websocket())

        # Check the order of the received files. Manifest should be last.
        self.assertEqual(3, len(storage.files))
        self.assertEqual("reports/TestReportID/0.pb", storage.get_filename(0))
        self.assertEqual("reports/TestReportID/1.pb", storage.get_filename(1))
        self.assertEqual("reports/TestReportID/manifest.pb",
                         storage.get_filename(2))

        # Check the manifest
        manifest = storage.get_message(2, StaticManifest)
        self.assertEqual("mock_report", manifest.name)
        self.assertEqual(2, manifest.num_messages)
        self.assertEqual(StaticManifest.DONE, manifest.server_status)

        # Check that the deltas we sent match messages in storage
        sent_messages = rs._report._master_queue._queue
        received_messages = [
            storage.get_message(0, ForwardMsg),
            storage.get_message(1, ForwardMsg),
        ]

        self.assertEqual(sent_messages, received_messages)

        add_report_ctx(ctx=orig_ctx)
Ejemplo n.º 5
0
    def _create_or_reuse_report_session(self, ws):
        """Register a connected browser with the server.

        Parameters
        ----------
        ws : _BrowserWebSocketHandler or None
            The newly-connected websocket handler or None if preheated
            connection.

        Returns
        -------
        ReportSession
            The newly-created ReportSession for this browser connection.

        """
        if self._preheated_session_id is not None:
            assert len(self._session_info_by_id) == 1
            assert ws is not None

            session_id = self._preheated_session_id
            self._preheated_session_id = None

            session_info = self._session_info_by_id[session_id]
            session_info.ws = ws
            session = session_info.session

            LOGGER.debug(
                "Reused preheated session for ws %s. Session ID: %s", id(ws), session_id
            )

        else:
            session = ReportSession(
                ioloop=self._ioloop,
                script_path=self._script_path,
                command_line=self._command_line,
                uploaded_file_manager=self._uploaded_file_mgr,
            )

            LOGGER.debug(
                "Created new session for ws %s. Session ID: %s", id(ws), session.id
            )

            assert session.id not in self._session_info_by_id, (
                "session.id '%s' registered multiple times!" % session.id
            )

        self._session_info_by_id[session.id] = SessionInfo(ws, session)

        if ws is None:
            self._preheated_session_id = session.id
        else:
            self._set_state(State.ONE_OR_MORE_BROWSERS_CONNECTED)

        return session
Ejemplo n.º 6
0
    def test_shutdown(self, _1):
        """Test that ReportSession.shutdown behaves sanely."""
        file_mgr = MagicMock(spec=UploadedFileManager)
        rs = ReportSession(False, None, "", "", file_mgr)

        rs.shutdown()
        self.assertEquals(ReportSessionState.SHUTDOWN_REQUESTED, rs._state)
        file_mgr.remove_session_files.assert_called_once_with(rs.id)

        # A 2nd shutdown call should have no effect.
        rs.shutdown()
        self.assertEquals(ReportSessionState.SHUTDOWN_REQUESTED, rs._state)
        file_mgr.remove_session_files.assert_called_once_with(rs.id)
Ejemplo n.º 7
0
    def _create_report_session(self, ws):
        """Register a connected browser with the server.

        Parameters
        ----------
        ws : _BrowserWebSocketHandler or None
            The newly-connected websocket handler or None if preheated
            connection.

        Returns
        -------
        ReportSession
            The newly-created ReportSession for this browser connection.

        """
        if PREHEATED_ID in self._session_info_by_id:
            assert len(self._session_info_by_id) == 1
            LOGGER.debug("Reusing preheated context for ws %s", ws)
            session = self._session_info_by_id[PREHEATED_ID].session
            del self._session_info_by_id[PREHEATED_ID]
            session.id = 0
        else:
            LOGGER.debug("Creating new context for ws %s", ws)
            session = ReportSession(
                is_preheat=(ws is None),
                ioloop=self._ioloop,
                script_path=self._script_path,
                command_line=self._command_line,
                uploaded_file_manager=self._uploaded_file_mgr,
            )

        assert session.id not in self._session_info_by_id, (
            "session.id '%s' registered multiple times!" % session.id)

        self._session_info_by_id[session.id] = SessionInfo(ws, session)

        if ws is not None:
            self._set_state(State.ONE_OR_MORE_BROWSERS_CONNECTED)

        return session
Ejemplo n.º 8
0
 def test_unique_id(self, _1):
     """Each ReportSession should have a unique ID"""
     file_mgr = MagicMock(spec=UploadedFileManager)
     rs1 = ReportSession(False, None, "", "", file_mgr)
     rs2 = ReportSession(False, None, "", "", file_mgr)
     self.assertNotEquals(rs1.id, rs2.id)