예제 #1
0
    def test_204_transport_auto_reopen_with_close(self):
        """Transport process shouldn't reopen after being closed via close()."""
        transport = mock.MagicMock(spec=fake_transport.FakeTransport)
        transport._properties = {}
        transport._properties[transport_properties.AUTO_REOPEN] = True
        transport._transport_open = mock.MagicMock(
            spec=multiprocessing_utils.get_context().Event())
        transport.is_open.side_effect = iter([False, False])
        self.uut = transport_process.TransportProcess(
            "fake_transport",
            self.exception_queue,
            self.command_queue,
            self.log_queue,
            transport,
            call_result_queue=self.call_result_queue)

        self.uut._pre_run_hook()
        transport.open.assert_called_once()

        self.command_queue.put((transport_process.CMD_TRANSPORT_CLOSE, None))
        wait_for_queue_writes(self.command_queue)
        self.uut._do_work()
        transport.close.assert_called()

        self.uut._do_work()  # Shouldn't reopen here

        self.uut._post_run_hook()
        transport.open.assert_called_once()
예제 #2
0
    def test_240_transport_sleeps_if_not_open(self):
        """Test transport read can retain partial log lines."""
        transport = fake_transport.FakeTransport()
        transport.set_property(transport_properties.OPEN_ON_START, False)
        read_timeout = 0.03
        self.uut = transport_process.TransportProcess(
            "fake_transport",
            self.exception_queue,
            self.command_queue,
            self.log_queue,
            transport,
            call_result_queue=self.call_result_queue,
            read_timeout=read_timeout)

        device_data1 = "partial log line\r"
        transport.reads.put(device_data1)
        wait_for_queue_writes(transport.reads)
        self.uut._pre_run_hook()
        start_time = time.time()
        self.uut._do_work()
        end_time = time.time()
        self.assertFalse(
            self.uut.is_open(),
            "Expected transport process to be closed, found open")
        self.uut._post_run_hook()

        self.assertGreater(
            end_time - start_time, read_timeout,
            "Expected transport to sleep for > {}s, found {}s".format(
                read_timeout, end_time - start_time))
예제 #3
0
    def test_211_transport_writes_split_commands(self):
        """Test transport writes split commands."""
        transport = mock.MagicMock(spec=fake_transport.FakeTransport)
        transport.read.return_value = (
            b"this will be a really long command that "
            b"will be split")

        self.uut = transport_process.TransportProcess(
            "fake_transport",
            self.exception_queue,
            self.command_queue,
            self.log_queue,
            transport,
            call_result_queue=self.call_result_queue)

        self.uut._pre_run_hook()
        long_command = "this will be a really long command that will be split"
        self.uut.send_command(transport_process.CMD_TRANSPORT_WRITE,
                              long_command)
        wait_for_queue_writes(self.command_queue)
        self.uut._do_work()
        self.uut._do_work()
        self.uut._post_run_hook()

        self.assertEqual(
            2, transport.write.call_count,
            "Expecting write to be called twice, found {}".format(
                transport.write.call_count))
예제 #4
0
    def test_205_transport_auto_reopen_unexpected_close(self):
        """Test transport process reopens if it closes unexpectedly."""
        transport = mock.MagicMock(spec=fake_transport.FakeTransport)
        transport._properties = {}
        transport._properties[transport_properties.AUTO_REOPEN] = True
        transport._transport_open = mock.MagicMock(
            spec=multiprocessing_utils.get_context().Event())
        transport.is_open.side_effect = iter([False])
        self.uut = transport_process.TransportProcess(
            "fake_transport",
            self.exception_queue,
            self.command_queue,
            self.log_queue,
            transport,
            call_result_queue=self.call_result_queue)

        self.uut._pre_run_hook()
        transport.open.assert_called_once()

        self.uut._do_work()  # Should reopen here
        self.assertEqual(
            2, transport.open.call_count,
            "Expected transport.open to be called {} called {}".format(
                2, transport.open.call_count))
        # If transport closes unexpectedly, transport.close() should be called
        # before re-opening the transport to clean up resources (b/183527797).
        transport.close.assert_called_once()

        self.uut._post_run_hook()
        self.assertEqual(transport.close.call_count, 2)
예제 #5
0
    def test_202_transport_opens_transport_on_command(self):
        """Test transport opens transport on command."""
        transport = mock.MagicMock(spec=fake_transport.FakeTransport)
        self.uut = transport_process.TransportProcess(
            "fake_transport",
            self.exception_queue,
            self.command_queue,
            self.log_queue,
            transport,
            call_result_queue=self.call_result_queue)

        self.command_queue.put((transport_process.CMD_TRANSPORT_OPEN, None))
        wait_for_queue_writes(self.command_queue)
        self.uut._pre_run_hook()
        self.assertTrue(
            self.uut.is_open(),
            "Expected transport process to be opened, found closed")
        self.uut._do_work()
        self.assertTrue(
            self.uut.is_open(),
            "Expected transport process to be opened, found closed")
        self.uut._post_run_hook()
        self.assertEqual(
            2, transport.open.call_count,
            "Expected transport.open to be called {} called {}".format(
                2, transport.open.call_count))
        transport.close.assert_called_once()
예제 #6
0
 def test_120_transport_get_raw_data_raises_error(self):
     """Test get_raw_data raises error."""
     transport = None
     self.uut = transport_process.TransportProcess(
         "fake_transport",
         self.exception_queue,
         self.command_queue,
         self.log_queue,
         transport,
         call_result_queue=self.call_result_queue)
     with self.assertRaisesRegex(RuntimeError, r"No queue provided"):
         self.uut.get_raw_data()
예제 #7
0
 def test_000_transport_construct_destruct(self):
     """Test TransportProcess constructing and destructing raises no errors."""
     transport = None
     self.uut = transport_process.TransportProcess(
         "fake_transport",
         self.exception_queue,
         self.command_queue,
         self.log_queue,
         transport,
         call_result_queue=self.call_result_queue)
     self.assertFalse(self.uut.is_started(),
                      "Expected process not started, found started")
     self.assertFalse(self.uut.is_running(),
                      "Expected process to not running, found running")
예제 #8
0
    def test_300_transport_exceeds_maximum_baudrate_required(self):
        """Test baud rate which exceeds the maximum baud rate of 921600."""

        baudrate = 115200 * 10
        minimum_bytes_per_second = 115200 * 8 / 10
        transport = fake_transport.FakeTransport(baudrate=baudrate,
                                                 generate_lines=True)
        self.uut = transport_process.TransportProcess(
            "fake_transport",
            self.exception_queue,
            self.command_queue,
            self.log_queue,
            transport,
            call_result_queue=self.call_result_queue,
            raw_data_queue=self.raw_data_queue)
        self.uut.toggle_raw_data()
        start_time = time.time()
        end_time = start_time + 5.0
        self.uut._pre_run_hook()
        while time.time() < end_time:
            self.uut._do_work()
        finish_time = time.time()
        self.uut._post_run_hook()
        generated_bytes_per_second = transport.bytes_per_second.value
        self.assertLess(
            minimum_bytes_per_second, generated_bytes_per_second,
            "Expected generator to produce bytes > {} but found {}. "
            "Check load on this lab server.".format(
                minimum_bytes_per_second, generated_bytes_per_second))
        bytes_received = 0
        expected_count = 0
        while not self.raw_data_queue.empty():
            expected_count += 1
            _, raw_data = self.raw_data_queue.get()
            actual_count = int(raw_data[:8])
            self.assertEqual(
                expected_count, actual_count,
                "Expected line count {} found {} in {!r}".format(
                    expected_count, actual_count, raw_data))
            bytes_received += len(raw_data)
        actual_bytes_per_second = bytes_received / (finish_time - start_time)
        self.assertLess(
            minimum_bytes_per_second, actual_bytes_per_second,
            "Expected actual bytes per second > {} but found {}".format(
                minimum_bytes_per_second, actual_bytes_per_second))
예제 #9
0
    def test_220_transport_can_disable_raw_data_queue(self):
        """Test transport can disable raw_data_queue."""
        device_data1 = b"some device message\n"
        device_data2 = b"other device message\n"
        transport = mock.MagicMock(spec=fake_transport.FakeTransport)
        transport.read.side_effect = iter([device_data1, device_data2])
        raw_data_id = 1
        self.uut = transport_process.TransportProcess(
            "fake_transport",
            self.exception_queue,
            self.command_queue,
            self.log_queue,
            transport,
            call_result_queue=self.call_result_queue,
            raw_data_queue=self.raw_data_queue,
            raw_data_id=raw_data_id)

        self.uut._pre_run_hook()
        self.uut.toggle_raw_data()  # enable raw data for first message
        self.uut._do_work()  # publish first raw data message

        self.uut.toggle_raw_data()  # disable raw data for second message
        self.uut._do_work()  # skips publishing second raw data message
        self.uut._post_run_hook()

        self.assertEqual(
            1, self.raw_data_queue.qsize(),
            "Expected 1 entry in raw_data_queue found {}".format(
                self.raw_data_queue.qsize()))
        self.assertEqual(
            2, self.log_queue.qsize(),
            "Expected 2 entries in log_queue found {}".format(
                self.log_queue.qsize()))

        data_id, raw_data = self.uut.get_raw_data()
        self.assertIsInstance(
            data_id, int,
            "Expecting int for raw data id found {}".format(type(data_id)))
        self.assertIsInstance(raw_data, str)
        self.assertEqual(raw_data_id, data_id,
                         "Expecting {} found {}".format(raw_data_id, data_id))
        self.assertEqual(
            device_data1.decode("utf-8", "replace"), raw_data,
            "Expecting {!r} found {!r}".format(
                device_data1.decode("utf-8", "replace"), raw_data))
예제 #10
0
    def test_210_transport_rejects_invalid_command(self):
        """Test transport rejects invalid command."""
        transport = fake_transport.FakeTransport()
        self.uut = transport_process.TransportProcess(
            "fake_transport",
            self.exception_queue,
            self.command_queue,
            self.log_queue,
            transport,
            call_result_queue=self.call_result_queue)

        self.command_queue.put(("invalid cmd", None))
        wait_for_queue_writes(self.command_queue)
        self.uut._pre_run_hook()
        with self.assertRaisesRegex(RuntimeError,
                                    r"received an unknown command"):
            self.uut._do_work()
        self.uut._post_run_hook()
예제 #11
0
    def test_311_transport_process_write_command(self):
        """Verify transport process processes WRITE command correctly."""
        transport = mock.Mock()
        uut = transport_process.TransportProcess(
            "fake_transport",
            self.exception_queue,
            self.command_queue,
            self.log_queue,
            transport=transport,
            call_result_queue=self.call_result_queue)

        with mock.patch.object(transport_process,
                               "_enqueue_command_writes") as mock_write:
            uut._process_command_message(
                (transport_process.CMD_TRANSPORT_WRITE, b"stuff"))
            mock_write.assert_called_once_with(mock.ANY,
                                               b"stuff",
                                               max_write_bytes=mock.ANY)
예제 #12
0
    def test_233_transport_read_reorders_log_interrupted_partial_lines(self):
        """Test transport read can order partial and full lines correctly.

    See NEP-3223 which is a bug in the interaction of TransportProcess and
    LogFramer.
    """
        transport = fake_transport.FakeTransport()
        response_start = u"response start"
        response_end = u" end"
        response_full = response_start + response_end
        log_line = u"my custom log line\n"
        log_regex = "({})".format(log_line)
        framer = data_framer.InterwovenLogFramer(log_regex)
        uut = transport_process.TransportProcess(
            "fake_transport",
            self.exception_queue,
            self.command_queue,
            self.log_queue,
            transport,
            call_result_queue=self.call_result_queue,
            framer=framer)

        device_data1 = response_start + log_line + response_end
        transport.reads.put(device_data1)
        wait_for_queue_writes(transport.reads)
        uut._pre_run_hook()
        uut._do_work()
        line1 = self.log_queue.get()
        self.assertIn(
            log_line, line1,
            "Expected {!r} in line but found {!r}".format(log_line, line1))
        self.assertTrue(self.log_queue.empty(),
                        "Expected log queue to be empty")
        time.sleep(_LOG_MESSAGE_TIMEOUT)
        uut._do_work()
        line2 = self.log_queue.get()
        self.assertIn(
            response_full, line2,
            "Expected {!r} in line but found {!r}".format(
                response_full, line2))
        self.assertTrue(self.log_queue.empty(),
                        "Expected log queue to be empty")
        uut._post_run_hook()
예제 #13
0
 def test_111_transport_toggle_raw_data_toggles(self):
     """Test toggle_raw_data toggles raw_data_enable."""
     transport = None
     self.uut = transport_process.TransportProcess(
         "fake_transport",
         self.exception_queue,
         self.command_queue,
         self.log_queue,
         transport,
         call_result_queue=self.call_result_queue,
         raw_data_queue=self.raw_data_queue)
     self.assertFalse(self.uut.raw_data_enabled(),
                      "Expected raw_data streaming to be disabled")
     self.uut.toggle_raw_data()
     self.assertTrue(self.uut.raw_data_enabled(),
                     "Expected raw_data streaming to be enabled")
     self.uut.toggle_raw_data()
     self.assertFalse(self.uut.raw_data_enabled(),
                      "Expected raw_data streaming to be disabled")
예제 #14
0
 def test_200_transport_opens_and_closes_transport(self):
     """Test transport process calls transport open and close."""
     transport = fake_transport.FakeTransport()
     self.uut = transport_process.TransportProcess(
         "fake_transport",
         self.exception_queue,
         self.command_queue,
         self.log_queue,
         transport,
         call_result_queue=self.call_result_queue)
     self.uut.start()
     self.uut.stop()
     self.assertEqual(
         1, transport.open_count.value,
         "Expected transport.open to be called {} called {}".format(
             1, transport.open_count.value))
     self.assertEqual(
         1, transport.close_count.value,
         "Expected transport.close to be called {} called {}".format(
             1, transport.close_count.value))
예제 #15
0
 def test_100_transport_accepts_valid_transport_commands(self):
     """Test send_command accepts valid transport commands."""
     transport = None
     self.uut = transport_process.TransportProcess(
         "fake_transport",
         self.exception_queue,
         self.command_queue,
         self.log_queue,
         transport,
         call_result_queue=self.call_result_queue)
     for command in transport_process._ALL_VALID_COMMANDS:
         self.uut.send_command(command)
         wait_for_queue_writes(self.command_queue)
         self.assertFalse(self.command_queue.empty(),
                          "Expected command queue to not be empty")
         command_message = self.command_queue.get()
         self.assertEqual(
             command, command_message[0],
             "Expected command {} found {}".format(command,
                                                   command_message[0]))
예제 #16
0
    def test_312_transport_process_call_command(self):
        """Verify transport process processes CALL command correctly."""
        transport = mock.Mock()
        uut = transport_process.TransportProcess(
            "fake_transport",
            self.exception_queue,
            self.command_queue,
            self.log_queue,
            transport=transport,
            call_result_queue=self.call_result_queue)

        transport.some_method.return_value = 123
        uut._process_command_message((transport_process.CMD_TRANSPORT_CALL,
                                      ("some_method", ("a", "b"), {
                                          "foo": "bar"
                                      })))
        transport.some_method.assert_called_once_with("a", "b", foo="bar")
        success, return_value = self.call_result_queue.get(block=True,
                                                           timeout=0.1)
        self.assertTrue(success)
        self.assertEqual(return_value, 123)
예제 #17
0
    def test_313_transport_process_call_command_error_handling(self):
        """Verify exceptions in transport methods are put into the result queue."""
        transport = mock.Mock()
        uut = transport_process.TransportProcess(
            "fake_transport",
            self.exception_queue,
            self.command_queue,
            self.log_queue,
            transport=transport,
            call_result_queue=self.call_result_queue)

        transport.some_method.side_effect = RuntimeError("Something failed")
        uut._process_command_message((transport_process.CMD_TRANSPORT_CALL,
                                      ("some_method", ("a", "b"), {
                                          "foo": "bar"
                                      })))
        transport.some_method.assert_called_once_with("a", "b", foo="bar")
        success, error_traceback = self.call_result_queue.get(block=True,
                                                              timeout=0.1)
        self.assertFalse(success)
        self.assertIn("RuntimeError: Something failed", error_traceback)
예제 #18
0
 def test_203_transport_skips_opens_on_start(self):
     """Test transport process calls transport open and close."""
     transport = fake_transport.FakeTransport()
     transport.set_property(transport_properties.OPEN_ON_START, False)
     self.uut = transport_process.TransportProcess(
         "fake_transport",
         self.exception_queue,
         self.command_queue,
         self.log_queue,
         transport,
         call_result_queue=self.call_result_queue)
     self.uut.start()
     self.uut.stop()
     self.assertEqual(
         0, transport.open_count.value,
         "Expected transport.open to be called {} called {}".format(
             0, transport.open_count.value))
     self.assertEqual(
         1, transport.close_count.value,
         "Expected transport.close to be called {} called {}".format(
             1, transport.close_count.value))
예제 #19
0
    def test_310_transport_process_open_close_commands(self):
        """Verify transport process processes OPEN and CLOSE commands correctly."""
        transport = mock.Mock()
        uut = transport_process.TransportProcess(
            "fake_transport",
            self.exception_queue,
            self.command_queue,
            self.log_queue,
            transport=transport,
            call_result_queue=self.call_result_queue)

        test_data = [
            ((transport_process.CMD_TRANSPORT_CLOSE, None), transport.close),
            ((transport_process.CMD_TRANSPORT_OPEN, None), transport.open)
        ]

        for message, expected_action in test_data:
            with self.subTest(command=message[0]):
                transport.reset_mock()
                uut._process_command_message(message)
                expected_action.assert_called_once()
예제 #20
0
    def test_231_transport_read_error_raises_error(self):
        """Test transport raises error on read exception."""
        transport = fake_transport.FakeTransport(fail_read=True)

        self.uut = transport_process.TransportProcess(
            "fake_transport",
            self.exception_queue,
            self.command_queue,
            self.log_queue,
            transport,
            call_result_queue=self.call_result_queue)
        self.uut.start()
        end_time = time.time() + _EXCEPTION_TIMEOUT
        while self.uut.is_running() and time.time() < end_time:
            time.sleep(0.001)
        self.assertFalse(
            self.uut.is_open(),
            "Expected transport process to be closed, found open")
        self.assertFalse(self.uut.is_running(),
                         "Expected process to end, still running")
        self.uut.stop()

        self.assertEqual(
            1, transport.open_count.value,
            "Expected transport.open to be called {} called {}".format(
                1, transport.open_count.value))
        self.assertEqual(
            1, transport.close_count.value,
            "Expected transport.close to be called {} called {}".format(
                1, transport.close_count.value))
        self.assertIsNotNone(self.exception,
                             "Expected exception to be raised found None")
        self.assertIn(
            fake_transport.EXCEPTION_MESSAGE, self.exception,
            "Expected exception message {} found {!r}".format(
                fake_transport.EXCEPTION_MESSAGE, self.exception))
        # Clear raised exception that was handled
        self.exception = None
예제 #21
0
    def test_234_transport_read_orders_lines_correctly(self):
        """Test transport read can order partial and full lines correctly.

    See NEP-3223 which is a bug in the interaction of TransportProcess and
    LogFramer.
    """
        response_start = u"response start"
        response_end = u" end\n"
        response_full = response_start + response_end
        log_line = u"my custom log line\n"
        log_regex = "({})".format(log_line)
        device_data1 = response_start + log_line + response_end
        transport = mock.MagicMock(fake_transport.FakeTransport)
        transport.read.return_value = device_data1.encode("utf-8", "replace")
        framer = data_framer.InterwovenLogFramer(log_regex)
        self.uut = transport_process.TransportProcess(
            "fake_transport",
            self.exception_queue,
            self.command_queue,
            self.log_queue,
            transport,
            call_result_queue=self.call_result_queue,
            framer=framer)

        self.uut._pre_run_hook()
        self.uut._do_work()
        line1 = self.log_queue.get()
        self.assertIn(
            log_line, line1,
            "Expected {!r} in line but found {!r}".format(log_line, line1))
        line2 = self.log_queue.get()
        self.assertIn(
            response_full, line2,
            "Expected {!r} in line but found {!r}".format(
                response_full, line2))
        self.assertTrue(self.log_queue.empty(),
                        "Expected log queue to be empty")
        self.uut._post_run_hook()
예제 #22
0
    def test_232_transport_read_retains_partial_lines(self):
        """Test transport read can retain partial log lines."""
        transport = fake_transport.FakeTransport()
        self.uut = transport_process.TransportProcess(
            "fake_transport",
            self.exception_queue,
            self.command_queue,
            self.log_queue,
            transport,
            call_result_queue=self.call_result_queue)

        device_data1 = "partial log line\r"
        transport.reads.put(device_data1)
        wait_for_queue_writes(transport.reads)
        self.uut._pre_run_hook()
        self.uut._do_work()
        self.assertTrue(self.log_queue.empty(),
                        "Expected log queue to be empty")
        time.sleep(_LOG_MESSAGE_TIMEOUT)
        self.uut._do_work()
        self.assertFalse(self.log_queue.empty(),
                         "Expected log queue to not be empty")
        self.uut._post_run_hook()
예제 #23
0
    def test_230_transport_invalid_command_raises_error(self):
        """Test transport raises exception on invalid command."""
        transport = fake_transport.FakeTransport()

        self.uut = transport_process.TransportProcess(
            "fake_transport",
            self.exception_queue,
            self.command_queue,
            self.log_queue,
            transport,
            call_result_queue=self.call_result_queue)
        self.command_queue.put(("Invalid command", None))
        wait_for_queue_writes(self.command_queue)
        self.uut.start()
        end_time = time.time() + _EXCEPTION_TIMEOUT
        while self.uut.is_running() and time.time() < end_time:
            time.sleep(0.001)
        self.assertFalse(self.uut.is_running(),
                         "Expected process to end, still running")
        self.uut.stop()

        self.assertEqual(
            1, transport.open_count.value,
            "Expected transport.open to be called {} called {}".format(
                1, transport.open_count.value))
        self.assertEqual(
            1, transport.close_count.value,
            "Expected transport.close to be called {} called {}".format(
                1, transport.close_count.value))
        self.assertIsNotNone(self.exception,
                             "Expected exception to be raised found None")
        self.assertIn(
            "received an unknown command", repr(self.exception),
            "Expected 'received an unknown command' found {!r}".format(
                self.exception))
        # Clear raised exception that was handled
        self.exception = None