0

我在 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用法的正确方法吗?是否有更好的模式用于测试命令行参数的解析?

4

0 回答 0