diff --git a/src/libraries/IntegrationTests/Directory.Build.props b/src/libraries/IntegrationTests/Directory.Build.props
new file mode 100644
index 00000000000000..5f191efe27c2e9
--- /dev/null
+++ b/src/libraries/IntegrationTests/Directory.Build.props
@@ -0,0 +1,3 @@
+
+
+
diff --git a/src/libraries/IntegrationTests/tests/iOS/Program.cs b/src/libraries/IntegrationTests/tests/iOS/Program.cs
new file mode 100644
index 00000000000000..9769ded207e150
--- /dev/null
+++ b/src/libraries/IntegrationTests/tests/iOS/Program.cs
@@ -0,0 +1,53 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Runtime.InteropServices;
+
+// it's not part of the BCL but runtime needs it for native-to-managed callbacks in AOT
+// To be replaced with NativeCallableAttribute
+public class MonoPInvokeCallbackAttribute : Attribute
+{
+ public MonoPInvokeCallbackAttribute(Type delegateType) { }
+}
+
+public static class Program
+{
+ // Defined in main.m
+ [DllImport("__Internal")]
+ private extern static void ios_set_text(string value);
+
+ [DllImport("__Internal")]
+ private extern static void ios_register_button_click(Action action);
+
+ private static Action buttonClickHandler = null;
+
+ private static int counter = 0;
+
+ // Called by native code, see main.m
+ [MonoPInvokeCallback(typeof(Action))]
+ private static void OnButtonClick()
+ {
+ ios_set_text("OnButtonClick! #" + counter++);
+ }
+
+ public static async Task Main(string[] args)
+ {
+ // Register a managed callback (will be called by UIButton, see main.m)
+ // Also, keep the handler alive so GC won't collect it.
+ ios_register_button_click(buttonClickHandler = OnButtonClick);
+
+ const string msg = "Hello World!\n.NET 5.0";
+ for (int i = 0; i < msg.Length; i++)
+ {
+ // a kind of an animation
+ ios_set_text(msg.Substring(0, i + 1));
+ await Task.Delay(100);
+ }
+
+ Console.WriteLine("Done!");
+ await Task.Delay(-1);
+ }
+}
diff --git a/src/libraries/IntegrationTests/tests/iOS/iOS.Simulator.Aot.Integration.Tests.csproj b/src/libraries/IntegrationTests/tests/iOS/iOS.Simulator.Aot.Integration.Tests.csproj
new file mode 100644
index 00000000000000..0f45ace47fc9bb
--- /dev/null
+++ b/src/libraries/IntegrationTests/tests/iOS/iOS.Simulator.Aot.Integration.Tests.csproj
@@ -0,0 +1,88 @@
+
+
+ Exe
+ bin
+ Portable
+ $(NetCoreAppCurrent)
+ iOS
+ $(ArtifactsBinDir)microsoft.netcore.app.runtime.ios-$(TargetArchitecture)\$(Configuration)\runtimes\ios-$(TargetArchitecture)\
+ false
+ ios-$(TargetArchitecture)
+ true
+ link
+ True
+ true
+ false
+
+
+
+
+
+
+ $(ArtifactsBinDir)microsoft.netcore.app.runtime.ios-$(TargetArchitecture)\$(Configuration)
+
+
+
+
+
+
+
+
+
+
+
+
+ $(MSBuildThisFileDirectory)$(PublishDir)\app
+ iPhone 11
+
+
+
+
+
+
+
+ @(MonoAOTCompilerDefaultAotArguments, ';')
+ @(MonoAOTCompilerDefaultProcessArguments, ';')
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/libraries/IntegrationTests/tests/iOS/main.m b/src/libraries/IntegrationTests/tests/iOS/main.m
new file mode 100644
index 00000000000000..0ab407e8398682
--- /dev/null
+++ b/src/libraries/IntegrationTests/tests/iOS/main.m
@@ -0,0 +1,80 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+#import
+#import "runtime.h"
+
+@interface ViewController : UIViewController
+@end
+
+@interface AppDelegate : UIResponder
+@property (strong, nonatomic) UIWindow *window;
+@property (strong, nonatomic) ViewController *controller;
+@end
+
+@implementation AppDelegate
+- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
+ self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
+ self.controller = [[ViewController alloc] initWithNibName:nil bundle:nil];
+ self.window.rootViewController = self.controller;
+ [self.window makeKeyAndVisible];
+ return YES;
+}
+@end
+
+UILabel *label;
+void (*clickHandlerPtr)(void);
+
+@implementation ViewController
+
+- (void)viewDidLoad {
+ [super viewDidLoad];
+
+ label = [[UILabel alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
+ label.textColor = [UIColor greenColor];
+ label.font = [UIFont boldSystemFontOfSize: 30];
+ label.numberOfLines = 2;
+ label.textAlignment = NSTextAlignmentCenter;
+ [self.view addSubview:label];
+
+ UIButton *button = [UIButton buttonWithType:UIButtonTypeInfoDark];
+ [button addTarget:self action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
+ [button setFrame:CGRectMake(50, 300, 200, 50)];
+ [button setTitle:@"Click me" forState:UIControlStateNormal];
+ [button setExclusiveTouch:YES];
+ [self.view addSubview:button];
+
+ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
+ mono_ios_runtime_init ();
+ });
+}
+-(void) buttonClicked:(UIButton*)sender
+{
+ if (clickHandlerPtr)
+ clickHandlerPtr();
+}
+
+@end
+
+// called from C# sample
+void
+ios_register_button_click (void* ptr)
+{
+ clickHandlerPtr = ptr;
+}
+
+// called from C# sample
+void
+ios_set_text (const char* value)
+{
+ NSString* nsstr = [NSString stringWithUTF8String:strdup(value)];
+ dispatch_async(dispatch_get_main_queue(), ^{
+ label.text = nsstr;
+ });
+}
+
+int main(int argc, char * argv[]) {
+ @autoreleasepool {
+ return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
+ }
+}
diff --git a/src/libraries/tests.proj b/src/libraries/tests.proj
index 511f7f68fe0020..f144efad5e2e41 100644
--- a/src/libraries/tests.proj
+++ b/src/libraries/tests.proj
@@ -151,6 +151,10 @@
+
+
+
+