def run_test(self): result = None timeout_duration = 10 # Default test case timeout event_queue = Queue() # Events from DUT to host dut_event_queue = Queue() # Events from host to DUT {k;v} def callback__notify_prn(key, value, timestamp): """! Handles __norify_prn. Prints all lines in separate log line """ for line in value.splitlines(): self.logger.prn_inf(line) callbacks = { "__notify_prn" : callback__notify_prn } # if True we will allow host test to consume all events after test is finished callbacks_consume = True # Flag check if __exit event occurred callbacks__exit = False # Handle to dynamically loaded host test object self.test_supervisor = None # Version: greentea-client version from DUT self.client_version = None self.logger.prn_inf("starting host test process...") def start_conn_process(): # Create device info here as it may change after restart. config = { "digest" : "serial", "port" : self.mbed.port, "baudrate" : self.mbed.serial_baud, "program_cycle_s" : self.options.program_cycle_s, "reset_type" : self.options.forced_reset_type } # DUT-host communication process args = (event_queue, dut_event_queue, self.prn_lock, config) p = Process(target=conn_process, args=args) p.deamon = True p.start() return p p = start_conn_process() start_time = time() try: consume_preamble_events = True while (time() - start_time) < timeout_duration: # Handle default events like timeout, host_test_name, ... if not event_queue.empty(): try: (key, value, timestamp) = event_queue.get(timeout=1) except QueueEmpty: continue if consume_preamble_events: if key == '__timeout': # Override default timeout for this event queue start_time = time() timeout_duration = int(value) # New timeout self.logger.prn_inf("setting timeout to: %d sec"% int(value)) elif key == '__version': self.client_version = value self.logger.prn_inf("DUT greentea-client version: " + self.client_version) elif key == '__host_test_name': # Load dynamically requested host test self.test_supervisor = get_host_test(value) if self.test_supervisor: # Pass communication queues and setup() host test self.test_supervisor.setup_communication(event_queue, dut_event_queue) try: # After setup() user should already register all callbacks self.test_supervisor.setup() except (TypeError, ValueError): # setup() can throw in normal circumstances TypeError and ValueError self.logger.prn_err("host test setup() failed, reason:") self.logger.prn_inf("==== Traceback start ====") for line in traceback.format_exc().splitlines(): print line self.logger.prn_inf("==== Traceback end ====") result = self.RESULT_ERROR break self.logger.prn_inf("host test setup() call...") if self.test_supervisor.get_callbacks(): callbacks.update(self.test_supervisor.get_callbacks()) self.logger.prn_inf("CALLBACKs updated") else: self.logger.prn_wrn("no CALLBACKs specified by host test") self.logger.prn_inf("host test detected: %s"% value) else: self.logger.prn_err("host test not detected: %s"% value) consume_preamble_events = False elif key == '__sync': # This is DUT-Host Test handshake event self.logger.prn_inf("sync KV found, uuid=%s, timestamp=%f"% (str(value), timestamp)) elif key == '__notify_conn_lost': # This event is sent by conn_process, DUT connection was lost self.logger.prn_err(value) self.logger.prn_wrn("stopped to consume events due to %s event"% key) callbacks_consume = False result = self.RESULT_IO_SERIAL break elif key.startswith('__'): # Consume other system level events pass else: self.logger.prn_err("orphan event in preamble phase: {{%s;%s}}, timestamp=%f"% (key, str(value), timestamp)) else: if key == '__notify_complete': # This event is sent by Host Test, test result is in value # or if value is None, value will be retrieved from HostTest.result() method self.logger.prn_inf("%s(%s)"% (key, str(value))) result = value break elif key == '__reset_dut': # Disconnecting and re-connecting comm process will reset DUT dut_event_queue.put(('__host_test_finished', True, time())) p.join() # self.mbed.update_device_info() - This call is commented but left as it would be required in hard reset. p = start_conn_process() elif key == '__notify_conn_lost': # This event is sent by conn_process, DUT connection was lost self.logger.prn_err(value) self.logger.prn_wrn("stopped to consume events due to %s event"% key) callbacks_consume = False result = self.RESULT_IO_SERIAL break elif key == '__exit': # This event is sent by DUT, test suite exited self.logger.prn_inf("%s(%s)"% (key, str(value))) callbacks__exit = True break elif key in callbacks: # Handle callback callbacks[key](key, value, timestamp) else: self.logger.prn_err("orphan event in main phase: {{%s;%s}}, timestamp=%f"% (key, str(value), timestamp)) except Exception: self.logger.prn_err("something went wrong in event main loop!") self.logger.prn_inf("==== Traceback start ====") for line in traceback.format_exc().splitlines(): print line self.logger.prn_inf("==== Traceback end ====") result = self.RESULT_ERROR time_duration = time() - start_time self.logger.prn_inf("test suite run finished after %.2f sec..."% time_duration) # Force conn_proxy process to return dut_event_queue.put(('__host_test_finished', True, time())) p.join() self.logger.prn_inf("CONN exited with code: %s"% str(p.exitcode)) # Callbacks... self.logger.prn_inf("No events in queue" if event_queue.empty() else "Some events in queue") # If host test was used we will: # 1. Consume all existing events in queue if consume=True # 2. Check result from host test and call teardown() if callbacks_consume: # We are consuming all remaining events if requested while not event_queue.empty(): try: (key, value, timestamp) = event_queue.get(timeout=1) except QueueEmpty: break if key == '__notify_complete': # This event is sent by Host Test, test result is in value # or if value is None, value will be retrieved from HostTest.result() method self.logger.prn_inf("%s(%s)"% (key, str(value))) result = value elif key.startswith('__'): # Consume other system level events pass elif key in callbacks: callbacks[key](key, value, timestamp) else: self.logger.prn_wrn(">>> orphan event: {{%s;%s}}, timestamp=%f"% (key, str(value), timestamp)) self.logger.prn_inf("stopped consuming events") if result is not None: # We must compare here against None! # Here for example we've received some error code like IOERR_COPY self.logger.prn_inf("host test result() call skipped, received: %s"% str(result)) else: if self.test_supervisor: result = self.test_supervisor.result() self.logger.prn_inf("host test result(): %s"% str(result)) if not callbacks__exit: self.logger.prn_wrn("missing __exit event from DUT") #if not callbacks__exit and not result: if not callbacks__exit and result is None: self.logger.prn_err("missing __exit event from DUT and no result from host test, timeout...") result = self.RESULT_TIMEOUT self.logger.prn_inf("calling blocking teardown()") if self.test_supervisor: self.test_supervisor.teardown() self.logger.prn_inf("teardown() finished") return result
def run_test(self): result = None timeout_duration = 10 # Default test case timeout event_queue = Queue() # Events from DUT to host dut_event_queue = Queue() # Events from host to DUT {k;v} def callback__notify_prn(key, value, timestamp): """! Handles __norify_prn. Prints all lines in separate log line """ for line in value.splitlines(): self.logger.prn_inf(line) callbacks = {"__notify_prn": callback__notify_prn} # if True we will allow host test to consume all events after test is finished callbacks_consume = True # Flag check if __exit event occurred callbacks__exit = False # Handle to dynamically loaded host test object self.test_supervisor = None # Version: greentea-client version from DUT self.client_version = None self.logger.prn_inf("starting host test process...") def start_conn_process(): # Create device info here as it may change after restart. config = { "digest": "serial", "port": self.mbed.port, "baudrate": self.mbed.serial_baud, "program_cycle_s": self.options.program_cycle_s, "reset_type": self.options.forced_reset_type } # DUT-host communication process args = (event_queue, dut_event_queue, self.prn_lock, config) p = Process(target=conn_process, args=args) p.deamon = True p.start() return p p = start_conn_process() start_time = time() try: consume_preamble_events = True while (time() - start_time) < timeout_duration: # Handle default events like timeout, host_test_name, ... if not event_queue.empty(): try: (key, value, timestamp) = event_queue.get(timeout=1) except QueueEmpty: continue if consume_preamble_events: if key == '__timeout': # Override default timeout for this event queue start_time = time() timeout_duration = int(value) # New timeout self.logger.prn_inf("setting timeout to: %d sec" % int(value)) elif key == '__version': self.client_version = value self.logger.prn_inf( "DUT greentea-client version: " + self.client_version) elif key == '__host_test_name': # Load dynamically requested host test self.test_supervisor = get_host_test(value) if self.test_supervisor: # Pass communication queues and setup() host test self.test_supervisor.setup_communication( event_queue, dut_event_queue) try: # After setup() user should already register all callbacks self.test_supervisor.setup() except (TypeError, ValueError): # setup() can throw in normal circumstances TypeError and ValueError self.logger.prn_err( "host test setup() failed, reason:") self.logger.prn_inf( "==== Traceback start ====") for line in traceback.format_exc( ).splitlines(): print line self.logger.prn_inf( "==== Traceback end ====") result = self.RESULT_ERROR break self.logger.prn_inf( "host test setup() call...") if self.test_supervisor.get_callbacks(): callbacks.update( self.test_supervisor.get_callbacks()) self.logger.prn_inf("CALLBACKs updated") else: self.logger.prn_wrn( "no CALLBACKs specified by host test") self.logger.prn_inf("host test detected: %s" % value) else: self.logger.prn_err( "host test not detected: %s" % value) consume_preamble_events = False elif key == '__sync': # This is DUT-Host Test handshake event self.logger.prn_inf( "sync KV found, uuid=%s, timestamp=%f" % (str(value), timestamp)) elif key == '__notify_conn_lost': # This event is sent by conn_process, DUT connection was lost self.logger.prn_err(value) self.logger.prn_wrn( "stopped to consume events due to %s event" % key) callbacks_consume = False result = self.RESULT_IO_SERIAL break elif key.startswith('__'): # Consume other system level events pass else: self.logger.prn_err( "orphan event in preamble phase: {{%s;%s}}, timestamp=%f" % (key, str(value), timestamp)) else: if key == '__notify_complete': # This event is sent by Host Test, test result is in value # or if value is None, value will be retrieved from HostTest.result() method self.logger.prn_inf("%s(%s)" % (key, str(value))) result = value break elif key == '__reset_dut': # Disconnecting and re-connecting comm process will reset DUT dut_event_queue.put( ('__host_test_finished', True, time())) p.join() # self.mbed.update_device_info() - This call is commented but left as it would be required in hard reset. p = start_conn_process() elif key == '__notify_conn_lost': # This event is sent by conn_process, DUT connection was lost self.logger.prn_err(value) self.logger.prn_wrn( "stopped to consume events due to %s event" % key) callbacks_consume = False result = self.RESULT_IO_SERIAL break elif key == '__exit': # This event is sent by DUT, test suite exited self.logger.prn_inf("%s(%s)" % (key, str(value))) callbacks__exit = True break elif key in callbacks: # Handle callback callbacks[key](key, value, timestamp) else: self.logger.prn_err( "orphan event in main phase: {{%s;%s}}, timestamp=%f" % (key, str(value), timestamp)) except Exception: self.logger.prn_err("something went wrong in event main loop!") self.logger.prn_inf("==== Traceback start ====") for line in traceback.format_exc().splitlines(): print line self.logger.prn_inf("==== Traceback end ====") result = self.RESULT_ERROR time_duration = time() - start_time self.logger.prn_inf("test suite run finished after %.2f sec..." % time_duration) # Force conn_proxy process to return dut_event_queue.put(('__host_test_finished', True, time())) p.join() self.logger.prn_inf("CONN exited with code: %s" % str(p.exitcode)) # Callbacks... self.logger.prn_inf("No events in queue" if event_queue.empty( ) else "Some events in queue") # If host test was used we will: # 1. Consume all existing events in queue if consume=True # 2. Check result from host test and call teardown() if callbacks_consume: # We are consuming all remaining events if requested while not event_queue.empty(): try: (key, value, timestamp) = event_queue.get(timeout=1) except QueueEmpty: break if key == '__notify_complete': # This event is sent by Host Test, test result is in value # or if value is None, value will be retrieved from HostTest.result() method self.logger.prn_inf("%s(%s)" % (key, str(value))) result = value elif key.startswith('__'): # Consume other system level events pass elif key in callbacks: callbacks[key](key, value, timestamp) else: self.logger.prn_wrn( ">>> orphan event: {{%s;%s}}, timestamp=%f" % (key, str(value), timestamp)) self.logger.prn_inf("stopped consuming events") if result is not None: # We must compare here against None! # Here for example we've received some error code like IOERR_COPY self.logger.prn_inf( "host test result() call skipped, received: %s" % str(result)) else: if self.test_supervisor: result = self.test_supervisor.result() self.logger.prn_inf("host test result(): %s" % str(result)) if not callbacks__exit: self.logger.prn_wrn("missing __exit event from DUT") #if not callbacks__exit and not result: if not callbacks__exit and result is None: self.logger.prn_err( "missing __exit event from DUT and no result from host test, timeout..." ) result = self.RESULT_TIMEOUT self.logger.prn_inf("calling blocking teardown()") if self.test_supervisor: self.test_supervisor.teardown() self.logger.prn_inf("teardown() finished") return result
def run_test(self): """! This function implements key-value protocol state-machine. Handling of all events and connector are handled here. @return Return self.TestResults.RESULT_* enum """ result = None timeout_duration = 10 # Default test case timeout event_queue = Queue() # Events from DUT to host dut_event_queue = Queue() # Events from host to DUT {k;v} def callback__notify_prn(key, value, timestamp): """! Handles __norify_prn. Prints all lines in separate log line """ for line in value.splitlines(): self.logger.prn_inf(line) callbacks = { "__notify_prn" : callback__notify_prn } # if True we will allow host test to consume all events after test is finished callbacks_consume = True # Flag check if __exit event occurred callbacks__exit = False # Flag check if __exit_event_queue event occurred callbacks__exit_event_queue = False # Handle to dynamically loaded host test object self.test_supervisor = None # Version: greentea-client version from DUT self.client_version = None self.logger.prn_inf("starting host test process...") def start_conn_process(): # Create device info here as it may change after restart. config = { "digest" : "serial", "port" : self.mbed.port, "baudrate" : self.mbed.serial_baud, "program_cycle_s" : self.options.program_cycle_s, "reset_type" : self.options.forced_reset_type, "target_id" : self.options.target_id, "serial_pooling" : self.options.pooling_timeout, "forced_reset_timeout" : self.options.forced_reset_timeout, "sync_behavior" : self.options.sync_behavior, "platform_name" : self.options.micro, "image_path" : self.mbed.image_path, } if self.options.global_resource_mgr: grm_module, grm_host, grm_port = self.options.global_resource_mgr.split(':') config.update({ "conn_resource" : 'grm', "grm_module" : grm_module, "grm_host" : grm_host, "grm_port" : grm_port, }) # DUT-host communication process args = (event_queue, dut_event_queue, config) p = Process(target=conn_process, args=args) p.deamon = True p.start() return p p = start_conn_process() start_time = time() try: consume_preamble_events = True while (time() - start_time) < timeout_duration: # Handle default events like timeout, host_test_name, ... try: (key, value, timestamp) = event_queue.get(timeout=1) except QueueEmpty: continue if consume_preamble_events: if key == '__timeout': # Override default timeout for this event queue start_time = time() timeout_duration = int(value) # New timeout self.logger.prn_inf("setting timeout to: %d sec"% int(value)) elif key == '__version': self.client_version = value self.logger.prn_inf("DUT greentea-client version: " + self.client_version) elif key == '__host_test_name': # Load dynamically requested host test self.test_supervisor = get_host_test(value) # Check if host test object loaded is actually host test class # derived from 'mbed_host_tests.BaseHostTest()' # Additionaly if host test class implements custom ctor it should # call BaseHostTest().__Init__() if self.test_supervisor and self.is_host_test_obj_compatible(self.test_supervisor): # Pass communication queues and setup() host test self.test_supervisor.setup_communication(event_queue, dut_event_queue) try: # After setup() user should already register all callbacks self.test_supervisor.setup() except (TypeError, ValueError): # setup() can throw in normal circumstances TypeError and ValueError self.logger.prn_err("host test setup() failed, reason:") self.logger.prn_inf("==== Traceback start ====") for line in traceback.format_exc().splitlines(): print line self.logger.prn_inf("==== Traceback end ====") result = self.RESULT_ERROR event_queue.put(('__exit_event_queue', 0, time())) self.logger.prn_inf("host test setup() call...") if self.test_supervisor.get_callbacks(): callbacks.update(self.test_supervisor.get_callbacks()) self.logger.prn_inf("CALLBACKs updated") else: self.logger.prn_wrn("no CALLBACKs specified by host test") self.logger.prn_inf("host test detected: %s"% value) else: self.logger.prn_err("host test not detected: %s"% value) result = self.RESULT_ERROR event_queue.put(('__exit_event_queue', 0, time())) consume_preamble_events = False elif key == '__sync': # This is DUT-Host Test handshake event self.logger.prn_inf("sync KV found, uuid=%s, timestamp=%f"% (str(value), timestamp)) elif key == '__notify_conn_lost': # This event is sent by conn_process, DUT connection was lost self.logger.prn_err(value) self.logger.prn_wrn("stopped to consume events due to %s event"% key) callbacks_consume = False result = self.RESULT_IO_SERIAL event_queue.put(('__exit_event_queue', 0, time())) elif key == '__exit_event_queue': # This event is sent by the host test indicating no more events expected self.logger.prn_inf("%s received"% (key)) callbacks__exit_event_queue = True break elif key.startswith('__'): # Consume other system level events pass else: self.logger.prn_err("orphan event in preamble phase: {{%s;%s}}, timestamp=%f"% (key, str(value), timestamp)) else: if key == '__notify_complete': # This event is sent by Host Test, test result is in value # or if value is None, value will be retrieved from HostTest.result() method self.logger.prn_inf("%s(%s)"% (key, str(value))) result = value elif key == '__reset_dut': # Disconnect to avoid connection lost event dut_event_queue.put(('__host_test_finished', True, time())) p.join() if value == DefaultTestSelector.RESET_TYPE_SW_RST: self.logger.prn_inf("Performing software reset.") # Just disconnecting and re-connecting comm process will soft reset DUT elif value == DefaultTestSelector.RESET_TYPE_HW_RST: self.logger.prn_inf("Performing hard reset.") # request hardware reset self.mbed.hw_reset() else: self.logger.prn_err("Invalid reset type (%s). Supported types [%s]." % (value, ", ".join([DefaultTestSelector.RESET_TYPE_HW_RST, DefaultTestSelector.RESET_TYPE_SW_RST]))) self.logger.prn_inf("Software reset will be performed.") # connect to the device p = start_conn_process() elif key == '__notify_conn_lost': # This event is sent by conn_process, DUT connection was lost self.logger.prn_err(value) self.logger.prn_wrn("stopped to consume events due to %s event"% key) callbacks_consume = False result = self.RESULT_IO_SERIAL event_queue.put(('__exit_event_queue', 0, time())) elif key == '__exit': # This event is sent by DUT, test suite exited self.logger.prn_inf("%s(%s)"% (key, str(value))) callbacks__exit = True event_queue.put(('__exit_event_queue', 0, time())) elif key == '__exit_event_queue': # This event is sent by the host test indicating no more events expected self.logger.prn_inf("%s received"% (key)) callbacks__exit_event_queue = True break elif key in callbacks: # Handle callback callbacks[key](key, value, timestamp) else: self.logger.prn_err("orphan event in main phase: {{%s;%s}}, timestamp=%f"% (key, str(value), timestamp)) except Exception: self.logger.prn_err("something went wrong in event main loop!") self.logger.prn_inf("==== Traceback start ====") for line in traceback.format_exc().splitlines(): print line self.logger.prn_inf("==== Traceback end ====") result = self.RESULT_ERROR time_duration = time() - start_time self.logger.prn_inf("test suite run finished after %.2f sec..."% time_duration) # Force conn_proxy process to return dut_event_queue.put(('__host_test_finished', True, time())) p.join() self.logger.prn_inf("CONN exited with code: %s"% str(p.exitcode)) # Callbacks... self.logger.prn_inf("No events in queue" if event_queue.empty() else "Some events in queue") # If host test was used we will: # 1. Consume all existing events in queue if consume=True # 2. Check result from host test and call teardown() # NOTE: with the introduction of the '__exit_event_queue' event, there # should never be left events assuming the DUT has stopped sending data # over the serial data. Leaving this for now to catch anything that slips through. if callbacks_consume: # We are consuming all remaining events if requested while not event_queue.empty(): try: (key, value, timestamp) = event_queue.get(timeout=1) except QueueEmpty: break if key == '__notify_complete': # This event is sent by Host Test, test result is in value # or if value is None, value will be retrieved from HostTest.result() method self.logger.prn_inf("%s(%s)"% (key, str(value))) result = value elif key.startswith('__'): # Consume other system level events pass elif key in callbacks: callbacks[key](key, value, timestamp) else: self.logger.prn_wrn(">>> orphan event: {{%s;%s}}, timestamp=%f"% (key, str(value), timestamp)) self.logger.prn_inf("stopped consuming events") if result is not None: # We must compare here against None! # Here for example we've received some error code like IOERR_COPY self.logger.prn_inf("host test result() call skipped, received: %s"% str(result)) else: if self.test_supervisor: result = self.test_supervisor.result() self.logger.prn_inf("host test result(): %s"% str(result)) if not callbacks__exit: self.logger.prn_wrn("missing __exit event from DUT") if not callbacks__exit_event_queue: self.logger.prn_wrn("missing __exit_event_queue event from host test") #if not callbacks__exit_event_queue and not result: if not callbacks__exit_event_queue and result is None: self.logger.prn_err("missing __exit_event_queue event from " + \ "host test and no result from host test, timeout...") result = self.RESULT_TIMEOUT self.logger.prn_inf("calling blocking teardown()") if self.test_supervisor: self.test_supervisor.teardown() self.logger.prn_inf("teardown() finished") return result
def test_basic_get_host_test(self): self.assertNotEqual(None, get_host_test("default")) self.assertNotEqual(None, get_host_test("default_auto"))
def test_basic_get_host_test(self): self.assertNotEqual(None, get_host_test('default')) self.assertNotEqual(None, get_host_test('default_auto'))
def run_test(self): """! This function implements key-value protocol state-machine. Handling of all events and connector are handled here. @return Return self.TestResults.RESULT_* enum """ result = None timeout_duration = 10 # Default test case timeout coverage_idle_timeout = 10 # Default coverage idle timeout event_queue = Queue() # Events from DUT to host dut_event_queue = Queue() # Events from host to DUT {k;v} def callback__notify_prn(key, value, timestamp): """! Handles __norify_prn. Prints all lines in separate log line """ for line in value.splitlines(): self.logger.prn_inf(line) callbacks = {"__notify_prn": callback__notify_prn} # if True we will allow host test to consume all events after test is finished callbacks_consume = True # Flag check if __exit event occurred callbacks__exit = False # Flag check if __exit_event_queue event occurred callbacks__exit_event_queue = False # Handle to dynamically loaded host test object self.test_supervisor = None # Version: greentea-client version from DUT self.client_version = None self.logger.prn_inf("starting host test process...") def start_conn_process(): # Create device info here as it may change after restart. config = { "digest": "serial", "port": self.mbed.port, "baudrate": self.mbed.serial_baud, "program_cycle_s": self.options.program_cycle_s, "reset_type": self.options.forced_reset_type, "target_id": self.options.target_id, "serial_pooling": self.options.pooling_timeout, "forced_reset_timeout": self.options.forced_reset_timeout, "sync_behavior": self.options.sync_behavior, "platform_name": self.options.micro, "image_path": self.mbed.image_path, } if self.options.global_resource_mgr: grm_module, grm_host, grm_port = self.options.global_resource_mgr.split( ':') config.update({ "conn_resource": 'grm', "grm_module": grm_module, "grm_host": grm_host, "grm_port": grm_port, }) # DUT-host communication process args = (event_queue, dut_event_queue, config) p = Process(target=conn_process, args=args) p.deamon = True p.start() return p def process_code_coverage(key, value, timestamp): """! Process the found coverage key value and perform an idle loop checking for more timeing out if there is no response from the target within the idle timeout. @param key The key from the first coverage event @param value The value from the first coverage event @param timestamp The timestamp from the first coverage event @return The elapsed time taken by the processing of code coverage, and the (key, value, and timestamp) of the next event """ original_start_time = time() start_time = time() # Perform callback on first event callbacks[key](key, value, timestamp) # Start idle timeout loop looking for other events while (time() - start_time) < coverage_idle_timeout: try: (key, value, timestamp) = event_queue.get(timeout=1) except QueueEmpty: continue # If coverage detected use idle loop # Prevent breaking idle loop for __rxd_line (occurs between keys) if key == '__coverage_start' or key == '__rxd_line': start_time = time() # Perform callback callbacks[key](key, value, timestamp) continue elapsed_time = time() - original_start_time return elapsed_time, (key, value, timestamp) p = start_conn_process() conn_process_started = False try: (key, value, timestamp) = event_queue.get( timeout=self.options.process_start_timeout) if key == '__conn_process_start': conn_process_started = True else: self.logger.prn_err( "First expected event was '__conn_process_start', received '%s' instead" % key) except QueueEmpty: self.logger.prn_err("Conn process failed to start in %f sec" % self.options.process_start_timeout) if not conn_process_started: p.terminate() return self.RESULT_TIMEOUT start_time = time() try: consume_preamble_events = True while (time() - start_time) < timeout_duration: # Handle default events like timeout, host_test_name, ... try: (key, value, timestamp) = event_queue.get(timeout=1) except QueueEmpty: continue if consume_preamble_events: if key == '__timeout': # Override default timeout for this event queue start_time = time() timeout_duration = int(value) # New timeout self.logger.prn_inf("setting timeout to: %d sec" % int(value)) elif key == '__version': self.client_version = value self.logger.prn_inf("DUT greentea-client version: " + self.client_version) elif key == '__host_test_name': # Load dynamically requested host test self.test_supervisor = get_host_test(value) # Check if host test object loaded is actually host test class # derived from 'mbed_host_tests.BaseHostTest()' # Additionaly if host test class implements custom ctor it should # call BaseHostTest().__Init__() if self.test_supervisor and self.is_host_test_obj_compatible( self.test_supervisor): # Pass communication queues and setup() host test self.test_supervisor.setup_communication( event_queue, dut_event_queue) try: # After setup() user should already register all callbacks self.test_supervisor.setup() except (TypeError, ValueError): # setup() can throw in normal circumstances TypeError and ValueError self.logger.prn_err( "host test setup() failed, reason:") self.logger.prn_inf( "==== Traceback start ====") for line in traceback.format_exc().splitlines( ): print line self.logger.prn_inf("==== Traceback end ====") result = self.RESULT_ERROR event_queue.put( ('__exit_event_queue', 0, time())) self.logger.prn_inf("host test setup() call...") if self.test_supervisor.get_callbacks(): callbacks.update( self.test_supervisor.get_callbacks()) self.logger.prn_inf("CALLBACKs updated") else: self.logger.prn_wrn( "no CALLBACKs specified by host test") self.logger.prn_inf("host test detected: %s" % value) else: self.logger.prn_err("host test not detected: %s" % value) result = self.RESULT_ERROR event_queue.put(('__exit_event_queue', 0, time())) consume_preamble_events = False elif key == '__sync': # This is DUT-Host Test handshake event self.logger.prn_inf( "sync KV found, uuid=%s, timestamp=%f" % (str(value), timestamp)) elif key == '__notify_conn_lost': # This event is sent by conn_process, DUT connection was lost self.logger.prn_err(value) self.logger.prn_wrn( "stopped to consume events due to %s event" % key) callbacks_consume = False result = self.RESULT_IO_SERIAL event_queue.put(('__exit_event_queue', 0, time())) elif key == '__exit_event_queue': # This event is sent by the host test indicating no more events expected self.logger.prn_inf("%s received" % (key)) callbacks__exit_event_queue = True break elif key.startswith('__'): # Consume other system level events pass else: self.logger.prn_err( "orphan event in preamble phase: {{%s;%s}}, timestamp=%f" % (key, str(value), timestamp)) else: # If coverage detected switch to idle loop if key == '__coverage_start': self.logger.prn_inf( "starting coverage idle timeout loop...") elapsed_time, (key, value, timestamp) = process_code_coverage( key, value, timestamp) # Ignore the time taken by the code coverage timeout_duration += elapsed_time self.logger.prn_inf( "exiting coverage idle timeout loop (elapsed_time: %.2f" % elapsed_time) if key == '__notify_complete': # This event is sent by Host Test, test result is in value # or if value is None, value will be retrieved from HostTest.result() method self.logger.prn_inf("%s(%s)" % (key, str(value))) result = value elif key == '__reset_dut': # Disconnect to avoid connection lost event dut_event_queue.put( ('__host_test_finished', True, time())) p.join() if value == DefaultTestSelector.RESET_TYPE_SW_RST: self.logger.prn_inf("Performing software reset.") # Just disconnecting and re-connecting comm process will soft reset DUT elif value == DefaultTestSelector.RESET_TYPE_HW_RST: self.logger.prn_inf("Performing hard reset.") # request hardware reset self.mbed.hw_reset() else: self.logger.prn_err( "Invalid reset type (%s). Supported types [%s]." % (value, ", ".join([ DefaultTestSelector.RESET_TYPE_HW_RST, DefaultTestSelector.RESET_TYPE_SW_RST ]))) self.logger.prn_inf( "Software reset will be performed.") # connect to the device p = start_conn_process() elif key == '__notify_conn_lost': # This event is sent by conn_process, DUT connection was lost self.logger.prn_err(value) self.logger.prn_wrn( "stopped to consume events due to %s event" % key) callbacks_consume = False result = self.RESULT_IO_SERIAL event_queue.put(('__exit_event_queue', 0, time())) elif key == '__exit': # This event is sent by DUT, test suite exited self.logger.prn_inf("%s(%s)" % (key, str(value))) callbacks__exit = True event_queue.put(('__exit_event_queue', 0, time())) elif key == '__exit_event_queue': # This event is sent by the host test indicating no more events expected self.logger.prn_inf("%s received" % (key)) callbacks__exit_event_queue = True break elif key in callbacks: # Handle callback callbacks[key](key, value, timestamp) else: self.logger.prn_err( "orphan event in main phase: {{%s;%s}}, timestamp=%f" % (key, str(value), timestamp)) except Exception: self.logger.prn_err("something went wrong in event main loop!") self.logger.prn_inf("==== Traceback start ====") for line in traceback.format_exc().splitlines(): print line self.logger.prn_inf("==== Traceback end ====") result = self.RESULT_ERROR time_duration = time() - start_time self.logger.prn_inf("test suite run finished after %.2f sec..." % time_duration) # Force conn_proxy process to return dut_event_queue.put(('__host_test_finished', True, time())) p.join() self.logger.prn_inf("CONN exited with code: %s" % str(p.exitcode)) # Callbacks... self.logger.prn_inf("No events in queue" if event_queue.empty( ) else "Some events in queue") # If host test was used we will: # 1. Consume all existing events in queue if consume=True # 2. Check result from host test and call teardown() # NOTE: with the introduction of the '__exit_event_queue' event, there # should never be left events assuming the DUT has stopped sending data # over the serial data. Leaving this for now to catch anything that slips through. if callbacks_consume: # We are consuming all remaining events if requested while not event_queue.empty(): try: (key, value, timestamp) = event_queue.get(timeout=1) except QueueEmpty: break if key == '__notify_complete': # This event is sent by Host Test, test result is in value # or if value is None, value will be retrieved from HostTest.result() method self.logger.prn_inf("%s(%s)" % (key, str(value))) result = value elif key.startswith('__'): # Consume other system level events pass elif key in callbacks: callbacks[key](key, value, timestamp) else: self.logger.prn_wrn( ">>> orphan event: {{%s;%s}}, timestamp=%f" % (key, str(value), timestamp)) self.logger.prn_inf("stopped consuming events") if result is not None: # We must compare here against None! # Here for example we've received some error code like IOERR_COPY self.logger.prn_inf( "host test result() call skipped, received: %s" % str(result)) else: if self.test_supervisor: result = self.test_supervisor.result() self.logger.prn_inf("host test result(): %s" % str(result)) if not callbacks__exit: self.logger.prn_wrn("missing __exit event from DUT") if not callbacks__exit_event_queue: self.logger.prn_wrn( "missing __exit_event_queue event from host test") #if not callbacks__exit_event_queue and not result: if not callbacks__exit_event_queue and result is None: self.logger.prn_err("missing __exit_event_queue event from " + \ "host test and no result from host test, timeout...") result = self.RESULT_TIMEOUT self.logger.prn_inf("calling blocking teardown()") if self.test_supervisor: self.test_supervisor.teardown() self.logger.prn_inf("teardown() finished") return result