// // Link All [Regression] Tests // // Authors: // Sebastien Pouliot // // Copyright 2012-2016 Xamarin Inc. All rights reserved. // using System; using System.ComponentModel; using System.Globalization; using System.IO; using System.Linq; using System.Net; using System.Net.Security; using System.Reflection; using System.Security.Cryptography.X509Certificates; using MonoTouch; #if XAMCORE_2_0 using CoreGraphics; using Foundation; using ObjCRuntime; #if !__WATCHOS__ using StoreKit; #endif using UIKit; #else using MonoTouch.CoreGraphics; using MonoTouch.Foundation; using MonoTouch.ObjCRuntime; using MonoTouch.StoreKit; using MonoTouch.UIKit; #endif using NUnit.Framework; namespace LinkAll { // we DO NOT want the code to be "fully" available public partial class NotPreserved { public byte One { get; set; } [DefaultValue (2)] public int Two { get; set; } } // nothing directly uses Parent public class Parent { // but the nested type is a subclass of NSObject and gets preserved (as it's not part of monotouch.dll) public class Derived : NSObject { [Export ("foo")] public void Foo () {} } public void UnusedMethod () {} } [TestFixture] // we want the tests to be available because we use the linker [Preserve (AllMembers = true)] public class LinkAllRegressionTest { #if __IOS__ #if XAMCORE_2_0 public const string NamespacePrefix = ""; public const string AssemblyName = "Xamarin.iOS"; #else public const string NamespacePrefix = "MonoTouch."; public const string AssemblyName = "monotouch"; #endif #elif __TVOS__ public const string NamespacePrefix = ""; public const string AssemblyName = "Xamarin.TVOS"; #elif __WATCHOS__ public const string NamespacePrefix = ""; public const string AssemblyName = "Xamarin.WatchOS"; #else #error Unknown platform #endif class TypeAttribute : Attribute { public TypeAttribute (Type type) {} } [Type (null)] public void NullTypeInAttribute () { // there's no need to execute this test. // desk #68380. } [Test] public void GetterOnly () { // that ensure the getter is not linked away, // which means the property will be available for MEF_3862 NotPreserved np = new NotPreserved (); Assert.That (np.Two, Is.EqualTo (0), "Two==0"); PropertyInfo pi = typeof (NotPreserved).GetProperty ("Two"); // check the *unused* setter absence from the application Assert.NotNull (pi.GetGetMethod (), "getter"); Assert.Null (pi.GetSetMethod (), "setter"); } [Test] public void SetterOnly () { // that ensure the setter is not linked away, NotPreserved np = new NotPreserved (); np.One = 1; PropertyInfo pi = typeof (NotPreserved).GetProperty ("One"); // check the *unused* setter absence from the application Assert.Null (pi.GetGetMethod (), "getter"); Assert.NotNull (pi.GetSetMethod (), "setter"); } [Test] public void MEF_3862 () { // note: avoiding using "typeof(DefaultValueAttribute)" in the code // so the linker does not keep it just because of it PropertyInfo pi = typeof (NotPreserved).GetProperty ("Two"); object [] attrs = pi.GetCustomAttributes (false); bool default_value = false; foreach (var ca in attrs) { if (ca.GetType ().Name == "DefaultValueAttribute") { default_value = true; break; } } Assert.True (default_value, "DefaultValue"); } class TestPolicy : ICertificatePolicy { const int RecoverableTrustFailure = 5; // SecTrustResult public TestPolicy () { CheckCount = 0; } public int CheckCount { get; private set; } public bool CheckValidationResult (ServicePoint srvPoint, X509Certificate certificate, WebRequest request, int certificateProblem) { Assert.That (certificateProblem, Is.EqualTo (0), "certificateProblem"); CheckCount++; return true; } } static TestPolicy test_policy = new TestPolicy (); [Test] public void TrustUsingOldPolicy () { #if __WATCHOS__ Assert.Ignore ("WatchOS doesn't support BSD sockets, which our network stack currently requires."); #endif // Three similar tests exists in dontlink, linkall and linksdk to test 3 different cases // untrusted, custom ICertificatePolicy and ServerCertificateValidationCallback without // having caching issues (in S.Net or the SSL handshake cache) ICertificatePolicy old = ServicePointManager.CertificatePolicy; try { ServicePointManager.CertificatePolicy = test_policy; WebClient wc = new WebClient (); Assert.IsNotNull (wc.DownloadString ("https://wrench.internalx.com/Wrench/Login.aspx")); // caching means it will be called at least for the first run, but it might not // be called again in subsequent requests (unless it expires) Assert.That (test_policy.CheckCount, Is.GreaterThan (0), "policy checked"); } finally { ServicePointManager.CertificatePolicy = old; } } [Test] public void DetectPlatform () { #if !__WATCHOS__ // for (future) nunit[lite] platform detection - if this test fails then platform detection won't work Assert.NotNull (Type.GetType (NamespacePrefix + "UIKit.UIApplicationDelegate, " + AssemblyName), "UIApplicationDelegate"); #endif // and you can trust the old trick with the linker Assert.NotNull (Type.GetType ("Mono.Runtime"), "Mono.Runtime"); } [Test] #if !XAMCORE_2_0 // internal (to be removed) in unified [Since (9,9)] #endif #if !XAMCORE_3_0 [Availability ()] [iOS (9,9)] [Mac (10, 99)] #endif [Introduced (PlatformName.None)] [Deprecated (PlatformName.None)] [Obsoleted (PlatformName.None)] [Unavailable (PlatformName.None)] [ThreadSafe] public void RemovedAttributes () { const string prefix = NamespacePrefix; const string suffix = ", " + AssemblyName; // since we're linking the attributes will NOT be available - even if they are used #if !XAMCORE_3_0 Assert.Null (Type.GetType (prefix + "ObjCRuntime.AvailabilityAttribute, " + suffix), "AvailabilityAttribute"); Assert.Null (Type.GetType (prefix + "ObjCRuntime.iOSAttribute, " + suffix), "AvailabilityAttribute"); Assert.Null (Type.GetType (prefix + "ObjCRuntime.AvailabilityAttribute, " + suffix), "AvailabilityAttribute"); Assert.Null (Type.GetType (prefix + "ObjCRuntime.SinceAttribute, " + suffix), "SinceAttribute"); #endif Assert.Null (Type.GetType (prefix + "ObjCRuntime.IntroducedAttribute, " + suffix), "IntroducedAttribute"); Assert.Null (Type.GetType (prefix + "ObjCRuntime.DeprecatedAttribute, " + suffix), "DeprecatedAttribute"); Assert.Null (Type.GetType (prefix + "ObjCRuntime.ObsoletedAttribute, " + suffix), "ObsoletedAttribute"); Assert.Null (Type.GetType (prefix + "ObjCRuntime.UnavailableAttribute, " + suffix), "UnavailableAttribute"); Assert.Null (Type.GetType (prefix + "ObjCRuntime.ThreadSafeAttribute, " + suffix), "ThreadSafeAttribute"); } [Test] public void Assembly_Load () { Assembly mscorlib = Assembly.Load ("mscorlib.dll"); Assert.NotNull (mscorlib, "mscorlib"); Assembly system = Assembly.Load ("System.dll"); Assert.NotNull (system, "System"); } [Test] public void Assembly_LoadFile () { string filename = Path.GetFileName (GetType ().Assembly.Location); try { Assert.NotNull (Assembly.LoadFile (filename), "1"); } catch (FileNotFoundException) { // 2nd chance since FAT 32/64 applications moved the assemblies (but that could prove an issue too) filename = Path.Combine (IntPtr.Size == 4 ? ".monotouch-32" : ".monotouch-64", filename); Assert.NotNull (Assembly.LoadFile (filename), "2"); } } [Test] public void Assembly_LoadFrom () { string filename = Path.GetFileName (GetType ().Assembly.Location); try { Assert.NotNull (Assembly.LoadFrom (filename), "1"); } catch (FileNotFoundException) { // 2nd chance since FAT 32/64 applications moved the assemblies (but that could prove an issue too) filename = Path.Combine (IntPtr.Size == 4 ? ".monotouch-32" : ".monotouch-64", filename); Assert.NotNull (Assembly.LoadFrom (filename), "2"); } } [Test] public void Assembly_ReflectionOnlyLoadFrom () { string filename = Path.GetFileName (GetType ().Assembly.Location); try { Assert.NotNull (Assembly.ReflectionOnlyLoadFrom (filename), "1"); } catch (FileNotFoundException) { // 2nd chance since FAT 32/64 applications moved the assemblies (but that could prove an issue too) filename = Path.Combine (IntPtr.Size == 4 ? ".monotouch-32" : ".monotouch-64", filename); Assert.NotNull (Assembly.ReflectionOnlyLoadFrom (filename), "2"); } } [Test] public void SystemDataSqlClient () { // notes: // * this test is mean to fail when building the application using a Community or Indie licenses // * linksdk.app references System.Data (assembly) but not types in SqlClient namespace using (var sc = new System.Data.SqlClient.SqlConnection ()) { Assert.NotNull (sc); } } #if !__TVOS__ && !__WATCHOS__ [Test] public void Pasteboard_ImagesTest () { string file = Path.Combine (NSBundle.MainBundle.ResourcePath, "basn3p08.png"); using (var dp = new CGDataProvider (file)) { using (var cgimg = CGImage.FromPNG (dp, null, false, CGColorRenderingIntent.Default)) { using (var img = new UIImage (cgimg)) { UIPasteboard.General.Images = new UIImage[] { img }; Assert.AreEqual (1, UIPasteboard.General.Images.Length, "a - length"); UIPasteboard.General.Images = new UIImage[] { img, img }; Assert.AreEqual (2, UIPasteboard.General.Images.Length, "b - length"); Assert.IsNotNull (UIPasteboard.General.Images [0], "b - nonnull[0]"); Assert.IsNotNull (UIPasteboard.General.Images [1], "b - nonnull[0]"); } } } } #endif // !__TVOS__ [Test] public void UltimateBindings () { Assert.IsNotNull (Bindings.Test.UltimateMachine.SharedInstance, "SharedInstance"); } #region bug 14456 [TypeConverter (typeof (TestEnumTypeConverter))] public enum TestEnum { One,Two } [Preserve (AllMembers = true)] public class TestEnumTypeConverter : System.ComponentModel.TypeConverter { public override object ConvertTo (ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) { return "hello"; } } [Test] public void Bug14456 () { var tc = TypeDescriptor.GetConverter (typeof (TestEnum)); // not using Is.TypeOf since it would give additional clue to the linker Assert.That (tc.GetType ().Name, Is.EqualTo ("TestEnumTypeConverter"), "TestEnumTypeConverter"); // notes: // * without [Preserve (AllMembers = true)] -> MissingMethodException : Default constructor // * without [TypeConverter (typeof (TestEnumTypeConverter))] -> EnumConverter } #endregion [Test] public void SingleEpsilon_Compare () { if (Runtime.Arch == Arch.DEVICE) Assert.Ignore ("Known to fail on devices, see bug #15802"); // works on some ARM CPU (e.g. iPhone5S) but not others (iPad4 or iPodTouch5) Assert.That (Single.Epsilon, Is.Not.EqualTo (0f), "Epsilon"); Assert.That (-Single.Epsilon, Is.Not.EqualTo (0f), "-Epsilon"); } [Test] public void SingleEpsilon_ToString () { if (Runtime.Arch == Arch.DEVICE) Assert.Ignore ("Known to fail on devices, see bug #15802"); var ci = CultureInfo.InvariantCulture; Assert.That (Single.Epsilon.ToString (ci), Is.EqualTo ("1.401298E-45"), "Epsilon.ToString()"); Assert.That ((-Single.Epsilon).ToString (ci), Is.EqualTo ("-1.401298E-45"), "-Epsilon.ToString()"); } [Test] public void DoubleEpsilon_Compare () { if (Runtime.Arch == Arch.DEVICE) Assert.Ignore ("Known to fail on devices, see bug #15802"); // works on some ARM CPU (e.g. iPhone5S) but not others (iPad4 or iPodTouch5) Assert.That (Double.Epsilon, Is.Not.EqualTo (0f), "Epsilon"); Assert.That (-Double.Epsilon, Is.Not.EqualTo (0f), "-Epsilon"); } [Test] public void DoubleEpsilon_ToString () { if (Runtime.Arch == Arch.DEVICE) Assert.Ignore ("Known to fail on devices, see bug #15802"); var ci = CultureInfo.InvariantCulture; // note: unlike Single this works on both my iPhone5S and iPodTouch5 Assert.That (Double.Epsilon.ToString (ci), Is.EqualTo ("4.94065645841247E-324"), "Epsilon.ToString()"); Assert.That ((-Double.Epsilon).ToString (ci), Is.EqualTo ("-4.94065645841247E-324"), "-Epsilon.ToString()"); } [Test] public void AssemblyReferences_16213 () { foreach (var assembly in typeof (System.Data.AcceptRejectRule).Assembly.GetReferencedAssemblies ()) { // Unlike the original bug report the unit tests uses Mono.Data.Tds so it will be part of the .app // so we check for System.Transactions which is not used (but referenced by the original System.Data) if (assembly.Name == "System.Transactions") Assert.Fail ("System.Transactions reference should have removed by the linker"); } } #if !__WATCHOS__ [Test] public void OpenTk10_Preserved () { // that will bring OpenTK-1.0 into the .app OpenTK.WindowState state = OpenTK.WindowState.Normal; var gl = Type.GetType ("OpenTK.Graphics.ES11.GL, OpenTK-1.0", false); Assert.NotNull (gl, "ES11/GL"); var core = Type.GetType ("OpenTK.Graphics.ES11.GL/Core, OpenTK-1.0", false); Assert.NotNull (core, "ES11/Core"); gl = Type.GetType ("OpenTK.Graphics.ES20.GL, OpenTK-1.0", false); Assert.NotNull (gl, "ES20/GL"); core = Type.GetType ("OpenTK.Graphics.ES20.GL/Core, OpenTK-1.0", false); Assert.NotNull (core, "ES20/Core"); } #endif // !__WATCHOS__ [Test] public void NestedNSObject () { // Parent type is not used - but it's not linked out var p = Type.GetType ("LinkAll.Parent"); Assert.NotNull (p, "Parent"); // because a nested type is a subclass of NSObject (and not part of monotouch.dll) var n = p.GetNestedType ("Derived"); Assert.NotNull (n, "Derived"); // however other stuff in Parent, like unused methods, will be removed Assert.Null (p.GetMethod ("UnusedMethod"), "unused method"); // while exported stuff will be present Assert.NotNull (n.GetMethod ("Foo"), "unused Export method"); } [Test] public void Bug20363 () { // testing compile time error CancelEventArgs cea = new CancelEventArgs (); Assert.NotNull (cea, "CancelEventArgs"); } string GetField (object o, string s) { var f = o.GetType ().GetField (s, BindingFlags.Instance | BindingFlags.NonPublic); if (f == null) return s; //Console.WriteLine (f.GetValue (o)); return null; } string FromPattern (string pattern, object o) { var s = GetField (o, ""); if (s != null) return s; s = GetField (o, ""); if (s != null) return s; return GetField (o, ""); } [Test] public void AnonymousType () { var result = FromPattern ("/{action}/{id}.{contentType}", new { action = "foo", id = 1234, contentType = "xml" }); Assert.Null (result, result); } #if !__WATCHOS__ [Test] public void Events () { using (var pr = new SKProductsRequest ()) { Assert.Null (pr.WeakDelegate, "none"); // event on SKProductsRequest itself pr.ReceivedResponse += (object sender, SKProductsRequestResponseEventArgs e) => {}; var t = pr.WeakDelegate.GetType (); Assert.That (t.Name, Is.EqualTo ("_SKProductsRequestDelegate"), "delegate"); var fi = t.GetField ("receivedResponse", BindingFlags.NonPublic | BindingFlags.Instance); Assert.NotNull (fi, "receivedResponse"); var value = fi.GetValue (pr.WeakDelegate); Assert.NotNull (value, "value"); #if XAMCORE_2_0 // and on the SKRequest defined one pr.RequestFailed += (object sender, SKRequestErrorEventArgs e) => {}; // and the existing (initial field) is still set fi = t.GetField ("receivedResponse", BindingFlags.NonPublic | BindingFlags.Instance); Assert.NotNull (fi, "receivedResponse/SKRequest"); #else // In Classic SKRequest also defines a RequestFailed event, so make sure we get the SKRequest one // that's because event are re-defined (new) in classic ((SKRequest) pr).RequestFailed += (object sender, SKRequestErrorEventArgs e) => {}; t = pr.WeakDelegate.GetType (); Assert.That (t.Name, Is.EqualTo ("_SKRequestDelegate"), "delegate-2"); fi = t.GetField ("receivedResponse", BindingFlags.NonPublic | BindingFlags.Instance); Assert.Null (fi, "receivedResponse/SKRequest"); #endif } } #endif // !__WATCHOS__ [Test] public void Aot_27116 () { var nix = (from nic in System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces () where nic.Id.StartsWith ("en") || nic.Id.StartsWith ("pdp_ip") select nic); Assert.NotNull (nix); } [Test] public void TlsProvider_Legacy () { var provider = Mono.Security.Interface.MonoTlsProviderFactory.GetProvider (); Assert.NotNull (provider, "provider"); Assert.That (provider.ID, Is.EqualTo (new Guid ("97d31751-d0b3-4707-99f7-a6456b972a19")), "correct provider"); } [Test] public void OldTlsProvider_Selected () { // make test work for classic (monotouch) and unified (iOS, tvOS and watchOS) var fqn = typeof (NSObject).AssemblyQualifiedName.Replace ("Foundation.NSObject", "Security.Tls.OldTlsProvider"); Assert.NotNull (Type.GetType (fqn), "Should be included"); } [Test] public void AppleTls_OptOut () { // make test work for classic (monotouch) and unified (iOS, tvOS and watchOS) var fqn = typeof (NSObject).AssemblyQualifiedName.Replace ("Foundation.NSObject", "Security.Tls.AppleTlsProvider"); Assert.Null (Type.GetType (fqn), "Should not be included"); } } }