blob: 10b354121d11b614b31e9d5c5ad7c48c6eab1081 [file] [log] [blame]
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build ignore
#import <Foundation/Foundation.h>
#import "GoTestpkg.h"
#define ERROR(...) \
do { \
NSLog(__VA_ARGS__); \
err = 1; \
} while (0);
static int err = 0;
void testConst() {
if (![GoTestpkgAString isEqualToString:@"a string"]) {
ERROR(@"GoTestpkgAString = %@, want 'a string'", GoTestpkgAString);
}
if (GoTestpkgAnInt != 7) {
ERROR(@"GoTestpkgAnInt = %lld, want 7", GoTestpkgAnInt);
}
if (ABS(GoTestpkgAFloat - 0.12345) > 0.0001) {
ERROR(@"GoTestpkgAFloat = %f, want 0.12345", GoTestpkgAFloat);
}
if (GoTestpkgABool != YES) {
ERROR(@"GoTestpkgABool = %@, want YES", GoTestpkgAFloat ? @"YES" : @"NO");
}
if (GoTestpkgMinInt32 != INT32_MIN) {
ERROR(@"GoTestpkgMinInt32 = %d, want %d", GoTestpkgMinInt32, INT32_MIN);
}
if (GoTestpkgMaxInt32 != INT32_MAX) {
ERROR(@"GoTestpkgMaxInt32 = %d, want %d", GoTestpkgMaxInt32, INT32_MAX);
}
if (GoTestpkgMinInt64 != INT64_MIN) {
ERROR(@"GoTestpkgMinInt64 = %lld, want %lld", GoTestpkgMinInt64, INT64_MIN);
}
if (GoTestpkgMaxInt64 != INT64_MAX) {
ERROR(@"GoTestpkgMaxInt64 = %lld, want %lld", GoTestpkgMaxInt64, INT64_MAX);
}
if (ABS(GoTestpkgSmallestNonzeroFloat64 -
4.940656458412465441765687928682213723651e-324) > 1e-323) {
ERROR(@"GoTestpkgSmallestNonzeroFloat64 = %f, want %f",
GoTestpkgSmallestNonzeroFloat64,
4.940656458412465441765687928682213723651e-324);
}
if (ABS(GoTestpkgMaxFloat64 -
1.797693134862315708145274237317043567981e+308) > 0.0001) {
ERROR(@"GoTestpkgMaxFloat64 = %f, want %f", GoTestpkgMaxFloat64,
1.797693134862315708145274237317043567981e+308);
}
if (ABS(GoTestpkgSmallestNonzeroFloat32 -
1.401298464324817070923729583289916131280e-45) > 1e-44) {
ERROR(@"GoTestpkgSmallestNonzeroFloat32 = %f, want %f",
GoTestpkgSmallestNonzeroFloat32,
1.401298464324817070923729583289916131280e-45);
}
if (ABS(GoTestpkgMaxFloat32 - 3.40282346638528859811704183484516925440e+38) >
0.0001) {
ERROR(@"GoTestpkgMaxFloat32 = %f, want %f", GoTestpkgMaxFloat32,
3.40282346638528859811704183484516925440e+38);
}
if (ABS(GoTestpkgLog2E -
1 / 0.693147180559945309417232121458176568075500134360255254120680009) >
0.0001) {
ERROR(
@"GoTestpkgLog2E = %f, want %f", GoTestpkgLog2E,
1 / 0.693147180559945309417232121458176568075500134360255254120680009);
}
}
void testHello(NSString *input) {
NSString *got = GoTestpkgHello(input);
NSString *want = [NSString stringWithFormat:@"Hello, %@!", input];
if (!got) {
ERROR(@"GoTestpkgHello(%@)= NULL, want %@", input, want);
return;
}
if (![got isEqualToString:want]) {
ERROR(@"want %@\nGoTestpkgHello(%@)= %@", want, input, got);
}
}
void testString() {
NSString *input = @"";
NSString *got = GoTestpkgEcho(input);
if (!got || ![got isEqualToString:input]) {
ERROR(@"want %@\nGoTestpkgEcho(%@)= %@", input, input, got);
}
input = @"FOO";
got = GoTestpkgEcho(input);
if (!got || ![got isEqualToString:input]) {
ERROR(@"want %@\nGoTestpkgEcho(%@)= %@", input, input, got);
}
}
void testBytesAppend(NSString *a, NSString *b) {
NSData *data_a = [a dataUsingEncoding:NSUTF8StringEncoding];
NSData *data_b = [b dataUsingEncoding:NSUTF8StringEncoding];
NSData *gotData = GoTestpkgBytesAppend(data_a, data_b);
NSString *got =
[[NSString alloc] initWithData:gotData encoding:NSUTF8StringEncoding];
NSString *want = [a stringByAppendingString:b];
if (![got isEqualToString:want]) {
ERROR(@"want %@\nGoTestpkgBytesAppend(%@, %@) = %@", want, a, b, got);
}
}
void testReturnsError() {
NSString *value;
NSError *error;
GoTestpkgReturnsError(TRUE, &value, &error);
NSString *got = [error.userInfo valueForKey:NSLocalizedDescriptionKey];
NSString *want = @"Error";
if (![got isEqualToString:want]) {
ERROR(@"want %@\nGoTestpkgReturnsError(TRUE) = (%@, %@)", want, value, got);
}
}
void testStruct() {
GoTestpkgS *s = GoTestpkgNewS(10.0, 100.0);
if (!s) {
ERROR(@"GoTestpkgNewS returned NULL");
}
double x = [s x];
double y = [s y];
double sum = [s sum];
if (x != 10.0 || y != 100.0 || sum != 110.0) {
ERROR(@"GoTestpkgS(10.0, 100.0).X=%f Y=%f SUM=%f; want 10, 100, 110", x, y,
sum);
}
double sum2 = GoTestpkgCallSSum(s);
if (sum != sum2) {
ERROR(@"GoTestpkgCallSSum(s)=%f; want %f as returned by s.Sum", sum2, sum);
}
[s setX:7];
[s setY:70];
x = [s x];
y = [s y];
sum = [s sum];
if (x != 7 || y != 70 || sum != 77) {
ERROR(@"GoTestpkgS(7, 70).X=%f Y=%f SUM=%f; want 7, 70, 77", x, y, sum);
}
NSString *first = @"trytwotested";
NSString *second = @"test";
NSString *got = [s tryTwoStrings:first second:second];
NSString *want = [first stringByAppendingString:second];
if (![got isEqualToString:want]) {
ERROR(@"GoTestpkgS_TryTwoStrings(%@, %@)= %@; want %@", first, second, got,
want);
}
GoTestpkgGC();
}
// Objective-C implementation of testpkg.I.
@interface Number : NSObject <GoTestpkgI> {
}
@property int32_t value;
// TODO(hyangah): error:error is not good.
- (BOOL)error:(BOOL)e error:(NSError **)error;
- (int64_t)times:(int32_t)v;
@end
// numI is incremented when the first numI objective-C implementation is
// deallocated.
static int numI = 0;
@implementation Number {
}
@synthesize value;
- (BOOL)stringError:(NSString *)s
ret0_:(NSString **)ret0_
error:(NSError **)error {
if ([s isEqualTo:@"number"]) {
if (ret0_ != NULL) {
*ret0_ = @"OK";
}
return true;
}
return false;
}
- (BOOL)error:(BOOL)triggerError error:(NSError **)error {
if (!triggerError) {
return YES;
}
if (error != NULL) {
*error = [NSError errorWithDomain:@"SeqTest" code:1 userInfo:NULL];
}
return NO;
}
- (int64_t)times:(int32_t)v {
return v * value;
}
- (void)dealloc {
if (self.value == 0) {
numI++;
}
}
@end
void testInterface() {
// Test Go object implementing testpkg.I is handled correctly.
id<GoTestpkgI> goObj = GoTestpkgNewI();
int64_t got = [goObj times:10];
if (got != 100) {
ERROR(@"GoTestpkgNewI().times(10) = %lld; want %d", got, 100);
}
int32_t key = -1;
GoTestpkgRegisterI(key, goObj);
int64_t got2 = GoTestpkgMultiply(key, 10);
if (got != got2) {
ERROR(@"GoTestpkgMultiply(10 * 10) = %lld; want %lld", got2, got);
}
GoTestpkgUnregisterI(key);
// Test Objective-C objects implementing testpkg.I is handled correctly.
@autoreleasepool {
for (int32_t i = 0; i < 10; i++) {
Number *num = [[Number alloc] init];
num.value = i;
GoTestpkgRegisterI(i, num);
}
GoTestpkgGC();
}
// Registered Objective-C objects are pinned on Go side which must
// prevent deallocation from Objective-C.
for (int32_t i = 0; i < 10; i++) {
int64_t got = GoTestpkgMultiply(i, 2);
if (got != i * 2) {
ERROR(@"GoTestpkgMultiply(%d, 2) = %lld; want %d", i, got, i * 2);
return;
}
GoTestpkgUnregisterI(i);
GoTestpkgGC();
}
// Unregistered all Objective-C objects.
}
void testIssue12307() {
Number *num = [[Number alloc] init];
num.value = 1024;
NSError *error;
if (GoTestpkgCallIError(num, YES, &error) == YES) {
ERROR(@"GoTestpkgCallIError(Number, YES) succeeded; want error");
}
NSError *error2;
if (GoTestpkgCallIError(num, NO, &error2) == NO) {
ERROR(@"GoTestpkgCallIError(Number, NO) failed(%@); want success", error2);
}
}
void testIssue12403() {
Number *num = [[Number alloc] init];
num.value = 1024;
NSString *ret;
NSError *error;
if (GoTestpkgCallIStringError(num, @"alphabet", &ret, &error) == YES) {
ERROR(
@"GoTestpkgCallIStringError(Number, 'alphabet') succeeded; want error");
}
NSError *error2;
if (GoTestpkgCallIStringError(num, @"number", &ret, &error2) == NO) {
ERROR(
@"GoTestpkgCallIStringError(Number, 'number') failed(%@); want success",
error2);
} else if (![ret isEqualTo:@"OK"]) {
ERROR(@"GoTestpkgCallIStringError(Number, 'number') returned unexpected "
@"results %@",
ret);
}
}
void testVar() {
NSString *s = GoTestpkg.stringVar;
if (![s isEqualToString:@"a string var"]) {
ERROR(@"GoTestpkg.StringVar = %@, want 'a string var'", s);
}
s = @"a new string var";
GoTestpkg.stringVar = s;
NSString *s2 = GoTestpkg.stringVar;
if (![s2 isEqualToString:s]) {
ERROR(@"GoTestpkg.stringVar = %@, want %@", s2, s);
}
int64_t i = GoTestpkg.intVar;
if (i != 77) {
ERROR(@"GoTestpkg.intVar = %lld, want 77", i);
}
GoTestpkg.intVar = 777;
i = GoTestpkg.intVar;
if (i != 777) {
ERROR(@"GoTestpkg.intVar = %lld, want 777", i);
}
[GoTestpkg setIntVar:7777];
i = [GoTestpkg intVar];
if (i != 7777) {
ERROR(@"GoTestpkg.intVar = %lld, want 7777", i);
}
GoTestpkgNode *n0 = GoTestpkg.structVar;
if (![n0.v isEqualToString:@"a struct var"]) {
ERROR(@"GoTestpkg.structVar = %@, want 'a struct var'", n0.v);
}
GoTestpkgNode *n1 = GoTestpkgNewNode(@"a new struct var");
GoTestpkg.structVar = n1;
GoTestpkgNode *n2 = GoTestpkg.structVar;
if (![n2.v isEqualToString:@"a new struct var"]) {
ERROR(@"GoTestpkg.StructVar = %@, want 'a new struct var'", n2.v);
}
Number *num = [[Number alloc] init];
num.value = 12345;
GoTestpkg.interfaceVar = num;
id<GoTestpkgI> iface = GoTestpkg.interfaceVar;
int64_t x = [iface times:10];
int64_t y = [num times:10];
if (x != y) {
ERROR(@"GoTestpkg.InterfaceVar Times 10 = %lld, want %lld", x, y);
}
}
// Invokes functions and object methods defined in Testpkg.h.
//
// TODO(hyangah): apply testing framework (e.g. XCTestCase)
// and test through xcodebuild.
int main(void) {
@autoreleasepool {
GoTestpkgHi();
GoTestpkgInt(42);
int64_t sum = GoTestpkgSum(31, 21);
if (sum != 52) {
ERROR(@"GoTestpkgSum(31, 21) = %lld, want 52\n", sum);
}
testHello(@"세계"); // korean, utf-8, world.
testString();
unichar t[] = {
0xD83D, 0xDCA9,
}; // utf-16, pile of poo.
testHello([NSString stringWithCharacters:t length:2]);
testBytesAppend(@"Foo", @"Bar");
testStruct();
int numS = GoTestpkgCollectS(
1, 10); // within 10 seconds, collect the S used in testStruct.
if (numS != 1) {
ERROR(@"%d S objects were collected; S used in testStruct is supposed to "
@"be collected.",
numS);
}
@autoreleasepool {
testInterface();
}
if (numI != 1) {
ERROR(@"%d I objects were collected; I used in testInterface is supposed "
@"to be collected.",
numI);
}
testConst();
testIssue12307();
testVar();
}
fprintf(stderr, "%s\n", err ? "FAIL" : "PASS");
return err;
}