I have written a small terminal application with objective-c on Mac that uses getoptlong to parse the command line arguments. The code that parses the command line is the following:
+ (void) parseCommandLine:(int) argc
args:(char **) argv
outSocketPath:(NSURL **) socketPath
outSocketHandle:(int *) socketHandle
outTestModePath:(NSURL **) testModePath {
*socketPath = nil;
*testModePath = nil;
socketHandle = 0;
// are we running with launchd, the default is true
BOOL noLaunchdFlag = NO;
struct sockaddr_un un;
// description of the available options of the daemon
static struct option longopts[] = {
{ "no-launchd", no_argument, NULL, 'l' },
{ "socket", required_argument, NULL, 's' },
{ "testing", required_argument, NULL, 't'},
{ "help", no_argument, NULL, 'h'}
};
// parse the options and decide how to move
int ch;
while ((ch = getopt_long(argc, argv, "lst:h", longopts, NULL)) != -1){
switch (ch) {
case 'l':
noLaunchdFlag = YES;
break;
case 's':
*socketPath = [NSURL fileURLWithPath: [NSString
stringWithCString:optarg encoding:NSUTF8StringEncoding]];
break;
case 't':
*testModePath = [NSURL fileURLWithPath: [NSString
stringWithCString:optarg encoding:NSUTF8StringEncoding]];
case 'h':
default:
return [FSEventsDaemon usage];
} // switch
} // while looping through args
// assert the parameters
if(noLaunchdFlag) {
if(*socketPath == nil){
// we always need to have a socket path
[NSException raise:@"Invalid Parameter" format:@""];
}
if([[*socketPath absoluteString] length] > sizeof(un.sun_path) - 1) {
// socket path is too long
[NSException raise:@"Invalid Parameter" format:@""];
}
if(*testModePath == nil && geteuid() != 0){
// if we are not running in test mode we must be root
[NSException raise:@"" format:@""];
}
// all args are ok
return;
}
else {
if(testModePath != nil) {
[NSException raise:@"Invalid Paramter"
format:@"You cannot use -t because testing is not supported via launchd"];
}
// get the handle
*socketHandle = [FSEventsDaemon getLauchdSocketHandle];
// all args are ok
return;
}
}
Having done that I'd like to use unit tests to assert that the operation is correctly done. I have for example written the following test:
- (void) testParseArgsNotTestNotRoot {
char * argv[] = {"./FsEvents", "--socket=", [self getPath], "-l"};
int argc = 4;
NSURL *sockPath = nil;
int handle;
NSURL *testPath = nil;
// should raise an exception because we are not root
STAssertThrows([FSEventsDaemon parseCommandLine:argc args:argv
outSocketPath:&sockPath outSocketHandle:&handle
outTestModePath:&testPath], nil);
}
When running the test via the debugger the getoptlong args parsing never gets the path. Is this the correct way to test the usage of getoptlong? Is there a better pattern used for testing the parsing of the command line arguments?