Пример #1
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()
Пример #2
0
    def __init__(self, ioloop, script_path, command_line):
        """Create the server. It won't be started yet.

        Parameters
        ----------
        ioloop : tornado.ioloop.IOLoop
        script_path : str
        command_line : str

        """
        if Server._singleton is not None:
            raise RuntimeError(
                "Server already initialized. Use .get_current() instead")

        Server._singleton = self

        _set_tornado_log_levels()

        self._ioloop = ioloop
        self._script_path = script_path
        self._command_line = command_line

        # Mapping of ReportSession.id -> SessionInfo.
        self._session_info_by_id = {}

        self._must_stop = threading.Event()
        self._state = None
        self._set_state(State.INITIAL)
        self._message_cache = ForwardMsgCache()
        self._uploaded_file_mgr = UploadedFileManager()
        self._uploaded_file_mgr.on_files_added.connect(self._on_file_uploaded)
        self._report = None  # type: Optional[Report]
Пример #3
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()
    def test_msg_hash(self):
        """Test that ForwardMsg hash generation works as expected"""

        widget_idA = "A0123456789"
        widget_idB = "B0123456789"
        file_name = "example_file.png"
        file_bytes = bytearray(
            "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789",
            "utf-8",
        )
        uploaded_file_mgr = UploadedFileManager()

        uploaded_file_mgr.create_or_clear_file(widget_idA, file_name,
                                               len(file_bytes), date.today(),
                                               1)
        uploaded_file_mgr.create_or_clear_file(widget_idB, file_name,
                                               len(file_bytes), date.today(),
                                               2)

        progress_a = uploaded_file_mgr.process_chunk(widget_idA, 0, file_bytes)
        self.assertEqual(progress_a, 1)

        progress_b = uploaded_file_mgr.process_chunk(widget_idB, 0,
                                                     file_bytes[0:50])
        self.assertEqual(progress_b, 0.5)

        progress_b = uploaded_file_mgr.process_chunk(widget_idB, 1,
                                                     file_bytes[50:100])
        self.assertEqual(progress_b, 1)

        progress_a, data_a = uploaded_file_mgr.get_data(widget_idA)
        progress_b, data_b = uploaded_file_mgr.get_data(widget_idB)
        self.assertEqual(progress_a, 100)
        self.assertEqual(progress_b, 100)
        self.assertEqual(len(data_a), len(file_bytes))
        self.assertEqual(data_a, file_bytes)
        self.assertEqual(data_a, data_b)

        uploaded_file_mgr.delete_file(widget_idA)

        progress_a, data_a = uploaded_file_mgr.get_data(widget_idA)
        self.assertEqual(progress_a, 0)
        self.assertEqual(data_a, None)

        uploaded_file_mgr.delete_all_files()
        progress_b, data_b = uploaded_file_mgr.get_data(widget_idB)
        self.assertEqual(progress_b, 0)
        self.assertEqual(data_b, None)
Пример #5
0
    def setUp(self, override_root=True):
        self.report_queue = ReportQueue()
        self.override_root = override_root
        self.orig_report_ctx = None

        if self.override_root:
            self.orig_report_ctx = get_report_ctx()
            add_report_ctx(
                threading.current_thread(),
                ReportContext(
                    enqueue=self.report_queue.enqueue,
                    widgets=Widgets(),
                    widget_ids_this_run=_WidgetIDSet(),
                    uploaded_file_mgr=UploadedFileManager(),
                ),
            )
Пример #6
0
    def __init__(self, ioloop, script_path, command_line):
        """Initialize the ReportSession.

        Parameters
        ----------
        ioloop : tornado.ioloop.IOLoop
            The Tornado IOLoop that we're running within.

        script_path : str
            Path of the Python file from which this report is generated.

        command_line : str
            Command line as input by the user.

        """
        # Each ReportSession gets a unique ID
        self.id = ReportSession._next_id
        ReportSession._next_id += 1

        self._ioloop = ioloop
        self._report = Report(script_path, command_line)

        self._state = ReportSessionState.REPORT_NOT_RUNNING

        self._uploaded_file_mgr = UploadedFileManager()

        self._main_dg = DeltaGenerator(enqueue=self.enqueue, container=BlockPath.MAIN)
        self._sidebar_dg = DeltaGenerator(
            enqueue=self.enqueue, container=BlockPath.SIDEBAR
        )

        self._widget_states = WidgetStates()
        self._local_sources_watcher = LocalSourcesWatcher(
            self._report, self._on_source_file_changed
        )
        self._sent_initialize_message = False
        self._storage = None
        self._maybe_reuse_previous_run = False
        self._run_on_save = config.get_option("server.runOnSave")

        # The ScriptRequestQueue is the means by which we communicate
        # with the active ScriptRunner.
        self._script_request_queue = ScriptRequestQueue()

        self._scriptrunner = None

        LOGGER.debug("ReportSession initialized (id=%s)", self.id)
Пример #7
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)
Пример #8
0
    def setUp(self, override_root=True):
        self.report_queue = ReportQueue()

        if override_root:
            main_dg = self.new_delta_generator()
            sidebar_dg = self.new_delta_generator(container=BlockPath.SIDEBAR)
            setattr(
                threading.current_thread(),
                REPORT_CONTEXT_ATTR_NAME,
                ReportContext(
                    main_dg=main_dg,
                    sidebar_dg=sidebar_dg,
                    widgets=Widgets(),
                    widget_ids_this_run=_WidgetIDSet(),
                    uploaded_file_mgr=UploadedFileManager(),
                ),
            )
 def setUp(self):
     self.mgr = UploadedFileManager()
     self.filemgr_events = []
     self.mgr.on_files_added.connect(self._on_files_added)
 def get_app(self):
     self.file_mgr = UploadedFileManager()
     return tornado.web.Application([("/upload_file",
                                      UploadFileRequestHandler,
                                      dict(file_mgr=self.file_mgr))])