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()
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()
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
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)
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
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)
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
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)