diff options
author | Benoit Foucher <benoit@zeroc.com> | 2016-12-16 15:56:18 +0100 |
---|---|---|
committer | Benoit Foucher <benoit@zeroc.com> | 2016-12-16 15:56:18 +0100 |
commit | 66e63999fd121114d27842f1bf3cd2121ccf320c (patch) | |
tree | cf20b42e13a4899f2182acc9a572cbae43987358 /objective-c/test/ios/controller/Classes/ViewController.m | |
parent | Remove unused Makefile (diff) | |
download | ice-66e63999fd121114d27842f1bf3cd2121ccf320c.tar.bz2 ice-66e63999fd121114d27842f1bf3cd2121ccf320c.tar.xz ice-66e63999fd121114d27842f1bf3cd2121ccf320c.zip |
Added support for Objective-C controller
Diffstat (limited to 'objective-c/test/ios/controller/Classes/ViewController.m')
-rw-r--r-- | objective-c/test/ios/controller/Classes/ViewController.m | 626 |
1 files changed, 351 insertions, 275 deletions
diff --git a/objective-c/test/ios/controller/Classes/ViewController.m b/objective-c/test/ios/controller/Classes/ViewController.m index 4807eeb9acc..6773a7f986e 100644 --- a/objective-c/test/ios/controller/Classes/ViewController.m +++ b/objective-c/test/ios/controller/Classes/ViewController.m @@ -8,377 +8,413 @@ // ********************************************************************** #import "ViewController.h" - -#import <objc/Ice/Ice.h> #import <Controller.h> +#import <TestCommon.h> -@interface ViewController() --(void) print:(NSString*)msg; --(void) println:(NSString*)msg; -@end - -namespace -{ - -typedef int (*MAIN_ENTRY_POINT)(int argc, char** argv, Test::MainHelper* helper); -typedef int (*SHUTDOWN_ENTRY_POINT)(); +#include <ifaddrs.h> +#include <arpa/inet.h> +#include <net/if.h> +#include <dlfcn.h> -class MainHelperI : public Test::MainHelper, private IceUtil::Monitor<IceUtil::Mutex>, public IceUtil::Thread +@interface MainHelper : NSThread { -public: - - MainHelperI(ViewController*, const string&, const StringSeq&); - virtual ~MainHelperI(); - - virtual void serverReady(); - virtual void shutdown(); - virtual void waitForCompleted() {} - virtual bool redirect(); - virtual void print(const std::string&); - - virtual void run(); - - void completed(int); - void waitReady(int) const; - int waitSuccess(int) const; - string getOutput() const; - -private: - - ViewController* _controller; - std::string _dll; - StringSeq _args; - CFBundleRef _handle; - SHUTDOWN_ENTRY_POINT _dllTestShutdown; - bool _ready; - bool _completed; + id<ViewController> _controller; + void* _func; + NSArray* _args; + BOOL _ready; + BOOL _completed; int _status; - std::ostringstream _out; -}; - -class ProcessI : public Process -{ -public: - - ProcessI(ViewController*, MainHelperI*); - virtual ~ProcessI(); - - void waitReady(int, const Ice::Current&); - int waitSuccess(int, const Ice::Current&); - string terminate(const Ice::Current&); - -private: - - ViewController* _controller; - IceUtil::Handle<MainHelperI> _helper; -}; - -class ProcessControllerI : public ProcessController -{ -public: - - ProcessControllerI(ViewController*); - -#ifdef ICE_CPP11_MAPPING - virtual shared_ptr<ProcessPrx> - start(string, string, StringSeq, const Ice::Current&); -#else - virtual ProcessPrx - start(const string&, const string&, const StringSeq&, const Ice::Current&); -#endif - -private: - - ViewController* _controller; -}; + NSMutableString* _out; + NSCondition* _cond; +} +-(void) serverReady; +-(void) shutdown; +-(void) print:(NSString*)str; +-(void) completed:(int)status; +-(void) waitReady:(int)timeout; +-(int) waitSuccess:(int)timeout; +-(NSString*)getOutput; +@end -class ControllerHelper +@interface ProcessI : TestCommonProcess<TestCommonProcess> { -public: - - ControllerHelper(ViewController*); - virtual ~ControllerHelper(); - -private: - - Ice::CommunicatorPtr _communicator; -}; - + id<ViewController> _controller; + MainHelper* _helper; } +-(void) waitReady:(int)timeout current:(ICECurrent*)current; +-(int) waitSuccess:(int)timeout current:(ICECurrent*)current; +-(NSString*) terminate:(ICECurrent*)current; +@end -MainHelperI::MainHelperI(ViewController* controller, const string& dll, const StringSeq& args) : - _controller(controller), - _dll(dll), - _args(args), - _ready(false), - _completed(false), - _status(0) +@interface ProcessControllerI : TestCommonProcessController<TestCommonProcessController> { + id<ViewController> _controller; + NSString* _ipv4; + NSString* _ipv6; } +-(id) init:(id<ViewController>) controller ipv4:(NSString*)ipv4 ipv6:(NSString*)ipv6; +-(id<TestCommonProcessPrx>) start:(NSString*)testsuite exe:(NSString*)exe args:(NSArray*)args current:(ICECurrent*)current; +-(NSString*) getHost:(NSString*)protocol ipv6:(BOOL)ipv6 current:(ICECurrent*)current; +@end -MainHelperI::~MainHelperI() +@implementation MainHelper +-(id) init:(id<ViewController>)controller func:(void*)func args:(NSArray*)args { - if(_handle) + self = [super init]; + if(self == nil) { - CFBundleUnloadExecutable(_handle); + return nil; } + _controller = ICE_RETAIN(controller); + _func = func; + _args = ICE_RETAIN(args); + _ready = FALSE; + _completed = FALSE; + _status = 0; + _out = ICE_RETAIN([NSMutableString string]); + _cond = [NSCondition new]; + return self; } - -void -MainHelperI::serverReady() +#if defined(__clang__) && !__has_feature(objc_arc) +-(void) dealloc { - Lock sync(*this); - _ready = true; - notifyAll(); + [_controller release]; + [_args release]; + [_cond release]; + [_out release]; + [super dealloc]; } - -void -MainHelperI::shutdown() +#endif +-(void) serverReady { - Lock sync(*this); - if(_completed) + [_cond lock]; + @try { - return; + _ready = YES; + [_cond signal]; } - - if(_dllTestShutdown) + @finally { - _dllTestShutdown(); + [_cond unlock]; } } - -bool -MainHelperI::redirect() -{ - return _dll.find("client") != string::npos || _dll.find("collocated") != string::npos; -} - -void - -MainHelperI::print(const std::string& msg) -{ - _out << msg; -} - -void -MainHelperI::run() +-(void) shutdown { - NSString* bundlePath = [[NSBundle mainBundle] privateFrameworksPath]; - - bundlePath = [bundlePath stringByAppendingPathComponent:[NSString stringWithUTF8String:_dll.c_str()]]; - - NSURL* bundleURL = [NSURL fileURLWithPath:bundlePath]; - _handle = CFBundleCreate(NULL, (CFURLRef)bundleURL); - if(!_handle) - { - print([[NSString stringWithFormat:@"Could not find bundle %@", bundlePath] UTF8String]); - completed(EXIT_FAILURE); - return; - } - - CFErrorRef error = nil; - Boolean loaded = CFBundleLoadExecutableAndReturnError(_handle, &error); - if(error != nil || !loaded) + [_cond lock]; + @try { - print([[(__bridge NSError *)error description] UTF8String]); - completed(EXIT_FAILURE); - return; + if(_completed) + { + return; + } + serverStop(); } - - void* sym = dlsym(_handle, "dllTestShutdown"); - sym = CFBundleGetFunctionPointerForName(_handle, CFSTR("dllTestShutdown")); - if(sym == 0) + @finally { - NSString* err = [NSString stringWithFormat:@"Could not get function pointer dllTestShutdown from bundle %@", - bundlePath]; - print([err UTF8String]); - completed(EXIT_FAILURE); - return; + [_cond unlock]; } - _dllTestShutdown = (SHUTDOWN_ENTRY_POINT)sym; - - sym = CFBundleGetFunctionPointerForName(_handle, CFSTR("dllMain")); - if(sym == 0) +} +-(void) print:(NSString*)msg +{ + [_out appendString:msg]; +} +-(void) main +{ + int (*mainEntryPoint)(int, char**) = (int (*)(int, char**))_func; + char** argv = malloc(sizeof(char*) * (_args.count + 1)); + int i = 0; + for(NSString* arg in _args) { - NSString* err = [NSString stringWithFormat:@"Could not get function pointer dllMain from bundle %@", - bundlePath]; - print([err UTF8String]); - completed(EXIT_FAILURE); - return; + argv[i++] = (char*)[arg UTF8String]; } - - MAIN_ENTRY_POINT dllMain = (MAIN_ENTRY_POINT)sym; - char** argv = new char*[_args.size() + 1]; - for(unsigned int i = 0; i < _args.size(); ++i) + argv[_args.count] = 0; + @try { - argv[i] = const_cast<char*>(_args[i].c_str()); + [self completed:mainEntryPoint((int)_args.count, argv)]; } - argv[_args.size()] = 0; - try + @catch(NSException* ex) { - completed(dllMain(static_cast<int>(_args.size()), argv, this)); + [self print:[NSString stringWithFormat:@"unexpected exception while running `%s':%@\n", argv[0], ex]]; + [self completed:EXIT_FAILURE]; } - catch(const std::exception& ex) + free(argv); +} +-(void) completed:(int)status +{ + [_cond lock]; + @try { - print("unexpected exception while running `" + _args[0] + "':\n" + ex.what()); + _completed = YES; + _status = status; + [_cond signal]; } - catch(...) + @finally { - print("unexpected unknown exception while running `" + _args[0] + "'"); + [_cond unlock]; } - delete[] argv; } - -void -MainHelperI::completed(int status) +-(void) waitReady:(int)timeout { - Lock sync(*this); - _completed = true; - _status = status; - notifyAll(); -} - -void -MainHelperI::waitReady(int timeout) const -{ - Lock sync(*this); - while(!_ready && !_completed) + [_cond lock]; + @try { - if(!timedWait(IceUtil::Time::seconds(timeout))) + while(!_ready && !_completed) + { + if(![_cond waitUntilDate:[NSDate dateWithTimeIntervalSinceNow:timeout]]) + { + @throw [TestCommonProcessFailedException + processFailedException:@"timed out waiting for the process to be ready"]; + } + } + if(_completed && _status == EXIT_FAILURE) { - throw ProcessFailedException("timed out waiting for the process to be ready"); + @throw [TestCommonProcessFailedException processFailedException:_out]; } } - if(_completed && _status == EXIT_FAILURE) + @finally { - throw ProcessFailedException(_out.str()); + [_cond unlock]; } } - -int -MainHelperI::waitSuccess(int timeout) const +-(int) waitSuccess:(int)timeout { - Lock sync(*this); - while(!_completed) + [_cond lock]; + @try { - if(!timedWait(IceUtil::Time::seconds(timeout))) + while(!_completed) { - throw ProcessFailedException("timed out waiting for the process to succeed"); + if(timeout >= 0) + { + if(![_cond waitUntilDate:[NSDate dateWithTimeIntervalSinceNow:timeout]]) + { + @throw [TestCommonProcessFailedException + processFailedException:@"timed out waiting for the process to succeed"]; + } + } + else + { + [_cond wait]; + } } } + @finally + { + [_cond unlock]; + } return _status; } - -string -MainHelperI::getOutput() const +-(NSString*) getOutput { - assert(_completed); - return _out.str(); + return _out; } +@end -ProcessI::ProcessI(ViewController* controller, MainHelperI* helper) : _controller(controller), _helper(helper) +@implementation ProcessI +-(id) init:(id<ViewController>)controller helper:(MainHelper*)helper { + self = [super init]; + if(self == nil) + { + return nil; + } + _controller = ICE_RETAIN(controller); + _helper = ICE_RETAIN(helper); + return self; } - -ProcessI::~ProcessI() +#if defined(__clang__) && !__has_feature(objc_arc) +-(void) dealloc { + [_controller release]; + [_helper release]; + [super dealloc]; } - -void -ProcessI::waitReady(int timeout, const Ice::Current&) +#endif +-(void) waitReady:(int)timeout current:(ICECurrent*)current { - _helper->waitReady(timeout); + [_helper waitReady:timeout]; } - -int -ProcessI::waitSuccess(int timeout, const Ice::Current&) +-(int) waitSuccess:(int)timeout current:(ICECurrent*)current { - return _helper->waitSuccess(timeout); + return [_helper waitSuccess:timeout]; } - -string -ProcessI::terminate(const Ice::Current& current) +-(NSString*) terminate:(ICECurrent*)current { - _helper->shutdown(); - current.adapter->remove(current.id); - _helper->getThreadControl().join(); - return _helper->getOutput(); + [_helper shutdown]; + [current.adapter remove:current.id_]; + [_helper waitSuccess:-1]; + return [_helper getOutput]; } +@end -ProcessControllerI::ProcessControllerI(ViewController* controller) : _controller(controller) +@implementation ProcessControllerI +-(id) init:(id<ViewController>)controller ipv4:(NSString*)ipv4 ipv6:(NSString*)ipv6 { + self = [super init]; + if(self == nil) + { + return nil; + } + _controller = ICE_RETAIN(controller); + _ipv4 = ICE_RETAIN(ipv4); + _ipv6 = ICE_RETAIN(ipv6); + return self; } - -#ifdef ICE_CPP11_MAPPING -shared_ptr<ProcessPrx> -ProcessControllerI::start(string testSuite, string exe, StringSeq args, const Ice::Current& c) -#else -ProcessPrx -ProcessControllerI::start(const string& testSuite, const string& exe, const StringSeq& args, const Ice::Current& c) -#endif +#if defined(__clang__) && !__has_feature(objc_arc) +-(void) dealloc { - std::string prefix = std::string("test/") + testSuite; - replace(prefix.begin(), prefix.end(), '/', '_'); - [_controller println:[NSString stringWithFormat:@"starting %s %s... ", testSuite.c_str(), exe.c_str()]]; - IceUtil::Handle<MainHelperI> helper = new MainHelperI(_controller, prefix + '/' + exe + ".bundle", args); - helper->start(); - return ICE_UNCHECKED_CAST(ProcessPrx, c.adapter->addWithUUID(ICE_MAKE_SHARED(ProcessI, _controller, helper.get()))); + [_controller release]; + [_ipv4 release]; + [_ipv6 release]; + [super dealloc]; } - -ControllerHelper::ControllerHelper(ViewController* controller) +#endif +-(id<TestCommonProcessPrx>) start:(NSString*)testSuite exe:(NSString*)exe args:(NSArray*)args current:(ICECurrent*)c { - Ice::registerIceDiscovery(); + [_controller println:[NSString stringWithFormat:@"starting %@ %@... ", testSuite, exe]]; - Ice::InitializationData initData = Ice::InitializationData(); - initData.properties = Ice::createProperties(); - initData.properties->setProperty("Ice.ThreadPool.Server.SizeMax", "10"); - initData.properties->setProperty("IceDiscovery.DomainId", "TestController"); - initData.properties->setProperty("IceDiscovery.Interface", "127.0.0.1"); - initData.properties->setProperty("Ice.Default.Host", "127.0.0.1"); - initData.properties->setProperty("ControllerAdapter.Endpoints", "tcp"); - //initData.properties->setProperty("Ice.Trace.Network", "2"); - //initData.properties->setProperty("Ice.Trace.Protocol", "2"); - initData.properties->setProperty("ControllerAdapter.AdapterId", Ice::generateUUID()); + NSArray<NSString*>* components = [testSuite componentsSeparatedByString:@"/"]; + components = [components arrayByAddingObject:exe]; + NSMutableString* func = [NSMutableString string]; + [func appendString:[components objectAtIndex:1]]; + for(int i = 2; i < components.count; ++i) + { + NSString* comp = [components objectAtIndex:i]; + [func appendString:[[comp substringToIndex:1] capitalizedString]]; + [func appendString:[comp substringFromIndex:1]]; + } - _communicator = Ice::initialize(initData); + void* sym = dlsym(RTLD_SELF, [func UTF8String]); + if(!sym) + { + @throw [TestCommonProcessFailedException processFailedException: + [NSString stringWithFormat:@"couldn't find %@", func]]; + } + MainHelper* helper = ICE_AUTORELEASE([[MainHelper alloc] init:_controller func:sym args:args]); + if([exe isEqualToString:@"client"] || [exe isEqualToString:@"collocated"]) + { + TestCommonInit(helper, @selector(print:)); + } + else + { + TestCommonInit(helper, @selector(print:)); + TestCommonTestInit(helper, @selector(serverReady), @"", NO, NO); + } + [helper start]; + id<ICEObjectPrx> prx = [c.adapter addWithUUID:ICE_AUTORELEASE([[ProcessI alloc] init:_controller helper:helper])]; + return [TestCommonProcessPrx uncheckedCast:prx]; +} +-(NSString*) getHost:(NSString*)protocol ipv6:(BOOL)ipv6 current:(ICECurrent*)c +{ + return ICE_AUTORELEASE(ICE_RETAIN(ipv6 ? _ipv6 : _ipv4)); +} +@end - Ice::ObjectAdapterPtr adapter = _communicator->createObjectAdapter("ControllerAdapter"); - Ice::Identity ident; +@implementation ViewController +- (void) startController +{ + NSString* ipv4 = [interfacesIPv4 objectAtIndex:[interfaceIPv4 selectedRowInComponent:0]]; + NSString* ipv6 = [interfacesIPv6 objectAtIndex:[interfaceIPv6 selectedRowInComponent:0]]; + + ICEInitializationData* initData = [ICEInitializationData initializationData]; + initData.properties = [ICEUtil createProperties]; + [initData.properties setProperty:@"Ice.ThreadPool.Server.SizeMax" value:@"10"]; + [initData.properties setProperty:@"Ice.Plugin.IceDiscovery" value:@"1"]; + [initData.properties setProperty:@"IceDiscovery.DomainId" value:@"TestController"]; + [initData.properties setProperty:@"IceDiscovery.Interface" value:ipv4]; + [initData.properties setProperty:@"Ice.Default.Host" value:ipv4]; + [initData.properties setProperty:@"ControllerAdapter.Endpoints" value:@"tcp"]; + //[initData.properties setProperty:@"Ice.Trace.Network", @"2"); + //[initData.properties setProperty:@"Ice.Trace.Protocol", @"2"); + [initData.properties setProperty:@"ControllerAdapter.AdapterId" value:[ICEUtil generateUUID]]; + + communicator = ICE_RETAIN([ICEUtil createCommunicator:initData]); + + id<ICEObjectAdapter> adapter = [communicator createObjectAdapter:@"ControllerAdapter"]; + ICEIdentity* ident = [ICEIdentity identity]; #if TARGET_IPHONE_SIMULATOR != 0 - ident.category = "iPhoneSimulator"; + ident.category = @"iPhoneSimulator"; #else - ident.category = "iPhoneOS"; + ident.category = @"iPhoneOS"; #endif - ident.name = [[[NSBundle mainBundle] bundleIdentifier] UTF8String]; - adapter->add(ICE_MAKE_SHARED(ProcessControllerI, controller), ident); - adapter->activate(); + ident.name = [[NSBundle mainBundle] bundleIdentifier]; + [adapter add:[[ProcessControllerI alloc] init:self ipv4:ipv4 ipv6:ipv6] identity:ident]; + [adapter activate]; } - -ControllerHelper::~ControllerHelper() +- (void) stopController { - _communicator->destroy(); - _communicator = 0; + [communicator destroy]; + ICE_RELEASE(communicator); + communicator = nil; } - -static ControllerHelper* controllerHelper = 0; - -@implementation ViewController - - (void)viewDidLoad { [super viewDidLoad]; - controllerHelper = new ControllerHelper(self); + ICEregisterIceDiscovery(NO); + + // + // Search for local network interfaces + // + interfacesIPv4 = ICE_RETAIN([NSMutableArray array]); + [interfacesIPv4 addObject:@"127.0.0.1"]; + interfacesIPv6 = ICE_RETAIN([NSMutableArray array]); + [interfacesIPv6 addObject:@"::1"]; + struct ifaddrs* ifap; + if(getifaddrs(&ifap) == 0) + { + struct ifaddrs* curr = ifap; + while(curr != 0) + { + if(curr->ifa_addr && curr->ifa_flags & IFF_UP && !(curr->ifa_flags & IFF_LOOPBACK)) + { + if(curr->ifa_addr->sa_family == AF_INET) + { + char buf[INET_ADDRSTRLEN]; + const struct sockaddr_in *addr = (const struct sockaddr_in*)curr->ifa_addr; + if(inet_ntop(AF_INET, &addr->sin_addr, buf, INET_ADDRSTRLEN)) + { + [interfacesIPv4 addObject:[NSString stringWithUTF8String:buf]]; + } + } + else if(curr->ifa_addr->sa_family == AF_INET6) + { + char buf[INET6_ADDRSTRLEN]; + const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6*)curr->ifa_addr; + if(inet_ntop(AF_INET6, &addr6->sin6_addr, buf, INET6_ADDRSTRLEN)) + { + [interfacesIPv6 addObject:[NSString stringWithUTF8String:buf]]; + } + } + } + curr = curr->ifa_next; + } + freeifaddrs(ifap); + } + + // By default, use the loopback + [interfaceIPv4 selectRow:0 inComponent:0 animated:NO]; + [interfaceIPv6 selectRow:0 inComponent:0 animated:NO]; + [self startController]; } + - (void) dealloc { - delete controllerHelper; + [self stopController]; +#if defined(__clang__) && !__has_feature(objc_arc) + [interfacesIPv4 release]; + [interfacesIPv6 release]; + [super dealloc]; +#endif } + -(void) write:(NSString*)msg { [output insertText:msg]; [output layoutIfNeeded]; [output scrollRangeToVisible:NSMakeRange([output.text length] - 1, 1)]; } + +#pragma mark ViewController + -(void) print:(NSString*)msg { [self performSelectorOnMainThread:@selector(write:) withObject:msg waitUntilDone:NO]; @@ -387,4 +423,44 @@ static ControllerHelper* controllerHelper = 0; { [self print:[msg stringByAppendingString:@"\n"]]; } + +#pragma mark UIPickerViewDelegate + +- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component +{ + if(pickerView == interfaceIPv4) + { + return [interfacesIPv4 objectAtIndex:row]; + } + else + { + return [interfacesIPv6 objectAtIndex:row]; + } +} + +- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component +{ + [self stopController]; + [self startController]; +} + +#pragma mark UIPickerViewDataSource + +- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView +{ + return 1; +} + +- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component +{ + if(pickerView == interfaceIPv4) + { + return interfacesIPv4.count; + } + else + { + return interfacesIPv6.count; + } +} + @end |