SOSAccountTesting.h [plain text]
#ifndef SEC_SOSAccountTesting_h
#define SEC_SOSAccountTesting_h
#include <CoreFoundation/CoreFoundation.h>
#include <SecureObjectSync/SOSAccount.h>
#define kAccountsAgreeTestMin 9
#define kAccountsAgreeTestPerPeer 1
#define accountsAgree(x) (kAccountsAgreeTestMin + kAccountsAgreeTestPerPeer * (x))
static void unretired_peers_is_subset(const char* label, CFArrayRef peers, CFArrayRef allowed_peers)
{
CFArrayForEach(peers, ^(const void *value) {
SOSPeerInfoRef pi = (SOSPeerInfoRef) value;
CFErrorRef leftError = NULL;
CFErrorRef rightError = NULL;
ok(SOSPeerInfoIsRetirementTicket(pi) || SOSPeerInfoIsCloudIdentity(pi) || CFArrayContainsValue(allowed_peers, CFRangeMake(0, CFArrayGetCount(allowed_peers)), pi), "Peer is allowed (%s) Peer: %@, Allowed %@", label, pi, allowed_peers);
CFReleaseNull(leftError);
CFReleaseNull(rightError);
});
}
static void accounts_agree_internal(char *label, SOSAccountRef left, SOSAccountRef right, bool check_peers)
{
CFErrorRef error = NULL;
{
CFArrayRef leftPeers = SOSAccountCopyActivePeers(left, &error);
ok(leftPeers, "Left peers (%@) - %s", error, label);
CFReleaseNull(error);
CFArrayRef rightPeers = SOSAccountCopyActivePeers(right, &error);
ok(rightPeers, "Right peers (%@) - %s", error, label);
CFReleaseNull(error);
ok(CFEqual(leftPeers, rightPeers), "Matching peers (%s) Left: %@, Right: %@", label, leftPeers, rightPeers);
if (check_peers) {
CFMutableArrayRef allowed_identities = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault);
CFArrayRef leftIdentities = SOSAccountCopyAccountIdentityPeerInfos(left, kCFAllocatorDefault, &error);
ok(leftIdentities, "Get identities (%@)", error);
CFReleaseNull(error);
CFArrayAppendArray(allowed_identities, leftIdentities, CFRangeMake(0, CFArrayGetCount(leftIdentities)));
CFReleaseNull(leftIdentities);
CFArrayRef rightIdentities = SOSAccountCopyAccountIdentityPeerInfos(right, kCFAllocatorDefault, &error);
ok(rightIdentities, "Get identities (%@)", error);
CFReleaseNull(error);
CFArrayAppendArray(allowed_identities, rightIdentities, CFRangeMake(0, CFArrayGetCount(rightIdentities)));
CFReleaseNull(rightIdentities);
unretired_peers_is_subset(label, leftPeers, allowed_identities);
}
CFReleaseNull(leftPeers);
CFReleaseNull(rightPeers);
}
{
CFArrayRef leftConcurringPeers = SOSAccountCopyConcurringPeers(left, &error);
ok(leftConcurringPeers, "Left peers (%@) - %s", error, label);
CFArrayRef rightConcurringPeers = SOSAccountCopyConcurringPeers(right, &error);
ok(rightConcurringPeers, "Right peers (%@) - %s", error, label);
ok(CFEqual(leftConcurringPeers, rightConcurringPeers), "Matching concurring peers Left: %@, Right: %@", leftConcurringPeers, rightConcurringPeers);
CFReleaseNull(leftConcurringPeers);
CFReleaseNull(rightConcurringPeers);
}
{
CFArrayRef leftApplicants = SOSAccountCopyApplicants(left, &error);
ok(leftApplicants, "Left Applicants (%@) - %s", error, label);
CFArrayRef rightApplicants = SOSAccountCopyApplicants(right, &error);
ok(rightApplicants, "Left Applicants (%@) - %s", error, label);
ok(CFEqual(leftApplicants, rightApplicants), "Matching applicants (%s) Left: %@, Right: %@", label, leftApplicants, rightApplicants);
CFReleaseNull(leftApplicants);
CFReleaseNull(rightApplicants);
}
}
static inline void accounts_agree(char *label, SOSAccountRef left, SOSAccountRef right)
{
accounts_agree_internal(label, left, right, true);
}
static CFMutableDictionaryRef ExtractPendingChanges(CFMutableDictionaryRef changes)
{
CFMutableDictionaryRef extracted = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, changes);
CFDictionaryRemoveAllValues(changes);
return extracted;
}
#define kFeedChangesToMultieTestCountPer 1
static inline void FeedChangesToMulti(CFMutableDictionaryRef changes, ...)
{
CFDictionaryRef changes_to_send = ExtractPendingChanges(changes);
SOSAccountRef account;
secerror("Change block: %@", changes_to_send);
CFErrorRef error = NULL;
va_list argp;
va_start(argp, changes);
while((account = va_arg(argp, SOSAccountRef)) != NULL) {
ok(SOSAccountHandleUpdates(account, changes_to_send, &error), "SOSAccountHandleUpdates failed (%@)", error);
CFReleaseNull(error);
}
}
static inline void InjectChangeToMulti(CFStringRef changeKey, CFStringRef changeValue, ...)
{
CFMutableDictionaryRef changes_to_send = CFDictionaryCreateMutable(NULL, 1, NULL, NULL);
CFDictionaryAddValue(changes_to_send, changeKey, changeValue);
SOSAccountRef account;
secerror("Change block: %@", changes_to_send);
CFErrorRef error = NULL;
va_list argp;
va_start(argp, changeValue);
while((account = va_arg(argp, SOSAccountRef)) != NULL) {
ok(SOSAccountHandleUpdates(account, changes_to_send, &error), "SOSAccountHandleUpdates failed (%@)", error);
CFReleaseNull(error);
}
CFReleaseNull(changes_to_send);
}
#define kFeedChangesToTestCount 1
static inline void FeedChangesTo(CFMutableDictionaryRef changes, SOSAccountRef account)
{
CFDictionaryRef changes_to_send = ExtractPendingChanges(changes);
secerror("Change block: %@", changes_to_send);
CFErrorRef error = NULL;
ok(SOSAccountHandleUpdates(account, changes_to_send, &error), "SOSAccountHandleUpdates failed (%@)", error);
CFReleaseNull(error);
CFReleaseNull(changes_to_send);
}
static SOSAccountRef CreateAccountForLocalChanges(CFMutableDictionaryRef changes, CFStringRef name, CFStringRef data_source_name)
{
SOSAccountKeyInterestBlock interest_block = ^(bool getNewKeysOnly, CFArrayRef alwaysKeys, CFArrayRef afterFirstUnlockKeys, CFArrayRef unlockedKeys) {};
SOSAccountDataUpdateBlock update_block = ^ bool (CFDictionaryRef keys, CFErrorRef *error) {
CFDictionaryForEach(keys, ^(const void *key, const void *value) {
CFDictionarySetValue(changes, key, value);
});
return true;
};
SOSDataSourceFactoryRef factory = SOSTestDataSourceFactoryCreate();
SOSTestDataSourceFactoryAddDataSource(factory, data_source_name, SOSTestDataSourceCreate());
CFDictionaryRef gestalt = SOSCreatePeerGestaltFromName(name);
SOSAccountRef result = SOSAccountCreate(kCFAllocatorDefault, gestalt, factory, interest_block, update_block);
CFReleaseNull(gestalt);
return result;
}
static inline int countPeers(SOSAccountRef account) {
CFErrorRef error = NULL;
CFArrayRef peers;
peers = SOSAccountCopyPeers(account, &error);
int retval = (int) CFArrayGetCount(peers);
CFReleaseNull(error);
CFReleaseNull(peers);
return retval;
}
static inline int countActivePeers(SOSAccountRef account) {
CFErrorRef error = NULL;
CFArrayRef peers;
peers = SOSAccountCopyActivePeers(account, &error);
int retval = (int) CFArrayGetCount(peers);
CFReleaseNull(error);
CFReleaseNull(peers);
return retval;
}
static inline int countActiveValidPeers(SOSAccountRef account) {
CFErrorRef error = NULL;
CFArrayRef peers;
peers = SOSAccountCopyActiveValidPeers(account, &error);
int retval = (int) CFArrayGetCount(peers);
CFReleaseNull(error);
CFReleaseNull(peers);
return retval;
}
static inline int countApplicants(SOSAccountRef account) {
CFErrorRef error = NULL;
CFArrayRef applicants = SOSAccountCopyApplicants(account, &error);
int retval = 0;
if(applicants) retval = (int)CFArrayGetCount(applicants);
CFReleaseNull(error);
CFReleaseNull(applicants);
return retval;
}
static inline void showActiveValidPeers(SOSAccountRef account) {
CFErrorRef error = NULL;
CFArrayRef peers;
peers = SOSAccountCopyActiveValidPeers(account, &error);
CFArrayForEach(peers, ^(const void *value) {
SOSPeerInfoRef pi = (SOSPeerInfoRef) value;
ok(0, "Active Valid Peer %@", pi);
});
CFReleaseNull(peers);
}
#endif