1/* 2 * Copyright (c) 2014 Apple Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24 25// Test syncing between SecItemDataSource and SOSTestDataSource 26 27#include <Regressions/SOSTestDevice.h> 28#include <Regressions/SOSTestDataSource.h> 29#include "secd_regressions.h" 30#include "SecdTestKeychainUtilities.h" 31 32#include <SecureObjectSync/SOSEngine.h> 33#include <SecureObjectSync/SOSPeer.h> 34#include <Security/SecBase64.h> 35#include <Security/SecItem.h> 36#include <Security/SecItemPriv.h> 37#include <corecrypto/ccsha2.h> 38#include <securityd/SecItemServer.h> 39#include <securityd/SecItemDataSource.h> 40#include <utilities/SecCFWrappers.h> 41#include <utilities/SecIOFormat.h> 42#include <utilities/SecFileLocations.h> 43 44#include <AssertMacros.h> 45#include <stdint.h> 46 47static int kTestTestCount = 1286; 48 49__unused static bool SOSCircleHandleCircleWithLock(SOSEngineRef engine, CFStringRef myID, CFDataRef message, CFErrorRef *error) { 50 51 CFMutableArrayRef trustedPeers = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); 52 CFMutableArrayRef untrustedPeers = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); 53 CFStringRef peerID = NULL; 54 const uint8_t expected[20] = { 0xea, 0x6c, 0x01, 0x4d, 55 0xc7, 0x2d, 0x6f, 0x8c, 56 0xcd, 0x1e, 0xd9, 0x2a, 57 0xce, 0x1d, 0x41, 0xf0, 58 0xd8, 0xde, 0x89, 0x57 }; 59 60 const char resultSize = sizeof(expected); 61 62 CFDataRef coder = CFDataCreate(kCFAllocatorDefault, expected, resultSize); 63 CFArrayForEachC(SOSEngineGetPeerIDs(engine), peerID){ 64 CFArrayAppendValue(trustedPeers, peerID); 65 SOSEngineSetCoderData(engine, peerID, coder, error); 66 }; 67 CFReleaseNull(coder); 68 69 CFShow(trustedPeers); 70 // all trusted 71 SOSEngineCircleChanged_locked(engine, myID,trustedPeers, untrustedPeers); 72 73 // make first peer untrusted 74 peerID = (CFStringRef)CFArrayGetValueAtIndex(trustedPeers, 0); 75 CFArrayAppendValue(untrustedPeers, peerID); 76 CFArrayRemoveAllValue(trustedPeers, peerID); 77 //we should see peerState cleared out except for the coder! 78 SOSEngineCircleChanged_locked(engine, myID, trustedPeers, untrustedPeers); 79 80 CFArrayAppendValue(trustedPeers, peerID); 81 CFArrayRemoveAllValue(untrustedPeers, peerID); 82 83 84 return true; 85} 86 87static void testsync3(const char *name, const char *test_directive, const char *test_reason) { 88 __block int iteration=0; 89 SOSTestDeviceListTestSync(name, test_directive, test_reason, 0, false, ^bool(SOSTestDeviceRef source, SOSTestDeviceRef dest) { 90 iteration++; 91 if (iteration == 12 || iteration == 13) { 92 pass("pre-rcv %@", dest); 93 } 94 if (iteration == 19) { 95 pass("pre-send %@", source); 96 } 97 return false; 98 }, ^bool(SOSTestDeviceRef source, SOSTestDeviceRef dest, SOSMessageRef message) { 99 if (iteration == 10) { 100 pass("pre-add %@", source); 101 //SOSTestDeviceAddGenericItem(source, CFSTR("test_account"), CFSTR("test service")); 102 SOSTestDeviceAddRemoteGenericItem(source, CFSTR("test_account"), CFSTR("test service")); 103 pass("post-add %@", source); 104 return true; // db changed 105 } else if (iteration == 12 || iteration == 15) { 106 pass("post-rcv %@", dest); 107 } 108 return false; 109 }, CFSTR("AAA"), CFSTR("BBB"), CFSTR("CCC"), NULL); 110} 111 112static void testsync2(const char *name, const char *test_directive, const char *test_reason, void (^aliceInit)(SOSDataSourceRef ds), void (^bobInit)(SOSDataSourceRef ds), CFStringRef msg, ...) { 113 __block int iteration=0; 114 SOSTestDeviceListTestSync(name, test_directive, test_reason, kSOSPeerVersion, false, ^bool(SOSTestDeviceRef source, SOSTestDeviceRef dest) { 115 if (iteration == 96) { 116 pass("%@ before message", source); 117 } 118 return false; 119 }, ^bool(SOSTestDeviceRef source, SOSTestDeviceRef dest, SOSMessageRef message) { 120 iteration++; 121 if (iteration == 60) { 122 pass("%@ before addition", source); 123 //SOSTestDeviceAddGenericItem(source, CFSTR("test_account"), CFSTR("test service")); 124 SOSTestDeviceAddRemoteGenericItem(source, CFSTR("test_account"), CFSTR("test service")); 125 pass("%@ after addition", source); 126 return true; 127 } 128 return false; 129 }, CFSTR("alice"), CFSTR("bob"), CFSTR("claire"), CFSTR("dave"),CFSTR("edward"), CFSTR("frank"), CFSTR("gary"), NULL); 130} 131 132static void testsync(const char *name, const char *test_directive, const char *test_reason, void (^aliceInit)(SOSDataSourceRef ds), void (^bobInit)(SOSDataSourceRef ds), ...) { 133 __block int msg_index = 0; 134 __block int last_msg_index = 0; 135 va_list args; 136 va_start(args, bobInit); 137 CFArrayRef messages = CFArrayCreateForVC(kCFAllocatorDefault, &kCFTypeArrayCallBacks, args); 138 SOSTestDeviceListTestSync(name, test_directive, test_reason, 0, false, 139 ^bool(SOSTestDeviceRef source, SOSTestDeviceRef dest) { 140 if (msg_index == 0) { 141 aliceInit(source->ds); 142 bobInit(dest->ds); 143 return true; 144 } 145 return false; 146 }, ^bool(SOSTestDeviceRef source, SOSTestDeviceRef dest, SOSMessageRef message) { 147 CFStringRef hexMsg = msg_index < CFArrayGetCount(messages) ? (CFStringRef)CFArrayGetValueAtIndex(messages, msg_index) : 0; 148 /* We are expecting a message and msg is it's digest. */ 149 if (message) { 150 msg_index++; 151 CFStringRef messageDigestStr = SOSMessageCopyDigestHex(message); 152 if (hexMsg) { 153 if (CFEqual(messageDigestStr, hexMsg)) { 154 pass("%s %@ handled message [%d] %@", name, SOSEngineGetMyID(dest->ds->engine), msg_index, message); 155 } else { 156 fail("%s %@ received message [%d] digest %@ != %@ %@", name, SOSEngineGetMyID(dest->ds->engine), msg_index, messageDigestStr, hexMsg, message); 157 } 158 last_msg_index = msg_index; 159 } else { 160 fail("%s %@ sent extra message [%d] with digest %@: %@", name, SOSEngineGetMyID(source->ds->engine), msg_index, messageDigestStr, message); 161 } 162 CFReleaseSafe(messageDigestStr); 163 //SOSCircleHandleCircleWithLock(source->ds->engine, SOSEngineGetMyID(source->ds->engine), CFDataCreate(kCFAllocatorDefault, 0, 0), NULL); 164 165 } 166 return false; 167 }, CFSTR("alice"), CFSTR("bob"), NULL); 168 169 if (msg_index < CFArrayGetCount(messages)) { 170 fail("%s nothing sent expecting message [%d] digest %@", name, msg_index, CFArrayGetValueAtIndex(messages, msg_index)); 171 } else if (last_msg_index < msg_index) { 172 fail("%s exchanged %d messages not in expected list", name, msg_index - last_msg_index); 173 } 174 175 176} 177 178#if 0 179// Test syncing an empty circle with 1 to 10 devices and both version 0 and version 2 protocols 180static void testsyncempty(void) { 181 CFMutableArrayRef deviceIDs = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); 182 for (int deviceIX=0; deviceIX < 10; ++deviceIX) { 183 CFStringRef deviceID = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%c"), 'A' + deviceIX); 184 CFArrayAppendValue(deviceIDs, deviceID); 185 CFReleaseSafe(deviceID); 186 if (deviceIX > 0) { 187 for (CFIndex version = 0; version < 3; version += 2) { 188 CFMutableDictionaryRef testDevices = SOSTestDeviceListCreate(false, version, deviceIDs); 189 SOSTestDeviceListSync("syncempty", test_directive, test_reason, testDevices, NULL, NULL); 190 SOSTestDeviceListInSync("syncempty", test_directive, test_reason, testDevices); 191 CFReleaseSafe(testDevices); 192 } 193 } 194 } 195 CFReleaseSafe(deviceIDs); 196} 197#endif 198 199static CFIndex syncmany_add(int iteration) { 200 if (iteration % 7 < 3 && iteration < 10) 201 return iteration % 17 + 200; 202 return 0; 203} 204 205static void testsyncmany(const char *name, const char *test_directive, const char *test_reason, int devFirst, int devCount, int version, CFIndex (*should_add)(int iteration)) { 206 CFMutableArrayRef deviceIDs = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); 207 for (int deviceIX=0; deviceIX < devCount; ++deviceIX) { 208 CFStringRef deviceID = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%c"), 'A' + deviceIX); 209 CFArrayAppendValue(deviceIDs, deviceID); 210 CFReleaseSafe(deviceID); 211 if (deviceIX >= devFirst) { 212 CFMutableDictionaryRef testDevices = SOSTestDeviceListCreate(false, version, deviceIDs); 213 __block int iteration = 0; 214 SOSTestDeviceListSync(name, test_directive, test_reason, testDevices, ^bool(SOSTestDeviceRef source, SOSTestDeviceRef dest) { 215 bool didAdd = false; 216 iteration++; 217 // Add 10 items in first 10 sync messages 218 CFIndex toAdd = should_add(iteration); 219 if (toAdd) { 220 CFStringRef account = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("item%d"), iteration); 221 didAdd = SOSTestDeviceAddGenericItems(source, toAdd, account, CFSTR("testsyncmany")); 222 CFReleaseSafe(account); 223 } 224 if (iteration == 279 || iteration == 459) 225 pass("pre-send[%d] %@", iteration, source); 226 227 return didAdd; 228 }, ^bool(SOSTestDeviceRef source, SOSTestDeviceRef dest, SOSMessageRef message) { 229 if (iteration == 262) 230 pass("post-rcv[%d] %@", iteration, dest); 231 232 if (iteration == 272 || iteration == 279) 233 pass("post-send[%d] %@", iteration, source); 234 235 return false; 236 }); 237 SOSTestDeviceListInSync(name, test_directive, test_reason, testDevices); 238 CFReleaseSafe(testDevices); 239 } 240 } 241 CFReleaseSafe(deviceIDs); 242} 243 244static void testsync2p(void) { 245 __block int iteration = 0; 246 SOSTestDeviceListTestSync("testsync2p", test_directive, test_reason, 0, false, ^bool(SOSTestDeviceRef source, SOSTestDeviceRef dest) { 247 iteration++; 248 // Add 10 items in first 10 sync messages 249 if (iteration <= 10) { 250 CFStringRef account = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("item%d"), iteration); 251 SOSTestDeviceAddGenericItem(source, account, CFSTR("testsync2p")); 252 CFReleaseSafe(account); 253 return true; 254 } 255 return false; 256 }, ^bool(SOSTestDeviceRef source, SOSTestDeviceRef dest, SOSMessageRef message) { 257 return false; 258 }, CFSTR("Atestsync2p"), CFSTR("Btestsync2p"), NULL); 259} 260 261static void synctests(void) { 262#if 0 263 // TODO: Adding items gives us non predictable creation and mod dates so 264 // the message hashes can't be precomputed. 265 CFDictionaryRef item = CFDictionaryCreateForCFTypes 266 (0, 267 kSecClass, kSecClassGenericPassword, 268 kSecAttrAccessible, kSecAttrAccessibleWhenUnlocked, 269 kSecAttrSynchronizable, kCFBooleanTrue, 270 kSecAttrService, CFSTR("service"), 271 kSecAttrAccount, CFSTR("account"), 272 NULL); 273 SecItemAdd(item, NULL); 274 CFReleaseSafe(item); 275#endif 276 277SKIP: 278 { 279 280#ifdef NO_SERVER 281 // Careful with this in !NO_SERVER, it'll destroy debug keychains. 282 WithPathInKeychainDirectory(CFSTR("keychain-2-debug.db"), ^(const char *keychain_path) { 283 unlink(keychain_path); 284 }); 285 286 // Don't ever do this in !NO_SERVER, it'll destroy real keychains. 287 WithPathInKeychainDirectory(CFSTR("keychain-2.db"), ^(const char *keychain_path) { 288 unlink(keychain_path); 289 }); 290 291 void kc_dbhandle_reset(void); 292 kc_dbhandle_reset(); 293#else 294 skip("Keychain not reset", kTestTestCount, false); 295#endif 296 297 testsync3("secd_70_engine3", test_directive, test_reason); 298 299 // Sync between 2 empty dataSources 300 testsync("secd_70_engine", test_directive, test_reason, 301 ^ (SOSDataSourceRef dataSource) {}, 302 ^ (SOSDataSourceRef dataSource) {}, 303 CFSTR("2AF312E092D67308A0083DFFBF2B6B754B967864"), 304 CFSTR("2AF312E092D67308A0083DFFBF2B6B754B967864"), 305 CFSTR("2AF312E092D67308A0083DFFBF2B6B754B967864"), 306 CFSTR("2AF312E092D67308A0083DFFBF2B6B754B967864"), 307 NULL); 308 309 // Sync a dataSource with one object to an empty dataSource 310 testsync("secd_70_engine-alice1", test_directive, test_reason, 311 ^ (SOSDataSourceRef dataSource) { 312 __block CFErrorRef error = NULL; 313 SOSObjectRef object = SOSDataSourceCreateGenericItem(dataSource, CFSTR("test_account"), CFSTR("test service")); 314 // TODO: Needs to be a SecDBItemRef for the SecItemDataSource... 315 ok(SOSDataSourceWith(dataSource, &error, ^(SOSTransactionRef txn, bool *commit) { 316 ok(SOSDataSourceMergeObject(dataSource, txn, object, NULL, &error), "dataSource %@ added object %@", SOSEngineGetMyID(dataSource->engine), error); 317 }), "ds transaction failed %@", error); 318 CFReleaseSafe(object); 319 CFReleaseNull(error); 320 }, 321 ^ (SOSDataSourceRef dataSource) {}, 322 CFSTR("DDDB2DCEB7B36F0757F400251ECD11E377A0DCE8"), 323 CFSTR("B2777CC898AE381B3F375B27E4FD9757F6CE9948"), 324 CFSTR("CB67BF9ECF00DC7664834DE7A2D7CC1523D25341"), 325 CFSTR("ADAA3ACE75ED516CB91893413EE9CC9ED04CA47B"), 326 327 //CFSTR("ADAA3ACE75ED516CB91893413EE9CC9ED04CA47B"), 328 //CFSTR("147B6C509908CC4A9FC4263973A842104A64CE01"), 329 //CFSTR("019B494F3C06B48BB02C280AF1E19AD861A7003C"), 330 //CFSTR("ADAA3ACE75ED516CB91893413EE9CC9ED04CA47B"), 331 NULL); 332 333 // Sync a dataSource with one object to another dataSource with the same object 334 testsync("secd_70_engine-alice1bob1", test_directive, test_reason, 335 ^ (SOSDataSourceRef dataSource) { 336#if 0 337 CFErrorRef error = NULL; 338 // TODO: Needs to be a SecDBItemRef for the SecItemDataSource... 339 CFDictionaryRef object = SOSDataSourceCreateGenericItem(dataSource, CFSTR("test_account"), CFSTR("test service")); 340 ok(SOSDataSourceMergeObject(dataSource, object, NULL, &error), "dataSource %@ added object %@", SOSEngineGetMyID(dataSource->engine), error); 341 CFReleaseSafe(object); 342 CFReleaseNull(error); 343#endif 344 }, 345 ^ (SOSDataSourceRef dataSource) { 346 __block CFErrorRef error = NULL; 347 SOSObjectRef object = SOSDataSourceCreateGenericItem(dataSource, CFSTR("test_account"), CFSTR("test service")); 348 ok(SOSDataSourceWith(dataSource, &error, ^(SOSTransactionRef txn, bool *commit) { 349 ok(SOSDataSourceMergeObject(dataSource, txn, object, NULL, &error), "dataSource %@ added object %@", SOSEngineGetMyID(dataSource->engine), error); 350 }), "ds transaction failed %@", error); 351 CFReleaseSafe(object); 352 CFReleaseNull(error); 353 }, 354 CFSTR("2AF312E092D67308A0083DFFBF2B6B754B967864"), 355 CFSTR("CB67BF9ECF00DC7664834DE7A2D7CC1523D25341"), 356 CFSTR("ADAA3ACE75ED516CB91893413EE9CC9ED04CA47B"), 357 358 //CFSTR("ADAA3ACE75ED516CB91893413EE9CC9ED04CA47B"), 359 //CFSTR("ADAA3ACE75ED516CB91893413EE9CC9ED04CA47B"), 360 //CFSTR("ADAA3ACE75ED516CB91893413EE9CC9ED04CA47B"), 361 NULL); 362 363 // Sync a dataSource with one object to another dataSource with the same object 364 testsync("secd_70_engine-alice1bob2", test_directive, test_reason, 365 ^ (SOSDataSourceRef dataSource) { 366#if 0 367 CFErrorRef error = NULL; 368 // TODO: Needs to be a SecDBItemRef for the SecItemDataSource... 369 SOSObjectRef object = SOSDataSourceCreateGenericItem(dataSource, CFSTR("test_account"), CFSTR("test service")); 370 ok(SOSDataSourceMergeObject(dataSource, object, NULL, &error), "dataSource %@ added object %@", SOSEngineGetMyID(dataSource->engine), error); 371 CFReleaseSafe(object); 372 CFReleaseNull(error); 373#endif 374 }, 375 ^ (SOSDataSourceRef dataSource) { 376 __block CFErrorRef error = NULL; 377 __block SOSObjectRef object = SOSDataSourceCreateGenericItem(dataSource, CFSTR("test_account"), CFSTR("test service")); 378 ok(SOSDataSourceWith(dataSource, &error, ^(SOSTransactionRef txn, bool *commit) { 379 ok(SOSDataSourceMergeObject(dataSource, txn, object, NULL, &error), "dataSource %@ added object %@", SOSEngineGetMyID(dataSource->engine), error); 380 CFReleaseSafe(object); 381 CFReleaseNull(error); 382 object = SOSDataSourceCreateGenericItem(dataSource, CFSTR("account1"), CFSTR("service1")); 383 ok(SOSDataSourceMergeObject(dataSource, txn, object, NULL, &error), "dataSource %@ added object %@", SOSEngineGetMyID(dataSource->engine), error); 384 CFReleaseSafe(object); 385 }), "ds transaction failed %@", error); 386 CFReleaseNull(error); 387 }, 388 CFSTR("2AF312E092D67308A0083DFFBF2B6B754B967864"), 389 CFSTR("270EB3953B2E1E295F668CFC27CBB7137991A4BE"), 390 CFSTR("D1B3944E3084425F41B2C2EA0BE82170E10AA37D"), 391 392 //CFSTR("ADAA3ACE75ED516CB91893413EE9CC9ED04CA47B"), 393 //CFSTR("D4049A1063CFBF7CAF8424E13DE3CE926FF5856C"), 394 //CFSTR("9624EA855BBED6B668868BB723443E804D04F6A1"), 395 //CFSTR("063E097CCD4FEB7F3610ED12B3DA828467314846"), 396 //CFSTR("D1B3944E3084425F41B2C2EA0BE82170E10AA37D"), 397 NULL); 398 399 // Sync a dataSource with a tombstone object to another dataSource with the same object 400 TODO: { 401 todo("<rdar://problem/14049022> Test case in sd-70-engine fails due to need for RowID"); 402 testsync("secd_70_engine-update", test_directive, test_reason, 403 ^ (SOSDataSourceRef dataSource) { 404 __block CFErrorRef error = NULL; 405 const char *password = "password1"; 406 CFDataRef data = CFDataCreate(kCFAllocatorDefault, (const UInt8 *)password, strlen(password)); 407 // TODO: Needs to be a SecDBItemRef for the SecItemDataSource... 408 SOSObjectRef object_to_find = SOSDataSourceCreateGenericItemWithData(dataSource, CFSTR("test_account"), CFSTR("test service"), true, NULL); 409 SOSObjectRef object = SOSDataSourceCopyObject(dataSource, object_to_find, &error); 410 SOSObjectRef old_object = NULL; 411 SKIP: { 412 skip("no object", 1, ok(object, "Finding object %@, error: %@", object_to_find, error)); 413 CFReleaseNull(data); 414 // TODO: Needs to be a SecDBItemRef for the SecItemDataSource... 415 old_object = SOSDataSourceCreateGenericItem(dataSource, CFSTR("test_account"), CFSTR("test service")); 416 ok(SOSDataSourceWith(dataSource, &error, ^(SOSTransactionRef txn, bool *commit) { 417 ok(SOSDataSourceMergeObject(dataSource, txn, object, NULL, &error), "dataSource %@ update object %@", SOSEngineGetMyID(dataSource->engine), error); 418 }), "ds transaction failed %@", error); 419 } 420 CFReleaseSafe(data); 421 CFReleaseSafe(old_object); 422 CFReleaseSafe(object); 423 CFReleaseNull(error); 424 }, 425 ^ (SOSDataSourceRef dataSource) { 426 __block CFErrorRef error = NULL; 427 __block SOSObjectRef object = SOSDataSourceCreateGenericItem(dataSource, CFSTR("test_account"), CFSTR("test service")); 428 ok(SOSDataSourceWith(dataSource, &error, ^(SOSTransactionRef txn, bool *commit) { 429 ok(SOSDataSourceMergeObject(dataSource, txn, object, NULL, &error), "dataSource %@ added object %@", SOSEngineGetMyID(dataSource->engine), error); 430 CFReleaseSafe(object); 431 CFReleaseNull(error); 432 object = SOSDataSourceCreateGenericItem(dataSource, CFSTR("account1"), CFSTR("service1")); 433 ok(SOSDataSourceMergeObject(dataSource, txn, object, NULL, &error), "dataSource %@ added object %@", SOSEngineGetMyID(dataSource->engine), error); 434 CFReleaseSafe(object); 435 }), "ds transaction failed %@", error); 436 CFReleaseNull(error); 437 }, 438 CFSTR("2AF312E092D67308A0083DFFBF2B6B754B967864"), 439 CFSTR("270EB3953B2E1E295F668CFC27CBB7137991A4BE"), 440 CFSTR("D1B3944E3084425F41B2C2EA0BE82170E10AA37D"), 441 442 //CFSTR("5D07A221A152D6D6C5F1919189F259A7278A08C5"), 443 //CFSTR("D4049A1063CFBF7CAF8424E13DE3CE926FF5856C"), 444 //CFSTR("137FD34E9BF11B4BA0620E8EBFAB8576BCCCF294"), 445 //CFSTR("5D07A221A152D6D6C5F1919189F259A7278A08C5"), 446 NULL); 447 } 448 449 // Sync a dataSource with one object to another dataSource with the same object 450 testsync("secd_70_engine-foreign-add", test_directive, test_reason, 451 ^ (SOSDataSourceRef dataSource) { 452 }, 453 ^ (SOSDataSourceRef dataSource) { 454 __block CFErrorRef error = NULL; 455 const char *password = "password1"; 456 CFDataRef data = CFDataCreate(kCFAllocatorDefault, (const UInt8 *)password, strlen(password)); 457 __block SOSObjectRef object = SOSDataSourceCreateGenericItemWithData(dataSource, CFSTR("test_account"), CFSTR("test service"), false, data); 458 CFReleaseSafe(data); 459 ok(SOSDataSourceWith(dataSource, &error, ^(SOSTransactionRef txn, bool *commit) { 460 ok(SOSDataSourceMergeObject(dataSource, txn, object, NULL, &error), "dataSource %@ added object %@", SOSEngineGetMyID(dataSource->engine), error); 461 CFReleaseSafe(object); 462 CFReleaseNull(error); 463 object = SOSDataSourceCreateGenericItem(dataSource, CFSTR("account1"), CFSTR("service1")); 464 ok(SOSDataSourceMergeObject(dataSource, txn, object, NULL, &error), "dataSource %@ added object %@", SOSEngineGetMyID(dataSource->engine), error); 465 CFReleaseSafe(object); 466 }), "ds transaction failed %@", error); 467 CFReleaseNull(error); 468 }, 469 CFSTR("2AF312E092D67308A0083DFFBF2B6B754B967864"), 470 CFSTR("769F63675CEE9CB968BFD9CA48DB9079BFCAFB6C"), 471 CFSTR("818C24B9BC495940836B9C8F76517C838CEFFA98"), 472 473 //CFSTR("D1B3944E3084425F41B2C2EA0BE82170E10AA37D"), 474 //CFSTR("607EEF976943FD781CFD2B3850E6DC7979AA61EF"), 475 //CFSTR("28434CD1B90CC205460557CAC03D7F12067F2329"), 476 //CFSTR("D1B3944E3084425F41B2C2EA0BE82170E10AA37D"), 477 NULL); 478 } 479 480 // Sync between 2 empty dataSources 481 testsync2("secd_70_engine2", test_directive, test_reason, 482 ^ (SOSDataSourceRef dataSource) {}, 483 ^ (SOSDataSourceRef dataSource) {}, 484 CFSTR("2AF312E092D67308A0083DFFBF2B6B754B967864"), 485 CFSTR("2AF312E092D67308A0083DFFBF2B6B754B967864"), 486 CFSTR("2AF312E092D67308A0083DFFBF2B6B754B967864"), 487 CFSTR("2AF312E092D67308A0083DFFBF2B6B754B967864"), 488 CFSTR("2AF312E092D67308A0083DFFBF2B6B754B967864"), 489 NULL); 490 491 //testsyncempty(); 492TODO: { 493 todo("testsync fails with 10 peers and staggered adds"); 494 testsyncmany("syncmany", test_directive, test_reason, 9, 10, 0, syncmany_add); 495} 496 testsyncmany("v2syncmany", test_directive, test_reason, 9, 10, 2, syncmany_add); 497 testsync2p(); 498} 499 500int secd_70_engine(int argc, char *const *argv) 501{ 502 plan_tests(kTestTestCount); 503 504 /* custom keychain dir */ 505 secd_test_setup_temp_keychain("secd_70_engine", NULL); 506 507 synctests(); 508 509 return 0; 510} 511