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