コード例 #1
0
        public void ManagedSignature()
        {
            int n = 0;

            Errors = 0;
            ErrorData.Clear();

            foreach (Type t in Assembly.GetTypes())
            {
                if (!NSObjectType.IsAssignableFrom(t))
                {
                    continue;
                }

                CurrentType = t;

                foreach (MethodInfo m in t.GetMethods(Flags))
                {
                    CheckManagedMemberSignatures(m, t, ref n);
                }

                foreach (MethodBase m in t.GetConstructors(Flags))
                {
                    CheckManagedMemberSignatures(m, t, ref n);
                }
            }
            AssertIfErrors("{0} errors found in {1} signatures validated{2}", Errors, n, Errors == 0 ? string.Empty : ":\n" + ErrorData.ToString() + "\n");
        }
コード例 #2
0
        public void StaticMethods()
        {
            Errors = 0;
            ErrorData.Clear();
            int n = 0;

            IntPtr responds_handle = Selector.GetHandle("respondsToSelector:");

            foreach (Type t in Assembly.GetTypes())
            {
                if (t.IsNested || !NSObjectType.IsAssignableFrom(t))
                {
                    continue;
                }

                if (Skip(t) || SkipDueToAttribute(t))
                {
                    continue;
                }

                FieldInfo fi = t.GetField("class_ptr", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static);
                if (fi == null)
                {
                    continue;                     // e.g. *Delegate
                }
                IntPtr class_ptr = (IntPtr)fi.GetValue(null);

                foreach (var m in t.GetMethods(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static))
                {
                    if (SkipDueToAttribute(m))
                    {
                        continue;
                    }

                    foreach (object ca in m.GetCustomAttributes(true))
                    {
                        if (ca is ExportAttribute)
                        {
                            string name = (ca as ExportAttribute).Selector;

                            if (Skip(t, name))
                            {
                                continue;
                            }

                            bool result   = bool_objc_msgSend_IntPtr(class_ptr, responds_handle, Selector.GetHandle(name));
                            bool response = CheckStaticResponse(result, t, m.DeclaringType, ref name);
                            if (!response)
                            {
                                ReportError(name);
                            }
                            n++;
                        }
                    }
                }
            }
            Assert.AreEqual(0, Errors, "{0} errors found in {1} static selector validated{2}", Errors, n, Errors == 0 ? string.Empty : ":\n" + ErrorData.ToString() + "\n");
        }
コード例 #3
0
        // we just want to confirm the symbol exists so `dlsym` can be disabled
        protected void Check(Assembly a)
        {
            Errors = 0;
            ErrorData.Clear();
            int n = 0;

            foreach (var t in a.GetTypes())
            {
                foreach (var m in t.GetMethods(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static))
                {
                    if ((m.Attributes & MethodAttributes.PinvokeImpl) == 0)
                    {
                        continue;
                    }

                    var dllimport = m.GetCustomAttribute <DllImportAttribute> ();

                    string name = dllimport.EntryPoint ?? m.Name;
                    switch (name)
                    {
                    // known not to be present in ARM64
                    case "objc_msgSend_stret":
                    case "objc_msgSendSuper_stret":
                        // the linker normally removes them (IntPtr.Size optimization)
                        continue;
                    }

                    string path = dllimport.Value;
                    switch (path)
                    {
                    case "__Internal":
                        // load from executable
                        path = null;
                        break;

                    case "libc":
                        // we still have some rogue/not-fully-qualified DllImport
                        path = "/usr/lib/libSystem.dylib";
                        break;
                    }

                    var lib = Dlfcn.dlopen(path, 0);
                    var h   = Dlfcn.dlsym(lib, name);
                    if (h == IntPtr.Zero)
                    {
                        ReportError("Could not find the symbol '{0}' in {1}", name, path);
                    }
                    Dlfcn.dlclose(lib);
                    n++;
                }
            }
            Assert.AreEqual(0, Errors, "{0} errors found in {1} symbol lookups{2}", Errors, n, Errors == 0 ? string.Empty : ":\n" + ErrorData.ToString() + "\n");
        }
コード例 #4
0
        public void NativeSignatures()
        {
            int n = 0;

            Errors = 0;
            ErrorData.Clear();

            foreach (Type t in Assembly.GetTypes())
            {
                var static_type = t.IsSealed && t.IsAbstract;                 // e.g. [Category]
                if (t.IsNested || (!static_type && !NSObjectType.IsAssignableFrom(t)))
                {
                    continue;
                }

                if (Skip(t))
                {
                    continue;
                }

                CurrentType = t;

                FieldInfo fi = null;
                if (!static_type)
                {
                    fi = t.GetField("class_ptr", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static);
                }
                IntPtr class_ptr = fi == null ? IntPtr.Zero : (IntPtr)fi.GetValue(null);

                foreach (MethodBase m in t.GetMethods(Flags))
                {
                    CheckMemberSignature(m, t, class_ptr, ref n);
                }
                foreach (MethodBase m in t.GetConstructors(Flags))
                {
                    CheckMemberSignature(m, t, class_ptr, ref n);
                }
            }
            AssertIfErrors("{0} errors found in {1} signatures validated{2}", Errors, n, Errors == 0 ? string.Empty : ":\n" + ErrorData.ToString() + "\n");
        }
コード例 #5
0
        public void InstanceMethods()
        {
            Errors = 0;
            ErrorData.Clear();
            int n = 0;

            foreach (Type t in Assembly.GetTypes())
            {
                if (t.IsNested || !NSObjectType.IsAssignableFrom(t))
                {
                    continue;
                }

                if (Skip(t) || SkipDueToAttribute(t))
                {
                    continue;
                }

                IntPtr class_ptr = GetClassForType(t);

                if (class_ptr == IntPtr.Zero)
                {
                    continue;
                }

                foreach (var c in t.GetConstructors(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance))
                {
                    Process(class_ptr, t, c, ref n);
                }

                foreach (var m in t.GetMethods(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance))
                {
                    Process(class_ptr, t, m, ref n);
                }
            }
            Assert.AreEqual(0, Errors, "{0} errors found in {1} instance selector validated{2}", Errors, n, Errors == 0 ? string.Empty : ":\n" + ErrorData.ToString() + "\n");
        }
コード例 #6
0
        public void DefaultCtorAllowed()
        {
            Errors = 0;
            ErrorData.Clear();
            int n = 0;

            foreach (Type t in Assembly.GetTypes())
            {
                if (t.IsAbstract || !NSObjectType.IsAssignableFrom(t))
                {
                    continue;
                }

                if (Skip(t))
                {
                    continue;
                }

                var ctor = t.GetConstructor(Type.EmptyTypes);
                if (SkipDueToAttribute(ctor))
                {
                    continue;
                }

                if ((ctor == null) || ctor.IsAbstract)
                {
                    if (LogUntestedTypes)
                    {
                        Console.WriteLine("[WARNING] {0} was skipped because it had no default constructor", t);
                    }
                    continue;
                }

                instance_type_name = t.FullName;
                if (LogProgress)
                {
                    Console.WriteLine("{0}. {1}", n, instance_type_name);
                }

                NSObject obj = null;
                try {
                    obj = ctor.Invoke(null) as NSObject;
                    CheckHandle(obj);
                    CheckToString(obj);
                    CheckIsDirectBinding(obj);
                    CheckNSObjectProtocol(obj);
                    Dispose(obj, t);
                }
                catch (Exception e) {
                    // Objective-C exception thrown
                    if (!ContinueOnFailure)
                    {
                        throw;
                    }

                    TargetInvocationException tie = (e as TargetInvocationException);
                    if (tie != null)
                    {
                        e = tie.InnerException;
                    }
                    ReportError("Default constructor not allowed for {0} : {1}", instance_type_name, e.Message);
                }
                n++;
            }
            Assert.AreEqual(0, Errors, "{0} potential errors found in {1} default ctor validated{2}", Errors, n, Errors == 0 ? string.Empty : ":\n" + ErrorData.ToString() + "\n");
        }
コード例 #7
0
        // we just want to confirm the symbol exists so `dlsym` can be disabled
        protected void Check(Assembly a)
        {
            Errors = 0;
            ErrorData.Clear();
            int n = 0;

            foreach (var t in a.GetTypes())
            {
                foreach (var m in t.GetMethods(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static))
                {
                    if ((m.Attributes & MethodAttributes.PinvokeImpl) == 0)
                    {
                        continue;
                    }

                    var dllimport = m.GetCustomAttribute <DllImportAttribute> ();

                    string name = dllimport.EntryPoint ?? m.Name;
                    switch (name)
                    {
                    // known not to be present in ARM64
                    case "objc_msgSend_stret":
                    case "objc_msgSendSuper_stret":
                        // the linker normally removes them (IntPtr.Size optimization)
                        continue;
                    }

                    string path = dllimport.Value;
                    switch (path)
                    {
                    case "__Internal":
                        // load from executable
                        path = null;
                        break;

#if NET
                    case "QCall":
                        // Globalization hasn't been implemented yet: https://github.com/xamarin/xamarin-macios/issues/8906
                        if (name.StartsWith("GlobalizationNative_", StringComparison.Ordinal))
                        {
                            continue;
                        }
                        break;

                    case "libhostpolicy":
                        // There's no libhostpolicy library.
                        // https://github.com/dotnet/runtime/issues/38543
                        continue;

                    case "libSystem.Native":
                        path += ".dylib";
                        break;
#endif
                    case "libc":
                        // we still have some rogue/not-fully-qualified DllImport
                        path = "/usr/lib/libSystem.dylib";
                        break;

                    case "System.Native":
                    case "System.Security.Cryptography.Native.Apple":
                    case "System.Net.Security.Native":
                        if (MonoNativeConfig.LinkMode == MonoNativeLinkMode.None)
                        {
                            continue;
                        }
#if __IOS__
                        path = MonoNativeConfig.GetPInvokeLibraryName(MonoNativeFlavor.Compat, MonoNativeConfig.LinkMode);
#else
                        path = null;
#endif
                        break;
                    }

                    var lib = Dlfcn.dlopen(path, 0);
                    var h   = Dlfcn.dlsym(lib, name);
                    if (h == IntPtr.Zero)
                    {
                        ReportError("Could not find the symbol '{0}' in {1}", name, path);
                    }
                    Dlfcn.dlclose(lib);
                    n++;
                }
            }
            Assert.AreEqual(0, Errors, "{0} errors found in {1} symbol lookups{2}", Errors, n, Errors == 0 ? string.Empty : ":\n" + ErrorData.ToString() + "\n");
        }
コード例 #8
0
        public void AsyncCandidates()
        {
            int n = 0;

            Errors = 0;
            ErrorData.Clear();

            foreach (Type t in Assembly.GetTypes())
            {
                // e.g. delegates used for events
                if (t.IsNested)
                {
                    continue;
                }

                if (!NSObjectType.IsAssignableFrom(t))
                {
                    continue;
                }

                if (t.GetCustomAttribute <ProtocolAttribute> () != null)
                {
                    continue;
                }
                if (t.GetCustomAttribute <ModelAttribute> () != null)
                {
                    continue;
                }

                // let's not encourage the use of some API
                if (IsDiscouraged(t))
                {
                    continue;
                }

                CurrentType = t;

                var methods = t.GetMethods(Flags);
                foreach (MethodInfo m in methods)
                {
                    if (m.DeclaringType != t)
                    {
                        continue;
                    }

                    // skip properties / events
                    if (m.IsSpecialName)
                    {
                        continue;
                    }

                    if (IgnoreAsync(m))
                    {
                        continue;
                    }

                    // some calls are "natively" async
                    if (m.Name.IndexOf("Async", StringComparison.Ordinal) != -1)
                    {
                        continue;
                    }

                    // let's not encourage the use of some API
                    if (IsDiscouraged(m))
                    {
                        continue;
                    }

                    // is it a candidate ?
                    var p = m.GetParameters();
                    if (p.Length == 0)
                    {
                        continue;
                    }
                    var last = p [p.Length - 1];
                    // trying to limit false positives and the need for large ignore lists to maintain
                    // unlike other introspection tests a failure does not mean a broken API
                    switch (last.Name)
                    {
                    case "completionHandler":
                    case "completion":
                        break;

                    default:
                        continue;
                    }
                    if (!last.ParameterType.IsSubclassOf(typeof(Delegate)))
                    {
                        continue;
                    }

                    // did we provide a async wrapper ?
                    string ma = m.Name + "Async";
                    if (methods.Where((mi) => mi.Name == ma).FirstOrDefault() != null)
                    {
                        continue;
                    }

                    var name = m.ToString();
                    var i    = name.IndexOf(' ');
                    ErrorData.AppendLine(name.Insert(i + 1, m.DeclaringType.Name + "::"));
                    Errors++;
                }
            }
            AssertIfErrors("{0} errors found in {1} signatures validated{2}", Errors, n, Errors == 0 ? string.Empty : ":\n" + ErrorData.ToString() + "\n");
        }
コード例 #9
0
        // we just want to confirm the symbol exists so `dlsym` can be disabled
        protected void Check(Assembly a)
        {
            Errors = 0;
            ErrorData.Clear();
            int n = 0;

            foreach (var t in a.GetTypes())
            {
                foreach (var m in t.GetMethods(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static))
                {
                    if ((m.Attributes & MethodAttributes.PinvokeImpl) == 0)
                    {
                        continue;
                    }

                    var dllimport = m.GetCustomAttribute <DllImportAttribute> ();

                    string name = dllimport.EntryPoint ?? m.Name;
                    switch (name)
                    {
                    // known not to be present in ARM64
                    case "objc_msgSend_stret":
                    case "objc_msgSendSuper_stret":
                        // the linker normally removes them (IntPtr.Size optimization)
                        continue;
                    }

                    string path = dllimport.Value;
                    switch (path)
                    {
                    case "__Internal":
                        // load from executable
                        path = null;
                        break;

#if NET
                    case "libSystem.Globalization.Native":
                        // load from executable (like __Internal above since it's part of the static library)
                        path = null;
                        break;

                    case "libSystem.Native":
                        path += ".dylib";
                        break;
#endif
                    case "libc":
                        // we still have some rogue/not-fully-qualified DllImport
                        path = "/usr/lib/libSystem.dylib";
                        break;

                    case "System.Native":
                    case "System.Security.Cryptography.Native.Apple":
                    case "System.Net.Security.Native":
                        if (MonoNativeConfig.LinkMode == MonoNativeLinkMode.None)
                        {
                            continue;
                        }
#if __IOS__
                        path = MonoNativeConfig.GetPInvokeLibraryName(MonoNativeFlavor.Compat, MonoNativeConfig.LinkMode);
#else
                        path = null;
#endif
                        break;
                    }

                    var lib = Dlfcn.dlopen(path, 0);
                    var h   = Dlfcn.dlsym(lib, name);
                    if (h == IntPtr.Zero)
                    {
                        ReportError("Could not find the symbol '{0}' in {1} for the P/Invoke {2}.{3} in {4}", name, path, t.FullName, m.Name, a.GetName().Name);
                    }
                    else if (path != null)
                    {
                        // Verify that the P/Invoke points to the right library.
                        Dl_info info  = default(Dl_info);
                        var     found = dladdr(h, out info);
                        if (found != 0)
                        {
                            // Resolve symlinks in both cases
                            var dllImportPath = ResolveLibrarySymlinks(path);
                            var foundLibrary  = ResolveLibrarySymlinks(Marshal.PtrToStringAuto(info.dli_fname));
                            if (Skip(name, ref dllImportPath, ref foundLibrary))
                            {
                                // Skipped
                            }
                            else if (foundLibrary != dllImportPath)
                            {
                                ReportError($"Found the symbol '{name}' in the library '{foundLibrary}', but the P/Invoke {t.FullName}.{m.Name} in {a.GetName ().Name} claims it's in '{dllimport.Value}'.");
                            }
                        }
                        else
                        {
                            Console.WriteLine($"Unable to find the library for the symbol '{name}' claimed to be in {path} for the P/Invoke {t.FullName}.{m.Name} in {a.GetName ().Name} (rv: {found})");
                        }
                    }

                    Dlfcn.dlclose(lib);
                    n++;
                }
            }
            Assert.AreEqual(0, Errors, "{0} errors found in {1} symbol lookups{2}", Errors, n, Errors == 0 ? string.Empty : ":\n" + ErrorData.ToString() + "\n");
        }