我在 Mac 上用 Objective-c 编写了一个小型终端应用程序,它使用 getoptlong 来解析命令行参数。解析命令行的代码如下:
+ (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;
}
}
完成后,我想使用单元测试来断言操作已正确完成。例如,我编写了以下测试:
- (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);
}
通过调试器运行测试时,getoptlong args 解析永远不会获得路径。这是测试getoptlong用法的正确方法吗?是否有更好的模式用于测试命令行参数的解析?