Commits

Ronald Oussoren committed 0458bdd

Some minor updates

* Explictly test ppc/intel en 32-bit/64-bit in one go

* Fix detection of embedded function pointers in
'constant' defintions

* Add some testcases to increase module coverage

* Add placeholder tests for the rest of the
_bridgesupport module

  • Participants
  • Parent commits 9442456

Comments (0)

Files changed (2)

File pyobjc-core/Lib/objc/_bridgesupport.py

         if typestr.startswith(objc._C_STRUCT_B):
             # Look for structs with embbeded function pointers
             # and ignore those
-            nm, fields = objc.splitStructSignature(_as_bytes(typestr))
-            for nm, tp in fields:
-                if tp == b'?':
-                    return
+
+            def has_embedded_function(typestr):
+                nm, fields = objc.splitStructSignature(_as_bytes(typestr))
+                for nm, tp in fields:
+                    if tp == b'?':
+                        return True
+                    elif tp.startswith(objc._C_STRUCT_B):
+                        return has_embedded_function(tp)
+
+                return False
+
+            if has_embedded_function(typestr):
+                return
 
         magic = self.attribute_bool(node, "magic_cookie", None, False)
         self.constants.append((name, typestr, magic))
         if value is None:
             if sys.byteorder == 'little':
                 value = self.attribute_string(node, "le_value", None)
+
             else:
                 value = self.attribute_string(node, "be_value", None)
 
                     except UnicodeError as e:
                         warnings.warn("Error parsing BridgeSupport data for constant %s: %s" % (name, e), RuntimeWarning)
                         return
-        else:
+        else: # pragma: no cover (py3k)
             if not nsstring:
                 try:
                     value = value.encode('latin1')

File pyobjc-core/PyObjCTest/test_bridgesupport.py

   <constant name='constant7' type='@' magic_cookie='false' />
   <constant name='constant8' type='@' magic_cookie='true' />
   <constant /><!-- ignore -->
+  <constant name='constant9' type='{foo=i?i}' /><!-- ignore: embedded ? -->
+  <constant name='constant10' type='{foo={x=?}}' /><!-- ignore: embedded ? -->
   <string_constant name='strconst1' value='string constant1' />
   <string_constant name='strconst2' value='string constant 2' value64='string constant two' />
   <string_constant name='strconst1u' value='string constant1 unicode' nsstring='true' />
   <string_constant /><!-- ignore -->
   <enum name='enum1' value='1' />
   <enum name='enum2' value='3' value64='4'/>
-  <enum name='enum3' le_value='5' be_value64='6'/>
+  <enum name='enum3' le_value='5' be_value='6'/>
   <enum name='enum4' value='7' be_value='8' /><!-- should have value 7 -->
   <enum name='enum5' /><!-- ignore -->
   <enum value='3' value64='4'/><!-- ignore -->
   <enum name='enum6' value64='4'/><!-- ignore 32-bit -->
-  <enum name='enum7' be_value64='6' /><!-- ignore intel -->
+  <enum name='enum7' be_value='6' /><!-- ignore intel -->
   <enum name='enum8' le_value='5' /><!-- ignore ppc -->
   <enum name='enum9' value='2.5' />
   <enum name='enum10' value='0x1.5p+3' />
   <class name='MyClass1'></class>
   <class /><!-- ignore -->
   <class name='MyClass2'>
+    <function name='method.function'></function><!-- ignore, not at toplevel -->
     <method selector='method1' classmethod='true' ></method>
     <method selector='method2' variadic='true' ></method>
     <method selector='method3' variadic='true' c_array_delimited_by_null='true'></method>
         <arg type='d' />
      </arg>
   </function>
+  <function name='function45'><!-- ignore: arg node without type-->
+    <arg type_modifier='n' />
+  </function>
+  <function name='function46'><!-- ignore: arg node without type-->
+    <arg type='@' />
+    <arg type_modifier='n' />
+  </function>
+  <function name='function47'><!-- ignore: retval node without type-->
+    <retval type_modifier='n'/>
+    <arg type='@' />
+    <arg type='@' />
+  </function>
   <!-- TODO: type rewriting (_C_BOOL, _C_NSBOOL)-->
   <informal_protocol/><!-- ignore -->
   <informal_protocol name='protocol1' />
   <struct name='struct5' type='{struct3=@@}' alias='module2.struct'/>
   <struct name='struct6' type='{struct6=BB}' /><!-- _C_NSBOOL -->
   <struct name='struct7' type='{struct7=Z@}' /><!-- _C_BOOL -->
-  <struct name='struct8' type='{struct8=@@}' alias='sys.maxsize'/><!-- _C_BOOL -->
+  <struct name='struct8' type='{struct8=@@}' alias='sys.maxsize'/>
+  <struct name='struct9' type='{struct9=ii}' alias='sys.does_not_exist'/>
 </signatures>
 """
 
-class TestBridgeSupport (TestCase):
+class TestBridgeSupportParser (TestCase):
     def testInvalidToplevel(self):
         self.assertRaises(objc.error, bridgesupport._BridgeSupportParser, '<signatures2></signatures2>', 'Cocoa')
         self.assertRaises(ET.ParseError, bridgesupport._BridgeSupportParser, '<signatures2></signatures>', 'Cocoa')
 
                 self.assert_valid_bridgesupport(os.path.basename(fn).split('.')[0], xmldata)
 
-    def _test_xml_structure_variants(self):
+    def test_xml_structure_variants(self):
         # Run 'verify_xml_structure' for all cpu variant 
         # (big/little endian,  32- en 64-bit)
         orig_byteorder = sys.byteorder
             # See above
             imp.reload(bridgesupport)
 
-    def test_verify_xml_structure(self):
+    def verify_xml_structure(self):
         prs = self.assert_valid_bridgesupport('TestXML', TEST_XML)
 
         all_constants = [
             ('struct6', b'{struct6=ZZ}', None),
             ('struct7', b'{struct7=B@}', None),
             ('struct8', b'{struct8=@@}', sys.maxsize),
+            ('struct9', b'{struct9=ii}', None),
         ]
 
-
+        self.maxDiff = None
         self.assertItemsEqual(prs.constants,    all_constants)
         self.assertEqual(prs.values,            all_values)
         self.assertItemsEqual(prs.opaque,       all_opaque)
 
         return prs
 
+class TestParseBridgeSupport (TestCase):
+    def test_calls(self):
+        # - Minimal XML with all types of metadata
+        # - Mock the APIs used by parseBridgeSupport
+        #   (with strict verification of arguments, based on C code)
+        # - Verify changes to globals where possible
+        # - Verify 'updatingmetadata' state
+        self.fail()
+
+    def test_real_loader(self):
+        # Use the real API in a subprocess and verify
+        # that the metadata is properly loaded
+        # (use subset of Foundation and CoreFoundation)
+        self.fail()
+
+
+class TestInitFrameworkWrapper (TestCase):
+    def test_calls(self):
+        # Test functionality of initFrameworkWrapper and _parseBridgeSupport
+        # by mocking 'parseBridgeSupport'. 
+        self.fail()
+
+    def test_real_loader(self):
+        # Load framework in subprocess and verify that
+        # the right metadata is loaded.
+        self.fail()
+
 
 if __name__ == "__main__":
     main()