def test_pipeline_registration(self):
    """ Verifies that the base driver class can correctly register pipelines
    """

    # Load a driver to test with
    test_driver = self.device_manager.get_device_driver("test_device")

    # Create some mock pipelines to register with the device
    test_pipeline = MagicMock()
    test_pipeline.id = "test_pipeline"
    test_pipeline.output_device = test_driver
    test_pipeline_2 = MagicMock()
    test_pipeline_2.id = "test_pipeline_2"
    test_pipeline_2.output_device = test_driver

    # Register the pipelines
    test_driver.register_pipeline(test_pipeline)
    test_driver.register_pipeline(test_pipeline_2)
    self.assertTrue((test_driver.associated_pipelines[test_pipeline.id].id == test_pipeline.id) and
                    (test_driver.associated_pipelines[test_pipeline.id].output_device is test_driver))
    self.assertTrue((test_driver.associated_pipelines[test_pipeline_2.id].id == test_pipeline_2.id) and
                    (test_driver.associated_pipelines[test_pipeline_2.id].output_device is test_driver))

    # Make sure that pipelines can't be re-registered
    self.assertRaises(driver.PipelineAlreadyRegistered, test_driver.register_pipeline, test_pipeline)
  def test_writing_device_output(self):
    """ Tests that the Driver class can pass its output to its registered pipelines. The default implementation of the 
    Driver.write_output() method only writes to active pipelines that specify this device as its output device.
    """ 

    # Load a device to test with
    test_driver = self.device_manager.get_device_driver("test_device")

    # Create some mock pipelines and register them with the device
    test_pipeline = MagicMock()
    test_pipeline.id = "test_pipeline"
    test_pipeline.is_active = False
    test_driver.register_pipeline(test_pipeline)
    test_pipeline_2 = MagicMock()
    test_pipeline_2.id = "test_pipeline_2"
    test_pipeline_2.is_active = True
    test_driver.register_pipeline(test_pipeline_2)
    test_pipeline_3 = MagicMock()
    test_pipeline_3.id = "test_pipeline_3"
    test_pipeline_3.is_active = True
    test_pipeline_3.output_device = test_driver
    test_driver.register_pipeline(test_pipeline_3)

    # Write some output to the associated pipelines
    test_driver.write_output("waffles")

    # Make sure the output never made it to the non-active pipeline
    self.assertEqual(test_pipeline.write_output.call_count, 0)

    # Make sure that test_pipeline_2 was never called (doesn't specify test_device as its output device)
    self.assertEqual(test_pipeline_2.write_output.call_count, 0)

    # Verify that test_pipeline_3 was called with the correct output
    test_pipeline_3.write_output.assert_called_once_with("waffles")
  def test_writing_device_telemetry(self):
    """ Tests that the Driver class can pass device telemetry and extra data streams to its registered pipelines via the
    Driver.write_telemetry() method. This method should always be used to write extra device data and telemetry back to 
    its pipelines.
    """ 

    # Load a device to test with
    test_driver = self.device_manager.get_device_driver("test_device")

    # Create some mock pipelines and register them with the device
    test_pipeline = MagicMock()
    test_pipeline.id = "test_pipeline"
    test_pipeline.is_active = False
    test_pipeline.output_device = test_driver
    test_driver.register_pipeline(test_pipeline)
    test_pipeline_2 = MagicMock()
    test_pipeline_2.id = "test_pipeline_2"
    test_pipeline_2.is_active = True
    test_pipeline_2.output_device = test_driver
    test_driver.register_pipeline(test_pipeline_2)

    # Write a telemetry point to the driver
    test_driver.write_telemetry("test_stream", "waffles", binary=False, test_header=42)

    # Make sure the telemetry was never passed to test_pipeline (not active)
    self.assertEqual(test_pipeline.write_telemetry.call_count, 0)

    # Make sure that the telemetry point was correctly passed to the active pipeline (test_pipeline_2). We can't just
    # use assert_called_once_with() because the timestamp argument is generated after write_telemetry() is called.
    mock_call = test_pipeline_2.write_telemetry.call_args_list[0]
    test_args, test_kwords = mock_call
    self.assertEqual(test_args[0], "test_device")
    self.assertEqual(test_args[1], "test_stream")
    int(test_args[2]) # Check if the auto generated timestamp is an integer (will throw exception otherwise)
    self.assertEqual(test_args[3], "waffles")
    self.assertTrue("binary" in test_kwords and test_kwords["binary"] == False)
    self.assertTrue("test_header" in test_kwords and test_kwords["test_header"] == 42)