Example #1
0
    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
Example #2
0
    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
Example #3
0
    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
Example #4
0
 def test_basic_get_host_test(self):
     self.assertNotEqual(None, get_host_test("default"))
     self.assertNotEqual(None, get_host_test("default_auto"))
Example #5
0
 def test_basic_get_host_test(self):
     self.assertNotEqual(None, get_host_test('default'))
     self.assertNotEqual(None, get_host_test('default_auto'))
Example #6
0
    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