def run(self, timeout=None):
        """\
        Run the expectation loop on the testcase until all
        expectations pass or the timeout is exceeded.

        :param int timeout: (optional) maximum time to wait for all
          expectations to be met (defaults to
          :attr:`tcfl.expecter.expecter_c.timeout`)
        """
        if timeout == None:
            timeout = self._timeout
        else:
            assert isinstance(timeout, int)
        # Fresh start
        self.buffers.clear()
        self.ts0 = time.time()
        _active_ts = self.ts0
        functors_pending = self.functors
        while True:
            ts = time.time()
            td = ts - self.ts0
            _functors_pending = list(functors_pending)

            for f, a, has_to_pass in _functors_pending:
                if a == None:
                    args = (self, )
                else:
                    args = (self, ) + a
                try:
                    self._log("running %s %s @%s" %
                              (f.__name__, f.origin, args),
                              dlevel=5)
                    _ts0 = time.time()
                    r = f(*args)
                    _ts1 = time.time()
                except tc.pass_e as e:
                    if has_to_pass:
                        # Report pass information, including attachments
                        tc.result_c.report_from_exception(self.testcase, e)
                        r = True

                # Once it passes, we don't check it anymore
                if has_to_pass and r != None:
                    self.remove(f, a)
                    # if this returned normally or raised a tc.pass_e,
                    # then it means the test passed; except if it
                    # returns None, then ignore it (might have
                    # been a poller)
                    if self.have_to_pass == 0:
                        raise tc.pass_e("all expectations found")

            # Check like this because we want to run the check
            # functions before determining a timeout as some of them
            # might also check on their own and offer better messages
            if td >= self.timeout:
                raise tc.error_e("Timed out (%.2fs)" % self.timeout)
            if ts - _active_ts > self.active_period:
                self.testcase._targets_active()
                _active_ts = ts
            time.sleep(self._poll_period)
Beispiel #2
0
    def run(self, timeout = None):
        """\
        Run the expectation loop on the testcase until all
        expectations pass or the timeout is exceeded.

        :param int timeout: (optional) maximum time to wait for all
          expectations to be met (defaults to
          :attr:`tcfl.expecter.expecter_c.timeout`)
        """
        if timeout == None:
            timeout = self._timeout
        else:
            assert isinstance(timeout, int)
        # Fresh start
        self.buffers.clear()
        self.ts0 = time.time()
        _active_ts = self.ts0
        functors_pending = self.functors
        while True:
            ts = time.time()
            td = ts - self.ts0
            _functors_pending = list(functors_pending)

            for f, a, has_to_pass in _functors_pending:
                if a == None:
                    args = (self,)
                else:
                    args = (self, ) + a
                try:
                    self._log(
                        "running %s %s @%s" % (f.__name__, f.origin, args),
                        dlevel = 5)
                    _ts0 = time.time()
                    r = f(*args)
                    _ts1 = time.time()
                except tc.pass_e as e:
                    if has_to_pass:
                        # Report pass information, including attachments
                        tc.result_c.report_from_exception(self.testcase, e)
                        r = True

                # Once it passes, we don't check it anymore
                if has_to_pass and r != None:
                    self.remove(f, a)
                    # if this returned normally or raised a tc.pass_e,
                    # then it means the test passed; except if it
                    # returns None, then ignore it (might have
                    # been a poller)
                    if self.have_to_pass == 0:
                        raise tc.pass_e("all expectations found")

            # Check like this because we want to run the check
            # functions before determining a timeout as some of them
            # might also check on their own and offer better messages
            if td >= self.timeout:
                raise tc.error_e("Timed out (%.2fs)" % self.timeout)
            if ts - _active_ts > self.active_period:
                self.testcase._targets_active()
                _active_ts = ts
            time.sleep(self._poll_period)
def console_rx_eval(expecter,
                    target,
                    regex,
                    console=None,
                    _timeout=None,
                    result=None,
                    uid=None):
    """
    Check what came on a console and act on it

    :param str uid: (optional) identifier to use to store offset data
    """

    if hasattr(regex, "pattern"):
        what = regex.pattern
    else:
        what = regex
        regex = re.compile(re.escape(regex))

    if not uid:
        uid = console_mk_uid(target, what, console, _timeout, result)

    console_id_name, console_code = console_mk_code(target, console)
    # These were set by the poller
    of = expecter.buffers.get(console_code, None)
    if of == None:
        # FIXME: debug lof output here? expecter->tc backlink?
        return None
    ofd = of.fileno()
    ts = time.time()

    # Get the offset we saved before as the last part where we looked
    # at. If none, then get the last offset the poller has
    # recorded. Otherwise, just default to look from the start
    # Note the idea is each eval function has a different offset where
    # it is looking at. Likewise the poller for each console.
    offset_poller_code = "offset_" + console_code
    offset = expecter.buffers_persistent.get(
        uid, expecter.buffers_persistent.get(offset_poller_code, 0))
    if _timeout != False:
        timeout = expecter.timeout if _timeout == None else _timeout

        # We can do timeout checks that provide better information
        # than a generic 'timeout'
        if ts - expecter.ts0 > timeout:
            of.seek(offset)  # so we report console from where searched
            raise tc.error_e(
                "expected console output '%s' from console '%s:%s' " \
                "NOT FOUND after %.1f s" \
                % (what, target.id, console_id_name, ts - expecter.ts0),
                { 'target': target, "console output": of })

    # mmap the whole file (which doesn't alter the file pointer)
    #
    # We have to mmap as the file might be getting huge and thus,
    # reading line by line might be dumb.
    #
    # However, we only search starting at @offset, which is set later
    # to the last success searching we had. So we shan't really map
    # the whole file, shall map on demand.

    stat_info = os.fstat(ofd)
    if stat_info.st_size == 0:  # Nothing to read
        return None

    with contextlib.closing(
            mmap.mmap(of.fileno(), 0, mmap.MAP_PRIVATE, mmap.PROT_READ,
                      0)) as mapping:
        target.report_info("looking for `%s` in console %s:%s @%d-%d at "
                           "%.2fs [%s]" %
                           (what, target.fullid, console_id_name, offset,
                            stat_info.st_size, ts - expecter.ts0, of.name),
                           dlevel=3)
        m = regex.search(mapping[offset:])
        if m:
            new_offset = offset + m.end()
            expecter.buffers_persistent[uid] = new_offset
            if result == None or result == "pass":
                # raising pass gets stopped at expecter.run(), so we
                # print instead, so we can see the console
                offset_tip = of.tell()  # we report console from where searched
                of.seek(offset)  # so we report console from where searched
                target.report_pass(
                    "found expected `%s` in console `%s:%s` at %.2fs @%d" %
                    (what, target.fullid, console_id_name, ts - expecter.ts0,
                     offset + m.start()), {"console output": of},
                    dlevel=1,
                    alevel=2)
                of.seek(offset_tip)
                raise tc.pass_e(
                    "found expected `%s` in console `%s:%s` at %.2fs" %
                    (what, target.fullid, console_id_name, ts - expecter.ts0),
                    {'target': target})
            elif result == "fail":
                of.seek(offset)  # so we report console from where searched
                raise tc.failed_e(
                    "found expected (for failure) `%s` in console "
                    "`%s:%s` at %.2fs" %
                    (what, target.fullid, console_id_name, ts - expecter.ts0),
                    {
                        'target': target,
                        "console output": of
                    })
            elif result == "error" or result == "errr":
                of.seek(offset)  # so we report console from where searched
                raise tc.error_e(
                    "found expected (for error) `%s` in console "
                    "`%s:%s` at %.2fs" %
                    (what, target.fullid, console_id_name, ts - expecter.ts0),
                    {
                        'target': target,
                        "console output": of
                    })
            elif result == "skip":
                of.seek(offset)  # so we report console from where searched
                raise tc.skip_e(
                    "found expected (for skip) `%s` in console "
                    "'%s:%s' at %.2fs" %
                    (what, target.fullid, console_id_name, ts - expecter.ts0),
                    {
                        'target': target,
                        "console output": of
                    })
            else:
                of.seek(offset)  # so we report console from where searched
                raise tc.blocked_e("BUG: invalid result requested (%s)" %
                                   result)
    return None
Beispiel #4
0
def console_rx_eval(expecter, target,
                    regex, console = None, _timeout = None, result = None,
                    uid = None):
    """
    Check what came on a console and act on it

    :param str uid: (optional) identifier to use to store offset data
    """

    if hasattr(regex, "pattern"):
        what = regex.pattern
    else:
        what = regex
        regex = re.compile(re.escape(regex))

    if not uid:
        uid = console_mk_uid(target, what, console, _timeout, result)

    console_id_name, console_code = console_mk_code(target, console)
    # These were set by the poller
    of = expecter.buffers.get(console_code, None)
    if of == None:
        # FIXME: debug lof output here? expecter->tc backlink?
        return None
    ofd = of.fileno()
    ts = time.time()

    # Get the offset we saved before as the last part where we looked
    # at. If none, then get the last offset the poller has
    # recorded. Otherwise, just default to look from the start
    # Note the idea is each eval function has a different offset where
    # it is looking at. Likewise the poller for each console.
    offset_poller_code = "offset_" + console_code
    offset = expecter.buffers_persistent.get(
        uid,
        expecter.buffers_persistent.get(offset_poller_code, 0))
    if _timeout != False:
        timeout = expecter.timeout if _timeout == None else _timeout

        # We can do timeout checks that provide better information
        # than a generic 'timeout'
        if ts - expecter.ts0 > timeout:
            of.seek(offset)	# so we report console from where searched
            raise tc.error_e(
                "expected console output '%s' from console '%s:%s' " \
                "NOT FOUND after %.1f s" \
                % (what, target.id, console_id_name, ts - expecter.ts0),
                { 'target': target, "console output": of })

    # mmap the whole file (which doesn't alter the file pointer)
    #
    # We have to mmap as the file might be getting huge and thus,
    # reading line by line might be dumb.
    #
    # However, we only search starting at @offset, which is set later
    # to the last success searching we had. So we shan't really map
    # the whole file, shall map on demand.

    stat_info = os.fstat(ofd)
    if stat_info.st_size == 0:	# Nothing to read
        return None

    with contextlib.closing(mmap.mmap(of.fileno(), 0, mmap.MAP_PRIVATE,
                                      mmap.PROT_READ, 0)) as mapping:
        target.report_info("looking for `%s` in console %s:%s @%d-%d at "
                           "%.2fs [%s]"
                           % (what, target.fullid, console_id_name, offset,
                              stat_info.st_size, ts - expecter.ts0, of.name),
                           dlevel = 3)
        m = regex.search(mapping[offset:])
        if m:
            new_offset = offset + m.end()
            expecter.buffers_persistent[uid] = new_offset
            if result == None or result == "pass":
                # raising pass gets stopped at expecter.run(), so we
                # print instead, so we can see the console
                offset_tip = of.tell()	# we report console from where searched
                of.seek(offset)	# so we report console from where searched
                target.report_pass(
                    "found expected `%s` in console `%s:%s` at %.2fs"
                    % (what, target.fullid, console_id_name,
                       ts - expecter.ts0),
                    { "console output": of }, dlevel = 1, alevel = 2)
                of.seek(offset_tip)
                raise tc.pass_e(
                    "found expected `%s` in console `%s:%s` at %.2fs"
                    % (what, target.fullid, console_id_name,
                       ts - expecter.ts0),
                    {'target': target })
            elif result == "fail":
                of.seek(offset)	# so we report console from where searched
                raise tc.failed_e(
                    "found expected (for failure) `%s` in console "
                    "`%s:%s` at %.2fs"
                    % (what, target.fullid, console_id_name,
                       ts - expecter.ts0),
                    { 'target': target, "console output": of })
            elif result == "error" or result == "errr":
                of.seek(offset)	# so we report console from where searched
                raise tc.error_e(
                    "found expected (for error) `%s` in console "
                    "`%s:%s` at %.2fs"
                    % (what, target.fullid, console_id_name,
                       ts - expecter.ts0),
                    { 'target': target, "console output": of })
            elif result == "skip":
                of.seek(offset)	# so we report console from where searched
                raise tc.skip_e(
                    "found expected (for skip) `%s` in console "
                    "'%s:%s' at %.2fs"
                    % (what, target.fullid, console_id_name,
                       ts - expecter.ts0),
                    { 'target': target, "console output": of })
            else:
                of.seek(offset)	# so we report console from where searched
                raise tc.blocked_e(
                    "BUG: invalid result requested (%s)" % result)
    return None