sc-103-syncupdate.c [plain text]
#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 <Security/SecItemPriv.h>
#include <CKBridge/SOSCloudKeychainClient.h>
#include <SecureObjectSync/SOSCloudCircle.h>
#include <notify.h>
#include <dispatch/dispatch.h>
#include <getopt.h>
#include <utilities/SecCFWrappers.h>
#include <utilities/debugging.h>
#include <utilities/SecCFRelease.h>
#include "SOSCircle_regressions.h"
#include "SOSRegressionUtilities.h"
#include "SOSCloudKeychainConstants.h"
#define xsecdebug(format...) secerror(format)
static dispatch_group_t sDispatchGroup = NULL;
static const uint64_t putTestInterval = 10ull * NSEC_PER_SEC;
static const uint64_t leeway = 1ull * NSEC_PER_SEC;
static const uint64_t syncInterval = 60ull * NSEC_PER_SEC; static const uint64_t putDelay = 10ull * NSEC_PER_SEC; static const uint64_t exitDelay = 180ull * NSEC_PER_SEC;
static dispatch_queue_t requestqueue;
static dispatch_source_t exitTimerSource;
static uint64_t failCounter = 0;
static uint64_t putAttemptCounter = 0;
static uint64_t itemsChangedCount = 0;
static void tearDown(void)
{
xsecdebug("exit");
CFRunLoopStop(CFRunLoopGetMain());
}
static void initCyclerTests(dispatch_group_t dgroup)
{
uint64_t delay = exitDelay;
dispatch_time_t exitFireTime = dispatch_time(DISPATCH_TIME_NOW, delay);
exitTimerSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, (uintptr_t)NULL, 0, requestqueue);
dispatch_source_set_timer(exitTimerSource, exitFireTime, 0ull, leeway);
dispatch_source_set_event_handler(exitTimerSource,
^{
xsecdebug("Test Exit: %lld", failCounter);
printf("Test Exit: fail: %lld, total: %lld, changed: %lld\n", failCounter, putAttemptCounter, itemsChangedCount);
tearDown();
exit(0);
});
}
static void updateSyncingEnabledSwitch()
{
CFErrorRef error = NULL;
SOSCCStatus ccstatus = SOSCCThisDeviceIsInCircle(&error);
pass("ccstatus: %d, error: %@", ccstatus, error);
}
static void requestToJoinCircle()
{
bool bx;
CFErrorRef error = NULL;
SOSCCStatus ccstatus = SOSCCThisDeviceIsInCircle(&error);
pass("ccstatus: %d, error: %@", ccstatus, error);
if (ccstatus == kSOSCCInCircle)
return;
if (ccstatus == kSOSCCNotInCircle)
{
pass("Not in circle, requesting admission");
bx = SOSCCRequestToJoinCircle(&error);
if (!bx)
pass("SOSCCRequestToJoinCircle error: %@", error);
}
else
if (ccstatus == kSOSCCRequestPending)
pass("Not in circle, admission pending");
}
static void handleEnableSyncing(bool turningOn)
{
dispatch_queue_t workq = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
if (turningOn) {
pass("Keychain syncing is being turned ON");
dispatch_async(workq, ^
{
CFErrorRef error = NULL;
bool bx = SOSCCResetToOffering(&error);
if (bx)
pass("ResetToOffering OK");
else
pass("ResetToOffering fail: %@", error);
requestToJoinCircle();
updateSyncingEnabledSwitch();
dispatch_group_leave(sDispatchGroup);
});
}
else
{
pass("Keychain syncing is being turned OFF");
CFErrorRef error = NULL;
bool bx = SOSCCRemoveThisDeviceFromCircle(&error);
updateSyncingEnabledSwitch();
if (!bx)
pass("SOSCCRemoveThisDeviceFromCircle fail: %@", error);
}
}
static void initialEstablish(void)
{
dispatch_group_enter(sDispatchGroup);
dispatch_group_notify(sDispatchGroup, requestqueue, ^
{
printf("Exiting via dispatch_group_notify; all work done\n");
CFRunLoopStop(CFRunLoopGetMain());
});
handleEnableSyncing(true);
#if 0
CFErrorRef error = NULL;
bool bx = false;
SOSCCStatus sccStatus = SOSCCThisDeviceIsInCircle(&error);
if (sccStatus == kSOSCCNotInCircle)
bx = SOSCCResetToOffering(&error);
else
bx = SOSCCRequestToJoinCircle(&error);
if (!bx)
xsecdebug("circle establish error: %@", error);
ok(bx, "Circle established");
#endif
}
static const struct option options[] =
{
{ "verbose", optional_argument, NULL, 'v' },
{ }
};
static int kTestCount = 22;
int sc_103_syncupdate(int argc, char *const *argv)
{
extern char *optarg;
int arg, argSlot;
while (argSlot = -1, (arg = getopt_long(argc, (char * const *)argv, "i:v", options, &argSlot)) != -1)
switch (arg)
{
default:
secerror("arg: %s", optarg);
break;
}
plan_tests(kTestCount);
SKIP:
{
skip("Skipping ckdclient tests because CloudKeychainProxy.xpc is not installed", kTestCount, XPCServiceInstalled());
sDispatchGroup = dispatch_group_create();
requestqueue = dispatch_queue_create("sc_103_syncupdate", DISPATCH_QUEUE_CONCURRENT);
initCyclerTests(sDispatchGroup);
initialEstablish();
}
dispatch_group_wait(sDispatchGroup, DISPATCH_TIME_FOREVER);
pass("Tests are running...");
printf("Tests are running...\n");
CFRunLoopRun(); pass("Exit from run loop");
return 0;
}