【问题标题】:NSURL bookmarks failing in unit tests on Xcode ServerNSURL 书签在 Xcode 服务器上的单元测试中失败
【发布时间】:2015-02-26 00:35:48
【问题描述】:

在我的应用程序的单元测试中,我创建了一个文档范围的 NSURL 书签。这些测试在我的机器上一直可以正常工作(现在仍然可以),但现在在 Xcode Server bot 上运行时失败了。我不会对单元测试包进行代码设计。

- (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 都不为零,并且我能够验证两个文件确实存在于磁盘上。它们都包含在 Git 结帐目录中,该帐户具有完全访问权限。 relativeToUrl 指向在测试之前创建的文件。

生成的NSError 具有以下信息:

"Error Domain=NSCocoaErrorDomain Code=256 "无法打开文件。"(安全策略不允许的项目 URL)UserInfo=0x10691c6d0 {NSDebugDescription=安全策略不允许的项目 URL}"

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

更新

我创建了一个演示项目,并将其推送到GitHub。随意创建您自己的 Xcode Bot,从那里拉出,看看您是否可以重现。我能够使用干净的 OS X、Xcode 和服务器安装进行重现。

【问题讨论】:

  • 您的捆绑包有哪些权利?第一行的路径,是怎么加到你的沙箱里的?
  • 这些是单元测试,没有沙盒,也没有代码签名。

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


【解决方案1】:

这是我(到目前为止)从与 DTS 团队成员的讨论中学到的东西。

  1. 安全范围的书签不适用于非沙盒(和非协同设计)应用。我的单元测试没有签名或沙盒化(这样做会引入其他问题),但无论如何它们确实有效。当下一个 OS X 版本发布时,它们可能会崩溃,但时间会证明这一点

  2. 显然,安全范围机制认为某些目录是禁止访问的。我将在下面开始一个列表(鉴于没有文档),并在我发现更多异常时更新它(请这样做)。

     /Library
     ~/Library
     /private/var
     /var
     /tmp
    

我的单元测试在结帐位置创建了一个目录,并为其中一个文件创建了一个书签。由于我的本地 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,这是禁止的。

【讨论】:

  • 您可以将 iCloud Drive 添加到禁止访问的目录列表中:-/ 我的解决方法是先尝试保存具有安全范围的 URL,如果失败(例如,由于 URL 指向iCloud Drive),请在没有安全范围的情况下重试。这似乎工作得相当好。
  • @MrMage 很有趣,谢谢!我去更新了上面的列表,但它已经包含在~/Library 下,对吗?
  • 噢,对了!不过,您可能还是想提一下,以防其他人忘记 iCloud Drive 是 ~/Library 的一部分;-)
猜你喜欢
  • 1970-01-01
  • 2021-03-28
  • 2012-10-26
  • 2011-10-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-01
相关资源
最近更新 更多