| Index: third_party/psutil/test/test_memory_leaks.py | 
| diff --git a/third_party/psutil/test/test_memory_leaks.py b/third_party/psutil/test/test_memory_leaks.py | 
| index d5591a3c6c6317f111601f6da3d58dfb741a70d1..b6a3a4e7cfd074a5846ba755220e0ad0654e5974 100644 | 
| --- a/third_party/psutil/test/test_memory_leaks.py | 
| +++ b/third_party/psutil/test/test_memory_leaks.py | 
| @@ -1,67 +1,95 @@ | 
| #!/usr/bin/env python | 
| # | 
| -# $Id: test_memory_leaks.py 777 2010-11-08 18:29:13Z g.rodola $ | 
| +# $Id: test_memory_leaks.py 1142 2011-10-05 18:45:49Z g.rodola $ | 
| # | 
| +# Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved. | 
| +# Use of this source code is governed by a BSD-style license that can be | 
| +# found in the LICENSE file. | 
|  | 
| """ | 
| -Note: this is targeted for python 2.x. | 
| -To run it under python 3.x you need to use 2to3 tool first: | 
| - | 
| -$ 2to3 -w test/test_memory_leaks.py | 
| +A test script which attempts to detect memory leaks by calling C | 
| +functions many times and compare process memory usage before and | 
| +after the calls.  It might produce false positives. | 
| """ | 
|  | 
| - | 
| import os | 
| import gc | 
| -import sys | 
| import unittest | 
| +import time | 
|  | 
| import psutil | 
| from test_psutil import reap_children, skipUnless, skipIf, \ | 
| -                        POSIX, LINUX, WINDOWS, OSX, BSD | 
| +                        POSIX, LINUX, WINDOWS, OSX, BSD, PY3 | 
|  | 
| LOOPS = 1000 | 
| TOLERANCE = 4096 | 
|  | 
| +if PY3: | 
| +    xrange = range | 
|  | 
| -class TestProcessObjectLeaks(unittest.TestCase): | 
| -    """Test leaks of Process class methods and properties""" | 
|  | 
| -    def setUp(self): | 
| -        gc.collect() | 
| +class Base(unittest.TestCase): | 
|  | 
| -    def tearDown(self): | 
| -        reap_children() | 
| - | 
| -    def execute(self, method, *args, **kwarks): | 
| +    def execute(self, function, *args, **kwargs): | 
| # step 1 | 
| -        p = psutil.Process(os.getpid()) | 
| for x in xrange(LOOPS): | 
| -            obj = getattr(p, method) | 
| -            if callable(obj): | 
| -                retvalue = obj(*args, **kwarks) | 
| -            else: | 
| -                retvalue = obj  # property | 
| -        del x, p, obj, retvalue | 
| +            self.call(function, *args, **kwargs) | 
| +        del x | 
| gc.collect() | 
| -        rss1 = psutil.Process(os.getpid()).get_memory_info()[0] | 
| +        rss1 = self.get_mem() | 
|  | 
| # step 2 | 
| -        p = psutil.Process(os.getpid()) | 
| for x in xrange(LOOPS): | 
| -            obj = getattr(p, method) | 
| -            if callable(obj): | 
| -                retvalue = obj(*args, **kwarks) | 
| -            else: | 
| -                retvalue = obj  # property | 
| -        del x, p, obj, retvalue | 
| +            self.call(function, *args, **kwargs) | 
| +        del x | 
| gc.collect() | 
| -        rss2 = psutil.Process(os.getpid()).get_memory_info()[0] | 
| +        rss2 = self.get_mem() | 
|  | 
| # comparison | 
| difference = rss2 - rss1 | 
| if difference > TOLERANCE: | 
| -            self.fail("rss1=%s, rss2=%s, difference=%s" %(rss1, rss2, difference)) | 
| +            # This doesn't necessarily mean we have a leak yet. | 
| +            # At this point we assume that after having called the | 
| +            # function so many times the memory usage is stabilized | 
| +            # and if there are no leaks it should not increase any | 
| +            # more. | 
| +            # Let's keep calling fun for 3 more seconds and fail if | 
| +            # we notice any difference. | 
| +            stop_at = time.time() + 3 | 
| +            while 1: | 
| +                self.call(function, *args, **kwargs) | 
| +                if time.time() >= stop_at: | 
| +                    break | 
| +            del stop_at | 
| +            gc.collect() | 
| +            rss3 = self.get_mem() | 
| +            difference = rss3 - rss2 | 
| +            if rss3 > rss2: | 
| +                self.fail("rss2=%s, rss3=%s, difference=%s" \ | 
| +                          % (rss2, rss3, difference)) | 
| + | 
| +    @staticmethod | 
| +    def get_mem(): | 
| +        return psutil.Process(os.getpid()).get_memory_info()[0] | 
| + | 
| +    def call(self): | 
| +        raise NotImplementedError("must be implemented in subclass") | 
| + | 
| + | 
| +class TestProcessObjectLeaks(Base): | 
| +    """Test leaks of Process class methods and properties""" | 
| + | 
| +    def setUp(self): | 
| +        gc.collect() | 
| + | 
| +    def tearDown(self): | 
| +        reap_children() | 
| + | 
| +    def call(self, function, *args, **kwargs): | 
| +        p = psutil.Process(os.getpid()) | 
| +        obj = getattr(p, function) | 
| +        if callable(obj): | 
| +            obj(*args, **kwargs) | 
|  | 
| def test_name(self): | 
| self.execute('name') | 
| @@ -72,11 +100,16 @@ class TestProcessObjectLeaks(unittest.TestCase): | 
| def test_ppid(self): | 
| self.execute('ppid') | 
|  | 
| -    def test_uid(self): | 
| -        self.execute('uid') | 
| +    @skipIf(WINDOWS) | 
| +    def test_uids(self): | 
| +        self.execute('uids') | 
|  | 
| -    def test_uid(self): | 
| -        self.execute('gid') | 
| +    @skipIf(WINDOWS) | 
| +    def test_gids(self): | 
| +        self.execute('gids') | 
| + | 
| +    def test_status(self): | 
| +        self.execute('status') | 
|  | 
| @skipIf(POSIX) | 
| def test_username(self): | 
| @@ -88,6 +121,9 @@ class TestProcessObjectLeaks(unittest.TestCase): | 
| def test_get_num_threads(self): | 
| self.execute('get_num_threads') | 
|  | 
| +    def test_get_threads(self): | 
| +        self.execute('get_threads') | 
| + | 
| def test_get_cpu_times(self): | 
| self.execute('get_cpu_times') | 
|  | 
| @@ -97,6 +133,10 @@ class TestProcessObjectLeaks(unittest.TestCase): | 
| def test_is_running(self): | 
| self.execute('is_running') | 
|  | 
| +    @skipIf(WINDOWS) | 
| +    def test_terminal(self): | 
| +        self.execute('terminal') | 
| + | 
| @skipUnless(WINDOWS) | 
| def test_resume(self): | 
| self.execute('resume') | 
| @@ -105,48 +145,25 @@ class TestProcessObjectLeaks(unittest.TestCase): | 
| def test_getcwd(self): | 
| self.execute('getcwd') | 
|  | 
| -    @skipUnless(WINDOWS) | 
| +    @skipUnless(WINDOWS or OSX) | 
| def test_get_open_files(self): | 
| self.execute('get_open_files') | 
|  | 
| -    @skipUnless(WINDOWS) | 
| +    @skipUnless(WINDOWS or OSX) | 
| def test_get_connections(self): | 
| self.execute('get_connections') | 
|  | 
|  | 
| -class TestModuleFunctionsLeaks(unittest.TestCase): | 
| +class TestModuleFunctionsLeaks(Base): | 
| """Test leaks of psutil module functions.""" | 
|  | 
| def setUp(self): | 
| gc.collect() | 
|  | 
| -    def execute(self, function, *args, **kwarks): | 
| -        # step 1 | 
| -        for x in xrange(LOOPS): | 
| -            obj = getattr(psutil, function) | 
| -            if callable(obj): | 
| -                retvalue = obj(*args, **kwarks) | 
| -            else: | 
| -                retvalue = obj  # property | 
| -        del x, obj, retvalue | 
| -        gc.collect() | 
| -        rss1 = psutil.Process(os.getpid()).get_memory_info()[0] | 
| - | 
| -        # step 2 | 
| -        for x in xrange(LOOPS): | 
| -            obj = getattr(psutil, function) | 
| -            if callable(obj): | 
| -                retvalue = obj(*args, **kwarks) | 
| -            else: | 
| -                retvalue = obj  # property | 
| -        del x, obj, retvalue | 
| -        gc.collect() | 
| -        rss2 = psutil.Process(os.getpid()).get_memory_info()[0] | 
| - | 
| -        # comparison | 
| -        difference = rss2 - rss1 | 
| -        if difference > TOLERANCE: | 
| -            self.fail("rss1=%s, rss2=%s, difference=%s" %(rss1, rss2, difference)) | 
| +    def call(self, function, *args, **kwargs): | 
| +        obj = getattr(psutil, function) | 
| +        if callable(obj): | 
| +            retvalue = obj(*args, **kwargs) | 
|  | 
| def test_get_pid_list(self): | 
| self.execute('get_pid_list') | 
| @@ -158,24 +175,30 @@ class TestModuleFunctionsLeaks(unittest.TestCase): | 
| def test_process_iter(self): | 
| self.execute('process_iter') | 
|  | 
| -    def test_used_phymem(self): | 
| -        self.execute('used_phymem') | 
| +    def test_phymem_usage(self): | 
| +        self.execute('phymem_usage') | 
| + | 
| +    def test_virtmem_usage(self): | 
| +        self.execute('virtmem_usage') | 
|  | 
| -    def test_avail_phymem(self): | 
| -        self.execute('avail_phymem') | 
| +    def test_cpu_times(self): | 
| +        self.execute('cpu_times') | 
|  | 
| -    def test_total_virtmem(self): | 
| -        self.execute('total_virtmem') | 
| +    def test_per_cpu_times(self): | 
| +        self.execute('cpu_times', percpu=True) | 
|  | 
| -    def test_used_virtmem(self): | 
| -        self.execute('used_virtmem') | 
| +    @skipUnless(WINDOWS) | 
| +    def test_disk_usage(self): | 
| +        self.execute('disk_usage', '.') | 
|  | 
| -    def test_avail_virtmem(self): | 
| -        self.execute('avail_virtmem') | 
| +    def test_disk_partitions(self): | 
| +        self.execute('disk_partitions') | 
|  | 
| -    def test_cpu_times(self): | 
| -        self.execute('cpu_times') | 
| +    def test_network_io_counters(self): | 
| +        self.execute('network_io_counters') | 
|  | 
| +    def test_disk_io_counters(self): | 
| +        self.execute('disk_io_counters') | 
|  | 
| def test_main(): | 
| test_suite = unittest.TestSuite() | 
|  |