Merge branch 'master' of http://git.tine20.org/git/Syncope
[tine20] / tine20 / library / Syncope / tests / Syncope / Command / SyncTests.php
1 <?php
2 /**
3  * Tine 2.0 - http://www.tine20.org
4  * 
5  * @package     Tests
6  * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
7  * @copyright   Copyright (c) 2011-2012 Metaways Infosystems GmbH (http://www.metaways.de)
8  * @author      Lars Kneschke <l.kneschke@metaways.de>
9  */
10
11 /**
12  * Test class for Syncope_Command_Sync
13  * 
14  * @package     Tests
15  */
16 class Syncope_Command_SyncTests extends Syncope_Command_ATestCase
17 {
18     #protected $_logPriority = Zend_Log::DEBUG;
19     
20     /**
21      * Runs the test methods of this class.
22      *
23      * @access public
24      * @static
25      */
26     public static function main()
27     {
28         $suite  = new PHPUnit_Framework_TestSuite('Tine 2.0 ActiveSync Sync Command Tests');
29         PHPUnit_TextUI_TestRunner::run($suite);
30     }
31     
32     /**
33      * test sync with non existing collection id and synckey > 0
34      */
35     public function testSyncWithInvalidCollectiondId()
36     {
37         $doc = new DOMDocument();
38         $doc->loadXML('<?xml version="1.0" encoding="utf-8"?>
39             <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/">
40             <Sync xmlns="uri:AirSync" xmlns:AirSyncBase="uri:AirSyncBase"><Collections><Collection><Class>Contacts</Class><SyncKey>1356</SyncKey><CollectionId>48ru47fhf7ghf7fgh4</CollectionId><DeletesAsMoves/><GetChanges/><WindowSize>100</WindowSize><Options><AirSyncBase:BodyPreference><AirSyncBase:Type>1</AirSyncBase:Type><AirSyncBase:TruncationSize>5120</AirSyncBase:TruncationSize></AirSyncBase:BodyPreference><Conflict>1</Conflict></Options></Collection></Collections></Sync>'
41         );
42         
43         $sync = new Syncope_Command_Sync($doc, $this->_device, $this->_device->policykey);
44         
45         $sync->handle();
46         
47         $syncDoc = $sync->getResponse();
48         #$syncDoc->formatOutput = true; echo $syncDoc->saveXML();
49         
50         $xpath = new DomXPath($syncDoc);
51         $xpath->registerNamespace('AirSync', 'uri:AirSync');
52         
53         $nodes = $xpath->query('//AirSync:Sync/AirSync:Collections/AirSync:Collection/AirSync:SyncKey');
54         $this->assertEquals(1, $nodes->length, $syncDoc->saveXML());
55         $this->assertEquals(0, $nodes->item(0)->nodeValue, $syncDoc->saveXML());
56         
57         $nodes = $xpath->query('//AirSync:Sync/AirSync:Collections/AirSync:Collection/AirSync:Status');
58         $this->assertEquals(1, $nodes->length, $syncDoc->saveXML());
59         $this->assertEquals(Syncope_Command_Sync::STATUS_INVALID_SYNC_KEY, $nodes->item(0)->nodeValue, $syncDoc->saveXML());
60     }
61     
62     /**
63      * test sync with non existing collection id and synckey == 0
64      */
65     public function testSyncWithInvalidCollectiondIdAndSyncKey0()
66     {
67         $doc = new DOMDocument();
68         $doc->loadXML('<?xml version="1.0" encoding="utf-8"?>
69             <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/">
70             <Sync xmlns="uri:AirSync" xmlns:AirSyncBase="uri:AirSyncBase"><Collections><Collection><Class>Contacts</Class><SyncKey>0</SyncKey><CollectionId>48ru47fhf7ghf7fgh4</CollectionId><DeletesAsMoves/><GetChanges/><WindowSize>100</WindowSize><Options><AirSyncBase:BodyPreference><AirSyncBase:Type>1</AirSyncBase:Type><AirSyncBase:TruncationSize>5120</AirSyncBase:TruncationSize></AirSyncBase:BodyPreference><Conflict>1</Conflict></Options></Collection></Collections></Sync>'
71         );
72         
73         $sync = new Syncope_Command_Sync($doc, $this->_device, $this->_device->policykey);
74         
75         $sync->handle();
76         
77         $syncDoc = $sync->getResponse();
78         #$syncDoc->formatOutput = true; echo $syncDoc->saveXML();
79         
80         $xpath = new DomXPath($syncDoc);
81         $xpath->registerNamespace('AirSync', 'uri:AirSync');
82         
83         $nodes = $xpath->query('//AirSync:Sync/AirSync:Collections/AirSync:Collection/AirSync:SyncKey');
84         $this->assertEquals(1, $nodes->length, $syncDoc->saveXML());
85         $this->assertEquals(0, $nodes->item(0)->nodeValue, $syncDoc->saveXML());
86         
87         $nodes = $xpath->query('//AirSync:Sync/AirSync:Collections/AirSync:Collection/AirSync:Status');
88         $this->assertEquals(1, $nodes->length, $syncDoc->saveXML());
89         $this->assertEquals(Syncope_Command_Sync::STATUS_OBJECT_NOT_FOUND, $nodes->item(0)->nodeValue, $syncDoc->saveXML());
90     }
91     
92     /**
93      * test sync of existing folder, before a folderSync got excecuted before
94      */
95     public function testSyncBeforeFolderSync()
96     {
97         $doc = new DOMDocument();
98         $doc->loadXML('<?xml version="1.0" encoding="utf-8"?>
99             <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/">
100             <Sync xmlns="uri:AirSync" xmlns:AirSyncBase="uri:AirSyncBase"><Collections><Collection><Class>Contacts</Class><SyncKey>0</SyncKey><CollectionId>addressbookFolderId</CollectionId><DeletesAsMoves/><GetChanges/><WindowSize>100</WindowSize><Options><AirSyncBase:BodyPreference><AirSyncBase:Type>1</AirSyncBase:Type><AirSyncBase:TruncationSize>5120</AirSyncBase:TruncationSize></AirSyncBase:BodyPreference><Conflict>1</Conflict></Options></Collection></Collections></Sync>'
101         );
102         
103         $sync = new Syncope_Command_Sync($doc, $this->_device, $this->_device->policykey);
104         
105         $sync->handle();
106         
107         $syncDoc = $sync->getResponse();
108         #$syncDoc->formatOutput = true; echo $syncDoc->saveXML();
109         
110         $xpath = new DomXPath($syncDoc);
111         $xpath->registerNamespace('AirSync', 'uri:AirSync');
112         
113         $nodes = $xpath->query('//AirSync:Sync/AirSync:Collections/AirSync:Collection/AirSync:SyncKey');
114         $this->assertEquals(1, $nodes->length, $syncDoc->saveXML());
115         $this->assertEquals(0, $nodes->item(0)->nodeValue, $syncDoc->saveXML());
116         
117         $nodes = $xpath->query('//AirSync:Sync/AirSync:Collections/AirSync:Collection/AirSync:Status');
118         $this->assertEquals(1, $nodes->length, $syncDoc->saveXML());
119         $this->assertEquals(Syncope_Command_Sync::STATUS_OBJECT_NOT_FOUND, $nodes->item(0)->nodeValue, $syncDoc->saveXML());
120     }
121     
122     /**
123      * test sync of existing contacts folder
124      */
125     public function testSyncOfContacts()
126     {        
127         // first do a foldersync
128         $doc = new DOMDocument();
129         $doc->loadXML('<?xml version="1.0" encoding="utf-8"?>
130             <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/">
131             <FolderSync xmlns="uri:FolderHierarchy"><SyncKey>0</SyncKey></FolderSync>'
132         );
133         $folderSync = new Syncope_Command_FolderSync($doc, $this->_device, $this->_device->policykey);
134         $folderSync->handle();
135         $folderSync->getResponse();
136         
137         
138         // request initial synckey
139         $doc = new DOMDocument();
140         $doc->loadXML('<?xml version="1.0" encoding="utf-8"?>
141             <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/">
142             <Sync xmlns="uri:AirSync" xmlns:AirSyncBase="uri:AirSyncBase"><Collections><Collection><Class>Contacts</Class><SyncKey>0</SyncKey><CollectionId>addressbookFolderId</CollectionId><DeletesAsMoves/><GetChanges/><WindowSize>2</WindowSize><Options><AirSyncBase:BodyPreference><AirSyncBase:Type>1</AirSyncBase:Type><AirSyncBase:TruncationSize>5120</AirSyncBase:TruncationSize></AirSyncBase:BodyPreference><Conflict>1</Conflict></Options></Collection></Collections></Sync>'
143         );
144         
145         $sync = new Syncope_Command_Sync($doc, $this->_device, $this->_device->policykey);
146         
147         $sync->handle();
148         
149         $syncDoc = $sync->getResponse();
150         #$syncDoc->formatOutput = true; echo $syncDoc->saveXML();
151         
152         $xpath = new DomXPath($syncDoc);
153         $xpath->registerNamespace('AirSync', 'uri:AirSync');
154         
155         $nodes = $xpath->query('//AirSync:Sync/AirSync:Collections/AirSync:Collection/AirSync:Class');
156         $this->assertEquals(1, $nodes->length, $syncDoc->saveXML());
157         $this->assertEquals('Contacts', $nodes->item(0)->nodeValue, $syncDoc->saveXML());
158         
159         $nodes = $xpath->query('//AirSync:Sync/AirSync:Collections/AirSync:Collection/AirSync:SyncKey');
160         $this->assertEquals(1, $nodes->length, $syncDoc->saveXML());
161         $this->assertEquals(1, $nodes->item(0)->nodeValue, $syncDoc->saveXML());
162         
163         $nodes = $xpath->query('//AirSync:Sync/AirSync:Collections/AirSync:Collection/AirSync:Status');
164         $this->assertEquals(1, $nodes->length, $syncDoc->saveXML());
165         $this->assertEquals(Syncope_Command_Sync::STATUS_SUCCESS, $nodes->item(0)->nodeValue, $syncDoc->saveXML());
166         
167         
168         // now do the first sync
169         $doc = new DOMDocument();
170         $doc->loadXML('<?xml version="1.0" encoding="utf-8"?>
171             <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/">
172             <Sync xmlns="uri:AirSync" xmlns:AirSyncBase="uri:AirSyncBase"><Collections><Collection><Class>Contacts</Class><SyncKey>1</SyncKey><CollectionId>addressbookFolderId</CollectionId><DeletesAsMoves/><GetChanges/><WindowSize>2</WindowSize><Options><AirSyncBase:BodyPreference><AirSyncBase:Type>1</AirSyncBase:Type><AirSyncBase:TruncationSize>5120</AirSyncBase:TruncationSize></AirSyncBase:BodyPreference><Conflict>1</Conflict></Options></Collection></Collections></Sync>'
173         );
174         
175         $sync = new Syncope_Command_Sync($doc, $this->_device, $this->_device->policykey);
176         
177         $sync->handle();
178         
179         $syncDoc = $sync->getResponse();
180         #$syncDoc->formatOutput = true; echo $syncDoc->saveXML();
181         
182         $xpath = new DomXPath($syncDoc);
183         $xpath->registerNamespace('AirSync', 'uri:AirSync');
184         
185         $nodes = $xpath->query('//AirSync:Sync/AirSync:Collections/AirSync:Collection/AirSync:Class');
186         $this->assertEquals(1, $nodes->length, $syncDoc->saveXML());
187         $this->assertEquals('Contacts', $nodes->item(0)->nodeValue, $syncDoc->saveXML());
188         
189         $nodes = $xpath->query('//AirSync:Sync/AirSync:Collections/AirSync:Collection/AirSync:SyncKey');
190         $this->assertEquals(1, $nodes->length, $syncDoc->saveXML());
191         $this->assertEquals(2, $nodes->item(0)->nodeValue, $syncDoc->saveXML());
192         
193         $nodes = $xpath->query('//AirSync:Sync/AirSync:Collections/AirSync:Collection/AirSync:Status');
194         $this->assertEquals(1, $nodes->length, $syncDoc->saveXML());
195         $this->assertEquals(Syncope_Command_Sync::STATUS_SUCCESS, $nodes->item(0)->nodeValue, $syncDoc->saveXML());
196         
197         $nodes = $xpath->query('//AirSync:Sync/AirSync:Collections/AirSync:Collection/AirSync:MoreAvailable');
198         $this->assertEquals(1, $nodes->length, $syncDoc->saveXML());
199         
200         $nodes = $xpath->query('//AirSync:Sync/AirSync:Collections/AirSync:Collection/AirSync:Commands');
201         $this->assertEquals(1, $nodes->length, $syncDoc->saveXML());
202         #$this->assertEquals(Syncope_Command_Sync::STATUS_SUCCESS, $nodes->item(0)->nodeValue, $syncDoc->saveXML());
203         
204         // there should be no responses element
205         $nodes = $xpath->query('//AirSync:Sync/AirSync:Collections/AirSync:Collection/AirSync:Responses');
206         $this->assertEquals(0, $nodes->length, $syncDoc->saveXML());
207                 
208         $this->assertEquals("uri:Contacts", $syncDoc->lookupNamespaceURI('Contacts'), $syncDoc->saveXML());
209         
210         // try with previous synckey again
211         $doc = new DOMDocument();
212         $doc->loadXML('<?xml version="1.0" encoding="utf-8"?>
213             <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/">
214             <Sync xmlns="uri:AirSync" xmlns:AirSyncBase="uri:AirSyncBase"><Collections><Collection><Class>Contacts</Class><SyncKey>1</SyncKey><CollectionId>addressbookFolderId</CollectionId><DeletesAsMoves/><GetChanges/><WindowSize>2</WindowSize><Options><AirSyncBase:BodyPreference><AirSyncBase:Type>1</AirSyncBase:Type><AirSyncBase:TruncationSize>5120</AirSyncBase:TruncationSize></AirSyncBase:BodyPreference><Conflict>1</Conflict></Options></Collection></Collections></Sync>'
215         );
216         
217         $sync = new Syncope_Command_Sync($doc, $this->_device, $this->_device->policykey);
218         
219         $sync->handle();
220         
221         $syncDoc = $sync->getResponse();
222         #$syncDoc->formatOutput = true; echo $syncDoc->saveXML();
223         
224         
225         // and now fetch the rest
226         $doc = new DOMDocument();
227         $doc->loadXML('<?xml version="1.0" encoding="utf-8"?>
228             <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/">
229             <Sync xmlns="uri:AirSync" xmlns:AirSyncBase="uri:AirSyncBase"><Collections><Collection><Class>Contacts</Class><SyncKey>2</SyncKey><CollectionId>addressbookFolderId</CollectionId><DeletesAsMoves/><GetChanges/><WindowSize>20</WindowSize><Options><AirSyncBase:BodyPreference><AirSyncBase:Type>1</AirSyncBase:Type><AirSyncBase:TruncationSize>5120</AirSyncBase:TruncationSize></AirSyncBase:BodyPreference><Conflict>1</Conflict></Options></Collection></Collections></Sync>'
230         );
231         
232         $sync = new Syncope_Command_Sync($doc, $this->_device, $this->_device->policykey);
233         
234         $sync->handle();
235         
236         $syncDoc = $sync->getResponse();
237         #$syncDoc->formatOutput = true; echo $syncDoc->saveXML();
238         
239         $xpath = new DomXPath($syncDoc);
240         $xpath->registerNamespace('AirSync', 'uri:AirSync');
241         
242         $nodes = $xpath->query('//AirSync:Sync/AirSync:Collections/AirSync:Collection/AirSync:MoreAvailable');
243         $this->assertEquals(0, $nodes->length, $syncDoc->saveXML());
244     }
245         
246     /**
247      * @return string the id of the newly created contact
248      */
249     public function testAddingContactToServer()
250     {
251         $this->testSyncOfContacts();
252         
253         // lets add one contact
254         $doc = new DOMDocument();
255         $doc->loadXML('<?xml version="1.0" encoding="utf-8"?>
256             <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/">
257             <Sync xmlns="uri:AirSync" xmlns:AirSyncBase="uri:AirSyncBase"><Collections>
258                 <Collection>
259                     <Class>Contacts</Class><SyncKey>2</SyncKey><CollectionId>addressbookFolderId</CollectionId><DeletesAsMoves/><GetChanges/><WindowSize>100</WindowSize>
260                     <Options><AirSyncBase:BodyPreference><AirSyncBase:Type>1</AirSyncBase:Type><AirSyncBase:TruncationSize>5120</AirSyncBase:TruncationSize></AirSyncBase:BodyPreference><Conflict>1</Conflict></Options>
261                     <Commands><Add><ClientId>42</ClientId><ApplicationData></ApplicationData></Add></Commands>
262                 </Collection>
263             </Collections></Sync>'
264         );
265         
266         $sync = new Syncope_Command_Sync($doc, $this->_device, $this->_device->policykey);
267         
268         $sync->handle();
269         
270         $syncDoc = $sync->getResponse();
271         #$syncDoc->formatOutput = true; echo $syncDoc->saveXML();
272
273         $xpath = new DomXPath($syncDoc);
274         $xpath->registerNamespace('AirSync', 'uri:AirSync');
275         
276         $nodes = $xpath->query('//AirSync:Sync/AirSync:Collections/AirSync:Collection/AirSync:Class');
277         $this->assertEquals(1, $nodes->length, $syncDoc->saveXML());
278         $this->assertEquals('Contacts', $nodes->item(0)->nodeValue, $syncDoc->saveXML());
279         
280         $nodes = $xpath->query('//AirSync:Sync/AirSync:Collections/AirSync:Collection/AirSync:SyncKey');
281         $this->assertEquals(1, $nodes->length, $syncDoc->saveXML());
282         $this->assertEquals(3, $nodes->item(0)->nodeValue, $syncDoc->saveXML());
283         
284         $nodes = $xpath->query('//AirSync:Sync/AirSync:Collections/AirSync:Collection/AirSync:Status');
285         $this->assertEquals(1, $nodes->length, $syncDoc->saveXML());
286         $this->assertEquals(Syncope_Command_Sync::STATUS_SUCCESS, $nodes->item(0)->nodeValue, $syncDoc->saveXML());
287         
288         $nodes = $xpath->query('//AirSync:Sync/AirSync:Collections/AirSync:Collection/AirSync:Responses/AirSync:Add/AirSync:ServerId');
289         $this->assertEquals(1, $nodes->length, $syncDoc->saveXML());
290         $this->assertFalse(empty($nodes->item(0)->nodeValue), $syncDoc->saveXML());
291         
292         return $nodes->item(0)->nodeValue;
293     }
294             
295     public function testUpdatingContactOnServer()
296     {
297         $serverId = $this->testAddingContactToServer();
298         
299         // lets add one contact
300         $doc = new DOMDocument();
301         $doc->loadXML('<?xml version="1.0" encoding="utf-8"?>
302             <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/">
303             <Sync xmlns="uri:AirSync" xmlns:Contacts="uri:Contacts" xmlns:AirSyncBase="uri:AirSyncBase"><Collections>
304                 <Collection>
305                     <Class>Contacts</Class><SyncKey>3</SyncKey><CollectionId>addressbookFolderId</CollectionId><DeletesAsMoves/><GetChanges/><WindowSize>100</WindowSize>
306                     <Options><AirSyncBase:BodyPreference><AirSyncBase:Type>1</AirSyncBase:Type><AirSyncBase:TruncationSize>5120</AirSyncBase:TruncationSize></AirSyncBase:BodyPreference><Conflict>1</Conflict></Options>
307                     <Commands><Change><ServerId>' . $serverId . '</ServerId><ApplicationData><Contacts:FirstName>aaaadde</Contacts:FirstName><Contacts:LastName>aaaaade</Contacts:LastName></ApplicationData></Change></Commands>
308                 </Collection>
309             </Collections></Sync>'
310         );
311         
312         $sync = new Syncope_Command_Sync($doc, $this->_device, $this->_device->policykey);
313         
314         $sync->handle();
315         
316         $syncDoc = $sync->getResponse();
317         #$syncDoc->formatOutput = true; echo $syncDoc->saveXML();
318
319         $xpath = new DomXPath($syncDoc);
320         $xpath->registerNamespace('AirSync', 'uri:AirSync');
321         
322         $nodes = $xpath->query('//AirSync:Sync/AirSync:Collections/AirSync:Collection/AirSync:Class');
323         $this->assertEquals(1, $nodes->length, $syncDoc->saveXML());
324         $this->assertEquals('Contacts', $nodes->item(0)->nodeValue, $syncDoc->saveXML());
325         
326         $nodes = $xpath->query('//AirSync:Sync/AirSync:Collections/AirSync:Collection/AirSync:SyncKey');
327         $this->assertEquals(1, $nodes->length, $syncDoc->saveXML());
328         $this->assertEquals(4, $nodes->item(0)->nodeValue, $syncDoc->saveXML());
329         
330         $nodes = $xpath->query('//AirSync:Sync/AirSync:Collections/AirSync:Collection/AirSync:Status');
331         $this->assertEquals(1, $nodes->length, $syncDoc->saveXML());
332         $this->assertEquals(Syncope_Command_Sync::STATUS_SUCCESS, $nodes->item(0)->nodeValue, $syncDoc->saveXML());
333         
334         $nodes = $xpath->query('//AirSync:Sync/AirSync:Collections/AirSync:Collection/AirSync:Responses');
335         $this->assertEquals(0, $nodes->length, $syncDoc->saveXML());
336         
337         $this->assertEquals('aaaadde', Syncope_Data_AData::$entries['Syncope_Data_Contacts']['addressbookFolderId'][$serverId]['FirstName']);
338         $this->assertEquals('aaaaade', Syncope_Data_AData::$entries['Syncope_Data_Contacts']['addressbookFolderId'][$serverId]['LastName']);
339     }
340             
341     public function testDeletingContactOnServer()
342     {
343         $serverId = $this->testAddingContactToServer();
344         
345         // lets add one contact
346         $doc = new DOMDocument();
347         $doc->loadXML('<?xml version="1.0" encoding="utf-8"?>
348             <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/">
349             <Sync xmlns="uri:AirSync" xmlns:AirSyncBase="uri:AirSyncBase"><Collections>
350                 <Collection>
351                     <Class>Contacts</Class><SyncKey>3</SyncKey><CollectionId>addressbookFolderId</CollectionId><DeletesAsMoves/><GetChanges/><WindowSize>100</WindowSize>
352                     <Options><AirSyncBase:BodyPreference><AirSyncBase:Type>1</AirSyncBase:Type><AirSyncBase:TruncationSize>5120</AirSyncBase:TruncationSize></AirSyncBase:BodyPreference><Conflict>1</Conflict></Options>
353                     <Commands><Delete><ServerId>' . $serverId . '</ServerId></Delete></Commands>
354                 </Collection>
355             </Collections></Sync>'
356         );
357         
358         $sync = new Syncope_Command_Sync($doc, $this->_device, $this->_device->policykey);
359         
360         $sync->handle();
361         
362         $syncDoc = $sync->getResponse();
363         #$syncDoc->formatOutput = true; echo $syncDoc->saveXML();
364
365         $xpath = new DomXPath($syncDoc);
366         $xpath->registerNamespace('AirSync', 'uri:AirSync');
367         
368         $nodes = $xpath->query('//AirSync:Sync/AirSync:Collections/AirSync:Collection/AirSync:Class');
369         $this->assertEquals(1, $nodes->length, $syncDoc->saveXML());
370         $this->assertEquals('Contacts', $nodes->item(0)->nodeValue, $syncDoc->saveXML());
371         
372         $nodes = $xpath->query('//AirSync:Sync/AirSync:Collections/AirSync:Collection/AirSync:SyncKey');
373         $this->assertEquals(1, $nodes->length, $syncDoc->saveXML());
374         $this->assertEquals(4, $nodes->item(0)->nodeValue, $syncDoc->saveXML());
375         
376         $nodes = $xpath->query('//AirSync:Sync/AirSync:Collections/AirSync:Collection/AirSync:Status');
377         $this->assertEquals(1, $nodes->length, $syncDoc->saveXML());
378         $this->assertEquals(Syncope_Command_Sync::STATUS_SUCCESS, $nodes->item(0)->nodeValue, $syncDoc->saveXML());
379     }
380             
381     public function testUpdatingContactOnClient()
382     {
383         $serverId = $this->testAddingContactToServer();
384         
385         Syncope_Data_Contacts::$changedEntries['Syncope_Data_Contacts'][] = $serverId;
386         
387         // lets add one contact
388         $doc = new DOMDocument();
389         $doc->loadXML('<?xml version="1.0" encoding="utf-8"?>
390             <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/">
391             <Sync xmlns="uri:AirSync" xmlns:AirSyncBase="uri:AirSyncBase"><Collections>
392                 <Collection>
393                     <Class>Contacts</Class><SyncKey>3</SyncKey><CollectionId>addressbookFolderId</CollectionId><DeletesAsMoves/><GetChanges/><WindowSize>100</WindowSize>
394                     <Options><AirSyncBase:BodyPreference><AirSyncBase:Type>1</AirSyncBase:Type><AirSyncBase:TruncationSize>5120</AirSyncBase:TruncationSize></AirSyncBase:BodyPreference><Conflict>1</Conflict></Options>
395                 </Collection>
396             </Collections></Sync>'
397         );
398         
399         $sync = new Syncope_Command_Sync($doc, $this->_device, $this->_device->policykey);
400         
401         $sync->handle();
402         
403         $syncDoc = $sync->getResponse();
404         #$syncDoc->formatOutput = true; echo $syncDoc->saveXML();
405
406         Syncope_Data_Contacts::$changedEntries['Syncope_Data_Contacts'] = array();
407         
408         $xpath = new DomXPath($syncDoc);
409         $xpath->registerNamespace('AirSync', 'uri:AirSync');
410         
411         $nodes = $xpath->query('//AirSync:Sync/AirSync:Collections/AirSync:Collection/AirSync:Class');
412         $this->assertEquals(1, $nodes->length, $syncDoc->saveXML());
413         $this->assertEquals('Contacts', $nodes->item(0)->nodeValue, $syncDoc->saveXML());
414         
415         $nodes = $xpath->query('//AirSync:Sync/AirSync:Collections/AirSync:Collection/AirSync:SyncKey');
416         $this->assertEquals(1, $nodes->length, $syncDoc->saveXML());
417         $this->assertEquals(4, $nodes->item(0)->nodeValue, $syncDoc->saveXML());
418         
419         $nodes = $xpath->query('//AirSync:Sync/AirSync:Collections/AirSync:Collection/AirSync:Status');
420         $this->assertEquals(1, $nodes->length, $syncDoc->saveXML());
421         $this->assertEquals(Syncope_Command_Sync::STATUS_SUCCESS, $nodes->item(0)->nodeValue, $syncDoc->saveXML());
422         
423         $nodes = $xpath->query('//AirSync:Sync/AirSync:Collections/AirSync:Collection/AirSync:Commands/AirSync:Change/AirSync:ServerId');
424         $this->assertEquals(1, $nodes->length, $syncDoc->saveXML());
425         $this->assertEquals($serverId, $nodes->item(0)->nodeValue, $syncDoc->saveXML());
426     }
427     
428     public function testDeletingContactOnClient()
429     {
430         $serverId = $this->testAddingContactToServer();
431         
432         unset(Syncope_Data_Contacts::$entries['Syncope_Data_Contacts']['addressbookFolderId'][$serverId]);
433         
434         // lets add one contact
435         $doc = new DOMDocument();
436         $doc->loadXML('<?xml version="1.0" encoding="utf-8"?>
437             <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/">
438             <Sync xmlns="uri:AirSync" xmlns:AirSyncBase="uri:AirSyncBase"><Collections>
439                 <Collection>
440                     <Class>Contacts</Class><SyncKey>3</SyncKey><CollectionId>addressbookFolderId</CollectionId><DeletesAsMoves/><GetChanges/><WindowSize>100</WindowSize>
441                     <Options><AirSyncBase:BodyPreference><AirSyncBase:Type>1</AirSyncBase:Type><AirSyncBase:TruncationSize>5120</AirSyncBase:TruncationSize></AirSyncBase:BodyPreference><Conflict>1</Conflict></Options>
442                 </Collection>
443             </Collections></Sync>'
444         );
445         
446         $sync = new Syncope_Command_Sync($doc, $this->_device, $this->_device->policykey);
447         
448         $sync->handle();
449         
450         $syncDoc = $sync->getResponse();
451         #$syncDoc->formatOutput = true; echo $syncDoc->saveXML();
452
453         $xpath = new DomXPath($syncDoc);
454         $xpath->registerNamespace('AirSync', 'uri:AirSync');
455         
456         $nodes = $xpath->query('//AirSync:Sync/AirSync:Collections/AirSync:Collection/AirSync:Class');
457         $this->assertEquals(1, $nodes->length, $syncDoc->saveXML());
458         $this->assertEquals('Contacts', $nodes->item(0)->nodeValue, $syncDoc->saveXML());
459         
460         $nodes = $xpath->query('//AirSync:Sync/AirSync:Collections/AirSync:Collection/AirSync:SyncKey');
461         $this->assertEquals(1, $nodes->length, $syncDoc->saveXML());
462         $this->assertEquals(4, $nodes->item(0)->nodeValue, $syncDoc->saveXML());
463         
464         $nodes = $xpath->query('//AirSync:Sync/AirSync:Collections/AirSync:Collection/AirSync:Status');
465         $this->assertEquals(1, $nodes->length, $syncDoc->saveXML());
466         $this->assertEquals(Syncope_Command_Sync::STATUS_SUCCESS, $nodes->item(0)->nodeValue, $syncDoc->saveXML());
467         
468         $nodes = $xpath->query('//AirSync:Sync/AirSync:Collections/AirSync:Collection/AirSync:Commands/AirSync:Delete/AirSync:ServerId');
469         $this->assertEquals(1, $nodes->length, $syncDoc->saveXML());
470         $this->assertEquals($serverId, $nodes->item(0)->nodeValue, $syncDoc->saveXML());
471     }
472     
473     public function testSyncWithNoChanges()
474     {
475         $serverId = $this->testSyncOfContacts();
476         
477         $doc = new DOMDocument();
478         $doc->loadXML('<?xml version="1.0" encoding="utf-8"?>
479             <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/">
480             <Sync xmlns="uri:AirSync" xmlns:AirSyncBase="uri:AirSyncBase"><Collections>
481                 <Collection>
482                     <Class>Contacts</Class><SyncKey>3</SyncKey><CollectionId>addressbookFolderId</CollectionId><DeletesAsMoves/><GetChanges/><WindowSize>100</WindowSize>
483                     <Options><AirSyncBase:BodyPreference><AirSyncBase:Type>1</AirSyncBase:Type><AirSyncBase:TruncationSize>5120</AirSyncBase:TruncationSize></AirSyncBase:BodyPreference><Conflict>1</Conflict></Options>
484                 </Collection>
485             </Collections></Sync>'
486         );
487         
488         $sync = new Syncope_Command_Sync($doc, $this->_device, $this->_device->policykey);
489         
490         $sync->handle();
491         
492         $syncDoc = $sync->getResponse();
493         #$syncDoc->formatOutput = true; echo $syncDoc->saveXML();
494
495         $xpath = new DomXPath($syncDoc);
496         $xpath->registerNamespace('AirSync', 'uri:AirSync');
497         
498         $nodes = $xpath->query('//AirSync:Sync/AirSync:Collections/AirSync:Collection/AirSync:SyncKey');
499         $this->assertEquals(1, $nodes->length, $syncDoc->saveXML());
500         $this->assertEquals(3, $nodes->item(0)->nodeValue, $syncDoc->saveXML());
501         
502         $nodes = $xpath->query('//AirSync:Sync/AirSync:Collections/AirSync:Collection/AirSync:Status');
503         $this->assertEquals(1, $nodes->length, $syncDoc->saveXML());
504         $this->assertEquals(Syncope_Command_Sync::STATUS_SUCCESS, $nodes->item(0)->nodeValue, $syncDoc->saveXML());
505     }
506     
507     /**
508      * @return string the id of the newly created contact
509      */
510     public function testConcurringSyncRequest()
511     {
512         $this->testSyncOfContacts();
513         
514         // lets add one contact
515         $doc = new DOMDocument();
516         $doc->loadXML('<?xml version="1.0" encoding="utf-8"?>
517             <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/">
518             <Sync xmlns="uri:AirSync" xmlns:AirSyncBase="uri:AirSyncBase"><Collections>
519                 <Collection>
520                     <Class>Contacts</Class><SyncKey>2</SyncKey><CollectionId>addressbookFolderId</CollectionId><DeletesAsMoves/><GetChanges/><WindowSize>100</WindowSize>
521                     <Options><AirSyncBase:BodyPreference><AirSyncBase:Type>1</AirSyncBase:Type><AirSyncBase:TruncationSize>5120</AirSyncBase:TruncationSize></AirSyncBase:BodyPreference><Conflict>1</Conflict></Options>
522                     <Commands><Add><ClientId>42</ClientId><ApplicationData></ApplicationData></Add></Commands>
523                 </Collection>
524             </Collections></Sync>'
525         );
526         
527         $sync = new Syncope_Command_Sync($doc, $this->_device, $this->_device->policykey);
528         
529         $sync->handle();
530         $count = count(Syncope_Data_Contacts::$entries['Syncope_Data_Contacts']["addressbookFolderId"]);
531         $folder = $this->_folderBackend->getFolder($this->_device, 'addressbookFolderId');
532         $syncState = $this->_syncStateBackend->getSyncState($this->_device, $folder);
533         $syncState->counter++;
534         $syncState = $this->_syncStateBackend->create($syncState);
535         
536         try {
537             $syncDoc = $sync->getResponse();
538             $catchedException = false;
539         } catch (Zend_Db_Statement_Exception $zdse) {
540             $catchedException = true;
541         }
542         
543         $this->assertTrue($catchedException);
544         $this->assertGreaterThan(count(Syncope_Data_Contacts::$entries['Syncope_Data_Contacts']["addressbookFolderId"]), $count);
545     }
546             
547 }