394 строки
15 KiB
C#
394 строки
15 KiB
C#
//
|
|
// Test the generated API `init` selectors are usable by developers
|
|
//
|
|
// Authors:
|
|
// Sebastien Pouliot <sebastien@xamarin.com>
|
|
//
|
|
// 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) && !TestRuntime.CheckXcodeVersion (7, 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 (!TestRuntime.CheckXcodeVersion (7, 0) || (MTLDevice.SystemDefault == null))
|
|
return true;
|
|
break;
|
|
#endif // !__WATCHOS__
|
|
case "CoreNFC": // Only available on devices that support NFC, so check if NFCNDEFReaderSession is present.
|
|
if (Class.GetHandle ("NFCNDEFReaderSession") == IntPtr.Zero)
|
|
return true;
|
|
break;
|
|
case "DeviceCheck": // Only available on device
|
|
if (Runtime.Arch == Arch.SIMULATOR)
|
|
return true;
|
|
break;
|
|
}
|
|
|
|
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 !TestRuntime.CheckXcodeVersion (4, 5);
|
|
|
|
// 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 TestRuntime.CheckXcodeVersion (6, 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 [<CIDepthOfField 0x158586970> valueForUndefinedKey:]: this class is not key value coding-compliant for the key inputPoint2.
|
|
case "CIDepthOfField":
|
|
// NSUnknownKeyException [<CISunbeamsGenerator 0x1586d0810> 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;
|
|
|
|
// these work only on devices, so we skip the simulator
|
|
case "MTLHeapDescriptor":
|
|
case "MTLSharedEventListener":
|
|
return Runtime.Arch == Arch.SIMULATOR;
|
|
#if __WATCHOS__
|
|
// The following watchOS 3.2 Beta 2 types Fails, but they can be created we verified using an ObjC app, we will revisit before stable
|
|
case "INRequestPaymentIntent":
|
|
case "INRequestRideIntent":
|
|
case "INResumeWorkoutIntent":
|
|
case "INRideVehicle":
|
|
case "INSearchCallHistoryIntent":
|
|
case "INSearchForMessagesIntent":
|
|
case "INSearchForPhotosIntent":
|
|
case "INSendMessageIntent":
|
|
case "INSendPaymentIntent":
|
|
case "INStartAudioCallIntent":
|
|
case "INStartPhotoPlaybackIntent":
|
|
case "INStartWorkoutIntent":
|
|
return true;
|
|
#endif
|
|
// iOS 11 Beta 1
|
|
case "UICollectionViewFocusUpdateContext": // [Assert] -init is not a useful initializer for this class. Use one of the designated initializers instead
|
|
case "UIFocusUpdateContext": // [Assert] -init is not a useful initializer for this class. Use one of the designated initializers instead
|
|
case "EKCalendarItem": // Fails with NSInvalidArgumentException +[EKCalendarItem frozenClass]: unrecognized selector sent to class, will fill a radar
|
|
case "EKParticipant": // ctor disabled in XAMCORE_3_0
|
|
case "UITableViewFocusUpdateContext": // Objective-C exception thrown. Name: NSInternalInconsistencyException Reason: Invalid parameter not satisfying: focusSystem, will fill a radar
|
|
return true;
|
|
case "INBookRestaurantReservationIntentResponse": // iOS 11 beta 2: stack overflow in description. radar:32945914
|
|
return true;
|
|
case "IOSurface": // Only works on device
|
|
case "NEHotspotEapSettings": // Wireless Accessory Configuration is not supported in the simulator.
|
|
case "NEHotspotConfigurationManager":
|
|
case "NEHotspotHS20Settings":
|
|
return Runtime.Arch == Arch.SIMULATOR;
|
|
// iOS 12
|
|
case "INGetAvailableRestaurantReservationBookingDefaultsIntentResponse": // Objective-C exception thrown. Name: NSInternalInconsistencyException Reason: Unable to initialize 'INGetAvailableRestaurantReservationBookingDefaultsIntentResponse'. Please make sure that your intent definition file is valid.
|
|
case "INGetAvailableRestaurantReservationBookingsIntentResponse": // Objective-C exception thrown. Name: NSInternalInconsistencyException Reason: Unable to initialize 'INGetAvailableRestaurantReservationBookingsIntentResponse'. Please make sure that your intent definition file is valid.
|
|
case "INGetRestaurantGuestIntentResponse": // Objective-C exception thrown. Name: NSInternalInconsistencyException Reason: Unable to initialize 'INGetRestaurantGuestIntentResponse'. Please make sure that your intent definition file is valid.
|
|
return TestRuntime.CheckXcodeVersion (10,0);
|
|
case "CMMovementDisorderManager": // Not available in simulator, added info to radar://41110708
|
|
case "RPSystemBroadcastPickerView": // Symbol not available in simulator
|
|
return Runtime.Arch == Arch.SIMULATOR;
|
|
default:
|
|
return base.Skip (type);
|
|
}
|
|
}
|
|
|
|
static List<NSObject> do_not_dispose = new List<NSObject> ();
|
|
|
|
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;
|
|
// iOS 10 beta 1 - crash when disposed
|
|
case "CLBeacon":
|
|
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 (TestRuntime.CheckXcodeVersion (7, 0))
|
|
return;
|
|
break;
|
|
// iOS 12
|
|
case "CIAztecCodeGenerator":
|
|
case "CIBarcodeGenerator":
|
|
case "CICode128BarcodeGenerator":
|
|
case "CIPdf417BarcodeGenerator":
|
|
case "CIQRCodeGenerator":
|
|
if (TestRuntime.CheckXcodeVersion (10,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 (TestRuntime.CheckXcodeVersion (4, 5))
|
|
return;
|
|
break;
|
|
// iOS 9 beta 1 - crash when called
|
|
case "WKFrameInfo":
|
|
case "WKNavigation":
|
|
case "WKNavigationAction":
|
|
if (TestRuntime.CheckXcodeVersion (7, 0))
|
|
return;
|
|
break;
|
|
// new iOS 10 beta 1 - crash when calling `description` selector
|
|
case "AVAudioSessionDataSourceDescription":
|
|
case "AVAudioSessionPortDescription":
|
|
case "CLBeacon":
|
|
case "CLCircularRegion":
|
|
// beta 2
|
|
case "CTCallCenter":
|
|
// beta 3
|
|
case "CNContainer":
|
|
if (TestRuntime.CheckXcodeVersion (8, 0))
|
|
return;
|
|
break;
|
|
// Xcode 9 Beta 1 to avoid crashes
|
|
case "CIImageAccumulator":
|
|
if (TestRuntime.CheckXcodeVersion (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 (!TestRuntime.CheckXcodeVersion (6, 0))
|
|
return;
|
|
break;
|
|
}
|
|
base.CheckNSObjectProtocol (obj);
|
|
}
|
|
|
|
// notes:
|
|
// * Splitview controller <UISplitViewController: 0xda106e0> is expected to have a view controller at index 0 before it's used!
|
|
// this happens when we dispose an empty UISplitViewController, harmless
|
|
}
|
|
}
|