xamarin-macios/tests/test-libraries/libtest.m

1289 строки
31 KiB
Mathematica
Исходник Обычный вид История

2016-04-26 15:00:35 +03:00
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
2016-04-26 15:00:35 +03:00
#include <objc/objc.h>
2016-04-26 15:00:35 +03:00
#include <objc/runtime.h>
#include <objc/message.h>
2016-04-26 15:00:35 +03:00
#include <zlib.h>
#include "libtest.h"
int
theUltimateAnswer ()
{
return 42;
}
void useZLib ()
{
printf ("ZLib version: %s\n", zlibVersion ());
}
Optimize calls to BlockLiteral.SetupBlock to inject the block signature. (#3391) * [linker] Optimize calls to BlockLiteral.SetupBlock to inject the block signature. Optimize calls to BlockLiteral.SetupBlock[Unsafe] to calculate the block signature at build time, and inject it into the call site. This makes block invocations 10-15x faster (I've added tests that asserts at least an 8x increase). It's also required in order to be able to remove the dynamic registrar code in the future (since calculating the block signature at runtime requires the dynamic registrar). * [mtouch/mmp] Add support for reporting errors/warnings that point to the code line causing the error/warning. Add support for reporting errors/warnings that point to the code line causing the error/warning by adding ErrorHelper overloads that take the exact instruction to report (previously we defaulted to the first line/instruction in a method). * [tests] Add support for asserting filename/linenumber in warning messages. * Make all methods that manually create BlockLiterals optimizable. * [tests] Create a BaseOptimizeGeneratedCodeTest test that's included in both XI's and XM's link all test. * [tests] Add link all test (for both XI and XM) to test the BlockLiteral.SetupBlock optimization. * [tests] Add mtouch/mmp tests for the BlockLiteral.SetupBlock optimization. * [tests][linker] Make the base test class abstract, so tests in the base class aren't executed twice. * [tests][linker] Don't execute linkall-only tests in linksdk. The optimization tests only apply when the test assembly is linked, and that only happens in linkall, so exclude those tests in linksdk. * [tests][mmptest] Update test according to mmp changes. Fixes these test failures: 1) Failed : Xamarin.MMP.Tests.MMPTests.MM0132("inline-runtime-arch") The warning 'MM0132: Unknown optimization: 'inline-runtime-arch'. Valid optimizations are: remove-uithread-checks, dead-code-elimination, inline-isdirectbinding, inline-intptr-size.' was not found in the output: Message #1 did not match: actual: 'Unknown optimization: 'inline-runtime-arch'. Valid optimizations are: remove-uithread-checks, dead-code-elimination, inline-isdirectbinding, inline-intptr-size, blockliteral-setupblock.' expected: 'Unknown optimization: 'inline-runtime-arch'. Valid optimizations are: remove-uithread-checks, dead-code-elimination, inline-isdirectbinding, inline-intptr-size.' Message #2 did not match: actual: 'Unknown optimization: 'inline-runtime-arch'. Valid optimizations are: remove-uithread-checks, dead-code-elimination, inline-isdirectbinding, inline-intptr-size, blockliteral-setupblock.' expected: 'Unknown optimization: 'inline-runtime-arch'. Valid optimizations are: remove-uithread-checks, dead-code-elimination, inline-isdirectbinding, inline-intptr-size.' 2) Failed : Xamarin.MMP.Tests.MMPTests.MM0132("foo") The warning 'MM0132: Unknown optimization: 'foo'. Valid optimizations are: remove-uithread-checks, dead-code-elimination, inline-isdirectbinding, inline-intptr-size.' was not found in the output: Message #1 did not match: actual: 'Unknown optimization: 'foo'. Valid optimizations are: remove-uithread-checks, dead-code-elimination, inline-isdirectbinding, inline-intptr-size, blockliteral-setupblock.' expected: 'Unknown optimization: 'foo'. Valid optimizations are: remove-uithread-checks, dead-code-elimination, inline-isdirectbinding, inline-intptr-size.' Message #2 did not match: actual: 'Unknown optimization: 'foo'. Valid optimizations are: remove-uithread-checks, dead-code-elimination, inline-isdirectbinding, inline-intptr-size, blockliteral-setupblock.' expected: 'Unknown optimization: 'foo'. Valid optimizations are: remove-uithread-checks, dead-code-elimination, inline-isdirectbinding, inline-intptr-size.' * [tests][linker] Fix typo. Fixes this test failure: 1) SetupBlock_CustomDelegate (Linker.Shared.BaseOptimizeGeneratedCodeTest.SetupBlock_CustomDelegate) Counter Expected: 1 But was: 2 * [registrar] Minor adjustment to error message to match previous (and better) behavior. Fixes this test failure: 1) Failed : Xamarin.Registrar.GenericType_WithInvalidParameterTypes The error 'MT4136: The registrar cannot marshal the parameter type 'System.Collections.Generic.List`1<U>' of the parameter 'arg' in the method 'Open`1.Bar(System.Collections.Generic.List`1<U>)'' was not found in the output: Message #1 did not match: actual: 'The registrar cannot marshal the parameter type 'System.Collections.Generic.List`1<Foundation.NSObject>' of the parameter 'arg' in the method 'Open`1.Bar(System.Collections.Generic.List`1<U>)'' expected: 'The registrar cannot marshal the parameter type 'System.Collections.Generic.List`1<U>' of the parameter 'arg' in the method 'Open`1.Bar(System.Collections.Generic.List`1<U>)'' * [docs] mmp shows MM errors/warnings. * [docs] Improve according to reviews. * [tests] Fix merge failure causing test duplication.
2018-02-06 09:08:15 +03:00
void x_call_block (x_block_callback block)
{
block ();
}
typedef matrix_float2x2 (*func_x_get_matrix_float2x2_msgSend) (id self, SEL sel);
void
x_get_matrix_float2x2 (id self, const char *sel,
float* r0c0, float* r0c1,
float* r1c0, float* r1c1)
{
matrix_float2x2 rv;
#if __i386__
IMP msgSend = (IMP) objc_msgSend_stret;
#elif __x86_64__
IMP msgSend = (IMP) objc_msgSend;
#elif __arm64__
IMP msgSend = (IMP) objc_msgSend;
#elif __arm__
IMP msgSend = (IMP) objc_msgSend_stret;
#else
#error unknown architecture
#endif
rv = ((func_x_get_matrix_float2x2_msgSend) msgSend) (self, sel_registerName (sel));
*r0c0 = rv.columns[0][0];
*r0c1 = rv.columns[1][0];
*r1c0 = rv.columns[0][1];
*r1c1 = rv.columns[1][1];
}
typedef matrix_float3x3 (*func_x_get_matrix_float3x3_msgSend) (id self, SEL sel);
void
x_get_matrix_float3x3 (id self, const char *sel,
float* r0c0, float* r0c1, float* r0c2,
float* r1c0, float* r1c1, float* r1c2,
float* r2c0, float* r2c1, float* r2c2)
{
matrix_float3x3 rv;
#if __i386__
IMP msgSend = (IMP) objc_msgSend_stret;
#elif __x86_64__
IMP msgSend = (IMP) objc_msgSend_stret;
#elif __arm64__
IMP msgSend = (IMP) objc_msgSend;
#elif __arm__
IMP msgSend = (IMP) objc_msgSend_stret;
#else
#error unknown architecture
#endif
rv = ((func_x_get_matrix_float3x3_msgSend) msgSend) (self, sel_registerName (sel));
*r0c0 = rv.columns[0][0];
*r0c1 = rv.columns[1][0];
*r0c2 = rv.columns[2][0];
*r1c0 = rv.columns[0][1];
*r1c1 = rv.columns[1][1];
*r1c2 = rv.columns[2][1];
*r2c0 = rv.columns[0][2];
*r2c1 = rv.columns[1][2];
*r2c2 = rv.columns[2][2];
}
typedef matrix_float4x4 (*func_x_get_matrix_float4x4_msgSend) (id self, SEL sel);
void
x_get_matrix_float4x4 (id self, const char *sel,
float* r0c0, float* r0c1, float* r0c2, float* r0c3,
float* r1c0, float* r1c1, float* r1c2, float* r1c3,
float* r2c0, float* r2c1, float* r2c2, float* r2c3,
float* r3c0, float* r3c1, float* r3c2, float* r3c3)
{
matrix_float4x4 rv;
#if __i386__
IMP msgSend = (IMP) objc_msgSend_stret;
#elif __x86_64__
IMP msgSend = (IMP) objc_msgSend_stret;
#elif __arm64__
IMP msgSend = (IMP) objc_msgSend;
#elif __arm__
IMP msgSend = (IMP) objc_msgSend_stret;
#else
#error unknown architecture
#endif
rv = ((func_x_get_matrix_float4x4_msgSend) msgSend) (self, sel_registerName (sel));
*r0c0 = rv.columns[0][0];
*r0c1 = rv.columns[1][0];
*r0c2 = rv.columns[2][0];
*r0c3 = rv.columns[3][0];
*r1c0 = rv.columns[0][1];
*r1c1 = rv.columns[1][1];
*r1c2 = rv.columns[2][1];
*r1c3 = rv.columns[3][1];
*r2c0 = rv.columns[0][2];
*r2c1 = rv.columns[1][2];
*r2c2 = rv.columns[2][2];
*r2c3 = rv.columns[3][2];
*r3c0 = rv.columns[0][3];
*r3c1 = rv.columns[1][3];
*r3c2 = rv.columns[2][3];
*r3c3 = rv.columns[3][3];
}
typedef matrix_float4x3 (*func_x_get_matrix_float4x3_msgSend) (id self, SEL sel);
void
x_get_matrix_float4x3 (id self, const char *sel,
float* r0c0, float* r0c1, float* r0c2, float* r0c3,
float* r1c0, float* r1c1, float* r1c2, float* r1c3,
float* r2c0, float* r2c1, float* r2c2, float* r2c3)
{
matrix_float4x3 rv;
#if __i386__
IMP msgSend = (IMP) objc_msgSend_stret;
#elif __x86_64__
IMP msgSend = (IMP) objc_msgSend_stret;
#elif __arm64__
IMP msgSend = (IMP) objc_msgSend;
#elif __arm__
IMP msgSend = (IMP) objc_msgSend_stret;
#else
#error unknown architecture
#endif
rv = ((func_x_get_matrix_float4x3_msgSend) msgSend) (self, sel_registerName (sel));
*r0c0 = rv.columns[0][0];
*r0c1 = rv.columns[1][0];
*r0c2 = rv.columns[2][0];
*r0c3 = rv.columns[3][0];
*r1c0 = rv.columns[0][1];
*r1c1 = rv.columns[1][1];
*r1c2 = rv.columns[2][1];
*r1c3 = rv.columns[3][1];
*r2c0 = rv.columns[0][2];
*r2c1 = rv.columns[1][2];
*r2c2 = rv.columns[2][2];
*r2c3 = rv.columns[3][2];
}
#if !TARGET_OS_WATCH
void
x_mdltransformcomponent_get_local_transform (id<MDLTransformComponent> self, NSTimeInterval time,
float* r0c0, float* r0c1, float* r0c2, float* r0c3,
float* r1c0, float* r1c1, float* r1c2, float* r1c3,
float* r2c0, float* r2c1, float* r2c2, float* r2c3,
float* r3c0, float* r3c1, float* r3c2, float* r3c3)
{
matrix_float4x4 rv;
rv = [self localTransformAtTime: time];
*r0c0 = rv.columns[0][0];
*r0c1 = rv.columns[1][0];
*r0c2 = rv.columns[2][0];
*r0c3 = rv.columns[3][0];
*r1c0 = rv.columns[0][1];
*r1c1 = rv.columns[1][1];
*r1c2 = rv.columns[2][1];
*r1c3 = rv.columns[3][1];
*r2c0 = rv.columns[0][2];
*r2c1 = rv.columns[1][2];
*r2c2 = rv.columns[2][2];
*r2c3 = rv.columns[3][2];
*r3c0 = rv.columns[0][3];
*r3c1 = rv.columns[1][3];
*r3c2 = rv.columns[2][3];
*r3c3 = rv.columns[3][3];
}
void
x_mdltransform_create_global_transform (MDLObject *object, NSTimeInterval time,
float* r0c0, float* r0c1, float* r0c2, float* r0c3,
float* r1c0, float* r1c1, float* r1c2, float* r1c3,
float* r2c0, float* r2c1, float* r2c2, float* r2c3,
float* r3c0, float* r3c1, float* r3c2, float* r3c3)
{
matrix_float4x4 rv;
rv = [MDLTransform globalTransformWithObject: object atTime: time];
*r0c0 = rv.columns[0][0];
*r0c1 = rv.columns[1][0];
*r0c2 = rv.columns[2][0];
*r0c3 = rv.columns[3][0];
*r1c0 = rv.columns[0][1];
*r1c1 = rv.columns[1][1];
*r1c2 = rv.columns[2][1];
*r1c3 = rv.columns[3][1];
*r2c0 = rv.columns[0][2];
*r2c1 = rv.columns[1][2];
*r2c2 = rv.columns[2][2];
*r2c3 = rv.columns[3][2];
*r3c0 = rv.columns[0][3];
*r3c1 = rv.columns[1][3];
*r3c2 = rv.columns[2][3];
*r3c3 = rv.columns[3][3];
}
void
x_mdltransform_get_rotation_matrix (MDLTransform *self, NSTimeInterval time,
float* r0c0, float* r0c1, float* r0c2, float* r0c3,
float* r1c0, float* r1c1, float* r1c2, float* r1c3,
float* r2c0, float* r2c1, float* r2c2, float* r2c3,
float* r3c0, float* r3c1, float* r3c2, float* r3c3)
{
matrix_float4x4 rv;
rv = [self rotationMatrixAtTime: time];
*r0c0 = rv.columns[0][0];
*r0c1 = rv.columns[1][0];
*r0c2 = rv.columns[2][0];
*r0c3 = rv.columns[3][0];
*r1c0 = rv.columns[0][1];
*r1c1 = rv.columns[1][1];
*r1c2 = rv.columns[2][1];
*r1c3 = rv.columns[3][1];
*r2c0 = rv.columns[0][2];
*r2c1 = rv.columns[1][2];
*r2c2 = rv.columns[2][2];
*r2c3 = rv.columns[3][2];
*r3c0 = rv.columns[0][3];
*r3c1 = rv.columns[1][3];
*r3c2 = rv.columns[2][3];
*r3c3 = rv.columns[3][3];
}
#endif // !TARGET_OS_WATCH
2016-04-26 15:00:35 +03:00
@interface UltimateMachine : NSObject {
}
- (int) getAnswer;
+ (UltimateMachine *) sharedInstance;
@end
@implementation UltimateMachine
{
}
- (int) getAnswer
{
return 42;
}
static UltimateMachine *shared;
+ (UltimateMachine *) sharedInstance
{
if (shared == nil)
shared = [[UltimateMachine alloc] init];
return shared;
}
@end
@interface FakeType2 : NSObject {
}
-(BOOL) isKindOfClass: (Class) cls;
@end
@implementation FakeType2
{
}
- (BOOL) isKindOfClass: (Class) cls;
{
if (cls == objc_getClass ("FakeType1"))
return YES;
return [super isKindOfClass: cls];
}
@end
/*
* ObjC test class used for registrar tests.
*/
@implementation ObjCRegistrarTest
{
}
-(void) V
{
}
-(float) F
{
return _Pf1;
}
-(double) D
{
return _Pd1;
}
-(struct Sd) Sd
{
return _PSd;
2016-04-26 15:00:35 +03:00
}
-(struct Sf) Sf
{
return _PSf;
2016-04-26 15:00:35 +03:00
}
-(void) V:(int)i1 i:(int)i2 i:(int)i3 i:(int)i4 i:(int)i5 i:(int)i6 i:(int)i7
{
// x86_64: 6 in regs, 7th in mem.
_Pi1 = i1; _Pi2 = i2; _Pi3 = i3; _Pi4 = i4; _Pi5 = i5; _Pi6 = i6; _Pi7 = i7;
}
-(void) V:(float)f1 f:(float)f2 f:(float)f3 f:(float)f4 f:(float)f5 f:(float)f6 f:(float)f7 f:(float)f8 f:(float)f9
{
// x86_64: 8 in regs, 9th in mem.
_Pf1 = f1; _Pf2 = f2; _Pf3 = f3; _Pf4 = f4; _Pf5 = f5; _Pf6 = f6; _Pf7 = f7; _Pf8 = f8; _Pf9 = f9;
}
-(void) V:(int)i1 i:(int)i2 i:(int)i3 i:(int)i4 i:(int)i5 i:(int)i6 i:(int)i7 f:(float)f1 f:(float)f2 f:(float)f3 f:(float)f4 f:(float)f5 f:(float)f6 f:(float)f7 f:(float)f8 f:(float)f9
{
// x86_64: 6 ints in regs, 8 floats in in regs, 1 int in mem, 1 float in mem.
_Pi1 = i1; _Pi2 = i2; _Pi3 = i3; _Pi4 = i4; _Pi5 = i5; _Pi6 = i6; _Pi7 = i7;
_Pf1 = f1; _Pf2 = f2; _Pf3 = f3; _Pf4 = f4; _Pf5 = f5; _Pf6 = f6; _Pf7 = f7; _Pf8 = f8; _Pf9 = f9;
}
-(void) V:(double)d1 d:(double)d2 d:(double)d3 d:(double)d4 d:(double)d5 d:(double)d6 d:(double)d7 d:(double)d8 d:(double)d9
{
// x86_64: 8 in regs, 9th in mem.
_Pd1 = d1; _Pd2 = d2; _Pd3 = d3; _Pd4 = d4; _Pd5 = d5; _Pd6 = d6; _Pd7 = d7; _Pd8 = d8; _Pd9 = d9;
}
-(void) V:(int)i1 i:(int)i2 Siid:(struct Siid)s1 i:(int)i3 i:(int)i4 d:(double)d1 d:(double)d2 d:(double)d3 i:(int)i5 i:(int)i6 i:(int)i7
{
_Pi1 = i1; _Pi2 = i2; _PSiid = s1; _Pi3 = i3; _Pi4 = i4; _Pd1 = d1; _Pd2 = d2; _Pd3 = d2; _Pi5 = i5; _Pi6 = i6; _Pi7 = i7;
2016-04-26 15:00:35 +03:00
}
-(void) V:(int)i1 i:(int)i2 f:(float)f1 Siid:(struct Siid)s1 i:(int)i3 i:(int)i4 d:(double)d1 d:(double)d2 d:(double)d3 i:(int)i5 i:(int)i6 i:(int)i7
{
_Pi1 = i1; _Pi2 = i2; _Pf1 = f1; _PSiid = s1; _Pi3 = i3; _Pi4 = i4; _Pd1 = d1; _Pd2 = d2; _Pd3 = d3; _Pi5 = i5; _Pi6 = i6; _Pi7 = i7;
2016-04-26 15:00:35 +03:00
}
-(void) V:(char)c1 c:(char)c2 c:(char)c3 c:(char)c4 c:(char)c5 i:(int)i1 d:(double)d1
{
_Pc1 = c1; _Pc2 = c2; _Pc3 = c3; _Pc4 = c4; _Pc5 = c5; _Pi1 = i1; _Pd1 = d1;
}
-(void) V:(out id _Nullable *)n1 n:(out NSString * _Nullable *)n2
{
abort (); // this method is supposed to be overridden
}
2016-04-26 15:00:35 +03:00
/*
* Invoke method
*/
-(void) invoke_V
{
[self V];
}
-(float) invoke_F
{
return [self F];
}
-(double) invoke_D
{
return [self D];
}
-(struct Sf) Sf_invoke
{
return [self Sf];
}
-(void) invoke_V_null_out
{
[self V:nil n:nil];
2016-04-26 15:00:35 +03:00
}
/*
* API returning blocks.
*/
-(RegistrarTestBlock) methodReturningBlock
{
return nil;
}
-(bool) testBlocks
{
unsigned int output;
unsigned int expected;
unsigned int input;
input = 0xdeadf00d;
expected = 0x1337b001;
output = [self methodReturningBlock] (input);
if (output != expected) {
NSLog (@"methodReturningBlock didn't return the expected value 0x%x for the input value 0x%x, but got instead 0x%x.", expected, input, output);
return false;
}
input = 0xdeadf11d;
expected = 0x7b001133;
output = self.propertyReturningBlock (input);
if (output != expected) {
NSLog (@"propertyReturningBlock didn't return the expected value 0x%x for the input value 0x%x, but got instead 0x%x.", expected, input, output);
return false;
}
return true;
}
-(void) idAsIntPtr: (id)p1
{
// Nothing to do here.
}
#include "libtest.methods.m"
-(void) outNSErrorOnStack:(int)i1 i:(int)i2 i:(int)i3 i:(int)i4 i:(int)i5 i:(int)i6 err:(NSError **)err
{
// Nothing to do here
}
-(void) outNSErrorOnStack:(id)obj1 obj:(id)obj2 obj:(id)obj3 int64:(long long)l4 i:(int)i5 err:(NSError **)err
{
// Nothing to do here
}
-(void) setStringArrayMethod:(NSArray *) array
{
self.stringArrayProperty = array;
}
-(NSArray *) getStringArrayMethod
{
return self.stringArrayProperty;
}
-(void) setNSObjectArrayMethod: (NSArray *) array
{
self.nsobjectArrayProperty = array;
}
-(NSArray *) getNSObjectArrayMethod
{
return self.nsobjectArrayProperty;
}
-(void) setINSCodingArrayMethod: (NSArray *) array
{
self.INSCodingArrayProperty = array;
}
-(NSArray *) getINSCodingArrayMethod
{
return self.INSCodingArrayProperty;
}
-(void) methodEncodings:
(inout NSObject **) obj1P
obj2: (in NSObject **) obj2P
obj3: (out NSObject **) obj3P
obj4: (const NSObject **) obj4P
obj5: (bycopy NSObject **) obj5P
obj6: (byref NSObject **) obj6P
obj7: (oneway NSObject **) obj7P
{
obj1P = NULL;
obj2P = NULL;
obj3P = NULL;
obj4P = NULL;
obj5P = NULL;
obj6P = NULL;
obj7P = NULL;
}
2016-04-26 15:00:35 +03:00
@end
@implementation ProtocolAssigner
-(void) setProtocol
{
ObjCProtocolTestImpl *p = [[ObjCProtocolTestImpl alloc] init];
[self completedSetProtocol: p];
}
-(void) completedSetProtocol: (id<ProtocolAssignerProtocol>) value
{
assert (false); // "THIS FUNCTION SHOULD BE OVERRIDDEN";
}
@end
@implementation ObjCProtocolTestImpl
@end
@implementation ObjCExceptionTest
{
}
-(void) throwObjCException
{
[NSException raise:@"Some exception" format:@"exception was thrown"];
}
-(void) throwManagedException
{
abort (); // this method should be overridden in managed code.
}
-(void) invokeManagedExceptionThrower
{
[self throwManagedException];
}
-(void) invokeManagedExceptionThrowerAndRethrow
{
@try {
[self throwManagedException];
} @catch (id exc) {
[NSException raise:@"Caught exception" format:@"exception was rethrown"];
}
}
-(void) invokeManagedExceptionThrowerAndCatch
{
@try {
[self throwManagedException];
} @catch (id exc) {
// do nothing
}
}
@end
2016-04-26 15:00:35 +03:00
@interface CtorChaining1 : NSObject
@property BOOL initCalled;
@property BOOL initCallsInitCalled;
-(instancetype) init;
-(instancetype) initCallsInit:(int) value;
@end
@implementation CtorChaining1
-(instancetype) init
{
self.initCalled = YES;
return [super init];
}
-(instancetype) initCallsInit:(int) value
{
self.initCallsInitCalled = YES;
return [self init];
}
@end
@implementation ObjCProtocolClassTest
-(void) idAsIntPtr: (id)p1
{
// Do nothing
}
-(void) methodEncodings:
(inout NSObject **) obj1P
obj2: (in NSObject **) obj2P
obj3: (out NSObject **) obj3P
obj4: (const NSObject **) obj4P
obj5: (bycopy NSObject **) obj5P
obj6: (byref NSObject **) obj6P
obj7: (oneway NSObject **) obj7P
{
// Do nothing
}
@end
[ObjCRuntime] Don't double-retain blocks. (#3717) * [ObjCRuntime] Don't double-retain blocks. First there was darkness; no blocks were retained. Then came the light; and all blocks were retained [1] Forever. But all that once is, must one day not be, and thus the light gave way to darkness, and blocks were only retained as long as need be [2]. But before there was a balance, there was a crossroad. In some places the light shone forever, and all blocks were retained. In other places there was a balance, and the light shone only as long as needed. A desire to unify arose. Alas, it could not be. It was a bright and sunny day When a merge failed [3]. And all blocks were retained. Twice. Once [here][4] and once [there][5]. For many years we could not see. Until a dark and rainy night, when an awareness arose. And the desire to unify the balance could finally be fulfilled. [1]: https://github.com/xamarin/maccore/commit/6efca92acb5d0f2b1b495a40ac2e89586200d206 [2]: https://github.com/xamarin/maccore/commit/a22f877539058b889555ae4decae0f2e9aca029c [3]: https://github.com/xamarin/maccore/commit/befa0477cf9f3c9602d3fda6b9dee65e5bba506f [4]: https://github.com/xamarin/xamarin-macios/blob/5158a3c00138ae9bc45979487ca6a0fbc3fccc4d/src/ObjCRuntime/Runtime.cs#L858 [5]: https://github.com/xamarin/xamarin-macios/blob/5158a3c00138ae9bc45979487ca6a0fbc3fccc4d/runtime/runtime.m#L2091 * [tests] Fix test builds. * [monotouch-test] RegistrarTest.BlockCollection: allocate more and wait longer for the GC. Allocate more objects and wait longer for the GC to run. Hopefully fixes this problem: [FAIL] RegistrarTest.BlockCollection : freed blocks Expected: greater than 0 But was: 0 The blocks are freed if we just wait long enough... The problem is that we don't want to wait very long (makes the tests slow to run), so try to speed things up by allocating more.
2018-03-13 14:30:32 +03:00
static volatile int freed_blocks = 0;
static volatile int called_blocks = 0;
[ObjCRuntime] Don't double-retain blocks. (#3717) * [ObjCRuntime] Don't double-retain blocks. First there was darkness; no blocks were retained. Then came the light; and all blocks were retained [1] Forever. But all that once is, must one day not be, and thus the light gave way to darkness, and blocks were only retained as long as need be [2]. But before there was a balance, there was a crossroad. In some places the light shone forever, and all blocks were retained. In other places there was a balance, and the light shone only as long as needed. A desire to unify arose. Alas, it could not be. It was a bright and sunny day When a merge failed [3]. And all blocks were retained. Twice. Once [here][4] and once [there][5]. For many years we could not see. Until a dark and rainy night, when an awareness arose. And the desire to unify the balance could finally be fulfilled. [1]: https://github.com/xamarin/maccore/commit/6efca92acb5d0f2b1b495a40ac2e89586200d206 [2]: https://github.com/xamarin/maccore/commit/a22f877539058b889555ae4decae0f2e9aca029c [3]: https://github.com/xamarin/maccore/commit/befa0477cf9f3c9602d3fda6b9dee65e5bba506f [4]: https://github.com/xamarin/xamarin-macios/blob/5158a3c00138ae9bc45979487ca6a0fbc3fccc4d/src/ObjCRuntime/Runtime.cs#L858 [5]: https://github.com/xamarin/xamarin-macios/blob/5158a3c00138ae9bc45979487ca6a0fbc3fccc4d/runtime/runtime.m#L2091 * [tests] Fix test builds. * [monotouch-test] RegistrarTest.BlockCollection: allocate more and wait longer for the GC. Allocate more objects and wait longer for the GC to run. Hopefully fixes this problem: [FAIL] RegistrarTest.BlockCollection : freed blocks Expected: greater than 0 But was: 0 The blocks are freed if we just wait long enough... The problem is that we don't want to wait very long (makes the tests slow to run), so try to speed things up by allocating more.
2018-03-13 14:30:32 +03:00
@implementation ObjCBlockTester
static Class _TestClass = NULL;
+ (Class)TestClass {
return _TestClass;
}
+ (void)setTestClass:(Class) value {
_TestClass = value;
}
-(void) classCallback: (void (^)(int32_t magic_number))completionHandler
{
assert (false); // THIS FUNCTION SHOULD BE OVERRIDDEN
}
-(void) callClassCallback
{
__block bool called = false;
[self classCallback: ^(int magic_number)
{
assert (magic_number == 42);
called = true;
}];
assert (called);
}
-(void) callRequiredCallback
{
__block bool called = false;
[self.TestObject requiredCallback: ^(int magic_number)
{
assert (magic_number == 42);
called = true;
}];
assert (called);
}
+(void) callRequiredStaticCallback
{
__block bool called = false;
[self.TestClass requiredStaticCallback: ^(int magic_number)
{
assert (magic_number == 42);
called = true;
}];
assert (called);
}
-(void) callOptionalCallback
{
__block bool called = false;
[self.TestObject optionalCallback: ^(int magic_number)
{
assert (magic_number == 42);
called = true;
}];
assert (called);
}
+(void) callOptionalStaticCallback
{
__block bool called = false;
[self.TestClass optionalStaticCallback: ^(int magic_number)
{
assert (magic_number == 42);
called = true;
}];
assert (called);
}
+(void) callAssertMainThreadBlockRelease: (outerBlock) completionHandler
{
MainThreadDeallocator *obj = [[MainThreadDeallocator alloc] init];
__block bool success = false;
dispatch_sync (dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0ul), ^{
completionHandler (^(int magic_number)
{
assert (magic_number == 42);
assert ([NSThread isMainThread]); // This may crash way after the failed test has finished executing.
success = obj != NULL; // this captures the 'obj', and it's only freed when the block is freed.
});
});
assert (success);
[obj release];
}
+(void) callAssertMainThreadBlockReleaseQOS: (outerBlock) completionHandler
{
MainThreadDeallocator *obj = [[MainThreadDeallocator alloc] init];
__block bool success = false;
dispatch_sync (dispatch_get_global_queue (QOS_CLASS_DEFAULT, 0ul), ^{
completionHandler (^(int magic_number)
{
assert (magic_number == 42);
assert ([NSThread isMainThread]); // This may crash way after the failed test has finished executing.
success = obj != NULL; // this captures the 'obj', and it's only freed when the block is freed.
});
});
assert (success);
[obj release];
}
-(void) callAssertMainThreadBlockReleaseCallback
{
MainThreadDeallocator *obj = [[MainThreadDeallocator alloc] init];
__block bool success = false;
dispatch_sync (dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0ul), ^{
[self assertMainThreadBlockReleaseCallback: ^(int magic_number)
{
assert (magic_number == 42);
assert ([NSThread isMainThread]); // This may crash way after the failed test has finished executing.
success = obj != NULL; // this captures the 'obj', and it's only freed when the block is freed.
}];
});
assert (success);
[obj release];
}
-(void) callAssertMainThreadBlockReleaseCallbackQOS
{
MainThreadDeallocator *obj = [[MainThreadDeallocator alloc] init];
__block bool success = false;
dispatch_sync (dispatch_get_global_queue (QOS_CLASS_DEFAULT, 0ul), ^{
[self assertMainThreadBlockReleaseCallback: ^(int magic_number)
{
assert (magic_number == 42);
assert ([NSThread isMainThread]); // This may crash way after the failed test has finished executing.
success = obj != NULL; // this captures the 'obj', and it's only freed when the block is freed.
}];
});
assert (success);
[obj release];
}
-(void) assertMainThreadBlockReleaseCallback: (innerBlock) completionHandler
{
assert (false); // THIS FUNCTION SHOULD BE OVERRIDDEN
}
[ObjCRuntime] Don't double-retain blocks. (#3717) * [ObjCRuntime] Don't double-retain blocks. First there was darkness; no blocks were retained. Then came the light; and all blocks were retained [1] Forever. But all that once is, must one day not be, and thus the light gave way to darkness, and blocks were only retained as long as need be [2]. But before there was a balance, there was a crossroad. In some places the light shone forever, and all blocks were retained. In other places there was a balance, and the light shone only as long as needed. A desire to unify arose. Alas, it could not be. It was a bright and sunny day When a merge failed [3]. And all blocks were retained. Twice. Once [here][4] and once [there][5]. For many years we could not see. Until a dark and rainy night, when an awareness arose. And the desire to unify the balance could finally be fulfilled. [1]: https://github.com/xamarin/maccore/commit/6efca92acb5d0f2b1b495a40ac2e89586200d206 [2]: https://github.com/xamarin/maccore/commit/a22f877539058b889555ae4decae0f2e9aca029c [3]: https://github.com/xamarin/maccore/commit/befa0477cf9f3c9602d3fda6b9dee65e5bba506f [4]: https://github.com/xamarin/xamarin-macios/blob/5158a3c00138ae9bc45979487ca6a0fbc3fccc4d/src/ObjCRuntime/Runtime.cs#L858 [5]: https://github.com/xamarin/xamarin-macios/blob/5158a3c00138ae9bc45979487ca6a0fbc3fccc4d/runtime/runtime.m#L2091 * [tests] Fix test builds. * [monotouch-test] RegistrarTest.BlockCollection: allocate more and wait longer for the GC. Allocate more objects and wait longer for the GC to run. Hopefully fixes this problem: [FAIL] RegistrarTest.BlockCollection : freed blocks Expected: greater than 0 But was: 0 The blocks are freed if we just wait long enough... The problem is that we don't want to wait very long (makes the tests slow to run), so try to speed things up by allocating more.
2018-03-13 14:30:32 +03:00
-(void) testFreedBlocks
{
FreedNotifier* obj = [[FreedNotifier alloc] init];
__block bool success = false;
[self classCallback: ^(int magic_number)
{
assert (magic_number == 42);
success = obj != NULL; // this captures the 'obj', and it's only freed when the block is freed.
}];
assert (success);
[obj release];
}
+(int) freedBlockCount
{
return freed_blocks;
}
+(int) calledBlockCount
{
return called_blocks;
}
static void block_called ()
{
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
OSAtomicIncrement32 (&called_blocks);
#pragma clang diagnostic pop
}
+(void) callProtocolWithBlockProperties: (id<ProtocolWithBlockProperties>) obj required: (bool) required instance: (bool) instance;
{
if (required) {
if (instance) {
obj.myRequiredProperty ();
} else {
[[(NSObject *) obj class] myRequiredStaticProperty] ();
}
} else {
if (instance) {
obj.myOptionalProperty ();
} else {
[[(NSObject *) obj class] myOptionalStaticProperty] ();
}
}
}
+(void) callProtocolWithBlockReturnValue: (id<ObjCProtocolBlockTest>) obj required: (bool) required instance: (bool) instance;
{
if (required) {
if (instance) {
[obj requiredReturnValue] (42);
} else {
[[(NSObject *) obj class] requiredStaticReturnValue] (42);
}
} else {
if (instance) {
[obj optionalReturnValue] (42);
} else {
[[(NSObject *) obj class] optionalStaticReturnValue] (42);
}
}
}
+(void) callProtocolWithBlockPropertiesRequired: (id<ProtocolWithBlockProperties>) obj
{
obj.myRequiredProperty ();
}
+(void) setProtocolWithBlockProperties: (id<ProtocolWithBlockProperties>) obj required: (bool) required instance: (bool) instance
{
simple_callback callback = ^{ block_called (); };
if (required) {
if (instance) {
obj.myRequiredProperty = callback;
} else {
[[(NSObject *) obj class] setMyRequiredStaticProperty: callback];
}
} else {
if (instance) {
obj.myOptionalProperty = callback;
} else {
[[(NSObject *) obj class] setMyOptionalStaticProperty: callback];
}
}
}
[ObjCRuntime] Don't double-retain blocks. (#3717) * [ObjCRuntime] Don't double-retain blocks. First there was darkness; no blocks were retained. Then came the light; and all blocks were retained [1] Forever. But all that once is, must one day not be, and thus the light gave way to darkness, and blocks were only retained as long as need be [2]. But before there was a balance, there was a crossroad. In some places the light shone forever, and all blocks were retained. In other places there was a balance, and the light shone only as long as needed. A desire to unify arose. Alas, it could not be. It was a bright and sunny day When a merge failed [3]. And all blocks were retained. Twice. Once [here][4] and once [there][5]. For many years we could not see. Until a dark and rainy night, when an awareness arose. And the desire to unify the balance could finally be fulfilled. [1]: https://github.com/xamarin/maccore/commit/6efca92acb5d0f2b1b495a40ac2e89586200d206 [2]: https://github.com/xamarin/maccore/commit/a22f877539058b889555ae4decae0f2e9aca029c [3]: https://github.com/xamarin/maccore/commit/befa0477cf9f3c9602d3fda6b9dee65e5bba506f [4]: https://github.com/xamarin/xamarin-macios/blob/5158a3c00138ae9bc45979487ca6a0fbc3fccc4d/src/ObjCRuntime/Runtime.cs#L858 [5]: https://github.com/xamarin/xamarin-macios/blob/5158a3c00138ae9bc45979487ca6a0fbc3fccc4d/runtime/runtime.m#L2091 * [tests] Fix test builds. * [monotouch-test] RegistrarTest.BlockCollection: allocate more and wait longer for the GC. Allocate more objects and wait longer for the GC to run. Hopefully fixes this problem: [FAIL] RegistrarTest.BlockCollection : freed blocks Expected: greater than 0 But was: 0 The blocks are freed if we just wait long enough... The problem is that we don't want to wait very long (makes the tests slow to run), so try to speed things up by allocating more.
2018-03-13 14:30:32 +03:00
@end
@implementation FreedNotifier
-(void) dealloc
{
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
[ObjCRuntime] Don't double-retain blocks. (#3717) * [ObjCRuntime] Don't double-retain blocks. First there was darkness; no blocks were retained. Then came the light; and all blocks were retained [1] Forever. But all that once is, must one day not be, and thus the light gave way to darkness, and blocks were only retained as long as need be [2]. But before there was a balance, there was a crossroad. In some places the light shone forever, and all blocks were retained. In other places there was a balance, and the light shone only as long as needed. A desire to unify arose. Alas, it could not be. It was a bright and sunny day When a merge failed [3]. And all blocks were retained. Twice. Once [here][4] and once [there][5]. For many years we could not see. Until a dark and rainy night, when an awareness arose. And the desire to unify the balance could finally be fulfilled. [1]: https://github.com/xamarin/maccore/commit/6efca92acb5d0f2b1b495a40ac2e89586200d206 [2]: https://github.com/xamarin/maccore/commit/a22f877539058b889555ae4decae0f2e9aca029c [3]: https://github.com/xamarin/maccore/commit/befa0477cf9f3c9602d3fda6b9dee65e5bba506f [4]: https://github.com/xamarin/xamarin-macios/blob/5158a3c00138ae9bc45979487ca6a0fbc3fccc4d/src/ObjCRuntime/Runtime.cs#L858 [5]: https://github.com/xamarin/xamarin-macios/blob/5158a3c00138ae9bc45979487ca6a0fbc3fccc4d/runtime/runtime.m#L2091 * [tests] Fix test builds. * [monotouch-test] RegistrarTest.BlockCollection: allocate more and wait longer for the GC. Allocate more objects and wait longer for the GC to run. Hopefully fixes this problem: [FAIL] RegistrarTest.BlockCollection : freed blocks Expected: greater than 0 But was: 0 The blocks are freed if we just wait long enough... The problem is that we don't want to wait very long (makes the tests slow to run), so try to speed things up by allocating more.
2018-03-13 14:30:32 +03:00
OSAtomicIncrement32 (&freed_blocks);
#pragma clang diagnostic pop
[ObjCRuntime] Don't double-retain blocks. (#3717) * [ObjCRuntime] Don't double-retain blocks. First there was darkness; no blocks were retained. Then came the light; and all blocks were retained [1] Forever. But all that once is, must one day not be, and thus the light gave way to darkness, and blocks were only retained as long as need be [2]. But before there was a balance, there was a crossroad. In some places the light shone forever, and all blocks were retained. In other places there was a balance, and the light shone only as long as needed. A desire to unify arose. Alas, it could not be. It was a bright and sunny day When a merge failed [3]. And all blocks were retained. Twice. Once [here][4] and once [there][5]. For many years we could not see. Until a dark and rainy night, when an awareness arose. And the desire to unify the balance could finally be fulfilled. [1]: https://github.com/xamarin/maccore/commit/6efca92acb5d0f2b1b495a40ac2e89586200d206 [2]: https://github.com/xamarin/maccore/commit/a22f877539058b889555ae4decae0f2e9aca029c [3]: https://github.com/xamarin/maccore/commit/befa0477cf9f3c9602d3fda6b9dee65e5bba506f [4]: https://github.com/xamarin/xamarin-macios/blob/5158a3c00138ae9bc45979487ca6a0fbc3fccc4d/src/ObjCRuntime/Runtime.cs#L858 [5]: https://github.com/xamarin/xamarin-macios/blob/5158a3c00138ae9bc45979487ca6a0fbc3fccc4d/runtime/runtime.m#L2091 * [tests] Fix test builds. * [monotouch-test] RegistrarTest.BlockCollection: allocate more and wait longer for the GC. Allocate more objects and wait longer for the GC to run. Hopefully fixes this problem: [FAIL] RegistrarTest.BlockCollection : freed blocks Expected: greater than 0 But was: 0 The blocks are freed if we just wait long enough... The problem is that we don't want to wait very long (makes the tests slow to run), so try to speed things up by allocating more.
2018-03-13 14:30:32 +03:00
[super dealloc];
}
@end
@implementation EvilDeallocator
-(void) dealloc
{
if (self.evilCallback != NULL)
self.evilCallback (314);
[super dealloc];
}
@end
@implementation MainThreadDeallocator : NSObject {
}
-(void) dealloc
{
assert ([NSThread isMainThread]);
[super dealloc];
}
@end
@implementation RefOutParameters : NSObject {
}
-(void) testCFBundle: (int) action a:(CFBundleRef *) refValue b:(CFBundleRef *) outValue
{
// We should never get null pointers.
assert (refValue != NULL);
assert (outValue != NULL);
// out parameters from managed code should always be NULL upon entry
assert (*outValue == NULL);
switch (action & 0xFF) {
case 1: // Set both to null
*refValue = NULL;
*outValue = NULL;
break;
case 2: // verify that refValue points to something
assert (*refValue != NULL);
break;
case 3: // set both parameteres to the same pointer of a CFBundle
*refValue = CFBundleGetMainBundle ();
*outValue = CFBundleGetMainBundle ();
break;
case 4: // set both parameteres to different pointers of a CFBundle
*refValue = (CFBundleRef) CFArrayGetValueAtIndex (CFBundleGetAllBundles (), 0);
*outValue = (CFBundleRef) CFArrayGetValueAtIndex (CFBundleGetAllBundles (), 1);
break;
default:
abort ();
}
}
-(void) testINSCoding: (int) action a:(id<NSCoding>*) refValue b:(id<NSCoding>*) outValue
{
NSString *str = NULL;
// We should never get null pointers.
assert (refValue != NULL);
assert (outValue != NULL);
// out parameters from managed code should always be NULL upon entry
assert (*outValue == NULL);
switch (action & 0xFF) {
case 1: // Set both to null
*refValue = NULL;
*outValue = NULL;
break;
case 2: // verify that refValue points to something
assert (*refValue != NULL);
break;
case 3: // set both parameteres to the same pointer of an NSString (which implements NSCoding)
str = @"Some static string";
*refValue = str;
*outValue = str;
return;
case 4: // set both parameteres to different pointers of an NSString
*refValue = @"A static string for ref";
*outValue = @"A static string for out";
break;
default:
abort ();
}
}
-(void) testNSObject: (int) action a:(id *) refValue b:(id *) outValue
{
NSObject *obj = NULL;
// We should never get null pointers.
assert (refValue != NULL);
assert (outValue != NULL);
// out parameters from managed code should always be NULL upon entry
assert (*outValue == NULL);
switch (action & 0xFF) {
case 1: // Set both to null
*refValue = NULL;
*outValue = NULL;
break;
case 2: // verify that refValue points to something
assert (*refValue != NULL);
break;
case 3: // set both parameteres to the same pointer of an NSObject
obj = [NSObject new];
*refValue = obj;
*outValue = obj;
return;
case 4: // set both parameteres to different objects
*refValue = [NSObject new];
*outValue = [NSObject new];
break;
default:
abort ();
}
}
-(void) testNSValue: (int) action a:(NSValue **) refValue b:(NSValue **) outValue
{
NSValue *obj = NULL;
// We should never get null pointers.
assert (refValue != NULL);
assert (outValue != NULL);
// out parameters from managed code should always be NULL upon entry
assert (*outValue == NULL);
switch (action & 0xFF) {
case 1: // Set both to null
*refValue = NULL;
*outValue = NULL;
break;
case 2: // verify that refValue points to something
assert (*refValue != NULL);
break;
case 3: // set both parameteres to the same pointer of an NSValue
obj = [NSValue valueWithMKCoordinate: CLLocationCoordinate2DMake (3, 14)];
*refValue = obj;
*outValue = obj;
return;
case 4: // set both parameteres to different objects
*refValue = [NSValue valueWithMKCoordinate: CLLocationCoordinate2DMake (3, 14)];
*outValue = [NSValue valueWithMKCoordinate: CLLocationCoordinate2DMake (2, 71)];
break;
default:
abort ();
}
}
-(void) testString: (int) action a:(NSString **) refValue b:(NSString **) outValue
{
NSString *obj = NULL;
// We should never get null pointers.
assert (refValue != NULL);
assert (outValue != NULL);
// out parameters from managed code should always be NULL upon entry
assert (*outValue == NULL);
switch (action & 0xFF) {
case 1: // Set both to null
*refValue = NULL;
*outValue = NULL;
break;
case 2: // verify that refValue points to something
assert (*refValue != NULL);
break;
case 3: // set both parameteres to the same pointer of an NSString
obj = @"A constant native string";
*refValue = obj;
*outValue = obj;
return;
case 4: // set both parameteres to different objects
*refValue = [NSString stringWithUTF8String: "Hello Xamarin"];
*outValue = [NSString stringWithUTF8String: "Hello Microsoft"];
break;
default:
abort ();
}
}
-(void) testInt: (int) action a:(int32_t *) refValue b:(int32_t *) outValue
{
NSString *obj = NULL;
// We should never get null pointers.
assert (refValue != NULL);
assert (outValue != NULL);
switch (action & 0xFF) {
case 1: // Set both to 0
*refValue = 0;
*outValue = 0;
break;
case 3: // set both parameteres to the same value
obj = @"A constant native string";
*refValue = 314159;
*outValue = 314159;
return;
case 4: // set both parameteres to different objects
*refValue = 3141592;
*outValue = 2718282;
break;
default:
abort ();
}
}
-(void) testSelector: (int) action a:(SEL *) refValue b:(SEL *) outValue
{
SEL obj = NULL;
// We should never get null pointers.
assert (refValue != NULL);
assert (outValue != NULL);
// out parameters from managed code should always be NULL upon entry
assert (*outValue == NULL);
switch (action & 0xFF) {
case 1: // Set both to null
*refValue = NULL;
*outValue = NULL;
break;
case 2: // verify that refValue points to something
assert (*refValue != NULL);
break;
case 3: // set both parameteres to the same selector
obj = @selector (testSelector);
*refValue = obj;
*outValue = obj;
return;
case 4: // set both parameteres to different selectors
*refValue = @selector (testSelector:a:);
*outValue = @selector (testSelector:b:);
break;
default:
abort ();
}
}
-(void) testClass: (int) action a:(Class *) refValue b:(Class *) outValue
{
Class obj = NULL;
// We should never get null pointers.
assert (refValue != NULL);
assert (outValue != NULL);
// out parameters from managed code should always be NULL upon entry
assert (*outValue == NULL);
switch (action & 0xFF) {
case 1: // Set both to null
*refValue = NULL;
*outValue = NULL;
break;
case 2: // verify that refValue points to something
assert (*refValue != NULL);
break;
case 3: // set both parameteres to the same class
obj = [NSString class];
*refValue = obj;
*outValue = obj;
return;
case 4: // set both parameteres to different classes
*refValue = [NSBundle class];
*outValue = [NSDate class];
break;
default:
abort ();
}
}
-(void) testINSCodingArray: (int) action a:(NSArray **) refValue b:(NSArray **) outValue
{
NSArray *arr = NULL;
// We should never get null pointers.
assert (refValue != NULL);
assert (outValue != NULL);
// out parameters from managed code should always be NULL upon entry
assert (*outValue == NULL);
switch (action & 0xFF) {
case 1: // Set both to null
*refValue = NULL;
*outValue = NULL;
break;
case 2: // verify that refValue points to something
assert (*refValue != NULL);
break;
case 3: // set both parameteres to the same pointer of an NSArray of NSString (which implements NSCoding)
arr =
@[
// This looks funny, but it's to ensure we don't get strings that are statically allocated (in which case the same pointer would be returned in multiple calls, which may throw off some of our tests)
[[NSString stringWithUTF8String: "Hello"] stringByAppendingString: @"World"],
[[NSString stringWithUTF8String: "Hello"] stringByAppendingString: @"Universe"]
];
*refValue = arr;
*outValue = arr;
return;
case 4: // set both parameteres to different NSArrays
*refValue = @[@3, @14];
*outValue = @[[NSString stringWithUTF8String: "Hello"], [NSString stringWithUTF8String: "Xamarin"]];
break;
default:
abort ();
}
}
-(void) testNSObjectArray: (int) action a:(NSArray **) refValue b:(NSArray **) outValue
{
NSArray *arr = NULL;
// We should never get null pointers.
assert (refValue != NULL);
assert (outValue != NULL);
// out parameters from managed code should always be NULL upon entry
assert (*outValue == NULL);
switch (action & 0xFF) {
case 1: // Set both to null
*refValue = NULL;
*outValue = NULL;
break;
case 2: // verify that refValue points to something
assert (*refValue != NULL);
break;
case 3: // set both parameteres to the same pointer of an NSArray of NSString
arr = @[@"Hello", @"World"];
*refValue = arr;
*outValue = arr;
return;
case 4: // set both parameteres to different NSArrays
*refValue = @[@3, @14];
*outValue = @[@"Hello", @"Xamarin"];
break;
default:
abort ();
}
}
-(void) testNSValueArray: (int) action a:(NSArray **) refValue b:(NSArray **) outValue
{
NSArray *arr = NULL;
// We should never get null pointers.
assert (refValue != NULL);
assert (outValue != NULL);
// out parameters from managed code should always be NULL upon entry
assert (*outValue == NULL);
switch (action & 0xFF) {
case 1: // Set both to null
*refValue = NULL;
*outValue = NULL;
break;
case 2: // verify that refValue points to something
assert (*refValue != NULL);
break;
case 3: // set both parameteres to the same pointer of an NSArray of NSValue
arr = @[[NSValue valueWithMKCoordinate: CLLocationCoordinate2DMake (3, 14)], [NSValue valueWithMKCoordinate: CLLocationCoordinate2DMake (2, 71)]];
*refValue = arr;
*outValue = arr;
return;
case 4: // set both parameteres to different NSArrays
*refValue = @[[NSValue valueWithMKCoordinate: CLLocationCoordinate2DMake (3, 14)], [NSValue valueWithMKCoordinate: CLLocationCoordinate2DMake (15, 92)]];
*outValue = @[[NSValue valueWithMKCoordinate: CLLocationCoordinate2DMake (2, 71)], [NSValue valueWithMKCoordinate: CLLocationCoordinate2DMake (82, 82)]];
break;
default:
abort ();
}
}
-(void) testStringArray: (int) action a:(NSArray **) refValue b:(NSArray **) outValue
{
NSArray *arr = NULL;
// We should never get null pointers.
assert (refValue != NULL);
assert (outValue != NULL);
// out parameters from managed code should always be NULL upon entry
assert (*outValue == NULL);
switch (action & 0xFF) {
case 1: // Set both to null
*refValue = NULL;
*outValue = NULL;
break;
case 2: // verify that refValue points to something
assert (*refValue != NULL);
break;
case 3: // set both parameteres to the same pointer of an NSArray of NSString
arr = @[@"Hello", @"World"];
*refValue = arr;
*outValue = arr;
return;
case 4: // set both parameteres to different NSArrays
*refValue = @[@"Hello", @"Microsoft"];
*outValue = @[@"Hello", @"Xamarin"];
break;
case 5: // assert that we got an immutable array
// We'll never get a mutable array (the binding code creates NSArrays), so assert that.
assert (![*refValue isKindOfClass: [NSMutableArray class]]);
break;
default:
abort ();
}
}
-(void) testClassArray: (int) action a:(NSArray **) refValue b:(NSArray **) outValue
{
NSArray *arr = NULL;
// We should never get null pointers.
assert (refValue != NULL);
assert (outValue != NULL);
// out parameters from managed code should always be NULL upon entry
assert (*outValue == NULL);
switch (action & 0xFF) {
case 1: // Set both to null
*refValue = NULL;
*outValue = NULL;
break;
case 2: // verify that refValue points to something
assert (*refValue != NULL);
break;
case 3: // set both parameteres to the same pointer of an NSArray of NSString
arr = @[[NSString class], [NSDate class]];
*refValue = arr;
*outValue = arr;
return;
case 4: // set both parameteres to different NSArrays
*refValue = @[[NSString class], [NSValue class]];
*outValue = @[[NSData class], [NSDate class]];
break;
case 5: // assert that we got an immutable array
// We'll never get a mutable array (the binding code creates NSArrays), so assert that.
assert (![*refValue isKindOfClass: [NSMutableArray class]]);
break;
default:
abort ();
}
}
@end
#include "libtest.decompile.m"