示例#1
0
        void Process_Exited(object sender, System.EventArgs e)
        {
            if (Process.ExitCode != 0)
            {
                ErrorData.Insert(0, string.Format("Exit code: {0}\n", Process.ExitCode));
            }

            ExitedDelegate ExitedHandler = Exited;

            if (ExitedHandler != null)
            {
                EditorMainThread.Run(() => {
                    ExitedHandler(Process.ExitCode, OutputData.ToString().Trim(), ErrorData.ToString().Trim());
                });
            }

            if (nextProcess != null)
            {
                if (Process.ExitCode == 0 || !nextStopOnError)
                {
                    nextProcess.Start();
                }
            }
        }
示例#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
        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");
        }
示例#4
0
        public void Keys()
        {
            Errors            = 0;
            ContinueOnFailure = true;
            var nspace = CIFilterType.Namespace;
            var types  = CIFilterType.Assembly.GetTypes();

            foreach (Type t in types)
            {
                if (t.Namespace != nspace)
                {
                    continue;
                }

                if (t.IsAbstract || !CIFilterType.IsAssignableFrom(t))
                {
                    continue;
                }

                // we need to skip the filters that are not supported by the executing version of iOS
                if (Skip(t))
                {
                    continue;
                }

                var ctor = t.GetConstructor(Type.EmptyTypes);
                if ((ctor == null) || ctor.IsAbstract)
                {
                    continue;
                }

                CIFilter f = ctor.Invoke(null) as CIFilter;

                // first check that every property can be mapped to an input key - except if it starts with "Output"
                foreach (var p in t.GetProperties(BindingFlags.Public | BindingFlags.Instance))
                {
                    var pt = p.DeclaringType;
                    if (!CIFilterType.IsAssignableFrom(pt) || (pt == CIFilterType))
                    {
                        continue;
                    }

                    if (SkipDueToAttribute(p))
                    {
                        continue;
                    }

                    var getter = p.GetGetMethod();
                    var ea     = getter.GetCustomAttribute <ExportAttribute> (false);
                    // only properties coming (inlined) from protocols have an [Export] attribute
                    if (ea == null)
                    {
                        continue;
                    }
                    var key = ea.Selector;
                    // 'output' is always explicit
                    if (key.StartsWith("output", StringComparison.Ordinal))
                    {
                        if (Array.IndexOf(f.OutputKeys, key) < 0)
                        {
                            ReportError($"{t.Name}: Property `{p.Name}` mapped to key `{key}` is not part of `OutputKeys`.");
                            //GenerateBinding (f, Console.Out);
                        }
                    }
                    else
                    {
                        // special cases (protocol names are better)
                        switch (t.Name)
                        {
                        case "CIBicubicScaleTransform":
                            switch (key)
                            {
                            case "parameterB":
                                key = "inputB";
                                break;

                            case "parameterC":
                                key = "inputC";
                                break;
                            }
                            break;

                        case "CICmykHalftone":
                            switch (key)
                            {
                            case "grayComponentReplacement":
                                key = "inputGCR";
                                break;

                            case "underColorRemoval":
                                key = "inputUCR";
                                break;
                            }
                            break;

                        case "CIGlassDistortion":
                            switch (key)
                            {
                            case "textureImage":
                                key = "texture";
                                break;
                            }
                            break;
                        }
                        // 'input' is implied (generally) and explicit (in a few cases)
                        if (!key.StartsWith("input", StringComparison.Ordinal))
                        {
                            key = "input" + Char.ToUpperInvariant(key [0]) + key.Substring(1);
                        }

                        if (Array.IndexOf(f.InputKeys, key) < 0)
                        {
                            ReportError($"{t.Name}: Property `{p.Name}` mapped to key `{key}` is not part of `InputKeys`.");
                            //GenerateBinding (f, Console.Out);
                        }
                    }
                }

                // second check that every input key is mapped to an property
                foreach (var key in f.InputKeys)
                {
                    string cap = Char.ToUpperInvariant(key [0]) + key.Substring(1);
                    // special cases (protocol names are better)
                    switch (t.Name)
                    {
                    case "CICmykHalftone":
                        switch (key)
                        {
                        case "inputGCR":
                            cap = "GrayComponentReplacement";
                            break;

                        case "inputUCR":
                            cap = "UnderColorRemoval";
                            break;
                        }
                        break;

                    case "CIAccordionFoldTransition":
                        switch (key)
                        {
                        case "inputNumberOfFolds":
                            cap = "FoldCount";
                            break;
                        }
                        break;

                    case "CIBicubicScaleTransform":
                        switch (key)
                        {
                        case "inputB":
                            cap = "ParameterB";
                            break;

                        case "inputC":
                            cap = "ParameterC";
                            break;
                        }
                        break;
                    }
                    // IgnoreCase because there are acronyms (more than 2 letters) that naming convention force us to change
                    var pi = t.GetProperty(cap, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy);
                    if (pi == null)
                    {
                        // 2nd chance: some, but not all, property are prefixed by `Input`
                        if (key.StartsWith("input", StringComparison.Ordinal))
                        {
                            cap = Char.ToUpperInvariant(key [5]) + key.Substring(6);
                            pi  = t.GetProperty(cap, BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy);
                        }
                    }
                    if (pi == null)
                    {
                        ReportError($"{t.Name}: Input Key `{key}` is NOT mapped to a `{cap}` property.");
                        //GenerateBinding (f, Console.Out);
                    }
                    else if (pi.GetSetMethod() == null)
                    {
                        ReportError($"{t.Name}: Property `{pi.Name}` MUST have a setter.");
                    }
                }

                // third check that every output key is mapped to an property
                foreach (var key in f.OutputKeys)
                {
                    // special cases
                    switch (t.Name)
                    {
                    case "CIKeystoneCorrectionCombined":
                    case "CIKeystoneCorrectionHorizontal":
                    case "CIKeystoneCorrectionVertical":
                        switch (key)
                        {
                        case "outputRotationFilter":
                            continue;                             // lack of documentation about the returned type
                        }
                        break;

                    case "CILanczosScaleTransform":
                        switch (key)
                        {
                        // ref: https://github.com/xamarin/xamarin-macios/issues/7209
                        case "outputImageNewScaleX:scaleY:":
                        case "outputImageOldScaleX:scaleY:":
                            continue;
                        }
                        break;

                    case "CIDiscBlur":
                        switch (key)
                        {
                        // existed in iOS 10.3 but not in iOS 13 - we're not adding them
                        case "outputImageOriginal":
                        case "outputImageEnhanced":
                            continue;
                        }
                        break;

                    case "CIGaussianBlur":
                        switch (key)
                        {
                        case "outputImageV1":
                            // existed briefly in macOS 10.11, but neither before nor after.
                            continue;
                        }
                        break;

                    case "CIAreaAverage":
                    case "CIAreaHistogram":
                    case "CIAreaMinMax":
                        switch (key)
                        {
                        case "outputImageMPS":
                        case "outputImageMPS:":
                        case "outputImageNonMPS:":
                            // no doc for argument
                            continue;
                        }
                        break;
                    }

                    var cap = Char.ToUpperInvariant(key [0]) + key.Substring(1);
                    // IgnoreCase because there are acronyms (more than 2 letters) that naming convention force us to change
                    var po = t.GetProperty(cap, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy);
                    if (po == null)
                    {
                        ReportError($"{t.Name}: Output Key `{key}` is NOT mapped to a `{cap}` property.");
                        //GenerateBinding (f, Console.Out);
                    }
                    else if (po.GetSetMethod() != null)
                    {
                        ReportError($"{t.Name}: Property `{po.Name}` should NOT have a setter.");
                    }
                }
            }
            Assert.AreEqual(0, Errors, "{0} potential errors found{1}", Errors, Errors == 0 ? string.Empty : ":\n" + ErrorData.ToString() + "\n");
        }
示例#5
0
        public void Protocols()
        {
            Errors = 0;
            var to_confirm_manually = new StringBuilder();

            ContinueOnFailure = true;
            var nspace = CIFilterType.Namespace;
            var types  = CIFilterType.Assembly.GetTypes();

            foreach (Type t in types)
            {
                if (t.Namespace != nspace)
                {
                    continue;
                }

                // e.g. FooProtocolWrapper
                if (!t.IsPublic)
                {
                    continue;
                }

                switch (t.Name)
                {
                // we are interested in subclasses (real) filters
                case "CIFilter":
                    continue;

                // no protocol has been added (yet?) you can confirm with `grep` that it does not report anything in the terminal
                case "CIAdditionCompositing":
                case "CIAreaAverage":
                case "CIAreaHistogram":
                case "CIAreaMaximum":
                case "CIAreaMaximumAlpha":
                case "CIAreaMinimum":
                case "CIAreaMinimumAlpha":
                case "CIAreaMinMax":
                case "CIAreaMinMaxRed":
                case "CIBlendFilter":
                case "CIBumpDistortion":
                case "CIBumpDistortionLinear":
                case "CICameraCalibrationLensCorrection":
                case "CICircleSplashDistortion":
                case "CICircularWrap":
                case "CIClamp":
                case "CICodeGenerator":
                case "CIColorBlendMode":
                case "CIColorBurnBlendMode":
                case "CIColorDodgeBlendMode":
                case "CIColumnAverage":
                case "CICompositingFilter":
                case "CIConstantColorGenerator":
                case "CIConvolution3X3":
                case "CIConvolution5X5":
                case "CIConvolution7X7":
                case "CIConvolution9Horizontal":
                case "CIConvolution9Vertical":
                case "CIConvolutionCore":
                case "CICoreMLModelFilter":
                case "CICrop":
                case "CIDarkenBlendMode":
                case "CIDepthBlurEffect":
                case "CIDepthDisparityConverter":
                case "CIDifferenceBlendMode":
                case "CIDisplacementDistortion":
                case "CIDistortionFilter":
                case "CIDivideBlendMode":
                case "CIDroste":
                case "CIExclusionBlendMode":
                case "CIFaceBalance":
                case "CIGlassDistortion":
                case "CIGlassLozenge":
                case "CIGuidedFilter":
                case "CIHardLightBlendMode":
                case "CIHistogramDisplayFilter":
                case "CIHoleDistortion":
                case "CIHueBlendMode":
                case "CIImageGenerator":
                case "CIKeystoneCorrection":
                case "CIKMeans":
                case "CILightenBlendMode":
                case "CILightTunnel":
                case "CILinearBlur":
                case "CILinearBurnBlendMode":
                case "CILinearDodgeBlendMode":
                case "CILuminosityBlendMode":
                case "CIMaximumCompositing":
                case "CIMinimumCompositing":
                case "CIMorphology":
                case "CIMorphologyRectangle":
                case "CIMultiplyBlendMode":
                case "CIMultiplyCompositing":
                case "CINinePartStretched":
                case "CINinePartTiled":
                case "CIOverlayBlendMode":
                case "CIPinchDistortion":
                case "CIPinLightBlendMode":
                case "CIReductionFilter":
                case "CIRowAverage":
                case "CISampleNearest":
                case "CISaturationBlendMode":
                case "CIScreenBlendMode":
                case "CIScreenFilter":
                case "CISoftLightBlendMode":
                case "CISourceAtopCompositing":
                case "CISourceInCompositing":
                case "CISourceOutCompositing":
                case "CISourceOverCompositing":
                case "CIStretchCrop":
                case "CISubtractBlendMode":
                case "CITileFilter":
                case "CITorusLensDistortion":
                case "CITwirlDistortion":
                case "CIVortexDistortion":
                    // this list is likely to change with newer Xcode - uncomment if you want to the script to check the list
                    //to_confirm_manually.AppendLine ($"grep {t.Name} `xcode-select -p`/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/System/Library/Frameworks/CoreImage.framework/Headers/*.h");
                    // since xtro will report the missing protocols this is a 2nd layer of safety :)
                    continue;
                }

                bool assign = typeof(ICIFilterProtocol).IsAssignableFrom(t);
                bool suffix = t.Name.EndsWith("Protocol", StringComparison.Ordinal);

                if (t.IsInterface)
                {
                    if (assign)
                    {
                        // check that `IFooProtocol` has a [Protocol (Name = "Foo")] attribute
                        var ca = t.GetCustomAttribute <ProtocolAttribute> (false);
                        if (ca == null)
                        {
                            ReportError($"Managed {t.Name} should have a '[Protocol (Name=\"{t.Name.Replace ("Protocol", "")}\")]' attribute");
                        }
                        // check that the managed name ends with Protocol, so we can have the _normal_ name to be a concrete type (like our historic, strongly typed filters)
                        if (!suffix)
                        {
                            ReportError($"Managed {t.Name} should have a 'Protocol' suffix");
                        }
                    }
                    else if (suffix)
                    {
                        ReportError($"Managed {t.Name} should implement 'ICIFilterProtocol' interface.");
                    }
                }
                else if (suffix)
                {
                    ReportError($"Managed {t.Name} should be an interface since it represent a protocol");
                }
                else if (assign)
                {
                    // all CIFilter should map to a `ICI*Protocol` interface / protocol
                    bool found = false;
                    foreach (var inft in t.GetInterfaces())
                    {
                        if (inft.Namespace == nspace && inft.Name.EndsWith("Protocol", StringComparison.Ordinal))
                        {
                            found = true;
                            break;
                        }
                    }
                    if (!found)
                    {
                        ReportError($"Managed CIFilter '{t.Name}' does not conform to any CoreImage filter protocol.");
                    }
                }
                else if (CIFilterType.IsAssignableFrom(t))
                {
                    // missing ICIFilterProtocol
                    to_confirm_manually.AppendLine($"grep \"protocol {t.Name} \" `xcode-select -p`/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/System/Library/Frameworks/CoreImage.framework/Headers/*.h");
                    ReportError($"Managed CIFilter '{t.Name}' does not conform to 'ICIFilterProtocol' protocol. Confirm with generated `grep` script on console.");
                }
            }
            if (to_confirm_manually.Length > 0)
            {
                Console.WriteLine(to_confirm_manually);
            }
            Assert.AreEqual(0, Errors, "{0} potential errors found{1}", Errors, 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 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");
        }
示例#9
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");
        }
示例#10
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");
        }
示例#11
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");
        }
示例#12
0
        internal static Error Create(ErrorData emessage, params string[] param)
        {
            string message = string.Format(emessage.ToString(), param);

            return(new Error(message, emessage.Code));
        }
示例#13
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");
        }