xamarin-macios/tests/monotouch-test/ObjCRuntime/BlocksTest.cs

118 строки
4.0 KiB
C#

//
// Unit tests for Blocks
//
// Authors:
// Rolf Bjarne Kvinge <rolf@xamarin.com>
//
// Copyright 2015 Xamarin Inc. All rights reserved.
//
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.InteropServices;
#if XAMCORE_2_0
using Foundation;
using ObjCRuntime;
#else
using MonoTouch;
using MonoTouch.Foundation;
using MonoTouch.ObjCRuntime;
#endif
using NUnit.Framework;
namespace MonoTouchFixtures.ObjCRuntime {
[TestFixture]
[Preserve (AllMembers = true)]
public class BlocksTest {
[DllImport ("/usr/lib/libobjc.dylib")]
extern static IntPtr objc_getClass (string name);
[DllImport("/usr/lib/libobjc.dylib")]
static extern IntPtr imp_implementationWithBlock(ref BlockLiteral block);
[DllImport ("/usr/lib/libobjc.dylib")]
static extern bool class_addMethod (IntPtr cls, IntPtr name, IntPtr imp, string types);
[Test]
public void TestSetupBlock ()
{
using (var obj = new TestClass ()) {
TestClass.OnCallback = ((IntPtr blockArgument, IntPtr self, IntPtr argument) =>
{
Assert.AreNotEqual (IntPtr.Zero, blockArgument, "block");
Assert.AreEqual (obj.Handle, self, "self");
Assert.AreEqual (argument, (IntPtr) 0x12345678, "argument");
});
Messaging.void_objc_msgSend_IntPtr (obj.Handle, Selector.GetHandle ("testBlocks:"), (IntPtr) 0x12345678);
}
}
class TestClass : NSObject {
[MonoPInvokeCallback (typeof (TestBlockCallbackDelegate))]
static void TestBlockCallback (IntPtr block, IntPtr self, IntPtr argument)
{
OnCallback (block, self, argument);
}
static TestBlockCallbackDelegate callback = new TestBlockCallbackDelegate (TestBlockCallback);
public delegate void TestBlockCallbackDelegate (IntPtr block, IntPtr self, IntPtr argument);
public static TestBlockCallbackDelegate OnCallback;
static TestClass ()
{
var cls = Class.GetHandle (typeof (TestClass));
var block = new BlockLiteral ();
block.SetupBlock (callback, null);
var imp = imp_implementationWithBlock (ref block);
class_addMethod (cls, Selector.GetHandle ("testBlocks:"), imp, "v@:^v");
}
}
#if !DEVICE && !MONOMAC // some of these tests cause the AOT compiler to assert
// No MonoPInvokeCallback
static void InvalidTrampoline1 () { }
// Wrong delegate signature in MonoPInvokeCallback
[MonoPInvokeCallback (typeof (Action<IntPtr>))]
static void InvalidTrampoline2 () { }
// Wrong delegate signature in MonoPInvokeCallback
[MonoPInvokeCallback (typeof (Func<IntPtr>))]
static void InvalidTrampoline3 () { }
// Wrong delegate signature in MonoPInvokeCallback
[MonoPInvokeCallback (typeof (Action<IntPtr>))]
static void InvalidTrampoline4 (int x) { }
// Wrong delegate signature in MonoPInvokeCallback
[MonoPInvokeCallback (typeof (Func<IntPtr>))]
static int InvalidTrampoline5 () { return 0; }
#endif // !DEVICE
[Test]
public void InvalidBlockTrampolines ()
{
BlockLiteral block = new BlockLiteral ();
Action userDelegate = new Action (() => Console.WriteLine ("Hello world!"));
Assert.Throws<ArgumentNullException> (() => block.SetupBlock (null, userDelegate), "null trampoline");
#if !DEVICE && !MONOMAC
if (Runtime.Arch == Arch.SIMULATOR) {
// These checks only occur in the simulator
Assert.Throws<ArgumentException> (() => block.SetupBlock ((Action) InvalidBlockTrampolines, userDelegate), "instance trampoline");
Assert.Throws<ArgumentException> (() => block.SetupBlock ((Action) InvalidTrampoline1, userDelegate), "invalid trampoline 1");
Assert.Throws<ArgumentException> (() => block.SetupBlock ((Action) InvalidTrampoline2, userDelegate), "invalid trampoline 2");
Assert.Throws<ArgumentException> (() => block.SetupBlock ((Action) InvalidTrampoline3, userDelegate), "invalid trampoline 3");
Assert.Throws<ArgumentException> (() => block.SetupBlock ((Action<int>) InvalidTrampoline4, userDelegate), "invalid trampoline 4");
Assert.Throws<ArgumentException> (() => block.SetupBlock ((Func<int>) InvalidTrampoline5, userDelegate), "invalid trampoline 5");
}
#endif // !DEVICE
}
}
}