Commits

Ronald Oussoren committed e71100f

More documentation and test updates

Comments (0)

Files changed (4)

pyobjc-core/Doc/api/module-PyObjCTools.TestSupport.rst

 
    This is similar to :class:`warnings.catch_warnings`.
 
+
+.. _`leaks(1)`: https://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man1/leaks.1.html
+
 .. class:: TestCase
 
    A subclass of :class:`unittest.TestCase` with some addition functionality. The
    most important addition is that each test gets run with a fresh autorelease pool.
 
+   .. method:: run()
+
+      Calls :meth:`unitest.TestCase.run`, but ensures that there is a fresh 
+      autorelease pool for every test. This makes is less likely that two
+      tests accidenty influence each other.
+
+      There will not be a fresh autorelease pool when :env:`PYOBJC_NO_AUTORELEASE`
+      is in the shell environment.
+
+
+      .. versionchanged:: 2.5
+         Removed support for using the `leaks(1)`_ tool to check for memory leaks because
+         that support was broken (cause test hangs) and didn't properly report leaks. This
+         used to environment variable :env:`PyOBJC_USE_LEAKS` as a trigger to enable the
+         functionality.
+
    .. method:: assertItemsEqual(seq1, seq2[, message])
 
       Asserts that sequences *seq1* and *seq2* have the same members (in any order).

pyobjc-core/Doc/blocks.rst

 Metadata for blocks
 -------------------
 
-The current implementation of blocks doesn't allow for full introspection, which means
-that PyObjC must be taught about the signatures of blocks. 
+The current implementation of blocks doesn't allow for full introspection, 
+which means that PyObjC must be taught about the signatures of blocks.  This
+is done using the :doc:`metadata system </metadata/index>`.
 
-.. todo::
-
-   Refer to the metadata documentation (which doesn't really exist at the moment)
+.. versionchanged:: 2.5
+   For basic blocks and (Objective-)C code compiled using a recent enough 
+   compiler the bridge can extract the block signature from the runtime.

pyobjc-core/Lib/PyObjCTools/TestSupport.py

 
 # Have a way to disable the autorelease pool behaviour
 _usepool = not _os.environ.get('PYOBJC_NO_AUTORELEASE')
-_useleaks = bool(_os.environ.get('PyOBJC_USE_LEAKS'))
-_leaksVerbose = True
 
 def _typemap(tp):
     if tp is None: return None
     """
     return onlyIf(os_release() <= release)
 
-def _leaks():
-    data = _subprocess.Popen(
-            ['/usr/bin/leaks', str(_os.getpid())], stdout=_subprocess.PIPE
-        ).communicate()[0]
-    return data.splitlines()
-
-
 _poolclass = objc.lookUpClass('NSAutoreleasePool')
 _nscftype = objc.lookUpClass('NSCFType')
 
 _typealias = {}
+
 if not is32Bit():
     _typealias[objc._C_LNG_LNG] = objc._C_LNG
     _typealias[objc._C_ULNG_LNG] = objc._C_ULNG
         if tp is _nscftype:
             self.fail(message or "%r is not a unique CFTypeRef type"%(tp,))
 
+        if not issubclass(tp, _nscftype):
+            self.fail(message or "%r is not a CFTypeRef subclass"%(tp,))
+
 
     def assertIsOpaquePointer(self, tp, message = None):
         if not hasattr(tp, "__pointer__"):
 
     def assertResultIsNullTerminated(self, method, message = None):
         info = method.__metadata__()
-        if not info['retval'].get('c_array_delimited_by_null'):
+        if not info.get('retval', {}).get('c_array_delimited_by_null'):
             self.fail(message or "result of %r is not a null-terminated array"%(method,))
 
     def assertIsNullTerminated(self, method, message = None):
         else:
             offset = 0
         info = method.__metadata__()
-        if not info['arguments'][argno+offset].get('c_array_delimited_by_null'):
+        if not info.get('arguments', {}).get(argno+offset, {}).get('c_array_delimited_by_null'):
             self.fail(message or "argument %d of %r is not a null-terminated array"%(argno, method))
 
     def assertArgIsVariableSize(self, method, argno, message = None):
         Run the test, same as unittest.TestCase.run, but every test is
         run with a fresh autorelease pool.
         """
-        if _useleaks:
-            leaksBefore = _leaks()
         if _usepool:
             p = _poolclass.alloc().init()
         else:
             _gc.collect()
             del p
             _gc.collect()
-            
-            if _useleaks:
-                leaksAfter = _leaks()
-                if len(leaksBefore) != len(leaksAfter):
-                    print("\ntest %s is leaking [%d lines]"%(self, len(leaksAfter) - len(leaksBefore)))
-                    if _leaksVerbose:
-                        # XXX: add a smartish filter the surpresses the leaks
-                        # in leaksBefore.
-                        for ln in leaksAfter:
-                            print(ln)
-
 
 main = _unittest.main
 

pyobjc-core/PyObjCTest/test_testsupport.py

 
 
 class TestTestSupport (TestCase):
-
     def test_sdkForPython(self):
         orig_get_config_var = TestSupport._get_config_var
         try:
             sys.maxsize = orig
 
 
+    def test_assert_cftype(self):
+        self.assertRaises(AssertionError, self.assertIsCFType, long)
+        self.assertRaises(AssertionError, self.assertIsCFType, objc.lookUpClass('NSObject'))
+        self.assertRaises(AssertionError, self.assertIsCFType, objc.lookUpClass('NSCFType'))
+
+        class OC_OPAQUE_TEST_1 (objc.lookUpClass('NSCFType')): pass
+        try:
+            self.assertIsCFType(OC_OPAQUE_TEST_1)
+        except AssertionError:
+            self.fail("CFType subclass not recognized as CFType")
+
+
+
     def test_assert_opaque(self):
         self.assertRaises(AssertionError, self.assertIsOpaquePointer, long)
 
             self.fail("assertIsOpaque fails on opaque pointer type")
 
 
+    def test_assert_result_nullterminated(self):
+        m = Method(None, {"c_array_delimited_by_null": True })
+        self.assertResultIsNullTerminated(m)
+
+        m = Method(None, {"c_array_delimited_by_null": False })
+        self.assertRaises(AssertionError, self.assertResultIsNullTerminated, m)
+
+        m = Method(None, {})
+        self.assertRaises(AssertionError, self.assertResultIsNullTerminated, m)
+
+    def test_assert_arg_nullterminated(self):
+        m = Method(3, {"c_array_delimited_by_null": True }, selector=True)
+        self.assertArgIsNullTerminated(m, 1)
+
+        m = Method(3, {"c_array_delimited_by_null": False }, selector=True)
+        self.assertRaises(AssertionError, self.assertArgIsNullTerminated, m, 1)
+
+        m = Method(3, {}, selector=True)
+        self.assertRaises(AssertionError, self.assertArgIsNullTerminated, m, 1)
+
+        m = Method(3, {"c_array_delimited_by_null": True }, selector=False)
+        self.assertArgIsNullTerminated(m, 3)
+
+        m = Method(3, {"c_array_delimited_by_null": False }, selector=False)
+        self.assertRaises(AssertionError, self.assertArgIsNullTerminated, m, 3)
+
+        m = Method(3, {}, selector=False)
+        self.assertRaises(AssertionError, self.assertArgIsNullTerminated, m, 3)
+
+
 
     def test_assert_arg_IN(self):
         m = Method(3, { "type": b"n^@" })
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.