コード例 #1
0
    def __init__(self, channel, params, evt_callback=None):
        """
        @param channel identifies the particular protocol instance.
        @param params the particular parameters for this channel.
        """
        InstrumentProtocol.__init__(self, evt_callback)
        self._channel = channel

        # initialize values for the params:
        MyProtocol.next_base_value += 1000
        next_value = MyProtocol.next_base_value
        self._values = {}
        for param in params:
            next_value += 1
            self._values[param] = next_value
コード例 #2
0
    def __init__(self, channel, params, evt_callback=None):
        """
        @param channel identifies the particular protocol instance.
        @param params the particular parameters for this channel.
        """
        InstrumentProtocol.__init__(self, evt_callback)
        self._channel = channel

        # initialize values for the params:
        MyProtocol.next_base_value += 1000
        next_value = MyProtocol.next_base_value
        self._values = {}
        for param in params:
            next_value += 1
            self._values[param] = next_value
コード例 #3
0
    def setUp(self):
        self.mock = DotDict()
        self.mock.port_agent = Mock(name='port_agent_client')
        self.mock.callback = Mock(name='callback')

        def mock_set(values, startup=True):
            assert isinstance(values, dict)
            return_string = ""
            for key in values.keys():
                return_string += "%s=%s" % (key, values[key]
                                            )  # inefficient, I know
            return return_string

        self.driver = SingleConnectionInstrumentDriver(self.mock.callback)

        # set some values
        self.driver._protocol = InstrumentProtocol(self.mock.callback)
        self.driver.set_resource = mock_set

        self.driver._protocol._param_dict.add(
            "foo",
            r'foo=(.*)',
            lambda match: int(match.group(1)),
            lambda x: str(x),
            direct_access=True,
            startup_param=True,
            default_value=10)
        self.driver._protocol._param_dict.set_default("foo")
        self.driver._protocol._param_dict.add(
            "bar",
            r'bar=(.*)',
            lambda match: int(match.group(1)),
            lambda x: str(x),
            direct_access=False,
            startup_param=True,
            default_value=15)
        self.driver._protocol._param_dict.set_default("bar")
        self.driver._protocol._param_dict.add(
            "baz",
            r'baz=(.*)',
            lambda match: int(match.group(1)),
            lambda x: str(x),
            direct_access=True,
            default_value=30)
        self.driver._protocol._param_dict.set_default("baz")
        self.driver._protocol._param_dict.add(
            "bat",
            r'bat=(.*)',
            lambda match: int(match.group(1)),
            lambda x: str(x),
            startup_param=False,
            default_value=40)
        self.driver._protocol._param_dict.set_default("bat")

        self.driver._protocol._cmd_dict.add("cmd1")
        self.driver._protocol._cmd_dict.add("cmd2")

        self.driver._protocol._driver_dict.add(
            DriverDictKey.VENDOR_SW_COMPATIBLE, True)
コード例 #4
0
    def setUp(self):
        """
        """
        self.callback_result = None
        self._trigger_count = 0
        self._events = []

        self.protocol = InstrumentProtocol(self.event_callback)
コード例 #5
0
    def setUp(self):
        """
        """
        self.callback_result = None
        self._trigger_count = 0
        self._events = []

        self.protocol = InstrumentProtocol(self.event_callback)
コード例 #6
0
class TestUnitInstrumentProtocol(IonUnitTestCase):
    """
    Test cases for instrument protocol class. Functions in this class provide
    instrument protocol unit tests and provide a tutorial on use of
    the protocol interface.
    """ 
    def setUp(self):
        """
        """
        self.callback_result = None
        
        def protocol_callback(self, arg):
            callback_result = arg
            
        self.protocol = InstrumentProtocol(protocol_callback)
    
    def test_extraction(self):
        sample_line = "SATPAR0229,10.01,2206748544,234"
        result = self.protocol._extract_sample(SatlanticPARDataParticle,
                                               SAMPLE_REGEX,
                                               sample_line,
                                               publish=False)
    
        self.assertTrue(result['parsed'])
        self.assertTrue(result['raw'])

        # Test the format of the result in the individual driver tests. Here,
        # just tests that the result is there.
        
    def test_publish_raw(self):
        """
        Tests to see if raw data is appropriately published back out to
        the InstrumentAgent via the event callback.
        """
        # build a packet
        # have it published by the protocol (force state if needed)
        # delay?
        # catch it in the  callback
        # confirm it came back
        # compare response to original packet
        
        self.assertTrue(False)
    
    def test_publish_parsed_data(self):
        """
        Tests to see if parsed data is appropriately published back to the
        InstrumentAgent via the event callback.
        """
        # similar to above
        self.assertTrue(False)

    def test_publish_engineering_data(self):
        """
        Tests to see if engineering data is appropriately published back to the
        InstrumentAgent via the event callback.
        """
        # similar to above
        self.assertTrue(False)    
コード例 #7
0
 def setUp(self):
     """
     """
     self.callback_result = None
     
     def protocol_callback(self, arg):
         callback_result = arg
         
     self.protocol = InstrumentProtocol(protocol_callback)
コード例 #8
0
    def setUp(self):
        """
        """
        self.callback_result = None
        self._trigger_count = 0

        def protocol_callback(self, arg):
            callback_result = arg
            
        self.protocol = InstrumentProtocol(protocol_callback)
コード例 #9
0
ファイル: driver.py プロジェクト: danmergens/mi-instrument
    def __init__(self, driver_event):
        """
        Protocol constructor.
        @param driver_event Driver process event callback.
        """
        # Construct protocol superclass.
        InstrumentProtocol.__init__(self, driver_event)

        # Build protocol state machine.
        self._protocol_fsm = ThreadSafeFSM(ProtocolState, ProtocolEvent,
                                           ProtocolEvent.ENTER, ProtocolEvent.EXIT)

        # Add event handlers for protocol state machine.
        handlers = {
            ProtocolState.UNKNOWN: [
                (ProtocolEvent.ENTER, self._handler_generic_enter),
                (ProtocolEvent.EXIT, self._handler_generic_exit),
                (ProtocolEvent.DISCOVER, self._handler_unknown_discover),
            ],
            ProtocolState.COMMAND: [
                (ProtocolEvent.ENTER, self._handler_generic_enter),
                (ProtocolEvent.EXIT, self._handler_generic_exit),
                (ProtocolEvent.START_DIRECT, self._handler_command_start_direct),
                (ProtocolEvent.GET, self._handler_command_get),
                (ProtocolEvent.SET, self._handler_command_set),
                (ProtocolEvent.START_AUTOSAMPLE, self._handler_command_start_autosample),
                (ProtocolEvent.ACQUIRE_SAMPLE, self._handler_command_start_poll),
                (ProtocolEvent.CALIBRATE, self._handler_command_start_calibrate),
                (ProtocolEvent.START_NAFION, self._handler_command_start_nafion_regen),
                (ProtocolEvent.START_ION, self._handler_command_start_ion_regen),
                (ProtocolEvent.ERROR, self._handler_error),
                (ProtocolEvent.POWEROFF, self._handler_command_poweroff),
                (ProtocolEvent.START_MANUAL, self._handler_command_start_manual),
            ],
            ProtocolState.AUTOSAMPLE: [
                (ProtocolEvent.ENTER, self._handler_generic_enter),
                (ProtocolEvent.EXIT, self._handler_generic_exit),
                (ProtocolEvent.ACQUIRE_SAMPLE, self._handler_autosample_acquire_sample),
                (ProtocolEvent.STOP, self._handler_stop_generic),
                (ProtocolEvent.STOP_AUTOSAMPLE, self._handler_stop_generic),
                (ProtocolEvent.ERROR, self._handler_error),
            ],
            ProtocolState.POLL: [
                (ProtocolEvent.ENTER, self._handler_generic_enter),
                (ProtocolEvent.EXIT, self._handler_generic_exit),
                (ProtocolEvent.STOP, self._handler_stop_generic),
                (ProtocolEvent.ERROR, self._handler_error),
            ],
            ProtocolState.ERROR: [
                (ProtocolEvent.ENTER, self._handler_generic_enter),
                (ProtocolEvent.EXIT, self._handler_generic_exit),
                (ProtocolEvent.CLEAR, self._handler_error_clear),
            ],
            ProtocolState.CALIBRATE: [
                (ProtocolEvent.ENTER, self._handler_generic_enter),
                (ProtocolEvent.EXIT, self._handler_generic_exit),
                (ProtocolEvent.STOP, self._handler_stop_generic),
                (ProtocolEvent.ERROR, self._handler_error),
            ],
            ProtocolState.REGEN: [
                (ProtocolEvent.ENTER, self._handler_generic_enter),
                (ProtocolEvent.EXIT, self._handler_generic_exit),
                (ProtocolEvent.STOP_REGEN, self._handler_stop_regen),
                (ProtocolEvent.REGEN_COMPLETE, self._handler_regen_complete),
                (ProtocolEvent.ERROR, self._handler_error),
            ],
            ProtocolState.DIRECT_ACCESS: [
                (ProtocolEvent.ENTER, self._handler_direct_access_enter),
                (ProtocolEvent.EXIT, self._handler_direct_access_exit),
                (ProtocolEvent.STOP_DIRECT, self._handler_direct_access_stop_direct),
                (ProtocolEvent.EXECUTE_DIRECT, self._handler_direct_access_execute_direct),
            ],
            ProtocolState.MANUAL_OVERRIDE: [
                (ProtocolEvent.ENTER, self._handler_generic_enter),
                (ProtocolEvent.EXIT, self._handler_generic_exit),
                (ProtocolEvent.STOP_MANUAL, self._handler_manual_override_stop),
                (ProtocolEvent.GET_SLAVE_STATES, self._handler_manual_get_slave_states),
            ],
        }

        for state in handlers:
            for event, handler in handlers[state]:
                self._protocol_fsm.add_handler(state, event, handler)

        # Construct the parameter dictionary containing device parameters,
        # current parameter values, and set formatting functions.
        self._build_param_dict()
        self._build_command_dict()
        self._build_driver_dict()

        # State state machine in UNKNOWN state.
        self._protocol_fsm.start(ProtocolState.UNKNOWN)

        # commands sent sent to device to be filtered in responses for telnet DA
        self._sent_cmds = []

        self._slave_protocols = {}
        self.initialize_scheduler()
コード例 #10
0
ファイル: driver.py プロジェクト: vipullakhani/mi-instrument
    def __init__(self, driver_event):
        """
        Protocol constructor.
        @param driver_event Driver process event callback.
        """
        # Construct protocol superclass.
        InstrumentProtocol.__init__(self, driver_event)

        # Build protocol state machine.
        self._protocol_fsm = ThreadSafeFSM(ProtocolState, ProtocolEvent,
                                           ProtocolEvent.ENTER,
                                           ProtocolEvent.EXIT)

        # Add event handlers for protocol state machine.
        handlers = {
            ProtocolState.UNKNOWN: [
                (ProtocolEvent.ENTER, self._handler_generic_enter),
                (ProtocolEvent.EXIT, self._handler_generic_exit),
                (ProtocolEvent.DISCOVER, self._handler_unknown_discover),
            ],
            ProtocolState.COMMAND: [
                (ProtocolEvent.ENTER, self._handler_generic_enter),
                (ProtocolEvent.EXIT, self._handler_generic_exit),
                (ProtocolEvent.START_DIRECT,
                 self._handler_command_start_direct),
                (ProtocolEvent.GET, self._handler_command_get),
                (ProtocolEvent.SET, self._handler_command_set),
                (ProtocolEvent.START_AUTOSAMPLE,
                 self._handler_command_start_autosample),
                (ProtocolEvent.ACQUIRE_SAMPLE,
                 self._handler_command_start_poll),
                (ProtocolEvent.CALIBRATE,
                 self._handler_command_start_calibrate),
                (ProtocolEvent.START_NAFION,
                 self._handler_command_start_nafion_regen),
                (ProtocolEvent.START_ION,
                 self._handler_command_start_ion_regen),
                (ProtocolEvent.ERROR, self._handler_error),
                (ProtocolEvent.POWEROFF, self._handler_command_poweroff),
                (ProtocolEvent.START_MANUAL,
                 self._handler_command_start_manual),
            ],
            ProtocolState.AUTOSAMPLE: [
                (ProtocolEvent.ENTER, self._handler_generic_enter),
                (ProtocolEvent.EXIT, self._handler_generic_exit),
                (ProtocolEvent.ACQUIRE_SAMPLE,
                 self._handler_autosample_acquire_sample),
                (ProtocolEvent.STOP, self._handler_stop_generic),
                (ProtocolEvent.STOP_AUTOSAMPLE, self._handler_stop_generic),
                (ProtocolEvent.ERROR, self._handler_error),
            ],
            ProtocolState.POLL: [
                (ProtocolEvent.ENTER, self._handler_generic_enter),
                (ProtocolEvent.EXIT, self._handler_generic_exit),
                (ProtocolEvent.STOP, self._handler_stop_generic),
                (ProtocolEvent.ERROR, self._handler_error),
            ],
            ProtocolState.ERROR: [
                (ProtocolEvent.ENTER, self._handler_generic_enter),
                (ProtocolEvent.EXIT, self._handler_generic_exit),
                (ProtocolEvent.CLEAR, self._handler_error_clear),
            ],
            ProtocolState.CALIBRATE: [
                (ProtocolEvent.ENTER, self._handler_generic_enter),
                (ProtocolEvent.EXIT, self._handler_generic_exit),
                (ProtocolEvent.STOP, self._handler_stop_generic),
                (ProtocolEvent.ERROR, self._handler_error),
            ],
            ProtocolState.REGEN: [
                (ProtocolEvent.ENTER, self._handler_generic_enter),
                (ProtocolEvent.EXIT, self._handler_generic_exit),
                (ProtocolEvent.STOP_REGEN, self._handler_stop_regen),
                (ProtocolEvent.REGEN_COMPLETE, self._handler_regen_complete),
                (ProtocolEvent.ERROR, self._handler_error),
            ],
            ProtocolState.DIRECT_ACCESS: [
                (ProtocolEvent.ENTER, self._handler_direct_access_enter),
                (ProtocolEvent.EXIT, self._handler_direct_access_exit),
                (ProtocolEvent.STOP_DIRECT,
                 self._handler_direct_access_stop_direct),
                (ProtocolEvent.EXECUTE_DIRECT,
                 self._handler_direct_access_execute_direct),
            ],
            ProtocolState.MANUAL_OVERRIDE: [
                (ProtocolEvent.ENTER, self._handler_generic_enter),
                (ProtocolEvent.EXIT, self._handler_generic_exit),
                (ProtocolEvent.STOP_MANUAL,
                 self._handler_manual_override_stop),
                (ProtocolEvent.GET_SLAVE_STATES,
                 self._handler_manual_get_slave_states),
            ],
        }

        for state in handlers:
            for event, handler in handlers[state]:
                self._protocol_fsm.add_handler(state, event, handler)

        # Construct the parameter dictionary containing device parameters,
        # current parameter values, and set formatting functions.
        self._build_param_dict()
        self._build_command_dict()
        self._build_driver_dict()

        # State state machine in UNKNOWN state.
        self._protocol_fsm.start(ProtocolState.UNKNOWN)

        # commands sent sent to device to be filtered in responses for telnet DA
        self._sent_cmds = []

        self._slave_protocols = {}
        self.initialize_scheduler()
コード例 #11
0
class TestUnitInstrumentProtocol(MiUnitTestCase):
    """
    Test cases for instrument protocol class. Functions in this class provide
    instrument protocol unit tests and provide a tutorial on use of
    the protocol interface.
    """ 
    def setUp(self):
        """
        """
        self.callback_result = None
        self._trigger_count = 0
        self._events = []

        self.protocol = InstrumentProtocol(self.event_callback)

    def event_callback(self, event, value=None):
        log.debug("Test event callback: %s" % event)
        self._events.append(event)
        self._trigger_count += 1

    def _scheduler_callback(self):
        """
        Callback to test the scheduler
        """
        self._trigger_count += 1

    def assert_scheduled_event_triggered(self, event_count=1):
        count = 0
        for i in range(0, 40):
            count = self._trigger_count
            log.debug("check for triggered event, count %d" % self._trigger_count)
            if(count >= event_count): break
            time.sleep(0.3)

        self.assertGreater(count, 0)


    def test_extraction(self):
        sample_line = "SATPAR0229,10.01,2206748544,234\r\n"
        ntptime = ntplib.system_to_ntp_time(time.time())
        result = self.protocol._extract_sample(SatlanticPARDataParticle,
                                               SAMPLE_REGEX,
                                               sample_line,
                                               ntptime,
                                               publish=False)

        log.debug("R: %s" % result)
        self.assertEqual(result['stream_name'], SatlanticPARDataParticle(None, None).data_particle_type())

        # Test the format of the result in the individual driver tests. Here,
        # just tests that the result is there.

    @unittest.skip('Not Written')
    def test_publish_raw(self):
        """
        Tests to see if raw data is appropriately published back out to
        the InstrumentAgent via the event callback.
        """
        # build a packet
        # have it published by the protocol (force state if needed)
        # delay?
        # catch it in the  callback
        # confirm it came back
        # compare response to original packet
        
        self.assertTrue(False)

    @unittest.skip('Not Written')
    def test_publish_parsed_data(self):
        """
        Tests to see if parsed data is appropriately published back to the
        InstrumentAgent via the event callback.
        """
        # similar to above
        self.assertTrue(False)

    @unittest.skip('Not Written')
    def test_publish_engineering_data(self):
        """
        Tests to see if engineering data is appropriately published back to the
        InstrumentAgent via the event callback.
        """
        # similar to above
        self.assertTrue(False)
        
    def test_get_running_config(self):
        """
        Checks to see that one can successfully get the running config from an
        instrument protocol.
        """
        # set some values
        log.debug("First param_dict: %s", self.protocol._param_dict.get_config())
        self.protocol._param_dict.add("foo", r'foo=(.*)',
                             lambda match : int(match.group(1)),
                             lambda x : str(x),
                             direct_access=True,
                             default_value=10)
        self.protocol._param_dict.set_default("foo") # test hack to set w/o fetch
        self.protocol._param_dict.add("bar", r'bar=(.*)',
                             lambda match : int(match.group(1)),
                             lambda x : str(x),
                             direct_access=False,
                             default_value=15)
        self.protocol._param_dict.set_default("bar")
                
        self.assertEquals(self.protocol._param_dict.get("foo"), 10)
        self.assertEquals(self.protocol._param_dict.get("bar"), 15)
        result = self.protocol.get_cached_config()
        self.assertEquals(result['foo'], 10)
        self.assertEquals(result['bar'], 15)

        self.protocol._param_dict.update("bar=20")
        result = self.protocol.get_cached_config()
        self.assertEquals(result['foo'], 10)
        self.assertEquals(result['bar'], 20)
        self.assertEquals(self.protocol._param_dict.get("bar"), 20)
        
        # get and check the running config
        result = self.protocol.get_cached_config()
        self.assertTrue(isinstance(result, dict))
        self.assertEquals(result['foo'], 10)
        self.assertEquals(result['bar'], 20)

    def test_init_values(self):
        """
        Test getting and setting the initialization value for a parameter
        """
        # set an additional value for test
        self.protocol._param_dict.add("foo", r'foo=(.*)',
                             lambda match : int(match.group(1)),
                             lambda x : str(x),
                             direct_access=True,
                             startup_param=True,
                             default_value=10)
        self.protocol._param_dict.add("bar", r'bar=(.*)',
                             lambda match : int(match.group(1)),
                             lambda x : str(x),
                             direct_access=False,
                             startup_param=True,
                             default_value=0)
        self.protocol._param_dict.add("baz", r'baz=(.*)',
                             lambda match : int(match.group(1)),
                             lambda x : str(x),
                             direct_access=True,
                             default_value=20)
        self.protocol._param_dict.add("bat", r'bat=(.*)',
                             lambda match : int(match.group(1)),
                             lambda x : str(x),
                             startup_param=False,
                             default_value=20)
        self.protocol._param_dict.add("qux", r'qux=(.*)',
                             lambda match : int(match.group(1)),
                             lambda x : str(x),
                             startup_param=True)
        self.protocol._param_dict.add("rok", r'rok=(.*)',
                             lambda match : int(match.group(1)),
                             lambda x : str(x))
        self.protocol._param_dict.update("qux=6666")
        
        # mark init params
        self.assertRaises(InstrumentParameterException,
                          self.protocol.set_init_params, [])
        self.protocol.set_init_params({DriverConfigKey.PARAMETERS: {"foo": 1111, "baz":2222}})
        
        # get new startup config
        self.assertRaises(InstrumentProtocolException, self.protocol.get_startup_config)
        self.protocol.set_init_params({DriverConfigKey.PARAMETERS: {"foo": 1111, "baz":2222, "bat": 11, "qux": 22}})
        result = self.protocol.get_startup_config()
        
        self.assertEquals(len(result), 5)
        self.assertEquals(result["foo"], 1111) # init param
        self.assertEquals(result["bar"], 0)    # init param with default value
        self.assertEquals(result["baz"], 2222) # non-init param, but value specified
        self.assertEquals(result["bat"], 11)   # set param
        self.assertEquals(result["qux"], 22)   # set param
        self.assertIsNone(result.get("rok"))   # defined in paramdict, no config

    def test_apply_startup_params(self):
        """
        Test that the apply startup parameters method exists and throws
        a "not implemented" exception for the base class
        """
        self.assertRaises(NotImplementedException,
                          self.protocol.apply_startup_params)

    def test_scheduler(self):
        """
        Test to see that the scheduler can add and remove jobs properly
        Jobs are just queued for adding unit we call initialize_scheduler
        then the jobs are actually created.
        """
        dt = datetime.datetime.now() + datetime.timedelta(0,1)
        job_name = 'test_job'
        startup_config = {
            DriverConfigKey.SCHEDULER: {
                job_name: {
                    DriverSchedulerConfigKey.TRIGGER: {
                        DriverSchedulerConfigKey.TRIGGER_TYPE: TriggerType.ABSOLUTE,
                        DriverSchedulerConfigKey.DATE: dt
                    }
                }
            }
        }

        self.protocol.set_init_params(startup_config)

        # Verify we are initialized properly
        self.assertIsNone(self.protocol._scheduler)
        self.assertEqual(self.protocol._scheduler_config, {})
        self.assertEqual(self.protocol._scheduler_callback, {})

        # Verify the the scheduler is created
        self.protocol.initialize_scheduler()
        self.assertIsInstance(self.protocol._scheduler, DriverScheduler)
        self.assertEqual(self.protocol._scheduler_config, {})
        self.assertEqual(self.protocol._scheduler_callback, {})

        # Now lets see some magic happen.  Lets add our schedulers.  Generally
        # This would be done as part of the protocol init, but it can happen
        # anytime.  If the scheduler has already been initialized the
        # job will be started right away
        self.protocol._add_scheduler(job_name, self._scheduler_callback)
        self.assertEqual(0, self._trigger_count)
        self.assert_scheduled_event_triggered()

    def test_scheduler_event(self):
        """
        Test if we can add and trigger jobs using events instead of callbacks
        We will create two event triggers, foo and bar.  They should come in
        that order.
        """
        self.protocol._protocol_fsm = Mock()
        #self.protocol._fsm.on_event = Mock()

        dt = datetime.datetime.now() + datetime.timedelta(0,1)
        foo_scheduler = 'foo'
        bar_scheduler = 'bar'
        startup_config = {
            DriverConfigKey.SCHEDULER: {
                foo_scheduler: {
                    DriverSchedulerConfigKey.TRIGGER: {
                        DriverSchedulerConfigKey.TRIGGER_TYPE: TriggerType.INTERVAL,
                        DriverSchedulerConfigKey.SECONDS: 1
                    }
                },
                bar_scheduler: {
                    DriverSchedulerConfigKey.TRIGGER: {
                        DriverSchedulerConfigKey.TRIGGER_TYPE: TriggerType.INTERVAL,
                        DriverSchedulerConfigKey.SECONDS: 2
                    }
                }
            }
        }

        self.protocol.set_init_params(startup_config)

        # Verify we are initialized properly
        self.assertIsNone(self.protocol._scheduler)
        self.assertEqual(self.protocol._scheduler_config, {})
        self.assertEqual(self.protocol._scheduler_callback, {})

        # Verify the the scheduler is created
        self.protocol.initialize_scheduler()
        self.assertIsInstance(self.protocol._scheduler, DriverScheduler)
        self.assertEqual(self.protocol._scheduler_config, {})
        self.assertEqual(self.protocol._scheduler_callback, {})

        # Now lets see some magic happen.  Lets add our schedulers.  Generally
        # This would be done as part of the protocol init, but it can happen
        # anytime.  If the scheduler has already been initialized the
        # job will be started right away
        foo_event='foo'
        bar_event='bar'
        self.protocol._add_scheduler_event(foo_scheduler, foo_event)
        self.protocol._add_scheduler_event(bar_scheduler, bar_event)

        self.assertEqual(0, self._trigger_count)