NSURL书签在Xcode Server上的单元测试中失败

时间:2014-12-29 20:17:30

标签: xcode cocoa unit-testing appstore-sandbox xcode-server

在我的应用程序的单元测试中,我创建了一个文档范围的NSURL书签。这些测试一直在我的机器上正常工作(现在仍然如此),但现在在Xcode Server机器人上运行时失败了。我没有对单元测试包进行编码。

- (void)testBookmarks
{
    // Create testing directory
    NSFileManager *fm = [NSFileManager defaultManager];
    NSString *sourceDir = [fm currentDirectoryPath];
    NSString *testingDir = [sourceDir stringByAppendingPathComponent:@"~testing dir"];

    if ([fm fileExistsAtPath:testingDir]) {
        [fm removeItemAtPath:testingDir error:NULL];
    }

    [fm createDirectoryAtPath:testingDir
  withIntermediateDirectories:NO
                   attributes:nil
                        error:NULL];

    // Create file to create bookmark to
    NSString *bookmarkedFilePath = [testingDir stringByAppendingPathComponent:@"fileToBookmark.txt"];
    [fm createFileAtPath:bookmarkedFilePath
                contents:nil
              attributes:nil];
    NSURL *originalURL = [NSURL fileURLWithPath:bookmarkedFilePath];

    // Create file to create bookmark relative to
    NSString *relativeFilePath = [testingDir stringByAppendingPathComponent:@"relativeToFile.txt"];
    [fm createFileAtPath:relativeFilePath
                contents:nil
              attributes:nil];

    // Create a document-scoped bookmark
    NSError *docScopedError = nil;
    NSURL *relativeToURL = [NSURL fileURLWithPath:relativeFilePath];
    NSData *bookmark = [originalURL bookmarkDataWithOptions:NSURLBookmarkCreationWithSecurityScope
                             includingResourceValuesForKeys:nil
                                              relativeToURL:relativeToURL
                                                      error:&docScopedError];

    // Assert everything went well
    XCTAssertNil(docScopedError, @"Error while creating document-scoped bookmark from URL:\n%@\nrelative to: %@",
                 originalURL, relativeToURL);
    XCTAssertNotNil(bookmark, @"No bookmark created to URL:\n%@\nrelative to: %@",
                 originalURL, relativeToURL);
}

两个断言都失败了,并且记录的消息会验证两个URL都不是nil,并且我能够验证这两个文件是否确实存在于磁盘上。它们都包含在Git结帐目录中,该目录具有该帐户的完全访问权限。 relativeToUrl指向测试前面创建的文件。

生成的NSError具有以下信息:

  

“Error Domain = NSCocoaErrorDomain Code = 256”无法打开该文件。“(安全策略禁止的项目URL)UserInfo = 0x10691c6d0 {NSDebugDescription =安全策略禁止的项目URL}”

它可以引用什么安全策略,以及如何更新它?同样,所有这些在我的本地开发机器上都能正常工作。

更新

我创建了一个演示项目,并将其推送到GitHub。随意创建自己的Xcode Bot,从那里拉出来看看你是否可以重现。我能够通过干净的OS X,Xcode和Server安装来重现。

1 个答案:

答案 0 :(得分:1)

以下是我与DTS团队成员讨论时所学到的(到目前为止)。

  1. 安全范围的书签不适用于非沙盒(和非代码签名)的应用程序。我的单元测试没有签名或沙箱(并且这样做引入了其他问题),但它们确实有效,无论如何。当下一个OS X发布时,它们可能会中断,但时间会告诉那里

  2. 显然,安全范围机制考虑的某些目录是禁止的。我将在下面列出一个列表(假设没有文档),并在发现更多异常时更新它(请同样)。

    /Library
    ~/Library
    /private/var
    /var
    
  3. 我的单元测试在结帐位置创建了一个目录,并为其中一个文件创建了一个书签。由于我的本地Xcode结帐位于~/Source Code,因此工作正常。但是,Xcode Server会结帐到/Library/Developer/XcodeServer/Caches/...,这就是造成问题的原因。

    我使用我的实现更新了我的示例GitHub项目。简而言之,我在单元测试中有以下代码:

    NSString *envVarTestingDir = [[NSProcessInfo processInfo].environment objectForKey:@"UNIT_TESTING_DIR"];
    NSString *sourceRelativeDir = [[fm currentDirectoryPath] stringByAppendingPathComponent:@"~testing dir"];
    NSString *testingDirPath = [envVarTestingDir length] > 0 ? envVarTestingDir : sourceRelativeDir;
    

    然后,我有一个单独的CI构建方案,它将UNIT_TESTING_DIR环境变量定义为/Users/Shared/~testing dir,因为它是一个全局可访问的位置。这样,我将本地构建写入我的首选位置,但CI构建不会失败。赢/赢了!

      

    PS

         

    显然,Xcode Server将NSHomeDirectory()返回的目录重新分配为/var/_xcsbuildd,这是禁止的。