5

使用命令行工具执行目标并且 iphone 模拟器设置为硬件版本 6.0 (10A403) 时,对钥匙串服务的调用失败并显示 errSecNotAvailable 。如果我将模拟器版本更改为其他先前版本(4.3、5.0、5.1)并使用相同的命令行脚本重新执行,则调用成功。

我正在运行最新的 XCode 4.5,命令行工具是从 XCode 中下载的。

要重现此错误,只需执行以下操作:

  1. 使用 OCUnit 目标设置 ios 库项目
  2. 将基础 SDK 设置为 6.0
  3. 将 iOS 部署目标设置为 4.3
  4. 将帖子末尾的代码复制并粘贴到测试项目中(它只会尝试存储密码并检索它)
  5. 将 Security.framework 添加到 OCUnit 目标

在 XCode 中执行 OCUnit 目标,并使用 iphone 模拟器中设置的任何硬件版本查看测试通过(只需在执行之间更改它)。

使用以下命令从命令行执行 OCUnit 目标:

xcodebuild -target TARGET_NAME_HERE -sdk iphonesimulator -configuration Release TEST_AFTER_BUILD=YES

将 iphone 模拟器设置为硬件版本 6.0,测试将失败。如果将iphone模拟器硬件版本更改为4.3、5.0或5.1并再次执行命令行脚本,测试将成功

这是命令行工具的问题吗?iphone模拟器问题?从命令行运行的 OCUnit 目标问题?

谁喜欢只有在彗星对齐时才能通过的单元测试?

有任何想法吗?

这是代码:

#define KEYCHAIN_ITEM_ATTRIBUTES (id)kSecClassGenericPassword, kSecClass, @"MyService", kSecAttrService, @"MyPassword", kSecAttrAccount

const NSString* MyPassword = @"blabla";

- (void)testExample
{
    // remove previous keychain item
    OSStatus status = SecItemDelete((CFTypeRef)[NSDictionary dictionaryWithObjectsAndKeys:KEYCHAIN_ITEM_ATTRIBUTES, nil]);
    NSLog(@"SecItemDelete status:%ld",status);
    NSParameterAssert(status == errSecSuccess || status == errSecItemNotFound);

    // add keychain item with new value
    NSData *data = [MyPassword dataUsingEncoding:NSUTF8StringEncoding];
    status = SecItemAdd((CFTypeRef)[NSDictionary dictionaryWithObjectsAndKeys:KEYCHAIN_ITEM_ATTRIBUTES, data, kSecValueData, nil], NULL);
    NSLog(@"SecItemAdd status:%ld",status);
    NSParameterAssert(status == errSecSuccess);

    // get password
    status = SecItemCopyMatching((CFTypeRef)[NSDictionary dictionaryWithObjectsAndKeys:KEYCHAIN_ITEM_ATTRIBUTES,
                                             kSecMatchLimitOne, kSecMatchLimit, kCFBooleanTrue, kSecReturnData, nil], (CFTypeRef *)&data);
    NSLog(@"SecItemCopyMatching status:%ld",status);
    NSParameterAssert(status == errSecSuccess);

    if (status == errSecItemNotFound)
        NSLog(@"SecItemCopyMatching status:%ld", status);
    else
        NSLog(@"SecItemCopyMatching result:%@",[[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease]);
}

关于未启动的安全守护程序,我可以检查它是否正在启动,使用

launchctl list | grep securityd

模拟器启动后,得到

-   0   com.apple.iPhoneSimulator:com.apple.securityd

我还尝试停止此安全守护程序并手动启动另一个...我查看了 GTM 的 RunIPhoneUnitTest.sh 脚本以获取可以使用的简单行,但是当我尝试此操作时

launchctl submit -l ios6securityd -- /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator6.0.sdk/usr/libexec/securityd

在那个守护进程上给我一个 -5 状态码。

4

1 回答 1

1

我遇到了这个问题,因为我在尝试从 Xcode 4.5.1 UI 运行我的单元测试时无法访问钥匙串。幸运的是,我在使用大多数以前的 Xcode 版本的 CI 构建中也熟悉了这种损坏,即模拟器的securityd没有正确启动。

尝试先启动 securityd,看看是否有帮助:

#!/bin/bash

simulator_root=`xcodebuild -version -sdk iphonesimulator Path`
"${simulator_root}/usr/libexec/securityd"

这对我有用。

于 2012-11-01T21:24:02.960 回答