示例#1
0
        private static void ValidateSetMessageSendPendingExceptionImpl(MessageSendFunction msgSend)
        {
            if (!LibObjC.SupportedOnPlatform(msgSend))
            {
                return;
            }

            IntPtr func = msgSend switch
            {
                MessageSendFunction.MsgSend => (IntPtr)(delegate * unmanaged <IntPtr, IntPtr, IntPtr>) & MsgSend,
                MessageSendFunction.MsgSendFpret => (IntPtr)(delegate * unmanaged <IntPtr, IntPtr, IntPtr>) & MsgSendFpret,
                MessageSendFunction.MsgSendStret => (IntPtr)(delegate * unmanaged <IntPtr *, IntPtr, IntPtr, void>) & MsgSendStret,
                MessageSendFunction.MsgSendSuper => (IntPtr)(delegate * unmanaged <IntPtr, IntPtr, IntPtr>) & MsgSendSuper,
                MessageSendFunction.MsgSendSuperStret => (IntPtr)(delegate * unmanaged <IntPtr *, IntPtr, IntPtr, void>) & MsgSendSuperStret,
                _ => throw new Exception($"Unknown {nameof(MessageSendFunction)}"),
            };

            // Override message send function
            //
            // We are using the overriding mechanism to enable validating in the Libraries test suite.
            // Technically any Objective-C code that is entered via msgSend could call the managed SetMessageSendPendingException()
            // and it would be thrown when returning from the P/Invoke. This approach avoids us having to
            // create a pure Objective-C library for testing this behavior.
            ObjectiveCMarshal.SetMessageSendCallback(msgSend, func);

            // Call message send function through P/Invoke
            IntPtr inst = IntPtr.Zero;
            IntPtr sel  = IntPtr.Zero;

            Exception ex = Assert.Throws <PendingException>(() => LibObjC.CallPInvoke(msgSend, inst, sel));

            Assert.Equal(msgSend.ToString(), ex.Message);
        }
示例#2
0
        public static IntPtr CallPInvoke(MessageSendFunction msgSend, IntPtr inst, IntPtr sel)
        {
            switch (msgSend)
            {
            case MessageSendFunction.MsgSend:
                return(LibObjC.objc_msgSend(inst, sel));

            case MessageSendFunction.MsgSendFpret:
                return(LibObjC.objc_msgSend_fpret(inst, sel));

            case MessageSendFunction.MsgSendStret:
            {
                IntPtr ret;
                LibObjC.objc_msgSend_stret(out ret, inst, sel);
                return(ret);
            }

            case MessageSendFunction.MsgSendSuper:
                return(LibObjC.objc_msgSendSuper(inst, sel));

            case MessageSendFunction.MsgSendSuperStret:
            {
                IntPtr ret;
                LibObjC.objc_msgSendSuper_stret(out ret, inst, sel);
                return(ret);
            }

            default:
                throw new ArgumentException($"Unknown {nameof(MessageSendFunction)}: {msgSend}");
            }
        }
示例#3
0
        public void ValidateSetMessageSendPendingException(MessageSendFunction func)
        {
            // Pass functions to override as a string for remote execution
            RemoteExecutor.Invoke((string funcToOverrideAsStr) =>
            {
                MessageSendFunction msgSend = Enum.Parse <MessageSendFunction>(funcToOverrideAsStr);
                Assert.True(Enum.IsDefined <MessageSendFunction>(msgSend));

                ValidateSetMessageSendPendingExceptionImpl(msgSend);
            }, func.ToString()).Dispose();
        }
示例#4
0
        public static bool SupportedOnPlatform(MessageSendFunction msgSend)
        {
            // The objc_msgSend_fpret, objc_msgSend_stret, and objc_msgSendSuper_stret exports
            // are not present on the ARM64 platform.
            if (RuntimeInformation.ProcessArchitecture == Architecture.Arm64 &&
                (msgSend == MessageSendFunction.MsgSendFpret ||
                 msgSend == MessageSendFunction.MsgSendStret ||
                 msgSend == MessageSendFunction.MsgSendSuperStret))
            {
                return(false);
            }

            return(true);
        }
示例#5
0
        public void ValidateSetMessageSendPendingException(MessageSendFunction func)
        {
            // Pass functions to override as a string for remote execution
            RemoteExecutor.Invoke((string funcToOverrideAsStr) =>
            {
                MessageSendFunction msgSend = Enum.Parse <MessageSendFunction>(funcToOverrideAsStr);
                Assert.True(Enum.IsDefined <MessageSendFunction>(msgSend));

                ValidateSetMessageSendPendingExceptionImpl(msgSend);

                // TODO: Remove once https://github.com/dotnet/arcade/issues/5865 is resolved
                // RemoteExecutor currently only checks the expected exit code if the invoked function returns an int.
                // Check the exit code to ensure the test will fail if there was a crash that could not be caught by the executor.
                return(RemoteExecutor.SuccessExitCode);
            }, func.ToString()).Dispose();
        }
 private static extern bool TrySetGlobalMessageSendCallback(
     MessageSendFunction msgSendFunction,
     IntPtr func);
示例#7
0
 /// <summary>
 /// Set a function pointer override for an Objective-C runtime message passing export.
 /// </summary>
 /// <param name="msgSendFunction">The export to override.</param>
 /// <param name="func">The function override.</param>
 /// <exception cref="InvalidOperationException">Thrown if the msgSend function has already been overridden.</exception>
 /// <remarks>
 /// Providing an override can enable support for Objective-C variadic argument support.
 /// </remarks>
 public static void SetMessageSendCallback(MessageSendFunction msgSendFunction, IntPtr func)
 => throw new PlatformNotSupportedException();
 private static bool TrySetGlobalMessageSendCallback(
     MessageSendFunction msgSendFunction,
     IntPtr func) => throw new NotImplementedException();
示例#9
0
 private static IntPtr ReturnPtr(MessageSendFunction msgSendFunc)
 {
     s_callbackInvoked = true;
     return(new IntPtr(s_count + (int)msgSendFunc));
 }