#include <AssertMacros.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <xpc/xpc.h>
#include <Security/SecBase.h>
#include <Security/SecItem.h>
#include <SecureObjectSync/SOSAccount.h>
#include <CKBridge/SOSCloudKeychainClient.h>
#include <utilities/SecCFWrappers.h>
#include <utilities/debugging.h>
#include "SOSCircle_regressions.h"
#include "SOSRegressionUtilities.h"
static bool verboseCKDClientDebugging = false;
static CFStringRef kTestKeyIDTimestamp = CFSTR("IDTimestamp");
static dispatch_group_t sDispatchGroup = NULL;
static dispatch_queue_t xpc_queue = NULL;
static CFStringRef kTestKeyString = CFSTR("teststring");
static CFStringRef kTestKeyData = CFSTR("testdata");
static const UInt8 tdata[] = {0x01, 0x02, 0x03, 0x04, 'a', 'b', 'c'};
static CFStringRef kTestKeyArray = CFSTR("testarray");
static const CFStringRef adata[] = {CFSTR("A"), CFSTR("b"), CFSTR("C"), CFSTR("D")};
static const CFStringRef circleKeyStrings[] = {CFSTR("circleA"), CFSTR("circleB"), CFSTR("circleC"), CFSTR("circleD")};
static const CFStringRef keysWhenUnlockedKeyStrings[] = {CFSTR("foo"), CFSTR("bar"), CFSTR("baz")};
static CFDataRef testData = NULL;
static CFArrayRef testArray = NULL;
static CFArrayRef circleKeys = NULL;
static CFArrayRef keysWhenUnlocked = NULL;
static void initializeTestData(void)
{
testData = CFDataCreate(kCFAllocatorDefault, tdata, sizeof(tdata)/sizeof(UInt8));
testArray = CFArrayCreate(kCFAllocatorDefault, (const void **)&adata, sizeof(adata)/sizeof(CFStringRef), &kCFTypeArrayCallBacks);
circleKeys = CFArrayCreate(kCFAllocatorDefault, (const void **)&circleKeyStrings, sizeof(circleKeyStrings)/sizeof(CFStringRef), &kCFTypeArrayCallBacks);
keysWhenUnlocked = CFArrayCreate(kCFAllocatorDefault, (const void **)&keysWhenUnlockedKeyStrings, sizeof(keysWhenUnlockedKeyStrings)/sizeof(CFStringRef),
&kCFTypeArrayCallBacks);
}
static void printTimeNow(const char *msg)
{
if (verboseCKDClientDebugging)
{
CFAbsoluteTime now = CFAbsoluteTimeGetCurrent();
const char *nowstr = cfabsoluteTimeToString(now);
if (nowstr)
{
printf("%s %s\n", nowstr, msg);
free((void *)nowstr);
}
}
}
static bool testPostGet(CFStringRef key, CFTypeRef cfobj, dispatch_queue_t processQueue, dispatch_group_t dgroup)
{
CFErrorRef error = NULL;
bool result = false;
CFTypeRef cfv = NULL;
testPutObjectInCloud(key, cfobj, &error, dgroup, processQueue);
CFTypeRef cfvalue = testGetObjectFromCloud(key, processQueue, dgroup);
printTimeNow("finished getObjectFromCloud");
if (!cfvalue)
return false;
if (CFGetTypeID(cfvalue)==CFDictionaryGetTypeID())
cfv = CFDictionaryGetValue(cfvalue, key);
else
cfv = cfvalue;
result = CFEqual(cfobj, cfv);
return result;
}
static bool postIDTimestamp(dispatch_queue_t theq, dispatch_group_t dgroup)
{
bool result = false;
CFStringRef macaddr = myMacAddress();
CFAbsoluteTime now = CFAbsoluteTimeGetCurrent();
const char *nowstr = cfabsoluteTimeToStringLocal(now);
CFStringRef cfidstr = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@: %@ %s"), kTestKeyIDTimestamp, macaddr ,nowstr);
secerror("Setting %@ key: %@", kTestKeyIDTimestamp, cfidstr);
result = testPostGet(kTestKeyIDTimestamp, cfidstr, theq, dgroup);
if (nowstr)
free((void *)nowstr);
CFReleaseSafe(cfidstr);
return result;
}
static const int kbasicKVSTestsCount = 10;
static void basicKVSTests(dispatch_group_t dgroup)
{
dispatch_queue_t generalq = dispatch_queue_create("general", DISPATCH_QUEUE_SERIAL);
printTimeNow("Start tests [basicKVSTests]");
ok(testSynchronize(generalq, dgroup), "test synchronize");
CFAbsoluteTime now = CFAbsoluteTimeGetCurrent();
const char *nowstr = cfabsoluteTimeToStringLocal(now);
CFStringRef cfstrtime = CFStringCreateWithCString(kCFAllocatorDefault, nowstr, kCFStringEncodingUTF8);
ok(testGetObjectFromCloud(kTestKeyIDTimestamp, generalq, dgroup) != nil, "testGet for %@", kTestKeyIDTimestamp);
ok(postIDTimestamp(generalq, dgroup), "testPostGet for %@", kTestKeyIDTimestamp);
ok(testPostGet(kTestKeyString, CFSTR("test string"), generalq, dgroup), "testPostGet for CFStringRef");
ok(testPostGet(kTestKeyString, CFSTR("test string"), generalq, dgroup), "testPostGet for CFStringRef");
ok(testPostGet(kTestKeyData, testData, generalq, dgroup), "testPostGet for CFDataRef");
ok(testPostGet(kTestKeyArray, testArray, generalq, dgroup), "testPostGet for CFDataRef");
ok(testRegisterKeys(circleKeys, generalq, dgroup), "test register keys");
ok(postIDTimestamp(generalq, dgroup), "testPostGet for %@", kTestKeyIDTimestamp);
ok(testSynchronize(generalq, dgroup), "test synchronize");
printTimeNow("End tests [basicKVSTests]");
CFRelease(testData);
CFRelease(testArray);
CFRelease(circleKeys);
CFRelease(keysWhenUnlocked);
CFRelease(cfstrtime);
if (nowstr)
free((void *)nowstr);
}
static int kTestTestCount = kbasicKVSTestsCount;
static void tests(void)
{
SKIP: {
skip("Skipping ckdclient tests because CloudKeychainProxy.xpc is not installed", kTestTestCount, XPCServiceInstalled());
xpc_queue = dispatch_queue_create("sc_90_ckdclient", DISPATCH_QUEUE_SERIAL);
sDispatchGroup = dispatch_group_create();
initializeTestData();
basicKVSTests(sDispatchGroup);
}
}
int sc_90_ckdclient(int argc, char *const *argv)
{
plan_tests(kTestTestCount);
tests();
return 0;
}