getoptlong を使用してコマンド ライン引数を解析する、Mac 上の Objective-C を使用した小さなターミナル アプリケーションを作成しました。コマンド ラインを解析するコードは次のとおりです。
+ (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 の使用をテストする正しい方法ですか? コマンドライン引数の解析をテストするために使用されるより良いパターンはありますか?