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