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