From d37bbaae2fe4fdd04e57d20fec38b6ab15493689 Mon Sep 17 00:00:00 2001 From: Iain Bullard Date: Wed, 12 Jul 2017 08:47:24 +0000 Subject: [PATCH] fix: fix _precache memory leak from LazySuite LazySuite keeps all a reference to all tests (even those that have been run) under self._precache. When running a large number of tests this can cause nose to use up all available system memory. This makes running the whole test suite impossible. This change fixes that issue and keeps the behaviour of LazySuite.__nonzero__ intact. All tests pass under python 2.7 that passed prior to the change (there are some for the coverage plugin that didn't and still don't pass). --- nose/suite.py | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/nose/suite.py b/nose/suite.py index a3699a1a..48bffbbb 100644 --- a/nose/suite.py +++ b/nose/suite.py @@ -66,6 +66,7 @@ def __hash__(self): def addTest(self, test): self._precache.append(test) + self._had_precache = True # added to bypass run changes in 2.7's unittest def run(self, result): @@ -79,21 +80,21 @@ def __nonzero__(self): log.debug("tests in %s?", id(self)) if self._precache: return True - if self.test_generator is None: - return False - try: - test = self.test_generator.next() - if test is not None: - self._precache.append(test) - return True - except StopIteration: - pass - return False + if self.test_generator is not None: + try: + test = self.test_generator.next() + if test is not None: + self.addTest(test) + return True + except StopIteration: + pass + + return self._had_precache def _get_tests(self): log.debug("precache is %s", self._precache) - for test in self._precache: - yield test + while self._precache: + yield self._precache.pop(0) if self.test_generator is None: return for test in self.test_generator: @@ -101,6 +102,7 @@ def _get_tests(self): def _set_tests(self, tests): self._precache = [] + self._had_precache = False is_suite = isinstance(tests, unittest.TestSuite) if callable(tests) and not is_suite: self.test_generator = tests()