0

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 の使用をテストする正しい方法ですか? コマンドライン引数の解析をテストするために使用されるより良いパターンはありますか?

4

0 に答える 0