This file is indexed.

/usr/share/pyshared/zope/testrunner/testrunner-leaks.txt is in python-zope.testrunner 4.0.3-3.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
Debugging Memory Leaks
======================

The --report-refcounts (-r) option can be used with the --repeat (-N)
option to detect and diagnose memory leaks.  To use this option, you
must configure Python with the --with-pydebug option. (On Unix, pass
this option to configure and then build Python.)

    >>> import os.path, sys
    >>> directory_with_tests = os.path.join(this_directory, 'testrunner-ex')
    >>> defaults = [
    ...     '--path', directory_with_tests,
    ...     '--tests-pattern', '^sampletestsf?$',
    ...     ]

    >>> from zope import testrunner
    
    >>> sys.argv = 'test --layer Layer11$ --layer Layer12$ -N4 -r'.split()
    >>> _ = testrunner.run_internal(defaults)
    Running samplelayers.Layer11 tests:
      Set up samplelayers.Layer1 in 0.000 seconds.
      Set up samplelayers.Layer11 in 0.000 seconds.
    Iteration 1
      Ran 26 tests with 0 failures and 0 errors in 0.013 seconds.
    Iteration 2
      Ran 26 tests with 0 failures and 0 errors in 0.012 seconds.
      sys refcount=100401   change=0     
    Iteration 3
      Ran 26 tests with 0 failures and 0 errors in 0.012 seconds.
      sys refcount=100401   change=0     
    Iteration 4
      Ran 26 tests with 0 failures and 0 errors in 0.013 seconds.
      sys refcount=100401   change=0     
    Running samplelayers.Layer12 tests:
      Tear down samplelayers.Layer11 in 0.000 seconds.
      Set up samplelayers.Layer12 in 0.000 seconds.
    Iteration 1
      Ran 26 tests with 0 failures and 0 errors in 0.013 seconds.
    Iteration 2
      Ran 26 tests with 0 failures and 0 errors in 0.012 seconds.
      sys refcount=100411   change=0     
    Iteration 3
      Ran 26 tests with 0 failures and 0 errors in 0.012 seconds.
      sys refcount=100411   change=0     
    Iteration 4
      Ran 26 tests with 0 failures and 0 errors in 0.012 seconds.
      sys refcount=100411   change=0     
    Tearing down left over layers:
      Tear down samplelayers.Layer12 in 0.000 seconds.
      Tear down samplelayers.Layer1 in 0.000 seconds.
    Total: 68 tests, 0 failures, 0 errors in N.NNN seconds.

Each layer is repeated the requested number of times.  For each
iteration after the first, the system refcount and change in system
refcount is shown. The system refcount is the total of all refcount in
the system.  When a refcount on any object is changed, the system
refcount is changed by the same amount.  Tests that don't leak show
zero changes in systen refcount.

Let's look at an example test that leaks:

    >>> sys.argv = 'test --tests-pattern leak -N4 -r'.split()
    >>> _ = testrunner.run_internal(defaults)
    Running zope.testrunner.layer.UnitTests tests:...
    Iteration 1
      Ran 1 tests with 0 failures and 0 errors in 0.000 seconds.
    Iteration 2
      Ran 1 tests with 0 failures and 0 errors in 0.000 seconds.
      sys refcount=92506    change=12
    Iteration 3
      Ran 1 tests with 0 failures and 0 errors in 0.000 seconds.
      sys refcount=92513    change=12
    Iteration 4
      Ran 1 tests with 0 failures and 0 errors in 0.000 seconds.
      sys refcount=92520    change=12
    Tearing down left over layers:
      Tear down zope.testrunner.layer.UnitTests in N.NNN seconds.

Here we see that the system refcount is increating.  If we specify a
verbosity greater than one, we can get details broken out by object
type (or class):

    >>> sys.argv = 'test --tests-pattern leak -N5 -r -v'.split()
    >>> _ = testrunner.run_internal(defaults)
    Running tests at level 1
    Running zope.testrunner.layer.UnitTests tests:...
    Iteration 1
      Running:
        .
      Ran 1 tests with 0 failures and 0 errors in 0.000 seconds.
    Iteration 2
      Running:
        .
      Ran 1 tests with 0 failures and 0 errors in 0.000 seconds.
      sum detail refcount=95832    sys refcount=105668   change=16    
        Leak details, changes in instances and refcounts by type/class:
        type/class                                               insts   refs
        -------------------------------------------------------  -----   ----
        classobj                                                     0      1
        dict                                                         2      2
        float                                                        1      1
        int                                                          2      2
        leak.ClassicLeakable                                         1      1
        leak.Leakable                                                1      1
        str                                                          0      4
        tuple                                                        1      1
        type                                                         0      3
        -------------------------------------------------------  -----   ----
        total                                                        8     16
    Iteration 3
      Running:
        .
      Ran 1 tests with 0 failures and 0 errors in 0.000 seconds.
      sum detail refcount=95844    sys refcount=105680   change=12    
        Leak details, changes in instances and refcounts by type/class:
        type/class                                               insts   refs
        -------------------------------------------------------  -----   ----
        classobj                                                     0      1
        dict                                                         2      2
        float                                                        1      1
        int                                                         -1      0
        leak.ClassicLeakable                                         1      1
        leak.Leakable                                                1      1
        str                                                          0      4
        tuple                                                        1      1
        type                                                         0      1
        -------------------------------------------------------  -----   ----
        total                                                        5     12
    Iteration 4
      Running:
        .
      Ran 1 tests with 0 failures and 0 errors in 0.000 seconds.
      sum detail refcount=95856    sys refcount=105692   change=12    
        Leak details, changes in instances and refcounts by type/class:
        type/class                                               insts   refs
        -------------------------------------------------------  -----   ----
        classobj                                                     0      1
        dict                                                         2      2
        float                                                        1      1
        leak.ClassicLeakable                                         1      1
        leak.Leakable                                                1      1
        str                                                          0      4
        tuple                                                        1      1
        type                                                         0      1
        -------------------------------------------------------  -----   ----
        total                                                        6     12
    Iteration 5
      Running:
        .
      Ran 1 tests with 0 failures and 0 errors in 0.000 seconds.
      sum detail refcount=95868    sys refcount=105704   change=12    
        Leak details, changes in instances and refcounts by type/class:
        type/class                                               insts   refs
        -------------------------------------------------------  -----   ----
        classobj                                                     0      1
        dict                                                         2      2
        float                                                        1      1
        leak.ClassicLeakable                                         1      1
        leak.Leakable                                                1      1
        str                                                          0      4
        tuple                                                        1      1
        type                                                         0      1
        -------------------------------------------------------  -----   ----
        total                                                        6     12
    Tearing down left over layers:
      Tear down zope.testrunner.layer.UnitTests in N.NNN seconds.

It is instructive to analyze the results in some detail.  The test
being run was designed to intentionally leak:

    class ClassicLeakable:
        def __init__(self):
            self.x = 'x'

    class Leakable(object):
        def __init__(self):
            self.x = 'x'

    leaked = []

    class TestSomething(unittest.TestCase):

        def testleak(self):
            leaked.append((ClassicLeakable(), Leakable(), time.time()))

Let's go through this by type.

float, leak.ClassicLeakable, leak.Leakable, and tuple
    We leak one of these every time.  This is to be expected because
    we are adding one of these to the list every time.

str
    We don't leak any instances, but we leak 4 references. These are
    due to the instance attributes avd values.

dict
    We leak 2 of these, one for each ClassicLeakable and Leakable
    instance. 

classobj
    We increase the number of classobj instance references by one each
    time because each ClassicLeakable instance has a reference to its
    class.  This instances increases the references in it's class,
    which increases the total number of references to classic classes
    (clasobj instances).

type
    For most interations, we increase the number of type references by
    one for the same reason we increase the number of clasobj
    references by one.  The increase of the number of type references
    by 3 in the second iteration is puzzling, but illustrates that
    this sort of data is often puzzling.

int
    The change in the number of int instances and references in this
    example is a side effect of the statistics being gathered.  Lots
    of integers are created to keep the memory statistics used here.

The summary statistics include the sum of the detail refcounts.  (Note
that this sum is less than the system refcount.  This is because the
detailed analysis doesn't inspect every object. Not all objects in the
system are returned by sys.getobjects.)