22 test some jython internals
33"""
44import unittest
5- import time
65from test import test_support
76
7+ import datetime
88import java
99import jarray
10+ import os
11+ import sys
12+ import time
13+ import weakref
1014
1115from org .python .core import Py
1216from org .python .util import PythonInterpreter
1317from javatests .TestSupport import invokePyTypeMethod
1418from java .sql import Date , Time , Timestamp
15- import datetime
16-
17-
18- class MemoryLeakTests (unittest .TestCase ):
19-
20- def test_class_to_test_weakness (self ):
21- # regrtest for bug 1522, adapted from test code submitted by Matt Brinkley
2219
23- # work around the fact that we can't look at PyType directly
24- # by using this helper function that reflects on PyType (and
25- # demonstrates here that it's the same as the builtin function
26- # `type`!)
27- class_to_type_map = invokePyTypeMethod (type , 'getClassToType' )
2820
29- def create_proxies ():
30- pi = PythonInterpreter ()
31- pi .exec ("""
21+ # Script for MemoryLeakTests.test_class_to_test_weakness
22+ DOG = """
3223from java.lang import Comparable
3324
3425class Dog(Comparable):
@@ -37,22 +28,83 @@ def compareTo(self, o):
3728 def bark(self):
3829 return 'woof woof'
3930
40- Dog().bark()
41- """ )
42- # get to steady state first, then verify we don't create new proxies
43- for i in xrange (2 ):
44- create_proxies ()
45- # Ensure the reaper thread can run and clear out weak refs, so
46- # use this supporting function
31+ dog = Dog()
32+ dog.bark()
33+ breed = dog.getClass()
34+ """
35+
36+ def run_script (script , names ):
37+ """Run the script and return a weak list of the values named"""
38+ pi = PythonInterpreter ()
39+ pi .exec (script )
40+ if isinstance (names , str ):
41+ names = (names , )
42+ result = []
43+ for n in names :
44+ obj = pi .getLocals ()[n ]
45+ result .append (weakref .ref (obj ))
46+ return result
47+
48+ def survivors (weak_list ):
49+ """Set of all objects on the weak list that are still live."""
50+ s = {ref () for ref in weak_list }
51+ s .discard (None )
52+ return s
53+
54+
55+ class MemoryLeakTests (unittest .TestCase ):
56+
57+ def test_class_to_test_weakness (self ):
58+ # regrtest for bug 1522, adapted from test code submitted by Matt Brinkley
59+
60+ # We wish to demonstrate that the proxy created by a Python class and
61+ # its PyType are GC'd when no longer in use, and therefore that the
62+ # Jython type system does not keep a PyType alive gratuitously. We do
63+ # this by holding weak references, then checking they're dead.
64+
65+ # Get to steady state by creating >1 Dog and then GC-ing homeless ones.
66+ battersea = []
67+ for i in range (2 ):
68+ battersea .extend (run_script (DOG , ('Dog' , 'dog' , 'breed' )))
69+ test_support .gc_collect ()
70+
71+ # This is the steady-state, GC number of Dog objects alive after GC:
72+ start_size = len (survivors (battersea )) # probably = 1
73+
74+ # Add more Dogs and GC the homeless ones again.
75+ for i in range (5 ):
76+ battersea .extend (run_script (DOG , ('Dog' , 'dog' , 'breed' )))
4777 test_support .gc_collect ()
48- # Given that taking the len (or size()) of Guava weak maps is
49- # eventually consistent, we should instead take a len of its
50- # keys.
51- start_size = len (list (class_to_type_map ))
52- for i in xrange (5 ):
53- create_proxies ()
78+ #print "\nDogs home =", battersea
79+ #print "\nDogs alive =", survivors(battersea)
80+
81+ # Post-GC number of Dogs should be as before
82+ self .assertEqual (start_size , len (survivors (battersea )))
83+
84+ def test_loading_classes_weakness (self ):
85+ # Show that classes loaded via a class loader are collectible once the
86+ # class loader is not strongly reachable.
87+
88+ # Reference all species of object on a weak list:
89+ zoo = []
90+
91+ def activity ():
92+ # Look for the Callbacker class ONLY in the special JAR
93+ jar = os .path .join (sys .prefix , "callbacker_test.jar" )
94+ cldr = test_support .make_jar_classloader (jar , None )
95+ CB = cldr .loadClass ("org.python.tests.Callbacker" )
96+ cb = CB ()
97+ # Save locals as weak references (that we hope will go dead)
98+ for obj in (cb , type (cb ), cldr ):
99+ zoo .append (weakref .ref (obj ))
100+
101+ # Load and use a class: objects created in zoo.
102+ activity ()
103+
104+ #print "\nzoo =", zoo
54105 test_support .gc_collect ()
55- self .assertEqual (start_size , len (list (class_to_type_map )))
106+ #print "\nsurvivors =", survivors(zoo)
107+ self .assertEqual (0 , len (survivors (zoo )))
56108
57109
58110class WeakIdentityMapTests (unittest .TestCase ):
@@ -93,6 +145,7 @@ def test_functionality(self):
93145 assert widmap .get (i ) == 'i' # triggers stale weak refs cleanup
94146 assert widmap ._internal_map_size () == 1
95147
148+
96149class LongAsScaledDoubleValueTests (unittest .TestCase ):
97150
98151 def setUp (self ):
@@ -143,6 +196,7 @@ def test_no_worse_than_doubleValue(self):
143196 assert float ((v + d )* 256 + y ) == sdv (((v + d )* 256 + y )* 256 , e )
144197 assert e [0 ] == 1
145198
199+
146200class ExtraMathTests (unittest .TestCase ):
147201 def test_epsilon (self ):
148202 from org .python .core .util import ExtraMath
@@ -162,6 +216,7 @@ def test_closeFloor(self):
162216 ExtraMath .closeFloor (3.0 - 3.0 * ExtraMath .CLOSE ), 2.0 )
163217 self .assertEquals (ExtraMath .closeFloor (math .log10 (10 ** 3 )), 3.0 )
164218
219+
165220class DatetimeTypeMappingTest (unittest .TestCase ):
166221 def test_date (self ):
167222 self .assertEquals (datetime .date (2008 , 5 , 29 ),
@@ -183,6 +238,7 @@ def test_datetime(self):
183238 self .assertEquals (datetime .datetime (2008 , 5 , 29 , 16 , 50 , 1 , 1 ),
184239 Py .newDatetime (Timestamp (108 , 4 , 29 , 16 , 50 , 1 , 1000 )))
185240
241+
186242class IdTest (unittest .TestCase ):
187243 def test_unique_ids (self ):
188244 d = {}
@@ -197,6 +253,7 @@ def test_unique_ids(self):
197253
198254 self .assertEquals (cnt , 0 )
199255
256+
200257class FrameTest (unittest .TestCase ):
201258 def test_stack_frame_locals (self ):
202259 def h ():
@@ -268,6 +325,7 @@ def baz(self):
268325 foo ()
269326 Bar ().baz ()
270327
328+
271329class ModuleTest (unittest .TestCase ):
272330 def test_create_module (self ):
273331 from org .python .core import PyModule , PyInstance
@@ -279,6 +337,7 @@ def test_create_module(self):
279337 exec "b = 3" in test .__dict__
280338 self .assertEquals (len (test .__dict__ ), 5 )
281339
340+
282341def test_main ():
283342 test_support .run_unittest (__name__ )
284343
0 commit comments