Example #1
0
    def getloadavg(self):
        for line in self.read_lines():
            line = line.rstrip()

            # Ignore the initial header:
            # "(PDH-CSV 4.0)","\\\\WIN\\System\\Processor Queue Length"
            if 'PDH-CSV' in line:
                continue

            # Ignore blank lines
            if not line:
                continue

            try:
                load = self._parse_line(line)
            except ValueError:
                print_warning("Failed to parse typeperf output: %a" % line)
                continue

            # We use an exponentially weighted moving average, imitating the
            # load calculation on Unix systems.
            # https://en.wikipedia.org/wiki/Load_(computing)#Unix-style_load_calculation
            new_load = self.load * LOAD_FACTOR_1 + load * (1.0 - LOAD_FACTOR_1)
            self.load = new_load

        return self.load
Example #2
0
def cleanup_test_droppings(test_name: str, verbose: int) -> None:
    # Try to clean up junk commonly left behind.  While tests shouldn't leave
    # any files or directories behind, when a test fails that can be tedious
    # for it to arrange.  The consequences can be especially nasty on Windows,
    # since if a test leaves a file open, it cannot be deleted by name (while
    # there's nothing we can do about that here either, we can display the
    # name of the offending test, which is a real help).
    for name in (os_helper.TESTFN,):
        if not os.path.exists(name):
            continue

        if os.path.isdir(name):
            import shutil
            kind, nuker = "directory", shutil.rmtree
        elif os.path.isfile(name):
            kind, nuker = "file", os.unlink
        else:
            raise RuntimeError(f"os.path says {name!r} exists but is neither "
                               f"directory nor file")

        if verbose:
            print_warning(f"{test_name} left behind {kind} {name!r}")
            support.environment_altered = True

        try:
            import stat
            # fix possible permissions problems that might prevent cleanup
            os.chmod(name, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO)
            nuker(name)
        except Exception as exc:
            print_warning(f"{test_name} left behind {kind} {name!r} "
                          f"and it couldn't be removed: {exc}")
Example #3
0
    def _kill(self) -> None:
        popen = self._popen
        if popen is None:
            return

        if self._killed:
            return
        self._killed = True

        if USE_PROCESS_GROUP:
            what = f"{self} process group"
        else:
            what = f"{self}"

        print(f"Kill {what}", file=sys.stderr, flush=True)
        try:
            if USE_PROCESS_GROUP:
                os.killpg(popen.pid, signal.SIGKILL)
            else:
                popen.kill()
        except ProcessLookupError:
            # popen.kill(): the process completed, the TestWorkerProcess thread
            # read its exit status, but Popen.send_signal() read the returncode
            # just before Popen.wait() set returncode.
            pass
        except OSError as exc:
            print_warning(f"Failed to kill {what}: {exc!r}")
Example #4
0
    def _wait_completed(self) -> None:
        popen = self._popen

        try:
            popen.wait(JOIN_TIMEOUT)
        except (subprocess.TimeoutExpired, OSError) as exc:
            print_warning(f"Failed to wait for {self} completion "
                          f"(timeout={format_duration(JOIN_TIMEOUT)}): "
                          f"{exc!r}")
 def wait_stopped(self, start_time):
     while True:
         # Write a message every second
         self.join(1.0)
         if not self.is_alive():
             break
         dt = time.monotonic() - start_time
         print(f"Waiting for {self} thread for {format_duration(dt)}", flush=True)
         if dt > JOIN_TIMEOUT:
             print_warning(f"Failed to join {self} in {format_duration(dt)}")
             break
Example #6
0
def _runtest_inner2(ns, test_name):
    # Load the test function, run the test function, handle huntrleaks
    # and findleaks to detect leaks

    abstest = get_abs_module(ns, test_name)

    # remove the module from sys.module to reload it if it was already imported
    support.unload(abstest)

    try:
        the_module = importlib.import_module(abstest)

        # If the test has a test_main, that will run the appropriate
        # tests.  If not, use normal unittest test loading.
        test_runner = getattr(the_module, "test_main", None)
        if test_runner is None:
            test_runner = functools.partial(_test_module, the_module)
    except ModuleNotFoundError:

        def test_runner():
            loader = unittest.TestLoader()
            tests = loader.loadTestsFromName(abstest)
            for error in loader.errors:
                print(error, file=sys.stderr)
            if loader.errors:
                raise Exception("errors while loading tests")
            support.run_unittest(tests)

    try:
        if ns.huntrleaks:
            # Return True if the test leaked references
            refleak = dash_R(ns, test_name, test_runner)
        else:
            test_runner()
            refleak = False
    finally:
        cleanup_test_droppings(test_name, ns.verbose)

    support.gc_collect()

    if gc.garbage:
        support.environment_altered = True
        print_warning(f"{test_name} created {len(gc.garbage)} "
                      f"uncollectable object(s).")

        # move the uncollectable objects somewhere,
        # so we don't see them again
        FOUND_GARBAGE.extend(gc.garbage)
        gc.garbage.clear()

    support.reap_children()

    return refleak
Example #7
0
def _runtest_inner2(ns: Namespace, test_name: str) -> bool:
    # Load the test function, run the test function, handle huntrleaks
    # and findleaks to detect leaks

    abstest = get_abs_module(ns, test_name)

    # remove the module from sys.module to reload it if it was already imported
    try:
        del sys.modules[abstest]
    except KeyError:
        pass

    the_module = importlib.import_module(abstest)

    if ns.huntrleaks:
        from test.libregrtest.refleak import dash_R

    # If the test has a test_main, that will run the appropriate
    # tests.  If not, use normal unittest test loading.
    test_runner = getattr(the_module, "test_main", None)
    if test_runner is None:
        test_runner = functools.partial(_test_module, the_module)

    try:
        with save_env(ns, test_name):
            if ns.huntrleaks:
                # Return True if the test leaked references
                refleak = dash_R(ns, test_name, test_runner)
            else:
                test_runner()
                refleak = False
    finally:
        # First kill any dangling references to open files etc.
        # This can also issue some ResourceWarnings which would otherwise get
        # triggered during the following test run, and possibly produce
        # failures.
        support.gc_collect()

        cleanup_test_droppings(test_name, ns.verbose)

    if gc.garbage:
        support.environment_altered = True
        print_warning(f"{test_name} created {len(gc.garbage)} "
                      f"uncollectable object(s).")

        # move the uncollectable objects somewhere,
        # so we don't see them again
        FOUND_GARBAGE.extend(gc.garbage)
        gc.garbage.clear()

    support.reap_children()

    return refleak
Example #8
0
    def _wait_completed(self) -> None:
        popen = self._popen

        # stdout must be closed to ensure that communicate() does not hang
        popen.stdout.close()

        try:
            popen.wait(JOIN_TIMEOUT)
        except (subprocess.TimeoutExpired, OSError) as exc:
            print_warning(f"Failed to wait for {self} completion "
                          f"(timeout={format_duration(JOIN_TIMEOUT)}): "
                          f"{exc!r}")
Example #9
0
    def _timedout(self, test_name):
        self._kill()

        stdout = stderr = ''
        popen = self._popen
        try:
            stdout, stderr = popen.communicate(timeout=JOIN_TIMEOUT)
        except (subprocess.TimeoutExpired, OSError) as exc:
            print_warning(f"Failed to read {self} output "
                          f"(timeout={format_duration(JOIN_TIMEOUT)}): "
                          f"{exc!r}")

        return self.mp_result_error(test_name, TIMEOUT, stdout, stderr)
    def _kill(self):
        popen = self._popen
        if popen is None:
            return

        if self._killed:
            return
        self._killed = True

        print(f"Kill {self}", file=sys.stderr, flush=True)
        try:
            popen.kill()
        except OSError as exc:
            print_warning(f"Failed to kill {self}: {exc!r}")
Example #11
0
def _runtest_inner2(ns, test_name):
    # Load the test function, run the test function, handle huntrleaks
    # and findleaks to detect leaks

    abstest = get_abs_module(ns, test_name)

    # remove the module from sys.module to reload it if it was already imported
    try:
        del sys.modules[abstest]
    except KeyError:
        pass

    the_module = importlib.import_module(abstest)

    if ns.huntrleaks:
        from test.libregrtest.refleak import dash_R

    # If the test has a test_main, that will run the appropriate
    # tests.  If not, use normal unittest test loading.
    test_runner = getattr(the_module, "test_main", None)
    if test_runner is None:
        test_runner = functools.partial(_test_module, the_module)

    try:
        with save_env(ns, test_name):
            if ns.huntrleaks:
                # Return True if the test leaked references
                refleak = dash_R(ns, test_name, test_runner)
            else:
                test_runner()
                refleak = False
    finally:
        cleanup_test_droppings(test_name, ns.verbose)

    support.gc_collect()

    if gc.garbage:
        support.environment_altered = True
        print_warning(f"{test_name} created {len(gc.garbage)} "
                      f"uncollectable object(s).")

        # move the uncollectable objects somewhere,
        # so we don't see them again
        FOUND_GARBAGE.extend(gc.garbage)
        gc.garbage.clear()

    support.reap_children()

    return refleak
Example #12
0
    def getloadavg(self):
        if self._popen is None:
            return None

        returncode = self._popen.poll()
        if returncode is not None:
            self.close(kill=False)
            return None

        try:
            lines = self._read_lines()
        except BrokenPipeError:
            self.close()
            return None

        for line in lines:
            line = line.rstrip()

            # Ignore the initial header:
            # "(PDH-CSV 4.0)","\\\\WIN\\System\\Processor Queue Length"
            if 'PDH-CSV' in line:
                continue

            # Ignore blank lines
            if not line:
                continue

            try:
                processor_queue_length = self._parse_line(line)
            except ValueError:
                print_warning("Failed to parse typeperf output: %a" % line)
                continue

            # We use an exponentially weighted moving average, imitating the
            # load calculation on Unix systems.
            # https://en.wikipedia.org/wiki/Load_(computing)#Unix-style_load_calculation
            # https://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average
            if self._load is not None:
                self._load = (self._load * LOAD_FACTOR_1 +
                              processor_queue_length * (1.0 - LOAD_FACTOR_1))
            elif len(self._values) < NVALUE:
                self._values.append(processor_queue_length)
            else:
                self._load = sum(self._values) / len(self._values)

        return self._load
Example #13
0
    def __exit__(self, exc_type, exc_val, exc_tb):
        saved_values = self.saved_values
        self.saved_values = None

        # Some resources use weak references
        support.gc_collect()

        for name, get, restore, original in saved_values:
            current = get()
            # Check for changes to the resource's value
            if current != original:
                support.environment_altered = True
                restore(original)
                if not self.quiet and not self.pgo:
                    print_warning(f"{name} was modified by {self.testname}\n"
                                  f"  Before: {original}\n"
                                  f"  After:  {current} ")
        return False
Example #14
0
def _runtest_inner2(ns, test_name):
    # Load the test function, run the test function, handle huntrleaks
    # and findleaks to detect leaks

    abstest = get_abs_module(ns, test_name)

    # remove the module from sys.module to reload it if it was already imported
    support.unload(abstest)

    the_module = importlib.import_module(abstest)

    # If the test has a test_main, that will run the appropriate
    # tests.  If not, use normal unittest test loading.
    test_runner = getattr(the_module, "test_main", None)
    if test_runner is None:
        test_runner = functools.partial(_test_module, the_module)

    try:
        if ns.huntrleaks:
            # Return True if the test leaked references
            refleak = dash_R(ns, test_name, test_runner)
        else:
            test_runner()
            refleak = False
    finally:
        cleanup_test_droppings(test_name, ns.verbose)

    if ns.findleaks:
        import gc
        support.gc_collect()
        if gc.garbage:
            import gc
            gc.garbage = [1]
            print_warning(f"{test_name} created {len(gc.garbage)} "
                          f"uncollectable object(s).")
            # move the uncollectable objects somewhere,
            # so we don't see them again
            found_garbage.extend(gc.garbage)
            gc.garbage.clear()
            support.environment_altered = True

    post_test_cleanup()

    return refleak
Example #15
0
    def _kill(self):
        popen = self._popen
        if popen is None:
            return

        if self._killed:
            return
        self._killed = True

        print(f"Kill {self}", file=sys.stderr, flush=True)
        try:
            popen.kill()
        except ProcessLookupError:
            # Process completed, the TestWorkerProcess thread read its exit
            # status, but Popen.send_signal() read the returncode just before
            # Popen.wait() set returncode.
            pass
        except OSError as exc:
            print_warning(f"Failed to kill {self}: {exc!r}")
Example #16
0
    def _process_result(self, item: QueueOutput) -> bool:
        """Returns True if test runner must stop."""
        if item[0]:
            # Thread got an exception
            format_exc = item[1]
            print_warning(f"regrtest worker thread failed: {format_exc}")
            return True

        self.test_index += 1
        mp_result = item[1]
        self.regrtest.accumulate_result(mp_result.result)
        self.display_result(mp_result)

        if mp_result.stdout:
            print(mp_result.stdout, flush=True)

        if must_stop(mp_result.result, self.ns):
            return True

        return False
    def _process_result(self, item):
        if item[0]:
            # Thread got an exception
            format_exc = item[1]
            print_warning(f"regrtest worker thread failed: {format_exc}")
            return True

        self.test_index += 1
        mp_result = item[1]
        self.regrtest.accumulate_result(mp_result.result)
        self.display_result(mp_result)

        if mp_result.stdout:
            print(mp_result.stdout, flush=True)
        if mp_result.stderr and not self.ns.pgo:
            print(mp_result.stderr, file=sys.stderr, flush=True)

        if must_stop(mp_result.result, self.ns):
            return True

        return False
Example #18
0
def cleanup_test_droppings(test_name, verbose):
    # First kill any dangling references to open files etc.
    # This can also issue some ResourceWarnings which would otherwise get
    # triggered during the following test run, and possibly produce failures.
    support.gc_collect()

    # Try to clean up junk commonly left behind.  While tests shouldn't leave
    # any files or directories behind, when a test fails that can be tedious
    # for it to arrange.  The consequences can be especially nasty on Windows,
    # since if a test leaves a file open, it cannot be deleted by name (while
    # there's nothing we can do about that here either, we can display the
    # name of the offending test, which is a real help).
    for name in (
            support.TESTFN,
            "db_home",
    ):
        if not os.path.exists(name):
            continue

        if os.path.isdir(name):
            import shutil
            kind, nuker = "directory", shutil.rmtree
        elif os.path.isfile(name):
            kind, nuker = "file", os.unlink
        else:
            raise RuntimeError(f"os.path says {name!r} exists but is neither "
                               f"directory nor file")

        if verbose:
            print_warning("%r left behind %s %r" % (test_name, kind, name))
            support.environment_altered = True

        try:
            import stat
            # fix possible permissions problems that might prevent cleanup
            os.chmod(name, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO)
            nuker(name)
        except Exception as exc:
            print_warning(f"{test_name} left behind {kind} {name!r} "
                          f"and it couldn't be removed: {exc}")
Example #19
0
    def __exit__(self, exc_type, exc_val, exc_tb):
        saved_values = self.saved_values
        del self.saved_values

        # Some resources use weak references
        support.gc_collect()

        # Read support.environment_altered, set by support helper functions
        self.changed |= support.environment_altered

        for name, get, restore in self.resource_info():
            current = get()
            original = saved_values.pop(name)
            # Check for changes to the resource's value
            if current != original:
                self.changed = True
                restore(original)
                if not self.quiet and not self.pgo:
                    print_warning(f"{name} was modified by {self.testname}")
                    print(f"  Before: {original}\n  After:  {current} ",
                          file=sys.stderr, flush=True)
        return False
Example #20
0
 def wait_stopped(self, start_time):
     # bpo-38207: MultiprocessTestRunner.stop_workers() called self.stop()
     # which killed the process. Sometimes, killing the process from the
     # main thread does not interrupt popen.communicate() in
     # TestWorkerProcess thread. This loop with a timeout is a workaround
     # for that.
     #
     # Moreover, if this method fails to join the thread, it is likely
     # that Python will hang at exit while calling threading._shutdown()
     # which tries again to join the blocked thread. Regrtest.main()
     # uses EXIT_TIMEOUT to workaround this second bug.
     while True:
         # Write a message every second
         self.join(1.0)
         if not self.is_alive():
             break
         dt = time.monotonic() - start_time
         self.regrtest.log(f"Waiting for {self} thread "
                           f"for {format_duration(dt)}")
         if dt > JOIN_TIMEOUT:
             print_warning(f"Failed to join {self} in {format_duration(dt)}")
             break
    def getloadavg(self):
        typeperf_output = self.read_output()
        # Nothing to update, just return the current load
        if not typeperf_output:
            return self.load

        # Process the backlog of load values
        for line in typeperf_output.splitlines():
            # Ignore the initial header:
            # "(PDH-CSV 4.0)","\\\\WIN\\System\\Processor Queue Length"
            if '\\\\' in line:
                continue

            # Ignore blank lines
            if not line.strip():
                continue

            # typeperf outputs in a CSV format like this:
            # "07/19/2018 01:32:26.605","3.000000"
            # (date, process queue length)
            try:
                tokens = line.split(',')
                if len(tokens) != 2:
                    raise ValueError

                value = tokens[1].replace('"', '')
                load = float(value)
            except ValueError:
                print_warning("Failed to parse typeperf output: %a" % line)
                continue

            # We use an exponentially weighted moving average, imitating the
            # load calculation on Unix systems.
            # https://en.wikipedia.org/wiki/Load_(computing)#Unix-style_load_calculation
            new_load = self.load * LOAD_FACTOR_1 + load * (1.0 - LOAD_FACTOR_1)
            self.load = new_load

        return self.load