在我的应用程序的单元测试中,我创建了一个文档范围的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
具有以下信息:
"错误域=NSCocoa错误域代码=256 "无法打开文件。"(安全策略不允许的项目 URL)UserInfo=0x10691c6d0 {NSDebugDescription=安全策略不允许的项目 URL}"
它可能指的是什么安全策略,我将如何更新它?同样,所有这些都在我的本地开发计算机上运行良好。
更新
我创建了一个演示项目,并将其推送到 GitHub。随意创建自己的 Xcode Bot,从那里拉取以查看是否可以复制。我能够使用干净的OS X,Xcode和服务器安装进行复制。
以下是我(到目前为止)从与DTS团队成员的讨论中学到的。
-
安全范围的书签不适用于非沙盒(和非协同设计)应用。我的单元测试没有签名或沙盒化(这样做会带来其他问题),但无论如何,它们确实有效。当下一个OS X版本发布时,它们可能会中断,但时间会证明一切。
-
显然,某些目录被安全范围机制视为禁区。我将在下面开始一个列表(鉴于没有文档),并在发现更多异常时对其进行更新(请做同样的事情)。
/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 构建方案,它定义了要/Users/Shared/~testing dir
UNIT_TESTING_DIR
环境变量,因为这是一个全局可访问的位置。这样,我就可以将本地生成写入我的首选位置,但 CI 生成不会失败。双赢!
附言
显然,Xcode 服务器将
NSHomeDirectory()
返回的目录重新分配为/var/_xcsbuildd
,这是禁止的。