1<?php
2
3use dokuwiki\ChangeLog\PageChangeLog;
4
5/**
6 * saveWikiText() stores files in pages/, attic/ and adds entries to changelog
7 */
8class common_saveWikiText_test extends DokuWikiTest {
9
10    /** Delay writes of old revisions by a second. */
11    public function handle_write(Doku_Event $event, $param) {
12        if ($event->data[3] !== false) {
13            $this->waitForTick();
14        }
15    }
16
17    /**
18     * assertions against changelog entries and attic after saveWikiText()
19     */
20    private function checkChangeLogAfterNormalSave(
21        PageChangeLog $pagelog,
22        $expectedRevs,               // @param int
23        &$expectedLastEntry,         // @param array, pass by reference
24        $expected2ndLastEntry = null // @param array (optional)
25    ) {
26        $revisions = $pagelog->getRevisions(-1, 200);
27        $this->assertCount($expectedRevs, $revisions);
28        $this->assertCount($expectedRevs, array_unique($revisions), 'date duplicated in changelog');
29        // last revision
30        $lastRevInfo = $pagelog->getRevisionInfo($revisions[0]);
31        $expectedLastEntry += $lastRevInfo;
32        $this->assertEquals($expectedLastEntry, $lastRevInfo);
33        // current revision
34        $currentRevInfo = $pagelog->getCurrentRevisionInfo();
35        $this->assertEquals($currentRevInfo, $lastRevInfo, 'current & last revs should be identical');
36        // attic
37        $attic = wikiFN($lastRevInfo['id'], $lastRevInfo['date']);
38        $this->assertFileExists($attic, 'file missing in attic');
39        $files = count(glob(dirname($attic).'/'.noNS($lastRevInfo['id']).'.*'));
40        $this->assertLessThanOrEqual($expectedRevs, $files, 'detectExternalEdit() should not add too often old revs');
41
42        // second to last revision (optional), intended to check logline of previous external edits
43        if ($expected2ndLastEntry && count($revisions) > 1) {
44            $prevRevInfo = $pagelog->getRevisionInfo($revisions[1]);
45            unset($expected2ndLastEntry['timestamp']); // drop timestamp key
46            $this->assertEquals($expected2ndLastEntry, $prevRevInfo);
47        }
48    }
49
50    /**
51     * assertions against changelog entries and attic after external edit, create or deletion of page
52     */
53    private function checkChangeLogAfterExternalEdit(
54        PageChangeLog $pagelog,
55        $expectedRevs,          // @param int
56        $expectedLastEntry,     // @param array
57        &$expectedCurrentEntry  // @param array, pass by reference
58    ) {
59        $revisions = $pagelog->getRevisions(-1, 200);
60        $this->assertCount($expectedRevs, $revisions);
61        $this->assertCount($expectedRevs, array_unique($revisions), 'date duplicated in changelog');
62        // last revision
63        if ($expectedRevs > 0) {
64            $lastRevInfo = $pagelog->getRevisionInfo($revisions[0]);
65            $expectedLastEntry += $lastRevInfo;
66            $this->assertEquals($expectedLastEntry, $lastRevInfo);
67        } else {
68            $this->assertFalse($pagelog->lastRevision(), 'changelog file does not yet exist');
69        }
70        // current revision
71        $currentRevInfo = $pagelog->getCurrentRevisionInfo();
72        $this->assertArrayHasKey('timestamp', $currentRevInfo, 'should be external revision');
73        $expectedCurrentEntry += $currentRevInfo;
74        if ($expectedRevs > 0) {
75            $this->assertEquals($expectedCurrentEntry, $currentRevInfo);
76
77        }
78        // attic
79        $attic = wikiFN($currentRevInfo['id'], $currentRevInfo['date']);
80        $this->assertFileDoesNotExist($attic, 'page does not yet exist in attic');
81    }
82
83
84    /**
85     * Execute a whole bunch of saves on the same page and check the results
86     * TEST 1
87     *  1.1 create a page
88     *  1.2 save with same content should be ignored
89     *  1.3 update the page with new text
90     *  1.4 add a minor edit (unauthenticated, minor not allowable)
91     *  1.5 add a minor edit (authenticated)
92     *  1.6 delete
93     *  1.7 restore
94     *  1.8 external edit
95     *  1.9 edit and save on top of external edit
96     */
97    function test_savesequence1() {
98        global $REV;
99
100        $page = 'page';
101        $file = wikiFN($page);
102        $this->assertFileDoesNotExist($file);
103
104        // 1.1 create a page
105        saveWikiText($page, 'teststring', '1st save', false);
106        clearstatcache(false, $file);
107        $this->assertFileExists($file);
108        $lastmod = filemtime($file);
109        $expectedRevs = 1;
110        $expect = array(
111            'date' => $lastmod,
112            'type' => DOKU_CHANGE_TYPE_CREATE,
113            'sum'  => '1st save',
114            'sizechange' => 10, // = strlen('teststring')
115        );
116
117        $pagelog = new PageChangeLog($page);
118        $this->checkChangeLogAfterNormalSave($pagelog, $expectedRevs, $expect);
119
120        $this->waitForTick(true); // wait for new revision ID
121
122        // 1.2 save with same content should be ignored
123        saveWikiText($page, 'teststring', '2nd save', false);
124        clearstatcache(false, $file);
125        $this->assertEquals($lastmod, filemtime($file));
126
127        $pagelog = new PageChangeLog($page);
128        $revisions = $pagelog->getRevisions(-1, 200);
129        $this->assertCount(1, $revisions);
130
131        // 1.3 update the page with new text
132        saveWikiText($page, 'teststring2long', '3rd save', false);
133        clearstatcache(false, $file);
134        $newmod = filemtime($file);
135        $this->assertNotEquals($lastmod, $newmod);
136        $lastmod = $newmod;
137        $expectedRevs = 2;
138        $expectPrev = $expect;
139        $expect = array(
140            'date' => $lastmod,
141            'type' => DOKU_CHANGE_TYPE_EDIT,
142            'sum'  => '3rd save',
143            'sizechange' => 5,
144        );
145
146        $pagelog = new PageChangeLog($page);
147        $this->checkChangeLogAfterNormalSave($pagelog, $expectedRevs, $expect, $expectPrev);
148
149        $this->waitForTick(); // wait for new revision ID
150
151        // 1.4 add a minor edit (unauthenticated, minor not allowable)
152        saveWikiText($page, 'teststring3long', '4th save', true);
153        clearstatcache(false, $file);
154        $newmod = filemtime($file);
155        $this->assertNotEquals($lastmod, $newmod);
156        $lastmod = $newmod;
157        $expectedRevs = 3;
158        $expect = array(
159            'date' => $lastmod,
160            'type' => DOKU_CHANGE_TYPE_EDIT,
161            'sum'  => '4th save',
162            'sizechange' => 0,
163        );
164
165        $pagelog = new PageChangeLog($page);
166        $this->checkChangeLogAfterNormalSave($pagelog, $expectedRevs, $expect);
167
168        $this->waitForTick(); // wait for new revision ID
169
170        // 1.5 add a minor edit (authenticated)
171        $_SERVER['REMOTE_USER'] = 'user';
172        saveWikiText($page, 'teststring4', '5th save', true);
173        clearstatcache(false, $file);
174        $newmod = filemtime($file);
175        $this->assertNotEquals($lastmod, $newmod);
176        $lastmod = $newmod;
177        $expectedRevs = 4;
178        $expect = array(
179            'date' => $lastmod,
180            'type' => DOKU_CHANGE_TYPE_MINOR_EDIT,
181            'sum'  => '5th save',
182            'sizechange' => -4,
183        );
184
185        $pagelog = new PageChangeLog($page);
186        $this->checkChangeLogAfterNormalSave($pagelog, $expectedRevs, $expect);
187
188        $this->waitForTick(); // wait for new revision ID
189
190        // 1.6 delete
191        saveWikiText($page, '', '6th save', false);
192        clearstatcache(false, $file);
193        $this->assertFileDoesNotExist($file);
194        $expectedRevs = 5;
195        $expect = array(
196          //'date' => $lastmod, // ignore from lastRev assertion, but confirm attic file existence
197            'type' => DOKU_CHANGE_TYPE_DELETE,
198            'sum'  => '6th save',
199            'sizechange' => -11,
200        );
201
202        $pagelog = new PageChangeLog($page);
203        $this->checkChangeLogAfterNormalSave($pagelog, $expectedRevs, $expect);
204
205        $this->waitForTick(); // wait for new revision ID
206
207        // 1.7 restore
208        $REV = $lastmod;
209        saveWikiText($page, 'teststring4', '7th save', true);
210        clearstatcache(false, $file);
211        $this->assertFileExists($file);
212        $newmod = filemtime($file);
213        $this->assertNotEquals($lastmod, $newmod);
214        $lastmod = $newmod;
215        $expectedRevs = 6;
216        $expect = array(
217            'date' => $lastmod,
218            'type' => DOKU_CHANGE_TYPE_REVERT,
219            'sum'  => '7th save',
220            'sizechange' => 11,
221        );
222
223        $pagelog = new PageChangeLog($page);
224        $this->checkChangeLogAfterNormalSave($pagelog, $expectedRevs, $expect);
225        $REV = '';
226
227        $this->waitForTick(); // wait for new revision ID
228
229        // 1.8 external edit
230        file_put_contents($file, 'teststring5 external edit');
231        clearstatcache(false, $file);
232        $newmod = filemtime($file);
233        $this->assertNotEquals($lastmod, $newmod);
234        $lastmod = $newmod;
235        $expectedRevs = 6; // external edit is not yet in changelog
236        $expectExternal = array(
237            'date' => $lastmod,
238            'type' => DOKU_CHANGE_TYPE_EDIT,
239            'sum'  => 'external edit',
240            'sizechange' => 14,
241        );
242
243        $pagelog = new PageChangeLog($page);
244        $this->checkChangeLogAfterExternalEdit($pagelog, $expectedRevs, $expect, $expectExternal);
245
246        $this->waitForTick(); // wait for new revision ID
247
248        // 1.9 save on top of external edit
249        saveWikiText($page, 'teststring6', '8th save', false);
250        clearstatcache(false, $file);
251        $newmod = filemtime($file);
252        $this->assertNotEquals($lastmod, $newmod);
253        $lastmod = $newmod;
254        $expectedRevs = 8;
255        $expect = array(
256            'date' => $lastmod,
257            'type' => DOKU_CHANGE_TYPE_EDIT,
258            'sum'  => '8th save',
259            'sizechange' => -14,
260        );
261
262        $pagelog = new PageChangeLog($page);
263        $this->checkChangeLogAfterNormalSave($pagelog, $expectedRevs, $expect, $expectExternal);
264    }
265
266    /**
267     * Execute a whole bunch of saves on the same page and check the results
268     * using $this->handle_write() in event IO_WIKIPAGE_WRITE
269     * TEST 2 - create a page externally in 2.3, while external edit in Test 1.8
270     *  2.1 create a page
271     *  2.2 delete
272     *  2.3 externally create the page
273     *  2.4 edit and save on top of external edit
274     *  2.5 external edit
275     *  2.6 edit and save on top of external edit, again
276     */
277    function test_savesequence2() {
278        // add an additional delay when saving files to make sure
279        // nobody relies on the saving happening in the same second
280        /** @var $EVENT_HANDLER \dokuwiki\Extension\EventHandler */
281        global $EVENT_HANDLER;
282        $EVENT_HANDLER->register_hook('IO_WIKIPAGE_WRITE', 'BEFORE', $this, 'handle_write');
283
284        $page = 'page2';
285        $file = wikiFN($page);
286        $this->assertFileDoesNotExist($file);
287
288        // 2.1 create a page
289        saveWikiText($page, 'teststring', 'Test 2, 1st save', false);
290        clearstatcache(false, $file);
291        $this->assertFileExists($file);
292        $lastmod = filemtime($file);
293        $expectedRevs = 1;
294        $expect = array(
295            'date' => $lastmod,
296            'type' => DOKU_CHANGE_TYPE_CREATE,
297            'sum'  => 'Test 2, 1st save',
298            'sizechange' => 10, // = strlen('teststring')
299        );
300
301        $pagelog = new PageChangeLog($page);
302        $this->checkChangeLogAfterNormalSave($pagelog, $expectedRevs, $expect);
303
304        $this->waitForTick(true); // wait for new revision ID
305
306        // 2.2 delete
307        saveWikiText($page, '', 'Test 2, 2nd save', false);
308        clearstatcache(false, $file);
309        $this->assertFileDoesNotExist($file);
310        $expectedRevs = 2;
311        $expect = array(
312          //'date' => $lastmod, // ignore from lastRev assertion, but confirm attic file existence
313            'type' => DOKU_CHANGE_TYPE_DELETE,
314            'sum'  => 'Test 2, 2nd save',
315            'sizechange' => -10,
316        );
317
318        $pagelog = new PageChangeLog($page);
319        $this->checkChangeLogAfterNormalSave($pagelog, $expectedRevs, $expect);
320
321        $this->waitForTick(); // wait for new revision ID
322
323        // 2.3 externally create the page
324        file_put_contents($file, 'teststring5');
325        clearstatcache(false, $file);
326        $lastmod = filemtime($file);
327        $expectedRevs = 2; // external edit is not yet in changelog
328        $expectExternal = array(
329            'date' => $lastmod,
330            'type' => DOKU_CHANGE_TYPE_CREATE,
331            'sum'  => 'created - external edit',
332            'sizechange' => 11,
333        );
334
335        $pagelog = new PageChangeLog($page);
336        $this->checkChangeLogAfterExternalEdit($pagelog, $expectedRevs, $expect, $expectExternal);
337
338        $this->waitForTick(); // wait for new revision ID
339
340        // 2.4 save on top of external edit
341        saveWikiText($page, 'teststring6', 'Test 2, 3rd save', false);
342        clearstatcache(false, $file);
343        $newmod = filemtime($file);
344        $this->assertNotEquals($lastmod, $newmod);
345        $lastmod = $newmod;
346        $expectedRevs = 4; // two more revisions now!
347        $expect = array(
348            'date' => $lastmod,
349            'type' => DOKU_CHANGE_TYPE_EDIT,
350            'sum'  => 'Test 2, 3rd save',
351            'sizechange' => 0,
352        );
353
354        $pagelog = new PageChangeLog($page);
355        $this->checkChangeLogAfterNormalSave($pagelog, $expectedRevs, $expect, $expectExternal);
356
357        $this->waitForTick(); // wait for new revision ID
358
359         // 2.5 external edit
360        file_put_contents($file, 'teststring7 external edit2');
361        clearstatcache(false, $file);
362        $newmod = filemtime($file);
363        $this->assertNotEquals($lastmod, $newmod);
364        $lastmod = $newmod;
365        $expectedRevs = 4; // external edit is not yet in changelog
366        $expectExternal = array(
367            'date' => $lastmod,
368            'type' => DOKU_CHANGE_TYPE_EDIT,
369            'sum'  => 'external edit',
370            'sizechange' => 15,
371        );
372
373        $pagelog = new PageChangeLog($page);
374        $this->checkChangeLogAfterExternalEdit($pagelog, $expectedRevs, $expect, $expectExternal);
375
376        $this->waitForTick(); // wait for new revision ID
377
378        // 2.6 save on top of external edit, again
379        saveWikiText($page, 'teststring8', 'Test 2, 4th save', false);
380        clearstatcache(false, $file);
381        $newmod = filemtime($file);
382        $this->assertNotEquals($lastmod, $newmod);
383        $lastmod = $newmod;
384        $expectedRevs = 6; // two more revisions now!
385        $expect = array(
386            'date' => $lastmod,
387            'type' => DOKU_CHANGE_TYPE_EDIT,
388            'sum'  => 'Test 2, 4th save',
389            'sizechange' => -15,
390        );
391
392        $pagelog = new PageChangeLog($page);
393        $this->checkChangeLogAfterNormalSave($pagelog, $expectedRevs, $expect, $expectExternal);
394    }
395
396    /**
397     * Execute a whole bunch of saves on the same page and check the results
398     * TEST 3 - typical page life of bundled page such as wiki:syntax
399     *  3.1 externally create a page
400     *  3.2 external edit
401     *  3.3 edit and save on top of external edit
402     *  3.4 externally delete the page
403     */
404    function test_savesequence3() {
405        $page = 'page3';
406        $file = wikiFN($page);
407
408        // 3.1 externally create a page
409        $this->assertFileDoesNotExist($file);
410        file_put_contents($file, 'teststring');
411        clearstatcache(false, $file);
412        $lastmod = filemtime($file);
413        $expectedRevs = 0; // external edit is not yet in changelog
414        $expect = false;
415        $expectExternal = array(
416            'date' => $lastmod,
417            'type' => DOKU_CHANGE_TYPE_CREATE,
418            'sum'  => 'created - external edit',
419            'sizechange' => 10,
420        );
421
422        $pagelog = new PageChangeLog($page);
423        $this->checkChangeLogAfterExternalEdit($pagelog, $expectedRevs, $expect, $expectExternal);
424
425        $this->waitForTick(true); // wait for new revision ID
426
427        // 3.2 external edit (repeated, still no changelog exists)
428        file_put_contents($file, 'teststring external edit');
429        clearstatcache(false, $file);
430        $newmod = filemtime($file);
431        $this->assertNotEquals($lastmod, $newmod);
432        $lastmod = $newmod;
433        $expectedRevs = 0; // external edit is not yet in changelog
434        $expectExternal = array(
435            'date' => $lastmod,
436            'type' => DOKU_CHANGE_TYPE_CREATE,  // not DOKU_CHANGE_TYPE_EDIT
437            'sum'  => 'created - external edit',
438            'sizechange' => 24,
439        );
440
441        $pagelog = new PageChangeLog($page);
442        $this->checkChangeLogAfterExternalEdit($pagelog, $expectedRevs, $expect, $expectExternal);
443
444        $this->waitForTick(true); // wait for new revision ID
445
446        // 3.3 save on top of external edit
447        saveWikiText($page, 'teststring1', 'Test 3, first save', false);
448        clearstatcache(false, $file);
449        $newmod = filemtime($file);
450        $this->assertNotEquals($lastmod, $newmod);
451        $lastmod = $newmod;
452        $expectedRevs = 2; // two more revisions now!
453        $expect = array(
454            'date' => $lastmod,
455            'type' => DOKU_CHANGE_TYPE_EDIT,
456            'sum'  => 'Test 3, first save',
457            'sizechange' => -13,
458        );
459
460        $pagelog = new PageChangeLog($page);
461        $this->checkChangeLogAfterNormalSave($pagelog, $expectedRevs, $expect, $expectExternal);
462
463        $this->waitForTick(true); // wait for new revision ID
464
465        // 3.4 externally delete the page
466        unlink($file);
467        $expectedRevs = 2;
468        $expectExternal = array(
469          //'date' => $lastmod,
470            'type' => DOKU_CHANGE_TYPE_DELETE,
471            'sum'  => 'removed - external edit (Unknown date)',
472            'sizechange' => -11,
473        );
474
475        $pagelog = new PageChangeLog($page);
476        $this->checkChangeLogAfterExternalEdit($pagelog, $expectedRevs, $expect, $expectExternal);
477    }
478
479    /**
480     * Execute a whole bunch of saves on the same page and check the results
481     * TEST 4 - typical page life of bundled page such as wiki:syntax
482     *  4.1 externally create a page
483     *  4.2 edit and save
484     *  4.3 externally edit as a result of a file which has older timestamp than last revision
485     */
486    function test_savesequence4() {
487        $page = 'page4';
488        $file = wikiFN($page);
489
490        // 4.1 externally create a page
491        $this->assertFileDoesNotExist($file);
492        file_put_contents($file, 'teststring');
493        clearstatcache(false, $file);
494        $lastmod = filemtime($file);
495        $expectedRevs = 0; // external edit is not yet in changelog
496        $expect = false;
497        $expectExternal = array(
498            'date' => $lastmod,
499            'type' => DOKU_CHANGE_TYPE_CREATE,
500            'sum'  => 'created - external edit',
501            'sizechange' => 10,
502        );
503
504        $pagelog = new PageChangeLog($page);
505        $this->checkChangeLogAfterExternalEdit($pagelog, $expectedRevs, $expect, $expectExternal);
506
507        $this->waitForTick(true); // wait for new revision ID
508
509        // 4.2 edit and save
510        saveWikiText($page, 'teststring1', 'Test 4, first save', false);
511        clearstatcache(false, $file);
512        $newmod = filemtime($file);
513        $this->assertNotEquals($lastmod, $newmod);
514        $lastmod = $newmod;
515        $expectedRevs = 2; // two more revisions now!
516        $expect = array(
517            'date' => $lastmod,
518            'type' => DOKU_CHANGE_TYPE_EDIT,
519            'sum'  => 'Test 4, first save',
520            'sizechange' => 1,
521        );
522
523        $pagelog = new PageChangeLog($page);
524        $this->checkChangeLogAfterNormalSave($pagelog, $expectedRevs, $expect, $expectExternal);
525
526        $this->waitForTick(true); // wait for new revision ID
527
528        // 4.3 externally edit as a result of a file which has older timestamp than last revision
529        unlink($file);
530        file_put_contents($file, 'teststring fake 1 hour past');
531        touch($file, filemtime($file) -3600); // change file modification time to 1 hour past
532        clearstatcache();
533        $newmod = filemtime($file);
534        $this->assertLessThan($lastmod, $newmod); // file must be older than previous for this test
535        $expectedRevs = 2; // external edit is not yet in changelog
536        $expectExternal = array(
537            'date' => $lastmod + 1,
538            'type' => DOKU_CHANGE_TYPE_EDIT,
539            'sum'  => 'external edit (Unknown date)',
540            'sizechange' => 16,
541        );
542
543        $this->expectLogMessage('current file modification time is older than last');
544        $pagelog = new PageChangeLog($page);
545        $this->checkChangeLogAfterExternalEdit($pagelog, $expectedRevs, $expect, $expectExternal);
546    }
547
548    /**
549     * Execute a whole bunch of saves on the same page and check the results
550     * TEST 5 - page creation and deletion
551     *  5.1 create a page
552     *  5.2 external edit
553     *  5.3 edit and save on top of external edit
554     *  5.4 delete
555     *  5.5 create a page, second time
556     *  5.6 externally delete
557     *  5.7 create a page, third time
558     */
559    function test_savesequence5() {
560        $page = 'page5';
561        $file = wikiFN($page);
562        $this->assertFileDoesNotExist($file);
563
564        // 5.1 create a page
565        saveWikiText($page, 'teststring', 'Test 5, 1st save', false);
566        $this->assertFileExists($file);
567        $lastmod = filemtime($file);
568        $expectedRevs = 1;
569        $expect = array(
570            'date' => $lastmod,
571            'type' => DOKU_CHANGE_TYPE_CREATE,
572            'sum'  => 'Test 5, 1st save',
573            'sizechange' => 10, // = strlen('teststring')
574        );
575
576        $pagelog = new PageChangeLog($page);
577        $this->checkChangeLogAfterNormalSave($pagelog, $expectedRevs, $expect);
578
579        $this->waitForTick(true); // wait for new revision ID
580
581        // 5.2 external edit
582        file_put_contents($file, 'teststring external edit');
583        clearstatcache(false, $file);
584        $newmod = filemtime($file);
585        $this->assertNotEquals($lastmod, $newmod);
586        $lastmod = $newmod;
587        $expectedRevs = 1; // external edit is not yet in changelog
588        $expectExternal = array(
589            'date' => $lastmod,
590            'type' => DOKU_CHANGE_TYPE_EDIT,
591            'sum'  => 'external edit',
592            'sizechange' => 14,
593        );
594
595        $pagelog = new PageChangeLog($page);
596        $this->checkChangeLogAfterExternalEdit($pagelog, $expectedRevs, $expect, $expectExternal);
597
598        $this->waitForTick(); // wait for new revision ID
599
600        // 5.3 edit and save on top of external edit
601        saveWikiText($page, 'teststring normal edit', 'Test 5, 2nd save', false);
602        clearstatcache(false, $file);
603        $newmod = filemtime($file);
604        $this->assertNotEquals($lastmod, $newmod);
605        $lastmod = $newmod;
606        $expectedRevs = 3; // two more revisions now!
607        $expect = array(
608            'date' => $lastmod,
609            'type' => DOKU_CHANGE_TYPE_EDIT,
610            'sum'  => 'Test 5, 2nd save',
611            'sizechange' => -2,
612        );
613
614        $pagelog = new PageChangeLog($page);
615        $this->checkChangeLogAfterNormalSave($pagelog, $expectedRevs, $expect, $expectExternal);
616
617        $this->waitForTick(); // wait for new revision ID
618
619        // 5.4 delete
620        saveWikiText($page, '', 'Test 5 3rd save', false);
621        clearstatcache(false, $file);
622        $this->assertFileDoesNotExist($file);
623        $expectedRevs = 4;
624        $expect = array(
625          //'date' => $lastmod, // ignore from lastRev assertion, but confirm attic file existence
626            'type' => DOKU_CHANGE_TYPE_DELETE,
627            'sum'  => 'Test 5 3rd save',
628            'sizechange' => -22,
629        );
630
631        $pagelog = new PageChangeLog($page);
632        $this->checkChangeLogAfterNormalSave($pagelog, $expectedRevs, $expect);
633
634        $this->waitForTick(); // wait for new revision ID
635
636        // 5.5 create a page, second time
637        $this->assertFileDoesNotExist($file);
638        saveWikiText($page, 'teststring revived', 'Test 5, 4th save', false);
639        $this->assertFileExists($file);
640        $lastmod = filemtime($file);
641        $expectedRevs = 5;
642        $expect = array(
643            'date' => $lastmod,
644            'type' => DOKU_CHANGE_TYPE_CREATE,
645            'sum'  => 'Test 5, 4th save',
646            'sizechange' => 18, // = strlen('teststring revived')
647        );
648
649        $pagelog = new PageChangeLog($page);
650        $this->checkChangeLogAfterNormalSave($pagelog, $expectedRevs, $expect);
651
652        $this->waitForTick(true); // wait for new revision ID
653
654        // 5.6 externally delete
655        unlink($file);
656        $this->assertFileDoesNotExist($file);
657        $expectedRevs = 5;
658        $expectExternal = array(
659          //'date' => $lastmod,
660            'type' => DOKU_CHANGE_TYPE_DELETE,
661            'sum'  => 'removed - external edit (Unknown date)',
662            'sizechange' => -18,
663        );
664
665        $pagelog = new PageChangeLog($page);
666        $this->checkChangeLogAfterExternalEdit($pagelog, $expectedRevs, $expect, $expectExternal);
667
668        $this->waitForTick(true); // wait for new revision ID
669
670        // 5.7 create a page, third time
671        $this->assertFileDoesNotExist($file);
672        saveWikiText($page, 'teststring revived 2', 'Test 5, 5th save', false);
673        clearstatcache(false, $file);
674        $this->assertFileExists($file);
675        $lastmod = filemtime($file);
676        $expectedRevs = 7;
677        $expect = array(
678            'date' => $lastmod,
679            'type' => DOKU_CHANGE_TYPE_CREATE,
680            'sum'  => 'Test 5, 5th save',
681            'sizechange' => 20, // = strlen('teststring revived 2')
682        );
683
684        $pagelog = new PageChangeLog($page);
685        $this->checkChangeLogAfterNormalSave($pagelog, $expectedRevs, $expect, $expectExternal);
686    }
687
688}
689