2016-05-05 03:14:32 +03:00
/ /
// Test the generated API `init` selectors are usable by the binding consumers
/ /
// Authors:
// Sebastien Pouliot <sebastien@xamarin.com>
/ /
// 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 ;
2017-11-28 23:29:05 +03:00
using System.Linq ;
using System.Text ;
2016-05-05 03:14:32 +03:00
using NUnit.Framework ;
2018-08-03 03:29:50 +03:00
#if __IOS__
using ARKit ;
#endif
2016-05-05 03:14:32 +03:00
#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 ;
/// <summary>
/// Gets or sets a value indicating whether this test fixture will log untested types.
/// </summary>
/// <value><c>true</c> if log untested types; otherwise, <c>false</c>.</value>
public bool LogUntestedTypes { get ; set ; }
/// <summary>
/// Override this method if you want the test to skip some specific types.
/// By default types decorated with [Model] will be skipped.
/// </summary>
/// <param name="type">The Type to be tested</param>
protected virtual bool Skip ( Type type )
{
if ( type . ContainsGenericParameters )
return true ;
2017-12-01 17:18:20 +03:00
#if ! XAMCORE_2_0
2016-05-05 03:14:32 +03:00
// 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 ;
}
2017-12-01 17:18:20 +03:00
#endif
2017-02-23 01:54:01 +03:00
2016-05-05 03:14:32 +03:00
switch ( type . Name ) {
2017-12-01 17:18:20 +03:00
case "JSExport" :
// This is interesting: Apple defines a private JSExport class - if you try to define your own in an Objective-C project you get this warning at startup:
// objc[334]: Class JSExport is implemented in both /Applications/Xcode91.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/System/Library/Frameworks/JavaScriptCore.framework/JavaScriptCore (0x112c1e430) and /Users/rolf/Library/Developer/CoreSimulator/Devices/AC5323CF-225F-44D9-AA18-A37B7C28CA68/data/Containers/Bundle/Application/DEF9EAFC-CB5C-454F-97F5-669BBD00A609/jsexporttest.app/jsexporttest (0x105b49df0). One of the two will be used. Which one is undefined.
// Due to how we treat models, we'll always look the Objective-C type up at runtime (even with the static registrar),
// see that there's an existing JSExport type, and use that one instead of creating a new type.
// This is problematic, because Apple's JSExport is completely unusable, and will crash if you try to do anything.
return true ;
2016-05-05 03:14:32 +03:00
#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 ;
2016-11-29 22:20:48 +03:00
case "NEPacketTunnelProvider" :
return true ;
2017-06-10 10:07:11 +03:00
case "NSUnitDispersion" : // -init should never be called on NSUnit!
case "NSUnitVolume" : // -init should never be called on NSUnit!
case "NSUnitDuration" : // -init should never be called on NSUnit!
case "NSUnitElectricCharge" : // -init should never be called on NSUnit!
case "NSUnitElectricCurrent" : // -init should never be called on NSUnit!
case "NSUnitElectricPotentialDifference" : // -init should never be called on NSUnit!
case "NSUnitElectricResistance" : // -init should never be called on NSUnit!
case "NSUnit" : // -init should never be called on NSUnit!
case "NSUnitEnergy" : // -init should never be called on NSUnit!
case "NSUnitAcceleration" : // -init should never be called on NSUnit!
case "NSUnitFrequency" : // -init should never be called on NSUnit!
case "NSUnitAngle" : // -init should never be called on NSUnit!
case "NSUnitFuelEfficiency" : // -init should never be called on NSUnit!
case "NSUnitArea" : // -init should never be called on NSUnit!
case "NSUnitIlluminance" : // -init should never be called on NSUnit!
case "NSUnitConcentrationMass" : // -init should never be called on NSUnit!
case "NSUnitLength" : // -init should never be called on NSUnit!
case "NSUnitMass" : // -init should never be called on NSUnit!
case "NSUnitPower" : // -init should never be called on NSUnit!
case "NSUnitPressure" : // -init should never be called on NSUnit!
case "NSUnitSpeed" : // -init should never be called on NSUnit!
return true ;
2017-11-28 23:29:05 +03:00
case "MPSCnnNeuron" : // Cannot directly initialize MPSCNNNeuron. Use one of the sub-classes of MPSCNNNeuron
case "MPSCnnNeuronPReLU" :
case "MPSCnnNeuronHardSigmoid" :
case "MPSCnnNeuronSoftPlus" :
return true ;
case "MPSCnnBinaryConvolution" : // [MPSCNNBinaryConvolution initWithDevice:] is not allowed. Please use initializers that are not marked NS_UNAVAILABLE.
case "MPSCnnDilatedPoolingMax" : // [MPSCNNDilatedPoolingMax initWithDevice:] is not allowed. Please use initializers that are not marked NS_UNAVAILABLE.
case "MPSCnnPoolingL2Norm" : // [MPSCNNPoolingL2Norm initWithDevice:] is not allowed. Please use initializers that are not marked NS_UNAVAILABLE.
return true ;
case "MPSCnnBinaryFullyConnected" : // Please initialize the MPSCNNBinaryFullyConnected class with initWithDevice:convolutionDescriptor:kernelWeights:biasTerms
return true ;
case "MPSCnnUpsampling" : // Cannot directly initialize MPSCNNUpsampling. Use one of the sub-classes of MPSCNNUpsampling
case "MPSCnnUpsamplingBilinear" :
case "MPSCnnUpsamplingNearest" :
return true ;
case "MPSImageArithmetic" : // Cannot directly initialize MPSImageArithmetic. Use one of the sub-classes of MPSImageArithmetic.
return true ;
Bump for Xcode 10.2 final (#5808)
* Bump for Xcode 10.2 final
* Bump macios-binaries so mlaunch works on 10.14.4
* [appkit] Update for Xcode 10.2 final
* [mps] Update for Xcode 10.2 final
* Bump maccore for swift5 runtime support on older macOS versions
* [AppKit] Ignore deprecated API
* [tests] Don't test QTMovie, it's broken (crashes).
QTKit is deprecated (and has been for 5 years), so just don't test QTMovie.
Fixes these crashes:
apitest:
***** DelegateAndDataSourceAllowsNull
Stacktrace:
at <unknown> <0xffffffff>
at (wrapper managed-to-native) ObjCRuntime.Messaging.IntPtr_objc_msgSend (intptr,intptr) [0x0000a] in <e8e733c9728c43cba731719f096ad306>:0
at QTKit.QTMovie..ctor () [0x00018] in /Library/Frameworks/Xamarin.Mac.framework/Versions/5.4.0.70/src/Xamarin.Mac/QTKit/QTMovie.g.cs:330
at (wrapper runtime-invoke) object.runtime_invoke_void__this__ (object,intptr,intptr,intptr) [0x0004f] in <3ad39e28642b49d2a535a565e6bf6837>:0
at <unknown> <0xffffffff>
at (wrapper managed-to-native) System.Reflection.MonoCMethod.InternalInvoke (System.Reflection.MonoCMethod,object,object[],System.Exception&) [0x00016] in <3ad39e28642b49d2a535a565e6bf6837>:0
at System.Reflection.MonoCMethod.InternalInvoke (object,object[],bool) [0x00005] in /Library/Frameworks/Xamarin.Mac.framework/Versions/5.4.0.70/src/Xamarin.Mac/mcs/class/corlib/System.Reflection/MonoMethod.cs:667
at System.Reflection.MonoCMethod.DoInvoke (object,System.Reflection.BindingFlags,System.Reflection.Binder,object[],System.Globalization.CultureInfo) [0x0007a] in /Library/Frameworks/Xamarin.Mac.framework/Versions/5.4.0.70/src/Xamarin.Mac/mcs/class/corlib/System.Reflection/MonoMethod.cs:657
at System.Reflection.MonoCMethod.Invoke (System.Reflection.BindingFlags,System.Reflection.Binder,object[],System.Globalization.CultureInfo) [0x00000] in /Library/Frameworks/Xamarin.Mac.framework/Versions/5.4.0.70/src/Xamarin.Mac/mcs/class/corlib/System.Reflection/MonoMethod.cs:689
at System.Reflection.ConstructorInfo.Invoke (object[]) [0x00000] in /Library/Frameworks/Xamarin.Mac.framework/Versions/5.4.0.70/src/Xamarin.Mac/mcs/class/corlib/System.Reflection/ConstructorInfo.cs:62
at Xamarin.Mac.Tests.DelegateAndDataSourceTest.DelegateAndDataSourceAllowsNull () [0x00110] in /Users/builder/jenkins/workspace/xamarin-macios-pr-builder/tests/apitest/src/DelegateAndDataSourceTest.cs:65
at (wrapper runtime-invoke) object.runtime_invoke_void__this__ (object,intptr,intptr,intptr) [0x0004f] in <3ad39e28642b49d2a535a565e6bf6837>:0
at <unknown> <0xffffffff>
at (wrapper managed-to-native) System.Reflection.MonoMethod.InternalInvoke (System.Reflection.MonoMethod,object,object[],System.Exception&) [0x00016] in <3ad39e28642b49d2a535a565e6bf6837>:0
at System.Reflection.MonoMethod.Invoke (object,System.Reflection.BindingFlags,System.Reflection.Binder,object[],System.Globalization.CultureInfo) [0x0003b] in /Library/Frameworks/Xamarin.Mac.framework/Versions/5.4.0.70/src/Xamarin.Mac/mcs/class/corlib/System.Reflection/MonoMethod.cs:305
at System.Reflection.MethodBase.Invoke (object,object[]) [0x00000] in /Library/Frameworks/Xamarin.Mac.framework/Versions/5.4.0.70/src/Xamarin.Mac/mcs/class/referencesource/mscorlib/system/reflection/methodbase.cs:229
at NUnit.Framework.Internal.Reflect/<>c__DisplayClass9_0.<InvokeMethod>b__0 () [0x00000] in /Users/builder/jenkins/workspace/xamarin-macios-pr-builder/external/guiunit/src/framework/Internal/Reflect.cs:226
at GuiUnit.InvokerHelper.Invoke () [0x0000e] in /Users/builder/jenkins/workspace/xamarin-macios-pr-builder/external/guiunit/src/framework/GuiUnit/InvokerHelper.cs:18
at Foundation.NSActionDispatcher.Apply () [0x00000] in /Library/Frameworks/Xamarin.Mac.framework/Versions/5.4.0.70/src/Xamarin.Mac/Foundation/NSAction.cs:62
at (wrapper runtime-invoke) object.runtime_invoke_void__this__ (object,intptr,intptr,intptr) [0x0004f] in <3ad39e28642b49d2a535a565e6bf6837>:0
at <unknown> <0xffffffff>
at (wrapper managed-to-native) ObjCRuntime.Messaging.void_objc_msgSend (intptr,intptr) [0x0000a] in <e8e733c9728c43cba731719f096ad306>:0
at AppKit.NSApplication.Run () [0x00012] in /Library/Frameworks/Xamarin.Mac.framework/Versions/5.4.0.70/src/Xamarin.Mac/AppKit/NSApplication.g.cs:2253
at Xamarin.Mac.Tests.MainClass/NSRunLoopIntegration.RunMainLoop () [0x00001] in /Users/builder/jenkins/workspace/xamarin-macios-pr-builder/tests/common/mac/MacTestMain.cs:79
at GuiUnit.TestRunner.ExecuteWithListener (string[],NUnitLite.Runner.TcpWriter) [0x0036f] in /Users/builder/jenkins/workspace/xamarin-macios-pr-builder/external/guiunit/src/framework/GuiUnit/TestRunner.cs:234
at GuiUnit.TestRunner.Execute (string[]) [0x00093] in /Users/builder/jenkins/workspace/xamarin-macios-pr-builder/external/guiunit/src/framework/GuiUnit/TestRunner.cs:137
at GuiUnit.TestRunner.Main (string[]) [0x00001] in /Users/builder/jenkins/workspace/xamarin-macios-pr-builder/external/guiunit/src/framework/GuiUnit/TestRunner.cs:71
at Xamarin.Mac.Tests.MainClass.RunTests (string[]) [0x000a9] in /Users/builder/jenkins/workspace/xamarin-macios-pr-builder/tests/common/mac/MacTestMain.cs:56
at Xamarin.Mac.Tests.MainClass.Main (string[]) [0x00007] in /Users/builder/jenkins/workspace/xamarin-macios-pr-builder/tests/common/mac/MacTestMain.cs:35
at (wrapper runtime-invoke) <Module>.runtime_invoke_void_object (object,intptr,intptr,intptr) [0x00051] in <4c10f2ab239246ba9514b976defa64c7>:0
Native stacktrace:
0 apitest 0x000000010c40b388 mono_handle_native_crash + 264
1 apitest 0x000000010c388dd6 altstack_handle_and_restore + 70
2 CoreFoundation 0x00007fff3b6f260b CFStringGetCString + 43
3 QTKit 0x00007fff457b6542 __51-[QTKitServerController startUsingServerForObject:]_block_invoke + 1238
4 libdispatch.dylib 0x00007fff67b4e63d _dispatch_client_callout + 8
5 libdispatch.dylib 0x00007fff67b5a129 _dispatch_lane_barrier_sync_invoke_and_complete + 60
6 QTKit 0x00007fff457b5f7a -[QTKitServerController startUsingServerForObject:] + 179
7 QTKit 0x00007fff457ac602 -[QTMovie_QuickTime initWithError:forParent:] + 98
8 QTKit 0x00007fff456f55b9 -[QTMovie initWithError:] + 59
9 apitest 0x000000010c31fbe9 xamarin_dyn_objc_msgSend + 217
10 ??? 0x0000000112791d05 0x0 + 4604894469
11 apitest 0x000000010c41f659 mono_jit_runtime_invoke + 1433
12 apitest 0x000000010c51a4df mono_runtime_invoke_checked + 127
13 apitest 0x000000010c522e70 mono_runtime_try_invoke_array + 1856
14 apitest 0x000000010c4be091 ves_icall_InternalInvoke + 657
15 ??? 0x0000000111abe261 0x0 + 4591444577
16 ??? 0x0000000114249463 0x0 + 4632908899
=================================================================
Got a SIGSEGV while executing native code. This usually indicates
a fatal error in the mono runtime or one of the native libraries
used by your application.
=================================================================
1 failing types:
QTKit.QTMovie: Object reference not set to an instance of an object
introspection:
***** ApiCtorInitTest.DefaultCtorAllowed
Stacktrace:
at <unknown> <0xffffffff>
at (wrapper managed-to-native) ObjCRuntime.Messaging.IntPtr_objc_msgSend (intptr,intptr) [0x0000a] in <e8e733c9728c43cba731719f096ad306>:0
at QTKit.QTMovie..ctor () [0x00018] in /Library/Frameworks/Xamarin.Mac.framework/Versions/5.4.0.70/src/Xamarin.Mac/QTKit/QTMovie.g.cs:330
at (wrapper runtime-invoke) object.runtime_invoke_void__this__ (object,intptr,intptr,intptr) [0x0004f] in <3ad39e28642b49d2a535a565e6bf6837>:0
at <unknown> <0xffffffff>
at (wrapper managed-to-native) System.Reflection.MonoCMethod.InternalInvoke (System.Reflection.MonoCMethod,object,object[],System.Exception&) [0x00016] in <3ad39e28642b49d2a535a565e6bf6837>:0
at System.Reflection.MonoCMethod.InternalInvoke (object,object[],bool) [0x00005] in /Library/Frameworks/Xamarin.Mac.framework/Versions/5.4.0.70/src/Xamarin.Mac/mcs/class/corlib/System.Reflection/MonoMethod.cs:667
at System.Reflection.MonoCMethod.DoInvoke (object,System.Reflection.BindingFlags,System.Reflection.Binder,object[],System.Globalization.CultureInfo) [0x0007a] in /Library/Frameworks/Xamarin.Mac.framework/Versions/5.4.0.70/src/Xamarin.Mac/mcs/class/corlib/System.Reflection/MonoMethod.cs:657
at System.Reflection.MonoCMethod.Invoke (System.Reflection.BindingFlags,System.Reflection.Binder,object[],System.Globalization.CultureInfo) [0x00000] in /Library/Frameworks/Xamarin.Mac.framework/Versions/5.4.0.70/src/Xamarin.Mac/mcs/class/corlib/System.Reflection/MonoMethod.cs:689
at System.Reflection.ConstructorInfo.Invoke (object[]) [0x00000] in /Library/Frameworks/Xamarin.Mac.framework/Versions/5.4.0.70/src/Xamarin.Mac/mcs/class/corlib/System.Reflection/ConstructorInfo.cs:62
at Introspection.ApiCtorInitTest.DefaultCtorAllowed () [0x000f0] in /Users/builder/jenkins/workspace/xamarin-macios-pr-builder/tests/introspection/ApiCtorInitTest.cs:267
at (wrapper runtime-invoke) object.runtime_invoke_void__this__ (object,intptr,intptr,intptr) [0x0004f] in <3ad39e28642b49d2a535a565e6bf6837>:0
at <unknown> <0xffffffff>
at (wrapper managed-to-native) System.Reflection.MonoMethod.InternalInvoke (System.Reflection.MonoMethod,object,object[],System.Exception&) [0x00016] in <3ad39e28642b49d2a535a565e6bf6837>:0
at System.Reflection.MonoMethod.Invoke (object,System.Reflection.BindingFlags,System.Reflection.Binder,object[],System.Globalization.CultureInfo) [0x0003b] in /Library/Frameworks/Xamarin.Mac.framework/Versions/5.4.0.70/src/Xamarin.Mac/mcs/class/corlib/System.Reflection/MonoMethod.cs:305
at System.Reflection.MethodBase.Invoke (object,object[]) [0x00000] in /Library/Frameworks/Xamarin.Mac.framework/Versions/5.4.0.70/src/Xamarin.Mac/mcs/class/referencesource/mscorlib/system/reflection/methodbase.cs:229
at NUnit.Framework.Internal.Reflect/<>c__DisplayClass9_0.<InvokeMethod>b__0 () [0x00000] in /Users/builder/jenkins/workspace/xamarin-macios-pr-builder/external/guiunit/src/framework/Internal/Reflect.cs:226
at GuiUnit.InvokerHelper.Invoke () [0x0000e] in /Users/builder/jenkins/workspace/xamarin-macios-pr-builder/external/guiunit/src/framework/GuiUnit/InvokerHelper.cs:18
at Foundation.NSActionDispatcher.Apply () [0x00000] in /Library/Frameworks/Xamarin.Mac.framework/Versions/5.4.0.70/src/Xamarin.Mac/Foundation/NSAction.cs:62
at (wrapper runtime-invoke) object.runtime_invoke_void__this__ (object,intptr,intptr,intptr) [0x0004f] in <3ad39e28642b49d2a535a565e6bf6837>:0
at <unknown> <0xffffffff>
at (wrapper managed-to-native) ObjCRuntime.Messaging.void_objc_msgSend (intptr,intptr) [0x0000a] in <e8e733c9728c43cba731719f096ad306>:0
at AppKit.NSApplication.Run () [0x00012] in /Library/Frameworks/Xamarin.Mac.framework/Versions/5.4.0.70/src/Xamarin.Mac/AppKit/NSApplication.g.cs:2253
at Xamarin.Mac.Tests.MainClass/NSRunLoopIntegration.RunMainLoop () [0x00001] in /Users/builder/jenkins/workspace/xamarin-macios-pr-builder/tests/common/mac/MacTestMain.cs:79
at GuiUnit.TestRunner.ExecuteWithListener (string[],NUnitLite.Runner.TcpWriter) [0x0036f] in /Users/builder/jenkins/workspace/xamarin-macios-pr-builder/external/guiunit/src/framework/GuiUnit/TestRunner.cs:234
at GuiUnit.TestRunner.Execute (string[]) [0x00093] in /Users/builder/jenkins/workspace/xamarin-macios-pr-builder/external/guiunit/src/framework/GuiUnit/TestRunner.cs:137
at GuiUnit.TestRunner.Main (string[]) [0x00001] in /Users/builder/jenkins/workspace/xamarin-macios-pr-builder/external/guiunit/src/framework/GuiUnit/TestRunner.cs:71
at Xamarin.Mac.Tests.MainClass.RunTests (string[]) [0x000a9] in /Users/builder/jenkins/workspace/xamarin-macios-pr-builder/tests/common/mac/MacTestMain.cs:56
at Xamarin.Mac.Tests.MainClass.Main (string[]) [0x00007] in /Users/builder/jenkins/workspace/xamarin-macios-pr-builder/tests/common/mac/MacTestMain.cs:35
at (wrapper runtime-invoke) <Module>.runtime_invoke_void_object (object,intptr,intptr,intptr) [0x00051] in <83b8b910cba94191a35185713f274e89>:0
Native stacktrace:
0 introspection 0x0000000104e33388 mono_handle_native_crash + 264
1 introspection 0x0000000104db0dd6 altstack_handle_and_restore + 70
2 CoreFoundation 0x00007fff3b6f260b CFStringGetCString + 43
3 QTKit 0x00007fff457b6542 __51-[QTKitServerController startUsingServerForObject:]_block_invoke + 1238
4 libdispatch.dylib 0x00007fff67b4e63d _dispatch_client_callout + 8
5 libdispatch.dylib 0x00007fff67b5a129 _dispatch_lane_barrier_sync_invoke_and_complete + 60
6 QTKit 0x00007fff457b5f7a -[QTKitServerController startUsingServerForObject:] + 179
7 QTKit 0x00007fff457ac602 -[QTMovie_QuickTime initWithError:forParent:] + 98
8 QTKit 0x00007fff456f55b9 -[QTMovie initWithError:] + 59
9 introspection 0x0000000104d47be9 xamarin_dyn_objc_msgSend + 217
10 ??? 0x00000001073f6de5 0x0 + 4416564709
11 introspection 0x0000000104e47659 mono_jit_runtime_invoke + 1433
12 introspection 0x0000000104f424df mono_runtime_invoke_checked + 127
13 introspection 0x0000000104f4ae70 mono_runtime_try_invoke_array + 1856
14 introspection 0x0000000104ee6091 ves_icall_InternalInvoke + 657
15 ??? 0x00000001072bd011 0x0 + 4415279121
16 ??? 0x000000010c993d63 0x0 + 4506336611
=================================================================
Got a SIGSEGV while executing native code. This usually indicates
a fatal error in the mono runtime or one of the native libraries
used by your application.
=================================================================
[FAIL] Default constructor not allowed for QTKit.QTMovie : Object reference not set to an instance of an object
2019-03-27 12:51:17 +03:00
case "QTMovie" :
return TestRuntime . CheckSystemVersion ( PlatformName . MacOSX , 10 , 14 , 4 ) ; // Broke in macOS 10.14.4.
2016-05-05 03:14:32 +03:00
}
2016-11-29 22:20:48 +03:00
2019-08-14 18:46:55 +03:00
#if __IOS__
switch ( type . Namespace ) {
case "WatchKit" :
return true ; // WatchKit has been removed from iOS.
}
#endif
2016-05-05 03:14:32 +03:00
return SkipDueToAttribute ( type ) ;
}
/// <summary>
/// Checks that the Handle property of the specified NSObject instance is not null (not IntPtr.Zero).
/// </summary>
/// <param name="obj">NSObject instance to validate</param>
protected virtual void CheckHandle ( NSObject obj )
{
if ( obj . Handle = = IntPtr . Zero )
ReportError ( "{0} : Handle" , instance_type_name ) ;
}
/// <summary>
/// Checks that ToString does not return null (not helpful for debugging) and that it does not crash.
/// </summary>
/// <param name="obj">NSObject instance to validate</param>
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
}
/// <summary>
/// Checks that the IsDirectBinding property is identical to the IsWrapper property of the Register attribute.
/// </summary>
/// <param name="obj">Object.</param>
protected virtual void CheckIsDirectBinding ( NSObject obj )
{
var attrib = obj . GetType ( ) . GetCustomAttribute < RegisterAttribute > ( 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 ) ;
}
/// <summary>
/// Skip, or not, the specified pproperty from being verified.
/// </summary>
/// <param name="pi">PropertyInfo candidate</param>
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 ) ;
}
/// <summary>
/// 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.
/// </summary>
/// <param name="obj">NSObject instance to dispose</param>
/// <param name="type">Type of the object, to be used if special logic is required.</param>
protected virtual void Dispose ( NSObject obj , Type type )
{
2017-02-24 05:10:58 +03:00
//***** ApiCtorInitTest.DefaultCtorAllowed
//2017-01-23 15:52:09.762 introspection[4084:16658258] *** -[NSKeyedArchiver dealloc]: warning: NSKeyedArchiver deallocated without having had -finishEncoding called on it.
( obj as NSKeyedArchiver ) ? . FinishEncoding ( ) ;
2016-05-05 03:14:32 +03:00
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 < ObsoleteAttribute > ( ) ;
return ca ! = null | | base . SkipDueToAttribute ( member ) ;
}
[Test]
public void DefaultCtorAllowed ( )
{
Errors = 0 ;
2016-09-08 14:44:43 +03:00
ErrorData . Clear ( ) ;
2016-05-05 03:14:32 +03:00
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 + + ;
}
2016-09-08 14:44:43 +03:00
Assert . AreEqual ( 0 , Errors , "{0} potential errors found in {1} default ctor validated{2}" , Errors , n , Errors = = 0 ? string . Empty : ":\n" + ErrorData . ToString ( ) + "\n" ) ;
2016-05-05 03:14:32 +03:00
}
// .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 < DesignatedInitializerAttribute > ( ) = = 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 < DesignatedInitializerAttribute > ( ) = = 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 )
{
2019-03-27 03:28:56 +03:00
#if XAMCORE_2_0
string foundation_namespace = "Foundation" ;
#elif MONOMAC
string foundation_namespace = "MonoMac.Foundation" ;
#else
string foundation_namespace = "MonoTouch.Foundation" ;
#endif
2016-05-05 03:14:32 +03:00
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:`
2019-03-27 03:28:56 +03:00
if ( ctor . ToString ( ) = = $"Void .ctor(MapKit.IMKOverlay)" )
2016-05-05 03:14:32 +03:00
return true ;
break ;
2016-08-16 19:00:49 +03:00
case "MPSMatrixMultiplication" :
// marked as NS_UNAVAILABLE - Use the above initialization method instead.
2016-05-05 03:14:32 +03:00
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
2019-03-27 03:28:56 +03:00
if ( ctor . ToString ( ) = = $"Void .ctor(Metal.IMTLDevice)" )
2016-05-05 03:14:32 +03:00
return true ;
break ;
case "NSDataDetector" :
// -[NSDataDetector initWithPattern:options:error:]: Not valid for NSDataDetector
2019-03-27 03:28:56 +03:00
if ( ctor . ToString ( ) = = $"Void .ctor({foundation_namespace}.NSString, {foundation_namespace}.NSRegularExpressionOptions, {foundation_namespace}.NSError ByRef)" )
2016-05-05 03:14:32 +03:00
return true ;
break ;
2016-10-13 18:23:37 +03:00
case "SKStoreProductViewController" :
case "SKCloudServiceSetupViewController" :
// SKStoreProductViewController and SKCloudServiceSetupViewController are OS View Controllers which can't be customized. Therefore they shouldn't re-expose initWithNibName:bundle:
2019-03-27 03:28:56 +03:00
if ( ctor . ToString ( ) = = $"Void .ctor(System.String, {foundation_namespace}.NSBundle)" )
2016-10-13 18:23:37 +03:00
return true ;
break ;
2017-07-18 15:50:48 +03:00
case "MKCompassButton" :
case "MKScaleView" :
case "MKUserTrackingButton" :
// Xcode9 added types that are created only from static methods (no init)
return true ;
2016-05-05 03:14:32 +03:00
#if __TVOS__
case "UISearchBar" :
// - (nullable instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER __TVOS_PROHIBITED;
return true ;
2018-06-28 15:51:38 +03:00
case "TVDigitEntryViewController" :
// full screen, no customization w/NIB
return true ;
2019-06-21 22:00:10 +03:00
case "TVDocumentViewController" :
// as documented
return true ;
2016-05-05 03:14:32 +03:00
#endif
2017-08-04 16:06:21 +03:00
case "PdfAnnotationButtonWidget" :
case "PdfAnnotationChoiceWidget" :
case "PdfAnnotationCircle" :
case "PdfAnnotationFreeText" :
case "PdfAnnotationInk" :
case "PdfAnnotationLine" :
case "PdfAnnotationLink" :
case "PdfAnnotationMarkup" :
case "PdfAnnotationPopup" :
case "PdfAnnotationSquare" :
case "PdfAnnotationStamp" :
case "PdfAnnotationText" :
case "PdfAnnotationTextWidget" :
// This ctor was introduced in 10,13 but all of the above objects are deprecated in 10,12
// so it does not make much sense to expose this ctor in all the deprecated subclasses
#if XAMCORE_2_0
2019-03-27 03:28:56 +03:00
if ( ctor . ToString ( ) = = $"Void .ctor(CoreGraphics.CGRect, {foundation_namespace}.NSString, {foundation_namespace}.NSDictionary)" )
2017-08-04 16:06:21 +03:00
#else
2019-03-27 03:28:56 +03:00
if ( ctor . ToString ( ) = = $"Void .ctor(System.Drawing.RectangleF, {foundation_namespace}.NSString, {foundation_namespace}.NSDictionary)" )
2017-08-04 16:06:21 +03:00
#endif
return true ;
break ;
2017-08-09 18:12:33 +03:00
case "VNTargetedImageRequest" : // Explicitly disabled
2019-03-27 03:28:56 +03:00
if ( ctor . ToString ( ) = = $"Void .ctor(Vision.VNRequestCompletionHandler)" )
2017-08-09 18:12:33 +03:00
return true ;
break ;
2017-08-12 20:09:46 +03:00
case "PKPaymentRequestShippingContactUpdate" :
// a more precise designated initializer is provided
2019-03-27 03:28:56 +03:00
if ( ctor . ToString ( ) = = $"Void .ctor(PassKit.PKPaymentSummaryItem[])" )
2017-08-12 20:09:46 +03:00
return true ;
break ;
2018-02-14 17:09:43 +03:00
case "NSApplication" : // Does not make sense, also it crashes
case "NSBitmapImageRep" : // exception raised
case "NSCachedImageRep" : // exception raised
case "NSCIImageRep" : // exception raised
case "NSCustomImageRep" : // exception raised
case "NSEPSImageRep" : // exception raised
case "NSPdfImageRep" : // exception raised
2019-03-27 03:28:56 +03:00
if ( ctor . ToString ( ) = = $"Void .ctor()" )
2018-02-14 17:09:43 +03:00
return true ;
break ;
2018-02-16 14:49:05 +03:00
case "AUPannerView" : // Do not make sense without the AudioUnit
case "AUGenericView" : // Do not make sense without the AudioUnit
2019-03-27 03:28:56 +03:00
if ( ctor . ToString ( ) = = $"Void .ctor(CoreGraphics.CGRect)" )
2018-02-16 14:49:05 +03:00
return true ;
break ;
2017-12-29 00:37:13 +03:00
case "MDLNoiseTexture" :
case "MDLSkyCubeTexture" :
case "MDLNormalMapTexture" :
case "MDLUrlTexture" :
case "MDLCheckerboardTexture" :
case "MDLColorSwatchTexture" :
// they don't make sense without extra arguments
return true ;
2018-06-15 08:35:27 +03:00
case "ASCredentialProviderViewController" : // goal is to "provides a standard interface for creating a credential provider extension", not a custom one
case "INUIAddVoiceShortcutViewController" : // Doesn't make sense without INVoiceShortcut and there is no other way to set this unless you use the other only .ctor
case "INUIEditVoiceShortcutViewController" : // Doesn't make sense without INVoiceShortcut and there is no other way to set this unless you use the other only .ctor
2018-06-16 04:46:35 +03:00
case "ILClassificationUIExtensionViewController" : // Meant to be an extension
2019-03-27 03:28:56 +03:00
if ( ctor . ToString ( ) = = $"Void .ctor(System.String, {foundation_namespace}.NSBundle)" )
2018-06-13 21:06:37 +03:00
return true ;
2019-01-26 01:24:13 +03:00
break ;
case "MPSImageReduceUnary" : // Not meant to be used, only subclasses
2019-02-27 14:36:08 +03:00
case "MPSCnnArithmetic" : // Not meant to be used, only subclasses
case "MPSCnnArithmeticGradient" : // Not meant to be used, only subclasses
case "MPSNNOptimizer" : // Not meant to be used, only subclasses
case "MPSNNReduceBinary" : // Not meant to be used, only subclasses
case "MPSNNReduceUnary" : // Not meant to be used, only subclasses
2019-01-26 01:24:13 +03:00
var cstr = ctor . ToString ( ) ;
2019-04-05 22:17:36 +03:00
if ( cstr = = "Void .ctor(Metal.IMTLDevice)" | | cstr = = $"Void .ctor({foundation_namespace}.NSCoder, Metal.IMTLDevice)" )
2019-01-26 01:24:13 +03:00
return true ;
2018-06-13 21:06:37 +03:00
break ;
2019-07-12 20:44:24 +03:00
case "MFMailComposeViewController" : // You are meant to use the system provided one
case "MFMessageComposeViewController" : // You are meant to use the system provided one
case "GKFriendRequestComposeViewController" : // You are meant to use the system provided one
case "GKGameCenterViewController" : // You are meant to use the system provided one
case "GKMatchmakerViewController" : // You are meant to use the system provided one
case "GKTurnBasedMatchmakerViewController" : // You are meant to use the system provided one
case "UIImagePickerController" : // You are meant to use the system provided one
case "UIVideoEditorController" : // You are meant to use the system provided one
2019-08-25 03:48:16 +03:00
case "VNDocumentCameraViewController" : // Explicitly disabled on the headers
2019-07-12 20:44:24 +03:00
if ( ctor . ToString ( ) = = $"Void .ctor(System.String, {foundation_namespace}.NSBundle)" )
return true ;
if ( ctor . ToString ( ) = = $"Void .ctor(UIKit.UIViewController)" )
return true ;
break ;
case "UICollectionViewCompositionalLayout" :
// Explicitly disabled ctors - (instancetype)init NS_UNAVAILABLE;
return true ;
2016-05-05 03:14:32 +03:00
}
2016-06-18 15:40:22 +03:00
var ep = ctor . GetParameters ( ) ;
2016-05-05 03:14:32 +03:00
// 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 ) ) {
2016-06-18 15:40:22 +03:00
var cp = candidate . GetParameters ( ) ;
if ( ep . Length ! = cp . Length )
continue ;
var result = true ;
for ( int i = 0 ; i < ep . Length ; i + + ) {
var cpt = cp [ i ] . ParameterType ;
var ept = ep [ i ] . ParameterType ;
if ( cpt = = ept )
continue ;
if ( ! cp [ i ] . ParameterType . IsSubclassOf ( ep [ i ] . ParameterType ) )
result = false ;
}
if ( result )
2016-05-05 03:14:32 +03:00
return true ;
}
return false ;
}
2017-11-28 23:29:05 +03:00
[Test]
public void ShouldNotExposeDefaultCtorTest ( )
{
Errors = 0 ;
int n = 0 ;
// Set to 'true' to generate alloc/init ObjC code of types that fail this test.
bool genObjCTestCode = false ;
var objCCode = genObjCTestCode ? new StringBuilder ( ) : null ;
var types = Assembly . GetTypes ( ) ;
var cifiltertype = types . FirstOrDefault ( c = > c . Name = = "CIFilter" ) ;
foreach ( Type t in types ) {
// TODO: Remove this MPS check in the future, at the time of writing this we currently only care about MPS.
if ( ! t . Name . StartsWith ( "MPS" , StringComparison . OrdinalIgnoreCase ) )
continue ;
if ( ! t . IsPublic | | ! NSObjectType . IsAssignableFrom ( t ) )
continue ;
// ignore CIFilter derived subclasses since they are specially generated
if ( cifiltertype ! = null & & t . IsSubclassOf ( cifiltertype ) )
continue ;
if ( SkipCheckShouldNotExposeDefaultCtor ( 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 ;
}
if ( LogProgress )
Console . WriteLine ( $"{n}: {t.FullName}" ) ;
var parentType = t . BaseType ;
var parentCtor = parentType . GetConstructor ( BindingFlags . Instance | BindingFlags . Public | BindingFlags . NonPublic , null , Type . EmptyTypes , null ) ;
if ( parentCtor = = null ) {
ReportError ( $"Type '{t.FullName}' is a possible candidate for [DisableDefaultCtor] because its BaseType '{parentType.FullName}' does not have one." ) ;
// Useful to test in Xcode
if ( genObjCTestCode ) {
var export = t . GetCustomAttribute < RegisterAttribute > ( ) ;
var typeName = export ? . Name ? ? t . Name ;
objCCode . AppendLine ( $"{typeName}* test{n} = [[{typeName} alloc] init];" ) ;
}
}
n + + ;
}
Assert . AreEqual ( 0 , Errors , $"{Errors} potential errors found in {n} BaseType empty ctor validated: \n{ErrorData}\n{(genObjCTestCode ? $" \ n \ n { objCCode } \ n " : string.Empty)}" ) ;
}
protected virtual bool SkipCheckShouldNotExposeDefaultCtor ( Type type )
{
if ( type . ContainsGenericParameters )
return true ;
foreach ( object ca in type . GetCustomAttributes ( false ) ) {
if ( ca is ProtocolAttribute | | ca is ModelAttribute )
return true ;
}
// Add Skipped types here
//switch (type.Namespace) {
//case "":
// return true;
//}
return SkipDueToAttribute ( type ) ;
}
2018-08-03 03:29:50 +03:00
#if __IOS__
/// <summary>
/// Ensures that all subclasses of a base class that conforms to IARAnchorCopying re-expose its constructor.
/// Note: we cannot have constructors in protocols so we have to inline them in every subclass.
/// </summary>
[Test]
public void ARAnchorCopyingCtorTest ( )
{
Errors = 0 ;
foreach ( Type t in Assembly . GetTypes ( ) ) {
if ( t . Name = = "IARAnchorCopying" | | t . Name = = "ARAnchorCopyingWrapper" )
continue ;
if ( ! typeof ( IARAnchorCopying ) . IsAssignableFrom ( t ) )
continue ;
if ( t . GetConstructor ( new Type [ ] { typeof ( ARAnchor ) } ) = = null )
ReportError ( "{0} should re-expose IARAnchorCopying::.ctor(ARAnchor)" , t ) ;
}
Assert . AreEqual ( 0 , Errors , "{0} potential errors found when validating if subclasses of 'ARAnchor' re-expose 'IARAnchorCopying' constructor" , Errors ) ;
}
#endif
2016-05-05 03:14:32 +03:00
}
}