diff --git a/.gitignore b/.gitignore index 8e8bd532f26..04401644f01 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,4 @@ bin obj packages ~.pmcs* +.DS_Store diff --git a/Xamarin.Mac.sln b/Xamarin.Mac.sln new file mode 100644 index 00000000000..16a87ed3698 --- /dev/null +++ b/Xamarin.Mac.sln @@ -0,0 +1,332 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "xammac", "src\xammac.csproj", "{87042AD2-CDC9-4A53-9193-56226B668B88}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "mmp", "tools\mmp\mmp.csproj", "{F3232882-0FA0-4BB6-9D9C-E2CC779EAF0D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Cecil.Mdb", "external\mono\external\cecil\symbols\mdb\Mono.Cecil.Mdb.csproj", "{8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Cecil", "external\mono\external\cecil\Mono.Cecil.csproj", "{D68133BD-1E63-496E-9EDE-4FBDBF77B486}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Linker", "external\mono\mcs\tools\linker\Mono.Linker.csproj", "{DD28E2B1-057B-4B4D-A04D-B2EBD9E76E46}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "libxammac", "runtime\libxammac.csproj", "{8A5B637C-E4FF-4145-B887-9347020100F4}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "bmac", "src\bmac.csproj", "{D2EE02C0-9BFD-477D-AC92-4DE2D8490790}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "opentk", "opentk\opentk.csproj", "{4DA3620B-D1BC-4B51-90BB-9789EF94C73C}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{542D4426-F287-4126-9889-E17628DAECEA}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GuiUnit_NET_4_5", "external\guiunit\src\framework\GuiUnit_NET_4_5.csproj", "{D12F0F7B-8DE3-43EC-BA49-41052D065A9B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "introspection-mac", "tests\introspection\Mac\introspection-mac.csproj", "{FD385098-B3FD-4331-92BF-CC1F918E3334}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + Debug|x86 = Debug|x86 + Release|x86 = Release|x86 + net_2_0_Debug|Any CPU = net_2_0_Debug|Any CPU + net_2_0_Release|Any CPU = net_2_0_Release|Any CPU + net_3_5_Debug|Any CPU = net_3_5_Debug|Any CPU + net_3_5_Release|Any CPU = net_3_5_Release|Any CPU + net_4_0_Debug|Any CPU = net_4_0_Debug|Any CPU + net_4_0_Release|Any CPU = net_4_0_Release|Any CPU + silverlight_Debug|Any CPU = silverlight_Debug|Any CPU + silverlight_Release|Any CPU = silverlight_Release|Any CPU + winphone_Debug|Any CPU = winphone_Debug|Any CPU + winphone_Release|Any CPU = winphone_Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {4DA3620B-D1BC-4B51-90BB-9789EF94C73C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4DA3620B-D1BC-4B51-90BB-9789EF94C73C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4DA3620B-D1BC-4B51-90BB-9789EF94C73C}.Debug|x86.ActiveCfg = Debug|Any CPU + {4DA3620B-D1BC-4B51-90BB-9789EF94C73C}.Debug|x86.Build.0 = Debug|Any CPU + {4DA3620B-D1BC-4B51-90BB-9789EF94C73C}.net_2_0_Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4DA3620B-D1BC-4B51-90BB-9789EF94C73C}.net_2_0_Debug|Any CPU.Build.0 = Debug|Any CPU + {4DA3620B-D1BC-4B51-90BB-9789EF94C73C}.net_2_0_Release|Any CPU.ActiveCfg = Debug|Any CPU + {4DA3620B-D1BC-4B51-90BB-9789EF94C73C}.net_2_0_Release|Any CPU.Build.0 = Debug|Any CPU + {4DA3620B-D1BC-4B51-90BB-9789EF94C73C}.net_3_5_Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4DA3620B-D1BC-4B51-90BB-9789EF94C73C}.net_3_5_Debug|Any CPU.Build.0 = Debug|Any CPU + {4DA3620B-D1BC-4B51-90BB-9789EF94C73C}.net_3_5_Release|Any CPU.ActiveCfg = Debug|Any CPU + {4DA3620B-D1BC-4B51-90BB-9789EF94C73C}.net_3_5_Release|Any CPU.Build.0 = Debug|Any CPU + {4DA3620B-D1BC-4B51-90BB-9789EF94C73C}.net_4_0_Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4DA3620B-D1BC-4B51-90BB-9789EF94C73C}.net_4_0_Debug|Any CPU.Build.0 = Debug|Any CPU + {4DA3620B-D1BC-4B51-90BB-9789EF94C73C}.net_4_0_Release|Any CPU.ActiveCfg = Debug|Any CPU + {4DA3620B-D1BC-4B51-90BB-9789EF94C73C}.net_4_0_Release|Any CPU.Build.0 = Debug|Any CPU + {4DA3620B-D1BC-4B51-90BB-9789EF94C73C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4DA3620B-D1BC-4B51-90BB-9789EF94C73C}.Release|Any CPU.Build.0 = Release|Any CPU + {4DA3620B-D1BC-4B51-90BB-9789EF94C73C}.Release|x86.ActiveCfg = Release|Any CPU + {4DA3620B-D1BC-4B51-90BB-9789EF94C73C}.Release|x86.Build.0 = Release|Any CPU + {4DA3620B-D1BC-4B51-90BB-9789EF94C73C}.silverlight_Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4DA3620B-D1BC-4B51-90BB-9789EF94C73C}.silverlight_Debug|Any CPU.Build.0 = Debug|Any CPU + {4DA3620B-D1BC-4B51-90BB-9789EF94C73C}.silverlight_Release|Any CPU.ActiveCfg = Debug|Any CPU + {4DA3620B-D1BC-4B51-90BB-9789EF94C73C}.silverlight_Release|Any CPU.Build.0 = Debug|Any CPU + {4DA3620B-D1BC-4B51-90BB-9789EF94C73C}.winphone_Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4DA3620B-D1BC-4B51-90BB-9789EF94C73C}.winphone_Debug|Any CPU.Build.0 = Debug|Any CPU + {4DA3620B-D1BC-4B51-90BB-9789EF94C73C}.winphone_Release|Any CPU.ActiveCfg = Debug|Any CPU + {4DA3620B-D1BC-4B51-90BB-9789EF94C73C}.winphone_Release|Any CPU.Build.0 = Debug|Any CPU + {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.Debug|Any CPU.ActiveCfg = net_4_0_Debug|Any CPU + {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.Debug|Any CPU.Build.0 = net_4_0_Debug|Any CPU + {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.Debug|x86.ActiveCfg = net_2_0_Debug|Any CPU + {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.Debug|x86.Build.0 = net_2_0_Debug|Any CPU + {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.net_2_0_Debug|Any CPU.ActiveCfg = net_2_0_Debug|Any CPU + {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.net_2_0_Debug|Any CPU.Build.0 = net_2_0_Debug|Any CPU + {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.net_2_0_Release|Any CPU.ActiveCfg = net_2_0_Release|Any CPU + {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.net_2_0_Release|Any CPU.Build.0 = net_2_0_Release|Any CPU + {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.net_3_5_Debug|Any CPU.ActiveCfg = net_3_5_Debug|Any CPU + {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.net_3_5_Debug|Any CPU.Build.0 = net_3_5_Debug|Any CPU + {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.net_3_5_Release|Any CPU.ActiveCfg = net_3_5_Release|Any CPU + {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.net_3_5_Release|Any CPU.Build.0 = net_3_5_Release|Any CPU + {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.net_4_0_Debug|Any CPU.ActiveCfg = net_4_0_Debug|Any CPU + {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.net_4_0_Debug|Any CPU.Build.0 = net_4_0_Debug|Any CPU + {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.net_4_0_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU + {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.net_4_0_Release|Any CPU.Build.0 = net_4_0_Release|Any CPU + {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.Release|Any CPU.ActiveCfg = net_2_0_Release|Any CPU + {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.Release|Any CPU.Build.0 = net_2_0_Release|Any CPU + {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.Release|x86.ActiveCfg = net_2_0_Release|Any CPU + {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.Release|x86.Build.0 = net_2_0_Release|Any CPU + {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.silverlight_Debug|Any CPU.ActiveCfg = net_2_0_Debug|Any CPU + {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.silverlight_Debug|Any CPU.Build.0 = net_2_0_Debug|Any CPU + {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.silverlight_Release|Any CPU.ActiveCfg = net_2_0_Debug|Any CPU + {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.silverlight_Release|Any CPU.Build.0 = net_2_0_Debug|Any CPU + {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.winphone_Debug|Any CPU.ActiveCfg = net_2_0_Debug|Any CPU + {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.winphone_Debug|Any CPU.Build.0 = net_2_0_Debug|Any CPU + {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.winphone_Release|Any CPU.ActiveCfg = net_2_0_Debug|Any CPU + {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.winphone_Release|Any CPU.Build.0 = net_2_0_Debug|Any CPU + {87042AD2-CDC9-4A53-9193-56226B668B88}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {87042AD2-CDC9-4A53-9193-56226B668B88}.Debug|Any CPU.Build.0 = Debug|Any CPU + {87042AD2-CDC9-4A53-9193-56226B668B88}.Debug|x86.ActiveCfg = Debug|Any CPU + {87042AD2-CDC9-4A53-9193-56226B668B88}.Debug|x86.Build.0 = Debug|Any CPU + {87042AD2-CDC9-4A53-9193-56226B668B88}.net_2_0_Debug|Any CPU.ActiveCfg = Debug|Any CPU + {87042AD2-CDC9-4A53-9193-56226B668B88}.net_2_0_Debug|Any CPU.Build.0 = Debug|Any CPU + {87042AD2-CDC9-4A53-9193-56226B668B88}.net_2_0_Release|Any CPU.ActiveCfg = Debug|Any CPU + {87042AD2-CDC9-4A53-9193-56226B668B88}.net_2_0_Release|Any CPU.Build.0 = Debug|Any CPU + {87042AD2-CDC9-4A53-9193-56226B668B88}.net_3_5_Debug|Any CPU.ActiveCfg = Debug|Any CPU + {87042AD2-CDC9-4A53-9193-56226B668B88}.net_3_5_Debug|Any CPU.Build.0 = Debug|Any CPU + {87042AD2-CDC9-4A53-9193-56226B668B88}.net_3_5_Release|Any CPU.ActiveCfg = Debug|Any CPU + {87042AD2-CDC9-4A53-9193-56226B668B88}.net_3_5_Release|Any CPU.Build.0 = Debug|Any CPU + {87042AD2-CDC9-4A53-9193-56226B668B88}.net_4_0_Debug|Any CPU.ActiveCfg = Debug|Any CPU + {87042AD2-CDC9-4A53-9193-56226B668B88}.net_4_0_Debug|Any CPU.Build.0 = Debug|Any CPU + {87042AD2-CDC9-4A53-9193-56226B668B88}.net_4_0_Release|Any CPU.ActiveCfg = Debug|Any CPU + {87042AD2-CDC9-4A53-9193-56226B668B88}.net_4_0_Release|Any CPU.Build.0 = Debug|Any CPU + {87042AD2-CDC9-4A53-9193-56226B668B88}.Release|Any CPU.ActiveCfg = Release|Any CPU + {87042AD2-CDC9-4A53-9193-56226B668B88}.Release|Any CPU.Build.0 = Release|Any CPU + {87042AD2-CDC9-4A53-9193-56226B668B88}.Release|x86.ActiveCfg = Release|Any CPU + {87042AD2-CDC9-4A53-9193-56226B668B88}.Release|x86.Build.0 = Release|Any CPU + {87042AD2-CDC9-4A53-9193-56226B668B88}.silverlight_Debug|Any CPU.ActiveCfg = Debug|Any CPU + {87042AD2-CDC9-4A53-9193-56226B668B88}.silverlight_Debug|Any CPU.Build.0 = Debug|Any CPU + {87042AD2-CDC9-4A53-9193-56226B668B88}.silverlight_Release|Any CPU.ActiveCfg = Debug|Any CPU + {87042AD2-CDC9-4A53-9193-56226B668B88}.silverlight_Release|Any CPU.Build.0 = Debug|Any CPU + {87042AD2-CDC9-4A53-9193-56226B668B88}.winphone_Debug|Any CPU.ActiveCfg = Debug|Any CPU + {87042AD2-CDC9-4A53-9193-56226B668B88}.winphone_Debug|Any CPU.Build.0 = Debug|Any CPU + {87042AD2-CDC9-4A53-9193-56226B668B88}.winphone_Release|Any CPU.ActiveCfg = Debug|Any CPU + {87042AD2-CDC9-4A53-9193-56226B668B88}.winphone_Release|Any CPU.Build.0 = Debug|Any CPU + {8A5B637C-E4FF-4145-B887-9347020100F4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8A5B637C-E4FF-4145-B887-9347020100F4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8A5B637C-E4FF-4145-B887-9347020100F4}.Debug|x86.ActiveCfg = Debug|Any CPU + {8A5B637C-E4FF-4145-B887-9347020100F4}.Debug|x86.Build.0 = Debug|Any CPU + {8A5B637C-E4FF-4145-B887-9347020100F4}.net_2_0_Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8A5B637C-E4FF-4145-B887-9347020100F4}.net_2_0_Debug|Any CPU.Build.0 = Debug|Any CPU + {8A5B637C-E4FF-4145-B887-9347020100F4}.net_2_0_Release|Any CPU.ActiveCfg = Debug|Any CPU + {8A5B637C-E4FF-4145-B887-9347020100F4}.net_2_0_Release|Any CPU.Build.0 = Debug|Any CPU + {8A5B637C-E4FF-4145-B887-9347020100F4}.net_3_5_Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8A5B637C-E4FF-4145-B887-9347020100F4}.net_3_5_Debug|Any CPU.Build.0 = Debug|Any CPU + {8A5B637C-E4FF-4145-B887-9347020100F4}.net_3_5_Release|Any CPU.ActiveCfg = Debug|Any CPU + {8A5B637C-E4FF-4145-B887-9347020100F4}.net_3_5_Release|Any CPU.Build.0 = Debug|Any CPU + {8A5B637C-E4FF-4145-B887-9347020100F4}.net_4_0_Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8A5B637C-E4FF-4145-B887-9347020100F4}.net_4_0_Debug|Any CPU.Build.0 = Debug|Any CPU + {8A5B637C-E4FF-4145-B887-9347020100F4}.net_4_0_Release|Any CPU.ActiveCfg = Debug|Any CPU + {8A5B637C-E4FF-4145-B887-9347020100F4}.net_4_0_Release|Any CPU.Build.0 = Debug|Any CPU + {8A5B637C-E4FF-4145-B887-9347020100F4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8A5B637C-E4FF-4145-B887-9347020100F4}.Release|Any CPU.Build.0 = Release|Any CPU + {8A5B637C-E4FF-4145-B887-9347020100F4}.Release|x86.ActiveCfg = Release|Any CPU + {8A5B637C-E4FF-4145-B887-9347020100F4}.Release|x86.Build.0 = Release|Any CPU + {8A5B637C-E4FF-4145-B887-9347020100F4}.silverlight_Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8A5B637C-E4FF-4145-B887-9347020100F4}.silverlight_Debug|Any CPU.Build.0 = Debug|Any CPU + {8A5B637C-E4FF-4145-B887-9347020100F4}.silverlight_Release|Any CPU.ActiveCfg = Debug|Any CPU + {8A5B637C-E4FF-4145-B887-9347020100F4}.silverlight_Release|Any CPU.Build.0 = Debug|Any CPU + {8A5B637C-E4FF-4145-B887-9347020100F4}.winphone_Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8A5B637C-E4FF-4145-B887-9347020100F4}.winphone_Debug|Any CPU.Build.0 = Debug|Any CPU + {8A5B637C-E4FF-4145-B887-9347020100F4}.winphone_Release|Any CPU.ActiveCfg = Debug|Any CPU + {8A5B637C-E4FF-4145-B887-9347020100F4}.winphone_Release|Any CPU.Build.0 = Debug|Any CPU + {D2EE02C0-9BFD-477D-AC92-4DE2D8490790}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D2EE02C0-9BFD-477D-AC92-4DE2D8490790}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D2EE02C0-9BFD-477D-AC92-4DE2D8490790}.Debug|x86.ActiveCfg = Debug|Any CPU + {D2EE02C0-9BFD-477D-AC92-4DE2D8490790}.Debug|x86.Build.0 = Debug|Any CPU + {D2EE02C0-9BFD-477D-AC92-4DE2D8490790}.net_2_0_Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D2EE02C0-9BFD-477D-AC92-4DE2D8490790}.net_2_0_Debug|Any CPU.Build.0 = Debug|Any CPU + {D2EE02C0-9BFD-477D-AC92-4DE2D8490790}.net_2_0_Release|Any CPU.ActiveCfg = Debug|Any CPU + {D2EE02C0-9BFD-477D-AC92-4DE2D8490790}.net_2_0_Release|Any CPU.Build.0 = Debug|Any CPU + {D2EE02C0-9BFD-477D-AC92-4DE2D8490790}.net_3_5_Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D2EE02C0-9BFD-477D-AC92-4DE2D8490790}.net_3_5_Debug|Any CPU.Build.0 = Debug|Any CPU + {D2EE02C0-9BFD-477D-AC92-4DE2D8490790}.net_3_5_Release|Any CPU.ActiveCfg = Debug|Any CPU + {D2EE02C0-9BFD-477D-AC92-4DE2D8490790}.net_3_5_Release|Any CPU.Build.0 = Debug|Any CPU + {D2EE02C0-9BFD-477D-AC92-4DE2D8490790}.net_4_0_Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D2EE02C0-9BFD-477D-AC92-4DE2D8490790}.net_4_0_Debug|Any CPU.Build.0 = Debug|Any CPU + {D2EE02C0-9BFD-477D-AC92-4DE2D8490790}.net_4_0_Release|Any CPU.ActiveCfg = Debug|Any CPU + {D2EE02C0-9BFD-477D-AC92-4DE2D8490790}.net_4_0_Release|Any CPU.Build.0 = Debug|Any CPU + {D2EE02C0-9BFD-477D-AC92-4DE2D8490790}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D2EE02C0-9BFD-477D-AC92-4DE2D8490790}.Release|Any CPU.Build.0 = Release|Any CPU + {D2EE02C0-9BFD-477D-AC92-4DE2D8490790}.Release|x86.ActiveCfg = Release|Any CPU + {D2EE02C0-9BFD-477D-AC92-4DE2D8490790}.Release|x86.Build.0 = Release|Any CPU + {D2EE02C0-9BFD-477D-AC92-4DE2D8490790}.silverlight_Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D2EE02C0-9BFD-477D-AC92-4DE2D8490790}.silverlight_Debug|Any CPU.Build.0 = Debug|Any CPU + {D2EE02C0-9BFD-477D-AC92-4DE2D8490790}.silverlight_Release|Any CPU.ActiveCfg = Debug|Any CPU + {D2EE02C0-9BFD-477D-AC92-4DE2D8490790}.silverlight_Release|Any CPU.Build.0 = Debug|Any CPU + {D2EE02C0-9BFD-477D-AC92-4DE2D8490790}.winphone_Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D2EE02C0-9BFD-477D-AC92-4DE2D8490790}.winphone_Debug|Any CPU.Build.0 = Debug|Any CPU + {D2EE02C0-9BFD-477D-AC92-4DE2D8490790}.winphone_Release|Any CPU.ActiveCfg = Debug|Any CPU + {D2EE02C0-9BFD-477D-AC92-4DE2D8490790}.winphone_Release|Any CPU.Build.0 = Debug|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Debug|Any CPU.ActiveCfg = net_4_0_Debug|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Debug|Any CPU.Build.0 = net_4_0_Debug|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Debug|x86.ActiveCfg = net_2_0_Debug|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Debug|x86.Build.0 = net_2_0_Debug|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.net_2_0_Debug|Any CPU.ActiveCfg = net_2_0_Debug|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.net_2_0_Debug|Any CPU.Build.0 = net_2_0_Debug|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.net_2_0_Release|Any CPU.ActiveCfg = net_2_0_Release|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.net_2_0_Release|Any CPU.Build.0 = net_2_0_Release|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.net_3_5_Debug|Any CPU.ActiveCfg = net_3_5_Debug|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.net_3_5_Debug|Any CPU.Build.0 = net_3_5_Debug|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.net_3_5_Release|Any CPU.ActiveCfg = net_3_5_Release|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.net_3_5_Release|Any CPU.Build.0 = net_3_5_Release|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.net_4_0_Debug|Any CPU.ActiveCfg = net_4_0_Debug|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.net_4_0_Debug|Any CPU.Build.0 = net_4_0_Debug|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.net_4_0_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.net_4_0_Release|Any CPU.Build.0 = net_4_0_Release|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Release|Any CPU.ActiveCfg = net_2_0_Release|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Release|Any CPU.Build.0 = net_2_0_Release|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Release|x86.ActiveCfg = net_2_0_Release|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Release|x86.Build.0 = net_2_0_Release|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.silverlight_Debug|Any CPU.ActiveCfg = silverlight_Debug|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.silverlight_Debug|Any CPU.Build.0 = silverlight_Debug|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.silverlight_Release|Any CPU.ActiveCfg = silverlight_Release|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.silverlight_Release|Any CPU.Build.0 = silverlight_Release|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.winphone_Debug|Any CPU.ActiveCfg = winphone_Debug|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.winphone_Debug|Any CPU.Build.0 = winphone_Debug|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.winphone_Release|Any CPU.ActiveCfg = winphone_Release|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.winphone_Release|Any CPU.Build.0 = winphone_Release|Any CPU + {DD28E2B1-057B-4B4D-A04D-B2EBD9E76E46}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DD28E2B1-057B-4B4D-A04D-B2EBD9E76E46}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DD28E2B1-057B-4B4D-A04D-B2EBD9E76E46}.Debug|x86.ActiveCfg = Debug|Any CPU + {DD28E2B1-057B-4B4D-A04D-B2EBD9E76E46}.Debug|x86.Build.0 = Debug|Any CPU + {DD28E2B1-057B-4B4D-A04D-B2EBD9E76E46}.net_2_0_Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DD28E2B1-057B-4B4D-A04D-B2EBD9E76E46}.net_2_0_Debug|Any CPU.Build.0 = Debug|Any CPU + {DD28E2B1-057B-4B4D-A04D-B2EBD9E76E46}.net_2_0_Release|Any CPU.ActiveCfg = Debug|Any CPU + {DD28E2B1-057B-4B4D-A04D-B2EBD9E76E46}.net_2_0_Release|Any CPU.Build.0 = Debug|Any CPU + {DD28E2B1-057B-4B4D-A04D-B2EBD9E76E46}.net_3_5_Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DD28E2B1-057B-4B4D-A04D-B2EBD9E76E46}.net_3_5_Debug|Any CPU.Build.0 = Debug|Any CPU + {DD28E2B1-057B-4B4D-A04D-B2EBD9E76E46}.net_3_5_Release|Any CPU.ActiveCfg = Debug|Any CPU + {DD28E2B1-057B-4B4D-A04D-B2EBD9E76E46}.net_3_5_Release|Any CPU.Build.0 = Debug|Any CPU + {DD28E2B1-057B-4B4D-A04D-B2EBD9E76E46}.net_4_0_Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DD28E2B1-057B-4B4D-A04D-B2EBD9E76E46}.net_4_0_Debug|Any CPU.Build.0 = Debug|Any CPU + {DD28E2B1-057B-4B4D-A04D-B2EBD9E76E46}.net_4_0_Release|Any CPU.ActiveCfg = Debug|Any CPU + {DD28E2B1-057B-4B4D-A04D-B2EBD9E76E46}.net_4_0_Release|Any CPU.Build.0 = Debug|Any CPU + {DD28E2B1-057B-4B4D-A04D-B2EBD9E76E46}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DD28E2B1-057B-4B4D-A04D-B2EBD9E76E46}.Release|Any CPU.Build.0 = Release|Any CPU + {DD28E2B1-057B-4B4D-A04D-B2EBD9E76E46}.Release|x86.ActiveCfg = Release|Any CPU + {DD28E2B1-057B-4B4D-A04D-B2EBD9E76E46}.Release|x86.Build.0 = Release|Any CPU + {DD28E2B1-057B-4B4D-A04D-B2EBD9E76E46}.silverlight_Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DD28E2B1-057B-4B4D-A04D-B2EBD9E76E46}.silverlight_Debug|Any CPU.Build.0 = Debug|Any CPU + {DD28E2B1-057B-4B4D-A04D-B2EBD9E76E46}.silverlight_Release|Any CPU.ActiveCfg = Debug|Any CPU + {DD28E2B1-057B-4B4D-A04D-B2EBD9E76E46}.silverlight_Release|Any CPU.Build.0 = Debug|Any CPU + {DD28E2B1-057B-4B4D-A04D-B2EBD9E76E46}.winphone_Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DD28E2B1-057B-4B4D-A04D-B2EBD9E76E46}.winphone_Debug|Any CPU.Build.0 = Debug|Any CPU + {DD28E2B1-057B-4B4D-A04D-B2EBD9E76E46}.winphone_Release|Any CPU.ActiveCfg = Debug|Any CPU + {DD28E2B1-057B-4B4D-A04D-B2EBD9E76E46}.winphone_Release|Any CPU.Build.0 = Debug|Any CPU + {F3232882-0FA0-4BB6-9D9C-E2CC779EAF0D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F3232882-0FA0-4BB6-9D9C-E2CC779EAF0D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F3232882-0FA0-4BB6-9D9C-E2CC779EAF0D}.Debug|x86.ActiveCfg = Debug|x86 + {F3232882-0FA0-4BB6-9D9C-E2CC779EAF0D}.Debug|x86.Build.0 = Debug|x86 + {F3232882-0FA0-4BB6-9D9C-E2CC779EAF0D}.net_2_0_Debug|Any CPU.ActiveCfg = Debug|x86 + {F3232882-0FA0-4BB6-9D9C-E2CC779EAF0D}.net_2_0_Debug|Any CPU.Build.0 = Debug|x86 + {F3232882-0FA0-4BB6-9D9C-E2CC779EAF0D}.net_2_0_Release|Any CPU.ActiveCfg = Debug|x86 + {F3232882-0FA0-4BB6-9D9C-E2CC779EAF0D}.net_2_0_Release|Any CPU.Build.0 = Debug|x86 + {F3232882-0FA0-4BB6-9D9C-E2CC779EAF0D}.net_3_5_Debug|Any CPU.ActiveCfg = Debug|x86 + {F3232882-0FA0-4BB6-9D9C-E2CC779EAF0D}.net_3_5_Debug|Any CPU.Build.0 = Debug|x86 + {F3232882-0FA0-4BB6-9D9C-E2CC779EAF0D}.net_3_5_Release|Any CPU.ActiveCfg = Debug|x86 + {F3232882-0FA0-4BB6-9D9C-E2CC779EAF0D}.net_3_5_Release|Any CPU.Build.0 = Debug|x86 + {F3232882-0FA0-4BB6-9D9C-E2CC779EAF0D}.net_4_0_Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F3232882-0FA0-4BB6-9D9C-E2CC779EAF0D}.net_4_0_Debug|Any CPU.Build.0 = Debug|Any CPU + {F3232882-0FA0-4BB6-9D9C-E2CC779EAF0D}.net_4_0_Release|Any CPU.ActiveCfg = Debug|x86 + {F3232882-0FA0-4BB6-9D9C-E2CC779EAF0D}.net_4_0_Release|Any CPU.Build.0 = Debug|x86 + {F3232882-0FA0-4BB6-9D9C-E2CC779EAF0D}.Release|Any CPU.ActiveCfg = Release|x86 + {F3232882-0FA0-4BB6-9D9C-E2CC779EAF0D}.Release|Any CPU.Build.0 = Release|x86 + {F3232882-0FA0-4BB6-9D9C-E2CC779EAF0D}.Release|x86.ActiveCfg = Release|x86 + {F3232882-0FA0-4BB6-9D9C-E2CC779EAF0D}.Release|x86.Build.0 = Release|x86 + {F3232882-0FA0-4BB6-9D9C-E2CC779EAF0D}.silverlight_Debug|Any CPU.ActiveCfg = Debug|x86 + {F3232882-0FA0-4BB6-9D9C-E2CC779EAF0D}.silverlight_Debug|Any CPU.Build.0 = Debug|x86 + {F3232882-0FA0-4BB6-9D9C-E2CC779EAF0D}.silverlight_Release|Any CPU.ActiveCfg = Debug|x86 + {F3232882-0FA0-4BB6-9D9C-E2CC779EAF0D}.silverlight_Release|Any CPU.Build.0 = Debug|x86 + {F3232882-0FA0-4BB6-9D9C-E2CC779EAF0D}.winphone_Debug|Any CPU.ActiveCfg = Debug|x86 + {F3232882-0FA0-4BB6-9D9C-E2CC779EAF0D}.winphone_Debug|Any CPU.Build.0 = Debug|x86 + {F3232882-0FA0-4BB6-9D9C-E2CC779EAF0D}.winphone_Release|Any CPU.ActiveCfg = Debug|x86 + {F3232882-0FA0-4BB6-9D9C-E2CC779EAF0D}.winphone_Release|Any CPU.Build.0 = Debug|x86 + {D12F0F7B-8DE3-43EC-BA49-41052D065A9B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D12F0F7B-8DE3-43EC-BA49-41052D065A9B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D12F0F7B-8DE3-43EC-BA49-41052D065A9B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D12F0F7B-8DE3-43EC-BA49-41052D065A9B}.Release|Any CPU.Build.0 = Release|Any CPU + {D12F0F7B-8DE3-43EC-BA49-41052D065A9B}.Debug|x86.ActiveCfg = Debug|Any CPU + {D12F0F7B-8DE3-43EC-BA49-41052D065A9B}.Debug|x86.Build.0 = Debug|Any CPU + {D12F0F7B-8DE3-43EC-BA49-41052D065A9B}.Release|x86.ActiveCfg = Release|Any CPU + {D12F0F7B-8DE3-43EC-BA49-41052D065A9B}.Release|x86.Build.0 = Release|Any CPU + {D12F0F7B-8DE3-43EC-BA49-41052D065A9B}.net_2_0_Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D12F0F7B-8DE3-43EC-BA49-41052D065A9B}.net_2_0_Debug|Any CPU.Build.0 = Debug|Any CPU + {D12F0F7B-8DE3-43EC-BA49-41052D065A9B}.net_2_0_Release|Any CPU.ActiveCfg = Debug|Any CPU + {D12F0F7B-8DE3-43EC-BA49-41052D065A9B}.net_2_0_Release|Any CPU.Build.0 = Debug|Any CPU + {D12F0F7B-8DE3-43EC-BA49-41052D065A9B}.net_3_5_Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D12F0F7B-8DE3-43EC-BA49-41052D065A9B}.net_3_5_Debug|Any CPU.Build.0 = Debug|Any CPU + {D12F0F7B-8DE3-43EC-BA49-41052D065A9B}.net_3_5_Release|Any CPU.ActiveCfg = Debug|Any CPU + {D12F0F7B-8DE3-43EC-BA49-41052D065A9B}.net_3_5_Release|Any CPU.Build.0 = Debug|Any CPU + {D12F0F7B-8DE3-43EC-BA49-41052D065A9B}.net_4_0_Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D12F0F7B-8DE3-43EC-BA49-41052D065A9B}.net_4_0_Debug|Any CPU.Build.0 = Debug|Any CPU + {D12F0F7B-8DE3-43EC-BA49-41052D065A9B}.net_4_0_Release|Any CPU.ActiveCfg = Debug|Any CPU + {D12F0F7B-8DE3-43EC-BA49-41052D065A9B}.net_4_0_Release|Any CPU.Build.0 = Debug|Any CPU + {D12F0F7B-8DE3-43EC-BA49-41052D065A9B}.silverlight_Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D12F0F7B-8DE3-43EC-BA49-41052D065A9B}.silverlight_Debug|Any CPU.Build.0 = Debug|Any CPU + {D12F0F7B-8DE3-43EC-BA49-41052D065A9B}.silverlight_Release|Any CPU.ActiveCfg = Debug|Any CPU + {D12F0F7B-8DE3-43EC-BA49-41052D065A9B}.silverlight_Release|Any CPU.Build.0 = Debug|Any CPU + {D12F0F7B-8DE3-43EC-BA49-41052D065A9B}.winphone_Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D12F0F7B-8DE3-43EC-BA49-41052D065A9B}.winphone_Debug|Any CPU.Build.0 = Debug|Any CPU + {D12F0F7B-8DE3-43EC-BA49-41052D065A9B}.winphone_Release|Any CPU.ActiveCfg = Debug|Any CPU + {D12F0F7B-8DE3-43EC-BA49-41052D065A9B}.winphone_Release|Any CPU.Build.0 = Debug|Any CPU + {FD385098-B3FD-4331-92BF-CC1F918E3334}.Debug|Any CPU.ActiveCfg = Debug|x86 + {FD385098-B3FD-4331-92BF-CC1F918E3334}.Debug|Any CPU.Build.0 = Debug|x86 + {FD385098-B3FD-4331-92BF-CC1F918E3334}.Release|Any CPU.ActiveCfg = Release|x86 + {FD385098-B3FD-4331-92BF-CC1F918E3334}.Release|Any CPU.Build.0 = Release|x86 + {FD385098-B3FD-4331-92BF-CC1F918E3334}.Debug|x86.ActiveCfg = Debug|x86 + {FD385098-B3FD-4331-92BF-CC1F918E3334}.Debug|x86.Build.0 = Debug|x86 + {FD385098-B3FD-4331-92BF-CC1F918E3334}.Release|x86.ActiveCfg = Release|x86 + {FD385098-B3FD-4331-92BF-CC1F918E3334}.Release|x86.Build.0 = Release|x86 + {FD385098-B3FD-4331-92BF-CC1F918E3334}.net_2_0_Debug|Any CPU.ActiveCfg = Debug|x86 + {FD385098-B3FD-4331-92BF-CC1F918E3334}.net_2_0_Debug|Any CPU.Build.0 = Debug|x86 + {FD385098-B3FD-4331-92BF-CC1F918E3334}.net_2_0_Release|Any CPU.ActiveCfg = Debug|x86 + {FD385098-B3FD-4331-92BF-CC1F918E3334}.net_2_0_Release|Any CPU.Build.0 = Debug|x86 + {FD385098-B3FD-4331-92BF-CC1F918E3334}.net_3_5_Debug|Any CPU.ActiveCfg = Debug|x86 + {FD385098-B3FD-4331-92BF-CC1F918E3334}.net_3_5_Debug|Any CPU.Build.0 = Debug|x86 + {FD385098-B3FD-4331-92BF-CC1F918E3334}.net_3_5_Release|Any CPU.ActiveCfg = Debug|x86 + {FD385098-B3FD-4331-92BF-CC1F918E3334}.net_3_5_Release|Any CPU.Build.0 = Debug|x86 + {FD385098-B3FD-4331-92BF-CC1F918E3334}.net_4_0_Debug|Any CPU.ActiveCfg = Debug|x86 + {FD385098-B3FD-4331-92BF-CC1F918E3334}.net_4_0_Debug|Any CPU.Build.0 = Debug|x86 + {FD385098-B3FD-4331-92BF-CC1F918E3334}.net_4_0_Release|Any CPU.ActiveCfg = Debug|x86 + {FD385098-B3FD-4331-92BF-CC1F918E3334}.net_4_0_Release|Any CPU.Build.0 = Debug|x86 + {FD385098-B3FD-4331-92BF-CC1F918E3334}.silverlight_Debug|Any CPU.ActiveCfg = Debug|x86 + {FD385098-B3FD-4331-92BF-CC1F918E3334}.silverlight_Debug|Any CPU.Build.0 = Debug|x86 + {FD385098-B3FD-4331-92BF-CC1F918E3334}.silverlight_Release|Any CPU.ActiveCfg = Debug|x86 + {FD385098-B3FD-4331-92BF-CC1F918E3334}.silverlight_Release|Any CPU.Build.0 = Debug|x86 + {FD385098-B3FD-4331-92BF-CC1F918E3334}.winphone_Debug|Any CPU.ActiveCfg = Debug|x86 + {FD385098-B3FD-4331-92BF-CC1F918E3334}.winphone_Debug|Any CPU.Build.0 = Debug|x86 + {FD385098-B3FD-4331-92BF-CC1F918E3334}.winphone_Release|Any CPU.ActiveCfg = Debug|x86 + {FD385098-B3FD-4331-92BF-CC1F918E3334}.winphone_Release|Any CPU.Build.0 = Debug|x86 + EndGlobalSection + GlobalSection(MonoDevelopProperties) = preSolution + StartupItem = tools\mmp\mmp.csproj + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {D12F0F7B-8DE3-43EC-BA49-41052D065A9B} = {542D4426-F287-4126-9889-E17628DAECEA} + {FD385098-B3FD-4331-92BF-CC1F918E3334} = {542D4426-F287-4126-9889-E17628DAECEA} + EndGlobalSection +EndGlobal diff --git a/Xamarin.iOS.sln b/Xamarin.iOS.sln index fcce22d12b7..2fe3708e9b4 100644 --- a/Xamarin.iOS.sln +++ b/Xamarin.iOS.sln @@ -7,6 +7,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Cecil", "external\ceci EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Cecil.Mdb", "external\cecil\symbols\mdb\Mono.Cecil.Mdb.csproj", "{8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{2BFA13F8-B568-48BF-9A70-9D43F718C523}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "introspection-ios", "tests\introspection\iOS\introspection-ios.csproj", "{208744BD-504E-47D7-9A98-1CF02454A6DA}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -21,6 +25,11 @@ Global silverlight_Release|Any CPU = silverlight_Release|Any CPU winphone_Debug|Any CPU = winphone_Debug|Any CPU winphone_Release|Any CPU = winphone_Release|Any CPU + Debug|iPhoneSimulator = Debug|iPhoneSimulator + Release|iPhoneSimulator = Release|iPhoneSimulator + Debug|iPhone = Debug|iPhone + Release|iPhone = Release|iPhone + DebugStaticRegistrar|iPhone = DebugStaticRegistrar|iPhone EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {A737EFCC-4348-4EB1-9C14-4FDC0975388D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU @@ -47,6 +56,16 @@ Global {A737EFCC-4348-4EB1-9C14-4FDC0975388D}.winphone_Debug|Any CPU.Build.0 = Debug|Any CPU {A737EFCC-4348-4EB1-9C14-4FDC0975388D}.winphone_Release|Any CPU.ActiveCfg = Debug|Any CPU {A737EFCC-4348-4EB1-9C14-4FDC0975388D}.winphone_Release|Any CPU.Build.0 = Debug|Any CPU + {A737EFCC-4348-4EB1-9C14-4FDC0975388D}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {A737EFCC-4348-4EB1-9C14-4FDC0975388D}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {A737EFCC-4348-4EB1-9C14-4FDC0975388D}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {A737EFCC-4348-4EB1-9C14-4FDC0975388D}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {A737EFCC-4348-4EB1-9C14-4FDC0975388D}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {A737EFCC-4348-4EB1-9C14-4FDC0975388D}.Debug|iPhone.Build.0 = Debug|Any CPU + {A737EFCC-4348-4EB1-9C14-4FDC0975388D}.Release|iPhone.ActiveCfg = Release|Any CPU + {A737EFCC-4348-4EB1-9C14-4FDC0975388D}.Release|iPhone.Build.0 = Release|Any CPU + {A737EFCC-4348-4EB1-9C14-4FDC0975388D}.DebugStaticRegistrar|iPhone.ActiveCfg = Debug|Any CPU + {A737EFCC-4348-4EB1-9C14-4FDC0975388D}.DebugStaticRegistrar|iPhone.Build.0 = Debug|Any CPU {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Debug|Any CPU.ActiveCfg = net_2_0_Release|Any CPU {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Debug|Any CPU.Build.0 = net_2_0_Release|Any CPU {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Release|Any CPU.ActiveCfg = net_2_0_Release|Any CPU @@ -71,6 +90,16 @@ Global {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.winphone_Debug|Any CPU.Build.0 = winphone_Debug|Any CPU {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.winphone_Release|Any CPU.ActiveCfg = winphone_Release|Any CPU {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.winphone_Release|Any CPU.Build.0 = winphone_Release|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Debug|iPhoneSimulator.ActiveCfg = net_2_0_Debug|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Debug|iPhoneSimulator.Build.0 = net_2_0_Debug|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Release|iPhoneSimulator.ActiveCfg = net_2_0_Debug|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Release|iPhoneSimulator.Build.0 = net_2_0_Debug|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Debug|iPhone.ActiveCfg = net_2_0_Debug|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Debug|iPhone.Build.0 = net_2_0_Debug|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Release|iPhone.ActiveCfg = net_2_0_Debug|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Release|iPhone.Build.0 = net_2_0_Debug|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.DebugStaticRegistrar|iPhone.ActiveCfg = net_2_0_Debug|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.DebugStaticRegistrar|iPhone.Build.0 = net_2_0_Debug|Any CPU {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.Debug|Any CPU.ActiveCfg = net_2_0_Release|Any CPU {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.Debug|Any CPU.Build.0 = net_2_0_Release|Any CPU {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.Release|Any CPU.ActiveCfg = net_2_0_Release|Any CPU @@ -95,5 +124,52 @@ Global {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.winphone_Debug|Any CPU.Build.0 = net_2_0_Release|Any CPU {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.winphone_Release|Any CPU.ActiveCfg = net_2_0_Release|Any CPU {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.winphone_Release|Any CPU.Build.0 = net_2_0_Release|Any CPU + {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.Debug|iPhoneSimulator.ActiveCfg = net_2_0_Debug|Any CPU + {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.Debug|iPhoneSimulator.Build.0 = net_2_0_Debug|Any CPU + {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.Release|iPhoneSimulator.ActiveCfg = net_2_0_Debug|Any CPU + {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.Release|iPhoneSimulator.Build.0 = net_2_0_Debug|Any CPU + {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.Debug|iPhone.ActiveCfg = net_2_0_Debug|Any CPU + {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.Debug|iPhone.Build.0 = net_2_0_Debug|Any CPU + {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.Release|iPhone.ActiveCfg = net_2_0_Debug|Any CPU + {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.Release|iPhone.Build.0 = net_2_0_Debug|Any CPU + {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.DebugStaticRegistrar|iPhone.ActiveCfg = net_2_0_Debug|Any CPU + {8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.DebugStaticRegistrar|iPhone.Build.0 = net_2_0_Debug|Any CPU + {208744BD-504E-47D7-9A98-1CF02454A6DA}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator + {208744BD-504E-47D7-9A98-1CF02454A6DA}.Debug|Any CPU.Build.0 = Debug|iPhoneSimulator + {208744BD-504E-47D7-9A98-1CF02454A6DA}.Release|Any CPU.ActiveCfg = Release|iPhoneSimulator + {208744BD-504E-47D7-9A98-1CF02454A6DA}.Release|Any CPU.Build.0 = Release|iPhoneSimulator + {208744BD-504E-47D7-9A98-1CF02454A6DA}.net_2_0_Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator + {208744BD-504E-47D7-9A98-1CF02454A6DA}.net_2_0_Debug|Any CPU.Build.0 = Debug|iPhoneSimulator + {208744BD-504E-47D7-9A98-1CF02454A6DA}.net_2_0_Release|Any CPU.ActiveCfg = Debug|iPhoneSimulator + {208744BD-504E-47D7-9A98-1CF02454A6DA}.net_2_0_Release|Any CPU.Build.0 = Debug|iPhoneSimulator + {208744BD-504E-47D7-9A98-1CF02454A6DA}.net_3_5_Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator + {208744BD-504E-47D7-9A98-1CF02454A6DA}.net_3_5_Debug|Any CPU.Build.0 = Debug|iPhoneSimulator + {208744BD-504E-47D7-9A98-1CF02454A6DA}.net_3_5_Release|Any CPU.ActiveCfg = Debug|iPhoneSimulator + {208744BD-504E-47D7-9A98-1CF02454A6DA}.net_3_5_Release|Any CPU.Build.0 = Debug|iPhoneSimulator + {208744BD-504E-47D7-9A98-1CF02454A6DA}.net_4_0_Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator + {208744BD-504E-47D7-9A98-1CF02454A6DA}.net_4_0_Debug|Any CPU.Build.0 = Debug|iPhoneSimulator + {208744BD-504E-47D7-9A98-1CF02454A6DA}.net_4_0_Release|Any CPU.ActiveCfg = Debug|iPhoneSimulator + {208744BD-504E-47D7-9A98-1CF02454A6DA}.net_4_0_Release|Any CPU.Build.0 = Debug|iPhoneSimulator + {208744BD-504E-47D7-9A98-1CF02454A6DA}.silverlight_Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator + {208744BD-504E-47D7-9A98-1CF02454A6DA}.silverlight_Debug|Any CPU.Build.0 = Debug|iPhoneSimulator + {208744BD-504E-47D7-9A98-1CF02454A6DA}.silverlight_Release|Any CPU.ActiveCfg = Debug|iPhoneSimulator + {208744BD-504E-47D7-9A98-1CF02454A6DA}.silverlight_Release|Any CPU.Build.0 = Debug|iPhoneSimulator + {208744BD-504E-47D7-9A98-1CF02454A6DA}.winphone_Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator + {208744BD-504E-47D7-9A98-1CF02454A6DA}.winphone_Debug|Any CPU.Build.0 = Debug|iPhoneSimulator + {208744BD-504E-47D7-9A98-1CF02454A6DA}.winphone_Release|Any CPU.ActiveCfg = Debug|iPhoneSimulator + {208744BD-504E-47D7-9A98-1CF02454A6DA}.winphone_Release|Any CPU.Build.0 = Debug|iPhoneSimulator + {208744BD-504E-47D7-9A98-1CF02454A6DA}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator + {208744BD-504E-47D7-9A98-1CF02454A6DA}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator + {208744BD-504E-47D7-9A98-1CF02454A6DA}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator + {208744BD-504E-47D7-9A98-1CF02454A6DA}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator + {208744BD-504E-47D7-9A98-1CF02454A6DA}.Debug|iPhone.ActiveCfg = Debug|iPhone + {208744BD-504E-47D7-9A98-1CF02454A6DA}.Debug|iPhone.Build.0 = Debug|iPhone + {208744BD-504E-47D7-9A98-1CF02454A6DA}.Release|iPhone.ActiveCfg = Release|iPhone + {208744BD-504E-47D7-9A98-1CF02454A6DA}.Release|iPhone.Build.0 = Release|iPhone + {208744BD-504E-47D7-9A98-1CF02454A6DA}.DebugStaticRegistrar|iPhone.ActiveCfg = DebugStaticRegistrar|iPhone + {208744BD-504E-47D7-9A98-1CF02454A6DA}.DebugStaticRegistrar|iPhone.Build.0 = DebugStaticRegistrar|iPhone + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {208744BD-504E-47D7-9A98-1CF02454A6DA} = {2BFA13F8-B568-48BF-9A70-9D43F718C523} EndGlobalSection EndGlobal diff --git a/tests/common/mac/MacTestMain.cs b/tests/common/mac/MacTestMain.cs new file mode 100644 index 00000000000..ac20b4908c9 --- /dev/null +++ b/tests/common/mac/MacTestMain.cs @@ -0,0 +1,54 @@ +using System; +#if XAMCORE_2_0 +using AppKit; +using Foundation; +#else +using MonoMac.AppKit; +using MonoMac.Foundation; +#endif +using GuiUnit; +using NUnit.Framework; + +namespace Xamarin.Mac.Tests +{ + static class MainClass + { + static void Main(string[] args) + { + NSApplication.Init(); + NSRunLoop.Main.InvokeOnMainThread(RunTests); + NSApplication.Main(args); + } + + static void RunTests() + { + TestRunner.MainLoop = new NSRunLoopIntegration(); + TestRunner.Main(new[] { + typeof(MainClass).Assembly.Location, + "-labels", + "-noheader" + }); + } + + class NSRunLoopIntegration : NSObject, IMainLoopIntegration + { + public void InitializeToolkit () + { + } + + public void RunMainLoop () + { + } + + public void InvokeOnMainLoop (InvokerHelper helper) + { + NSApplication.SharedApplication.InvokeOnMainThread (helper.Invoke); + } + + public void Shutdown () + { + Environment.Exit (TestRunner.ExitCode); + } + } + } +} diff --git a/tests/introspection/ApiBaseTest.cs b/tests/introspection/ApiBaseTest.cs new file mode 100644 index 00000000000..fccfbc91949 --- /dev/null +++ b/tests/introspection/ApiBaseTest.cs @@ -0,0 +1,270 @@ +// +// Base test fixture for introspection tests +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012-2016 Xamarin Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +using System; +using System.IO; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Text; +using NUnit.Framework; +using Xamarin.Utils; +using System.Linq; + +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +#if MONOTOUCH +using UIKit; +#endif +#else +#if MONOMAC +using MonoMac.Foundation; +using MonoMac.ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +#endif + +namespace Introspection { + + public abstract class ApiBaseTest { + [DllImport ("/usr/lib/libobjc.dylib", EntryPoint = "objc_msgSend")] + protected static extern bool bool_objc_msgSend_IntPtr (IntPtr receiver, IntPtr selector, IntPtr arg1); + [DllImport ("/usr/lib/libobjc.dylib", EntryPoint = "objc_msgSend")] + protected static extern IntPtr IntPtr_objc_msgSend (IntPtr receiver, IntPtr selector); + + private LatchedEnvironmentVariable continueOnFailure = new LatchedEnvironmentVariable ("API_TEST_CONTINUE_ON_FAILURE"); + + StringBuilder error_output = new StringBuilder (); + + protected void AddErrorLine (string line) + { + error_output.AppendLine (line); + Console.Error.WriteLine (line); + Errors++; + } + + protected void AddErrorLine (string format, params object[] parameters) + { + AddErrorLine (string.Format (format, parameters)); + } + + /// + /// Gets or sets a value indicating whether this test fixture will continue after failures. + /// + /// + /// true if continue on failure; otherwise, false. + /// + public bool ContinueOnFailure { + get { return continueOnFailure.Value; } + set { continueOnFailure.Value = value; } + } + + + private LatchedEnvironmentVariable logProgress = new LatchedEnvironmentVariable ("API_TEST_LOG_PROGRESS"); + + /// + /// Gets or sets a value indicating whether this test fixture will log it's progress. + /// + /// + /// true if log progress; otherwise, false. + /// + public bool LogProgress { + get { return logProgress.Value; } + set { logProgress.Value = value; } + } + + protected TextWriter Writer { +#if MONOMAC + get { return Console.Out; } +#elif __WATCHOS__ + get { return Console.Out; } +#else + get { return AppDelegate.Runner.Writer; } +#endif + } + + protected int Errors; + protected void ReportError (string s, params object [] parameters) + { + if (!ContinueOnFailure) + Assert.Fail (s, parameters); + else { + Writer.Write ("[FAIL] "); + Writer.WriteLine (s, parameters); + Errors++; + } + } + + protected void AssertIfErrors (string s, params object[] parameters) + { + if (Errors == 0) + return; + + var msg = string.Format (s, parameters); + if (error_output.Length > 0) { + msg += "\n" + error_output.ToString () + "\n"; + error_output.Clear (); + } + Assert.Fail (msg); + } + + static protected Type NSObjectType = typeof (NSObject); + + protected virtual bool Skip (Attribute attribute) + { + return false; + } + + protected virtual bool SkipDueToAttribute (MemberInfo member) + { + if (member == null) + return false; + + return !member.IsAvailableOnHostPlatform () || + SkipDueToAttribute (member.DeclaringType) || + SkipDueToAttributeInProperty (member); + } + + // We need to check Availability info on PropertyInfo attributes too + // due to sometimes the Availability info only exist on the property + // and not on the property Getter or Setter, this complements the fix for bug: + // https://bugzilla.xamarin.com/show_bug.cgi?id=35176 + protected bool SkipDueToAttributeInProperty (MemberInfo member) + { + if (member == null) + return false; + + var m = member as MethodInfo; + + if (m == null || // Skip anything that is not a method + !m.Attributes.HasFlag (MethodAttributes.SpecialName) || + !m.Name.Contains ("get_")) // We want getters with SpecialName Attribute + return false; + + // FIXME: In the future we could cache this to reduce memory requirements + var property = m.DeclaringType + .GetProperties () + .SingleOrDefault (p => p.GetGetMethod () == m); + return property != null && SkipDueToAttribute (property); + } + + /// + /// Gets the assembly on which the test fixture will reflect the NSObject-derived types. + /// The default implementation returns the assembly where NSObject is defined, e.g. + /// monotouch.dll or xammac.dll. + /// You need to override this method to return the binding assembly you wish to test. + /// + /// + /// The assembly on which the fixture will execute it's tests. + /// + protected virtual Assembly Assembly { + get { return NSObjectType.Assembly; } + } + + const string libprefix = "/System/Library/Frameworks"; + static readonly string simprefix = Environment.GetEnvironmentVariable ("IPHONE_SIMULATOR_ROOT"); + + protected virtual string FindLibrary (string libname, bool requiresFullPath = false) + { + string prefix; + if (!String.IsNullOrEmpty (simprefix) && libname.StartsWith (libprefix, StringComparison.Ordinal)) { + libname = simprefix + libname; + prefix = String.Empty; + } else { + prefix = libprefix; // re-root libname + } + + switch (libname) { +#if !MONOMAC + case "AudioUnit": + libname = "AudioToolbox"; + break; +#endif + case "CoreAnimation": + // generated code uses QuartzCore correctly - even if the [Field] property is wrong + libname = "QuartzCore"; + break; + case "CoreMidi": + // generated code uses CoreMIDI correctly + libname = "CoreMIDI"; + break; + default: + if (requiresFullPath && (Path.GetDirectoryName (libname).Length == 0)) + ReportError ("[FAIL] Library '{0}' is specified without a path", libname); + break; + } + + return Path.Combine (prefix, libname + ".framework", libname); + } + + protected bool IsOSX11OrIOS9 { + get { +#if MONOMAC + return Mac.IsElCapitanOrHigher; +#elif __WATCHOS__ + return false; +#else + return UIDevice.CurrentDevice.CheckSystemVersion (9, 0); +#endif + } + } + + protected bool CheckiOSSystemVersion (int major, int minor) + { +#if __IOS__ + return UIDevice.CurrentDevice.CheckSystemVersion (major, minor); +#else + throw new InvalidOperationException ("Can only check iOS system version on iOS."); +#endif + } + + // This only works for API introduced in the same numeric version in both iOS and tvOS. + protected bool CheckiOSOrTVOSSystemVersion (int major, int minor) + { +#if __IOS__ || __TVOS__ + return UIDevice.CurrentDevice.CheckSystemVersion (major, minor); +#else + throw new InvalidOperationException ("Can only check iOS or tvOS system version on iOS or tvOS."); +#endif + } + + protected bool CheckWatchOSSystemVersion (int major, int minor) + { +#if __WATCHOS__ + throw new NotImplementedException (); +// return UIDevice.CurrentDevice.CheckSystemVersion (major, minor); +#else + throw new InvalidOperationException ("Can only check watchOS system version on watchOS."); +#endif + } + + protected bool CheckTVOSSystemVersion (int major, int minor) + { +#if __TVOS__ + return UIDevice.CurrentDevice.CheckSystemVersion (major, minor); +#else + throw new InvalidOperationException ("Can only check tvOS system version on tvOS."); +#endif + } + } +} diff --git a/tests/introspection/ApiCMAttachmentTest.cs b/tests/introspection/ApiCMAttachmentTest.cs new file mode 100644 index 00000000000..a3cced8173b --- /dev/null +++ b/tests/introspection/ApiCMAttachmentTest.cs @@ -0,0 +1,535 @@ +#if !__WATCHOS__ + +using System; +using System.Drawing; +using System.IO; +using System.Net; +using System.Linq; +using System.Security.Cryptography.X509Certificates; + +using NUnit.Framework; + +#if XAMCORE_2_0 +using AudioToolbox; +using AudioUnit; +using CoreMedia; +using CoreFoundation; +using CoreGraphics; +using CoreText; +using CoreServices; +using CoreVideo; +using Foundation; +using ImageIO; +using MediaToolbox; +using SystemConfiguration; +using ObjCRuntime; +using Security; +using UIKit; +#else +using MonoTouch.AudioToolbox; +using MonoTouch.CoreMedia; +using MonoTouch.CoreFoundation; +using MonoTouch.CoreGraphics; +using MonoTouch.CoreServices; +using MonoTouch.CoreText; +using MonoTouch.CoreVideo; +using MonoTouch.Foundation; +using MonoTouch.ImageIO; +using MonoTouch.SystemConfiguration; +using MonoTouch.ObjCRuntime; +using MonoTouch.Security; +using MonoTouch.UIKit; +#endif + +#if !__TVOS__ + +#if XAMCORE_2_0 +using VideoToolbox; +#else +using MonoTouch.VideoToolbox; +#endif + +#endif + +namespace Introspection { + + [TestFixture] + public class ApiCMAttachmentTest : ApiBaseTest { + static Type CMClockType = typeof (CMClock); + static Type CMAttachmentInterfaceType = typeof (ICMAttachmentBearer); + static Type NativeObjectInterfaceType = typeof (INativeObject); + static Type DispatchSourceType = typeof (DispatchSource); + // CN=mail.google.com, O=Google Inc, L=Mountain View, S=California, C=US + static public byte[] mail_google_com = { + 0x30, 0x82, 0x03, 0x22, 0x30, 0x82, 0x02, 0x8b, 0xa0, 0x03, 0x02, 0x01, + 0x02, 0x02, 0x10, 0x2b, 0x9f, 0x7e, 0xe5, 0xca, 0x25, 0xa6, 0x25, 0x14, + 0x20, 0x47, 0x82, 0x75, 0x3a, 0x9b, 0xb9, 0x30, 0x0d, 0x06, 0x09, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x4c, + 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x5a, + 0x41, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x1c, + 0x54, 0x68, 0x61, 0x77, 0x74, 0x65, 0x20, 0x43, 0x6f, 0x6e, 0x73, 0x75, + 0x6c, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x28, 0x50, 0x74, 0x79, 0x29, 0x20, + 0x4c, 0x74, 0x64, 0x2e, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x0d, 0x54, 0x68, 0x61, 0x77, 0x74, 0x65, 0x20, 0x53, 0x47, + 0x43, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x31, 0x31, 0x30, + 0x32, 0x36, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x31, + 0x33, 0x30, 0x39, 0x33, 0x30, 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, 0x5a, + 0x30, 0x69, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x13, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, + 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x07, 0x14, 0x0d, 0x4d, + 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x56, 0x69, 0x65, 0x77, + 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x14, 0x0a, 0x47, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x31, 0x18, 0x30, + 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x14, 0x0f, 0x6d, 0x61, 0x69, 0x6c, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, + 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, + 0x02, 0x81, 0x81, 0x00, 0xaf, 0x39, 0x15, 0x98, 0x68, 0xe4, 0x92, 0xfe, + 0x4f, 0x4f, 0xf1, 0xbb, 0xff, 0x0d, 0x2e, 0xb0, 0xfe, 0x25, 0xaa, 0xbd, + 0x68, 0x04, 0x67, 0x27, 0xea, 0x6c, 0x43, 0x4c, 0xa7, 0x6d, 0xcb, 0xc8, + 0x8f, 0x7e, 0x81, 0xee, 0x87, 0x26, 0x25, 0x10, 0x12, 0x54, 0x33, 0x9e, + 0xaa, 0x3d, 0x9b, 0x8f, 0x8e, 0x92, 0xb3, 0x4b, 0x01, 0xe3, 0xf9, 0x4a, + 0x29, 0xc3, 0x0f, 0xfd, 0xac, 0xb7, 0xd3, 0x4c, 0x97, 0x29, 0x3f, 0x69, + 0x55, 0xcf, 0x70, 0x83, 0x04, 0xaf, 0x2e, 0x04, 0x6e, 0x74, 0xd6, 0x0f, + 0x17, 0x09, 0xfe, 0x9e, 0x20, 0x24, 0x24, 0xe3, 0xc7, 0x68, 0x9c, 0xac, + 0x11, 0xbd, 0x92, 0xe4, 0xb2, 0x1b, 0x09, 0xf2, 0x02, 0x32, 0xbb, 0x55, + 0x1b, 0x2d, 0x16, 0x5f, 0x30, 0x12, 0x23, 0xe2, 0x4c, 0x4a, 0x8d, 0xc2, + 0xda, 0x3f, 0xe1, 0xb8, 0xbf, 0xf7, 0x3a, 0xb1, 0x86, 0xbe, 0xf0, 0xc5, + 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xe7, 0x30, 0x81, 0xe4, 0x30, + 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x02, 0x30, + 0x00, 0x30, 0x36, 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x2f, 0x30, 0x2d, + 0x30, 0x2b, 0xa0, 0x29, 0xa0, 0x27, 0x86, 0x25, 0x68, 0x74, 0x74, 0x70, + 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, 0x2e, 0x74, 0x68, 0x61, 0x77, 0x74, + 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x54, 0x68, 0x61, 0x77, 0x74, 0x65, + 0x53, 0x47, 0x43, 0x43, 0x41, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x28, 0x06, + 0x03, 0x55, 0x1d, 0x25, 0x04, 0x21, 0x30, 0x1f, 0x06, 0x08, 0x2b, 0x06, + 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, + 0x05, 0x07, 0x03, 0x02, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, + 0x42, 0x04, 0x01, 0x30, 0x72, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, + 0x07, 0x01, 0x01, 0x04, 0x66, 0x30, 0x64, 0x30, 0x22, 0x06, 0x08, 0x2b, + 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, 0x16, 0x68, 0x74, 0x74, + 0x70, 0x3a, 0x2f, 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x2e, 0x74, 0x68, 0x61, + 0x77, 0x74, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x3e, 0x06, 0x08, 0x2b, + 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x32, 0x68, 0x74, 0x74, + 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x74, 0x68, 0x61, 0x77, + 0x74, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x72, 0x65, 0x70, 0x6f, 0x73, + 0x69, 0x74, 0x6f, 0x72, 0x79, 0x2f, 0x54, 0x68, 0x61, 0x77, 0x74, 0x65, + 0x5f, 0x53, 0x47, 0x43, 0x5f, 0x43, 0x41, 0x2e, 0x63, 0x72, 0x74, 0x30, + 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, + 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x35, 0x80, 0x11, 0xcd, 0x52, 0x3e, + 0x84, 0x29, 0xfb, 0xc1, 0x28, 0xe1, 0x20, 0xe5, 0x02, 0x8f, 0x5f, 0x71, + 0x65, 0x58, 0x1d, 0x62, 0x72, 0x57, 0x3c, 0xe6, 0x5e, 0x25, 0x61, 0xd3, + 0xcb, 0xad, 0x22, 0xf8, 0xd8, 0x81, 0xa4, 0xe7, 0xf4, 0xae, 0x7c, 0xd9, + 0xc1, 0x6d, 0xaa, 0x93, 0x0d, 0x62, 0x07, 0x9f, 0xf2, 0x67, 0x47, 0x99, + 0x34, 0x33, 0x4f, 0x3d, 0x02, 0x74, 0xf4, 0x81, 0xd6, 0x38, 0x08, 0x21, + 0xe8, 0xe2, 0xa1, 0xfa, 0x05, 0x41, 0x9c, 0x9c, 0xc9, 0xf9, 0xf3, 0xc8, + 0xa3, 0xee, 0x0d, 0xa5, 0xd7, 0x50, 0x54, 0x5e, 0x2f, 0x7d, 0x79, 0xb7, + 0x7e, 0x0a, 0x7c, 0xb6, 0xe2, 0x2c, 0xa8, 0xae, 0xfe, 0x94, 0xd7, 0xcd, + 0x16, 0x30, 0x71, 0x04, 0xaa, 0x9e, 0x79, 0xc3, 0xd2, 0xb6, 0x24, 0xa7, + 0x25, 0xab, 0xf0, 0x48, 0x8e, 0x2f, 0xc3, 0xa7, 0xbb, 0x50, 0xdd, 0x0f, + 0xcf, 0xb0, }; + + // copy-pasted from mono/mcs/class/corlib/Test/System.Security.Cryptography.X509Certificates/X509Cert20Test.cs + static public byte[] farscape_pfx = { 0x30, 0x82, 0x06, 0xA3, 0x02, 0x01, 0x03, 0x30, 0x82, 0x06, 0x63, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x01, 0xA0, 0x82, 0x06, 0x54, 0x04, 0x82, 0x06, 0x50, 0x30, 0x82, 0x06, 0x4C, 0x30, 0x82, 0x03, 0x8D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x01, 0xA0, 0x82, 0x03, 0x7E, 0x04, 0x82, 0x03, 0x7A, 0x30, 0x82, 0x03, 0x76, 0x30, 0x82, 0x03, 0x72, 0x06, 0x0B, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0C, 0x0A, 0x01, 0x02, 0xA0, 0x82, 0x02, 0xB6, 0x30, 0x82, 0x02, 0xB2, 0x30, 0x1C, 0x06, 0x0A, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0C, 0x01, 0x03, 0x30, + 0x0E, 0x04, 0x08, 0x67, 0xFE, 0x3A, 0x52, 0x75, 0xF3, 0x82, 0x1F, 0x02, 0x02, 0x07, 0xD0, 0x04, 0x82, 0x02, 0x90, 0x31, 0x6B, 0x00, 0xFA, 0x73, 0xE6, 0x8D, 0x3D, 0x62, 0x93, 0x41, 0xA1, 0x44, 0x04, 0x17, 0x8D, 0x66, 0x7A, 0x75, 0x14, 0x89, 0xA8, 0xD1, 0x4D, 0x2A, 0xD7, 0x20, 0x27, 0x71, 0x58, 0x81, 0x16, 0xB5, 0xA6, 0x41, 0x75, 0x92, 0xB2, 0xF4, 0x0C, 0xAA, 0x9B, 0x00, 0x46, 0x85, 0x85, 0x3B, 0x09, 0x2A, 0x62, 0x33, 0x3F, 0x3D, 0x06, 0xC7, 0xE7, 0x16, 0x0C, 0xA7, 0x1D, 0x9C, 0xDA, 0x9D, 0xD3, 0xC9, 0x05, 0x60, 0xA5, 0xBE, 0xF0, 0x07, 0xD5, 0xA9, 0x4F, 0x8A, 0x80, 0xF8, 0x55, 0x7B, 0x7B, 0x3C, + 0xA0, 0x7C, 0x29, 0x29, 0xAB, 0xB1, 0xE1, 0x5A, 0x25, 0xE3, 0x23, 0x6A, 0x56, 0x98, 0x37, 0x68, 0xAF, 0x9C, 0x87, 0xBB, 0x21, 0x6E, 0x68, 0xBE, 0xAE, 0x65, 0x0C, 0x41, 0x8F, 0x5C, 0x3A, 0xB8, 0xB1, 0x9D, 0x42, 0x37, 0xE4, 0xA0, 0x37, 0xA6, 0xB8, 0xAC, 0x85, 0xD7, 0x85, 0x27, 0x68, 0xD0, 0xB6, 0x3D, 0xC7, 0x39, 0x92, 0x41, 0x46, 0x24, 0xDD, 0x08, 0x57, 0x22, 0x6A, 0xC0, 0xB7, 0xAD, 0x52, 0xC6, 0x7F, 0xE5, 0x74, 0x6A, 0x5E, 0x28, 0xA3, 0x85, 0xBD, 0xE8, 0xAD, 0x5D, 0xA3, 0x55, 0xE6, 0x63, 0x15, 0x56, 0x7B, 0x01, 0x26, 0x68, 0x5F, 0x11, 0xA3, 0x12, 0x37, 0x02, 0xA5, 0xD0, 0xB7, 0x73, 0x0C, 0x7C, + 0x97, 0xE1, 0xC6, 0x2F, 0x98, 0x82, 0x67, 0x2F, 0x5F, 0x3F, 0xBE, 0x32, 0x16, 0x25, 0x9D, 0x51, 0x48, 0x32, 0xCB, 0x42, 0xD1, 0x31, 0x07, 0xBE, 0x5D, 0xF8, 0xCD, 0x2C, 0x38, 0x0A, 0x33, 0x3B, 0x7B, 0x04, 0x84, 0xAE, 0x9C, 0xA7, 0x6B, 0x36, 0x39, 0x12, 0x87, 0x9D, 0x5B, 0x56, 0x00, 0x44, 0x11, 0xB1, 0xE2, 0x78, 0x14, 0x60, 0xF3, 0xE4, 0x1A, 0x08, 0x14, 0xC0, 0x9E, 0x49, 0x9F, 0xE0, 0x4C, 0xEC, 0x95, 0x15, 0x18, 0x48, 0x0E, 0xB9, 0x0B, 0x3A, 0xFE, 0x45, 0xB0, 0x2D, 0x0D, 0x4F, 0x94, 0x5A, 0x3C, 0x43, 0xB7, 0x40, 0x8E, 0x7B, 0xA2, 0x8E, 0x23, 0x9F, 0x75, 0x97, 0xE7, 0x21, 0x0D, 0xEB, 0xA3, 0x9D, + 0x6C, 0xC0, 0xDC, 0x73, 0xED, 0x15, 0x98, 0xE3, 0xE8, 0x32, 0x2C, 0x12, 0x92, 0x45, 0x25, 0x45, 0x76, 0x18, 0xF5, 0x97, 0x7F, 0xAC, 0xCE, 0xCF, 0x23, 0xF7, 0xD1, 0xCF, 0x06, 0xAB, 0x82, 0x96, 0x1F, 0xF8, 0x68, 0x4F, 0x5D, 0xE1, 0x09, 0xAA, 0xCB, 0xB3, 0x50, 0x85, 0x46, 0x72, 0x14, 0x6C, 0x49, 0x84, 0x57, 0x55, 0x00, 0x78, 0x3E, 0xD9, 0xAA, 0xBD, 0xCC, 0xE2, 0x7B, 0x18, 0xAA, 0x2E, 0x5D, 0xB9, 0x28, 0xEA, 0x8F, 0x8C, 0xFA, 0xB7, 0x06, 0x27, 0x07, 0x89, 0x41, 0x3F, 0x66, 0x1A, 0x91, 0xCA, 0xE9, 0xEC, 0x09, 0x12, 0x1C, 0x67, 0xB2, 0x2A, 0x8B, 0x4A, 0xF0, 0x97, 0x17, 0xDC, 0x3E, 0xCD, 0x9F, 0x03, + 0x15, 0xEF, 0x03, 0x84, 0x08, 0x4A, 0x73, 0xAE, 0xE4, 0x07, 0x30, 0x27, 0xF7, 0x25, 0x69, 0x9D, 0x6C, 0x7D, 0x81, 0x88, 0xCC, 0xFA, 0xD4, 0xC7, 0x64, 0x11, 0xC0, 0xC8, 0x2C, 0x23, 0xF6, 0xFF, 0x9B, 0xE3, 0xC8, 0x89, 0x85, 0x0B, 0x3E, 0x81, 0xD8, 0x9C, 0xBD, 0xD0, 0x2D, 0xCD, 0x15, 0xA9, 0x30, 0x84, 0xF7, 0x6D, 0xEF, 0x62, 0x3B, 0xA7, 0x8C, 0xC2, 0x93, 0x90, 0x6F, 0x91, 0xB4, 0x8A, 0x71, 0x4E, 0x41, 0x4E, 0x5C, 0x67, 0xB5, 0x49, 0xF8, 0x56, 0x3A, 0x83, 0x03, 0x4F, 0xB1, 0xF6, 0xB7, 0x31, 0x5B, 0x68, 0x26, 0x70, 0x89, 0xB1, 0x1E, 0x67, 0x4F, 0xBA, 0xE7, 0xD9, 0xDF, 0x91, 0xD8, 0xFB, 0x8A, 0xDD, + 0xB2, 0xD3, 0x4B, 0xBB, 0x9F, 0x5C, 0xA3, 0x04, 0x2C, 0x87, 0xBC, 0xD5, 0xBE, 0x8C, 0xD7, 0xCF, 0x9B, 0x72, 0x82, 0xA6, 0x99, 0xDA, 0xD7, 0x66, 0x48, 0xE7, 0x8F, 0xE9, 0x48, 0x56, 0x9D, 0xD2, 0xB9, 0x28, 0x84, 0x4F, 0x6A, 0x83, 0xB2, 0xB9, 0x4D, 0x91, 0x10, 0x58, 0x22, 0x4C, 0xE7, 0x9D, 0xC6, 0x0C, 0x74, 0xF4, 0x16, 0x58, 0x30, 0xB7, 0xB7, 0x96, 0x39, 0x6C, 0x5D, 0xFA, 0xB2, 0x03, 0x8C, 0x98, 0xD2, 0xC0, 0x64, 0xB8, 0x05, 0x29, 0x4F, 0xF0, 0x4C, 0x43, 0x48, 0xD3, 0xD8, 0xBD, 0xC7, 0xC1, 0xEA, 0x39, 0x2A, 0xDF, 0xD4, 0xDA, 0x79, 0x7C, 0xB9, 0x06, 0xC7, 0x10, 0x8D, 0x8B, 0xF1, 0xA8, 0x8E, 0x44, + 0x9E, 0x99, 0xFF, 0x81, 0x84, 0x8F, 0xD0, 0x38, 0xE1, 0xF0, 0x5A, 0x12, 0x5F, 0xC5, 0xA6, 0xED, 0x6D, 0xEE, 0xE7, 0x69, 0xC0, 0xA2, 0xB4, 0x13, 0xCA, 0x7A, 0x5D, 0xDE, 0x88, 0x75, 0xE7, 0xE2, 0x6D, 0x8A, 0xEC, 0x0F, 0x88, 0x3F, 0xE2, 0xCB, 0x60, 0xF0, 0x6A, 0xEC, 0xD0, 0xF4, 0x0D, 0x11, 0xC2, 0x84, 0x19, 0x67, 0x52, 0xAD, 0xC0, 0xC0, 0x20, 0x84, 0x6D, 0x7D, 0xEA, 0xD2, 0xF9, 0x3F, 0xE5, 0x58, 0x00, 0xED, 0x24, 0xD6, 0x50, 0x9B, 0x80, 0x80, 0x0A, 0x31, 0x81, 0xA8, 0x30, 0x0D, 0x06, 0x09, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x11, 0x02, 0x31, 0x00, 0x30, 0x13, 0x06, 0x09, 0x2A, 0x86, 0x48, + 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x15, 0x31, 0x06, 0x04, 0x04, 0x01, 0x00, 0x00, 0x00, 0x30, 0x17, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x14, 0x31, 0x0A, 0x1E, 0x08, 0x00, 0x4D, 0x00, 0x6F, 0x00, 0x6E, 0x00, 0x6F, 0x30, 0x69, 0x06, 0x09, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x11, 0x01, 0x31, 0x5C, 0x1E, 0x5A, 0x00, 0x4D, 0x00, 0x69, 0x00, 0x63, 0x00, 0x72, 0x00, 0x6F, 0x00, 0x73, 0x00, 0x6F, 0x00, 0x66, 0x00, 0x74, 0x00, 0x20, 0x00, 0x52, 0x00, 0x53, 0x00, 0x41, 0x00, 0x20, 0x00, 0x53, 0x00, 0x43, 0x00, 0x68, 0x00, 0x61, 0x00, 0x6E, 0x00, 0x6E, 0x00, 0x65, 0x00, 0x6C, + 0x00, 0x20, 0x00, 0x43, 0x00, 0x72, 0x00, 0x79, 0x00, 0x70, 0x00, 0x74, 0x00, 0x6F, 0x00, 0x67, 0x00, 0x72, 0x00, 0x61, 0x00, 0x70, 0x00, 0x68, 0x00, 0x69, 0x00, 0x63, 0x00, 0x20, 0x00, 0x50, 0x00, 0x72, 0x00, 0x6F, 0x00, 0x76, 0x00, 0x69, 0x00, 0x64, 0x00, 0x65, 0x00, 0x72, 0x30, 0x82, 0x02, 0xB7, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x06, 0xA0, 0x82, 0x02, 0xA8, 0x30, 0x82, 0x02, 0xA4, 0x02, 0x01, 0x00, 0x30, 0x82, 0x02, 0x9D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x01, 0x30, 0x1C, 0x06, 0x0A, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0C, 0x01, + 0x06, 0x30, 0x0E, 0x04, 0x08, 0xB8, 0x22, 0xEA, 0x3C, 0x70, 0x6A, 0xFC, 0x39, 0x02, 0x02, 0x07, 0xD0, 0x80, 0x82, 0x02, 0x70, 0x76, 0xBE, 0x5B, 0xD5, 0x3D, 0x05, 0xC1, 0xDB, 0x10, 0xA3, 0x02, 0xBB, 0x7F, 0x0A, 0x8B, 0x54, 0xC1, 0x7D, 0x19, 0xDA, 0x7E, 0x82, 0xDF, 0xAD, 0x6B, 0x42, 0xC2, 0x95, 0x95, 0x00, 0x6E, 0x82, 0x77, 0xD5, 0x42, 0x6E, 0x21, 0xA2, 0x95, 0xB4, 0x98, 0xF5, 0xDD, 0x18, 0x6F, 0xC4, 0xF3, 0xB6, 0x93, 0xA0, 0x6C, 0xF4, 0x34, 0x7A, 0x48, 0x72, 0x08, 0xB1, 0x28, 0x51, 0x54, 0x10, 0x7F, 0x35, 0xB2, 0xE5, 0x89, 0x5C, 0x0A, 0x14, 0x31, 0x1C, 0x9D, 0xA9, 0xE4, 0x94, 0x91, 0x28, 0x65, + 0xC4, 0xE7, 0x5E, 0xA9, 0x37, 0x08, 0x3D, 0xB1, 0x16, 0x61, 0x9D, 0xA9, 0x44, 0x6F, 0x20, 0x0C, 0x55, 0xD7, 0xCC, 0x48, 0x82, 0x13, 0x5D, 0xE1, 0xBD, 0x9D, 0xCE, 0x64, 0x28, 0x6D, 0x69, 0x4E, 0x08, 0x53, 0x09, 0xE0, 0xCC, 0xA8, 0x79, 0x04, 0xCF, 0xFA, 0x35, 0x1C, 0xA6, 0x70, 0x37, 0x64, 0x70, 0x74, 0xF8, 0xD0, 0xC4, 0x34, 0x0F, 0x71, 0xEF, 0x57, 0xC2, 0x43, 0x7D, 0xFA, 0xE5, 0x1B, 0x8C, 0x15, 0xA5, 0x08, 0x60, 0x78, 0xAF, 0xDA, 0x36, 0xDF, 0x79, 0x2D, 0xD7, 0x54, 0x35, 0xD7, 0x8D, 0x99, 0xD5, 0x81, 0xEC, 0x6D, 0x9F, 0x2D, 0x5E, 0xF8, 0x48, 0x85, 0x50, 0x20, 0x7D, 0xBB, 0x16, 0x4E, 0x39, 0x64, + 0xB7, 0xBC, 0xED, 0xA9, 0x6A, 0x7A, 0x06, 0x09, 0x6B, 0xBC, 0x2C, 0x5A, 0xE1, 0x4F, 0xD4, 0xA9, 0x82, 0x83, 0x5B, 0xBD, 0xCE, 0x14, 0x31, 0x89, 0x66, 0xB3, 0x9C, 0x31, 0x23, 0x00, 0x4B, 0x02, 0x34, 0x85, 0x30, 0x39, 0x77, 0x80, 0x5D, 0x72, 0x0A, 0xCE, 0x43, 0x2A, 0x1F, 0x02, 0x09, 0xAB, 0x2D, 0x46, 0x3A, 0x1C, 0xD2, 0x7B, 0xF6, 0x02, 0x92, 0xCA, 0xDA, 0x26, 0x0C, 0xF8, 0xE2, 0x67, 0x7E, 0xE2, 0x55, 0xB1, 0x3F, 0x6A, 0x06, 0x65, 0x6D, 0x74, 0x98, 0x59, 0xE2, 0x8A, 0x1E, 0x61, 0x03, 0x4D, 0xFC, 0x68, 0x31, 0x6A, 0xE7, 0xCF, 0x52, 0x88, 0x8E, 0x06, 0x97, 0x77, 0xB3, 0x20, 0x7E, 0x09, 0x5D, 0x3B, + 0xAF, 0x56, 0xF4, 0xE8, 0x4C, 0x69, 0x09, 0xB9, 0x80, 0x38, 0xDC, 0x66, 0x2E, 0x06, 0xF6, 0xCB, 0x1F, 0x1B, 0xAD, 0x51, 0xFF, 0xFD, 0x38, 0x8D, 0x03, 0x90, 0xCF, 0x31, 0x01, 0x30, 0xEA, 0x48, 0x4C, 0xBB, 0x40, 0x87, 0x1D, 0x97, 0x6A, 0x56, 0x4C, 0xED, 0x07, 0x23, 0x45, 0x50, 0x2F, 0x56, 0xC9, 0x90, 0x79, 0x09, 0xC5, 0x45, 0xB9, 0xAD, 0x58, 0x2B, 0x4C, 0xA3, 0x01, 0xE0, 0x2D, 0xE5, 0x30, 0xBC, 0x54, 0xEC, 0x65, 0xB4, 0x79, 0x22, 0x7D, 0x15, 0xF6, 0x28, 0xCD, 0x84, 0x7E, 0x27, 0x95, 0xA1, 0xC7, 0x82, 0x6D, 0xFB, 0xDF, 0x03, 0xD9, 0x14, 0xFE, 0x0A, 0x06, 0x6F, 0x14, 0xFF, 0x8A, 0x27, 0x80, 0x36, + 0xDC, 0xBA, 0xAE, 0xDD, 0x44, 0x15, 0xA5, 0x6E, 0x64, 0x73, 0xBD, 0xFB, 0xAE, 0x6D, 0x6F, 0x42, 0x96, 0xDF, 0x90, 0xE5, 0x6A, 0x9B, 0x05, 0xAE, 0xD5, 0x0A, 0x22, 0x88, 0xD6, 0x5D, 0x4C, 0x7B, 0xB1, 0x3A, 0xFC, 0x0C, 0x32, 0x02, 0xB1, 0x18, 0x0D, 0xAF, 0xE0, 0xFE, 0x7E, 0x07, 0x96, 0x85, 0xBB, 0xC8, 0x21, 0x68, 0x12, 0xD4, 0xC8, 0xBF, 0x91, 0x47, 0xE2, 0xF3, 0xA5, 0xA3, 0x86, 0xE6, 0x30, 0x42, 0xF5, 0xA9, 0xB9, 0x48, 0xCB, 0x18, 0xE6, 0x64, 0x3B, 0xE0, 0x8E, 0xC3, 0x03, 0x45, 0xA0, 0xED, 0x1A, 0x09, 0xFF, 0xB3, 0x99, 0x14, 0x5F, 0xDA, 0x90, 0x58, 0x61, 0x8E, 0xF7, 0x0A, 0x00, 0xC7, 0x44, 0xE7, + 0x73, 0x78, 0xC4, 0x8B, 0x39, 0xCE, 0x70, 0x0E, 0x24, 0x03, 0x95, 0x94, 0x73, 0x76, 0x10, 0x7E, 0x4C, 0xFF, 0xCA, 0x49, 0x93, 0x89, 0xD4, 0x3E, 0x1A, 0x88, 0xCC, 0x48, 0xA7, 0x78, 0x2F, 0x83, 0x4F, 0x6C, 0x33, 0x55, 0xDD, 0x7F, 0x7D, 0x4D, 0xE5, 0xCD, 0x9C, 0x3D, 0x04, 0x1E, 0xC1, 0x9B, 0x6D, 0x7E, 0x7A, 0xAC, 0x93, 0x5E, 0x2B, 0xC3, 0x85, 0x36, 0x07, 0x66, 0xE8, 0xC9, 0xC0, 0xD1, 0x54, 0xF4, 0x4C, 0x6A, 0x02, 0x24, 0x9A, 0x7D, 0x10, 0xD9, 0x79, 0x94, 0x00, 0x64, 0x63, 0x36, 0xDC, 0x35, 0x0C, 0x8F, 0x79, 0xBA, 0xC7, 0x10, 0x76, 0xF8, 0x4A, 0xD3, 0x69, 0x95, 0x23, 0x89, 0x66, 0xC4, 0x5A, 0xE7, + 0xCE, 0x21, 0xBC, 0xCB, 0xF2, 0x4F, 0x92, 0x33, 0xE7, 0x89, 0xD6, 0x23, 0xF7, 0x67, 0x5B, 0x20, 0xD9, 0xDA, 0x1A, 0xD1, 0xF6, 0x9E, 0x01, 0x83, 0x51, 0xAF, 0x35, 0x43, 0xDD, 0x3A, 0xAB, 0xCA, 0x0E, 0xED, 0x2E, 0x4D, 0x1E, 0x91, 0xCF, 0x2E, 0xA9, 0x4D, 0x08, 0xD9, 0x48, 0x30, 0x37, 0x30, 0x1F, 0x30, 0x07, 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x04, 0x14, 0xA2, 0xED, 0x05, 0x50, 0x89, 0x91, 0x1D, 0xEB, 0xF6, 0x57, 0x66, 0xAF, 0x70, 0x15, 0xDD, 0x1A, 0xA1, 0x94, 0xB7, 0xB2, 0x04, 0x14, 0x09, 0xE4, 0x0B, 0xEC, 0x1D, 0x93, 0x3E, 0x32, 0x94, 0x6A, 0x95, 0x36, 0xDD, 0xBA, 0x93, 0x9D, 0x75, 0xB6, + 0x3E, 0xF5 }; + + // wrap the object so that we can use the extensions and fail + class AttachableNativeObject : ICMAttachmentBearer + { + INativeObject nativeObj; + + public AttachableNativeObject (INativeObject obj) + { + nativeObj = obj; + } + + public IntPtr Handle + { + get { return nativeObj.Handle; } + } + } + + protected virtual bool Skip (Type type) + { + return Skip (type.Name) || SkipDueToAttribute (type); + } + + protected virtual bool Skip (string nativeName) + { + if (nativeName.Contains ("`")) { + nativeName = nativeName.Substring (0, nativeName.IndexOf ("`")); + } + if (nativeName.StartsWith ("CGPDF")) // all those types crash the app + return true; + switch (nativeName) { + case "CFMachPort": + case "CFMessagePort": + case "DispatchSource": + case "AudioConverter": // does crash the tests + case "AudioFile": // does crash the tests + case "CFHTTPAuthentication": + case "CFHTTPStream": + case "SystemSound": // does crash the tests + case "MusicPlayer": // does crash the tests + case "MusicTrack": // does crash the tests + case "AUGraph": // does crash the tests + case "CGFunction": + case "CGShading": + case "CVMetalTexture": + case "CVMetalTextureCache": + case "CTRun": + case "CTRunDelegate": + case "CGImageMetadata": + case "SecKeyChain": // static class + case "VTDecompressionSession": + case "Class": // makes no sense to test + case "Selector": // makes no sense to test + case "CFRunLoopSource": + case "CFRunLoop": + case "NSZone": + case "MusicSequence": // crashes tests + case "AudioBuffers": // crashes tests + case "CGContext": + case "AudioComponent": + case "AudioUnit": + case "AURenderEventEnumerator": + case "CGLayer": + case "CMFormatDescription": + case "CMAudioFormatDescription": + case "CMVideoFormatDescription": + case "CMBlockBuffer": + case "CMSampleBuffer": + case "CVBuffer": // DOES support the API, but it has its own version and is already in the bindings, so no need ATM + case "CVImageBuffer": // same as CVBuffer + case "CVPixelBuffer": // same as CVBuffer + case "MTAudioProcessingTap": + case "Protocol": + case "MidiObject": // causes crash + case "CMClockOrTimebase": + case "MidiClient": + case "MidiPort": + case "MidiEntity": + case "MidiDevice": + case "MidiEndpoint": + case "ABMultiValue": + return true; + default: + return false; + } + } + + protected INativeObject GetINativeInstance (Type t) + { + var ctor = t.GetConstructor (Type.EmptyTypes); + if ((ctor != null) && !ctor.IsAbstract) + return ctor.Invoke (null) as INativeObject; + + if (!NativeObjectInterfaceType.IsAssignableFrom (t)) + throw new ArgumentException ("t"); + switch (t.Name) { + case "CFAllocator": + return CFAllocator.SystemDefault; + case "CFBundle": + var bundles = CFBundle.GetAll (); + if (bundles.Length > 0) + return bundles [0]; + else + throw new InvalidOperationException (string.Format ("Could not create the new instance for type {0}.", t.Name)); + case "CFNotificationCenter": + return CFNotificationCenter.Darwin; + case "CFReadStream": + case "CFStream": + CFReadStream readStream; + CFWriteStream writeStream; + CFStream.CreatePairWithSocketToHost ("www.google.com", 80, out readStream, out writeStream); + return readStream; + case "CFWriteStream": + CFStream.CreatePairWithSocketToHost ("www.google.com", 80, out readStream, out writeStream); + return writeStream; + case "CFUrl": + return CFUrl.FromFile ("/etc"); + case "AudioFile": + var path = Path.GetFullPath ("1.caf"); + var af = AudioFile.Open (CFUrl.FromFile (path), AudioFilePermission.Read, AudioFileType.CAF); + return af; + case "CFHTTPMessage": + return CFHTTPMessage.CreateEmpty (false); + case "CGBitmapContext": + byte[] data = new byte [400]; + using (CGColorSpace space = CGColorSpace.CreateDeviceRGB ()) { + return new CGBitmapContext (data, 10, 10, 8, 40, space, CGBitmapFlags.PremultipliedLast); + } + case "CGContextPDF": + var filename = Environment.GetFolderPath (Environment.SpecialFolder.CommonDocuments) + "/t.pdf"; + using (var url = new NSUrl (filename)) + return new CGContextPDF (url); + case "CGColorConverter": + var cvt = new CGColorConverterTriple () { + Space = CGColorSpace.CreateGenericRgb (), + Intent = CGColorRenderingIntent.Default, + Transform = CGColorConverterTransformType.ApplySpace + }; + return new CGColorConverter (null, cvt, cvt, cvt); + case "CGDataConsumer": + using (NSMutableData destData = new NSMutableData ()) { + return new CGDataConsumer (destData); + } + case "CGDataProvider": + filename = "xamarin1.png"; + return new CGDataProvider (filename); + case "CGFont": + return CGFont.CreateWithFontName ("Courier New"); + case "CGPattern": + return new CGPattern ( + new RectangleF (0, 0, 16, 16), + CGAffineTransform.MakeIdentity (), + 16, 16, + CGPatternTiling.NoDistortion, + true, + (cgc) => {}); + case "CMBufferQueue": + return CMBufferQueue.CreateUnsorted (2); + case "CTFont": + CTFontDescriptorAttributes fda = new CTFontDescriptorAttributes () { + FamilyName = "Courier", + StyleName = "Bold", + Size = 16.0f + }; + using (var fd = new CTFontDescriptor (fda)) + return new CTFont (fd, 10, CTFontOptions.Default); + case "CTFontCollection": + return new CTFontCollection (new CTFontCollectionOptions ()); + case "CTFontDescriptor": + fda = new CTFontDescriptorAttributes (); + return new CTFontDescriptor (fda); + case "CTTextTab": + return new CTTextTab (CTTextAlignment.Left, 2); + case "CTTypesetter": + return new CTTypesetter (new NSAttributedString ("Hello, world", + new CTStringAttributes () { + ForegroundColorFromContext = true, + Font = new CTFont ("Arial", 24) + })); + case "CTFrame": + var framesetter = new CTFramesetter (new NSAttributedString ("Hello, world", + new CTStringAttributes () { + ForegroundColorFromContext = true, + Font = new CTFont ("Arial", 24) + })); + var bPath = UIBezierPath.FromRect (new RectangleF (0, 0, 3, 3)); + return framesetter.GetFrame (new NSRange (0, 0), bPath.CGPath, null); + case "CTFramesetter": + return new CTFramesetter (new NSAttributedString ("Hello, world", + new CTStringAttributes () { + ForegroundColorFromContext = true, + Font = new CTFont ("Arial", 24) + })); + case "CTGlyphInfo": + return new CTGlyphInfo ("Zapfino", new CTFont ("Arial", 24), "Foo"); + case "CTLine": + return new CTLine (new NSAttributedString ("Hello, world", + new CTStringAttributes () { + ForegroundColorFromContext = true, + Font = new CTFont ("Arial", 24) + })); + case "CGImageDestination": + var storage = new NSMutableData (); + return CGImageDestination.Create (new CGDataConsumer (storage), "public.png", 1); + case "CGImageMetadataTag": + using (NSString name = new NSString ("tagName")) + using (var value = new NSString ("value")) + return new CGImageMetadataTag (CGImageMetadataTagNamespaces.Exif, CGImageMetadataTagPrefixes.Exif, name, CGImageMetadataType.Default, value); + case "CGImageSource": + filename = "xamarin1.png"; + return CGImageSource.FromUrl (NSUrl.FromFilename (filename)); + case "SecPolicy": + return SecPolicy.CreateSslPolicy (false, null); + case "SecIdentity": + using (var options = NSDictionary.FromObjectAndKey (new NSString ("farscape"), SecImportExport.Passphrase)) { + NSDictionary[] array; + var result = SecImportExport.ImportPkcs12 (farscape_pfx, options, out array); + if (result != SecStatusCode.Success) + throw new InvalidOperationException (string.Format ("Could not create the new instance for type {0} due to {1}.", t.Name, result)); + return new SecIdentity (array [0].LowlevelObjectForKey (SecImportExport.Identity.Handle)); + } + case "SecTrust": + X509Certificate x = new X509Certificate (mail_google_com); + using (var policy = SecPolicy.CreateSslPolicy (true, "mail.google.com")) + return new SecTrust (x, policy); + case "SslContext": + return new SslContext (SslProtocolSide.Client, SslConnectionType.Stream); + case "UIFontFeature": + return new UIFontFeature (CTFontFeatureNumberSpacing.Selector.ProportionalNumbers); + case "NetworkReachability": + return new NetworkReachability (IPAddress.Loopback, null); +#if !__TVOS__ + case "VTCompressionSession": + case "VTSession": + return VTCompressionSession.Create (1024, 768, CMVideoCodecType.H264, (sourceFrame, status, flags, buffer) => { }, null, (CVPixelBufferAttributes) null); + case "VTFrameSilo": + return VTFrameSilo.Create (); + case "VTMultiPassStorage": + return VTMultiPassStorage.Create (); +#endif + case "CFString": + return new CFString ("test"); + case "DispatchQueue": + return new DispatchQueue ("com.example.subsystem.taskXYZ"); + case "DispatchGroup": + return DispatchGroup.Create (); + case "CGColorSpace": + return CGColorSpace.CreateAcesCGLinear (); + case "CGGradient": + CGColor[] cArray = { UIColor.Black.CGColor, UIColor.Clear.CGColor, UIColor.Blue.CGColor }; + return new CGGradient (null, cArray); + case "CGImage": + filename = "xamarin1.png"; + using (var dp = new CGDataProvider (filename)) + return CGImage.FromPNG (dp, null, false, CGColorRenderingIntent.Default); + case "CGColor": + return UIColor.Black.CGColor; + case "CMClock": + CMClockError ce; + CMClock clock = CMClock.CreateAudioClock (out ce); + if (ce == CMClockError.None) + return clock; + throw new InvalidOperationException (string.Format ("Could not create the new instance for type {0}.", t.Name)); + case "CMTimebase": + clock = CMClock.CreateAudioClock (out ce); + if (ce == CMClockError.None) { + return new CMTimebase (clock); + } + throw new InvalidOperationException (string.Format ("Could not create the new instance for type {0}.", t.Name)); + case "CVPixelBufferPool": + return new CVPixelBufferPool ( + new CVPixelBufferPoolSettings (), + new CVPixelBufferAttributes (CVPixelFormatType.CV24RGB, 100, 50) + ); + case "SecCertificate": + using (var cdata = NSData.FromArray (mail_google_com)) + return new SecCertificate (cdata); + case "SecKey": + SecKey private_key; + SecKey public_key; + using (var record = new SecRecord (SecKind.Key)) { + record.KeyType = SecKeyType.RSA; + record.KeySizeInBits = 512; // it's not a performance test :) + SecKey.GenerateKeyPair (record.ToDictionary (), out public_key, out private_key); + return private_key; + } + case "SecAccessControl": + return new SecAccessControl (SecAccessible.WhenPasscodeSetThisDeviceOnly); + default: + throw new InvalidOperationException (string.Format ("Could not create the new instance for type {0}.", t.Name)); + } + } + + protected ICMAttachmentBearer GetInstance (Type t) + { + if (!CMAttachmentInterfaceType.IsAssignableFrom (t)) + throw new ArgumentException ("t"); + switch (t.Name) { + case "CMBlockBuffer": + CMBlockBufferError bbe; + var result = CMBlockBuffer.CreateEmpty (0, CMBlockBufferFlags.AssureMemoryNow, out bbe); + if (bbe == CMBlockBufferError.None) + return result; + else + throw new InvalidOperationException (string.Format ("Could not create the new instance {0}.", bbe.ToString ())); + case "CMSampleBuffer": + var pixelBuffer = new CVPixelBuffer (20, 10, CVPixelFormatType.CV24RGB); + + CMFormatDescriptionError fde; + var desc = CMVideoFormatDescription.CreateForImageBuffer (pixelBuffer, out fde); + + var sampleTiming = new CMSampleTimingInfo (); + + CMSampleBufferError sbe; + var sb = CMSampleBuffer.CreateForImageBuffer (pixelBuffer, true, desc, sampleTiming, out sbe); + if (sbe == CMSampleBufferError.None) + return sb; + else + throw new InvalidOperationException (string.Format ("Could not create the new instance {0}.", sbe.ToString ())); + default: + throw new InvalidOperationException (string.Format ("Could not create the new instance for type {0}.", t.Name)); + } + } + + [Test] + // test that the tag classes DO support the attachments API. + public void CheckAttachments () + { + var types = CMClockType.Assembly.GetTypes () + .Where(t => CMAttachmentInterfaceType.IsAssignableFrom(t) && !t.IsInterface); + foreach (var t in types) { + ICMAttachmentBearer obj = GetInstance (t); + if (obj is NSObject) + continue; + Assert.That (obj.Handle, Is.Not.EqualTo (IntPtr.Zero), t.Name + ".Handle"); + using (var attch = new CFString ("myAttch")) { + var mode = CMAttachmentMode.ShouldNotPropagate; + CMAttachmentMode otherMode; + obj.SetAttachment ("key", attch, CMAttachmentMode.ShouldNotPropagate); + using (var otherAttch = obj.GetAttachment ("key", out otherMode)) { + obj.RemoveAllAttachments (); + Assert.AreEqual (mode, otherMode); + Assert.IsNotNull (otherAttch, "For type {0}", t.Name); + Assert.AreEqual (attch.ToString (), otherAttch.ToString (), "For type {0}", t.Name); + } + } + if (t is IDisposable) { + var disposable = obj as IDisposable; + disposable.Dispose (); + } + } + } + + [Test] + // test that the classes do not support the attachments API + public void CheckFailAttachments () + { + // get all tupes that are public, native object but not NSobjects or DispatchSources and that are not interfaces or abstract classes + var types = CMClockType.Assembly.GetTypes () + .Where(t => !t.IsNotPublic && !CMAttachmentInterfaceType.IsAssignableFrom(t) + && NativeObjectInterfaceType.IsAssignableFrom (t) && !t.IsSubclassOf (NSObjectType) + && !t.IsSubclassOf (DispatchSourceType) && !t.IsInterface && !t.IsAbstract); + foreach (var t in types) { + if (Skip (t)) + continue; + var obj = new AttachableNativeObject (GetINativeInstance (t)); + Assert.That (obj.Handle, Is.Not.EqualTo (IntPtr.Zero), t.Name + ".Handle"); + using (var attch = new CFString ("myAttch")) { + CMAttachmentMode otherMode; + obj.SetAttachment ("key", attch, CMAttachmentMode.ShouldNotPropagate); + using (var otherAttch = obj.GetAttachment ("key", out otherMode)) { + obj.RemoveAllAttachments (); + Assert.Null (otherAttch, "For type {0}", t.Name); + } + } + if (t is IDisposable) { + var disposable = obj as IDisposable; + disposable.Dispose (); + } + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/introspection/ApiClassPtrTest.cs b/tests/introspection/ApiClassPtrTest.cs new file mode 100644 index 00000000000..2e58dea9937 --- /dev/null +++ b/tests/introspection/ApiClassPtrTest.cs @@ -0,0 +1,119 @@ +// +// Test fixture for class_ptr introspection tests +// +// Authors: +// Alex Soto +// +// Copyright 2012-2014, 2016 Xamarin Inc. +// +using System; +using System.Reflection; +using System.Linq; + +using NUnit.Framework; +using Xamarin.Utils; +using System.Runtime.CompilerServices; + +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +#elif MONOMAC +using MonoMac.Foundation; +using MonoMac.ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif + +namespace Introspection { + + public abstract class ApiClassPtrTest : ApiBaseTest { + + protected virtual bool Skip (Type type) + { + // skip delegate (and other protocol references) + foreach (object ca in type.GetCustomAttributes (false)) { + if (ca is ProtocolAttribute) + return true; + if (ca is ModelAttribute) + return true; + } + return SkipDueToAttribute (type); + } + + Type GetExtendedType (Type extensionType) + { + var method = + (from m in extensionType.GetMethods (BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) + where m.IsDefined (typeof (ExtensionAttribute), false) + select m).FirstOrDefault(); + + if (method != null) { + var paramType = method.GetParameters () [0].ParameterType; + if (paramType.Name == "String") + return typeof (NSString); + else + return paramType; + } + else + return null; + } + + IntPtr GetClassPtrFromRegister (Type t) + { + var attribs = t.GetCustomAttributes (typeof (RegisterAttribute), true); + if (attribs.Length > 0) { + var register = ((RegisterAttribute) attribs [0]); + return Class.GetHandle (register.Name); + } + return IntPtr.Zero; + } + + [Test] + public void VerifyClassPtr () + { + foreach (Type t in Assembly.GetTypes ()) { + if (t.IsNested || !NSObjectType.IsAssignableFrom (t)) + continue; + + if (t.ContainsGenericParameters) + continue; + + if (Skip (t)) + continue; + + FieldInfo fi = t.GetField ("class_ptr", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static); + if (fi == null) + continue; + IntPtr class_ptr = (IntPtr) fi.GetValue (null); + IntPtr register_class_ptr = GetClassPtrFromRegister (t); + + Assert.AreEqual (class_ptr, register_class_ptr, "class_ptr and RegisterAttribute are different: " + t.Name); + } + } + + [Test] + public void VerifyClassPtrCategories () + { + foreach (Type t in Assembly.GetTypes().Where (t => t.IsClass && t.IsSealed && t.IsAbstract)) { + if (Skip (t)) + continue; + + FieldInfo fi = t.GetField ("class_ptr", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static); + if (fi == null) + continue; + IntPtr class_ptr = (IntPtr)fi.GetValue (null); + + var extendedType = GetExtendedType (t); + IntPtr extended_class_ptr; + if (extendedType == null) + extended_class_ptr = IntPtr.Zero; + else + extended_class_ptr = GetClassPtrFromRegister (extendedType); + + Assert.AreEqual (class_ptr, extended_class_ptr, "class_ptr and RegisterAttribute from extended class are different: " + t.Name); + } + } + } +} + diff --git a/tests/introspection/ApiCoreImageFiltersTest.cs b/tests/introspection/ApiCoreImageFiltersTest.cs new file mode 100644 index 00000000000..fd7678e30cf --- /dev/null +++ b/tests/introspection/ApiCoreImageFiltersTest.cs @@ -0,0 +1,211 @@ +// +// Test the generated API for all CoreImage filters +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013, 2015 Xamarin Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#if !__WATCHOS__ + +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; + +using NUnit.Framework; + +#if XAMCORE_2_0 +using CoreImage; +using Foundation; +using ObjCRuntime; +#if !MONOMAC +using UIKit; +#endif +#elif MONOMAC +using MonoMac.CoreImage; +using MonoMac.Foundation; +#else +using MonoTouch.CoreImage; +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +#endif + +namespace Introspection { + + [TestFixture] + // we want the tests to be available because we use the linker + [Preserve (AllMembers = true)] + public abstract class ApiCoreImageFiltersTest : ApiBaseTest { + + static Type CIFilterType = typeof (CIFilter); + + protected virtual bool Skip (Type type) + { + return Skip (type.Name) || SkipDueToAttribute (type); + } + + protected virtual bool Skip (string nativeName) + { + switch (nativeName) { + // Both reported in radar #21548819 + // NSUnknownKeyException [ valueForUndefinedKey:]: this class is not key value coding-compliant for the key inputPoint2. + case "CIDepthOfField": + // NSUnknownKeyException [ valueForUndefinedKey:]: this class is not key value coding-compliant for the key inputCropAmount. + case "CISunbeamsGenerator": + return true; + // FIXME: Remove if fixed. Doesn't appear to exist in El Capitan. Reported in radar #22099780 +// case "CIMaskedVariableBlur": +// cd .. return true; + default: + return false; + } + } + + [Test] + // this test checks that all native filters have a managed peer, i.e. against missing filters + public void CheckNativeFilters () + { + List filters = new List (); + int n = 0; + string qname = CIFilterType.AssemblyQualifiedName; + // that will give us only the list of filters supported by the executing version of iOS + foreach (var filter_name in CIFilter.FilterNamesInCategories (null)) { + if (Skip (filter_name)) + continue; + string type_name = qname.Replace ("CIFilter", filter_name); + if (Type.GetType (type_name, false, true) == null) { + filters.Add (filter_name); + // uncomment to generate bindings for any new native filter +// GenerateBinding (CIFilter.FromName (filter_name), Console.Out); + } + n++; + } + Assert.That (filters.Count, Is.EqualTo (0), "{0} native filters missing: {1}", filters.Count, String.Join (", ", filters)); + } + + [Test] + // this test checks that all managed filters have a native peer, i.e. against extra filters + public void CheckManagedFilters () + { + List filters = new List (CIFilter.FilterNamesInCategories (null)); + 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; + + NSObject obj = ctor.Invoke (null) as NSObject; + Assert.That (obj.Handle, Is.Not.EqualTo (IntPtr.Zero), t.Name + ".Handle"); +#if false + // check base type - we might have our own base type or different names, so it's debug only (not failure) + var super = new Class (obj.Class.SuperClass).Name; + var bt = t.BaseType.Name; + if ((super != bt) && (bt == "CIFilter")) // check if we should (like Apple) use a non-default base type for filters + Console.WriteLine ("[WARN] {0}.SuperClass == {1} (native) and {2} managed", t.Name, super, bt); +#endif + int result = filters.RemoveAll (s => StringComparer.OrdinalIgnoreCase.Compare (t.Name, s) == 0); + Assert.That (result, Is.GreaterThan (0), t.Name); + } + // in case it's a buggy filter we need to try to remove it from the list too + for (int i = filters.Count - 1; i >= 0; i--) { + if (Skip (filters [i])) + filters.RemoveAt (i); + } + Assert.That (filters.Count, Is.EqualTo (0), "Managed filters not found for {0}", String.Join (", ", filters)); + } + + static void GenerateBinding (NSObject filter, TextWriter writer) + { + NSObject value; + var attributes = (filter as CIFilter).Attributes; + + writer.WriteLine ("[CoreImageFilter]"); + + if (!attributes.TryGetValue ((NSString)"CIAttributeFilterAvailable_iOS", out value)) { + writer.WriteLine ("[NoiOS]"); + } else { + var v = value.ToString (); + // in the (quite common) case we get "5" for iOS 5.0 + if (v.IndexOf ('.') == -1) + v += ".0"; + var ios = Version.Parse (v); + // we only document availability for iOS 6+ + if (ios.Major > 5) + writer.WriteLine ("[iOS ({0},{1})]", ios.Major, ios.Minor); + } + + if (!attributes.TryGetValue ((NSString)"CIAttributeFilterAvailable_Mac", out value)) { + writer.WriteLine ("[NoMac]"); + } else { + try { + var mac = Version.Parse (value.ToString ()); + // we only document availability for 10.7+ + if (mac.Minor > 6) + writer.WriteLine ("[Mac ({0},{1})]", mac.Major, mac.Minor); + } + catch (FormatException) { + // 10.? is not a valid version - we'll assume it was added a long time ago (in a galaxy far away) + writer.WriteLine ("// incorrect version string for OSX: '{0}' Double-check documentation", value); + } + } + writer.WriteLine ("[BaseType (typeof (CIFilter))]"); + var fname = attributes [(NSString)"CIAttributeFilterName"].ToString (); + writer.WriteLine ("interface {0} {{", fname); + foreach (var k in attributes.Keys) { + var key = k.ToString (); + if (key.StartsWith ("CIAttribute", StringComparison.Ordinal)) + continue; + // CIFilter defines it for all filters + if (key == "inputImage") + continue; + + writer.WriteLine (); + var dict = attributes [k] as NSDictionary; + var type = dict [(NSString) "CIAttributeClass"]; + writer.WriteLine ("\t[CoreImageProperty (\"{0}\")]", key); + + // by default we drop the "input" prefix, but keep the "output" prefix to avoid confusion + if (key.StartsWith ("input", StringComparison.Ordinal)) + key = Char.ToUpperInvariant (key [5]) + key.Substring (6); + + var ptype = type.ToString (); + // Too many things ends up in NSNumber but we do a better job in our bindings + if (ptype == "NSNumber") { + ptype = "float"; + writer.WriteLine ("\t// TODO: this was an NSNumber transformed to float, but maybe an int or bool is more appropriate"); + } + writer.WriteLine ("\t{0} {1} {{ get; set; }}", ptype, key); + } + writer.WriteLine ("}"); + writer.WriteLine (); + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/introspection/ApiCtorInitTest.cs b/tests/introspection/ApiCtorInitTest.cs new file mode 100644 index 00000000000..8c9564abc7e --- /dev/null +++ b/tests/introspection/ApiCtorInitTest.cs @@ -0,0 +1,306 @@ +// +// Test the generated API `init` selectors are usable by the binding consumers +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012-2015 Xamarin Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +using System; +using System.Reflection; + +using NUnit.Framework; + +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +#elif MONOMAC +using MonoMac.Foundation; +using MonoMac.ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif + +namespace Introspection { + + public abstract class ApiCtorInitTest : ApiBaseTest { + + string instance_type_name; + + /// + /// Gets or sets a value indicating whether this test fixture will log untested types. + /// + /// true if log untested types; otherwise, false. + public bool LogUntestedTypes { get; set; } + + /// + /// Override this method if you want the test to skip some specific types. + /// By default types decorated with [Model] will be skipped. + /// + /// The Type to be tested + protected virtual bool Skip (Type type) + { + if (type.ContainsGenericParameters) + return true; + + // skip delegate (and other protocol references) + foreach (object ca in type.GetCustomAttributes (false)) { + if (ca is ProtocolAttribute) + return true; + if (ca is ModelAttribute) + return true; + } + switch (type.Name) { +#if !XAMCORE_2_0 + case "AVAssetResourceLoader": // We have DisableDefaultCtor in XAMCORE_2_0 but can't change in compat because of backwards compat + case "AVAssetResourceLoadingRequest": + case "AVAssetResourceLoadingContentInformationRequest": +#endif + // on iOS 8.2 (beta 1) we get: NSInvalidArgumentException Caller did not provide an activityType, and this process does not have a NSUserActivityTypes in its Info.plist. + // even if we specify an NSUserActivityTypes in the Info.plist - might be a bug or there's a new (undocumented) requirement + case "NSUserActivity": + return true; + } + return SkipDueToAttribute (type); + } + + /// + /// Checks that the Handle property of the specified NSObject instance is not null (not IntPtr.Zero). + /// + /// NSObject instance to validate + protected virtual void CheckHandle (NSObject obj) + { + if (obj.Handle == IntPtr.Zero) + ReportError ("{0} : Handle", instance_type_name); + } + + /// + /// Checks that ToString does not return null (not helpful for debugging) and that it does not crash. + /// + /// NSObject instance to validate + protected virtual void CheckToString (NSObject obj) + { + if (obj.ToString () == null) + ReportError ("{0} : ToString", instance_type_name); + } + + bool GetIsDirectBinding (NSObject obj) + { +#if XAMCORE_2_0 + int flags = (byte) typeof (NSObject).GetField ("flags", BindingFlags.Instance | BindingFlags.GetField | BindingFlags.NonPublic).GetValue (obj); + return (flags & 4) == 4; +#else + return (bool) typeof (NSObject).GetField ("IsDirectBinding", BindingFlags.Instance | BindingFlags.GetField | BindingFlags.NonPublic).GetValue (obj); +#endif + } + + /// + /// Checks that the IsDirectBinding property is identical to the IsWrapper property of the Register attribute. + /// + /// Object. + protected virtual void CheckIsDirectBinding (NSObject obj) + { + var attrib = obj.GetType ().GetCustomAttribute (false); + // only check types that we register - that way we avoid the 118 MonoTouch.CoreImagge.CI* "special" types + if (attrib == null) + return; + var is_wrapper = attrib != null && attrib.IsWrapper; + var is_direct_binding = GetIsDirectBinding (obj); + if (is_direct_binding != is_wrapper) + ReportError ("{0} : IsDirectBinding (expected {1}, got {2})", instance_type_name, is_wrapper, is_direct_binding); + } + + /// + /// Skip, or not, the specified pproperty from being verified. + /// + /// PropertyInfo candidate + protected virtual bool Skip (PropertyInfo pi) + { + // manually bound API can have the attributes only on the property (and not on the getter/setter) + return SkipDueToAttribute (pi); + } + + /// + /// Dispose the specified NSObject instance. In some cases objects cannot be disposed safely. + /// Override this method to keep them alive while the remaining tests execute. + /// + /// NSObject instance to dispose + /// Type of the object, to be used if special logic is required. + protected virtual void Dispose (NSObject obj, Type type) + { + obj.Dispose (); + } + + protected virtual void CheckNSObjectProtocol (NSObject obj) + { + // not documented to allow null, but commonly used this way. OTOH it's not clear what code answer this + // (it might be different implementations) but we can make sure that Apple allows null with this test + // ref: https://bugzilla.xamarin.com/show_bug.cgi?id=35924 + var kind_of_null = obj.IsKindOfClass (null); + if (kind_of_null) + ReportError ("{0} : IsKindOfClass(null) failed", instance_type_name); + var is_member_of_null = obj.IsMemberOfClass (null); + if (is_member_of_null) + ReportError ("{0} : IsMemberOfClass(null) failed", instance_type_name); + var respond_to_null = obj.RespondsToSelector (null); + if (respond_to_null) + ReportError ("{0} : RespondToSelector(null) failed", instance_type_name); + var conforms_to_null = obj.ConformsToProtocol (IntPtr.Zero); + if (conforms_to_null) + ReportError ("{0} : ConformsToProtocol(null) failed", instance_type_name); + } + + // if a .ctor is obsolete then it's because it was not usable (nor testable) + protected override bool SkipDueToAttribute (MemberInfo member) + { + if (member == null) + return false; + var ca = member.GetCustomAttribute (); + return ca != null || base.SkipDueToAttribute (member); + } + + [Test] + public void DefaultCtorAllowed () + { + Errors = 0; + 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", Errors, n); + } + + // .NET constructors are not virtual, so we need to re-expose the base class .ctor when a subclass is created. + // That's very important for designated initializer since we can end up with no correct/safe way to create + // subclasses of an existing type + [Test] + public void DesignatedInitializer () + { + Errors = 0; + int n = 0; + + foreach (Type t in Assembly.GetTypes ()) { + // we only care for NSObject subclasses that we expose publicly + if (!t.IsPublic || !NSObjectType.IsAssignableFrom (t)) + continue; + + int designated = 0; + foreach (var ctor in t.GetConstructors ()) { + if (ctor.GetCustomAttribute () == null) + continue; + designated++; + } + // that does not mean that inlining is not required, i.e. it might be useful, even needed + // but it's not a showstopper for subclassing so we'll start with those cases + if (designated > 1) + continue; + + var base_class = t.BaseType; + // NSObject ctor requirements are handled by the generator + if (base_class == NSObjectType) + continue; + foreach (var ctor in base_class.GetConstructors ()) { + // if the base ctor is a designated (not a convenience) initializer then we should re-expose it + if (ctor.GetCustomAttribute () == null) + continue; + + // check if this ctor (from base type) is exposed in the current (subclass) type + if (!Match (ctor, t)) + ReportError ("{0} should re-expose {1}::{2}", t, base_class.Name, ctor.ToString ().Replace ("Void ", String.Empty)); + n++; + } + } + Assert.AreEqual (0, Errors, "{0} potential errors found in {1} designated initializer validated", Errors, n); + } + + protected virtual bool Match (ConstructorInfo ctor, Type type) + { + switch (type.Name) { + case "MKTileOverlayRenderer": + // NSInvalidArgumentEception Expected a MKTileOverlay + // looks like Apple has not yet added a DI for this type, but it should be `initWithTileOverlay:` + if (ctor.ToString () == "Void .ctor(IMKOverlay)") + return true; + break; + case "MPSImageHistogram": + // Could not initialize an instance of the type 'MetalPerformanceShaders.MPSImageHistogram': the native 'initWithDevice:' method returned nil. + // make sense: there's a `initWithDevice:histogramInfo:` DI + if (ctor.ToString () == "Void .ctor(IMTLDevice)") + return true; + break; + case "NSDataDetector": + // -[NSDataDetector initWithPattern:options:error:]: Not valid for NSDataDetector + if (ctor.ToString () == "Void .ctor(NSString, NSRegularExpressionOptions, NSError&)") + return true; + break; +#if __TVOS__ + case "UISearchBar": + // - (nullable instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER __TVOS_PROHIBITED; + return true; +#endif + } + + var expected = ctor.ToString (); + // NonPublic to get `protected` which can be autogenerated for abstract types (subclassing a non-abstract type) + foreach (var candidate in type.GetConstructors (BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance)) { + if (candidate.ToString () == expected) + return true; + } + return false; + } + } +} diff --git a/tests/introspection/ApiFieldTest.cs b/tests/introspection/ApiFieldTest.cs new file mode 100644 index 00000000000..88b7cad97fd --- /dev/null +++ b/tests/introspection/ApiFieldTest.cs @@ -0,0 +1,187 @@ +// +// Test the generated API fields (e.g. against typos or unexisting values for the platform) +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012-2014 Xamarin Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +using System; +using System.IO; +using System.Collections.Generic; +using System.Reflection; + +using NUnit.Framework; + +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +#elif MONOMAC +using MonoMac.Foundation; +using MonoMac.ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif + +namespace Introspection { + + [Preserve (AllMembers = true)] + public abstract class ApiFieldTest : ApiBaseTest { +#if XAMCORE_2_0 + const string NSStringType = "Foundation.NSString"; +#elif MONOMAC + const string NSStringType = "MonoMac.Foundation.NSString"; +#else + const string NSStringType = "MonoTouch.Foundation.NSString"; +#endif + + /// + /// Override if you want to skip testing the specified type. + /// + /// Type to be tested + protected virtual bool Skip (Type type) + { + return false; + } + + /// + /// Override if you want to skip testing the specified property. + /// + /// Property to be tested + protected virtual bool Skip (PropertyInfo property) + { + return SkipDueToAttribute (property); + } + + /// + /// Override if you want to skip testing the specified constant. + /// + /// Constant name to ignore. + protected virtual bool Skip (string constantName) + { + return false; + } + + // check generated code, which are static properties, e.g. + // [Field ("kCGImagePropertyIPTCObjectTypeReference")] + // NSString IPTCObjectTypeReference { get; } + bool CheckAgainstNull (PropertyInfo p, out string name) + { + name = String.Empty; + var g = p.GetGetMethod (true); + if (!g.IsStatic) + return true; + + if (Skip (p)) + return true; + + try { + // if it return nulls then it could be a typo... + // or something not available in the executing version of iOS + bool result = g.Invoke (null, null) != null; + if (!result) + name = p.DeclaringType.FullName + "." + p.Name; + return result; + } + catch (Exception e) { + Console.WriteLine ("[FAIL] Exception on '{0}' : {1}", p, e); + name = p.DeclaringType.FullName + "." + p.Name; + return false; + } + } + + [Test] + public void NonNullNSStringFields () + { + var failed_fields = new List (); + + Errors = 0; + int c = 0, n = 0; + foreach (Type t in Assembly.GetTypes ()) { + if (Skip (t) || SkipDueToAttribute (t)) + continue; + + if (LogProgress) + Console.WriteLine ("{0}. {1}", c++, t.FullName); + + foreach (var p in t.GetProperties (BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)) { + // looking for properties with getters only + if (p.CanWrite || !p.CanRead) + continue; + + if (p.PropertyType.FullName != NSStringType) + continue; + + if (SkipDueToAttribute (p)) + continue; + + string name; + bool result = CheckAgainstNull (p, out name); + if (!result) { + ReportError (name); + failed_fields.Add (name); + } + n++; + } + } + Assert.AreEqual (0, Errors, "{0} errors found in {1} fields validated: {2}", Errors, n, string.Join (", ", failed_fields)); + } + + [Test] + public void FieldExists () + { + var failed_fields = new List (); + + Errors = 0; + int c = 0, n = 0; + foreach (Type t in Assembly.GetTypes ()) { + if (Skip (t) || SkipDueToAttribute (t)) + continue; + + if (LogProgress) + Console.WriteLine ("{0}. {1}", c++, t.FullName); + + foreach (var p in t.GetProperties (BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)) { + // looking for properties with getters only + if (p.CanWrite || !p.CanRead) + continue; + + if (SkipDueToAttribute (p)) + continue; + + var f = p.GetCustomAttribute (); + if (f == null) + continue; + + string name = f.SymbolName; + if (Skip (name)) + continue; + + string path = FindLibrary (f.LibraryName); + IntPtr lib = Dlfcn.dlopen (path, 0); + if (Dlfcn.GetIndirect (lib, name) == IntPtr.Zero) { + ReportError ("Could not find the field '{0}' in {1}", name, path); + failed_fields.Add (name); + } + Dlfcn.dlclose (lib); + n++; + } + } + Assert.AreEqual (0, Errors, "{0} errors found in {1} fields validated: {2}", Errors, n, string.Join (", ", failed_fields)); + } + } +} diff --git a/tests/introspection/ApiPInvokeTest.cs b/tests/introspection/ApiPInvokeTest.cs new file mode 100644 index 00000000000..6e587237bf1 --- /dev/null +++ b/tests/introspection/ApiPInvokeTest.cs @@ -0,0 +1,251 @@ +// +// ApiPInvokeTest.cs: enforce P/Invoke signatures +// +// Authors: +// Aaron Bockover +// Sebastien Pouliot +// +// Copyright 2013-2014 Xamarin, Inc. + +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Runtime.InteropServices; + +using NUnit.Framework; + +#if XAMCORE_2_0 +using ObjCRuntime; +using Foundation; +#elif MONOMAC +using MonoMac.ObjCRuntime; +using MonoMac.Foundation; +#else +using MonoTouch.ObjCRuntime; +using MonoTouch.Foundation; +#endif + +namespace Introspection +{ + [Preserve (AllMembers = true)] + public abstract class ApiPInvokeTest : ApiBaseTest { + IEnumerable pinvokeQuery; + + public ApiPInvokeTest () + { + ContinueOnFailure = true; + LogProgress = false; + + pinvokeQuery = from type in Assembly.GetTypes () + where !Skip (type) + from mi in type.GetMethods ( + BindingFlags.NonPublic | + BindingFlags.Public | + BindingFlags.Static) + let attr = mi.GetCustomAttribute () + where attr != null && !Skip (mi) + select mi; + } + + protected virtual bool Skip (Type type) + { + return SkipDueToAttribute (type); + } + + protected virtual bool Skip (MethodInfo methodInfo) + { + return SkipDueToAttribute (methodInfo); + } + + [Test] + public void Signatures () + { + int totalPInvokes = 0; + int totalErrors = 0; + + foreach (MethodInfo mi in pinvokeQuery) { + totalPInvokes++; + if (!CheckSignature (mi)) { + totalErrors++; + + if (!ContinueOnFailure) + break; + } + } + + AssertIfErrors ( + "{0} errors found in {1} P/Invoke signatures validated", + totalErrors, totalPInvokes); + } + + protected virtual bool CheckSignature (MethodInfo mi) + { + var success = true; + + if (!CheckReturnParameter (mi, mi.ReturnParameter)) + success = false; + + foreach (var pi in mi.GetParameters ()) { + if (!CheckParameter (mi, pi)) + success = false; + } + + return success; + } + + protected virtual bool CheckReturnParameter (MethodInfo mi, ParameterInfo pi) + { + return CheckForEnumParameter (mi, pi); + } + + protected virtual bool CheckParameter (MethodInfo mi, ParameterInfo pi) + { + return CheckForEnumParameter (mi, pi); + } + + protected virtual bool CheckForEnumParameter (MethodInfo mi, ParameterInfo pi) + { + if (pi.ParameterType.IsEnum && pi.ParameterType.GetCustomAttribute () != null) { + AddErrorLine ("{0}.{1} has a [Native] enum parameter in its signature: {2} {3}", + mi.DeclaringType.FullName, mi.Name, pi.ParameterType, pi.Name); + return false; + } + + return true; + } + + protected virtual bool Skip (string symbolName) + { + return false; + } + + protected virtual bool SkipLibrary (string libraryName) + { + return false; + } + + [Test] + public void SymbolExists () + { + var failed_api = new List (); + Errors = 0; + int c = 0, n = 0; + foreach (MethodInfo mi in pinvokeQuery) { + + if (LogProgress) + Console.WriteLine ("{0}. {1}", c++, mi); + + var dllimport = mi.GetCustomAttribute (); + + string libname = dllimport.Value; + if (libname == "__Internal" || SkipLibrary (libname)) + continue; + + string path = FindLibrary (dllimport.Value, requiresFullPath: true); + + string name = dllimport.EntryPoint ?? mi.Name; + if (Skip (name)) + continue; + + IntPtr lib = Dlfcn.dlopen (path, 0); + if (Dlfcn.GetIndirect (lib, name) == IntPtr.Zero) { + ReportError ("Could not find the field '{0}' in {1}", name, path); + failed_api.Add (name); + } + Dlfcn.dlclose (lib); + n++; + } + Assert.AreEqual (0, Errors, "{0} errors found in {1} functions validated: {2}", Errors, n, string.Join (", ", failed_api)); + } + + // we just want to confirm the symbol exists so `dlsym` can be disabled + protected void Check (Assembly a) + { + Errors = 0; + 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 (); + + 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", Errors, n); + } + + protected abstract bool SkipAssembly (Assembly a); + + // Note: this looks very similar to the "SymbolExists" test above (and it is) + // except that we never skip based on availability attributes or __Internal... + // since this is a test to ensure thigns will work at native link time (e.g. + // for devices) when dlsym is disabled + + [Test] + public void Product () + { + var a = typeof (NSObject).Assembly; + if (!SkipAssembly (a)) + Check (a); + } + + // since we already have non-linked version of the most common assemblies available here + // we can use them to check for missing symbols (from DllImport) + // it's not complete (there's many more SDK assemblies) but we cannot add all of them into a single project anyway + + [Test] + public void Corlib () + { + var a = typeof (int).Assembly; + if (!SkipAssembly (a)) + Check (a); + } + + [Test] + public void System () + { + var a = typeof (System.Net.WebClient).Assembly; + if (!SkipAssembly (a)) + Check (a); + } + + [Test] + public void SystemCore () + { + var a = typeof (Enumerable).Assembly; + if (!SkipAssembly (a)) + Check (a); + } + } +} diff --git a/tests/introspection/ApiProtocolTest.cs b/tests/introspection/ApiProtocolTest.cs new file mode 100644 index 00000000000..487a1114197 --- /dev/null +++ b/tests/introspection/ApiProtocolTest.cs @@ -0,0 +1,297 @@ +// +// Test the generated API for common protocol support +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013, 2015 Xamarin Inc. +// + +using System; +using System.Reflection; +using System.Runtime.InteropServices; +using NUnit.Framework; + +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +#elif MONOMAC +using MonoMac.Foundation; +using MonoMac.ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif + +namespace Introspection { + + public abstract class ApiProtocolTest : ApiBaseTest { + + static IntPtr conform_to = Selector.GetHandle ("conformsToProtocol:"); + + public ApiProtocolTest () + { + ContinueOnFailure = true; + } + + static bool ConformTo (IntPtr klass, IntPtr protocol) + { + return bool_objc_msgSend_IntPtr (klass, conform_to, protocol); + } + + protected virtual bool Skip (Type type) + { + switch (type.Name) { + // *** NSForwarding: warning: object 0x5cbd078 of class 'JSExport' does not implement methodSignatureForSelector: -- trouble ahead + // *** NSForwarding: warning: object 0x5cbd078 of class 'JSExport' does not implement doesNotRecognizeSelector: -- abort + case "JSExport": + return true; + default: +#if !XAMCORE_2_0 + // in Classic our internal delegates _inherits_ the type with the [Protocol] attribute + // in Unified our internal delegates _implements_ the interface that has the [Protocol] attribute + if (type.GetCustomAttribute (true) != null) + return true; +#endif + return SkipDueToAttribute (type); + } + } + + IntPtr GetClass (Type type) + { + return Class.GetHandle (type); + } + + protected virtual bool Skip (Type type, string protocolName) + { + switch (protocolName) { + case "NSCopying": + switch (type.Name) { + // undocumented conformance (up to 7.0) and conformity varies between iOS versions + case "CAEmitterCell": + case "GKAchievement": + case "GKScore": + // new in iOS8 and 10.0 + case "NSExtensionContext": + return true; // skip + } + break; + case "NSCoding": + switch (type.Name) { + // only documented to support NSCopying - not NSCoding (fails on iOS 7.1 but not 8.0) + case "NSUrlSessionTask": + case "NSUrlSessionDataTask": + case "NSUrlSessionUploadTask": + case "NSUrlSessionDownloadTask": + // + case "NSUrlSessionConfiguration": + case "NSMergeConflict": + // new in iOS8 and 10.0 + case "NSExtensionContext": + case "NSItemProvider": + // undocumented + return true; + } + break; + case "NSSecureCoding": + switch (type.Name) { + case "NSMergeConflict": // undocumented + // only documented to support NSCopying (and OSX side only does that) + case "NSUrlSessionTask": + case "NSUrlSessionDataTask": + case "NSUrlSessionUploadTask": + case "NSUrlSessionDownloadTask": + case "NSUrlSessionConfiguration": + // new in iOS8 and 10.0 + case "NSExtensionContext": + case "NSItemProvider": + case "NSParagraphStyle": //17770106 + case "NSMutableParagraphStyle": //17770106 + return true; // skip + // iOS9 / 10.11 + case "NSPersonNameComponentsFormatter": + return true; // skip + } + break; + } + return false; + } + + void CheckProtocol (string protocolName, Action action) + { + IntPtr protocol = Runtime.GetProtocol (protocolName); + Assert.AreNotEqual (protocol, IntPtr.Zero, protocolName); + + int n = 0; + foreach (Type t in Assembly.GetTypes ()) { + if (!NSObjectType.IsAssignableFrom (t)) + continue; + + if (Skip (t) || Skip (t, protocolName)) + continue; + + if (LogProgress) + Console.WriteLine ("{0}. {1} conforms to {2}", ++n, t.FullName, protocolName); + + IntPtr klass = GetClass (t); + action (t, klass, ConformTo (klass, protocol)); + } + } + + [Test] + public void Coding () + { + Errors = 0; + CheckProtocol ("NSCoding", delegate (Type type, IntPtr klass, bool result) { + if (result) { + // `type` conforms to (native) NSCoding so... + if (result) { + // the type should implements INSCoding + if (!typeof (INSCoding).IsAssignableFrom (type)) { + ReportError ("{0} conforms to NSCoding but does not implement INSCoding", type.Name); + } + // FIXME: and implement the .ctor(NSCoder) + } + } + }); + Assert.AreEqual (Errors, 0, "{0} types conforms to NSCoding but does not implement INSCoding", Errors); + } + + // [Test] -> iOS 6.0+ and Mountain Lion (10.8) + + public virtual void SecureCoding () + { + Errors = 0; + CheckProtocol ("NSSecureCoding", delegate (Type type, IntPtr klass, bool result) { + if (result) { + // the type should implements INSSecureCoding + if (!typeof (INSSecureCoding).IsAssignableFrom (type)) { + ReportError ("{0} conforms to NSSecureCoding but does not implement INSSecureCoding", type.Name); + } + } + }); + Assert.AreEqual (Errors, 0, "{0} types conforms to NSSecureCoding but does not implement INSSecureCoding", Errors); + } + + bool SupportsSecureCoding (Type type) + { + Class cls = new Class (type); + if (!bool_objc_msgSend_IntPtr (cls.Handle, Selector.GetHandle ("respondsToSelector:"), Selector.GetHandle ("supportsSecureCoding"))) + return false; + + return NSSecureCoding.SupportsSecureCoding (type); + } + + + // [Test] -> iOS 6.0+ and Mountain Lion (10.8) + + public virtual void SupportsSecureCoding () + { + Errors = 0; + CheckProtocol ("NSSecureCoding", delegate (Type type, IntPtr klass, bool result) { + bool supports = SupportsSecureCoding (type); + if (result) { + // check that +supportsSecureCoding returns YES + if (!supports) { + ReportError ("{0} conforms to NSSecureCoding but SupportsSecureCoding returned false", type.Name); + } + } else if (type.IsPublic && supports) { + // there are internal types, e.g. DataWrapper : NSData, that subclass NSSecureCoding-types without + // [re-]declaring their allegiance - but we can live with those small betrayals + Assert.IsFalse (NSSecureCoding.SupportsSecureCoding (type), "{0} !SupportsSecureCoding", type.Name); + ReportError ("SupportsSecureCoding returns true but {0} does not conforms to NSSecureCoding", type.Name); + } + }); + Assert.AreEqual (Errors, 0, "{0} types conforms to NSCoding but does not implement INSSecureCoding", Errors); + } + + [Test] + public void Copying () + { + Errors = 0; + CheckProtocol ("NSCopying", delegate (Type type, IntPtr klass, bool result) { + // `type` conforms to (native) NSCopying so... + if (result) { + // the type should implements INSCopying + if (!typeof (INSCopying).IsAssignableFrom (type)) { + ReportError ("{0} conforms to NSCopying but does not implement INSCopying", type.Name); + } + } + }); + Assert.AreEqual (Errors, 0, "{0} types conforms to NSCopying but does not implement INSCopying", Errors); + } + + [Test] + public void MutableCopying () + { + Errors = 0; + CheckProtocol ("NSMutableCopying", delegate (Type type, IntPtr klass, bool result) { + // `type` conforms to (native) NSMutableCopying so... + if (result) { + // the type should implements INSMutableCopying + if (!typeof (INSMutableCopying).IsAssignableFrom (type)) { + ReportError ("{0} conforms to NSMutableCopying but does not implement INSMutableCopying", type.Name); + } + } + }); + Assert.AreEqual (Errors, 0, "{0} types conforms to NSMutableCopying but does not implement INSMutableCopying", Errors); + } + + [Test] + public void GeneralCase () + { + Errors = 0; + foreach (Type t in Assembly.GetTypes ()) { + if (!NSObjectType.IsAssignableFrom (t)) + continue; + + if (Skip (t)) + continue; + + foreach (var intf in t.GetInterfaces ()) { + if (SkipDueToAttribute (intf)) + continue; + + string protocolName = intf.Name.Substring (1); + switch (protocolName) { + case "NSCoding": + case "NSSecureCoding": + case "NSCopying": + case "NSMutableCopying": + // we have special test cases for them + continue; + default: +#if !XAMCORE_2_0 + // in Classic our internal delegates _inherits_ the type with the [Protocol] attribute + // in Unified our internal delegates _implements_ the interface that has the [Protocol] attribute + var pt = Type.GetType (intf.Namespace + "." + protocolName + ", " + intf.Assembly.FullName); + if (SkipDueToAttribute (pt)) + continue; +#endif + if (Skip (t, protocolName)) + continue; + break; + } + + var a = intf.GetCustomAttribute (true); + if (a == null || a.IsInformal) + continue; + + IntPtr protocol = Runtime.GetProtocol (protocolName); + if (protocol == IntPtr.Zero) + continue; // not a protocol + + if (LogProgress) + Console.WriteLine ("{0} conforms to {1}", t.FullName, protocolName); + + var klass = new Class (t); + if (klass.Handle == IntPtr.Zero) { + AddErrorLine ("Could not load {0}", t.FullName); + } else if (t.IsPublic && !ConformTo (klass.Handle, protocol)) { + // note: some internal types, e.g. like UIAppearance subclasses, return false (and there's not much value in changing this) + ReportError ("Type {0} (native: {1}) does not conform {2}", t.FullName, klass.Name, protocolName); + } + } + } + AssertIfErrors ("{0} types do not really conform to the protocol interfaces", Errors); + } + } +} diff --git a/tests/introspection/ApiSelectorTest.cs b/tests/introspection/ApiSelectorTest.cs new file mode 100644 index 00000000000..5e85eb0cd93 --- /dev/null +++ b/tests/introspection/ApiSelectorTest.cs @@ -0,0 +1,406 @@ +// +// Test the generated API selectors against typos or non-existing cases +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012-2013 Xamarin Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +using System; +using System.Reflection; +using NUnit.Framework; + +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +#elif MONOMAC +using MonoMac.Foundation; +using MonoMac.ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif + +namespace Introspection { + + public abstract class ApiSelectorTest : ApiBaseTest { + + // not everything should be even tried + + protected virtual bool Skip (Type type) + { + if (type.ContainsGenericParameters) + return true; + + // skip delegate (and other protocol references) + foreach (object ca in type.GetCustomAttributes (false)) { + if (ca is ProtocolAttribute) + return true; + if (ca is ModelAttribute) + return true; + } + return SkipDueToAttribute (type); + } + + protected virtual bool Skip (Type type, string selectorName) + { +#if !XAMCORE_2_0 + // old binding mistake + if (selectorName == "subscribedCentrals") + return true; +#else + // The MapKit types/selectors are optional protocol members pulled in from MKAnnotation/MKOverlay. + // These concrete (wrapper) subclasses do not implement all of those optional members, but we + // still need to provide a binding for them, so that user subclasses can implement those members. + switch (type.Name) { + case "MKCircle": + case "MKPolygon": + case "MKPolyline": + switch (selectorName) { + case "canReplaceMapContent": + return true; + } + break; + case "MKShape": + switch (selectorName) { + case "setCoordinate:": + return true; + } + break; + case "MKPlacemark": + switch (selectorName) { + case "setCoordinate:": + case "subtitle": + return true; + } + break; + case "MKTileOverlay": + switch (selectorName) { + case "intersectsMapRect:": + return true; + } + break; + // AVAudioChannelLayout and AVAudioFormat started conforming to NSSecureCoding in OSX 10.11 and iOS 9 + case "AVAudioChannelLayout": + case "AVAudioFormat": + switch (selectorName) { + case "encodeWithCoder:": + return true; + } + break; + // SKTransition started conforming to NSCopying in OSX 10.11 and iOS 9 + case "SKTransition": + switch (selectorName) { + case "copyWithZone:": + return true; + } + break; + } +#endif + // This ctors needs to be manually bound + switch (type.Name) { + case "GKPath": + switch (selectorName) { + case "initWithPoints:count:radius:cyclical:": + return true; + } + break; + case "GKPolygonObstacle": + switch (selectorName) { + case "initWithPoints:count:": + return true; + } + break; + case "NSImage": + switch (selectorName) { + case "initByReferencingFile:": + return true; + } + break; + case "SKVideoNode": + switch (selectorName) { + case "initWithFileNamed:": + case "initWithURL:": + case "initWithVideoFileNamed:": + case "initWithVideoURL:": + case "videoNodeWithFileNamed:": + case "videoNodeWithURL:": + return true; + } + break; + } + + // old binding mistake + return (selectorName == "initWithCoder:"); + } + + protected virtual bool CheckResponse (bool value, Type actualType, MethodBase method, ref string name) + { + if (value) + return true; + + var mname = method.Name; + // properties getter and setter will be methods in the _Extensions type + if (method.IsSpecialName) + mname = mname.Replace ("get_", "Get").Replace ("set_", "Set"); + + // it's possible that the selector was inlined for an OPTIONAL protocol member + // we do not want those reported (too many false positives) and we have other tests to find such mistakes + foreach (var intf in actualType.GetInterfaces ()) { + if (intf.GetCustomAttributes () == null) + continue; + var ext = Type.GetType (intf.Namespace + "." + intf.Name.Remove (0, 1) + "_Extensions, " + intf.Assembly.FullName); + if (ext == null) + continue; + foreach (var m in ext.GetMethods ()) { + if (mname != m.Name) + continue; + var parameters = method.GetParameters (); + var ext_params = m.GetParameters (); + // first parameters is `this XXX This` + if (parameters.Length == ext_params.Length - 1) { + bool match = true; + for (int i = 1; i < ext_params.Length; i++) { + match |= (parameters [i - 1].ParameterType == ext_params [i].ParameterType); + } + if (match) + return true; + } + } + } + + name = actualType.FullName + " : " + name; + return false; + } + + static IntPtr responds_handle = Selector.GetHandle ("instancesRespondToSelector:"); + + [Test] + public void Protocols () + { + Errors = 0; + int n = 0; + + foreach (Type t in Assembly.GetTypes ()) { + if (t.IsNested || !NSObjectType.IsAssignableFrom (t)) + continue; + + foreach (object ca in t.GetCustomAttributes (false)) { + if (ca is ProtocolAttribute) { + foreach (var c in t.GetConstructors (BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance)) { + ProcessProtocolMember (t, c, ref n); + } + foreach (var m in t.GetMethods (BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance)) { + ProcessProtocolMember (t, m, ref n); + } + } + } + } + Assert.AreEqual (0, Errors, "{0} errors found in {1} protocol selectors validated", Errors, n); + } + + void ProcessProtocolMember (Type t, MethodBase m, ref int n) + { + if (SkipDueToAttribute (m)) + return; + + foreach (object ca in m.GetCustomAttributes (true)) { + ExportAttribute export = (ca as ExportAttribute); + if (export == null) + continue; + + string name = export.Selector; + if (Skip (t, name)) + continue; + + CheckInit (t, m, name); + n++; + } + } + + protected virtual IntPtr GetClassForType (Type type) + { + var fi = type.GetField ("class_ptr", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static); + if (fi == null) + return IntPtr.Zero; // e.g. *Delegate + return (IntPtr) fi.GetValue (null); + } + + [Test] + public void InstanceMethods () + { + Errors = 0; + 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", Errors, n); + } + + void Process (IntPtr class_ptr, Type t, MethodBase m, ref int n) + { + if (m.DeclaringType != t || SkipDueToAttribute (m)) + return; + + foreach (object ca in m.GetCustomAttributes (true)) { + ExportAttribute export = (ca as ExportAttribute); + if (export == null) + continue; + + string name = export.Selector; + if (Skip (t, name)) + continue; + + CheckInit (t, m, name); + + bool result = bool_objc_msgSend_IntPtr (class_ptr, responds_handle, Selector.GetHandle (name)); + bool response = CheckResponse (result, t, m, ref name); + if (!response) + ReportError ("Selector not found for {0}", name); + n++; + } + } + + void CheckInit (Type t, MethodBase m, string name) + { + if (SkipInit (name, m)) + return; + + bool init = IsInitLike (name); + if (m is ConstructorInfo) { + if (!init) + ReportError ("Selector {0} used on a constructor (not a method) on {1}", name, t.FullName); + } else { + if (init) + ReportError ("Selector {0} used on a method (not a constructor) on {1}", name, t.FullName); + } + } + + bool IsInitLike (string selector) + { + if (!selector.StartsWith ("init", StringComparison.OrdinalIgnoreCase)) + return false; + return selector.Length < 5 || Char.IsUpper (selector [4]); + } + + protected virtual bool SkipInit (string selector, MethodBase m) + { + switch (selector) { + // NSAttributedString + case "initWithHTML:documentAttributes:": + case "initWithRTF:documentAttributes:": + case "initWithRTFD:documentAttributes:": + case "initWithURL:options:documentAttributes:error:": + case "initWithFileURL:options:documentAttributes:error:": + // AVAudioRecorder + case "initWithURL:settings:error:": + // NSUrlProtectionSpace + case "initWithHost:port:protocol:realm:authenticationMethod:": + case "initWithProxyHost:port:type:realm:authenticationMethod:": + // NSUserDefaults + case "initWithSuiteName:": + case "initWithUser:": + // GKScore + case "initWithCategory:": + case "initWithLeaderboardIdentifier:": + // MCSession + case "initWithPeer:securityIdentity:encryptionPreference:": + // UISegmentedControl + case "initWithItems:": + var mi = m as MethodInfo; + return mi != null && !mi.IsPublic && mi.ReturnType.Name == "IntPtr"; + default: + return false; + } + } + + protected virtual void Dispose (NSObject obj, Type type) + { + obj.Dispose (); + } + + // funny, this is how I envisioned the instance version... before hitting run :| + protected virtual bool CheckStaticResponse (bool value, Type actualType, Type declaredType, ref string name) + { + if (value) + return true; + + name = actualType.FullName + " : " + name; + return false; + } + + [Test] + public void StaticMethods () + { + Errors = 0; + 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", Errors, n); + } + } +} diff --git a/tests/introspection/ApiSignatureTest.cs b/tests/introspection/ApiSignatureTest.cs new file mode 100644 index 00000000000..2528023438d --- /dev/null +++ b/tests/introspection/ApiSignatureTest.cs @@ -0,0 +1,760 @@ +// +// Test the generated API selectors against typos or non-existing cases +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012-2013 Xamarin Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Reflection; +using System.Text; +using NUnit.Framework; +using System.Linq; + +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +#elif MONOMAC +using MonoMac.Foundation; +using MonoMac.ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif + +namespace Introspection { + + public abstract class ApiSignatureTest : ApiBaseTest { + + [DllImport ("/usr/lib/libobjc.dylib")] + // note: the returned string is not ours to free + static extern IntPtr objc_getClass (string name); + + [DllImport ("/usr/lib/libobjc.dylib")] + // note: the returned string is not ours to free + static extern IntPtr method_getTypeEncoding (IntPtr method); + + [DllImport ("/usr/lib/libobjc.dylib")] + static extern IntPtr class_getClassMethod (IntPtr klass, IntPtr selector); + + [DllImport ("/usr/lib/libobjc.dylib")] + static extern IntPtr class_getInstanceMethod (IntPtr klass, IntPtr selector); + + protected string[] Split (string encoded, out int size) + { + List elements = new List (); + int pos = 0; + string s = Next (encoded, ref pos); + int end = pos; + while (Char.IsDigit (encoded [end])) + end++; + + size = Int32.Parse (encoded.Substring (pos, end - pos)); + + if (encoded [end] != '@' || encoded [end + 1] != '0' || encoded [end + 2] != ':') { + if (!ContinueOnFailure) + Assert.Fail ("Unexpected format, missing '@0:', inside '{0}'", encoded); + return null; + } + + pos = end + 3; + + while (s != null) { + elements.Add (s); + s = Next (encoded, ref pos); + } + return elements.ToArray (); + } + + static string Next (string encoded, ref int pos) + { + // skip digits + while (pos < encoded.Length && Char.IsDigit (encoded [pos])) + pos++; + if (pos >= encoded.Length) + return null; + + StringBuilder sb = new StringBuilder (); + int acc = 0; + char c = encoded [pos]; + while (!Char.IsDigit (c) || acc > 0) { + sb.Append (c); + if (c == '{' || c == '(') + acc++; + else if (c == '}' || c == ')') + acc--; + if (++pos >= encoded.Length) + break; + c = encoded [pos]; + } + return sb.ToString (); + } + + int TypeSize (Type t) + { + return TypeSize (t, ref t); + } + + int TypeSize (Type t, ref Type real) + { + real = t; + if (!t.IsValueType) + return IntPtr.Size; // platform + if (t.IsEnum) { + foreach (var ca in t.CustomAttributes) { + if (ca.AttributeType.Name == "NativeAttribute") + return IntPtr.Size; + } + real = Enum.GetUnderlyingType (t); + } + return Marshal.SizeOf (real); + } + + protected virtual int Size (Type t, bool simd = false) + { + switch (t.Name) { + // rdar 21375616 - Breaking change with EventKit[UI] enum base type + // EventKit.EK* enums are anonymous enums in 10.10 and iOS 8, but an NSInteger in 10.11 and iOS 9. + case "EKCalendarType": + case "EKParticipantType": + case "EKParticipantRole": + case "EKParticipantStatus": + case "EKEventStatus": + case "EKSourceType": + case "EKSpan": + case "EKRecurrenceFrequency": + case "EKEventAvailability": + if (!IsOSX11OrIOS9) + return 4; + break; + case "MDLAxisAlignedBoundingBox": + return 32; // struct (Vector3, Vector3) + } + if (simd) { + switch (t.Name) { + case "Vector3i": // sizeof (vector_uint3) + case "Vector3": // sizeof (vector_float3) + return 16; + case "MDLAxisAlignedBoundingBox": + return 32; // struct (Vector3, Vector3) + } + } + int size = TypeSize (t, ref t); + return t.IsPrimitive && size < 4 ? 4 : size; + } + + protected virtual bool Skip (Type type) + { + if (type.ContainsGenericParameters) + return true; + + return false; + } + + protected virtual bool Skip (Type type, MethodBase method, string selector) + { + return SkipDueToAttribute (method); + } + + public int CurrentParameter { get; private set; } + + public MethodBase CurrentMethod { get; private set; } + + public string CurrentSelector { get; private set; } + + public Type CurrentType { get; private set; } + + const BindingFlags Flags = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance; + + [Test] + public void Signatures () + { + int n = 0; + Errors = 0; + + 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", Errors, n); + } + + void CheckMemberSignature (MethodBase m, Type t, IntPtr class_ptr, ref int n) + { + var methodinfo = m as MethodInfo; + var constructorinfo = m as ConstructorInfo; + + if (methodinfo == null && constructorinfo == null) + return; + + if (m.DeclaringType != t) + return; + + CurrentMethod = m; + + foreach (object ca in m.GetCustomAttributes (true)) { + var exportAttribute = ca as ExportAttribute; + if (exportAttribute == null) + continue; + string name = exportAttribute.Selector; + + if (Skip (t, m, name)) + continue; + + CurrentSelector = name; + + // in some cases, e.g. *Delegate, we cannot use introspection but we can still do some checks + if (class_ptr == IntPtr.Zero) { + BasicChecks (m, t, ref n); + } else { + IntrospectionTest (m, methodinfo, t, class_ptr, ref n); + } + } + } + + void BasicChecks (MethodBase m, Type t, ref int n) + { + int native = 0; + int pos = CurrentSelector.IndexOf (':'); + while (pos != -1) { + native++; + pos = CurrentSelector.IndexOf (':', pos + 1); + } + var mp = m.GetParameters (); + int managed = mp.Length; + if (t.IsSealed && t.IsAbstract) { + // static types, e.g. [Category], adds a first 'This' argument for extension methods + // but we also expose static properties this way, e.g. NSUrlUtilities_NSCharacterSet + if ((managed >= 1) && (mp [0].Name == "This")) + managed--; + } + if (LogProgress) + Console.WriteLine ("{0} {1} '{2}' selector {3} : {4} == {5}", ++n, t.Name, m, CurrentSelector, native, managed); + if (native != managed) { + AddErrorLine ("Parameter count mismatch for {0} in {1}:{2} : Native {3} vs Managed {4}", + CurrentSelector, t, m.Name, native, managed); + } + } + + void IntrospectionTest (MethodBase m, MethodInfo methodinfo, Type t, IntPtr class_ptr, ref int n) + { + IntPtr sel = Selector.GetHandle (CurrentSelector); + IntPtr method; + if (methodinfo != null) + method = m.IsStatic ? class_getClassMethod (class_ptr, sel) : class_getInstanceMethod (class_ptr, sel); + else + method = class_getInstanceMethod (class_ptr, sel); + IntPtr tenc = method_getTypeEncoding (method); + string encoded = Marshal.PtrToStringAuto (tenc); + + if (LogProgress) + Console.WriteLine ("{0} {1} '{2} {3}' selector: {4} == {5}", ++n, t.Name, methodinfo != null ? methodinfo.IsStatic ? "static" : "instance" : "ctor", m, CurrentSelector, encoded); + + // NSObject has quite a bit of stuff that's not usable (except by some class that inherits from it) + if (String.IsNullOrEmpty (encoded)) + return; + + int encoded_size = -1; + string [] elements = null; + try { + elements = Split (encoded, out encoded_size); + } + catch { + } + if (elements == null) { + if (LogProgress) + Console.WriteLine ("[WARNING] Could not parse encoded signature for {0} : {1}", CurrentSelector, encoded); + return; + } + + bool result; + CurrentParameter = 0; + + if (methodinfo != null) { + // check return value + + result = Check (elements [CurrentParameter], methodinfo.ReturnType); + if (!result) + AddErrorLine ("Return Value of selector: {0} on type {1}, Type: {2}, Encoded as: {3}", CurrentSelector, t, methodinfo.ReturnType, elements [CurrentParameter]); + } + + int size = 2 * IntPtr.Size; // self + selector (@0:) + + var parameters = m.GetParameters (); + bool simd = (parameters.Length >= elements.Length); + foreach (var p in parameters) { + CurrentParameter++; + var pt = p.ParameterType; + if (CurrentParameter >= elements.Length) { + // SIMD structures are not (ios8 beta2) encoded in the signature, we ignore them + result = IgnoreSimd (CurrentSelector, t, pt); + if (!result) + AddErrorLine ("Selector: {0} on type {1}, Type: {2}, nothing encoded", CurrentSelector, t, pt); + } else { + // skip SIMD/vector parameters (as they are not encoded) + result = IgnoreSimd (CurrentSelector, t, pt); + if (result) + CurrentParameter--; + else + result = Check (elements [CurrentParameter], pt); + if (!result) + AddErrorLine ("Signature failure in {1} {0} Parameter '{4}' (#{5}) is encoded as '{3}' and bound as '{2}'", + CurrentSelector, t, pt, elements [CurrentParameter], p.Name, CurrentParameter); + } + + size += Size (pt, simd); + } + + // also ensure the encoded size match what MT (or XM) provides + // catch API errors (and should catch most 64bits issues as well) + if (size != encoded_size) + AddErrorLine ("Size {0} != {1} for {2} on {3}: {4}", encoded_size, size, CurrentSelector, t, encoded); + } + + static bool IgnoreSimd (string name, Type t, Type pt) + { + switch (pt.Name) { + case "Vector2": + case "Vector2i": + case "Vector3": + case "Vector3i": + case "Vector4": + case "Vector4i": + case "MDLAxisAlignedBoundingBox": // struct { Vector3, Vector3 } + return true; + default: + return false; + } + } + + protected virtual bool IsValidStruct (Type type, string structName) + { + switch (structName) { + // MKPolygon 'static MonoTouch.MapKit.MKPolygon _FromPoints(IntPtr, Int32)' selector: polygonWithPoints:count: == @16@0:4^{?=dd}8I12 + // NSValue 'static MonoTouch.Foundation.NSValue FromCMTime(CMTime)' selector: valueWithCMTime: == @32@0:4{?=qiIq}8 + case "?": + return type.IsValueType; // || (type.FullName == "System.IntPtr"); +#if XAMCORE_2_0 + case "CGRect": + return type.FullName == "CoreGraphics.CGRect"; + case "CGSize": + return type.FullName == "CoreGraphics.CGSize"; + case "CGPoint": + return type.FullName == "CoreGraphics.CGPoint"; +#else + case "CGRect": + return type.FullName == "System.Drawing.RectangleF"; + case "CGSize": + return type.FullName == "System.Drawing.SizeF"; + case "CGPoint": + return type.FullName == "System.Drawing.PointF"; +#endif + case "opaqueCMFormatDescription": + switch (type.Name) { + case "CMFormatDescription": + case "CMVideoFormatDescription": + case "CMAudioFormatDescription": + return true; + } + break; + case "opaqueCMSampleBuffer": + structName = "CMSampleBuffer"; + break; + case "_NSRange": + structName = "NSRange"; + break; + // textureWithContentsOfFile:options:queue:completionHandler: == v24@0:4@8@12^{dispatch_queue_s=}16@?20 + case "dispatch_queue_s": + structName = "DispatchQueue"; + break; + case "OpaqueCMClock": + structName = "CMClock"; + break; + case "OpaqueCMTimebase": + structName = "CMTimebase"; + break; + case "__CFRunLoop": + structName = "CFRunLoop"; + break; + case "_GLKVector4": + structName = "Vector4"; + break; + case "_GLKVector3": + structName = "Vector3"; + break; + case "_GLKVector2": + structName = "Vector2"; + break; + case "_GLKMatrix2": + structName = "Matrix2"; + break; + case "_GLKMatrix3": + structName = "Matrix3"; + break; + case "_GLKMatrix4": + structName = "Matrix4"; + break; + case "__CVPixelBufferPool": + structName = "CVPixelBufferPool"; + break; + case "opaqueMTAudioProcessingTap": + structName = "MTAudioProcessingTap"; + break; + case "OpaqueMIDIEndpoint": + structName = "Int32"; + break; + case "__CFDictionary": + structName = "NSDictionary"; + break; + case "__CFUUID": + // CBAttribute.UUID is defined as a CBUUID but ObjC runtime tell us it's __CFUUID + // which makes it sound like a (undocumented) toll free bridged type + structName = "CBUUID"; + break; + case "__CFString": + if (type.FullName == "System.String") + return true; + break; +#if !MONOMAC + // definition is different on OSX + case "SCNVector4": + switch (type.Name) { + case "SCNVector4": + // typedef SCNVector4 SCNQuaternion; (SceneKitTypes.h) + case "SCNQuaternion": + return true; + } + break; +#endif + case "_CGLContextObject": + structName = "CGLContext"; + break; + case "_CGLPixelFormatObject": + structName = "CGLPixelFormat"; + break; + case "OpaqueSecIdentityRef": + structName = "SecIdentity"; + break; + case "__SecTrust": + structName = "SecTrust"; + break; + case "_NSZone": + structName = "NSZone"; + break; + case "_AVBeatRange": + structName = "AVBeatRange"; + break; + case "AVAudio3DPoint": + structName = "Vector3"; + break; + case "OpaqueMusicSequence": + structName = "MusicSequence"; + break; + case "OpaqueAudioComponentInstance": + structName = "AudioUnit"; + break; + case "OpaqueAudioComponent": + structName = "AudioComponent"; + break; + case "GCQuaternion": + structName = "Quaterniond"; // OpenTK.Quaterniond + break; + case "OpaqueSecAccessControl": // El Capitan + case "__SecAccessControl": + structName = "SecAccessControl"; + break; + case "AudioChannelLayout": + // this is actually an `nint` used as a pointer (to get a unique signature for the .ctor) + // there's custom code in src/AVFoundation/AVAudioChannelLayout.cs to deal with this +#if XAMCORE_2_0 + structName = "nint"; +#else + structName = "Int32"; +#endif + break; +#if !XAMCORE_2_0 + // in compat it's a class (instead of a struct) hence this hack + case "AudioComponentDescription": + structName = "AudioComponentDescriptionNative"; + break; +#endif + } + return type.Name == structName; + } + + static Type inativeobject = typeof (INativeObject); + + protected virtual bool Check (string encodedType, Type type) + { + char c = encodedType [0]; + + if (encodedType.Length == 1) + return Check (c, type); + + switch (c) { + // GLKBaseEffect 'instance Vector4 get_LightModelAmbientColor()' selector: lightModelAmbientColor == (_GLKVector4={?=ffff}{?=ffff}{?=ffff}[4f])8@0:4 + case '(': + case '{': + string struct_name = encodedType.Substring (1, encodedType.IndexOf ('=') - 1); + return IsValidStruct (type, struct_name); + case '@': + switch (encodedType [1]) { + case '?': + return (type.Name == "NSAction") || type.BaseType.FullName == "System.MulticastDelegate"; + default: + return false; + } + case '^': + switch (encodedType [1]) { + case 'v': + // NSOpenGLContext 'instance MonoMac.OpenGL.CGLContext get_CGLContext()' selector: CGLContextObj == ^v8@0:4 + if ((CurrentType.Name == "NSOpenGLContext") && (type.Name == "CGLContext")) + return true; + // NSOpenGLPixelFormat 'instance MonoMac.OpenGL.CGLPixelFormat get_CGLPixelFormat()' selector: CGLPixelFormatObj == ^v8@0:4 + if ((CurrentType.Name == "NSOpenGLPixelFormat") && (type.Name == "CGLPixelFormat")) + return true; + if (type.Name == "ABRecord") { + if ((CurrentType.Name == "EKParticipant") || CurrentType.Name.StartsWith ("PKPayment", StringComparison.OrdinalIgnoreCase)) + return true; + } + if ((type.Name == "ABAddressBook") && (CurrentType.Name == "EKParticipant")) + return true; + return (type.FullName == "System.IntPtr"); + case 'B': + case 'd': + case 'f': + case 'I': + case 'i': + case 'c': + case 'q': + case 'Q': + case 'S': + return (type.FullName == "System.IntPtr") || Check (encodedType.Substring (1), type.GetElementType ()); + // NSInputStream 'instance Boolean GetBuffer(IntPtr ByRef, UInt32 ByRef)' selector: getBuffer:length: == c16@0:4^*8^I12 + case '*': + case '{': + // 10.7 only: NSArray 'static MonoMac.Foundation.NSArray FromObjects(IntPtr, Int32)' selector: arrayWithObjects:count: == @16@0:4^r@8I12 + case 'r': + if (type.FullName == "System.IntPtr") + return true; + return Check (encodedType.Substring (1), type.IsByRef ? type.GetElementType () : type); + case '@': + return Check ('@', type.IsByRef ? type.GetElementType () : type); + case '^': + case '?': + return (type.FullName == "System.IntPtr"); + default: + return false; + } + case 'r': + // const -> ignore + // e.g. vectorWithValues:count: == @16@0:4r^f8L12 + case 'o': + // out -> ignore + // e.g. validateValue:forKey:error: == c20@0:4N^@8@12o^@16 + case 'N': + // inout -> ignore + // e.g. validateValue:forKey:error: == c20@0:4N^@8@12o^@16 + case 'V': + // oneway -> ignore + // e.g. NSObject 'instance Void NativeRelease()' selector: release == Vv8@0:4 + return Check (encodedType.Substring (1), type); + default: + return false; + } + } + + /// + /// Check that specified encodedType match the type and caller. + /// + /// Encoded type from the ObjC signature. + /// Managed type representing the encoded type. + /// Caller's type. Useful to limit any special case. + protected virtual bool Check (char encodedType, Type type) + { + switch (encodedType) { + case '@': + return (type.IsInterface || // protocol + type.IsArray || // NSArray + (type.Name == "NSArray") || // NSArray + (type.FullName == "System.String") || // NSString + (type.FullName == "System.IntPtr") || // unbinded, e.g. internal + (type.BaseType.FullName == "System.MulticastDelegate") || // completion handler -> delegate + NSObjectType.IsAssignableFrom (type)) || // NSObject derived + inativeobject.IsAssignableFrom (type); // e.g. CGImage + case 'B': + // 64 bits only encode this + return type.FullName == "System.Boolean"; + case 'c': // char, used for C# bool + switch (type.FullName) { + case "System.Boolean": + case "System.SByte": + return true; + default: + return type.IsEnum && TypeSize (type) == 1; + } + case 'C': + switch (type.FullName) { + case "System.Byte": + // GLKBaseEffect 'instance Boolean get_ColorMaterialEnabled()' selector: colorMaterialEnabled == C8@0:4 + case "System.Boolean": + return true; + default: + return false; + } + case 'd': + switch (type.FullName) { + case "System.Double": + return true; + case "System.nfloat": + return IntPtr.Size == 8; + default: + return false; + } + case 'f': + switch (type.FullName) { + case "System.Single": + return true; + case "System.nfloat": + return IntPtr.Size == 4; + default: + return false; + } + case 'i': + switch (type.FullName) { + case "System.Int32": + return true; + case "System.nint": + return IntPtr.Size == 4; + case "EventKit.EKSourceType": + case "EventKit.EKCalendarType": + case "EventKit.EKEventAvailability": + case "EventKit.EKEventStatus": + case "EventKit.EKParticipantRole": + case "EventKit.EKParticipantStatus": + case "EventKit.EKParticipantType": + case "EventKit.EKRecurrenceFrequency": + case "EventKit.EKSpan": + case "EventKit.EKAlarmType": + // EventKit.EK* enums are anonymous enums in 10.10 and iOS 8, but an NSInteger in 10.11 and iOS 9. + if (IsOSX11OrIOS9) + goto default; + return true; + default: + return type.IsEnum && TypeSize (type) == 4; + } + case 'I': + switch (type.FullName) { + case "System.UInt32": + return true; + case "System.nint": // check + case "System.nuint": + return IntPtr.Size == 4; + default: + return type.IsEnum && TypeSize (type) == 4; + } + case 'l': + switch (type.FullName) { + case "System.Int32": + return true; + case "System.nint": + return IntPtr.Size == 4; + default: + return type.IsEnum && TypeSize (type) == 4; + } + case 'L': + switch (type.FullName) { + case "System.UInt32": + return true; + case "System.nint": // check + case "System.nuint": + return IntPtr.Size == 4; + default: + return type.IsEnum && TypeSize (type) == 4; + } + case 'q': + switch (type.FullName) { + case "System.Int64": + return true; + case "System.nint": + return IntPtr.Size == 8; + default: + return type.IsEnum && TypeSize (type) == 8; + } + case 'Q': + switch (type.FullName) { + case "System.UInt64": + return true; + case "System.nint": // check + case "System.nuint": + return IntPtr.Size == 8; + default: + return type.IsEnum && TypeSize (type) == 8; + } + case 's': + return type.FullName == "System.Int16"; + // unsigned 16 bits + case 'S': + switch (type.FullName) { + case "System.UInt16": + // NSString 'instance Char _characterAtIndex(Int32)' selector: characterAtIndex: == S12@0:4I8 + case "System.Char": + return true; + default: + return type.IsEnum && TypeSize (type) == 2; + } + case ':': + return type.Name == "Selector"; + case 'v': + return type.FullName == "System.Void"; + case '?': + return type.BaseType.FullName == "System.MulticastDelegate"; // completion handler -> delegate + case '#': + return type.FullName == "System.IntPtr" || type.Name == "Class"; + // CAMediaTimingFunction 'instance Void GetControlPointAtIndex(Int32, IntPtr)' selector: getControlPointAtIndex:values: == v16@0:4L8[2f]12 + case '[': + return type.FullName == "System.IntPtr"; + // const uint8_t * -> IntPtr + // NSCoder 'instance Void EncodeBlock(IntPtr, Int32, System.String)' selector: encodeBytes:length:forKey: == v20@0:4r*8I12@16 + case '*': + return type.FullName == "System.IntPtr"; + case '^': + return type.FullName == "System.IntPtr"; + } + return false; + } + } +} diff --git a/tests/introspection/ApiStructTest.cs b/tests/introspection/ApiStructTest.cs new file mode 100644 index 00000000000..3e29fa4a8a1 --- /dev/null +++ b/tests/introspection/ApiStructTest.cs @@ -0,0 +1,94 @@ +// +// ApiStructTest.cs: enforce structure definitions +// +// Authors: +// Aaron Bockover +// +// Copyright 2013 Xamarin, Inc. + +using System; +using System.Linq; +using System.Reflection; +using System.Runtime.InteropServices; + +using NUnit.Framework; + +#if XAMCORE_2_0 +using ObjCRuntime; +using Foundation; +#elif MONOMAC +using MonoMac.ObjCRuntime; +using MonoMac.Foundation; +#else +using MonoTouch.ObjCRuntime; +using MonoTouch.Foundation; +#endif + +namespace Introspection { + + [TestFixture] + public class ApiStructTest : ApiBaseTest + { + public ApiStructTest () + { + ContinueOnFailure = true; + LogProgress = true; + } + + protected virtual bool Skip (Type type) + { + return SkipDueToAttribute (type); + } + + [Test] + public void Structs () + { + int totalStructs = 0; + int totalErrors = 0; + + var structQuery = from type in Assembly.GetTypes () + where type.IsValueType && !type.IsPrimitive && !type.IsEnum && !Skip (type) + select type; + + foreach (var type in structQuery) { + totalStructs++; + if (!CheckStruct (type)) { + totalErrors++; + + if (!ContinueOnFailure) + break; + } + } + + Assert.AreEqual (0, totalErrors, + "{0} errors found in {1} structures validated", + totalErrors, totalStructs); + } + + protected virtual bool CheckStruct (Type type) + { + var success = true; + + foreach (var fi in type.GetFields ()) { + if (!CheckField (type, fi)) + success = false; + } + + return success; + } + + protected virtual bool CheckField (Type type, FieldInfo fi) + { +#if XAMCORE_2_0 + if (fi.FieldType.IsEnum && fi.FieldType.GetCustomAttribute () != null) { + if (LogProgress) + Console.Error.WriteLine ("{0} has a [Native] enum field in its definition: {1} {2}", + type.FullName, fi.FieldType, fi.Name); + return false; + } +#endif + return true; + } + } +} + diff --git a/tests/introspection/ApiTypoTest.cs b/tests/introspection/ApiTypoTest.cs new file mode 100644 index 00000000000..c39d371b455 --- /dev/null +++ b/tests/introspection/ApiTypoTest.cs @@ -0,0 +1,476 @@ +// +// Test the generated API selectors against typos or non-existing cases +// +// Authors: +// Paola Villarreal +// +// Copyright 2015 Xamarin Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using NUnit.Framework; +#if XAMCORE_2_0 +using UIKit; +using Foundation; +#else +using MonoTouch.UIKit; +using MonoTouch.Foundation; +#endif + +namespace Introspection +{ + public abstract class ApiTypoTest : ApiBaseTest + { + protected ApiTypoTest () + { + ContinueOnFailure = true; + } + + public virtual bool Skip (Type baseType, string typo) { + return SkipAllowed (baseType.Name, null, typo); + } + + public virtual bool Skip (MemberInfo methodName, string typo) { + return SkipAllowed (methodName.DeclaringType.Name, methodName.Name, typo); + } + + HashSet allowed = new HashSet () { + "Aac", + "Accurracy", + "Achivements", + "Acos", + "Actionname", + "Activitiy", + "Addr", + "Adjustmentfor", + "Aifc", + "Aiff", + "Amete", + "Amr", + "Anglet", + "Arraycollation", + "Asin", + "Atan", + "Attrib", + "Attributevalue", + "Audiofile", + "Automounted", + "Autoredirect", + "Backface", + "Bary", + "Batc", + "Bim", + "Biquad", + "Bitangent", + "Blinn", + "Blit", + "Bokeh", + "Bsln", + "Bssid", + "Bzip", + "Cabac", + "Caf", // acronym: Core Audio Format + "Cancellable", + "Cavlc", + "Celp", // MPEG4ObjectID + "Characterteristic", + "Chromaticities", + "Ciff", + "Cinepak", + "Clearcoat", + "Colos", + "Commerical", + "Composable", + "Conflictserror", + "Connnect", + "Counterclock", + "Craete", + "Cubemap", + "Cmyk", // acronym: Cyan, magenta, yellow and key + "Daap", + "Dav", + "Dcip", // acronym: Digital Cinema Implementation Partners + "Deca", + "Decomposables", + "Deinterlace", + "Descendents", + "Descrete", + "Differental", + "Diffie", + "Directionfor", + "Dist", + "dlclose", + "dlerror", + "Dlfcn", + "dlopen", + "dlsym", + "Dng", + "Dns", + "Dont", + "Dop", + "Downsample", + "Downmix", // Sound terminology that means making a stereo mix from a 5.1 surround mix. + "Dpa", + "Dpad", // Directional pad (D-pad) + "Droste", + "Dtls", + "dy", + "Ebu", + "Ecc", + "Eof", // acronym End-Of-File + "Emagic", + "Emaili", + "Eppc", + "Exhange", + "Exp", + "Flipside", + "Formati", + "Fov", + "Framebuffer", + "Framesetter", + "Freq", + "Ftps", + "Func", + "Gadu", + "Geocoder", + "Gpp", + "Hdmi", + "Hdr", + "Hevc", // CMVideoCodecType / High Efficiency Video Coding + "Hfp", + "Hipass", + "Hls", + "Hrtf", // acronym used in AUSpatializationAlgorithm + "Hvxc", // MPEG4ObjectID + "Icq", + "Identd", + "Imagefor", + "Imap", + "Imaps", + "Img", + "Inser", + "Interac", + "Interframe", + "Interitem", + "Intermenstrual", + "Intoi", + "Ios", + "Ipp", + "Iptc", + "Ircs", + "Itu", + "Jfif", + "Json", + "Keyerror", + "Keyi", + "Keyspace", + "ks", + "Langauges", + "Ldaps", + "Lerp", + "Linecap", + "Lingustic", + "Lod", + "Lopass", + "Lowlevel", + "Matchingcoalesce", + "Metacharacters", + "Minification", + "Mobike", // acronym + "Morpher", + "Mtu", // acronym + "Mtc", // acronym + "Mul", + "Mult", + "Multipeer", + "Muxed", + "nfloat", + "nint", + "Nntps", + "Ntlm", + "Ntsc", + "nuint", + "Numbernumber", + "Nyquist", + "Objectfor", + "Occlussion", + "Ocurrences", + "Oid", + "Oneup", // TVElementKeyOneupTemplate + "Orthographyrange", + "ove", + "Paeth", // PNG filter + "Pausable", + "Pcl", + "Pcm", + "Pdu", + "Persistance", + "Pesented", + "Pfs", // acronym + "Pkcs", + "Placemark", + "Playthrough", + "Pointillize", + "Polyline", + "Popularimeter", + "Prerolls", + "Preseti", + "Propogate", + "Psec", + "Pvrtc", // MTLBlitOption - PowerVR Texture Compression + "Quaterniond", + "Qura", + "Reacquirer", + "Reinvitation", + "Reinvite", + "Replayable", + "Requestwith", + "Rgb", + "Rgba", + "Roi", + "Romm", // acronym: Reference Output Medium Metric + "Rpa", + "Rpn", // acronym + "Rssi", + "Rtsp", + "Scn", + "Sdk", + "Sdtv", // acronym: Standard Definition Tele Vision + "Seekable", + "Shadable", + "Sharegroup", + "Siemen", + "Sinh", + "Sint", // as in "Signed Integer" + "Slerp", + "Slomo", + "Smpte", + "Snapshotter", + "Snorm", + "Sobel", + "Spacei", + "Sqrt", + "Srgb", + "Ssid", + "Standarize", + "Stateful", + "Stateright", + "Subbeat", + "Subcardioid", + "Subentities", + "Subheadline", + "Submesh", + "Submeshes", + "Subpixel", + "Subsec", + "Superentity", + "Sym", + "Synchronizable", + "Tanh", + "Texcoord", + "Texel", + "th", + "Threadgroup", + "Threadgroups", + "Thumbstick", + "Timelapse", + "Timelapses", + "Tls", + "Tlv", + "Toi", + "Truncantion", + "Tweening", + "tx", + "ty", + "Udi", + "Udp", + "Unconfigured", + "Undecodable", + "Underrun", + "Unorm", + "Unprepare", + "Unproject", + "Uterance", + "Utf", + "Uti", + "Varispeed", + "Vergence", + "Vnode", + "Vpn", + "Whitespaces", + "Writeability", + "Xpc", + "xy", + "Xyz", + "yuvs", + "yx", + "yy", + "Yyy", +#if !XAMCORE_2_0 + // classic only mistakes - that should not change anymore + "Timetime", + "Rectfrom", + "Distancefrom", + "Calendarc", + "Negotiat", + "Trus", + "Placemarks", + "Chage", + "Elipse", + "intptr", + "rbool", + "rint", + "rfloat", + "rdouble", + "rintptr", + "cgsize", + "cgpoint", + "cgrect", + "nsrange", + "stret", + "monotouch", + "xamarin", + "Dimiss", + "Owneroptions", + "Delegat", + "Nibfor", + "Delegatequeue", + "Sispatch", +#endif + }; + + // ease maintenance of the list + HashSet used = new HashSet (); + + bool SkipAllowed (string typeName, string methodName, string typo) + { + if (allowed.Contains (typo)) { + used.Add (typo); + return true; + } + return false; + } + + bool IsObsolete (MemberInfo mi) + { + if (mi == null) + return false; + if (mi.GetCustomAttributes (true).Any ()) + return true; + return IsObsolete (mi.DeclaringType); + } + + [Test] + public void TypoTest () + { + var types = Assembly.GetTypes (); + int totalErrors = 0; + foreach (Type t in types) { + if (t.IsPublic && !IsObsolete (t)) { + string txt = NameCleaner (t.Name); + var typo = GetTypo (txt); + if (typo.Length > 0 ) { + if (!Skip (t, typo)) { + ReportError ("Typo in TYPE: {0} - {1} ", t.Name, typo); + totalErrors++; + } + } + + var fields = t.GetFields (); + foreach (FieldInfo f in fields) { + if (!f.IsPublic && !f.IsFamily && !IsObsolete (f)) + continue; + + txt = NameCleaner (f.Name); + typo = GetTypo (txt); + if (typo.Length > 0) { + if (!Skip (f, typo)) { + ReportError ("Typo in FIELD name: {0} - {1}, Type: {2}", f.Name, typo, t.Name); + totalErrors++; + } + } + } + + var methods = t.GetMethods (); + foreach (MethodInfo m in methods) { + if (!m.IsPublic && !m.IsFamily && !IsObsolete (m)) + continue; + + txt = NameCleaner (m.Name); + typo = GetTypo (txt); + if (typo.Length > 0) { + if (!Skip (m, typo)) { + ReportError ("Typo in METHOD name: {0} - {1}, Type: {2}", m.Name, typo, t.Name); + totalErrors++; + } + } +#if false + var parameters = m.GetParameters (); + foreach (ParameterInfo p in parameters) { + txt = NameCleaner (p.Name); + typo = GetTypo (txt); + if (typo.Length > 0) { + ReportError ("Typo in PARAMETER Name: {0} - {1}, Method: {2}, Type: {3}", p.Name, typo, m.Name, t.Name); + totalErrors++; + } + } +#endif + } + } + } +#if false + // ease removal of unrequired values (but needs to be checked for every profile) + var unused = allowed.Except (used); + foreach (var typo in unused) + Console.WriteLine ("Unused entry \"{0}\"", typo); +#endif + Assert.IsTrue ((totalErrors == 0), "We have {0} typos!", totalErrors); + } + + public abstract string GetTypo (string txt); + + static StringBuilder clean = new StringBuilder (); + + static string NameCleaner (string name) + { + clean.Clear (); + foreach (char c in name) { + if (Char.IsUpper (c)) { + clean.Append (' ').Append (c); + continue; + } + if (Char.IsDigit (c)) { + clean.Append (' '); + continue; + } + switch (c) { + case '<': + case '>': + case '_': + clean.Append (' '); + break; + default: + clean.Append (c); + break; + } + } + return clean.ToString (); + } + } +} \ No newline at end of file diff --git a/tests/introspection/ApiWeakPropertyTest.cs b/tests/introspection/ApiWeakPropertyTest.cs new file mode 100644 index 00000000000..932a98ddf7d --- /dev/null +++ b/tests/introspection/ApiWeakPropertyTest.cs @@ -0,0 +1,110 @@ +using System; +using System.IO; +using System.Collections.Generic; +using System.Reflection; + +using NUnit.Framework; + +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +#elif MONOMAC +using MonoMac.Foundation; +using MonoMac.ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif + +namespace Introspection { + [Preserve (AllMembers = true)] + public abstract class ApiWeakPropertyTest : ApiBaseTest { + + /// + /// Override if you want to skip testing the specified type. + /// + /// Type to be tested + protected virtual bool Skip (Type type) + { + switch (type.Name) { + case "LinkWithAttribute": // LinkWithAttribute.WeakFrameworks + return true; + } + return false; + } + + /// + /// Override if you want to skip testing the specified property. + /// + /// Property candidate. + protected virtual bool Skip (PropertyInfo property) + { + return false; + } + + [Test] + public void WeakPropertiesHaveArgumentSemantic () + { + var failed_properties = new List (); + + Errors = 0; + int c = 0, n = 0; + foreach (Type t in Assembly.GetTypes ()) { + if (Skip (t) || SkipDueToAttribute (t)) + continue; + + if (LogProgress) + Console.WriteLine ("{0}. {1}", c++, t.FullName); + + foreach (var p in t.GetProperties (BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) { + // looking for properties with setters only + if (!p.CanWrite) + continue; + + if (SkipDueToAttribute (p)) + continue; + + if (Skip (p)) + continue; + + string name = p.Name; + if (!name.StartsWith ("Weak")) + continue; + + string error; + if (CheckArgumentSemantic (p.GetMethod, out error)) { + ReportError (error); + failed_properties.Add (p.ToString ()); + } + if (CheckArgumentSemantic (p.SetMethod, out error)) { + ReportError (error); + failed_properties.Add (p.ToString ()); + } + n++; + } + } + Assert.AreEqual (0, Errors, "{0} errors found in {1} fields validated: {2}", Errors, n, string.Join (", ", failed_properties)); + } + + bool CheckArgumentSemantic (MethodInfo meth, out string error) + { + error = null; + var export = meth.GetCustomAttribute (); + if (export == null) { + error = String.Format ("{0}.{1} has no [Export]", meth.DeclaringType.FullName, meth.Name); + return true; + } + + switch (export.ArgumentSemantic) { + case ArgumentSemantic.Assign: // Also case ArgumentSemantic.UnsafeUnretained: + case ArgumentSemantic.Copy: + case ArgumentSemantic.Retain: // case ArgumentSemantic.Strong: + case ArgumentSemantic.Weak: + return false; + default: + error = String.Format ("{0}.{1} has incorrect ArgumentSemantics: {2}", meth.DeclaringType.FullName, meth.Name, export.ArgumentSemantic); + return true; + } + } + } +} \ No newline at end of file diff --git a/tests/introspection/CoreSelectorTest.cs b/tests/introspection/CoreSelectorTest.cs new file mode 100644 index 00000000000..40f471020d1 --- /dev/null +++ b/tests/introspection/CoreSelectorTest.cs @@ -0,0 +1,130 @@ +// +// Test the generated API selectors against typos or non-existing cases +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012-2013 Xamarin Inc. All rights reserved. +// + +using System; +using System.Reflection; +using NUnit.Framework; + +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +#elif MONOMAC +using MonoMac.Foundation; +using MonoMac.ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif + +namespace Introspection { + + public abstract class CoreSelectorTest : ApiSelectorTest { + + protected override bool CheckResponse (bool value, Type actualType, MethodBase method, ref string name) + { + if (value) + return true; + + var declaredType = method.DeclaringType; + + switch (name) { + // optional stuff defined in NSObject (but not implemented by every subclasses) + case "encodeWithCoder:": + case "objectDidEndEditing:": + case "commitEditing": + case "commitEditingWithDelegate:didCommitSelector:contextInfo:": + if (declaredType.Name == "NSObject") + return true; + break; + // internal stuff that must be used + case "_setCFClientFlags:callback:context:": + case "_scheduleInCFRunLoop:forMode:": + case "_unscheduleFromCFRunLoop:forMode:": + // init* works (see monotouchtest.app) but does not respond when queried + case "initWithFileAtPath:": + case "initWithData:": + case "initWithURL:": + if (declaredType.Name == "NSInputStream") + return true; + break; + // init* works (see monotouchtest.app) but does not respond when queried + case "initToMemory": + case "initToFileAtPath:append:": + if (declaredType.Name == "NSOutputStream") + return true; + break; + // init* works (see monotouchtest.app) but does not respond when queried + case "initWithFileDescriptor:": + case "initWithFileDescriptor:closeOnDealloc:": + if (declaredType.Name == "NSFileHandle") + return true; + break; + case "initWithString:": + case "initWithString:attributes:": + case "initWithAttributedString:": + if (declaredType.Name == "NSAttributedString" || declaredType.Name == "NSMutableAttributedString") + return true; + break; + } + return base.CheckResponse (value, actualType, method, ref name); + } + + protected override bool Skip (Type type) + { + switch (type.Name) { + case "MTLRenderPassAttachmentDescriptor": + // This is an abstract(-ish...) type, iOS allows creating an instance of it, but the instance doesn't respond to most of the selector in the headers. + return true; + } + + return base.Skip (type); + } + + protected override IntPtr GetClassForType (Type type) + { + switch (type.Namespace) { + case "MonoTouch.Metal": + case "MonoMac.Metal": + case "Metal": + switch (type.Name) { + case "MTLArgument": + case "MTLArrayType": + case "MTLCompileOptions": + case "MTLComputePipelineDescriptor": + case "MTLComputePipelineReflection": + case "MTLDepthStencilDescriptor": + case "MTLRenderPassAttachmentDescriptor": + case "MTLRenderPassColorAttachmentDescriptor": + case "MTLRenderPassDepthAttachmentDescriptor": + case "MTLRenderPassDescriptor": + case "MTLRenderPassStencilAttachmentDescriptor": + case "MTLRenderPipelineColorAttachmentDescriptor": + case "MTLRenderPipelineDescriptor": + case "MTLRenderPipelineReflection": + case "MTLSamplerDescriptor": + case "MTLStencilDescriptor": + case "MTLStructMember": + case "MTLStructType": + case "MTLTextureDescriptor": + case "MTLVertexAttribute": + case "MTLVertexAttributeDescriptor": + case "MTLVertexBufferLayoutDescriptor": + case "MTLVertexDescriptor": + var ctor = type.GetConstructor (Type.EmptyTypes); + using (var obj = ctor.Invoke (null) as NSObject) { + return IntPtr_objc_msgSend (obj.Handle, Selector.GetHandle ("class")); + } + } + break; + } + + return base.GetClassForType (type); + } + } +} diff --git a/tests/introspection/EnvironmentVariable.cs b/tests/introspection/EnvironmentVariable.cs new file mode 100644 index 00000000000..52214ccb38b --- /dev/null +++ b/tests/introspection/EnvironmentVariable.cs @@ -0,0 +1,19 @@ +using System; + +namespace Xamarin.Utils { + // Boolean variable that defaults to false, unless a environmental variable is set. Setting value explictly overrides all other values. + class LatchedEnvironmentVariable { + bool envVariable; + bool? setValue; + + internal LatchedEnvironmentVariable (string variableName) + { + envVariable = !String.IsNullOrEmpty (Environment.GetEnvironmentVariable (variableName)); + } + + internal bool Value { + set { setValue = value; } + get { return setValue.HasValue ? setValue.Value : envVariable; } + } + } +} diff --git a/tests/introspection/Mac/Info.plist b/tests/introspection/Mac/Info.plist new file mode 100644 index 00000000000..af788969bc6 --- /dev/null +++ b/tests/introspection/Mac/Info.plist @@ -0,0 +1,20 @@ + + + + + CFBundleDisplayName + apitest + CFBundleIdentifier + com.xamarin.introspection + CFBundleVersion + 1 + LSMinimumSystemVersion + 10.7 + NSPrincipalClass + NSApplication + LSApplicationCategoryType + public.app-category.developer-tools + CFBundleName + introspection + + diff --git a/tests/introspection/Mac/Mac.cs b/tests/introspection/Mac/Mac.cs new file mode 100644 index 00000000000..170543089c2 --- /dev/null +++ b/tests/introspection/Mac/Mac.cs @@ -0,0 +1,31 @@ +// +// Mac-specific Helpers +// +// Authors: +// Sebastien Pouliot +// Aaron Bockover +// +// Copyright 2012-2016 Xamarin Inc. All rights reserved. +// + +using System; + +namespace Introspection { + + public static class Mac { + public static readonly Version Version_10_7 = new Version (10, 7); + public static readonly Version Version_10_8 = new Version (10, 8); + public static readonly Version Version_10_9 = new Version (10, 9); + public static readonly Version Version_10_10 = new Version (10, 10); + public static readonly Version Version_10_11 = new Version (10, 11); + + static PlatformInfo host => PlatformInfo.Host; + + public static bool CheckSystemVersion (int major, int minor) => host.Version >= new Version (major, minor); + public static bool Is32BitMavericks => host.IsArch32 && IsAtLeast (Version_10_9); + public static bool IsYosemiteOrHigher => IsAtLeast (Version_10_10); + public static bool IsElCapitanOrHigher => IsAtLeast (Version_10_11); + public static bool IsAtLeast (int major, int minor) => IsAtLeast (new Version (major, minor)); + public static bool IsAtLeast (Version version) => host.IsMac && host.Version >= version; + } +} diff --git a/tests/introspection/Mac/MacApiCtorInitTest.cs b/tests/introspection/Mac/MacApiCtorInitTest.cs new file mode 100644 index 00000000000..0defbe53952 --- /dev/null +++ b/tests/introspection/Mac/MacApiCtorInitTest.cs @@ -0,0 +1,243 @@ +// +// Mac-specific `init*` selectors validations +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012-2013,2015 Xamarin Inc. All rights reserved. +// + +using System; +using System.Collections.Generic; + +#if XAMCORE_2_0 +using Foundation; +#else +using MonoMac.Foundation; +#endif + +using NUnit.Framework; + +namespace Introspection { + + [TestFixture] + public class MacApiCtorInitTest : ApiCtorInitTest { + + public MacApiCtorInitTest () + { + //LogProgress = true; + ContinueOnFailure = true; + } + + protected override bool Skip (Attribute attr) + { + return base.Skip (attr); + } + + protected override bool Skip (Type type) + { + switch (type.FullName) { + // These should be DisableDefaultCtor but can't due to backward compat + case "MonoMac.EventKit.EKParticipant": + case "EventKit.EKParticipant": + case "XamCore.CoreImage.CISampler": + case "CoreImage.CISampler": + return true; + // OSX 10.8+ + case "MonoMac.AppKit.NSSharingService": + case "AppKit.NSSharingService": + case "MonoMac.AppKit.NSSharingServicePicker": + case "AppKit.NSSharingServicePicker": + case "MonoMac.Foundation.NSUserNotification": + case "Foundation.NSUserNotification": + case "MonoMac.Foundation.NSUserNotificationCenter": + case "Foundation.NSUserNotificationCenter": + case "MonoMac.AVFoundation.AVPlayerItemVideoOutput": + case "AVFoundation.AVPlayerItemVideoOutput": + case "MonoMac.Foundation.NSUuid": + case "Foundation.NSUuid": + if (!Mac.CheckSystemVersion (10, 8)) + return true; + break; + // Native exception coming from [NSWindow init] which calls + // [NSWindow initWithContentRect:styleMask:backing:defer] + case "MonoMac.AppKit.NSWindow": + case "AppKit.NSWindow": + return true; +#if !XAMCORE_2_0 + case "MonoMac.AppKit.NSToolbar": // mono[10518:626783] *** -[__NSDictionaryM removeObjectForKey:]: key cannot be nil + case "MonoMac.SceneKit.SCNRenderer": // -[SCNRenderer init]: unrecognized selector sent to instance 0x7c6446c0 + case "MonoMac.SceneKit.SCNLookAtConstraint": + return true; +#endif + case "MonoMac.Foundation.NSUrlSession": + case "Foundation.NSUrlSession": + case "MonoMac.Foundation.NSUrlSessionTask": + case "Foundation.NSUrlSessionTask": + case "MonoMac.Foundation.NSUrlSessionDataTask": + case "Foundation.NSUrlSessionDataTask": + case "MonoMac.Foundation.NSUrlSessionUploadTask": + case "Foundation.NSUrlSessionUploadTask": + case "MonoMac.Foundation.NSUrlSessionDownloadTask": + case "Foundation.NSUrlSessionDownloadTask": + case "MonoMac.Foundation.NSUrlSessionConfiguration": + case "Foundation.NSUrlSessionConfiguration": + // These types were introduced as 64-bit only in Mavericks, and 32+64bits in Yosemite. We can't + // express that with our AvailabilityAttribute, we set it as available (for all architectures, since + // we can't distinguish them) starting with Mavericks. + if (Mac.Is32BitMavericks) + return true; + break; + + case "GLKit.GLKSkyboxEffect": + // Crashes inside libGL.dylib, most likely because something hasn't been initialized yet, because + // I can reproduce in an Xcode project if I put [[GLKSkyboxEffect alloc] init]; in main, but it doesn't + // crash in applicationDidFinishLaunching. + // + // frame #0: 0x00007fff8d570db1 libGL.dylib`glGetError + 13 + // frame #1: 0x0000000100025542 GLKit`-[GLKEffect initWithPropertyArray:] + 1142 + // frame #2: 0x0000000100022c2d GLKit`-[GLKSkyboxEffect init] + 493 + // + if (IntPtr.Size == 8) + return true; + break; + +#if !XAMCORE_3_0 + case "SpriteKit.SKView": + // Causes a crash later. Filed as radar://18440271. + // Apple said they won't fix this ('init' isn't a designated initializer) + if (IntPtr.Size == 8) + return true; + break; +#endif + + case "MonoMac.AppKit.NSSpeechRecognizer": + case "AppKit.NSSpeechRecognizer": + // Makes OSX put up "a download is required for speech recognition" dialog. + return true; + + case "MonoMac.Foundation.NSUserActivity": + case "Foundation.NSUserActivity": + // Crashes by default: + // Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Caller did not provide an activityType, and this process does not have a NSUserActivityTypes in its Info.plist. + // but since it looks like the constructor is usable with the proper Info.plist, we can't remove it. + return true; + } + + switch (type.Namespace) { + // OSX 10.8+ + case "MonoMac.Accounts": + case "Accounts": + case "MonoMac.GameKit": + case "GameKit": + case "MonoMac.Social": + case "Social": + case "MonoMac.StoreKit": + case "StoreKit": + if (!Mac.CheckSystemVersion (10, 8)) + return true; + break; + case "SceneKit": + case "MonoMac.SceneKit": + if (!Mac.CheckSystemVersion (10, 8) || IntPtr.Size != 8) + return true; + break; + } + + return base.Skip (type); + } + + protected override void CheckNSObjectProtocol (NSObject obj) + { + switch (obj.GetType ().Name) { + case "NSString": + // according to bots `isKindOf (null)` returns true before Yosemite + break; + case "SBObject": + // *** NSForwarding: warning: object 0x77a49a0 of class '__NSMessageBuilder' does not implement doesNotRecognizeSelector: -- abort + break; + default: + base.CheckNSObjectProtocol (obj); + break; + } + } + + protected override void CheckToString (NSObject obj) + { + switch (obj.GetType ().FullName) { + // native crash calling MonoMac.Foundation.NSObject.get_Description () + case "WebKit.WKNavigationAction": + case "WebKit.WKFrameInfo": // EXC_BAD_ACCESS (code=1, address=0x0) + case "MonoMac.Foundation.NSUrlConnection": + case "Foundation.NSUrlConnection": + case "MonoMac.AppKit.NSLayoutConstraint": // Unable to create description in descriptionForLayoutAttribute_layoutItem_coefficient. Something is nil + case "AppKit.NSLayoutConstraint": + case "MonoMac.AVFoundation.AVPlayerItemTrack": + case "AVFoundation.AVPlayerItemTrack": + // 10.8 + case "MonoMac.AVFoundation.AVComposition": + case "AVFoundation.AVComposition": + case "MonoMac.GameKit.GKPlayer": // Crashing on 10.8.3 from the Apple beta channel for abock (on 2013-01-30) + case "GameKit.GKPlayer": + case "MonoMac.AVFoundation.AVAssetResourceLoadingRequest": // Crashing on 10.9.1 for abock (2014-01-13) + case "AVFoundation.AVAssetResourceLoadingRequest": + case "MonoMac.AVFoundation.AVAssetResourceLoadingDataRequest": // Crashes on 10.9.3 for chamons (constructor found in AVCompat) + case "AVFoundation.AVAssetResourceLoadingDataRequest": + case "MonoMac.AVFoundation.AVCaptureDeviceInputSource": // Crashes on 10.9.5 + case "AVFoundation.AVCaptureDeviceInputSource": + break; + default: + base.CheckToString (obj); + break; + } + } + + static List do_not_dispose = new List (); + + protected override void Dispose (NSObject obj, Type type) + { + switch (type.FullName) { + // FIXME: those crash the application when Dispose is called + case "MonoMac.JavaScriptCore.JSManagedValue": + case "JavaScriptCore.JSManagedValue": + // JSManagedValue crashes in Yosemite (b7), but not Mavericks. + if (!Mac.CheckSystemVersion (10, 10)) + goto default; + goto case "MonoMac.ImageKit.IKScannerDeviceView"; // fallthrough + case "MonoMac.ImageKit.IKScannerDeviceView": // 19835 + case "ImageKit.IKScannerDeviceView": + case "MonoMac.AppKit.NSFontPanel": // *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'An instance 0x11491cc00 of class NSButton was deallocated while key value observers were still registered with it. + case "AppKit.NSFontPanel": + case "MonoMac.AVFoundation.AVAudioRecorder": // same on iOS + case "AVFoundation.AVAudioRecorder": + case "MonoMac.Foundation.NSUrlConnection": + case "Foundation.NSUrlConnection": + // 10.8: + case "MonoMac.Accounts.ACAccount": // maybe the default .ctor is not allowed ? + case "Accounts.ACAccount": + case "MonoMac.Accounts.ACAccountCredential": + case "Accounts.ACAccountCredential": + case "MonoMac.Accounts.ACAccountStore": + case "Accounts.ACAccountStore": + case "MonoMac.Accounts.ACAccountType": + case "Accounts.ACAccountType": + case "MonoMac.CoreData.NSPersistentStoreCoordinator": + case "CoreData.NSPersistentStoreCoordinator": + do_not_dispose.Add (obj); + break; + // 10.11 + case "MonoMac.CoreImage.CIImageAccumulator": + case "CoreImage.CIImageAccumulator": + case "WebKit.WKNavigation": + // crashes on El Capitan (b2) but not before + if (!Mac.CheckSystemVersion (10, 11)) + goto default; + do_not_dispose.Add (obj); + break; + default: + base.Dispose (obj, type); + break; + } + } + } +} diff --git a/tests/introspection/Mac/MacApiFieldTest.cs b/tests/introspection/Mac/MacApiFieldTest.cs new file mode 100644 index 00000000000..0af31f50c04 --- /dev/null +++ b/tests/introspection/Mac/MacApiFieldTest.cs @@ -0,0 +1,220 @@ +// +// Mac specific fields validator +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +using System; +using System.Linq; +using System.Reflection; + +using NUnit.Framework; + +namespace Introspection { + + [TestFixture] + public class MacApiFieldTest : ApiFieldTest { + + public MacApiFieldTest () + { + ContinueOnFailure = true; + } + + static bool IsUnified { + get { + return AppDomain.CurrentDomain.GetAssemblies ().Any (x => x.FullName.Contains ("Xamarin.Mac")); + } + } + + protected override bool Skip (Type type) + { + switch (type.FullName) { + // OS X 10.8 + + case "MonoMac.AppKit.NSSharingService": + case "AppKit.NSSharingService": + case "MonoMac.Foundation.NSUserNotification": + case "Foundation.NSUserNotification": + return !Mac.CheckSystemVersion (10, 8); + } + + switch (type.Namespace) { + // OSX 10.8+ + case "MonoMac.Accounts": + case "Accounts": + case "MonoMac.GameKit": + case "GameKit": + case "MonoMac.Social": + case "Social": + return !Mac.CheckSystemVersion (10, 8); + case "SceneKit": + case "MonoMac.SceneKit": + return !Mac.CheckSystemVersion (10, 8) || IntPtr.Size != 8; + default: + return false; + } + } + + protected override bool Skip (PropertyInfo p) + { + switch (p.DeclaringType.Name) { + case "NSUrlSessionDownloadDelegate": + switch (p.Name) { + case "TaskResumeDataKey": + // This field was introduced as 64-bit only in Mavericks, and 32+64bits in Yosemite. We can't + // express that with our AvailabilityAttribute, we set it as available (for all architectures, since + // we can't distinguish them) starting with Mavericks. + if (Mac.Is32BitMavericks) + return true; + break; + } + break; + } + + switch (p.Name) { + // NSTableView + case "RowViewKey": + return true; + // NSBitmapImageRep + case "CompressionMethod": + case "CompressionFactor": + case "DitherTransparency": + return true; + // CIImage 10.8+ + case "AutoAdjustFeaturesKey": // kCIImageAutoAdjustFeatures - documented in 10.8 + case "AutoAdjustRedEyeKey": + case "AutoAdjustEnhanceKey": + case "CIImagePropertiesKey": + return true; + // CIImage + case "CIImageColorSpaceKey": + return true; // returns null but documented prior to 10.8 + // CLLocation 10.8+ + case "ErrorUserInfoAlternateRegionKey": // kCLErrorUserInfoAlternateRegionKey also returns null on iOS + return true; + // NSUrl 10.8+ + case "PathKey": + return !Mac.CheckSystemVersion (10, 8); + // AVMediaCharacteristic 10.8+ + case "IsMainProgramContent": + case "IsAuxiliaryContent": + case "ContainsOnlyForcedSubtitles": + case "TranscribesSpokenDialogForAccessibility": + case "DescribesMusicAndSoundForAccessibility": + case "DescribesVideoForAccessibility": + return !Mac.CheckSystemVersion (10, 8); + // AVVideo 10.8+ + case "ProfileLevelH264Main32": + return !Mac.CheckSystemVersion (10, 8); + // AVMetadata 10.8+ + case "QuickTimeUserDataKeyTaggedCharacteristic": + return !Mac.CheckSystemVersion (10, 8); + // CIDetector + case "TypeFace": // CIDetectorTypeFace - documented as available in 10.7 + case "Accuracy": // CIDetectorAccuracy 10.7 + case "AccuracyLow": // CIDetectorAccuracyLow 10.7 + case "AccuracyHigh": // CIDetectorAccuracyHigh 10.7 + return true; + // CIDetector + case "ImageOrientation": // documented in 10.8 + case "Tracking": + case "MinFeatureSize": + return true; + // CGImageProperties - all new (10.7) values are missing (from pre-6 iOS too iirc) + case "ExifCameraOwnerName": // kCGImagePropertyExifCameraOwnerName + case "ExifBodySerialNumber": // kCGImagePropertyExifBodySerialNumber + case "ExifLensSpecification": // kCGImagePropertyExifLensSpecification + case "ExifLensMake": // kCGImagePropertyExifLensMake + case "ExifLensModel": // kCGImagePropertyExifLensModel + case "ExifLensSerialNumber": // kCGImagePropertyExifLensSerialNumber + return true; + // ACErrorDomain is _listed_ in the 10.8 Accounts Changes but like iOS it's not documented anywhere else (and does not seems to exists) + case "ErrorDomain": + // ACAccountStoreDidChangeNotification - documented in 10.8 + case "ChangeNotification": + // ACAccountType - documented in 10.8 + case "Twitter": // ACAccountTypeIdentifierTwitter + case "SinaWeibo": + case "Facebook": + case "AppId": // ACFacebookAppIdKey + case "Permissions": // ACFacebookPermissionsKey + case "Audience": // *** NOT documented in 10.8 - but part of our API enhancement + case "Everyone": // ^ MonoMac.Accounts.ACFacebookAudienceValue.Everyone + case "Friends": // ^ MonoMac.Accounts.ACFacebookAudienceValue.Friends + case "OnlyMe": // ^ MonoMac.Accounts.ACFacebookAudienceValue.OnlyMe + return true; + // MonoMac.CoreServices.CFHTTPMessage - document in 10.9 but returns null + case "_AuthenticationSchemeOAuth1": + return true; + default: + return base.Skip (p); + } + } + + protected override bool Skip (string constantName) + { + switch (constantName) { + // Only there for API compat + case "kSecUseNoAuthenticationUI": + case "kSecUseOperationPrompt": + return !IsUnified; + // MonoMac.CoreServices.CFHTTPMessage - document in 10.9 but returns null + case "kCFHTTPAuthenticationSchemeOAuth1": + return true; + // kCLErrorUserInfoAlternateRegionKey also returns null on iOS + case "kCLErrorUserInfoAlternateRegionKey": + return true; + case "NSURLSessionTransferSizeUnknown": + case "NSURLSessionDownloadTaskResumeData": + if (Mac.Is32BitMavericks) + return true; + goto default; + default: + return base.Skip (constantName); + } + } + + protected override string FindLibrary (string libraryName, bool requiresFullPath = false) + { + switch (libraryName) { + case "CFNetwork": + if (Mac.IsAtLeast (10,8)) + break; + return "/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/CFNetwork.framework/CFNetwork"; + case "CoreText": + case "CoreGraphics": + if (Mac.IsAtLeast (10,8)) + break; + return string.Format ("/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/{0}.framework/{0}", libraryName); + case "ImageIO": + if (Mac.IsAtLeast (10,9)) + break; + return "/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ImageIO.framework/ImageIO"; + case "CoreImage": + // generated code uses QuartzCore correctly - even if the [Field] property is wrong + libraryName = "QuartzCore"; + break; + case "QuartzComposer": + case "PdfKit": + case "ImageKit": + // generated code uses Quartz correctly - even if the [Field] property is wrong + libraryName = "Quartz"; + break; + case "CoreBluetooth": + if (Mac.IsYosemiteOrHigher) { + // CoreBluetooth is in /System/Library/Frameworks/CoreBluetooth.framework starting with Yosemite. + break; + } + + // CoreBluetooth is inside IOBluetooth.framework in earlier OSXs + return "/System/Library/Frameworks/IOBluetooth.framework/Versions/A/Frameworks/CoreBluetooth.framework/CoreBluetooth"; + case "SearchKit": + return "/System/Library/Frameworks/CoreServices.framework/Frameworks/SearchKit.framework/SearchKit"; + } + + return base.FindLibrary (libraryName, requiresFullPath); + } + } +} diff --git a/tests/introspection/Mac/MacApiPInvokeTest.cs b/tests/introspection/Mac/MacApiPInvokeTest.cs new file mode 100644 index 00000000000..e74f5fdac10 --- /dev/null +++ b/tests/introspection/Mac/MacApiPInvokeTest.cs @@ -0,0 +1,76 @@ +using System; +using System.Linq; +using System.Reflection; + +using NUnit.Framework; + +namespace Introspection { + + [TestFixture] + public class MacApiPInvokeTest : ApiPInvokeTest { + protected override bool SkipLibrary (string libraryName) + { + switch (libraryName){ + case "/System/Library/Frameworks/OpenGL.framework/OpenGL": + return true; + } + return base.SkipLibrary (libraryName); + } + + static bool IsUnified { + get + { + return AppDomain.CurrentDomain.GetAssemblies().Any(x => x.FullName.Contains("Xamarin.Mac")); + } + } + + protected override bool Skip (Type type) + { + string typeName = type.ToString (); + bool is32Bit = IntPtr.Size == 4; + if (is32Bit && typeName.StartsWith ("MapKit", StringComparison.Ordinal)) // MapKit is 64-bit only + return true; + + switch (type.Namespace) { + case "SceneKit": + case "MonoMac.SceneKit": + if (is32Bit) + return true; + break; + } + + switch (typeName) { + case "MonoMac.GameController.GCExtendedGamepadSnapshot": // These next 4 are in the compat API, even if they don't work. + case "MonoMac.GameController.GCGamepadSnapshot": + case "MonoMac.GameController.GCExtendedGamepadSnapShotDataV100": + case "MonoMac.GameController.GCGamepadSnapShotDataV100": + return !IsUnified; + case "GameController.GCGamepadSnapShotDataV100": // These are 64-bit only + case "GameController.GCExtendedGamepadSnapShotDataV100": + return is32Bit; + case "MonoMac.AudioToolbox.AudioSession": // These are iOS APIs that were mistakenly pulled into OSX. Removed in unified but not classic + case "MonoMac.AudioUnit.AudioUnitUtils": + return !IsUnified; // If these are in unified, don't skip, we want to scream + } + + return base.Skip(type); + } + + protected override bool Skip (string symbolName) + { + switch (symbolName) { + case "SKTerminateForInvalidReceipt": // Only there for API compat + return !IsUnified; + } + return false; + } + + protected override bool SkipAssembly (Assembly a) + { + // too many things are missing from XM 32bits bindings + // and the BCL is identical for 64 bits (no need to test it 3 times) +// return IntPtr.Size == 4; + return true; // skip everything until fixed + } + } +} \ No newline at end of file diff --git a/tests/introspection/Mac/MacApiProtocolTest.cs b/tests/introspection/Mac/MacApiProtocolTest.cs new file mode 100644 index 00000000000..a4bab15ef26 --- /dev/null +++ b/tests/introspection/Mac/MacApiProtocolTest.cs @@ -0,0 +1,171 @@ +// +// Test the generated API for common protocol support +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013 Xamarin Inc. +// + +using System; + +#if XAMCORE_2_0 +using Foundation; +using AppKit; +using CoreImage; +#else +using MonoMac.AppKit; +using MonoMac.CoreImage; +#endif + +using NUnit.Framework; + +namespace Introspection { + + [TestFixture] + public class MonoMacFixtures : ApiProtocolTest { + + protected override bool Skip (Type type, string protocolName) + { + switch (protocolName) { + case "NSSecureCoding": + switch (type.Name) { + case "NSCachedImageRep": // Not declared in header file + case "NSCIImageRep": + case "NSCustomImageRep": + case "NSEPSImageRep": + case "NSBitmapImageRep": + case "NSImageRep": + case "NSPdfImageRep": + case "AVAssetTrackSegment": // Not declared in header file + case "AVComposition": // Not declared in header file + case "AVMutableComposition": // Not declared in header file + case "AVCompositionTrackSegment": // Not declared in header file + case "MKMapSnapshotOptions": // Not declared in header file + case "NSTextTab": // Not declared in header file + return true; + default: + // CIFilter started implementing NSSecureCoding in 10.11 + if (!Mac.CheckSystemVersion (10, 11) && (type == typeof(CIFilter) || type.IsSubclassOf (typeof(CIFilter)))) + return true; + break; + } + break; + case "NSCopying": + switch (type.Name) { + case "DomNodeFilter": // Not declared in header file + case "MKDirectionsRequest": // Not declared in header file + case "EKObject": // Not declared in header file + case "EKCalendarItem": // Not declared in header file + case "EKSource": // Not declared in header file + case "EKCalendar": // Not declared in header file + case "EKEvent": // Not declared in header file + case "EKReminder": // Not declared in header file + case "ACAccount": // Not declared in header file + return true; + } + break; + case "NSMutableCopying": + switch (type.Name) { + case "EKObject": // Not declared in header file + case "EKCalendarItem": // Not declared in header file + case "EKSource": // Not declared in header file + case "EKStructuredLocation": // Not declared in header file + case "EKAlarm": // Not declared in header file + case "EKCalendar": // Not declared in header file + case "EKEvent": // Not declared in header file + case "EKParticipant": // Not declared in header file + case "EKRecurrenceRule": // Not declared in header file + case "EKReminder": // Not declared in header file + return true; + } + break; + case "NSCoding": + switch (type.Name) { + case "EKObject": // Not declared in header file + case "EKCalendarItem": // Not declared in header file + case "EKSource": // Not declared in header file + case "EKStructuredLocation": // Not declared in header file + case "EKAlarm": // Not declared in header file + case "EKCalendar": // Not declared in header file + case "EKEvent": // Not declared in header file + case "EKParticipant": // Not declared in header file + case "EKRecurrenceRule": // Not declared in header file + case "EKReminder": // Not declared in header file + case "AVAssetTrackSegment": // Not declared in header file + case "AVComposition": // Not declared in header file + case "AVMutableComposition": // Not declared in header file + case "AVCompositionTrackSegment": // Not declared in header file + case "MKMapSnapshotOptions": // Not declared in header file + return true; + } + break; + case "NSWindowRestoration": + switch (type.Name) { + case "NSDocumentController": + // There's a category that implements the NSWindowRestoration protocol for NSDocumentController, + // but that apparently doesn't make conformsToProtocol: return true. + // '@interface NSDocumentController (NSWindowRestoration) ' + return true; + } + break; + case "NSUserInterfaceItemIdentification": + // NSViewController started implementing NSUserInterfaceItemIdentification in 10.10 + if (!Mac.CheckSystemVersion (10, 10) && (type == typeof(NSViewController) || type.IsSubclassOf (typeof (NSViewController)))) + return true; + + break; + case "NSMenuDelegate": + switch (type.Name) { + case "PdfView": + if (!Mac.CheckSystemVersion (10, 10)) + return true; + break; + } + break; + case "NSTextFinderClient": // Not listed in header, nor conformsToProtocol, but works in sample. But it just repondsToSelectors + if (type.Name == "NSTextView") + return true; + break; +#if !XAMCORE_4_0 + case "NSDraggingInfo": + return true; // We have to keep the type to maintain backwards compatibility. +#endif + } + + switch (type.Name) { +#if !XAMCORE_3_0 + case "NSRemoteSavePanel": + case "NSRemoteOpenPanel": + return true; // These two classes don't show up in any documentation. +#endif + } + + switch (type.Namespace) { + case "MonoMac.SceneKit": + case "SceneKit": + return IntPtr.Size == 4; // 64bits should be fine + } + + return base.Skip (type, protocolName); + } + + [Test] + public override void SecureCoding () + { + if (!Mac.CheckSystemVersion (10, 8)) + return; + + base.SecureCoding (); + } + + [Test] + public override void SupportsSecureCoding () + { + if (!Mac.CheckSystemVersion (10,8)) + return; + + base.SupportsSecureCoding (); + } + } +} diff --git a/tests/introspection/Mac/MacApiSelectorTest.cs b/tests/introspection/Mac/MacApiSelectorTest.cs new file mode 100644 index 00000000000..eb733ba9c61 --- /dev/null +++ b/tests/introspection/Mac/MacApiSelectorTest.cs @@ -0,0 +1,818 @@ +// +// Mac specific selector validators +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012 Xamarin Inc. All rights reserved. +// + +using System; +using System.Collections.Generic; +using System.Reflection; + +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +#else +using MonoMac.Foundation; +using MonoMac.ObjCRuntime; +#endif + +using NUnit.Framework; + +namespace Introspection { + + [TestFixture] + public class MacApiSelectorTest : CoreSelectorTest { + + static MacApiSelectorTest () + { + Runtime.RegisterAssembly (typeof (NSObject).Assembly); + } + + public MacApiSelectorTest () + { + //LogProgress = true; Don't uncomment this anymore, export API_TEST_LOG_PROGRESS=1 + ContinueOnFailure = true; + } + + protected override bool Skip (Type type) + { + switch (type.FullName) { + case "MonoMac.CIFilter.CIMaskedVariableBlur": // Appears to be missing from 10.11, not documented + case "CIFilter.CIMaskedVariableBlur": + if (Mac.CheckSystemVersion (10, 11)) + return true; + break; + case "MonoMac.Foundation.NSUrlSession": + case "Foundation.NSUrlSession": + case "MonoMac.Foundation.NSUrlSessionTask": + case "Foundation.NSUrlSessionTask": + case "MonoMac.Foundation.NSUrlSessionDataTask": + case "Foundation.NSUrlSessionDataTask": + case "MonoMac.Foundation.NSUrlSessionUploadTask": + case "Foundation.NSUrlSessionUploadTask": + case "MonoMac.Foundation.NSUrlSessionDownloadTask": + case "Foundation.NSUrlSessionDownloadTask": + case "MonoMac.Foundation.NSUrlSessionConfiguration": + case "Foundation.NSUrlSessionConfiguration": + // These classes are available in 32-bit Yosemite, or 32+64bit Mavericks. + if (IntPtr.Size == 4 && !Mac.CheckSystemVersion (10, 10)) + return true; + break; + case "MonoMac.AppKit.NSSharingService": + case "AppKit.NSSharingService": + case "MonoMac.AppKit.NSSharingServicePicker": + case "AppKit.NSSharingServicePicker": + case "MonoMac.Foundation.NSByteCountFormatter": + case "Foundation.NSByteCountFormatter": + case "MonoMac.Foundation.NSUserNotification": + case "Foundation.NSUserNotification": + case "MonoMac.Foundation.NSUserNotificationCenter": + case "Foundation.NSUserNotificationCenter": + case "MonoMac.AVFoundation.AVPlayerItemOutput": + case "AVFoundation.AVPlayerItemOutput": + case "MonoMac.AVFoundation.AVPlayerItemVideoOutput": + case "AVFoundation.AVPlayerItemVideoOutput": + case "MonoMac.Foundation.NSUuid": + case "Foundation.NSUuid": + if (!Mac.CheckSystemVersion (10, 8)) + return true; + break; + } + + switch (type.Namespace) { + // OSX 10.8+ + case "MonoMac.Accounts": + case "Accounts": + case "MonoMac.GameKit": + case "GameKit": + case "MonoMac.Social": + case "Social": + case "MonoMac.StoreKit": + case "StoreKit": + if (!Mac.CheckSystemVersion (10, 8)) + return true; + break; + case "SceneKit": + case "MonoMac.SceneKit": + if (!Mac.CheckSystemVersion (10, 8) || IntPtr.Size != 8) + return true; + break; + // not installed by default + case "MonoMac.Growl": + case "Growl": + return true; + } + + return base.Skip (type); + } + + protected override bool Skip (Type type, string selectorName) + { + switch (selectorName) { +#if !XAMCORE_4_0 + case "xamarinselector:removed:": + return true; +#endif +#if !XAMCORE_3_0 + case "initWithPasteboardPropertyList:ofType:": + // This is a broken binding, but it's an abstract protocol + // method, so there's no way to remove it without breaking + // compat. + return true; +#endif + case "waitUntilExit": + // category, NSTask won't respond -> @interface NSTask (NSTaskConveniences) + if (type.Name == "NSTask") + return true; + break; + case "readInBackgroundAndNotifyForModes:": + case "readInBackgroundAndNotify": + case "readToEndOfFileInBackgroundAndNotifyForModes:": + case "readToEndOfFileInBackgroundAndNotify": + case "acceptConnectionInBackgroundAndNotifyForModes:": + case "acceptConnectionInBackgroundAndNotify": + case "waitForDataInBackgroundAndNotifyForModes:": + case "waitForDataInBackgroundAndNotify": + // category, NSFileHandle won't respond -> @interface NSFileHandle (NSFileHandleAsynchronousAccess) + if (type.Name == "NSFileHandle") + return true; + break; + // initWithPlayerIDs: works (valid handle) and is documented - but does not respond when queried + case "initWithPlayerIDs:": + if (type.Name == "GKLeaderboard") + return true; + break; + // some types had NSCopying added after they were first introduced + case "copyWithZone:": + if (type.Name == "CBPeripheral" && !Mac.CheckSystemVersion (10, 9)) + return true; + break; + case "readingOptionsForType:pasteboard:": + case "writingOptionsForType:pasteboard:": + return true; // Optional selectors on NSPasteboardReading/NSPasteboardWriting + } + + switch (type.Namespace) { + // Notifications seems to follow a pattern were selectors are routed to an internal concrete type + case "MonoMac.Foundation": + case "Foundation": + switch (type.Name) { + // looks like it's routed to (private) NSConcreteUserNotificationCenter + case "NSUserNotificationCenter": + switch (selectorName) { + case "delegate": + case "setDelegate:": + case "scheduledNotifications": + case "setScheduledNotifications:": + case "deliveredNotifications": + return true; + } + break; + // looks like it's routed to (private) NSConcreteUserNotification + case "NSUserNotification": + switch (selectorName) { + case "title": + case "setTitle:": + case "subtitle": + case "setSubtitle:": + case "informativeText": + case "setInformativeText:": + case "actionButtonTitle": + case "setActionButtonTitle:": + case "userInfo": + case "setUserInfo:": + case "deliveryDate": + case "setDeliveryDate:": + case "deliveryTimeZone": + case "setDeliveryTimeZone:": + case "deliveryRepeatInterval": + case "setDeliveryRepeatInterval:": + case "actualDeliveryDate": + case "isPresented": + case "isRemote": + case "soundName": + case "setSoundName:": + case "hasActionButton": + case "setHasActionButton:": + case "activationType": + case "otherButtonTitle": + case "setOtherButtonTitle:": + return true; + } + break; + case "NSFileHandle": //Fails on Lion + case "NSUrlAuthenticationChallenge": + case "NSUrlCredential": + case "NSUrlProtectionSpace": + case "NSAppleEventDescriptor": + if (selectorName == "encodeWithCoder:" && !Mac.CheckSystemVersion (10, 8)) + return true; + break; + case "NSValue": + switch (selectorName) { + case "SCNMatrix4Value": + case "SCNVector3Value": + case "SCNVector4Value": + case "valueWithSCNMatrix4:": + if (IntPtr.Size != 8) + return true; + break; + } + break; + case "NSUrlSession": + switch (selectorName) { + case "delegateQueue": + case "sessionDescription": + case "setSessionDescription:": + case "delegate": + if (Mac.CheckSystemVersion (10, 11)) + return true; + break; + } + break; + case "NSUrlSessionStreamTask": + switch (selectorName) { + case "captureStreams": + case "closeRead": + case "closeWrite": + case "readDataOfMinLength:maxLength:timeout:completionHandler:": + case "startSecureConnection": + case "stopSecureConnection": + case "writeData:timeout:completionHandler:": + if (Mac.CheckSystemVersion (10, 11)) + return true; + break; + } + break; + case "NSUrlSessionTask": + switch (selectorName) { + case "countOfBytesExpectedToReceive": + case "countOfBytesExpectedToSend": + case "countOfBytesReceived": + case "countOfBytesSent": + case "currentRequest": + case "error": + case "originalRequest": + case "response": + case "state": + case "taskDescription": + case "setTaskDescription:": + case "taskIdentifier": + if (Mac.CheckSystemVersion (10, 11)) + return true; + break; + } + break; + case "NSUrlSessionConfiguration": + if (Mac.IsAtLeast (10, 11)) + return true; + break; + } + break; + case "MonoMac.AppKit": + case "AppKit": + switch (type.Name) { +#if !XAMCORE_3_0 // These should be not be marked [Abstract] but can't fix w/o breaking change... + case "NSScrollView": + case "NSTextView": + switch (selectorName) { + case "contentViewAtIndex:effectiveCharacterRange:": + case "didReplaceCharacters": + case "drawCharactersInRange:forContentView:": + case "rectsForCharacterRange:": + case "replaceCharactersInRange:withString:": + case "scrollRangeToVisible:": + case "shouldReplaceCharactersInRanges:withStrings:": + case "stringAtIndex:effectiveRange:endsWithSearchBoundary:": + case "stringLength": + case "allowsMultipleSelection": + case "isEditable": + case "firstSelectedRange": + case "isSelectable": + case "selectedRanges": + case "setSelectedRanges:": + case "string": + case "visibleCharacterRanges": + return true; + } + break; +#endif + case "NSMenuDelegate": + switch (selectorName) { +#if !XAMCORE_3_0 + case "menu:willHighlightItem:": + return true; // bound +#endif + } + break; + case "NSResponder": + switch (selectorName) { + case "smartMagnifyWithEvent:": + case "quickLookWithEvent:": + if (!Mac.CheckSystemVersion (10, 8)) + return true; + break; + } + break; + case "NSViewController": + switch (selectorName) { + case "identifier": // + case "setIdentifier:": + // In Yosemite (but not before) NSViewController implements the NSUserInterfaceItemIdentification + // protocol (which brings a r/w Identifier property). We don't have any way of expressing that + // a type started implementing a protocol in a particular version, so just ignore these selectors. + if (!Mac.CheckSystemVersion (10, 10)) + return true; + break; + } + break; + } + break; + // GameKit seems to follow a pattern were selectors are routed to an internal concrete type + case "MonoMac.GameKit": + case "GameKit": + switch (type.Name) { + case "GKTurnBasedExchange": + switch (selectorName) { + case "completionDate": + case "data": + case "exchangeID": + case "sendDate": + case "timeoutDate": + return true; + } + break; + case "GKTurnBasedExchangeReply": + switch (selectorName) { + case "data": + case "replyDate": + return true; + } + break; + // looks like it's routed to (private) GKDialogController_Concrete + case "GKDialogController": + switch (selectorName) { + case "parentWindow": + case "setParentWindow:": + return true; + } + break; + // looks like it's routed to (private) GKVoiceChat_Concrete + case "GKVoiceChat": + switch (selectorName) { + case "start": + case "stop": + case "setMute:forPlayer:": + case "name": + case "isActive": + case "setActive:": + case "volume": + case "setVolume:": + case "playerStateUpdateHandler": + case "setPlayerStateUpdateHandler:": + case "playerIDs": + return true; + } + break; + // looks like it's routed to (private) GKLeaderboard_Concrete + case "GKLeaderboard": + switch (selectorName) { + case "loadScoresWithCompletionHandler:": + case "timeScope": + case "setTimeScope:": + case "playerScope": + case "setPlayerScope:": + case "maxRange": + case "category": + case "setCategory:": + case "title": + case "range": + case "setRange:": + case "scores": + case "localPlayerScore": + case "groupIdentifier": + case "setGroupIdentifier:": + return true; + } + break; + // looks like it's routed to (private) GKLeaderboard_Concrete + case "GKLocalPlayer": + switch (selectorName) { + case "authenticateWithCompletionHandler:": + case "loadDefaultLeaderboardCategoryIDWithCompletionHandler:": + case "setDefaultLeaderboardCategoryID:completionHandler:": + case "authenticateHandler": + case "setAuthenticateHandler:": + case "loadFriendsWithCompletionHandler:": + case "isAuthenticated": + return true; + } + break; + // looks like it's routed to (private) GKMatch_Concrete + case "GKMatch": + switch (selectorName) { + case "sendData:toPlayers:withDataMode:error:": + case "sendDataToAllPlayers:withDataMode:error:": + case "disconnect": + case "voiceChatWithName:": + case "playerIDs": + case "delegate": + case "setDelegate:": + case "expectedPlayerCount": + return true; + } + break; + // looks like it's routed to (private) GKMatchmater_Concrete + case "GKMatchmaker": + switch (selectorName) { + case "inviteHandler": + case "setInviteHandler:": + case "findMatchForRequest:withCompletionHandler:": + case "findPlayersForHostedMatchRequest:withCompletionHandler:": + case "addPlayersToMatch:matchRequest:completionHandler:": + case "cancel": + case "queryPlayerGroupActivity:withCompletionHandler:": + case "queryActivityWithCompletionHandler:": + return true; + } + break; + } + break; + // Gone in Mavericks + case "MonoMac.StoreKit": + case "StoreKit": + switch (type.Name) { + case "SKPayment": + case "SKMutablePayment": + switch (selectorName) { + case "paymentWithProductIdentifier:": + if (Mac.CheckSystemVersion (10, 9)) + return true; + break; + } + break; + } + break; + case "MonoMac.PdfKit": // Bug 20232 + case "PdfKit": + switch (type.Name) { + case "PdfBorder": // Fails on Lion + case "PdfAnnotation": + if (selectorName == "encodeWithCoder:" && !Mac.CheckSystemVersion (10, 8)) + return true; + break; + case "PdfView": + switch (selectorName) { +#if !XAMCORE_3_0 + case "menu:willHighlightItem:": + return true; +#endif + } + break; + } + break; + case "MonoMac.SceneKit": + case "SceneKit": + switch (type.Name) { + case "SCNGeometryElement": + // Ignore on 10.8 where SCNGeometryPrimitiveType is int (32), but + // on 10.9+ is NSInteger/nint (32/64). SceneKit is next to useless + // on 10.8 anyway. -abock + if (selectorName == "primitiveType" && Mac.CheckSystemVersion (10, 8)) + return true; + // fall through + goto case "SCNCamera"; + case "SCNCamera": + case "SCNGeometry": + case "SCNGeometrySource": + case "SCNLight": + case "SCNMaterial": + case "SCNMaterialProperty": + case "SCNNode": + case "SCNProgram": + case "SCNScene": + case "SCNMorpher": + case "SCNSkinner": + case "SCNConstraint": + case "SCNLevelOfDetail": + // The NSSecureCoding protocol was added to these types in Yosemite, + // and we can't (yet?) describe "type added protocol P in version X.Y" + // with our AvailabilityAttribute, so do this check manually. + if (selectorName == "encodeWithCoder:" && !Mac.CheckSystemVersion (10, 10)) + return true; + break; + } + + switch (type.Name) { + case "SCNGeometry": + // SCNGeometry added the SCNShadable protocol in 10.9, which brings in the 'program' selector. + switch (selectorName) { + case "program": + case "setProgram:": + if (!Mac.CheckSystemVersion (10, 9)) + return true; + break; + } + break; + } + break; + } + return base.Skip (type, selectorName); + } + + static List do_not_dispose = new List (); + + protected override void Dispose (NSObject obj, Type type) + { + switch (type.FullName) { + // FIXME: those crash the application when Dispose is called + case "MonoMac.AVFoundation.AVAudioRecorder": + case "AVFoundation.AVAudioRecorder": + case "MonoMac.Foundation.NSUrlConnection": + case "Foundation.NSUrlConnection": + + // 10.8: + case "MonoMac.Accounts.ACAccount": // maybe the default .ctor is not allowed ? + case "Accounts.ACAccount": + case "MonoMac.Accounts.ACAccountCredential": + case "Accounts.ACAccountCredential": + case "MonoMac.Accounts.ACAccountStore": + case "Accounts.ACAccountStore": + case "MonoMac.Accounts.ACAccountType": + case "Accounts.ACAccountType": + do_not_dispose.Add (obj); + break; + default: + base.Dispose (obj, type); + break; + } + } + + protected override bool CheckResponse (bool value, Type actualType, MethodBase method, ref string name) + { + var declaredType = method.DeclaringType; + + switch (name) { + // NSDraggingDestination protocol + case "concludeDragOperation:": // e.g. NSTokenField + case "draggingEnded:": // e.g. NSMatrix + case "draggingExited:": // e.g. NSTokenField + case "draggingUpdated:": // e.g. NSTokenField + case "performDragOperation:": // e.g. NSTokenField + case "prepareForDragOperation:": // e.g. NSTokenField + case "wantsPeriodicDraggingUpdates": // e.g. NSBrowser - optional, [DefaultValue(true)] if it does not exists + return true; + // NSDraggingSource + case "draggedImage:beganAt:": // e.g. NSTextView + case "draggedImage:endedAt:deposited:": // e.g. NSTableView + case "draggedImage:movedTo:": // e.g. NSCollectionView + case "ignoreModifierKeysWhileDragging": // e.g. NSTextView + case "namesOfPromisedFilesDroppedAtDestination:": // e.g. NSTextView + return true; + // NSAnimatablePropertyContainer + case "animationForKey:": // e.g. NSViewAnimation + case "animator": + case "animations": + case "setAnimations:": + return true; + // NSTypeSetter - Layout Phase Interface (needs to be overridden, not really part of the provided types) + case "willSetLineFragmentRect:forGlyphRange:usedRect:baselineOffset:": + case "shouldBreakLineByWordBeforeCharacterAtIndex:": + case "shouldBreakLineByHyphenatingBeforeCharacterAtIndex:": + case "hyphenationFactorForGlyphAtIndex:": + case "hyphenCharacterForGlyphAtIndex:": + case "boundingBoxForControlGlyphAtIndex:forTextContainer:proposedLineFragment:glyphPosition:characterIndex:": + return true; + // in NSView documentation but defined in NSClipView - no answers to call + case "scrollClipView:toPoint:": + return true; + // IKFilterBrowserPanel ??? not clear why + case "finish:": + return true; + // IKFilterUIView + case "viewForUIConfiguration:excludedKeys:": // [Target] on CIFilter + return true; + // NSDictionaryEnumerator + case "fileModificationDate": + case "fileType": + case "filePosixPermissions": + case "fileOwnerAccountName": + case "fileGroupOwnerAccountName": + case "fileSystemNumber": + case "fileSystemFileNumber": + case "fileExtensionHidden": + case "fileHFSCreatorCode": + case "fileHFSTypeCode": + case "fileIsImmutable": + case "fileIsAppendOnly": + case "fileCreationDate": + case "fileOwnerAccountID": + case "fileGroupOwnerAccountID": + return true; // all [Target] on NSDictionary + // SBObject + case "get": + return true; + + // NSCoder - documented as available in 10.8 + case "allowedClasses": + case "requiresSecureCoding": + return true; + + // NSFileManager + case "ubiquityIdentityToken": // documented in 10.8 + return true; + // NS[Mutable]UrlRequest + case "allowsCellularAccess": // documented in 10.8 + case "setAllowsCellularAccess:": // documented in 10.8 + return true; + // NSString + case "capitalizedStringWithLocale:": // documented in 10.8 + case "lowercaseStringWithLocale:": // documented in 10.8 + case "uppercaseStringWithLocale:": // documented in 10.8 + return true; + // AVVideoComposition + case "isValidForAsset:timeRange:validationDelegate:": // documented in 10.8 + return true; + // AVPlayer + case "setRate:time:atHostTime:": // 10.8+ + case "prerollAtRate:completionHandler:": // 10.8+ + case "cancelPendingPrerolls": // 10.8+ + case "masterClock": // 10.8+ + case "setMasterClock:": // 10.8+ + // NSDateComponents + case "isLeapMonth": // 10.8+ + case "setLeapMonth:": // 10.8+ + // NSFileCoordinator + case "itemAtURL:willMoveToURL:": // 10.8+ + return true; // documented (but does not respond) + + // MonoMac.CoreImage.CIDetector (10.8+) + case "featuresInImage:options:": + // MonoMac.CoreImage.CIFaceFeature (10.8+) + case "hasTrackingID": + case "trackingID": + case "hasTrackingFrameCount": + case "trackingFrameCount": + // MonoMac.CoreImage.CIImage : only in 10.8+ + case "properties": // only documented in header files + case "autoAdjustmentFilters": + case "autoAdjustmentFiltersWithOptions:": + // MonoMac.AVFoundation.AVAssetExportSession (10.8+) + case "asset": + // MonoMac.AVFoundation.AVAssetReaderOutput + case "alwaysCopiesSampleData": + case "setAlwaysCopiesSampleData:": + // MonoMac.AVFoundation.AVAssetTrack + case "isPlayable": + // MonoMac.AVFoundation.AVAudioPlayer (10.8+) + case "enableRate": + case "setEnableRate:": + case "rate": + case "setRate:": + // MonoMac.AVFoundation.AVMutableCompositionTrack + case "insertTimeRanges:ofTracks:atTime:error:": + // MonoMac.AVFoundation.AVPlayerItem + case "addOutput:": + case "removeOutput:": + case "canPlayFastReverse": + case "canPlayFastForward": + case "canPlaySlowForward": + case "canPlayReverse": + case "canPlaySlowReverse": + case "canStepForward": + case "canStepBackward": + case "outputs": + case "timebase": + // MonoMac.CoreAnimation.CAAnimation : only on OSX, added for SceneKit + case "usesSceneTimeBase": + case "setUsesSceneTimeBase:": + if (!Mac.CheckSystemVersion (10, 8)) + return true; + break; + case "initWithString:": + if (declaredType.Name == "NSTextStorage") + return true; + break; + } + + switch (declaredType.Name) { + case "NSUrlSession": + case "Foundation.NSUrlSession": + switch (name) { + case "delegateQueue": + case "sessionDescription": + case "setSessionDescription:": + case "delegate": + if (!Mac.CheckSystemVersion (10, 11)) + return true; + break; + } + break; + case "NSUrlSessionTask": + case "Foundation.NSUrlSessionTask": + switch (name) { + case "countOfBytesExpectedToReceive": + case "countOfBytesExpectedToSend": + case "countOfBytesReceived": + case "countOfBytesSent": + case "currentRequest": + case "error": + case "originalRequest": + case "response": + case "state": + case "taskDescription": + case "setTaskDescription:": + case "taskIdentifier": + case "priority": + case "setPriority:": + if (!Mac.CheckSystemVersion (10, 11)) + return true; + break; + } + break; + case "Foundation.NSUrlSessionStreamTask": + case "NSUrlSessionStreamTask": + switch (name) { + case "captureStreams": + case "closeRead": + case "closeWrite": + case "readDataOfMinLength:maxLength:timeout:completionHandler:": + case "startSecureConnection": + case "stopSecureConnection": + case "writeData:timeout:completionHandler:": + if (!Mac.CheckSystemVersion (10, 11)) + return true; + break; + } + break; + } + +// Console.WriteLine ("{0} {1}", declaredType, name); + return base.CheckResponse (value, actualType, method, ref name); + } + + protected override bool CheckStaticResponse (bool value, Type actualType, Type declaredType, ref string name) + { + switch (name) { + // 10.7 exceptions + + // NSAnimatablePropertyContainer protocol (10.7) -> NSViewAnimation + case "defaultAnimationForKey:": + return true; + + // 10.8 exceptions + + // GKPlayer - documented as available in 10.8 + case "loadPlayersForIdentifiers:withCompletionHandler:": + // SLRequest - documented as available in 10.8 + case "requestForServiceType:requestMethod:URL:parameters:": + // NSDictionary - documented as available in 10.8 + case "dictionaryWithSharedKeySet:": + case "sharedKeySetForKeys:": + // AVMetadataItem - documented as available in 10.8 + case "metadataItemsFromArray:filteredAndSortedAccordingToPreferredLanguages:": + return true; + } + return base.CheckStaticResponse (value, actualType, declaredType, ref name); + } + + protected override bool SkipInit (string selector, MethodBase m) + { + switch (selector) { +#if !XAMCORE_3_0 + // DomEvent + case "initEvent:canBubbleArg:cancelableArg:": + // DomOverflowEvent + case "initOverflowEvent:horizontalOverflow:verticalOverflow:": + // DomUIEvent + case "initUIEvent:canBubble:cancelable:view:detail:": + // DomKeyboardEvent + case "initKeyboardEvent:canBubble:cancelable:view:keyIdentifier:keyLocation:ctrlKey:altKey:shiftKey:metaKey:altGraphKey:": + case "initKeyboardEvent:canBubble:cancelable:view:keyIdentifier:keyLocation:ctrlKey:altKey:shiftKey:metaKey:": + // DomMouseEvent + case "initMouseEvent:canBubble:cancelable:view:detail:screenX:screenY:clientX:clientY:ctrlKey:altKey:shiftKey:metaKey:button:relatedTarget:": + // DomWheelEvent + case "initWheelEvent:wheelDeltaY:view:screenX:screenY:clientX:clientY:ctrlKey:altKey:shiftKey:metaKey:": + // QTMovie + case "movieWithTimeRange:error:": + case "initWithQuickTimeMedia:error:": + // NSAppleEventDescriptor + case "initListDescriptor": + case "initRecordDescriptor": + // NSAnimation + case "initWithDuration:animationCurve:": + return true; +#endif + // NSImage + case "initWithDataIgnoringOrientation:": + var mi = m as MethodInfo; + return mi != null && !mi.IsPublic && mi.ReturnType.Name == "IntPtr"; + default: + return base.SkipInit (selector, m); + } + } + } +} diff --git a/tests/introspection/Mac/MacApiSignatureTest.cs b/tests/introspection/Mac/MacApiSignatureTest.cs new file mode 100644 index 00000000000..32ba458e193 --- /dev/null +++ b/tests/introspection/Mac/MacApiSignatureTest.cs @@ -0,0 +1,234 @@ +// +// Test the generated API selectors against typos or non-existing cases +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012-2013 Xamarin Inc. All rights reserved. +// + +using System; +using System.Reflection; + +using NUnit.Framework; + +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +#else +using MonoMac.Foundation; +using MonoMac.ObjCRuntime; +#endif + +namespace Introspection { + + [TestFixture] + // we want the tests to be available because we use the linker + [Preserve (AllMembers = true)] + public class MacSignatureTest : ApiSignatureTest { + + static MacSignatureTest () + { + Runtime.RegisterAssembly (typeof (NSObject).Assembly); + } + + public MacSignatureTest () + { + ContinueOnFailure = true; + //LogProgress = true; + } + + protected override bool Skip (Type type, MethodBase method, string selector) + { + switch (type.Namespace) { + case "MonoMac.GameKit": + case "GameKit": + case "MonoMac.StoreKit": + case "StoreKit": + if (!Mac.CheckSystemVersion (10, 8)) + return true; + break; + case "MonoMac.SceneKit": + case "SceneKit": + // SceneKit is half-baked at best, and they broke compatibility significantly + // from Mountain Lion to Mavericks, so just ignore all problems there. + if (!Mac.CheckSystemVersion (10, 9)) + return true; + break; + } + + // Bug 20232 - This is a hack. + if (selector == "geometryElementWithData:primitiveType:primitiveCount:bytesPerIndex:") + return true; + + switch (type.Name) { + case "AVPlayerItemOutput": + case "AVPlayerItemVideoOutput": + case "NSSharingService": + case "NSSharingServicePicker": + case "NSUserNotification": + case "NSUserNotificationCenter": + case "NSUuid": + return !Mac.CheckSystemVersion (10, 8); + + case "CALayer": + case "CAEmitterLayer": + case "CAGradientLayer": + case "CAOpenGLLayer": + case "CAReplicatorLayer": + case "CAScrollLayer": + case "CAShapeLayer": + case "CATextLayer": + case "CATiledLayer": + case "CATransformLayer": + case "QTCaptureLayer": + case "QTMovieLayer": + case "QCCompositionLayer": + case "AVCaptureVideoPreviewLayer": + case "AVPlayerLayer": + case "SCNLayer": + switch (selector) { + // CAGradientLayer 'instance MonoMac.CoreAnimation.CAConstraint[] get_Constraints()' selector: constraints == @?@: + case "constraints": + // CAGradientLayer 'instance Void set_Constraints(MonoMac.CoreAnimation.CAConstraint[])' selector: setConstraints: == v@:@? + case "setConstraints:": + return true; + } + break; + case "SCNSkinner": + return !Mac.CheckSystemVersion (10, 9); + case "NSGradient": + switch (selector) { + case "initWithColorsAndLocations:": // variable length parameters ... + case "initWithColors:atLocations:colorSpace:": // void * -> nfloat [] (internal) + return true; + } + break; + case "AVAudioIONode": + case "AVAudioUnit": + switch (selector) { + case "audioUnit": // ^{ComponentInstanceRecord=[1l], tested to work in an apitest + return true; + } + break; + } + return base.Skip (type, method, selector); + } + + protected override int Size (Type t, bool simd = false) + { + switch (t.FullName) { + case "GameKit.GKGameCenterViewControllerState": + case "AppKit.NSOpenGLContextParameter": + // NSOpenGLContextParameter and GKGameCenterViewControllerState are anonymous enums in 10.9, but an NSInteger in 10.10. + if (IntPtr.Size == 8 && !Mac.CheckSystemVersion (10, 10)) + return 4; + break; + } + + return base.Size (t, simd); + } + + protected override bool IsValidStruct (Type type, string structName) + { + switch (structName) { + case "_NSPoint": +#if XAMCORE_2_0 + return type.FullName == "CoreGraphics.CGPoint"; +#else + return type.FullName == "System.Drawing.PointF"; +#endif + case "_NSRect": +#if XAMCORE_2_0 + return type.FullName == "CoreGraphics.CGRect"; +#else + return type.FullName == "System.Drawing.RectangleF"; +#endif + case "_NSSize": +#if XAMCORE_2_0 + return type.FullName == "CoreGraphics.CGSize"; +#else + return type.FullName == "System.Drawing.SizeF"; +#endif + case "_SCNVector3": + return type.Name == "SCNVector3"; + case "_SCNVector4": + return type.Name == "SCNVector4"; + // CIImage 'static MonoMac.CoreImage.CIImage FromImageBuffer(MonoMac.CoreVideo.CVImageBuffer)' selector: imageWithCVImageBuffer: == @12@0:4^{__CVBuffer=}8 + // AVAssetWriterInputPixelBufferAdaptor 'instance Boolean AppendPixelBufferWithPresentationTime(MonoMac.CoreVideo.CVPixelBuffer, CMTime)' selector: appendPixelBuffer:withPresentationTime: == c36@0:4^{__CVBuffer=}8{?=qiIq}12 + case "__CVBuffer": + return type.Name == "CVImageBuffer" || type.Name == "CVPixelBuffer";; + case "CATransform3D": + return type.Name == "CATransform3D" || type.Name == "SCNMatrix4"; + case "SCNVector4": + return type.Name == "SCNVector4" || type.Name == "SCNQuaternion"; // "SCNQuaternion is a SCNVector 3, then a nfloat, so same structure + } + return base.IsValidStruct (type, structName); + } + + // only handle exception here (to return true) otherwise call base to deal with it + protected override bool Check (string encodedType, Type type) + { + switch (encodedType) { + case "^{OpaqueSecTrustRef=}": + // On 10.7 and 10.8: + // [FAIL] Signature failure in MonoMac.Foundation.NSUrlCredential initWithTrust: Parameter 'trust' (#1) is encoded as '^{OpaqueSecTrustRef=}' and bound as 'MonoMac.Security.SecTrust' + return type.Name == "SecTrust" || type.FullName == "System.IntPtr"; + } + return base.Check (encodedType, type); + } + + // only handle exception here (to return true) otherwise call base to deal with it + // `caller` is provided to make it easier to detect "special" cases + protected override bool Check (char encodedType, Type type) + { + switch (encodedType) { + case 'i': + switch (type.FullName) { + case "System.nuint": + case "System.UInt32": + // sign-ness mis-binding, not critical + // Signature failure in MonoMac.AppKit.NSViewController presentViewController:asPopoverRelativeToRect:ofView:preferredEdge:behavior: Parameter 'preferredEdge' (#4) is encoded as 'i' and bound as 'System.UInt32' + return true; + case "GameKit.GKGameCenterViewControllerState": + case "AppKit.NSOpenGLContextParameter": + // NSOpenGLContextParameter and GKGameCenterViewControllerState are anonymous enums in 10.9, but an NSInteger in 10.10. + if (IntPtr.Size == 8 && !Mac.CheckSystemVersion (10, 10)) + return true; + break; + } + break; + // unsigned 32 bits + case 'I': + switch (type.FullName) { + case "System.Int32": + // sign-ness mis-binding, several of them (not critical) + // NSActionCell 'instance Int32 get_MnemonicLocation()' selector: mnemonicLocation == I8@0:4 + // NSPathCell 'instance Int32 get_MnemonicLocation()' selector: mnemonicLocation == I8@0:4 + // SCNText 'instance Void InsertMaterial(MonoMac.SceneKit.SCNMaterial, Int32)' selector: insertMaterial:atIndex: == v16@0:4@8I12 + return true; + } + break; + // unsigned 32 bits + case 'L': + switch (type.FullName) { + // sign-ness mis-binding (not critical) e.g. + // CAMediaTimingFunction 'instance Void GetControlPointAtIndex(Int32, IntPtr)' selector: getControlPointAtIndex:values: == v16@0:4L8[2f]12 + case "System.Int32": + return true; + } + break; + // unsigned 64 bits + case 'Q': + switch (type.FullName) { + // sign-ness mis-binding (not critical) e.g. + // NSEvent 'instance Int64 get_UniqueID()' selector: uniqueID == Q8@0:4 + case "System.Int64": + return true; + } + break; + } + return base.Check (encodedType, type); + } + } +} diff --git a/tests/introspection/Mac/MacApiWeakPropertyTest.cs b/tests/introspection/Mac/MacApiWeakPropertyTest.cs new file mode 100644 index 00000000000..904a20f0c0f --- /dev/null +++ b/tests/introspection/Mac/MacApiWeakPropertyTest.cs @@ -0,0 +1,26 @@ +using System; + +#if XAMCORE_2_0 +using Foundation; +#else +using MonoMac.Foundation; +#endif + +using NUnit.Framework; + +namespace Introspection { + + [TestFixture] + public class MacApiWeakPropertyTest : ApiWeakPropertyTest { + protected override bool Skip (Type type) + { + switch (type.Name) { + case "CATextLayer": // CATextLayer.WeakFont is done correctly by hand + return true; + case "NSAttributedStringDocumentAttributes": // NSAttributedStringDocumentAttributes.WeakDocumentType is done by hand, not a binding + return true; + } + return base.Skip (type); + } + } +} diff --git a/tests/introspection/Mac/MacCoreImageFiltersTest.cs b/tests/introspection/Mac/MacCoreImageFiltersTest.cs new file mode 100644 index 00000000000..caaa2755134 --- /dev/null +++ b/tests/introspection/Mac/MacCoreImageFiltersTest.cs @@ -0,0 +1,47 @@ +// +// Test the generated API for all Mac CoreImage filters +// +// Authors: +// Sebastien Pouliot +// Alex Soto +// +// Copyright 2013, 2015 Xamarin Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +using System; + +using NUnit.Framework; + +namespace Introspection { + + [TestFixture] + public class MacCoreImageFiltersTest : ApiCoreImageFiltersTest + { + protected override bool Skip (string nativeName) + { + switch (nativeName) { + case "CIMaskedVariableBlur": // Appears removed in 10.11 but not documented + if (Mac.CheckSystemVersion (10, 11)) + return true; + return false; + case "CICMYKHalftone": // Renamed as CICmykHalftone + return true; + default: + return base.Skip (nativeName); + } + } + } +} + diff --git a/tests/introspection/Mac/introspection-mac.csproj b/tests/introspection/Mac/introspection-mac.csproj new file mode 100644 index 00000000000..f940c1ce740 --- /dev/null +++ b/tests/introspection/Mac/introspection-mac.csproj @@ -0,0 +1,124 @@ + + + + Debug + x86 + {FD385098-B3FD-4331-92BF-CC1F918E3334} + {42C0BBD9-55CE-4FC1-8D90-A7348ABAFB23};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + dontlink + dontlink-mac + Resources + v4.5 + + + true + full + false + bin\x86\Debug + DEBUG;MONOMAC + prompt + 4 + false + false + Mac Developer + false + false + false + false + x86 + + + true + bin\x86\Release + MONOMAC + prompt + 4 + false + true + Developer ID Application + true + false + true + false + SdkOnly + x86 + + + + + + + + + + + + + + + + + + + + + ApiBaseTest.cs + + + ApiClassPtrTest.cs + + + ApiCoreImageFiltersTest.cs + + + ApiCtorInitTest.cs + + + ApiFieldTest.cs + + + ApiPInvokeTest.cs + + + ApiProtocolTest.cs + + + ApiSelectorTest.cs + + + ApiSignatureTest.cs + + + ApiStructTest.cs + + + ApiTypoTest.cs + + + ApiWeakPropertyTest.cs + + + CoreSelectorTest.cs + + + EnvironmentVariable.cs + + + PlatformInfo.cs + + + MacTestMain.cs + + + + + {D12F0F7B-8DE3-43EC-BA49-41052D065A9B} + GuiUnit_NET_4_5 + + + + + + + diff --git a/tests/introspection/PlatformInfo.cs b/tests/introspection/PlatformInfo.cs new file mode 100644 index 00000000000..f569f5f4b18 --- /dev/null +++ b/tests/introspection/PlatformInfo.cs @@ -0,0 +1,151 @@ +// +// PlatformInfo.cs: info about the host platform +// and AvailabilityBaseAttribute extensions for tests +// +// Author: +// Aaron Bockover +// +// Copyright 2015 Xamarin Inc. All rights reserved. + +using System; +using System.Linq; +using System.Reflection; +using System.Collections.Generic; + +#if XAMCORE_2_0 +using ObjCRuntime; +using Foundation; +#if !MONOMAC +using UIKit; +#endif +#elif MONOMAC +using MonoMac.ObjCRuntime; +using MonoMac.Foundation; +#else +using MonoTouch.ObjCRuntime; +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif + +namespace Introspection +{ + public sealed class PlatformInfo + { + static PlatformInfo GetHostPlatformInfo () + { + string name; + string version; +#if __TVOS__ || __IOS__ + name = UIDevice.CurrentDevice.SystemName; + version = UIDevice.CurrentDevice.SystemVersion; +#elif __WATCHOS__ + name = WatchKit.WKInterfaceDevice.CurrentDevice.SystemName; + version = WatchKit.WKInterfaceDevice.CurrentDevice.SystemVersion; +#elif MONOMAC + using (var plist = NSDictionary.FromFile ("/System/Library/CoreServices/SystemVersion.plist")) { + name = (NSString)plist ["ProductName"]; + version = (NSString)plist ["ProductVersion"]; + } +#else +#error Unknown platform +#endif + name = name?.Replace (" ", String.Empty)?.ToLowerInvariant (); + + var platformInfo = new PlatformInfo (); + + if (name != null && name.StartsWith ("mac", StringComparison.Ordinal)) + platformInfo.Name = PlatformName.MacOSX; + else if (name != null && (name.StartsWith ("ios", StringComparison.Ordinal) || name.StartsWith ("iphoneos", StringComparison.Ordinal))) + platformInfo.Name = PlatformName.iOS; + else if (name != null && name.StartsWith ("tvos", StringComparison.Ordinal)) + platformInfo.Name = PlatformName.TvOS; + else if (name != null && name.StartsWith ("watchos", StringComparison.Ordinal)) + platformInfo.Name = PlatformName.WatchOS; + else + throw new FormatException ($"Unknown product name: {name}"); + + platformInfo.Version = Version.Parse (version); + + if (IntPtr.Size == 4) + platformInfo.Architecture = PlatformArchitecture.Arch32; + else if (IntPtr.Size == 8) + platformInfo.Architecture = PlatformArchitecture.Arch64; + + return platformInfo; + } + + public static readonly PlatformInfo Host = GetHostPlatformInfo (); + + public PlatformName Name { get; private set; } + public PlatformArchitecture Architecture { get; private set; } + public Version Version { get; private set; } + + public bool IsMac => Name == PlatformName.MacOSX; + public bool IsIos => Name == PlatformName.iOS; + public bool IsArch32 => Architecture.HasFlag (PlatformArchitecture.Arch32); + public bool IsArch64 => Architecture.HasFlag (PlatformArchitecture.Arch64); + + PlatformInfo () + { + } + } + + public static class AvailabilityExtensions + { + public static bool IsAvailableOnHostPlatform (this ICustomAttributeProvider attributeProvider) + { + return attributeProvider.IsAvailable (PlatformInfo.Host); + } + + public static bool IsAvailable (this ICustomAttributeProvider attributeProvider, PlatformInfo targetPlatform) + { + return attributeProvider + .GetCustomAttributes (true) + .OfType () + .IsAvailable (targetPlatform); + } + + public static bool IsAvailableOnHostPlatform (this IEnumerable attributes) + { + return attributes.IsAvailable (PlatformInfo.Host); + } + + public static bool IsAvailable (this IEnumerable attributes, PlatformInfo targetPlatform) + { + // always "available" from a binding perspective if + // there are no explicit annotations saying otherwise + var available = true; + + foreach (var attr in attributes) { + if (attr.Platform != targetPlatform.Name) + continue; + + switch (attr.AvailabilityKind) { + case AvailabilityKind.Introduced: + if (attr.Version != null) + available &= targetPlatform.Version >= attr.Version; + + if (attr.Architecture != PlatformArchitecture.None && + attr.Architecture != PlatformArchitecture.All) + available &= attr.Architecture.HasFlag (targetPlatform.Architecture); + break; + case AvailabilityKind.Deprecated: + case AvailabilityKind.Obsoleted: + if (attr.Version != null) + available &= targetPlatform.Version < attr.Version; + // FIXME: handle architecture-level _un_availability? + // we didn't do this with the old AvailabilityAttribute... + break; + case AvailabilityKind.Unavailable: + available = false; + break; + } + + if (!available) + return false; + } + + return available; + } + } +} diff --git a/tests/introspection/iOS/AppDelegate.cs b/tests/introspection/iOS/AppDelegate.cs new file mode 100644 index 00000000000..b2067a32ef9 --- /dev/null +++ b/tests/introspection/iOS/AppDelegate.cs @@ -0,0 +1,40 @@ +#if !__WATCHOS__ +using System; +using System.Reflection; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif +using MonoTouch.NUnit.UI; + +namespace Introspection { + + [Register ("AppDelegate")] + public partial class AppDelegate : UIApplicationDelegate + { + static public TouchRunner Runner { get; private set; } + + public override UIWindow Window { get; set; } + + public override bool FinishedLaunching (UIApplication application, NSDictionary launchOptions) + { + // create a new window instance based on the screen size + Window = new UIWindow (UIScreen.MainScreen.Bounds); + Runner = new TouchRunner (Window); + + // tests can be inside the main assembly + Runner.Add (Assembly.GetExecutingAssembly ()); + + Window.RootViewController = new UINavigationController (Runner.GetViewController ()); + + // make the window visible + Window.MakeKeyAndVisible (); + + return true; + } + } +} +#endif // !__WATCHOS__ diff --git a/tests/introspection/iOS/Assets.xcassets/AppIcons.appiconset/Contents.json b/tests/introspection/iOS/Assets.xcassets/AppIcons.appiconset/Contents.json new file mode 100644 index 00000000000..6be52c8f764 --- /dev/null +++ b/tests/introspection/iOS/Assets.xcassets/AppIcons.appiconset/Contents.json @@ -0,0 +1,221 @@ +{ + "images": [ + { + "size": "29x29", + "scale": "1x", + "idiom": "iphone" + }, + { + "size": "29x29", + "scale": "2x", + "idiom": "iphone" + }, + { + "size": "29x29", + "scale": "3x", + "idiom": "iphone" + }, + { + "size": "40x40", + "scale": "2x", + "idiom": "iphone" + }, + { + "size": "40x40", + "scale": "3x", + "idiom": "iphone" + }, + { + "filename": "icon-app-57.png", + "size": "57x57", + "scale": "1x", + "idiom": "iphone" + }, + { + "filename": "icon-app-57@2x.png", + "size": "57x57", + "scale": "2x", + "idiom": "iphone" + }, + { + "filename": "icon-app-60@2x.png", + "size": "60x60", + "scale": "2x", + "idiom": "iphone" + }, + { + "filename": "icon-app-60@3x.png", + "size": "60x60", + "scale": "3x", + "idiom": "iphone" + }, + { + "size": "29x29", + "scale": "1x", + "idiom": "ipad" + }, + { + "size": "29x29", + "scale": "2x", + "idiom": "ipad" + }, + { + "size": "40x40", + "scale": "1x", + "idiom": "ipad" + }, + { + "size": "40x40", + "scale": "2x", + "idiom": "ipad" + }, + { + "size": "50x50", + "scale": "1x", + "idiom": "ipad" + }, + { + "size": "50x50", + "scale": "2x", + "idiom": "ipad" + }, + { + "filename": "icon-app-83.5@2x.png", + "size": "83.5x83.5", + "scale": "2x", + "idiom": "ipad" + }, + { + "filename": "icon-app-72.png", + "size": "72x72", + "scale": "1x", + "idiom": "ipad" + }, + { + "filename": "icon-app-72@2x.png", + "size": "72x72", + "scale": "2x", + "idiom": "ipad" + }, + { + "filename": "icon-app-76.png", + "size": "76x76", + "scale": "1x", + "idiom": "ipad" + }, + { + "filename": "icon-app-76@2x.png", + "size": "76x76", + "scale": "2x", + "idiom": "ipad" + }, + { + "role": "notificationCenter", + "size": "24x24", + "subtype": "38mm", + "scale": "2x", + "idiom": "watch" + }, + { + "role": "notificationCenter", + "size": "27.5x27.5", + "subtype": "42mm", + "scale": "2x", + "idiom": "watch" + }, + { + "role": "companionSettings", + "size": "29x29", + "scale": "2x", + "idiom": "watch" + }, + { + "role": "companionSettings", + "size": "29x29", + "scale": "3x", + "idiom": "watch" + }, + { + "role": "appLauncher", + "size": "40x40", + "subtype": "38mm", + "scale": "2x", + "idiom": "watch" + }, + { + "role": "longLook", + "size": "44x44", + "subtype": "42mm", + "scale": "2x", + "idiom": "watch" + }, + { + "role": "quickLook", + "size": "86x86", + "subtype": "38mm", + "scale": "2x", + "idiom": "watch" + }, + { + "role": "quickLook", + "size": "98x98", + "subtype": "42mm", + "scale": "2x", + "idiom": "watch" + }, + { + "size": "16x16", + "scale": "1x", + "idiom": "mac" + }, + { + "size": "16x16", + "scale": "2x", + "idiom": "mac" + }, + { + "size": "32x32", + "scale": "1x", + "idiom": "mac" + }, + { + "size": "32x32", + "scale": "2x", + "idiom": "mac" + }, + { + "size": "128x128", + "scale": "1x", + "idiom": "mac" + }, + { + "size": "128x128", + "scale": "2x", + "idiom": "mac" + }, + { + "size": "256x256", + "scale": "1x", + "idiom": "mac" + }, + { + "size": "256x256", + "scale": "2x", + "idiom": "mac" + }, + { + "size": "512x512", + "scale": "1x", + "idiom": "mac" + }, + { + "size": "512x512", + "scale": "2x", + "idiom": "mac" + } + ], + "info": { + "version": 1, + "author": "xcode" + } +} \ No newline at end of file diff --git a/tests/introspection/iOS/Assets.xcassets/AppIcons.appiconset/Icon-app-60@3x.png b/tests/introspection/iOS/Assets.xcassets/AppIcons.appiconset/Icon-app-60@3x.png new file mode 100644 index 00000000000..45342a7513b Binary files /dev/null and b/tests/introspection/iOS/Assets.xcassets/AppIcons.appiconset/Icon-app-60@3x.png differ diff --git a/tests/introspection/iOS/Assets.xcassets/AppIcons.appiconset/icon-app-57.png b/tests/introspection/iOS/Assets.xcassets/AppIcons.appiconset/icon-app-57.png new file mode 100644 index 00000000000..ce1d9df94d4 Binary files /dev/null and b/tests/introspection/iOS/Assets.xcassets/AppIcons.appiconset/icon-app-57.png differ diff --git a/tests/introspection/iOS/Assets.xcassets/AppIcons.appiconset/icon-app-57@2x.png b/tests/introspection/iOS/Assets.xcassets/AppIcons.appiconset/icon-app-57@2x.png new file mode 100644 index 00000000000..d34d9c694d3 Binary files /dev/null and b/tests/introspection/iOS/Assets.xcassets/AppIcons.appiconset/icon-app-57@2x.png differ diff --git a/tests/introspection/iOS/Assets.xcassets/AppIcons.appiconset/icon-app-60@2x.png b/tests/introspection/iOS/Assets.xcassets/AppIcons.appiconset/icon-app-60@2x.png new file mode 100644 index 00000000000..4409624b29d Binary files /dev/null and b/tests/introspection/iOS/Assets.xcassets/AppIcons.appiconset/icon-app-60@2x.png differ diff --git a/tests/introspection/iOS/Assets.xcassets/AppIcons.appiconset/icon-app-72.png b/tests/introspection/iOS/Assets.xcassets/AppIcons.appiconset/icon-app-72.png new file mode 100644 index 00000000000..9a77ea27731 Binary files /dev/null and b/tests/introspection/iOS/Assets.xcassets/AppIcons.appiconset/icon-app-72.png differ diff --git a/tests/introspection/iOS/Assets.xcassets/AppIcons.appiconset/icon-app-72@2x.png b/tests/introspection/iOS/Assets.xcassets/AppIcons.appiconset/icon-app-72@2x.png new file mode 100644 index 00000000000..32f57d7d89d Binary files /dev/null and b/tests/introspection/iOS/Assets.xcassets/AppIcons.appiconset/icon-app-72@2x.png differ diff --git a/tests/introspection/iOS/Assets.xcassets/AppIcons.appiconset/icon-app-76.png b/tests/introspection/iOS/Assets.xcassets/AppIcons.appiconset/icon-app-76.png new file mode 100644 index 00000000000..12db0c47cc4 Binary files /dev/null and b/tests/introspection/iOS/Assets.xcassets/AppIcons.appiconset/icon-app-76.png differ diff --git a/tests/introspection/iOS/Assets.xcassets/AppIcons.appiconset/icon-app-76@2x.png b/tests/introspection/iOS/Assets.xcassets/AppIcons.appiconset/icon-app-76@2x.png new file mode 100644 index 00000000000..163f1c7f0f1 Binary files /dev/null and b/tests/introspection/iOS/Assets.xcassets/AppIcons.appiconset/icon-app-76@2x.png differ diff --git a/tests/introspection/iOS/Assets.xcassets/AppIcons.appiconset/icon-app-83.5@2x.png b/tests/introspection/iOS/Assets.xcassets/AppIcons.appiconset/icon-app-83.5@2x.png new file mode 100644 index 00000000000..0bac1da399b Binary files /dev/null and b/tests/introspection/iOS/Assets.xcassets/AppIcons.appiconset/icon-app-83.5@2x.png differ diff --git a/tests/introspection/iOS/Info.plist b/tests/introspection/iOS/Info.plist new file mode 100644 index 00000000000..35d14405cb6 --- /dev/null +++ b/tests/introspection/iOS/Info.plist @@ -0,0 +1,29 @@ + + + + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + + MinimumOSVersion + 6.0 + CFBundleName + introspection + CFBundleIdentifier + com.xamarin.introspection + UIDeviceFamily + + 1 + 2 + + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1.0 + UILaunchStoryboardName + LaunchScreen + XSAppIconAssets + Assets.xcassets/AppIcons.appiconset + + diff --git a/tests/introspection/iOS/LaunchScreen.storyboard b/tests/introspection/iOS/LaunchScreen.storyboard new file mode 100644 index 00000000000..7981a14b773 --- /dev/null +++ b/tests/introspection/iOS/LaunchScreen.storyboard @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/introspection/iOS/Main.cs b/tests/introspection/iOS/Main.cs new file mode 100644 index 00000000000..12c5bdd9b38 --- /dev/null +++ b/tests/introspection/iOS/Main.cs @@ -0,0 +1,24 @@ +#if !__WATCHOS__ +using System; +#if XAMCORE_2_0 +using Foundation; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif + +namespace dontlink +{ + public class Application + { + // This is the main entry point of the application. + static void Main (string[] args) + { + // if you want to use a different Application Delegate class from "AppDelegate" + // you can specify it here. + UIApplication.Main (args, null, "AppDelegate"); + } + } +} +#endif // !__WATCHOS__ diff --git a/tests/introspection/iOS/iOSApiClassPtrTest.cs b/tests/introspection/iOS/iOSApiClassPtrTest.cs new file mode 100644 index 00000000000..09f31fafc17 --- /dev/null +++ b/tests/introspection/iOS/iOSApiClassPtrTest.cs @@ -0,0 +1,39 @@ +// +// Test fixture for class_ptr introspection tests +// +// Authors: +// Alex Soto +// +// Copyright 2012-2014 Xamarin Inc. +// +using System; +using System.Reflection; +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif +using NUnit.Framework; + +namespace Introspection { + [TestFixture] + [Preserve (AllMembers = true)] + public class iOSApiClassPtrTest : ApiClassPtrTest { + + protected override bool Skip (Type type) + { + // While the following types are categories and contains a class_ptr + // they are not used at all as extensions since they are just used to expose + // static properties. + switch (type.Name) { + case "NSUrlUtilities_NSCharacterSet": + case "AVAssetTrackTrackAssociation": + return true; + } + return base.Skip (type); + } + } +} + diff --git a/tests/introspection/iOS/iOSApiCtorInitTest.cs b/tests/introspection/iOS/iOSApiCtorInitTest.cs new file mode 100644 index 00000000000..f11dbbc40b9 --- /dev/null +++ b/tests/introspection/iOS/iOSApiCtorInitTest.cs @@ -0,0 +1,315 @@ +// +// Test the generated API `init` selectors are usable by developers +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012-2013 Xamarin Inc. All rights reserved. +// + +using System; +using System.Collections.Generic; +using System.Reflection; +#if XAMCORE_2_0 +#if !__TVOS__ +using PassKit; +#endif +using Foundation; +#if !__WATCHOS__ +using Metal; +#endif +using ObjCRuntime; +using UIKit; +#else +using MonoTouch.PassKit; +using MonoTouch.Foundation; +using MonoTouch.Metal; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +#endif + +using NUnit.Framework; + +namespace Introspection { + + [TestFixture] + // we want the tests to be available because we use the linker + [Preserve (AllMembers = true)] + public class iOSApiCtorInitTest : ApiCtorInitTest { + + public iOSApiCtorInitTest () + { + Class.ThrowOnInitFailure = false; + ContinueOnFailure = true; + //LogProgress = true; + } + + protected override bool Skip (Type type) + { + switch (type.Namespace) { + // all default ctor did not work and were replaced with [Obsolete("",true)] placeholders + // reflecting on those would create invalid instances (no handle) that crash the app + case "CoreBluetooth": + case "MonoTouch.CoreBluetooth": + return true; + + case "CoreAudioKit": + case "MonoTouch.CoreAudioKit": + case "Metal": + case "MonoTouch.Metal": + // they works with iOS9 beta 4 (but won't work on older simulators) + if ((Runtime.Arch == Arch.SIMULATOR) && !CheckiOSOrTVOSSystemVersion (9,0)) + return true; + break; +#if !__WATCHOS__ + case "MetalKit": + case "MonoTouch.MetalKit": + case "MetalPerformanceShaders": + case "MonoTouch.MetalPerformanceShaders": + if (Runtime.Arch == Arch.SIMULATOR) + return true; + // some devices don't support metal and that crash some API that does not check that, e.g. #33153 + if (!CheckiOSOrTVOSSystemVersion (9,0) || (MTLDevice.SystemDefault == null)) + return true; + break; +#endif // !__WATCHOS__ + } + + switch (type.Name) { + // under iOS7 creating this type will crash later (after test execution) with a stack similar to: + // https://gist.github.com/rolfbjarne/457f78e20c8c31edef5c + case "EKCalendarChooserDelegate": + case "EKEventEditViewController": + return true; + + // Objective-C exception thrown. Name: NSInternalInconsistencyException Reason: There can only be one UIApplication instance. + case "UIApplication": + return true; + // Objective-C exception thrown. Name: NSInvalidArgumentException Reason: UISplitViewController is only supported when running under UIUserInterfaceIdiomPad + case "UISplitViewController": +#if !__WATCHOS__ + // Objective-C exception thrown. Name: NSInternalInconsistencyException Reason: ADInterstitialAd is available on iPad only. + case "ADInterstitialAd": + return UIDevice.CurrentDevice.UserInterfaceIdiom == UIUserInterfaceIdiom.Phone; +#endif + + case "UIVideoEditorController": + return true; + // shows an alert on the simulator + case "MFMessageComposeViewController": + return true; + // shows an alert on the device (if no email address is configured) + case "MFMailComposeViewController": + return true; + +#if !__TVOS__ + // PassKit is not available on iPads + case "PKPassLibrary": + return !PKPassLibrary.IsAvailable; +#endif // !__TVOS__ + + + // default ctor started to throw on iOS7 - we should never have exposed it but, for API compatibility, + // we now have an "empty" obsolete ctor + case "UIFont": + return true; + + case "NSUrlSessionConfiguration": + case "NSUrlSession": + // This crashes when arc frees this object at the end of the scope: + // { NSURLSession *var = [[NSURLSession alloc] init]; } + return true; + + case "GKAchievementViewController": + case "GKLeaderboardViewController": + // technically available since 4.1 - however it got a new base class in 6.0 + // and that new base class GKGameCenterViewController did not exists before 6.0 + // which makes the type unusable in 5.x, ref: https://gist.github.com/spouliot/271b6230a3aa2b58bc6e + return !CheckiOSSystemVersion (6,0); + + // mistake - we should not have exposed those default ctor and now we must live with them + case "GCControllerElement": + case "GCControllerAxisInput": + case "GCControllerButtonInput": + case "GCControllerDirectionPad": + case "GCGamepad": + case "GCExtendedGamepad": + case "GCController": + return true; + + // default constructor are not working on iOS8 so we removed them + // and can't test them even in earlier iOS versions + case "JSManagedValue": + case "MKLocalSearch": + case "MKTileOverlayRenderer": + case "AVAssetResourceLoadingDataRequest": + case "CLBeaconRegion": + case "NSPersistentStoreCoordinator": + return true; + + // Metal is not available on the (iOS8) simulator + case "CAMetalLayer": + return (Runtime.Arch == Arch.SIMULATOR); + +#if !XAMCORE_2_0 + // from iOS8 (beta4) they do not return a valid handle + case "AVAssetResourceLoader": + case "AVAssetResourceLoadingRequest": + case "AVAssetResourceLoadingContentInformationRequest": + return true; + // Started with iOS8 on simulator (always) but it looks like it can happen on devices too + // NSInvalidArgumentException Use initWithAccessibilityContainer: + case "UIAccessibilityElement": + return CheckiOSSystemVersion (8,0); +#endif + // in 8.2 beta 1 this crash the app (simulator) without giving any details in the logs + case "WKUserNotificationInterfaceController": + return true; + + // Both reported in radar #21548819 + // NSUnknownKeyException [ valueForUndefinedKey:]: this class is not key value coding-compliant for the key inputPoint2. + case "CIDepthOfField": + // NSUnknownKeyException [ valueForUndefinedKey:]: this class is not key value coding-compliant for the key inputCropAmount. + case "CISunbeamsGenerator": + return true; + + case "MPMediaItemArtwork": + // NSInvalidArgumentException Reason: image must be non-nil + return true; + default: + return base.Skip (type); + } + } + + static List do_not_dispose = new List (); + + protected override void Dispose (NSObject obj, Type type) + { + switch (type.Name) { + // this crash the application after test completed their execution so we keep it alive + case "AVAudioRecorder": + case "AVCaptureConnection": + case "GKFriendRequestComposeViewController": + case "SKView": + // NSInvalidArgumentException *** -[__NSDictionaryM removeObjectForKey:]: key cannot be nil + case "SKTextureAtlas": + // fails under iOS5 with NSInvalidArgumentException Reason: -[__NSCFDictionary removeObjectForKey:]: attempt to remove nil key + case "NSBundle": + case "NSUrlConnection": // crash too (only on iOS5) + // iOS8 beta 5 -> SIGABRT (only on devices) + case "CABTMidiCentralViewController": + case "CABTMidiLocalPeripheralViewController": + do_not_dispose.Add (obj); + break; + // iOS 9 beta 1 - crash when disposed + case "MidiNetworkConnection": + case "WKNavigation": + case "CIImageAccumulator": + case "NEAppProxyTcpFlow": + case "NEAppProxyUdpFlow": + do_not_dispose.Add (obj); + break; + default: + base.Dispose (obj, type); + break; + } + } + + protected override void CheckHandle (NSObject obj) + { + bool result = obj.Handle != IntPtr.Zero; + if (!result) { + string name = obj.GetType ().Name; + switch (name) { + // FIXME: it's not clear what's the alternative to 'init' and it could be because I have no phone device + case "CTCallCenter": + case "CTTelephonyNetworkInfo": + return; + // to avoid crashes we do not really create (natively) default instances (iOS gives them to us) + // for compatibility purpose - we should never had included the default .ctor in monotouch.dll + case "CAMediaTimingFunction": + case "CLHeading": + case "CLRegion": + case "CLPlacemark": + case "CMAccelerometerData": + case "CMLogItem": + case "CMAttitude": + case "CMDeviceMotion": + case "CMGyroData": + case "CMMagnetometerData": + return; + // under iOS5 only - MPMediaPickerController: Unable to access iPod library. + case "MPMediaPickerController": + return; + // re-enabled as an [Obsolete ("", true)] but it will crash if we create it (which we can since we use reflection) + case "NSTimer": + case "NSCompoundPredicate": + return; + // iOS9 - the instance was "kind of valid" before + case "PKPaymentAuthorizationViewController": + if (CheckiOSSystemVersion (9,0)) + return; + break; + } + base.CheckHandle (obj); + } + } + + protected override void CheckToString (NSObject obj) + { + string name = obj.GetType ().Name; + switch (name) { + // crash at at MonoTouch.Foundation.NSObject.get_Description () [0x0000b] in /mono/ios/monotouch-ios7/monotouch/src/Foundation/NSObject.g.cs:500 + case "SKTexture": + case "MCSession": + // crash at at MonoTouch.Foundation.NSObject.get_Description () [0x0000b] in /Developer/MonoTouch/Source/monotouch/src/Foundation/NSObject.g.cs:554 + case "AVPlayerItemTrack": + case "AVCaptureConnection": + return; + // worked before ios6.0 beta 1 + case "AVComposition": + // new API in iOS7 + case "AVAssetResourceLoadingDataRequest": + // Objective-C exception thrown. Name: NSInvalidArgumentException Reason: Unable to create description in descriptionForLayoutAttribute_layoutItem_coefficient. Something is nil + case "NSLayoutConstraint": + // new in 6.0 + case "AVAssetResourceLoadingRequest": + case "GKScoreChallenge": // Objective-C exception thrown. Name: NSInvalidArgumentException Reason: -[GKScoreChallenge challengeID]: unrecognized selector sent to instance 0x18acc340 + case "GKAchievementChallenge": // Objective-C exception thrown. Name: NSInvalidArgumentException Reason: -[GKAchievementChallenge challengeID]: unrecognized selector sent to instance 0x160f4840 + if (CheckiOSOrTVOSSystemVersion (6,0)) + return; + break; + // crash (when asking `description`) under iOS5 (only) simulator + case "NSUrlConnection": + return; + // iOS 9 beta 1 - crash when called + case "WKFrameInfo": + case "WKNavigation": + case "WKNavigationAction": + if (CheckiOSSystemVersion (9,0)) + return; + break; + default: + base.CheckToString (obj); + break; + } + } + + + protected override void CheckNSObjectProtocol (NSObject obj) + { + switch (obj.GetType ().Name) { + case "NSString": + // according to bots `isKindOf (null)` returns true before iOS 8, ref: #36726 + if (!CheckiOSOrTVOSSystemVersion (8, 0)) + return; + break; + } + base.CheckNSObjectProtocol (obj); + } + + // notes: + // * Splitview controller is expected to have a view controller at index 0 before it's used! + // this happens when we dispose an empty UISplitViewController, harmless + } +} diff --git a/tests/introspection/iOS/iOSApiFieldTest.cs b/tests/introspection/iOS/iOSApiFieldTest.cs new file mode 100644 index 00000000000..cd9eb9183ee --- /dev/null +++ b/tests/introspection/iOS/iOSApiFieldTest.cs @@ -0,0 +1,143 @@ +// +// Test the generated API fields (e.g. against typos or OSX-only values) +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012-2013 Xamarin Inc. All rights reserved. +// + +using System; +using System.Reflection; +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +using UIKit; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace Introspection { + + [TestFixture] + // we want the tests to be available because we use the linker + [Preserve (AllMembers = true)] + public class iOSApiFieldTest : ApiFieldTest { + + public iOSApiFieldTest () + { + ContinueOnFailure = true; + //LogProgress = true; + } + + protected override bool Skip (Type type) + { + return base.Skip (type); + } + + protected override bool Skip (PropertyInfo p) + { + switch (p.DeclaringType.Namespace) { + case "CoreAudioKit": + case "MonoTouch.CoreAudioKit": + case "Metal": + case "MonoTouch.Metal": + // they works with iOS9 beta 4 (but won't work on older simulators) + if ((Runtime.Arch == Arch.SIMULATOR) && !CheckiOSSystemVersion (9,0)) + return true; + break; + case "MetalKit": + case "MonoTouch.MetalKit": + case "MetalPerformanceShaders": + case "MonoTouch.MetalPerformanceShaders": + if (Runtime.Arch == Arch.SIMULATOR) + return true; + break; + } + + switch (p.Name) { + case "AutoConfigurationHTTPResponseKey": // kCFProxyAutoConfigurationHTTPResponseKey + case "CFNetworkProxiesProxyAutoConfigJavaScript": // kCFNetworkProxiesProxyAutoConfigJavaScript + return true; + + // defined in Apple PDF (online) but not in the HTML documentation + // but also inside CLError.h from iOS 5.1 SDK... + case "ErrorUserInfoAlternateRegionKey": // kCLErrorUserInfoAlternateRegionKey + return true; + + // documented since iOS 4.0 - but the symbols are not in the libraries (see specific unit tests) + case "MakerMinoltaDictionary": // kCGImagePropertyMakerMinoltaDictionary + case "MakerFujiDictionary": // kCGImagePropertyMakerFujiDictionary + case "MakerOlympusDictionary": // kCGImagePropertyMakerOlympusDictionary + case "MakerPentaxDictionary": // kCGImagePropertyMakerPentaxDictionary + return true; + + // ImageIO: documented since iOS 4.3 but null in iOS5 (works on iOS 6.1) + // https://developer.apple.com/library/ios/releasenotes/General/iOS43APIDiffs/ + case "ExifCameraOwnerName": + case "ExifBodySerialNumber": + case "ExifLensSpecification": + case "ExifLensMake": + case "ExifLensModel": + case "ExifLensSerialNumber": + return !CheckiOSOrTVOSSystemVersion (6,1); + + // ImageIO: new in iOS 8 but returns nil (at least in beta 1) seems fixed in iOS9 + case "PNGLoopCount": + case "PNGDelayTime": + case "PNGUnclampedDelayTime": + return !CheckiOSOrTVOSSystemVersion (9,0); + + // CoreServices.CFHTTPMessage - document in 10.9 but returns null + case "_AuthenticationSchemeOAuth1": + return true; + + // Apple does not ship a PushKit for every arch on some devices :( + case "Voip": + return Runtime.Arch == Arch.DEVICE; + + default: + return base.Skip (p); + } + } + + protected override bool Skip (string constantName) + { + switch (constantName) { + // grep ImageIO binary shows those symbols are not part of the binary + // that match older results (nil) when loading them (see above) + case "kCGImagePropertyAPNGLoopCount": + case "kCGImagePropertyAPNGDelayTime": + case "kCGImagePropertyAPNGUnclampedDelayTime": + case "kCGImagePropertyMakerFujiDictionary": + case "kCGImagePropertyMakerMinoltaDictionary": + case "kCGImagePropertyMakerOlympusDictionary": + case "kCGImagePropertyMakerPentaxDictionary": + // + case "kCFHTTPAuthenticationSchemeOAuth1": + return true; + // Apple does not ship a PushKit for every arch on some devices :( + case "PKPushTypeVoIP": + return Runtime.Arch == Arch.DEVICE; + // there's only partial support for metal on the simulator (on iOS9 beta 5) but most other frameworks + // that interop with it are not (yet) supported + case "kCVMetalTextureCacheMaximumTextureAgeKey": + case "MPSRectNoClip": + case "MTKTextureLoaderErrorDomain": + case "MTKTextureLoaderErrorKey": + case "MTKTextureLoaderOptionAllocateMipmaps": + case "MTKTextureLoaderOptionSRGB": + case "MTKTextureLoaderOptionTextureUsage": + case "MTKTextureLoaderOptionTextureCPUCacheMode": + case "MTKModelErrorDomain": + case "MTKModelErrorKey": + return Runtime.Arch == Arch.SIMULATOR; + default: + return false; + } + } + } +} \ No newline at end of file diff --git a/tests/introspection/iOS/iOSApiPInvokeTest.cs b/tests/introspection/iOS/iOSApiPInvokeTest.cs new file mode 100644 index 00000000000..724f04cb5fa --- /dev/null +++ b/tests/introspection/iOS/iOSApiPInvokeTest.cs @@ -0,0 +1,99 @@ +// +// Test the existing of p/invoked symbols +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2014-2015 Xamarin Inc. All rights reserved. +// + +using System; +using System.Reflection; +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +using UIKit; +#else +using MonoTouch; +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +#endif +using NUnit.Framework; + +namespace Introspection { + + [TestFixture] + // we want the tests to be available because we use the linker + [Preserve (AllMembers = true)] + public class iOSApiPInvokeTest : ApiPInvokeTest { + + protected override bool Skip (string symbolName) + { + bool simulator = Runtime.Arch == Arch.SIMULATOR; + switch (symbolName) { + // Metal support inside simulator is only available in recent iOS9 SDK +#if !__WATCHOS__ + case "MTLCreateSystemDefaultDevice": + return simulator && !UIDevice.CurrentDevice.CheckSystemVersion (9, 0); +#endif + // still most Metal helpers are not available on the simulator (even when the framework is present, it's missing symbols) + case "MPSSupportsMTLDevice": + // neither are the CoreVideo extensions for Metal + case "CVMetalTextureGetTexture": + case "CVMetalTextureIsFlipped": + case "CVMetalTextureGetCleanTexCoords": + case "CVMetalTextureCacheCreate": + case "CVMetalTextureCacheFlush": + case "CVMetalTextureCacheCreateTextureFromImage": + case "MTKMetalVertexDescriptorFromModelIO": + case "MTKModelIOVertexDescriptorFromMetal": + case "MTKModelIOVertexFormatFromMetal": + case "MTKMetalVertexFormatFromModelIO": + return simulator; + + // it's not needed for ARM64 and Apple does not have stubs for them in libobjc.dylib + case "objc_msgSend_stret": + case "objc_msgSendSuper_stret": + return IntPtr.Size == 8 && !simulator; + + default: + return base.Skip (symbolName); + } + } + + protected override bool SkipAssembly (Assembly a) + { + // we only want to check this on a version of iOS that + // 1. is the current SDK target (or a newer one) +#if !__WATCHOS__ + var sdk = new Version (Constants.SdkVersion); + if (!UIDevice.CurrentDevice.CheckSystemVersion (sdk.Major, sdk.Minor)) + return true; +#endif + // 2. on the real target for Xamarin.iOS.dll/monotouch.dll + // as the simulator miss some libraries and symbols + // but the rest of the BCL is fine to test + return (a == typeof (NSObject).Assembly && (Runtime.Arch == Arch.SIMULATOR)); + } + + [Test] + public void NUnitLite () + { + var a = typeof (TestAttribute).Assembly; + if (!SkipAssembly (a)) + Check (a); + } + +#if !__WATCHOS__ + [Test] + public void MonoTouchDialog () + { + // there's no direct reference to MTD - but it's there + var a = AppDelegate.Runner.NavigationController.TopViewController.GetType ().Assembly; + if (!SkipAssembly (a)) + Check (a); + } +#endif + } +} \ No newline at end of file diff --git a/tests/introspection/iOS/iOSApiProtocolTest.cs b/tests/introspection/iOS/iOSApiProtocolTest.cs new file mode 100644 index 00000000000..3b71c8b2f64 --- /dev/null +++ b/tests/introspection/iOS/iOSApiProtocolTest.cs @@ -0,0 +1,286 @@ +// +// Test the generated API for common protocol support +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013-2015 Xamarin Inc. +// + +using System; +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +using UIKit; +#if !__TVOS__ +using WatchConnectivity; +#endif +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +using MonoTouch.WatchConnectivity; +#endif +using NUnit.Framework; + +namespace Introspection { + + [TestFixture] + // we want the tests to be available because we use the linker + [Preserve (AllMembers = true)] + public class iOSApiProtocolTest : ApiProtocolTest { + + public iOSApiProtocolTest () + { + ContinueOnFailure = true; + // LogProgress = true; + } + + protected override bool Skip (Type type) + { + switch (type.Namespace) { + case "MetalKit": + case "MonoTouch.MetalKit": + case "MetalPerformanceShaders": + case "MonoTouch.MetalPerformanceShaders": + if (Runtime.Arch == Arch.SIMULATOR) + return true; + break; + } + + switch (type.Name) { + // Apple does not ship a PushKit for every arch on some devices :( + case "PKPushCredentials": + case "PKPushPayload": + case "PKPushRegistry": + if (Runtime.Arch != Arch.DEVICE) + return true; + + // Requires iOS 8.2 or later in 32-bit mode + if (!CheckiOSSystemVersion (8, 2) && IntPtr.Size == 4) + return true; + + break; + } + + return base.Skip (type); + } + + protected override bool Skip (Type type, string protocolName) + { + // some code cannot be run on the simulator (e.g. missing frameworks) + switch (type.Namespace) { + case "MonoTouch.Metal": + case "Metal": + case "MonoTouch.CoreAudioKit": + case "CoreAudioKit": + // they works with iOS9 beta 4 (but won't work on older simulators) + if ((Runtime.Arch == Arch.SIMULATOR) && !CheckiOSOrTVOSSystemVersion (9,0)) + return true; + break; + +#if !__TVOS__ + case "WatchConnectivity": + case "MonoTouch.WatchConnectivity": + if (!WCSession.IsSupported) + return true; + break; +#endif // !__TVOS__ + } + + switch (type.Name) { + case "CAMetalLayer": + // that one still does not work with iOS9 beta 4 + if (Runtime.Arch == Arch.SIMULATOR) + return true; + break; +#if !XAMCORE_3_0 + // mistake (base type) fixed by a breaking change + case "MFMailComposeViewControllerDelegate": + if (protocolName == "UINavigationControllerDelegate") + return true; + break; +#endif + // special case: the Delegate property is id so we made A subclass B in managed + // but this test see the conformance is not correct + case "UIImagePickerControllerDelegate": + case "UIVideoEditorControllerDelegate": + if (protocolName == "UINavigationControllerDelegate") + return true; + break; + } + + switch (protocolName) { + case "NSCoding": + switch (type.Name) { + case "GKPlayer": + case "GKLocalPlayer": + // NSSecureCoding is still undocumented, for iOS, and neither is NSCoding for OSX + // and it did not respond before 6.0 (when NSSecureCoding was introduced) + return !CheckiOSOrTVOSSystemVersion (6,0); + case "UITableViewDataSource": + // this is a *protocol( and we do not want to force people to conform to (an + // undocumented "requirement") NSCoding - as ObjC do not have to do this + return true; + // part of HomeKit are *privately* conforming to NSCoding + case "HMCharacteristic": + case "HMCharacteristicMetadata": + case "HMHome": + case "HMService": + case "HMAccessory": + case "HMActionSet": + case "HMCharacteristicWriteAction": + case "HMRoom": + case "HMServiceGroup": + case "HMTimerTrigger": + case "HMTrigger": + case "HMUser": + case "HMZone": + case "HMAccessoryCategory": + case "HMCharacteristicEvent": + case "HMEvent": + case "HMEventTrigger": + case "HMLocationEvent": + // new PassKit for payment also *privately* conforms to NSCoding + case "PKPayment": + case "PKPaymentSummaryItem": + case "PKShippingMethod": + case "PKPaymentRequest": + case "PKPaymentToken": + // iOS9 + case "UIFont": + case "AVAssetTrackSegment": + case "AVComposition": + case "AVMutableComposition": + case "AVCompositionTrackSegment": + case "MKMapSnapshotOptions": + case "WCSessionFile": + case "WCSessionFileTransfer": + return true; + } + break; + case "NSSecureCoding": + switch (type.Name) { + // part of HomeKit are *privately* conforming to NSSecureCoding + case "HMCharacteristic": + case "HMCharacteristicMetadata": + case "HMHome": + case "HMService": + case "HMAccessory": + case "HMActionSet": + case "HMCharacteristicWriteAction": + case "HMRoom": + case "HMServiceGroup": + case "HMTimerTrigger": + case "HMTrigger": + case "HMUser": + case "HMZone": + case "HMAccessoryCategory": + case "HMCharacteristicEvent": + case "HMEvent": + case "HMEventTrigger": + case "HMLocationEvent": + return true; + // new PassKit for payment also *privately* conforms to NSCoding + case "PKPayment": + case "PKPaymentSummaryItem": + case "PKShippingMethod": + case "PKPaymentRequest": + case "PKPaymentToken": + // iOS9 + case "UIFont": + case "AVAssetTrackSegment": + case "AVComposition": + case "AVMutableComposition": + case "AVCompositionTrackSegment": + case "MKMapSnapshotOptions": + case "NSTextTab": + case "WCSessionFile": + case "WCSessionFileTransfer": + return true; + } + break; + case "NSCopying": + switch (type.Name) { + // undocumented conformance (up to 7.0) and conformity varies between iOS versions + case "MKDirectionsRequest": + case "MPMediaItem": + case "MPMediaPlaylist": + case "MPMediaItemCollection": + case "MPMediaEntity": + return true; // skip + // new PassKit for payment also *privately* conforms to NSCoding + case "PKPaymentSummaryItem": + case "PKShippingMethod": + return true; // skip + // iOS9 + case "ACAccount": + case "HKCategorySample": + case "HKCorrelation": + case "HKObject": + case "HKQuantitySample": + case "HKSample": + case "HKWorkout": + return true; + } + break; + case "UIAccessibilityIdentification": + // UIView satisfy the contract - but return false for conformance (and so does all it's subclasses) + return true; + case "UIAppearance": + // we added UIAppearance to some types that do not conform to it + // note: removing them cause the *Appearance types to be removed too + switch (type.Name) { + case "ABPeoplePickerNavigationController": + case "EKEventEditViewController": + case "GKAchievementViewController": + case "GKFriendRequestComposeViewController": + case "GKLeaderboardViewController": + case "GKTurnBasedMatchmakerViewController": + case "MFMailComposeViewController": + case "MFMessageComposeViewController": + return true; + } + break; + case "UITextInputTraits": + // UISearchBar conformance fails before 7.1 - reference bug #33333 + if ((type.Name == "UISearchBar") && !CheckiOSOrTVOSSystemVersion (7,1)) + return true; + break; +#if !XAMCORE_3_0 + case "UINavigationControllerDelegate": + switch (type.Name) { + case "ABPeoplePickerNavigationControllerDelegate": // 37180 + return true; + } + break; +#endif + case "GKSavedGameListener": + switch (type.Name) { + case "GKLocalPlayerListener": // 37180 + return !CheckiOSOrTVOSSystemVersion (8, 0); + } + break; + } + return base.Skip (type, protocolName); + } + + [Test] + public override void SecureCoding () + { + if (!CheckiOSOrTVOSSystemVersion (6,0)) + Assert.Inconclusive ("Requires iOS 6+"); + + base.SecureCoding (); + } + + [Test] + public override void SupportsSecureCoding () + { + if (!CheckiOSOrTVOSSystemVersion (6,0)) + Assert.Inconclusive ("Requires iOS 6+"); + + base.SupportsSecureCoding (); + } + } +} diff --git a/tests/introspection/iOS/iOSApiSelectorTest.cs b/tests/introspection/iOS/iOSApiSelectorTest.cs new file mode 100644 index 00000000000..b7c57364261 --- /dev/null +++ b/tests/introspection/iOS/iOSApiSelectorTest.cs @@ -0,0 +1,608 @@ +// +// Test the generated API selectors against typos or non-existing cases +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2012-2013 Xamarin Inc. All rights reserved. +// + +using System; +using System.Collections.Generic; +using System.Reflection; +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +using UIKit; +#if !__TVOS__ +using WatchConnectivity; +#endif +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +using MonoTouch.WatchConnectivity; +#endif +using NUnit.Framework; + +namespace Introspection { + + [TestFixture] + // we want the tests to be available because we use the linker + [Preserve (AllMembers = true)] + public class iOSApiSelectorTest : CoreSelectorTest { + + public iOSApiSelectorTest () + { + ContinueOnFailure = true; + //LogProgress = true; + } + + protected override bool Skip (Type type) + { + switch (type.Namespace) { + // they don't answer on the simulator (Apple implementation does not work) but fine on devices + case "GameController": + case "MonoTouch.GameController": + return Runtime.Arch == Arch.SIMULATOR; + + case "CoreAudioKit": + case "MonoTouch.CoreAudioKit": + case "Metal": + case "MonoTouch.Metal": + // they works with iOS9 beta 4 (but won't work on older simulators) + if ((Runtime.Arch == Arch.SIMULATOR) && !CheckiOSOrTVOSSystemVersion (9,0)) + return true; + break; + case "MetalKit": + case "MonoTouch.MetalKit": + case "MetalPerformanceShaders": + case "MonoTouch.MetalPerformanceShaders": + if (Runtime.Arch == Arch.SIMULATOR) + return true; + break; + + // Apple does not ship a PushKit for every arch on some devices :( +// case "PushKit": +// case "MonoTouch.PushKit": +// if (Runtime.Arch == Arch.DEVICE) +// return true; +// break; +#if !__TVOS__ + case "WatchConnectivity": + case "MonoTouch.WatchConnectivity": + if (!WCSession.IsSupported) + return true; + break; +#endif // !__TVOS__ + } + + switch (type.Name) { + // abstract superclass + case "UIBarItem": + return true; + + // does not answer to anything ? + case "UILocalNotification": + return true; + + // Metal is not available on the (iOS8) simulator + case "CAMetalLayer": + return (Runtime.Arch == Arch.SIMULATOR); + + default: + return base.Skip (type); + } + } + + protected override bool CheckResponse (bool value, Type actualType, MethodBase method, ref string name) + { + if (value) + return true; + + var declaredType = method.DeclaringType; + + switch (declaredType.Name) { + case "NSUrlSession": + switch (name) { + case "delegateQueue": + case "sessionDescription": + case "setSessionDescription:": + case "delegate": + // does not respond anymore but the properties works (see monotouch-test) + if (CheckiOSOrTVOSSystemVersion (9, 0)) + return true; + break; + } + break; + case "NSUrlSessionTask": + switch (name) { + case "countOfBytesExpectedToReceive": + case "countOfBytesExpectedToSend": + case "countOfBytesReceived": + case "countOfBytesSent": + case "currentRequest": + case "error": + case "originalRequest": + case "response": + case "state": + case "taskDescription": + case "setTaskDescription:": + case "taskIdentifier": + // does not respond anymore but the properties works (see monotouch-test) + if (CheckiOSOrTVOSSystemVersion (9, 0)) + return true; + break; + } + break; + case "NSUrlSessionConfiguration": + case "NSUrlSessionStreamTask": + // does not respond anymore but the properties works (see monotouch-test for a partial list) + if (CheckiOSOrTVOSSystemVersion (9, 0)) + return true; + break; + + case "AVAssetDownloadTask": + switch (name) { + case "currentRequest": + case "originalRequest": + case "response": + if (CheckiOSOrTVOSSystemVersion (9, 0)) + return true; + break; + } + break; + case "CMSensorRecorder": + switch (name) { + // breaking change from Apple in iOS 9.3 betas + // https://trello.com/c/kqlEkPbG/30-24508290-cmsensorrecorder-breaking-change-re-opening-24231250 + // https://trello.com/c/pKLOLjVJ/29-24231250-coremotion-api-removal-without-deprecation + case "accelerometerDataFromDate:toDate:": + case "recordAccelerometerForDuration:": + if (!CheckiOSOrTVOSSystemVersion (9, 3)) + return true; + break; + } + break; + } + + switch (name) { + // UIResponderStandardEditActions - stuffed inside UIResponder + case "cut:": + case "copy:": + case "paste:": + case "delete:": + case "select:": + case "selectAll:": + // A subclass of UIResponder typically implements this method... + case "toggleBoldface:": + case "toggleItalics:": + case "toggleUnderline:": + if (declaredType.Name == "UIResponder") + return true; + break; + case "makeTextWritingDirectionLeftToRight:": + case "makeTextWritingDirectionRightToLeft:": + // MonoTouch.AddressBookUI.ABNewPersonViewController + // MonoTouch.AddressBookUI.ABPeoplePickerNavigationController + // MonoTouch.AddressBookUI.ABPersonViewController + if (declaredType.Name == "UIResponder") + return true; + break; +#if !XAMCORE_2_0 + case "enableInputClicksWhenVisible": + // defined in UIInputViewAudioFeedback protocol + // meant to be added (not part of iOS) in custom UIView and defined (by default) by MonoTouch + if (declaredType.Name == "UIView") + return true; + break; + case "subtitle": + // exists because of MKAnnotation protocol + if (declaredType.Name == "MKPlacemark") + return true; + break; + case "setCoordinate:": + // exists because of MKAnnotation protocol + if (declaredType.Name == "MKShape" || declaredType.Name == "MKPlacemark") + return true; + break; + case "intersectsMapRect:": + // optional method of a protocol MKTileOverlay implements. + if (declaredType.Name == "MKTileOverlay") + return true; + break; +#endif + case "autocapitalizationType": + case "setAutocapitalizationType:": + case "autocorrectionType": + case "setAutocorrectionType:": + case "keyboardType": + case "setKeyboardType:": + case "spellCheckingType": + case "setSpellCheckingType:": + // UITextInputTraits and UITextInputProtocol + if (declaredType.Name == "UITextField" || declaredType.Name == "UITextView") + return true; + if (CheckiOSOrTVOSSystemVersion (7,1) && declaredType.Name == "UISearchBar") + return true; + break; + case "keyboardAppearance": + case "setKeyboardAppearance:": + case "returnKeyType": + case "setReturnKeyType:": + case "enablesReturnKeyAutomatically": + case "setEnablesReturnKeyAutomatically:": + case "isSecureTextEntry": + case "setSecureTextEntry:": + // UITextInputTraits and UITextInput Protocol + switch (declaredType.Name) { + case "UITextField": + case "UITextView": + case "UISearchBar": + return true; + } + break; + case "textStylingAtPosition:inDirection:": + case "positionWithinRange:atCharacterOffset:": + case "characterOffsetOfPosition:withinRange:": + case "shouldChangeTextInRange:replacementText:": + // UITextInputTraits and UITextInputProtocol + if (declaredType.Name == "UITextField" || declaredType.Name == "UITextView") + return true; + // ignore UISearchBar before iOS8 - it did not really implement UITextInput + if (declaredType.Name == "UISearchBar" && !CheckiOSSystemVersion (8,0)) + return true; + break; + case "dictationRecognitionFailed": + case "dictationRecordingDidEnd": + case "insertDictationResult:": + // iOS 5.1 and not every device (or simulator) + if (declaredType.Name == "UITextField" || declaredType.Name == "UITextView") + return true; + break; + // special case: see http://developer.apple.com/library/ios/#documentation/GLkit/Reference/GLKViewController_ClassRef/Reference/Reference.html + case "update": + if (declaredType.Name == "GLKViewController") + return true; + break; + case "thumbnailImageAtTime:timeOption:": + case "requestThumbnailImagesAtTimes:timeOption:": + case "cancelAllThumbnailImageRequests": + case "accessLog": + case "errorLog": + case "timedMetadata": + if (declaredType.Name == "MPMoviePlayerController") + return true; + break; + // deprecated (removed in iOS 3.2) + case "backgroundColor": + case "setBackgroundColor:": + case "movieControlMode": + case "setMovieControlMode:": + if (declaredType.Name == "MPMoviePlayerController") + return true; + break; + case "skipToNextItem": + case "skipToBeginning": + case "skipToPreviousItem": + case "setNowPlayingItem:": + if (actualType.Name == "MPMusicPlayerController") + return true; + break; + // deprecated (according to docs) but actually removed (test) in iOS 6 + case "useApplicationAudioSession": + case "setUseApplicationAudioSession:": + if (declaredType.Name == "MPMoviePlayerController") + return CheckiOSSystemVersion (6,0); + break; + + // iOS6 - headers says readwrite but they do not respond + case "setUUID:": + case "setIsPrimary:": + if (declaredType.Name == "CBMutableService") + return CheckiOSSystemVersion (6, 0); + if (declaredType.Name == "CBMutableCharacteristic") + return CheckiOSSystemVersion (9, 0); + break; + + // documented since 4.0 - but does not answer on an iPad1 with 5.1.1 + case "isAdjustingFocus": + if (declaredType.Name == "AVCaptureDevice") + return true; + break; + + // GameKit: documented since 4.1 - but does not answer + case "alias": + if (declaredType.Name == "GKPlayer") + return true; + break; + case "playerID": + switch (declaredType.Name) { + case "GKPlayer": + case "GKScore": + case "GKTurnBasedParticipant": // iOS 5 + return true; + } + break; + case "category": + case "setCategory:": + case "date": + case "formattedValue": + case "rank": + case "value": + case "setValue:": + case "context": // iOS5 + case "setContext:": // iOS5 + if (declaredType.Name == "GKScore") + return true; + break; + case "isUnderage": + if (declaredType.Name == "GKLocalPlayer") + return true; + break; + case "identifier": + if (declaredType.Name == "GKAchievement" || declaredType.Name == "GKAchievementDescription") + return true; + break; + case "setIdentifier:": + case "percentComplete": + case "setPercentComplete:": + case "lastReportedDate": + case "setLastReportedDate:": + if (declaredType.Name == "GKAchievement") + return true; + break; + case "achievedDescription": + case "isHidden": + case "maximumPoints": + case "title": + case "unachievedDescription": + if (declaredType.Name == "GKAchievementDescription") + return true; + break; + // 5.0 + case "lastTurnDate": + case "matchOutcome": + case "setMatchOutcome:": + if (declaredType.Name == "GKTurnBasedParticipant") + return true; + break; + case "creationDate": + case "matchData": + case "message": + case "setMessage:": + if (declaredType.Name == "GKTurnBasedMatch") + return true; + break; + + // iOS6 - protocols for UICollectionView + case "numberOfSectionsInCollectionView:": + case "collectionView:viewForSupplementaryElementOfKind:atIndexPath:": + case "collectionView:shouldHighlightItemAtIndexPath:": + case "collectionView:didHighlightItemAtIndexPath:": + case "collectionView:didUnhighlightItemAtIndexPath:": + case "collectionView:shouldSelectItemAtIndexPath:": + case "collectionView:shouldDeselectItemAtIndexPath:": + case "collectionView:didSelectItemAtIndexPath:": + case "collectionView:didDeselectItemAtIndexPath:": + case "collectionView:didEndDisplayingCell:forItemAtIndexPath:": + case "collectionView:didEndDisplayingSupplementaryView:forElementOfKind:atIndexPath:": + case "collectionView:shouldShowMenuForItemAtIndexPath:": + case "collectionView:canPerformAction:forItemAtIndexPath:withSender:": + case "collectionView:performAction:forItemAtIndexPath:withSender:": + // which also inherits from UIScrollViewDelegate + case "scrollViewDidScroll:": + case "scrollViewWillBeginDragging:": + case "scrollViewDidEndDragging:willDecelerate:": + case "scrollViewWillBeginDecelerating:": + case "scrollViewDidEndDecelerating:": + case "scrollViewDidEndScrollingAnimation:": + case "viewForZoomingInScrollView:": + case "scrollViewShouldScrollToTop:": + case "scrollViewDidScrollToTop:": + case "scrollViewDidEndZooming:withView:atScale:": + case "scrollViewDidZoom:": + case "scrollViewWillBeginZooming:withView:": + case "scrollViewWillEndDragging:withVelocity:targetContentOffset:": + if (declaredType.Name == "UICollectionViewController") + return CheckiOSOrTVOSSystemVersion (6,0); + break; + + // failing (check why) + case "initialLayoutAttributesForInsertedItemAtIndexPath:": + case "initialLayoutAttributesForInsertedSupplementaryElementOfKind:atIndexPath:": + case "finalLayoutAttributesForDeletedItemAtIndexPath:": + case "finalLayoutAttributesForDeletedSupplementaryElementOfKind:atIndexPath:": + if (declaredType.Name == "UICollectionViewLayout") + return CheckiOSSystemVersion (6,0); + break; + + // This is implemented by internal concrete classes of NSFileHandle + case "readInBackgroundAndNotify": + case "readInBackgroundAndNotifyForModes:": + case "readToEndOfFileInBackgroundAndNotifyForModes:": + case "readToEndOfFileInBackgroundAndNotify": + case "acceptConnectionInBackgroundAndNotifyForModes:": + case "acceptConnectionInBackgroundAndNotify": + case "waitForDataInBackgroundAndNotifyForModes:": + case "waitForDataInBackgroundAndNotify": + if (declaredType.Name == "NSFileHandle") + return true; + break; + + // UITableViewController conforms to both UITableViewDelegate and UITableViewDataSource + case "tableView:canEditRowAtIndexPath:": + case "tableView:canMoveRowAtIndexPath:": + case "sectionIndexTitlesForTableView:": + case "tableView:sectionForSectionIndexTitle:atIndex:": + case "tableView:commitEditingStyle:forRowAtIndexPath:": + case "tableView:moveRowAtIndexPath:toIndexPath:": + case "tableView:willDisplayCell:forRowAtIndexPath:": + case "tableView:accessoryTypeForRowWithIndexPath:": + case "tableView:accessoryButtonTappedForRowWithIndexPath:": + case "tableView:willSelectRowAtIndexPath:": + case "tableView:willDeselectRowAtIndexPath:": + case "tableView:didSelectRowAtIndexPath:": + case "tableView:didDeselectRowAtIndexPath:": + case "tableView:editingStyleForRowAtIndexPath:": + case "tableView:titleForDeleteConfirmationButtonForRowAtIndexPath:": + case "tableView:shouldIndentWhileEditingRowAtIndexPath:": + case "tableView:targetIndexPathForMoveFromRowAtIndexPath:toProposedIndexPath:": + case "tableView:shouldShowMenuForRowAtIndexPath:": + case "tableView:canPerformAction:forRowAtIndexPath:withSender:": + case "tableView:performAction:forRowAtIndexPath:withSender:": + case "tableView:willDisplayHeaderView:forSection:": + case "tableView:willDisplayFooterView:forSection:": + case "tableView:didEndDisplayingCell:forRowAtIndexPath:": + case "tableView:didEndDisplayingHeaderView:forSection:": + case "tableView:didEndDisplayingFooterView:forSection:": + case "tableView:shouldHighlightRowAtIndexPath:": + case "tableView:didHighlightRowAtIndexPath:": + case "tableView:didUnhighlightRowAtIndexPath:": + // iOS7 + case "tableView:estimatedHeightForRowAtIndexPath:": + case "tableView:estimatedHeightForHeaderInSection:": + case "tableView:estimatedHeightForFooterInSection:": + // iOS 8 + case "tableView:editActionsForRowAtIndexPath:": + if (declaredType.Name == "UITableViewController") + return true; + break; + + // iOS7 beta issue ? remains in beta 5 / sim + // MCSession documents the cancelConnectPeer: selector but it does not answer + case "cancelConnectPeer:": + // CBCharacteristic documents the selector but does not respond + case "subscribedCentrals": + // UIPrintFormatter header attributedText says the API is not approved yet - and it does not respond + case "attributedText": + case "setAttributedText:": + // UISplitViewController + case "splitViewControllerSupportedInterfaceOrientations:": + case "splitViewControllerPreferredInterfaceOrientationForPresentation:": + return true; + + case "color": + case "setColor:": + case "font": + case "setFont:": + case "text": + case "setText:": + case "textAlignment": + case "setTextAlignment:": + // iOS7 GM a "no text" instance does not answer to the selector (but you can call them) + if (declaredType.Name == "UISimpleTextPrintFormatter") + return true; + break; + + case "copyWithZone:": + switch (declaredType.Name) { + // not conforming to NSCopying in 5.1 SDK + case "UIFont": + return !CheckiOSSystemVersion (6,0); + // not conforming to NSCopying before 7.0 SDK + case "CBPeripheral": + return !CheckiOSSystemVersion (7,0); + // not conforming to NSCopying before 8.0 SDK + case "AVMetadataFaceObject": + return !CheckiOSSystemVersion (8,0); + // not conforming to NSCopying before 8.2 SDK + case "HKUnit": + return !CheckiOSSystemVersion (8,2); + case "HKBiologicalSexObject": + case "HKBloodTypeObject": + return !CheckiOSSystemVersion (9,0); + } + break; + + // on iOS8.0 this does not work on the simulator (but works on devices) + case "language": + if (declaredType.Name == "AVSpeechSynthesisVoice" && CheckiOSSystemVersion (8,0) && Runtime.Arch == Arch.SIMULATOR) + return true; + break; + + // new, optional members of UIDynamicItem protocol in iOS9 + case "collisionBoundingPath": + case "collisionBoundsType": + switch (declaredType.Name) { + case "UICollectionViewLayoutAttributes": + case "UIView": + case "UIDynamicItemGroup": + return true; + } + break; + + // SceneKit integration with Metal is not working on simulators (at least for iOS9 beta 5) + case "currentRenderCommandEncoder": + case "colorPixelFormat": + case "commandQueue": + case "depthPixelFormat": + case "device": + case "stencilPixelFormat": + switch (declaredType.Name) { + case "SCNRenderer": + case "SCNView": + return Runtime.Arch == Arch.SIMULATOR; + } + break; + +#if XAMCORE_2_0 + // some types adopted NS[Secure]Coding after the type was added + // and for unified that's something we generate automatically (so we can't put [iOS] on them) + case "encodeWithCoder:": + switch (declaredType.Name) { + // UITextInputMode was added in 4.2 but conformed to NSSecureCoding only from 7.0+ + case "UITextInputMode": + return !CheckiOSSystemVersion (7,0); + // iOS9 + case "HKBiologicalSexObject": + case "HKBloodTypeObject": + return !CheckiOSSystemVersion (9,0); + } + break; +#else + // that was a binding mistake - the API should not have been exposed (not in the header file) + // we'll ignore them for compat - but won't provide them in the new assemblies + case "backgroundImageForBarMetrics:": + case "setBackgroundImage:forBarMetrics:": + if (declaredType.Name == "UISearchBar" && CheckiOSSystemVersion (8,0)) + return true; + break; +#endif + } + + return base.CheckResponse (value, actualType, method, ref name); + } + + protected override bool CheckStaticResponse (bool value, Type actualType, Type declaredType, ref string name) + { + switch (name) { + // new API in iOS9 beta 5 but is does not respond when queried - https://bugzilla.xamarin.com/show_bug.cgi?id=33431 + case "geometrySourceWithBuffer:vertexFormat:semantic:vertexCount:dataOffset:dataStride:": + switch (declaredType.Name) { + case "SCNGeometrySource": + return true; + } + break; + } + return base.CheckStaticResponse (value, actualType, declaredType, ref name); + } + + static List do_not_dispose = new List (); + + protected override void Dispose (NSObject obj, Type type) + { + switch (type.Name) { + // this crash the application after test completed their execution so we keep them alive + case "GKFriendRequestComposeViewController": + case "PKAddPassesViewController": + case "SKView": + do_not_dispose.Add (obj); + break; + default: + base.Dispose (obj, type); + break; + } + } + } +} \ No newline at end of file diff --git a/tests/introspection/iOS/iOSApiSignatureTest.cs b/tests/introspection/iOS/iOSApiSignatureTest.cs new file mode 100644 index 00000000000..d552c8baabf --- /dev/null +++ b/tests/introspection/iOS/iOSApiSignatureTest.cs @@ -0,0 +1,180 @@ +// +// iOS tests for the generated API selectors against typos or non-existing cases +// +// Authors: +// Sebastien Pouliot +// +// Copyright 2013 Xamarin Inc. All rights reserved. +// + +using System; +using System.Reflection; + +using NUnit.Framework; + +#if XAMCORE_2_0 +using ObjCRuntime; +using Foundation; +using UIKit; +#else +using MonoTouch.ObjCRuntime; +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif + +namespace Introspection { + + [TestFixture] + // we want the tests to be available because we use the linker + [Preserve (AllMembers = true)] + public class iOSApiSignatureTest : ApiSignatureTest { + + public iOSApiSignatureTest () + { + ContinueOnFailure = true; + //LogProgress = true; + } + + protected override int Size (Type t, bool simd = false) + { + switch (t.Name) { + // rdar 21375616 - Breaking change with EventKit[UI] enum base type + // EventKit.EK* enums are anonymous enums in 10.10 and iOS 8, but an NSInteger in 10.11 and iOS 9. + case "EKCalendarChooserSelectionStyle": + case "EKCalendarChooserDisplayStyle": + if (!IsOSX11OrIOS9) + return 4; + break; + } + return base.Size (t, simd); + } + + protected override bool Skip (Type type, MethodBase method, string selector) + { + switch (type.Name) { + case "UIAlertView": + // variable length parameters ... + if (selector == "initWithTitle:message:delegate:cancelButtonTitle:otherButtonTitles:") + return true; + break; + case "UIViewController": + switch (selector) { + // offically added in 6.0 - but retroactively supported in iOS5 (including documentation) + // the code works (see monotouch-test.app) but Apple changed their return value in 6.0 + // (they used to return `bool`) + case "beginAppearanceTransition:animated:": + case "endAppearanceTransition": + if (!CheckiOSOrTVOSSystemVersion (6,0)) + return true; + break; + } + break; + case "NKIssue": + // Apple "promoted" this to `NSInteger` in iOS8 but this already existed (as a 32bits value) in iOS 7.x + // sadly, and even with a bug report with a few exchanges, this was not fixed before iOS8 GM :-( + // 64bits application for iOS 7.x will be uncommon so we prefer to be forward compatible + if (selector == "status") + return !CheckiOSSystemVersion (8,0); + break; + case "CMMotionManager": + // iOS 8.3 changed CMMotionManager from 4 to 8 bytes on 64bits CPU and we have to follow that breaking + // change unless Apple revert that before final. [radar 20295259] + if ((IntPtr.Size == 4) || CheckiOSSystemVersion (8,3)) + return false; + // which means iOS 8.2 (and earlier can't match) + switch (selector) { + case "startDeviceMotionUpdatesUsingReferenceFrame:": + case "startDeviceMotionUpdatesUsingReferenceFrame:toQueue:withHandler:": + case "attitudeReferenceFrame": + return true; + default: + return false; + } + } + + return base.Skip (type, method, selector); + } + + protected override bool IsValidStruct (Type type, string structName) + { + switch (structName) { + // CIImage 'static MonoTouch.CoreImage.CIImage FromImageBuffer(MonoTouch.CoreVideo.CVPixelBuffer)' selector: imageWithCVPixelBuffer: == @12@0:4^{__CVBuffer=} + case "__CVBuffer": + return type.Name == "CVPixelBuffer" || type.Name == "CVImageBuffer"; + } + return base.IsValidStruct (type, structName); + } + + // only handle exception here (to return true) otherwise call base to deal with it + // `caller` is provided to make it easier to detect "special" cases + protected override bool Check (char encodedType, Type type) + { + // return an error if null (instead of throwing) so we can continue execution + if (type == null) + return false; + + switch (encodedType) { + case 'c': // char, used for C# bool +#if !XAMCORE_2_0 + switch (type.FullName) { + // looks like it returns a bool even if documented as a void + // UIPrintInteractionController 'instance Void Present(Boolean, MonoTouch.UIKit.UIPrintInteractionCompletionHandler)' selector: presentAnimated:completionHandler: + // update: documentation (and header) mistake that Apple corrected (IIRC I filled that issue) + case "System.Void": + return CurrentType.Name == "UIPrintInteractionController"; + } +#endif + break; + // float (32 bits) + case 'f': + switch (type.FullName) { + // documented (web and header file) as NSInteger + // UIImageView 'instance Void set_AnimationRepeatCount(Int32)' selector: setAnimationRepeatCount: == v12@0:4f8 + case "System.Int32": + return CurrentType.FullName == "MonoTouch.UIKit.UIImageView"; + } + break; + case 'i': + switch (type.FullName) { + case "MonoTouch.EventKitUI.EKCalendarChooserSelectionStyle": + case "MonoTouch.EventKitUI.EKCalendarChooserDisplayStyle": + case "EventKitUI.EKCalendarChooserSelectionStyle": + case "EventKitUI.EKCalendarChooserDisplayStyle": + return (IntPtr.Size == 4) || !IsOSX11OrIOS9; + case "System.UInt32": + // numberOfTouchesRequired was signed before iOS6, unsigned since then + return true; + } + break; + // unsigned 32 bits + case 'I': + switch (type.FullName) { + case "System.Int32": + // sign-ness mis-binding, several of them (not critical) + // CBATTRequest 'instance Int32 get_Offset()' selector: offset == I8@0:4 + return true; + } + break; + // unsigned 32 bits + case 'L': + switch (type.FullName) { + // sign-ness mis-binding (not critical) e.g. + // CAMediaTimingFunction 'instance Void GetControlPointAtIndex(Int32, IntPtr)' selector: getControlPointAtIndex:values: == v16@0:4L8[2f]12 + case "System.Int32": + return true; + } + break; + // unsigned 64 bits + case 'Q': + switch (type.FullName) { + // sign-ness mis-binding (not critical) e.g. + // NSIncrementalStoreNode 'instance Int64 get_Version()' selector: version == Q8@0:4 + case "System.Int64": + return true; + } + break; + } + return base.Check (encodedType, type); + } + } +} \ No newline at end of file diff --git a/tests/introspection/iOS/iOSApiTypoTest.cs b/tests/introspection/iOS/iOSApiTypoTest.cs new file mode 100644 index 00000000000..c4377e53e4e --- /dev/null +++ b/tests/introspection/iOS/iOSApiTypoTest.cs @@ -0,0 +1,55 @@ +using System; +using NUnit.Framework; + +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +using UIKit; +#else +using MonoTouch; +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouch.UIKit; +#endif + +namespace Introspection { + + [TestFixture] + public class iOSApiTypoTest : ApiTypoTest { +#if !__WATCHOS__ + UITextChecker checker = new UITextChecker (); +#endif + + [SetUp] + public void SetUp () + { +#if __WATCHOS__ + Assert.Fail ("Need to find alternative for UITextChecker on WatchOS."); +#else + // that's slow and there's no value to run it on devices as the API names + // being verified won't change from the simulator + if (Runtime.Arch == Arch.DEVICE) + Assert.Ignore ("Typos only detected on simulator"); + + // the dictionary used by iOS varies with versions and + // we don't want to maintain special cases for each version + var sdk = new Version (Constants.SdkVersion); + if (!UIDevice.CurrentDevice.CheckSystemVersion (sdk.Major, sdk.Minor)) + Assert.Ignore ("Typos only verified using the latest SDK"); +#endif + } + + public override string GetTypo (string txt) + { +#if __WATCHOS__ + return string.Empty; +#else + var checkRange = new NSRange (0, txt.Length); + var typoRange = checker.RangeOfMisspelledWordInString (txt, checkRange, checkRange.Location, false, "en_US"); + if (typoRange.Length == 0) + return String.Empty; + return txt.Substring ((int) typoRange.Location, (int) typoRange.Length); +#endif + } + } +} diff --git a/tests/introspection/iOS/iOSApiWeakPropertyTest.cs b/tests/introspection/iOS/iOSApiWeakPropertyTest.cs new file mode 100644 index 00000000000..2c2f3c84b84 --- /dev/null +++ b/tests/introspection/iOS/iOSApiWeakPropertyTest.cs @@ -0,0 +1,54 @@ +using System; +using System.Reflection; + +#if XAMCORE_2_0 +using Foundation; +#else +using MonoTouch.Foundation; +#endif + +using NUnit.Framework; + +namespace Introspection { + + [TestFixture] + // we want the tests to be available because we use the linker + [Preserve (AllMembers = true)] + public class iOSApiWeakPropertyTest : ApiWeakPropertyTest { + + public iOSApiWeakPropertyTest () + { + ContinueOnFailure = true; + } + + protected override bool Skip (PropertyInfo property) + { + switch (property.DeclaringType.Name) { + // WeakVideoGravity is an NSString that we could/should provide a better binding (e.g. enum) + case "AVPlayerViewController": + return property.Name == "WeakVideoGravity"; + // CATextLayer.WeakFont is done correctly by hand + case "CATextLayer": + return property.Name == "WeakFont"; + // NSAttributedStringDocumentAttributes is a DictionaryContainer that expose some Weak* NSDictionary + case "NSAttributedStringDocumentAttributes": + return property.Name == "WeakDocumentType" || property.Name == "WeakDefaultAttributes"; + // UIFontAttributes is a DictionaryContainer that expose a Weak* NSDictionary + case "UIFontAttributes": + return property.Name == "WeakFeatureSettings"; + // UIStringAttributes is a DictionaryContainer that expose a Weak* NSString + case "UIStringAttributes": + return property.Name == "WeakTextEffect"; +#if !XAMCORE_3_0 + // #37451 - setter does not exists but we have to keep it for binary compatibility + // OTOH we can't give it a selector (private API) even if we suspect Apple is mostly running `strings` on executable + case "IUIViewControllerPreviewing": + return property.Name == "WeakDelegate"; + case "UIViewControllerPreviewingWrapper": + return property.Name == "WeakDelegate"; +#endif + } + return base.Skip (property); + } + } +} \ No newline at end of file diff --git a/tests/introspection/iOS/iOSCoreImageFiltersTest.cs b/tests/introspection/iOS/iOSCoreImageFiltersTest.cs new file mode 100644 index 00000000000..dcaffc5ebf6 --- /dev/null +++ b/tests/introspection/iOS/iOSCoreImageFiltersTest.cs @@ -0,0 +1,36 @@ +// +// Test the generated API for all iOS CoreImage filters +// +// Authors: +// Sebastien Pouliot +// Alex Soto +// +// Copyright 2012-2013 Xamarin Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +using System.Reflection; +#if XAMCORE_2_0 +using CoreImage; +using Foundation; +using ObjCRuntime; +#else +using MonoTouch.CoreImage; +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif +using NUnit.Framework; + +namespace Introspection { + + [TestFixture] + // we want the tests to be available because we use the linker + [Preserve (AllMembers = true)] + public class iOSCoreImageFiltersTest : ApiCoreImageFiltersTest { + + + } +} +#endif // !__WATCHOS__ diff --git a/tests/introspection/iOS/introspection-ios.csproj b/tests/introspection/iOS/introspection-ios.csproj new file mode 100644 index 00000000000..974d78ac422 --- /dev/null +++ b/tests/introspection/iOS/introspection-ios.csproj @@ -0,0 +1,187 @@ + + + + Debug + iPhoneSimulator + 8.0.30703 + 2.0 + {208744BD-504E-47D7-9A98-1CF02454A6DA} + {6BC8ED88-2882-458C-8E55-DFD12B67127B};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + Introspection + introspection + MonoTouch + + + True + full + False + bin\iPhoneSimulator\Debug + DEBUG;MONOTOUCH + prompt + 4 + False + None + True + -v -v + + + i386 + iPhone Developer + + + none + False + bin\iPhoneSimulator\Release + prompt + 4 + False + None + -v -v -gcc_flags="-weak_framework GameController" + i386 + + + MONOTOUCH + + + True + full + False + bin\iPhone\Debug + DEBUG;MONOTOUCH + prompt + 4 + False + True + iPhone Developer + None + + + -v -v --registrar:static + ARMv7 + + + none + False + bin\iPhone\Release + prompt + 4 + False + iPhone Developer + -v -v + True + + + None + ARMv7 + MONOTOUCH + + + true + full + false + bin\iPhone\Debug + DEBUG;MONOTOUCH + prompt + 4 + false + ARMv7 + + + None + true + iPhone Developer + -v -v --registrar:static + + + + + + + + + + + + + + + + + + + + + ApiBaseTest.cs + + + ApiClassPtrTest.cs + + + ApiCMAttachmentTest.cs + + + ApiCoreImageFiltersTest.cs + + + ApiCtorInitTest.cs + + + ApiFieldTest.cs + + + ApiPInvokeTest.cs + + + ApiProtocolTest.cs + + + ApiSelectorTest.cs + + + ApiSignatureTest.cs + + + ApiStructTest.cs + + + ApiTypoTest.cs + + + ApiWeakPropertyTest.cs + + + CoreSelectorTest.cs + + + EnvironmentVariable.cs + + + PlatformInfo.cs + + + + + + + + + + + + + + + + + + + + + + + xamarin1.png + + + + diff --git a/tests/introspection/xamarin1.png b/tests/introspection/xamarin1.png new file mode 100644 index 00000000000..9874955dd09 Binary files /dev/null and b/tests/introspection/xamarin1.png differ