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