github.com/F4RD1N/gomobile@v1.0.1/bind/objc/SeqTest.m (about)

     1  // Copyright 2015 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // +build ignore
     6  
     7  #import <Foundation/Foundation.h>
     8  #import <XCTest/XCTest.h>
     9  #import "testpkg/Testpkg.h"
    10  
    11  // Objective-C implementation of testpkg.I2.
    12  @interface Number : NSObject <TestpkgI2> {
    13  }
    14  @property int32_t value;
    15  
    16  // TODO(hyangah): error:error is not good.
    17  - (BOOL)error:(BOOL)e error:(NSError **)error;
    18  - (int64_t)times:(int32_t)v;
    19  @end
    20  
    21  // numI is incremented when the first numI objective-C implementation is
    22  // deallocated.
    23  static int numI = 0;
    24  
    25  @implementation Number {
    26  }
    27  @synthesize value;
    28  
    29  - (NSString *)stringError:(NSString *)s
    30                error:(NSError **)error {
    31     if ([s isEqualToString:@"number"]) {
    32         return @"OK";
    33     }
    34     *error = [NSError errorWithDomain:@"SeqTest" code:1 userInfo:@{NSLocalizedDescriptionKey: @"NumberError"}];
    35     return NULL;
    36  }
    37  
    38  - (BOOL)error:(BOOL)triggerError error:(NSError **)error {
    39      if (!triggerError) {
    40          return YES;
    41      }
    42      if (error != NULL) {
    43          *error = [NSError errorWithDomain:@"SeqTest" code:1 userInfo:NULL];
    44      }
    45      return NO;
    46  }
    47  
    48  - (int64_t)times:(int32_t)v {
    49      return v * value;
    50  }
    51  
    52  - (void)dealloc {
    53      if (self.value == 0) {
    54          numI++;
    55      }
    56  }
    57  @end
    58  
    59  // Objective-C implementation of testpkg.NullTest.
    60  @interface NullTest : NSObject <TestpkgNullTest> {
    61  }
    62  
    63  - (TestpkgNullTest *)null;
    64  @end
    65  
    66  @implementation NullTest {
    67  }
    68  
    69  - (TestpkgNullTest *)null {
    70    return nil;
    71  }
    72  @end
    73  
    74  // Objective-C implementation of testpkg.InterfaceDupper.
    75  @interface IDup : NSObject <TestpkgInterfaceDupper> {
    76  }
    77  
    78  @end
    79  
    80  @implementation IDup {
    81  }
    82  
    83  - (id<TestpkgInterface>)iDup:(id<TestpkgInterface>)i {
    84    return i;
    85  }
    86  @end
    87  
    88  // Objective-C implementation of testpkg.ConcreteDupper.
    89  @interface CDup : NSObject <TestpkgConcreteDupper> {
    90  }
    91  
    92  @end
    93  
    94  @implementation CDup {
    95  }
    96  
    97  - (TestpkgConcrete *)cDup:(TestpkgConcrete *)c {
    98    return c;
    99  }
   100  @end
   101  
   102  // Objective-C implementation of testpkg.EmptyThrower.
   103  @interface EmptyErrorer: NSObject <TestpkgEmptyErrorer> {
   104  }
   105  
   106  @end
   107  
   108  @implementation EmptyErrorer {
   109  }
   110  
   111  - (BOOL)emptyError:(NSError **)error {
   112  	*error = [NSError errorWithDomain:@"SeqTest" code:1 userInfo:NULL];
   113  	return NO;
   114  }
   115  @end
   116  
   117  @interface tests : XCTestCase
   118  
   119  @end
   120  
   121  @implementation tests
   122  
   123  - (void)setUp {
   124  	[super setUp];
   125  }
   126  
   127  - (void)tearDown {
   128  	[super tearDown];
   129  }
   130  
   131  - (void)testBasics {
   132  	TestpkgHi();
   133  
   134  	TestpkgInt(42);
   135  }
   136  
   137  - (void)testAdd {
   138  	int64_t sum = TestpkgAdd(31, 21);
   139  	XCTAssertEqual(sum, 52, @"TestpkgSum(31, 21) = %lld, want 52\n", sum);
   140  }
   141  
   142  - (void)testHello:(NSString *)input {
   143  	NSString *got = TestpkgAppendHello(input);
   144  	NSString *want = [NSString stringWithFormat:@"Hello, %@!", input];
   145  	XCTAssertEqualObjects(got, want, @"want %@\nTestpkgHello(%@)= %@", want, input, got);
   146  }
   147  
   148  - (void)testHellos {
   149  	[self testHello:@"세계"]; // korean, utf-8, world.
   150  	unichar t[] = {
   151  		0xD83D, 0xDCA9,
   152  	}; // utf-16, pile of poo.
   153  	[self testHello:[NSString stringWithCharacters:t length:2]];
   154  }
   155  
   156  - (void)testString {
   157  	NSString *input = @"";
   158  	NSString *got = TestpkgStrDup(input);
   159  	XCTAssertEqualObjects(got, input, @"want %@\nTestpkgEcho(%@)= %@", input, input, got);
   160  
   161  	input = @"FOO";
   162  	got = TestpkgStrDup(input);
   163  	XCTAssertEqualObjects(got, input, @"want %@\nTestpkgEcho(%@)= %@", input, input, got);
   164  }
   165  
   166  - (void)testStruct {
   167  	TestpkgS2 *s = TestpkgNewS2(10.0, 100.0);
   168  	XCTAssertNotNil(s, @"TestpkgNewS2 returned NULL");
   169  
   170  	double x = [s x];
   171  	double y = [s y];
   172  	double sum = [s sum];
   173  	XCTAssertTrue(x == 10.0 && y == 100.0 && sum == 110.0,
   174  			@"TestpkgS2(10.0, 100.0).X=%f Y=%f SUM=%f; want 10, 100, 110", x, y, sum);
   175  
   176  	double sum2 = TestpkgCallSSum(s);
   177  	XCTAssertEqual(sum, sum2, @"TestpkgCallSSum(s)=%f; want %f as returned by s.Sum", sum2, sum);
   178  
   179  	[s setX:7];
   180  	[s setY:70];
   181  	x = [s x];
   182  	y = [s y];
   183  	sum = [s sum];
   184  	XCTAssertTrue(x == 7 && y == 70 && sum == 77,
   185  		@"TestpkgS2(7, 70).X=%f Y=%f SUM=%f; want 7, 70, 77", x, y, sum);
   186  
   187  	NSString *first = @"trytwotested";
   188  	NSString *second = @"test";
   189  	NSString *got = [s tryTwoStrings:first second:second];
   190  	NSString *want = [first stringByAppendingString:second];
   191  	XCTAssertEqualObjects(got, want, @"TestpkgS_TryTwoStrings(%@, %@)= %@; want %@", first, second, got, want);
   192  }
   193  
   194  - (void)testCollectS {
   195  	@autoreleasepool {
   196  		[self testStruct];
   197  	}
   198  
   199  	TestpkgGC();
   200  	long numS = TestpkgCollectS2(
   201  		1, 10); // within 10 seconds, collect the S used in testStruct.
   202  	XCTAssertEqual(numS, 1, @"%ld S objects were collected; S used in testStruct is supposed to "
   203  		@"be collected.",
   204  		numS);
   205  }
   206  - (void)testBytesAppend {
   207  	NSString *a = @"Foo";
   208  	NSString *b = @"Bar";
   209  	NSData *data_a = [a dataUsingEncoding:NSUTF8StringEncoding];
   210  	NSData *data_b = [b dataUsingEncoding:NSUTF8StringEncoding];
   211  	NSData *gotData = TestpkgBytesAppend(data_a, data_b);
   212  	NSString *got = [[NSString alloc] initWithData:gotData encoding:NSUTF8StringEncoding];
   213  	NSString *want = [a stringByAppendingString:b];
   214  	XCTAssertEqualObjects(got, want, @"want %@\nTestpkgBytesAppend(%@, %@) = %@", want, a, b, got);
   215  }
   216  
   217  - (void)testInterface {
   218  	// Test Go object implementing testpkg.I is handled correctly.
   219  	id<TestpkgI2> goObj = TestpkgNewI();
   220  	int64_t got = [goObj times:10];
   221  	XCTAssertEqual(got, 100, @"TestpkgNewI().times(10) = %lld; want %d", got, 100);
   222  	int32_t key = -1;
   223  	TestpkgRegisterI(key, goObj);
   224  	int64_t got2 = TestpkgMultiply(key, 10);
   225  	XCTAssertEqual(got, got2, @"TestpkgMultiply(10 * 10) = %lld; want %lld", got2, got);
   226  	TestpkgUnregisterI(key);
   227  
   228  	// Test Objective-C objects implementing testpkg.I is handled correctly.
   229  	@autoreleasepool {
   230  		for (int32_t i = 0; i < 10; i++) {
   231  			Number *num = [[Number alloc] init];
   232  			num.value = i;
   233  			TestpkgRegisterI(i, num);
   234  		}
   235  		TestpkgGC();
   236  	}
   237  
   238  	// Registered Objective-C objects are pinned on Go side which must
   239  	// prevent deallocation from Objective-C.
   240  	for (int32_t i = 0; i < 10; i++) {
   241  		int64_t got = TestpkgMultiply(i, 2);
   242  		XCTAssertEqual(got, i * 2,@"TestpkgMultiply(%d, 2) = %lld; want %d", i, got, i * 2);
   243  		TestpkgUnregisterI(i);
   244  		TestpkgGC();
   245  	}
   246  	// Unregistered all Objective-C objects.
   247  }
   248  
   249  - (void)testCollectI {
   250  	@autoreleasepool {
   251  		[self testInterface];
   252  	}
   253  	XCTAssertEqual(numI, 1, @"%d I objects were collected; I used in testInterface is supposed "
   254  		@"to be collected.", numI);
   255  }
   256  
   257  - (void)testConst {
   258  	XCTAssertEqualObjects(TestpkgAString, @"a string", @"TestpkgAString = %@, want 'a string'", TestpkgAString);
   259  	XCTAssertEqual(TestpkgAnInt, 7, @"TestpkgAnInt = %lld, want 7", TestpkgAnInt);
   260  	XCTAssertTrue(ABS(TestpkgAFloat - 0.12345) < 0.0001, @"TestpkgAFloat = %f, want 0.12345", TestpkgAFloat);
   261  	XCTAssertTrue(TestpkgABool == YES, @"TestpkgABool = %@, want YES", TestpkgAFloat ? @"YES" : @"NO");
   262  	XCTAssertEqual(TestpkgMinInt32, INT32_MIN, @"TestpkgMinInt32 = %d, want %d", TestpkgMinInt32, INT32_MIN);
   263  	XCTAssertEqual(TestpkgMaxInt32, INT32_MAX, @"TestpkgMaxInt32 = %d, want %d", TestpkgMaxInt32, INT32_MAX);
   264  	XCTAssertEqual(TestpkgMinInt64, INT64_MIN, @"TestpkgMinInt64 = %lld, want %lld", TestpkgMinInt64, INT64_MIN);
   265  	XCTAssertEqual(TestpkgMaxInt64, INT64_MAX, @"TestpkgMaxInt64 = %lld, want %lld", TestpkgMaxInt64, INT64_MAX);
   266  	XCTAssertTrue(ABS(TestpkgSmallestNonzeroFloat64 -
   267  		4.940656458412465441765687928682213723651e-324) < 1e-323, @"TestpkgSmallestNonzeroFloat64 = %f, want %f",
   268  		TestpkgSmallestNonzeroFloat64,
   269  		4.940656458412465441765687928682213723651e-324);
   270  	XCTAssertTrue(ABS(TestpkgMaxFloat64 -
   271  		1.797693134862315708145274237317043567981e+308) < 0.0001, @"TestpkgMaxFloat64 = %f, want %f", TestpkgMaxFloat64,
   272  		1.797693134862315708145274237317043567981e+308);
   273  	XCTAssertTrue(ABS(TestpkgSmallestNonzeroFloat32 -
   274  		1.401298464324817070923729583289916131280e-45) < 1e-44, @"TestpkgSmallestNonzeroFloat32 = %f, want %f",
   275  		TestpkgSmallestNonzeroFloat32,
   276  		1.401298464324817070923729583289916131280e-45);
   277  	XCTAssertTrue(ABS(TestpkgMaxFloat32 - 3.40282346638528859811704183484516925440e+38) < 0.0001,
   278  		@"TestpkgMaxFloat32 = %f, want %f", TestpkgMaxFloat32, 3.40282346638528859811704183484516925440e+38);
   279  	XCTAssertTrue(ABS(TestpkgLog2E - 1 / 0.693147180559945309417232121458176568075500134360255254120680009) < 0.0001,
   280  		@"TestpkgLog2E = %f, want %f", TestpkgLog2E, 1 / 0.693147180559945309417232121458176568075500134360255254120680009);
   281  }
   282  
   283  - (void)testIssue12307 {
   284  	Number *num = [[Number alloc] init];
   285  	num.value = 1024;
   286  	NSError *error;
   287  	XCTAssertFalse(TestpkgCallIError(num, YES, &error), @"TestpkgCallIError(Number, YES) succeeded; want error");
   288  	NSError *error2;
   289  	XCTAssertTrue(TestpkgCallIError(num, NO, &error2), @"TestpkgCallIError(Number, NO) failed(%@); want success", error2);
   290  }
   291  
   292  - (void)testErrorField {
   293  	NSString *wantMsg = @"an error message";
   294  	NSError *want = [NSError errorWithDomain:@"SeqTest" code:1 userInfo:@{NSLocalizedDescriptionKey: wantMsg}];
   295  	TestpkgNode *n = TestpkgNewNode(@"ErrTest");
   296  	n.err = want;
   297  	NSError *got = n.err;
   298  	XCTAssertEqual(got, want, @"got different objects after roundtrip");
   299  	NSString *gotMsg = TestpkgErrorMessage(want);
   300  	XCTAssertEqualObjects(gotMsg, wantMsg, @"err = %@, want %@", gotMsg, wantMsg);
   301  }
   302  
   303  - (void)testErrorDup {
   304  	NSError *err = Testpkg.globalErr;
   305  	XCTAssertTrue(TestpkgIsGlobalErr(err), @"A Go error must preserve its identity across the boundary");
   306  	XCTAssertEqualObjects([err localizedDescription], @"global err", "A Go error message must be preserved");
   307  }
   308  
   309  - (void)testVar {
   310  	NSString *s = Testpkg.stringVar;
   311  	XCTAssertEqualObjects(s, @"a string var", @"Testpkg.StringVar = %@, want 'a string var'", s);
   312  	s = @"a new string var";
   313  	Testpkg.stringVar = s;
   314  	NSString *s2 = Testpkg.stringVar;
   315  	XCTAssertEqualObjects(s2, s, @"Testpkg.stringVar = %@, want %@", s2, s);
   316  
   317  	int64_t i = Testpkg.intVar;
   318  	XCTAssertEqual(i, 77, @"Testpkg.intVar = %lld, want 77", i);
   319  	Testpkg.intVar = 777;
   320  	i = Testpkg.intVar;
   321  	XCTAssertEqual(i, 777, @"Testpkg.intVar = %lld, want 777", i);
   322  	[Testpkg setIntVar:7777];
   323  	i = [Testpkg intVar];
   324  	XCTAssertEqual(i, 7777, @"Testpkg.intVar = %lld, want 7777", i);
   325  
   326  	TestpkgNode *n0 = Testpkg.nodeVar;
   327  	XCTAssertEqualObjects(n0.v, @"a struct var", @"Testpkg.NodeVar = %@, want 'a struct var'", n0.v);
   328  	TestpkgNode *n1 = TestpkgNewNode(@"a new struct var");
   329  	Testpkg.nodeVar = n1;
   330  	TestpkgNode *n2 = Testpkg.nodeVar;
   331  	XCTAssertEqualObjects(n2.v, @"a new struct var", @"Testpkg.NodeVar = %@, want 'a new struct var'", n2.v);
   332  
   333  	Number *num = [[Number alloc] init];
   334  	num.value = 12345;
   335  	Testpkg.interfaceVar2 = num;
   336  	id<TestpkgI2> iface = Testpkg.interfaceVar2;
   337  	int64_t x = [iface times:10];
   338  	int64_t y = [num times:10];
   339  	XCTAssertEqual(x, y, @"Testpkg.InterfaceVar2 Times 10 = %lld, want %lld", x, y);
   340  }
   341  
   342  - (void)testIssue12403 {
   343  	Number *num = [[Number alloc] init];
   344  	num.value = 1024;
   345  
   346  	NSError *error;
   347  	NSString *ret = TestpkgCallIStringError(num, @"alphabet", &error);
   348  	XCTAssertNil(ret, @"TestpkgCallIStringError(Number, 'alphabet') succeeded(%@); want error", ret);
   349  	NSString *desc = [error localizedDescription];
   350  	XCTAssertEqualObjects(desc, @"NumberError", @"TestpkgCallIStringError(Number, 'alphabet') returned unexpected error message %@", desc);
   351  	NSError *error2;
   352  	NSString *ret2 = TestpkgCallIStringError(num, @"number", &error2);
   353  	XCTAssertNotNil(ret2, @"TestpkgCallIStringError(Number, 'number') failed(%@); want success", error2);
   354  	XCTAssertEqualObjects(ret2, @"OK", @"TestpkgCallIStringError(Number, 'number') returned unexpected results %@", ret2);
   355  }
   356  
   357  - (void)testStrDup:(NSString *)want {
   358  	NSString *got = TestpkgStrDup(want);
   359  	XCTAssertEqualObjects(want, got, @"StrDup returned %@; expected %@", got, want);
   360  }
   361  
   362  - (void)testUnicodeStrings {
   363  	[self testStrDup:@"abcxyz09{}"];
   364  	[self testStrDup:@"Hello, 世界"];
   365  	[self testStrDup:@"\uffff\U00010000\U00010001\U00012345\U0010ffff"];
   366  }
   367  
   368  - (void)testByteArrayRead {
   369  	NSData *arr = [NSMutableData dataWithLength:8];
   370  	long n;
   371  	XCTAssertTrue(TestpkgReadIntoByteArray(arr, &n, nil), @"ReadIntoByteArray failed");
   372  	XCTAssertEqual(n, 8, @"ReadIntoByteArray wrote %ld bytes, expected %d", n, 8);
   373  	const uint8_t *b = [arr bytes];
   374  	for (int i = 0; i < [arr length]; i++) {
   375  		XCTAssertEqual(b[i], i, @"ReadIntoByteArray wrote %d at %d; expected %d", b[i], i, i);
   376  	}
   377  	// Test that immutable data cannot be changed from Go
   378  	const uint8_t buf[] = {42};
   379  	arr = [NSData dataWithBytes:buf length:1];
   380  	XCTAssertTrue(TestpkgReadIntoByteArray(arr, &n, nil), @"ReadIntoByteArray failed");
   381  	XCTAssertEqual(n, 1, @"ReadIntoByteArray wrote %ld bytes, expected %d", n, 8);
   382  	b = [arr bytes];
   383  	XCTAssertEqual(b[0], 42, @"ReadIntoByteArray wrote to an immutable NSData; expected no change");
   384  }
   385  
   386  - (void)testNilField {
   387  	TestpkgNullFieldStruct *s = TestpkgNewNullFieldStruct();
   388  	XCTAssertNil([s f], @"NullFieldStruct has non-nil field; expected nil");
   389  }
   390  
   391  - (void)testNullReferences {
   392  	NullTest *t = [[NullTest alloc] init];
   393  	XCTAssertTrue(TestpkgCallWithNull(nil, t), @"Testpkg.CallWithNull failed");
   394  	id<TestpkgI> i = TestpkgNewNullInterface();
   395  	XCTAssertNil(i, @"NewNullInterface() returned %p; expected nil", i);
   396  	TestpkgS *s = TestpkgNewNullStruct();
   397  	XCTAssertNil(s, @"NewNullStruct() returned %p; expected nil", s);
   398  	TestpkgIssue20330 *nullArger = TestpkgNewIssue20330();
   399  	XCTAssertTrue([nullArger callWithNull:nil], @"Issue20330.CallWithNull failed");
   400  }
   401  
   402  - (void)testReturnsError {
   403  	NSError *error;
   404  	NSString *value = TestpkgReturnsError(TRUE, &error);
   405  	NSString *got = [error.userInfo valueForKey:NSLocalizedDescriptionKey];
   406  	NSString *want = @"Error";
   407  	XCTAssertEqualObjects(got, want, @"want %@\nTestpkgReturnsError(TRUE) = (%@, %@)", want, value, got);
   408  }
   409  
   410  - (void)testImportedPkg {
   411  	XCTAssertEqualObjects(SecondpkgHelloString, SecondpkgHello(), @"imported string should match");
   412  	id<SecondpkgI> i = TestpkgNewImportedI();
   413  	SecondpkgS *s = TestpkgNewImportedS();
   414  	XCTAssertEqual(8, [i f:8], @"numbers should match");
   415  	XCTAssertEqual(8, [s f:8], @"numbers should match");
   416  	i = TestpkgWithImportedI(i);
   417  	s = TestpkgWithImportedS(s);
   418  	i = [Testpkg importedVarI];
   419  	s = [Testpkg importedVarS];
   420  	[Testpkg setImportedVarI:i];
   421  	[Testpkg setImportedVarS:s];
   422  	TestpkgImportedFields *fields = TestpkgNewImportedFields();
   423  	i = [fields i];
   424  	s = [fields s];
   425  	[fields setI:i];
   426  	[fields setS:s];
   427  }
   428  
   429  - (void)testRoundTripEquality {
   430  	Number *want = [[Number alloc] init];
   431  	Number *got = (Number *)TestpkgI2Dup(want);
   432  	XCTAssertEqual(got, want, @"ObjC object passed through Go should not be wrapped");
   433  
   434  	IDup *idup = [[IDup alloc] init];
   435  	XCTAssertTrue(TestpkgCallIDupper(idup), @"Go interface passed through ObjC should not be wrapped");
   436  	CDup *cdup = [[CDup alloc] init];
   437  	XCTAssertTrue(TestpkgCallCDupper(cdup), @"Go struct passed through ObjC should not be wrapped");
   438  }
   439  
   440  - (void)testEmptyError {
   441  	NSError *error;
   442  	XCTAssertFalse(TestpkgEmptyError(&error), @"GoTestpkgEmptyError succeeded; want error");
   443  	XCTAssertNotNil(error, @"TestpkgEmptyError returned nil error");
   444  	id<TestpkgEmptyErrorer> empty = [[EmptyErrorer alloc] init];
   445  	XCTAssertFalse(TestpkgCallEmptyError(empty, &error), @"TestpkgCallEmptyError succeeded; want error");
   446  	XCTAssertNotNil(error, @"TestpkgCallEmptyError returned nil error");
   447  }
   448  
   449  - (void)testSIGPIPE {
   450  	TestpkgTestSIGPIPE();
   451  }
   452  
   453  - (void)testTags {
   454  	XCTAssertEqual(42, TestpkgTaggedConst, @"Tagged const must exist");
   455  }
   456  
   457  - (void)testConstructors {
   458  	id<TestpkgInterface> i = [[TestpkgConcrete alloc] init];
   459  	[i f];
   460  
   461  	TestpkgS2 *s = [[TestpkgS2 alloc] init:1 y:2];
   462  	XCTAssertEqual(3.0, [s sum]);
   463  	XCTAssertEqualObjects(@"gostring", [s tryTwoStrings:@"go" second:@"string"]);
   464  
   465  	TestpkgS3 *s3 __attribute__((unused)) = [[TestpkgS3 alloc] init];
   466  
   467  	TestpkgS4 *s4 = [[TestpkgS4 alloc] initWithInt:123];
   468  	XCTAssertEqual(123, s4.i);
   469  
   470  	s4 = [[TestpkgS4 alloc] initWithFloat: 123.456];
   471  	XCTAssertEqual(123, s4.i);
   472  
   473  	s4 = [[TestpkgS4 alloc] initWithBoolAndError: false];
   474  	XCTAssertEqual(0, s4.i);
   475  
   476  	s4 = [[TestpkgS4 alloc] initWithBoolAndError: true];
   477  	XCTAssertEqual(s4, NULL);
   478  }
   479  
   480  @end