2 * Copyright (c) 2014 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
25 // Test syncing between SecItemDataSource and SOSTestDataSource
27 #include <SOSCircle/Regressions/SOSTestDevice.h>
28 #include <SOSCircle/Regressions/SOSTestDataSource.h>
29 #include "secd_regressions.h"
30 #include "SecdTestKeychainUtilities.h"
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>
44 #include <AssertMacros.h>
47 static int kTestTestCount
= 1306;
49 __unused
static bool SOSCircleHandleCircleWithLock(SOSEngineRef engine
, CFStringRef myID
, CFDataRef message
, CFErrorRef
*error
) {
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 };
60 const char resultSize
= sizeof(expected
);
62 CFDataRef coder
= CFDataCreate(kCFAllocatorDefault
, expected
, resultSize
);
63 CFArrayForEachC(SOSEngineGetPeerIDs(engine
), peerID
){
64 CFArrayAppendValue(trustedPeers
, peerID
);
65 SOSEngineSetCoderData(engine
, peerID
, coder
, error
);
71 SOSEngineCircleChanged(engine
, myID
,trustedPeers
, untrustedPeers
);
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(engine
, myID
, trustedPeers
, untrustedPeers
);
80 CFArrayAppendValue(trustedPeers
, peerID
);
81 CFArrayRemoveAllValue(untrustedPeers
, peerID
);
87 static 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
) {
91 if (iteration
== 12 || iteration
== 13) {
92 pass("pre-rcv %@", dest
);
94 if (iteration
== 19) {
95 pass("pre-send %@", source
);
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
);
109 }, CFSTR("AAA"), CFSTR("BBB"), CFSTR("CCC"), NULL
);
112 static 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
);
119 }, ^bool(SOSTestDeviceRef source
, SOSTestDeviceRef dest
, SOSMessageRef message
) {
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
);
129 }, CFSTR("alice"), CFSTR("bob"), CFSTR("claire"), CFSTR("dave"),CFSTR("edward"), CFSTR("frank"), CFSTR("gary"), NULL
);
132 static 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;
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
);
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. */
151 CFStringRef messageDigestStr
= SOSMessageCopyDigestHex(message
);
153 if (CFEqual(messageDigestStr
, hexMsg
)) {
154 pass("%s %@ handled message [%d] %@", name
, SOSEngineGetMyID(dest
->ds
->engine
), msg_index
, message
);
157 todo("manifest caching changed");
158 fail("%s %@ received message [%d] digest %@ != %@ %@", name
, SOSEngineGetMyID(dest
->ds
->engine
), msg_index
, messageDigestStr
, hexMsg
, message
);
161 last_msg_index
= msg_index
;
164 todo("manifest caching changed");
165 fail("%s %@ sent extra message [%d] with digest %@: %@", name
, SOSEngineGetMyID(source
->ds
->engine
), msg_index
, messageDigestStr
, message
);
168 CFReleaseSafe(messageDigestStr
);
169 //SOSCircleHandleCircleWithLock(source->ds->engine, SOSEngineGetMyID(source->ds->engine), CFDataCreate(kCFAllocatorDefault, 0, 0), NULL);
173 }, CFSTR("alice"), CFSTR("bob"), NULL
);
175 if (msg_index
< CFArrayGetCount(messages
)) {
177 todo("manifest caching changed");
178 fail("%s nothing sent expecting message [%d] digest %@", name
, msg_index
, CFArrayGetValueAtIndex(messages
, msg_index
));
180 } else if (last_msg_index
< msg_index
) {
182 todo("manifest caching changed");
183 fail("%s exchanged %d messages not in expected list", name
, msg_index
- last_msg_index
);
191 // Test syncing an empty circle with 1 to 10 devices and both version 0 and version 2 protocols
192 static void testsyncempty(void) {
193 CFMutableArrayRef deviceIDs
= CFArrayCreateMutableForCFTypes(kCFAllocatorDefault
);
194 for (int deviceIX
=0; deviceIX
< 10; ++deviceIX
) {
195 CFStringRef deviceID
= CFStringCreateWithFormat(kCFAllocatorDefault
, NULL
, CFSTR("%c"), 'A' + deviceIX
);
196 CFArrayAppendValue(deviceIDs
, deviceID
);
197 CFReleaseSafe(deviceID
);
199 for (CFIndex version
= 0; version
< 3; version
+= 2) {
200 CFMutableDictionaryRef testDevices
= SOSTestDeviceListCreate(false, version
, deviceIDs
);
201 SOSTestDeviceListSync("syncempty", test_directive
, test_reason
, testDevices
, NULL
, NULL
);
202 SOSTestDeviceListInSync("syncempty", test_directive
, test_reason
, testDevices
);
203 SOSTestDeviceDestroyEngine(testDevices
);
204 CFReleaseSafe(testDevices
);
208 CFReleaseSafe(deviceIDs
);
212 static CFIndex
syncmany_add(int iteration
) {
213 if (iteration
% 7 < 3 && iteration
< 10)
214 return iteration
% 17 + 200;
218 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
)) {
219 CFMutableArrayRef deviceIDs
= CFArrayCreateMutableForCFTypes(kCFAllocatorDefault
);
220 for (int deviceIX
=0; deviceIX
< devCount
; ++deviceIX
) {
221 CFStringRef deviceID
= CFStringCreateWithFormat(kCFAllocatorDefault
, NULL
, CFSTR("%c"), 'A' + deviceIX
);
222 CFArrayAppendValue(deviceIDs
, deviceID
);
223 CFReleaseSafe(deviceID
);
224 if (deviceIX
>= devFirst
) {
225 CFMutableDictionaryRef testDevices
= SOSTestDeviceListCreate(false, version
, deviceIDs
);
226 __block
int iteration
= 0;
227 SOSTestDeviceListSync(name
, test_directive
, test_reason
, testDevices
, ^bool(SOSTestDeviceRef source
, SOSTestDeviceRef dest
) {
230 // Add 10 items in first 10 sync messages
231 CFIndex toAdd
= should_add(iteration
);
233 CFStringRef account
= CFStringCreateWithFormat(kCFAllocatorDefault
, NULL
, CFSTR("item%d"), iteration
);
234 didAdd
= SOSTestDeviceAddGenericItems(source
, toAdd
, account
, CFSTR("testsyncmany"));
235 CFReleaseSafe(account
);
237 if (iteration
== 279 || iteration
== 459)
238 pass("pre-send[%d] %@", iteration
, source
);
241 }, ^bool(SOSTestDeviceRef source
, SOSTestDeviceRef dest
, SOSMessageRef message
) {
242 if (iteration
== 262)
243 pass("post-rcv[%d] %@", iteration
, dest
);
245 if (iteration
== 272 || iteration
== 279)
246 pass("post-send[%d] %@", iteration
, source
);
250 SOSTestDeviceListInSync(name
, test_directive
, test_reason
, testDevices
);
251 SOSTestDeviceDestroyEngine(testDevices
);
252 CFReleaseSafe(testDevices
);
255 CFReleaseSafe(deviceIDs
);
258 static void testsync2p(void) {
259 __block
int iteration
= 0;
260 SOSTestDeviceListTestSync("testsync2p", test_directive
, test_reason
, 0, false, ^bool(SOSTestDeviceRef source
, SOSTestDeviceRef dest
) {
262 // Add 10 items in first 10 sync messages
263 if (iteration
<= 10) {
264 CFStringRef account
= CFStringCreateWithFormat(kCFAllocatorDefault
, NULL
, CFSTR("item%d"), iteration
);
265 SOSTestDeviceAddGenericItem(source
, account
, CFSTR("testsync2p"));
266 CFReleaseSafe(account
);
270 }, ^bool(SOSTestDeviceRef source
, SOSTestDeviceRef dest
, SOSMessageRef message
) {
272 }, CFSTR("Atestsync2p"), CFSTR("Btestsync2p"), NULL
);
275 static void synctests(void) {
277 // TODO: Adding items gives us non predictable creation and mod dates so
278 // the message hashes can't be precomputed.
279 CFDictionaryRef item
= CFDictionaryCreateForCFTypes
281 kSecClass
, kSecClassGenericPassword
,
282 kSecAttrAccessible
, kSecAttrAccessibleWhenUnlocked
,
283 kSecAttrSynchronizable
, kCFBooleanTrue
,
284 kSecAttrService
, CFSTR("service"),
285 kSecAttrAccount
, CFSTR("account"),
287 SecItemAdd(item
, NULL
);
295 // Careful with this in !NO_SERVER, it'll destroy debug keychains.
296 WithPathInKeychainDirectory(CFSTR("keychain-2-debug.db"), ^(const char *keychain_path
) {
297 unlink(keychain_path
);
300 // Don't ever do this in !NO_SERVER, it'll destroy real keychains.
301 WithPathInKeychainDirectory(CFSTR("keychain-2.db"), ^(const char *keychain_path
) {
302 unlink(keychain_path
);
305 void kc_dbhandle_reset(void);
308 skip("Keychain not reset", kTestTestCount
, false);
311 testsync3("secd_70_engine3", test_directive
, test_reason
);
313 // Sync between 2 empty dataSources
314 testsync("secd_70_engine", test_directive
, test_reason
,
315 ^ (SOSDataSourceRef dataSource
) {},
316 ^ (SOSDataSourceRef dataSource
) {},
317 CFSTR("2AF312E092D67308A0083DFFBF2B6B754B967864"),
318 CFSTR("2AF312E092D67308A0083DFFBF2B6B754B967864"),
319 CFSTR("2AF312E092D67308A0083DFFBF2B6B754B967864"),
320 CFSTR("2AF312E092D67308A0083DFFBF2B6B754B967864"),
323 // Sync a dataSource with one object to an empty dataSource
324 testsync("secd_70_engine-alice1", test_directive
, test_reason
,
325 ^ (SOSDataSourceRef dataSource
) {
326 __block CFErrorRef error
= NULL
;
327 SOSObjectRef object
= SOSDataSourceCreateGenericItem(dataSource
, CFSTR("test_account"), CFSTR("test service"));
328 // TODO: Needs to be a SecDBItemRef for the SecItemDataSource...
329 ok(SOSDataSourceWith(dataSource
, &error
, ^(SOSTransactionRef txn
, bool *commit
) {
330 ok(SOSDataSourceMergeObject(dataSource
, txn
, object
, NULL
, &error
), "dataSource %@ added object %@", SOSEngineGetMyID(dataSource
->engine
), error
);
331 }), "ds transaction failed %@", error
);
332 CFReleaseSafe(object
);
333 CFReleaseNull(error
);
335 ^ (SOSDataSourceRef dataSource
) {},
336 CFSTR("DDDB2DCEB7B36F0757F400251ECD11E377A0DCE8"),
337 CFSTR("B2777CC898AE381B3F375B27E4FD9757F6CE9948"),
338 CFSTR("CB67BF9ECF00DC7664834DE7A2D7CC1523D25341"),
339 CFSTR("ADAA3ACE75ED516CB91893413EE9CC9ED04CA47B"),
341 //CFSTR("ADAA3ACE75ED516CB91893413EE9CC9ED04CA47B"),
342 //CFSTR("147B6C509908CC4A9FC4263973A842104A64CE01"),
343 //CFSTR("019B494F3C06B48BB02C280AF1E19AD861A7003C"),
344 //CFSTR("ADAA3ACE75ED516CB91893413EE9CC9ED04CA47B"),
347 // Sync a dataSource with one object to another dataSource with the same object
348 testsync("secd_70_engine-alice1bob1", test_directive
, test_reason
,
349 ^ (SOSDataSourceRef dataSource
) {
351 CFErrorRef error
= NULL
;
352 // TODO: Needs to be a SecDBItemRef for the SecItemDataSource...
353 CFDictionaryRef object
= SOSDataSourceCreateGenericItem(dataSource
, CFSTR("test_account"), CFSTR("test service"));
354 ok(SOSDataSourceMergeObject(dataSource
, object
, NULL
, &error
), "dataSource %@ added object %@", SOSEngineGetMyID(dataSource
->engine
), error
);
355 CFReleaseSafe(object
);
356 CFReleaseNull(error
);
359 ^ (SOSDataSourceRef dataSource
) {
360 __block CFErrorRef error
= NULL
;
361 SOSObjectRef object
= SOSDataSourceCreateGenericItem(dataSource
, CFSTR("test_account"), CFSTR("test service"));
362 ok(SOSDataSourceWith(dataSource
, &error
, ^(SOSTransactionRef txn
, bool *commit
) {
363 ok(SOSDataSourceMergeObject(dataSource
, txn
, object
, NULL
, &error
), "dataSource %@ added object %@", SOSEngineGetMyID(dataSource
->engine
), error
);
364 }), "ds transaction failed %@", error
);
365 CFReleaseSafe(object
);
366 CFReleaseNull(error
);
368 CFSTR("2AF312E092D67308A0083DFFBF2B6B754B967864"),
369 CFSTR("CB67BF9ECF00DC7664834DE7A2D7CC1523D25341"),
370 CFSTR("ADAA3ACE75ED516CB91893413EE9CC9ED04CA47B"),
372 //CFSTR("ADAA3ACE75ED516CB91893413EE9CC9ED04CA47B"),
373 //CFSTR("ADAA3ACE75ED516CB91893413EE9CC9ED04CA47B"),
374 //CFSTR("ADAA3ACE75ED516CB91893413EE9CC9ED04CA47B"),
377 // Sync a dataSource with one object to another dataSource with the same object
378 testsync("secd_70_engine-alice1bob2", test_directive
, test_reason
,
379 ^ (SOSDataSourceRef dataSource
) {
381 CFErrorRef error
= NULL
;
382 // TODO: Needs to be a SecDBItemRef for the SecItemDataSource...
383 SOSObjectRef object
= SOSDataSourceCreateGenericItem(dataSource
, CFSTR("test_account"), CFSTR("test service"));
384 ok(SOSDataSourceMergeObject(dataSource
, object
, NULL
, &error
), "dataSource %@ added object %@", SOSEngineGetMyID(dataSource
->engine
), error
);
385 CFReleaseSafe(object
);
386 CFReleaseNull(error
);
389 ^ (SOSDataSourceRef dataSource
) {
390 __block CFErrorRef error
= NULL
;
391 __block SOSObjectRef object
= SOSDataSourceCreateGenericItem(dataSource
, CFSTR("test_account"), CFSTR("test service"));
392 ok(SOSDataSourceWith(dataSource
, &error
, ^(SOSTransactionRef txn
, bool *commit
) {
393 ok(SOSDataSourceMergeObject(dataSource
, txn
, object
, NULL
, &error
), "dataSource %@ added object %@", SOSEngineGetMyID(dataSource
->engine
), error
);
394 CFReleaseSafe(object
);
395 CFReleaseNull(error
);
396 object
= SOSDataSourceCreateGenericItem(dataSource
, CFSTR("account1"), CFSTR("service1"));
397 ok(SOSDataSourceMergeObject(dataSource
, txn
, object
, NULL
, &error
), "dataSource %@ added object %@", SOSEngineGetMyID(dataSource
->engine
), error
);
398 CFReleaseSafe(object
);
399 }), "ds transaction failed %@", error
);
400 CFReleaseNull(error
);
402 CFSTR("2AF312E092D67308A0083DFFBF2B6B754B967864"),
403 CFSTR("270EB3953B2E1E295F668CFC27CBB7137991A4BE"),
404 CFSTR("D1B3944E3084425F41B2C2EA0BE82170E10AA37D"),
406 //CFSTR("ADAA3ACE75ED516CB91893413EE9CC9ED04CA47B"),
407 //CFSTR("D4049A1063CFBF7CAF8424E13DE3CE926FF5856C"),
408 //CFSTR("9624EA855BBED6B668868BB723443E804D04F6A1"),
409 //CFSTR("063E097CCD4FEB7F3610ED12B3DA828467314846"),
410 //CFSTR("D1B3944E3084425F41B2C2EA0BE82170E10AA37D"),
413 // Sync a dataSource with a tombstone object to another dataSource with the same object
415 todo("<rdar://problem/14049022> Test case in sd-70-engine fails due to need for RowID");
416 testsync("secd_70_engine-update", test_directive
, test_reason
,
417 ^ (SOSDataSourceRef dataSource
) {
418 __block CFErrorRef error
= NULL
;
419 const char *password
= "password1";
420 CFDataRef data
= CFDataCreate(kCFAllocatorDefault
, (const UInt8
*)password
, strlen(password
));
421 // TODO: Needs to be a SecDBItemRef for the SecItemDataSource...
422 SOSObjectRef object_to_find
= SOSDataSourceCreateGenericItemWithData(dataSource
, CFSTR("test_account"), CFSTR("test service"), true, NULL
);
423 SOSObjectRef object
= SOSDataSourceCopyObject(dataSource
, object_to_find
, &error
);
424 SOSObjectRef old_object
= NULL
;
426 skip("no object", 1, ok(object
, "Finding object %@, error: %@", object_to_find
, error
));
428 // TODO: Needs to be a SecDBItemRef for the SecItemDataSource...
429 old_object
= SOSDataSourceCreateGenericItem(dataSource
, CFSTR("test_account"), CFSTR("test service"));
430 ok(SOSDataSourceWith(dataSource
, &error
, ^(SOSTransactionRef txn
, bool *commit
) {
431 ok(SOSDataSourceMergeObject(dataSource
, txn
, object
, NULL
, &error
), "dataSource %@ update object %@", SOSEngineGetMyID(dataSource
->engine
), error
);
432 }), "ds transaction failed %@", error
);
435 CFReleaseSafe(old_object
);
436 CFReleaseSafe(object
);
437 CFReleaseNull(error
);
439 ^ (SOSDataSourceRef dataSource
) {
440 __block CFErrorRef error
= NULL
;
441 __block SOSObjectRef object
= SOSDataSourceCreateGenericItem(dataSource
, CFSTR("test_account"), CFSTR("test service"));
442 ok(SOSDataSourceWith(dataSource
, &error
, ^(SOSTransactionRef txn
, bool *commit
) {
443 ok(SOSDataSourceMergeObject(dataSource
, txn
, object
, NULL
, &error
), "dataSource %@ added object %@", SOSEngineGetMyID(dataSource
->engine
), error
);
444 CFReleaseSafe(object
);
445 CFReleaseNull(error
);
446 object
= SOSDataSourceCreateGenericItem(dataSource
, CFSTR("account1"), CFSTR("service1"));
447 ok(SOSDataSourceMergeObject(dataSource
, txn
, object
, NULL
, &error
), "dataSource %@ added object %@", SOSEngineGetMyID(dataSource
->engine
), error
);
448 CFReleaseSafe(object
);
449 }), "ds transaction failed %@", error
);
450 CFReleaseNull(error
);
452 CFSTR("2AF312E092D67308A0083DFFBF2B6B754B967864"),
453 CFSTR("270EB3953B2E1E295F668CFC27CBB7137991A4BE"),
454 CFSTR("D1B3944E3084425F41B2C2EA0BE82170E10AA37D"),
456 //CFSTR("5D07A221A152D6D6C5F1919189F259A7278A08C5"),
457 //CFSTR("D4049A1063CFBF7CAF8424E13DE3CE926FF5856C"),
458 //CFSTR("137FD34E9BF11B4BA0620E8EBFAB8576BCCCF294"),
459 //CFSTR("5D07A221A152D6D6C5F1919189F259A7278A08C5"),
463 // Sync a dataSource with one object to another dataSource with the same object
464 testsync("secd_70_engine-foreign-add", test_directive
, test_reason
,
465 ^ (SOSDataSourceRef dataSource
) {
467 ^ (SOSDataSourceRef dataSource
) {
468 __block CFErrorRef error
= NULL
;
469 const char *password
= "password1";
470 CFDataRef data
= CFDataCreate(kCFAllocatorDefault
, (const UInt8
*)password
, strlen(password
));
471 __block SOSObjectRef object
= SOSDataSourceCreateGenericItemWithData(dataSource
, CFSTR("test_account"), CFSTR("test service"), false, data
);
473 ok(SOSDataSourceWith(dataSource
, &error
, ^(SOSTransactionRef txn
, bool *commit
) {
474 ok(SOSDataSourceMergeObject(dataSource
, txn
, object
, NULL
, &error
), "dataSource %@ added object %@", SOSEngineGetMyID(dataSource
->engine
), error
);
475 CFReleaseSafe(object
);
476 CFReleaseNull(error
);
477 object
= SOSDataSourceCreateGenericItem(dataSource
, CFSTR("account1"), CFSTR("service1"));
478 ok(SOSDataSourceMergeObject(dataSource
, txn
, object
, NULL
, &error
), "dataSource %@ added object %@", SOSEngineGetMyID(dataSource
->engine
), error
);
479 CFReleaseSafe(object
);
480 }), "ds transaction failed %@", error
);
481 CFReleaseNull(error
);
483 CFSTR("2AF312E092D67308A0083DFFBF2B6B754B967864"),
484 CFSTR("769F63675CEE9CB968BFD9CA48DB9079BFCAFB6C"),
485 CFSTR("818C24B9BC495940836B9C8F76517C838CEFFA98"),
487 //CFSTR("D1B3944E3084425F41B2C2EA0BE82170E10AA37D"),
488 //CFSTR("607EEF976943FD781CFD2B3850E6DC7979AA61EF"),
489 //CFSTR("28434CD1B90CC205460557CAC03D7F12067F2329"),
490 //CFSTR("D1B3944E3084425F41B2C2EA0BE82170E10AA37D"),
494 // Sync between 2 empty dataSources
495 testsync2("secd_70_engine2", test_directive
, test_reason
,
496 ^ (SOSDataSourceRef dataSource
) {},
497 ^ (SOSDataSourceRef dataSource
) {},
498 CFSTR("2AF312E092D67308A0083DFFBF2B6B754B967864"),
499 CFSTR("2AF312E092D67308A0083DFFBF2B6B754B967864"),
500 CFSTR("2AF312E092D67308A0083DFFBF2B6B754B967864"),
501 CFSTR("2AF312E092D67308A0083DFFBF2B6B754B967864"),
502 CFSTR("2AF312E092D67308A0083DFFBF2B6B754B967864"),
506 testsyncmany("syncmany", test_directive
, test_reason
, 9, 10, 0, syncmany_add
);
507 testsyncmany("v2syncmany", test_directive
, test_reason
, 9, 10, 2, syncmany_add
);
511 int secd_70_engine(int argc
, char *const *argv
)
513 plan_tests(kTestTestCount
);
515 /* custom keychain dir */
516 secd_test_setup_temp_keychain(__FUNCTION__
, NULL
);