7 class FileBackendTest
extends MediaWikiTestCase
{
8 private $backend, $multiBackend;
9 private $filesToPrune = array();
10 private $dirsToPrune = array();
11 private static $backendToUse;
14 global $wgFileBackends;
16 $tmpPrefix = wfTempDir() . '/filebackend-unittest-' . time() . '-' . mt_rand();
17 if ( $this->getCliArg( 'use-filebackend=' ) ) {
18 if ( self
::$backendToUse ) {
19 $this->singleBackend
= self
::$backendToUse;
21 $name = $this->getCliArg( 'use-filebackend=' );
23 foreach ( $wgFileBackends as $conf ) {
24 if ( $conf['name'] == $name ) {
29 $useConfig['name'] = 'localtesting'; // swap name
30 $class = $useConfig['class'];
31 self
::$backendToUse = new $class( $useConfig );
32 $this->singleBackend
= self
::$backendToUse;
35 $this->singleBackend
= new FSFileBackend( array(
36 'name' => 'localtesting',
37 'lockManager' => 'fsLockManager',
38 #'parallelize' => 'implicit',
39 'containerPaths' => array(
40 'unittest-cont1' => "{$tmpPrefix}-localtesting-cont1",
41 'unittest-cont2' => "{$tmpPrefix}-localtesting-cont2" )
44 $this->multiBackend
= new FileBackendMultiWrite( array(
45 'name' => 'localtesting',
46 'lockManager' => 'fsLockManager',
47 'parallelize' => 'implicit',
50 'name' => 'localmutlitesting1',
51 'class' => 'FSFileBackend',
52 'lockManager' => 'nullLockManager',
53 'containerPaths' => array(
54 'unittest-cont1' => "{$tmpPrefix}-localtestingmulti1-cont1",
55 'unittest-cont2' => "{$tmpPrefix}-localtestingmulti1-cont2" ),
56 'isMultiMaster' => false
59 'name' => 'localmutlitesting2',
60 'class' => 'FSFileBackend',
61 'lockManager' => 'nullLockManager',
62 'containerPaths' => array(
63 'unittest-cont1' => "{$tmpPrefix}-localtestingmulti2-cont1",
64 'unittest-cont2' => "{$tmpPrefix}-localtestingmulti2-cont2" ),
65 'isMultiMaster' => true
69 $this->filesToPrune
= array();
72 private function baseStorePath() {
73 return 'mwstore://localtesting';
76 private function backendClass() {
77 return get_class( $this->backend
);
81 * @dataProvider provider_testIsStoragePath
83 public function testIsStoragePath( $path, $isStorePath ) {
84 $this->assertEquals( $isStorePath, FileBackend
::isStoragePath( $path ),
85 "FileBackend::isStoragePath on path '$path'" );
88 function provider_testIsStoragePath() {
90 array( 'mwstore://', true ),
91 array( 'mwstore://backend', true ),
92 array( 'mwstore://backend/container', true ),
93 array( 'mwstore://backend/container/', true ),
94 array( 'mwstore://backend/container/path', true ),
95 array( 'mwstore://backend//container/', true ),
96 array( 'mwstore://backend//container//', true ),
97 array( 'mwstore://backend//container//path', true ),
98 array( 'mwstore:///', true ),
99 array( 'mwstore:/', false ),
100 array( 'mwstore:', false ),
105 * @dataProvider provider_testSplitStoragePath
107 public function testSplitStoragePath( $path, $res ) {
108 $this->assertEquals( $res, FileBackend
::splitStoragePath( $path ),
109 "FileBackend::splitStoragePath on path '$path'" );
112 function provider_testSplitStoragePath() {
114 array( 'mwstore://backend/container', array( 'backend', 'container', '' ) ),
115 array( 'mwstore://backend/container/', array( 'backend', 'container', '' ) ),
116 array( 'mwstore://backend/container/path', array( 'backend', 'container', 'path' ) ),
117 array( 'mwstore://backend/container//path', array( 'backend', 'container', '/path' ) ),
118 array( 'mwstore://backend//container/path', array( null, null, null ) ),
119 array( 'mwstore://backend//container//path', array( null, null, null ) ),
120 array( 'mwstore://', array( null, null, null ) ),
121 array( 'mwstore://backend', array( null, null, null ) ),
122 array( 'mwstore:///', array( null, null, null ) ),
123 array( 'mwstore:/', array( null, null, null ) ),
124 array( 'mwstore:', array( null, null, null ) )
129 * @dataProvider provider_normalizeStoragePath
131 public function testNormalizeStoragePath( $path, $res ) {
132 $this->assertEquals( $res, FileBackend
::normalizeStoragePath( $path ),
133 "FileBackend::normalizeStoragePath on path '$path'" );
136 function provider_normalizeStoragePath() {
138 array( 'mwstore://backend/container', 'mwstore://backend/container' ),
139 array( 'mwstore://backend/container/', 'mwstore://backend/container' ),
140 array( 'mwstore://backend/container/path', 'mwstore://backend/container/path' ),
141 array( 'mwstore://backend/container//path', 'mwstore://backend/container/path' ),
142 array( 'mwstore://backend/container///path', 'mwstore://backend/container/path' ),
143 array( 'mwstore://backend/container///path//to///obj', 'mwstore://backend/container/path/to/obj',
144 array( 'mwstore://', null ),
145 array( 'mwstore://backend', null ),
146 array( 'mwstore://backend//container/path', null ),
147 array( 'mwstore://backend//container//path', null ),
148 array( 'mwstore:///', null ),
149 array( 'mwstore:/', null ),
150 array( 'mwstore:', null ), )
155 * @dataProvider provider_testParentStoragePath
157 public function testParentStoragePath( $path, $res ) {
158 $this->assertEquals( $res, FileBackend
::parentStoragePath( $path ),
159 "FileBackend::parentStoragePath on path '$path'" );
162 function provider_testParentStoragePath() {
164 array( 'mwstore://backend/container/path/to/obj', 'mwstore://backend/container/path/to' ),
165 array( 'mwstore://backend/container/path/to', 'mwstore://backend/container/path' ),
166 array( 'mwstore://backend/container/path', 'mwstore://backend/container' ),
167 array( 'mwstore://backend/container', null ),
168 array( 'mwstore://backend/container/path/to/obj/', 'mwstore://backend/container/path/to' ),
169 array( 'mwstore://backend/container/path/to/', 'mwstore://backend/container/path' ),
170 array( 'mwstore://backend/container/path/', 'mwstore://backend/container' ),
171 array( 'mwstore://backend/container/', null ),
176 * @dataProvider provider_testExtensionFromPath
178 public function testExtensionFromPath( $path, $res ) {
179 $this->assertEquals( $res, FileBackend
::extensionFromPath( $path ),
180 "FileBackend::extensionFromPath on path '$path'" );
183 function provider_testExtensionFromPath() {
185 array( 'mwstore://backend/container/path.txt', 'txt' ),
186 array( 'mwstore://backend/container/path.svg.png', 'png' ),
187 array( 'mwstore://backend/container/path', '' ),
188 array( 'mwstore://backend/container/path.', '' ),
193 * @dataProvider provider_testStore
195 public function testStore( $op ) {
196 $this->filesToPrune
[] = $op['src'];
198 $this->backend
= $this->singleBackend
;
199 $this->tearDownFiles();
200 $this->doTestStore( $op );
201 $this->tearDownFiles();
203 $this->backend
= $this->multiBackend
;
204 $this->tearDownFiles();
205 $this->doTestStore( $op );
206 $this->filesToPrune
[] = $op['src']; # avoid file leaking
207 $this->tearDownFiles();
210 private function doTestStore( $op ) {
211 $backendName = $this->backendClass();
213 $source = $op['src'];
215 $this->prepare( array( 'dir' => dirname( $dest ) ) );
217 file_put_contents( $source, "Unit test file" );
219 if ( isset( $op['overwrite'] ) ||
isset( $op['overwriteSame'] ) ) {
220 $this->backend
->store( $op );
223 $status = $this->backend
->doOperation( $op );
225 $this->assertGoodStatus( $status,
226 "Store from $source to $dest succeeded without warnings ($backendName)." );
227 $this->assertEquals( true, $status->isOK(),
228 "Store from $source to $dest succeeded ($backendName)." );
229 $this->assertEquals( array( 0 => true ), $status->success
,
230 "Store from $source to $dest has proper 'success' field in Status ($backendName)." );
231 $this->assertEquals( true, file_exists( $source ),
232 "Source file $source still exists ($backendName)." );
233 $this->assertEquals( true, $this->backend
->fileExists( array( 'src' => $dest ) ),
234 "Destination file $dest exists ($backendName)." );
236 $this->assertEquals( filesize( $source ),
237 $this->backend
->getFileSize( array( 'src' => $dest ) ),
238 "Destination file $dest has correct size ($backendName)." );
240 $props1 = FSFile
::getPropsFromPath( $source );
241 $props2 = $this->backend
->getFileProps( array( 'src' => $dest ) );
242 $this->assertEquals( $props1, $props2,
243 "Source and destination have the same props ($backendName)." );
246 public function provider_testStore() {
249 $tmpName = TempFSFile
::factory( "unittests_", 'txt' )->getPath();
250 $toPath = $this->baseStorePath() . '/unittest-cont1/fun/obj1.txt';
251 $op = array( 'op' => 'store', 'src' => $tmpName, 'dst' => $toPath );
259 $op2['overwrite'] = true;
267 $op2['overwriteSame'] = true;
278 * @dataProvider provider_testCopy
280 public function testCopy( $op ) {
281 $this->backend
= $this->singleBackend
;
282 $this->tearDownFiles();
283 $this->doTestCopy( $op );
284 $this->tearDownFiles();
286 $this->backend
= $this->multiBackend
;
287 $this->tearDownFiles();
288 $this->doTestCopy( $op );
289 $this->tearDownFiles();
292 private function doTestCopy( $op ) {
293 $backendName = $this->backendClass();
295 $source = $op['src'];
297 $this->prepare( array( 'dir' => dirname( $source ) ) );
298 $this->prepare( array( 'dir' => dirname( $dest ) ) );
300 $status = $this->backend
->doOperation(
301 array( 'op' => 'create', 'content' => 'blahblah', 'dst' => $source ) );
302 $this->assertGoodStatus( $status,
303 "Creation of file at $source succeeded ($backendName)." );
305 if ( isset( $op['overwrite'] ) ||
isset( $op['overwriteSame'] ) ) {
306 $this->backend
->copy( $op );
309 $status = $this->backend
->doOperation( $op );
311 $this->assertGoodStatus( $status,
312 "Copy from $source to $dest succeeded without warnings ($backendName)." );
313 $this->assertEquals( true, $status->isOK(),
314 "Copy from $source to $dest succeeded ($backendName)." );
315 $this->assertEquals( array( 0 => true ), $status->success
,
316 "Copy from $source to $dest has proper 'success' field in Status ($backendName)." );
317 $this->assertEquals( true, $this->backend
->fileExists( array( 'src' => $source ) ),
318 "Source file $source still exists ($backendName)." );
319 $this->assertEquals( true, $this->backend
->fileExists( array( 'src' => $dest ) ),
320 "Destination file $dest exists after copy ($backendName)." );
323 $this->backend
->getFileSize( array( 'src' => $source ) ),
324 $this->backend
->getFileSize( array( 'src' => $dest ) ),
325 "Destination file $dest has correct size ($backendName)." );
327 $props1 = $this->backend
->getFileProps( array( 'src' => $source ) );
328 $props2 = $this->backend
->getFileProps( array( 'src' => $dest ) );
329 $this->assertEquals( $props1, $props2,
330 "Source and destination have the same props ($backendName)." );
333 public function provider_testCopy() {
336 $source = $this->baseStorePath() . '/unittest-cont1/file.txt';
337 $dest = $this->baseStorePath() . '/unittest-cont2/fileMoved.txt';
339 $op = array( 'op' => 'copy', 'src' => $source, 'dst' => $dest );
347 $op2['overwrite'] = true;
355 $op2['overwriteSame'] = true;
366 * @dataProvider provider_testMove
368 public function testMove( $op ) {
369 $this->backend
= $this->singleBackend
;
370 $this->tearDownFiles();
371 $this->doTestMove( $op );
372 $this->tearDownFiles();
374 $this->backend
= $this->multiBackend
;
375 $this->tearDownFiles();
376 $this->doTestMove( $op );
377 $this->tearDownFiles();
380 private function doTestMove( $op ) {
381 $backendName = $this->backendClass();
383 $source = $op['src'];
385 $this->prepare( array( 'dir' => dirname( $source ) ) );
386 $this->prepare( array( 'dir' => dirname( $dest ) ) );
388 $status = $this->backend
->doOperation(
389 array( 'op' => 'create', 'content' => 'blahblah', 'dst' => $source ) );
390 $this->assertGoodStatus( $status,
391 "Creation of file at $source succeeded ($backendName)." );
393 if ( isset( $op['overwrite'] ) ||
isset( $op['overwriteSame'] ) ) {
394 $this->backend
->copy( $op );
397 $status = $this->backend
->doOperation( $op );
398 $this->assertGoodStatus( $status,
399 "Move from $source to $dest succeeded without warnings ($backendName)." );
400 $this->assertEquals( true, $status->isOK(),
401 "Move from $source to $dest succeeded ($backendName)." );
402 $this->assertEquals( array( 0 => true ), $status->success
,
403 "Move from $source to $dest has proper 'success' field in Status ($backendName)." );
404 $this->assertEquals( false, $this->backend
->fileExists( array( 'src' => $source ) ),
405 "Source file $source does not still exists ($backendName)." );
406 $this->assertEquals( true, $this->backend
->fileExists( array( 'src' => $dest ) ),
407 "Destination file $dest exists after move ($backendName)." );
409 $this->assertNotEquals(
410 $this->backend
->getFileSize( array( 'src' => $source ) ),
411 $this->backend
->getFileSize( array( 'src' => $dest ) ),
412 "Destination file $dest has correct size ($backendName)." );
414 $props1 = $this->backend
->getFileProps( array( 'src' => $source ) );
415 $props2 = $this->backend
->getFileProps( array( 'src' => $dest ) );
416 $this->assertEquals( false, $props1['fileExists'],
417 "Source file does not exist accourding to props ($backendName)." );
418 $this->assertEquals( true, $props2['fileExists'],
419 "Destination file exists accourding to props ($backendName)." );
422 public function provider_testMove() {
425 $source = $this->baseStorePath() . '/unittest-cont1/file.txt';
426 $dest = $this->baseStorePath() . '/unittest-cont2/fileMoved.txt';
428 $op = array( 'op' => 'move', 'src' => $source, 'dst' => $dest );
436 $op2['overwrite'] = true;
444 $op2['overwriteSame'] = true;
455 * @dataProvider provider_testDelete
457 public function testDelete( $op, $withSource, $okStatus ) {
458 $this->backend
= $this->singleBackend
;
459 $this->tearDownFiles();
460 $this->doTestDelete( $op, $withSource, $okStatus );
461 $this->tearDownFiles();
463 $this->backend
= $this->multiBackend
;
464 $this->tearDownFiles();
465 $this->doTestDelete( $op, $withSource, $okStatus );
466 $this->tearDownFiles();
469 private function doTestDelete( $op, $withSource, $okStatus ) {
470 $backendName = $this->backendClass();
472 $source = $op['src'];
473 $this->prepare( array( 'dir' => dirname( $source ) ) );
476 $status = $this->backend
->doOperation(
477 array( 'op' => 'create', 'content' => 'blahblah', 'dst' => $source ) );
478 $this->assertGoodStatus( $status,
479 "Creation of file at $source succeeded ($backendName)." );
482 $status = $this->backend
->doOperation( $op );
484 $this->assertGoodStatus( $status,
485 "Deletion of file at $source succeeded without warnings ($backendName)." );
486 $this->assertEquals( true, $status->isOK(),
487 "Deletion of file at $source succeeded ($backendName)." );
488 $this->assertEquals( array( 0 => true ), $status->success
,
489 "Deletion of file at $source has proper 'success' field in Status ($backendName)." );
491 $this->assertEquals( false, $status->isOK(),
492 "Deletion of file at $source failed ($backendName)." );
495 $this->assertEquals( false, $this->backend
->fileExists( array( 'src' => $source ) ),
496 "Source file $source does not exist after move ($backendName)." );
499 $this->backend
->getFileSize( array( 'src' => $source ) ),
500 "Source file $source has correct size (false) ($backendName)." );
502 $props1 = $this->backend
->getFileProps( array( 'src' => $source ) );
503 $this->assertFalse( $props1['fileExists'],
504 "Source file $source does not exist according to props ($backendName)." );
507 public function provider_testDelete() {
510 $source = $this->baseStorePath() . '/unittest-cont1/myfacefile.txt';
512 $op = array( 'op' => 'delete', 'src' => $source );
521 false, // without source
525 $op['ignoreMissingSource'] = true;
528 false, // without source
536 * @dataProvider provider_testCreate
538 public function testCreate( $op, $alreadyExists, $okStatus, $newSize ) {
539 $this->backend
= $this->singleBackend
;
540 $this->tearDownFiles();
541 $this->doTestCreate( $op, $alreadyExists, $okStatus, $newSize );
542 $this->tearDownFiles();
544 $this->backend
= $this->multiBackend
;
545 $this->tearDownFiles();
546 $this->doTestCreate( $op, $alreadyExists, $okStatus, $newSize );
547 $this->tearDownFiles();
550 private function doTestCreate( $op, $alreadyExists, $okStatus, $newSize ) {
551 $backendName = $this->backendClass();
554 $this->prepare( array( 'dir' => dirname( $dest ) ) );
556 $oldText = 'blah...blah...waahwaah';
557 if ( $alreadyExists ) {
558 $status = $this->backend
->doOperation(
559 array( 'op' => 'create', 'content' => $oldText, 'dst' => $dest ) );
560 $this->assertGoodStatus( $status,
561 "Creation of file at $dest succeeded ($backendName)." );
564 $status = $this->backend
->doOperation( $op );
566 $this->assertGoodStatus( $status,
567 "Creation of file at $dest succeeded without warnings ($backendName)." );
568 $this->assertEquals( true, $status->isOK(),
569 "Creation of file at $dest succeeded ($backendName)." );
570 $this->assertEquals( array( 0 => true ), $status->success
,
571 "Creation of file at $dest has proper 'success' field in Status ($backendName)." );
573 $this->assertEquals( false, $status->isOK(),
574 "Creation of file at $dest failed ($backendName)." );
577 $this->assertEquals( true, $this->backend
->fileExists( array( 'src' => $dest ) ),
578 "Destination file $dest exists after creation ($backendName)." );
580 $props1 = $this->backend
->getFileProps( array( 'src' => $dest ) );
581 $this->assertEquals( true, $props1['fileExists'],
582 "Destination file $dest exists according to props ($backendName)." );
583 if ( $okStatus ) { // file content is what we saved
584 $this->assertEquals( $newSize, $props1['size'],
585 "Destination file $dest has expected size according to props ($backendName)." );
586 $this->assertEquals( $newSize,
587 $this->backend
->getFileSize( array( 'src' => $dest ) ),
588 "Destination file $dest has correct size ($backendName)." );
589 } else { // file content is some other previous text
590 $this->assertEquals( strlen( $oldText ), $props1['size'],
591 "Destination file $dest has original size according to props ($backendName)." );
592 $this->assertEquals( strlen( $oldText ),
593 $this->backend
->getFileSize( array( 'src' => $dest ) ),
594 "Destination file $dest has original size according to props ($backendName)." );
599 * @dataProvider provider_testCreate
601 public function provider_testCreate() {
604 $dest = $this->baseStorePath() . '/unittest-cont2/myspacefile.txt';
606 $op = array( 'op' => 'create', 'content' => 'test test testing', 'dst' => $dest );
609 false, // no dest already exists
611 strlen( $op['content'] )
615 $op2['content'] = "\n";
618 false, // no dest already exists
620 strlen( $op2['content'] )
624 $op2['content'] = "fsf\n waf 3kt";
627 true, // dest already exists
629 strlen( $op2['content'] )
633 $op2['content'] = "egm'g gkpe gpqg eqwgwqg";
634 $op2['overwrite'] = true;
637 true, // dest already exists
639 strlen( $op2['content'] )
643 $op2['content'] = "39qjmg3-qg";
644 $op2['overwriteSame'] = true;
647 true, // dest already exists
649 strlen( $op2['content'] )
656 * @dataProvider provider_testConcatenate
658 public function testConcatenate( $op, $srcs, $srcsContent, $alreadyExists, $okStatus ) {
659 $this->filesToPrune
[] = $op['dst'];
661 $this->backend
= $this->singleBackend
;
662 $this->tearDownFiles();
663 $this->doTestConcatenate( $op, $srcs, $srcsContent, $alreadyExists, $okStatus );
664 $this->tearDownFiles();
666 $this->backend
= $this->multiBackend
;
667 $this->tearDownFiles();
668 $this->doTestConcatenate( $op, $srcs, $srcsContent, $alreadyExists, $okStatus );
669 $this->filesToPrune
[] = $op['dst']; # avoid file leaking
670 $this->tearDownFiles();
673 private function doTestConcatenate( $params, $srcs, $srcsContent, $alreadyExists, $okStatus ) {
674 $backendName = $this->backendClass();
679 foreach ( $srcs as $i => $source ) {
680 $this->prepare( array( 'dir' => dirname( $source ) ) );
682 'op' => 'create', // operation
683 'dst' => $source, // source
684 'content' => $srcsContent[$i]
686 $expContent .= $srcsContent[$i];
688 $status = $this->backend
->doOperations( $ops );
690 $this->assertGoodStatus( $status,
691 "Creation of source files succeeded ($backendName)." );
693 $dest = $params['dst'];
694 if ( $alreadyExists ) {
695 $ok = file_put_contents( $dest, 'blah...blah...waahwaah' ) !== false;
696 $this->assertEquals( true, $ok,
697 "Creation of file at $dest succeeded ($backendName)." );
699 $ok = file_put_contents( $dest, '' ) !== false;
700 $this->assertEquals( true, $ok,
701 "Creation of 0-byte file at $dest succeeded ($backendName)." );
704 // Combine the files into one
705 $status = $this->backend
->concatenate( $params );
707 $this->assertGoodStatus( $status,
708 "Creation of concat file at $dest succeeded without warnings ($backendName)." );
709 $this->assertEquals( true, $status->isOK(),
710 "Creation of concat file at $dest succeeded ($backendName)." );
712 $this->assertEquals( false, $status->isOK(),
713 "Creation of concat file at $dest failed ($backendName)." );
717 $this->assertEquals( true, is_file( $dest ),
718 "Dest concat file $dest exists after creation ($backendName)." );
720 $this->assertEquals( true, is_file( $dest ),
721 "Dest concat file $dest exists after failed creation ($backendName)." );
724 $contents = file_get_contents( $dest );
725 $this->assertNotEquals( false, $contents, "File at $dest exists ($backendName)." );
728 $this->assertEquals( $expContent, $contents,
729 "Concat file at $dest has correct contents ($backendName)." );
731 $this->assertNotEquals( $expContent, $contents,
732 "Concat file at $dest has correct contents ($backendName)." );
736 function provider_testConcatenate() {
739 $rand = mt_rand( 0, 2000000000 ) . time();
740 $dest = wfTempDir() . "/randomfile!$rand.txt";
742 $this->baseStorePath() . '/unittest-cont1/file1.txt',
743 $this->baseStorePath() . '/unittest-cont1/file2.txt',
744 $this->baseStorePath() . '/unittest-cont1/file3.txt',
745 $this->baseStorePath() . '/unittest-cont1/file4.txt',
746 $this->baseStorePath() . '/unittest-cont1/file5.txt',
747 $this->baseStorePath() . '/unittest-cont1/file6.txt',
748 $this->baseStorePath() . '/unittest-cont1/file7.txt',
749 $this->baseStorePath() . '/unittest-cont1/file8.txt',
750 $this->baseStorePath() . '/unittest-cont1/file9.txt',
751 $this->baseStorePath() . '/unittest-cont1/file10.txt'
765 $params = array( 'srcs' => $srcs, 'dst' => $dest );
768 $params, // operation
770 $content, // content for each source
771 false, // no dest already exists
776 $params, // operation
778 $content, // content for each source
779 true, // dest already exists
787 * @dataProvider provider_testGetFileStat
789 public function testGetFileStat( $path, $content, $alreadyExists ) {
790 $this->backend
= $this->singleBackend
;
791 $this->tearDownFiles();
792 $this->doTestGetFileStat( $path, $content, $alreadyExists );
793 $this->tearDownFiles();
795 $this->backend
= $this->multiBackend
;
796 $this->tearDownFiles();
797 $this->doTestGetFileStat( $path, $content, $alreadyExists );
798 $this->tearDownFiles();
801 private function doTestGetFileStat( $path, $content, $alreadyExists ) {
802 $backendName = $this->backendClass();
804 if ( $alreadyExists ) {
805 $this->prepare( array( 'dir' => dirname( $path ) ) );
806 $status = $this->backend
->create( array( 'dst' => $path, 'content' => $content ) );
807 $this->assertGoodStatus( $status,
808 "Creation of file at $path succeeded ($backendName)." );
810 $size = $this->backend
->getFileSize( array( 'src' => $path ) );
811 $time = $this->backend
->getFileTimestamp( array( 'src' => $path ) );
812 $stat = $this->backend
->getFileStat( array( 'src' => $path ) );
814 $this->assertEquals( strlen( $content ), $size,
815 "Correct file size of '$path'" );
816 $this->assertTrue( abs( time() - wfTimestamp( TS_UNIX
, $time ) ) < 5,
817 "Correct file timestamp of '$path'" );
819 $size = $stat['size'];
820 $time = $stat['mtime'];
821 $this->assertEquals( strlen( $content ), $size,
822 "Correct file size of '$path'" );
823 $this->assertTrue( abs( time() - wfTimestamp( TS_UNIX
, $time ) ) < 5,
824 "Correct file timestamp of '$path'" );
826 $size = $this->backend
->getFileSize( array( 'src' => $path ) );
827 $time = $this->backend
->getFileTimestamp( array( 'src' => $path ) );
828 $stat = $this->backend
->getFileStat( array( 'src' => $path ) );
830 $this->assertFalse( $size, "Correct file size of '$path'" );
831 $this->assertFalse( $time, "Correct file timestamp of '$path'" );
832 $this->assertFalse( $stat, "Correct file stat of '$path'" );
836 function provider_testGetFileStat() {
839 $base = $this->baseStorePath();
840 $cases[] = array( "$base/unittest-cont1/b/z/some_file.txt", "some file contents", true );
841 $cases[] = array( "$base/unittest-cont1/b/some-other_file.txt", "", true );
842 $cases[] = array( "$base/unittest-cont1/b/some-diff_file.txt", null, false );
848 * @dataProvider provider_testGetFileContents
850 public function testGetFileContents( $source, $content ) {
851 $this->backend
= $this->singleBackend
;
852 $this->tearDownFiles();
853 $this->doTestGetFileContents( $source, $content );
854 $this->tearDownFiles();
856 $this->backend
= $this->multiBackend
;
857 $this->tearDownFiles();
858 $this->doTestGetFileContents( $source, $content );
859 $this->tearDownFiles();
862 private function doTestGetFileContents( $source, $content ) {
863 $backendName = $this->backendClass();
865 $this->prepare( array( 'dir' => dirname( $source ) ) );
867 $status = $this->backend
->doOperation(
868 array( 'op' => 'create', 'content' => $content, 'dst' => $source ) );
869 $this->assertGoodStatus( $status,
870 "Creation of file at $source succeeded ($backendName)." );
871 $this->assertEquals( true, $status->isOK(),
872 "Creation of file at $source succeeded with OK status ($backendName)." );
874 $newContents = $this->backend
->getFileContents( array( 'src' => $source, 'latest' => 1 ) );
875 $this->assertNotEquals( false, $newContents,
876 "Read of file at $source succeeded ($backendName)." );
878 $this->assertEquals( $content, $newContents,
879 "Contents read match data at $source ($backendName)." );
882 function provider_testGetFileContents() {
885 $base = $this->baseStorePath();
886 $cases[] = array( "$base/unittest-cont1/b/z/some_file.txt", "some file contents" );
887 $cases[] = array( "$base/unittest-cont1/b/some-other_file.txt", "more file contents" );
893 * @dataProvider provider_testGetLocalCopy
895 public function testGetLocalCopy( $source, $content ) {
896 $this->backend
= $this->singleBackend
;
897 $this->tearDownFiles();
898 $this->doTestGetLocalCopy( $source, $content );
899 $this->tearDownFiles();
901 $this->backend
= $this->multiBackend
;
902 $this->tearDownFiles();
903 $this->doTestGetLocalCopy( $source, $content );
904 $this->tearDownFiles();
907 private function doTestGetLocalCopy( $source, $content ) {
908 $backendName = $this->backendClass();
910 $this->prepare( array( 'dir' => dirname( $source ) ) );
912 $status = $this->backend
->doOperation(
913 array( 'op' => 'create', 'content' => $content, 'dst' => $source ) );
914 $this->assertGoodStatus( $status,
915 "Creation of file at $source succeeded ($backendName)." );
917 $tmpFile = $this->backend
->getLocalCopy( array( 'src' => $source ) );
918 $this->assertNotNull( $tmpFile,
919 "Creation of local copy of $source succeeded ($backendName)." );
921 $contents = file_get_contents( $tmpFile->getPath() );
922 $this->assertNotEquals( false, $contents, "Local copy of $source exists ($backendName)." );
925 function provider_testGetLocalCopy() {
928 $base = $this->baseStorePath();
929 $cases[] = array( "$base/unittest-cont1/a/z/some_file.txt", "some file contents" );
930 $cases[] = array( "$base/unittest-cont1/a/some-other_file.txt", "more file contents" );
936 * @dataProvider provider_testGetLocalReference
938 public function testGetLocalReference( $source, $content ) {
939 $this->backend
= $this->singleBackend
;
940 $this->tearDownFiles();
941 $this->doTestGetLocalReference( $source, $content );
942 $this->tearDownFiles();
944 $this->backend
= $this->multiBackend
;
945 $this->tearDownFiles();
946 $this->doTestGetLocalReference( $source, $content );
947 $this->tearDownFiles();
950 private function doTestGetLocalReference( $source, $content ) {
951 $backendName = $this->backendClass();
953 $this->prepare( array( 'dir' => dirname( $source ) ) );
955 $status = $this->backend
->doOperation(
956 array( 'op' => 'create', 'content' => $content, 'dst' => $source ) );
957 $this->assertGoodStatus( $status,
958 "Creation of file at $source succeeded ($backendName)." );
960 $tmpFile = $this->backend
->getLocalReference( array( 'src' => $source ) );
961 $this->assertNotNull( $tmpFile,
962 "Creation of local copy of $source succeeded ($backendName)." );
964 $contents = file_get_contents( $tmpFile->getPath() );
965 $this->assertNotEquals( false, $contents, "Local copy of $source exists ($backendName)." );
968 function provider_testGetLocalReference() {
971 $base = $this->baseStorePath();
972 $cases[] = array( "$base/unittest-cont1/a/z/some_file.txt", "some file contents" );
973 $cases[] = array( "$base/unittest-cont1/a/some-other_file.txt", "more file contents" );
979 * @dataProvider provider_testPrepareAndClean
981 public function testPrepareAndClean( $path, $isOK ) {
982 $this->backend
= $this->singleBackend
;
983 $this->doTestPrepareAndClean( $path, $isOK );
984 $this->tearDownFiles();
986 $this->backend
= $this->multiBackend
;
987 $this->doTestPrepareAndClean( $path, $isOK );
988 $this->tearDownFiles();
991 function provider_testPrepareAndClean() {
992 $base = $this->baseStorePath();
994 array( "$base/unittest-cont1/a/z/some_file1.txt", true ),
995 array( "$base/unittest-cont2/a/z/some_file2.txt", true ),
996 # Specific to FS backend with no basePath field set
997 #array( "$base/unittest-cont3/a/z/some_file3.txt", false ),
1001 private function doTestPrepareAndClean( $path, $isOK ) {
1002 $backendName = $this->backendClass();
1004 $status = $this->prepare( array( 'dir' => dirname( $path ) ) );
1006 $this->assertGoodStatus( $status,
1007 "Preparing dir $path succeeded without warnings ($backendName)." );
1008 $this->assertEquals( true, $status->isOK(),
1009 "Preparing dir $path succeeded ($backendName)." );
1011 $this->assertEquals( false, $status->isOK(),
1012 "Preparing dir $path failed ($backendName)." );
1015 $status = $this->backend
->clean( array( 'dir' => dirname( $path ) ) );
1017 $this->assertGoodStatus( $status,
1018 "Cleaning dir $path succeeded without warnings ($backendName)." );
1019 $this->assertEquals( true, $status->isOK(),
1020 "Cleaning dir $path succeeded ($backendName)." );
1022 $this->assertEquals( false, $status->isOK(),
1023 "Cleaning dir $path failed ($backendName)." );
1027 public function testRecursiveClean() {
1028 $this->backend
= $this->singleBackend
;
1029 $this->doTestRecursiveClean();
1030 $this->tearDownFiles();
1032 $this->backend
= $this->multiBackend
;
1033 $this->doTestRecursiveClean();
1034 $this->tearDownFiles();
1037 function doTestRecursiveClean() {
1038 $backendName = $this->backendClass();
1040 $base = $this->baseStorePath();
1042 "$base/unittest-cont1/a",
1043 "$base/unittest-cont1/a/b",
1044 "$base/unittest-cont1/a/b/c",
1045 "$base/unittest-cont1/a/b/c/d0",
1046 "$base/unittest-cont1/a/b/c/d1",
1047 "$base/unittest-cont1/a/b/c/d2",
1048 "$base/unittest-cont1/a/b/c/d0/1",
1049 "$base/unittest-cont1/a/b/c/d0/2",
1050 "$base/unittest-cont1/a/b/c/d1/3",
1051 "$base/unittest-cont1/a/b/c/d1/4",
1052 "$base/unittest-cont1/a/b/c/d2/5",
1053 "$base/unittest-cont1/a/b/c/d2/6"
1055 foreach ( $dirs as $dir ) {
1056 $status = $this->prepare( array( 'dir' => $dir ) );
1057 $this->assertGoodStatus( $status,
1058 "Preparing dir $dir succeeded without warnings ($backendName)." );
1061 if ( $this->backend
instanceof FSFileBackend
) {
1062 foreach ( $dirs as $dir ) {
1063 $this->assertEquals( true, $this->backend
->directoryExists( array( 'dir' => $dir ) ),
1064 "Dir $dir exists ($backendName)." );
1068 $status = $this->backend
->clean(
1069 array( 'dir' => "$base/unittest-cont1", 'recursive' => 1 ) );
1070 $this->assertGoodStatus( $status,
1071 "Recursive cleaning of dir $dir succeeded without warnings ($backendName)." );
1073 foreach ( $dirs as $dir ) {
1074 $this->assertEquals( false, $this->backend
->directoryExists( array( 'dir' => $dir ) ),
1075 "Dir $dir no longer exists ($backendName)." );
1079 // @TODO: testSecure
1081 public function testDoOperations() {
1082 $this->backend
= $this->singleBackend
;
1083 $this->tearDownFiles();
1084 $this->doTestDoOperations();
1085 $this->tearDownFiles();
1087 $this->backend
= $this->multiBackend
;
1088 $this->tearDownFiles();
1089 $this->doTestDoOperations();
1090 $this->tearDownFiles();
1092 $this->backend
= $this->singleBackend
;
1093 $this->tearDownFiles();
1094 $this->doTestDoOperations2();
1095 $this->tearDownFiles();
1097 $this->backend
= $this->multiBackend
;
1098 $this->tearDownFiles();
1099 $this->doTestDoOperations2();
1100 $this->tearDownFiles();
1102 $this->backend
= $this->singleBackend
;
1103 $this->tearDownFiles();
1104 $this->doTestDoOperationsFailing();
1105 $this->tearDownFiles();
1107 $this->backend
= $this->multiBackend
;
1108 $this->tearDownFiles();
1109 $this->doTestDoOperationsFailing();
1110 $this->tearDownFiles();
1113 private function doTestDoOperations() {
1114 $base = $this->baseStorePath();
1116 $fileA = "$base/unittest-cont1/a/b/fileA.txt";
1117 $fileAContents = '3tqtmoeatmn4wg4qe-mg3qt3 tq';
1118 $fileB = "$base/unittest-cont1/a/b/fileB.txt";
1119 $fileBContents = 'g-jmq3gpqgt3qtg q3GT ';
1120 $fileC = "$base/unittest-cont1/a/b/fileC.txt";
1121 $fileCContents = 'eigna[ogmewt 3qt g3qg flew[ag';
1122 $fileD = "$base/unittest-cont1/a/b/fileD.txt";
1124 $this->prepare( array( 'dir' => dirname( $fileA ) ) );
1125 $this->backend
->create( array( 'dst' => $fileA, 'content' => $fileAContents ) );
1126 $this->prepare( array( 'dir' => dirname( $fileB ) ) );
1127 $this->backend
->create( array( 'dst' => $fileB, 'content' => $fileBContents ) );
1128 $this->prepare( array( 'dir' => dirname( $fileC ) ) );
1129 $this->backend
->create( array( 'dst' => $fileC, 'content' => $fileCContents ) );
1130 $this->prepare( array( 'dir' => dirname( $fileD ) ) );
1132 $status = $this->backend
->doOperations( array(
1133 array( 'op' => 'copy', 'src' => $fileA, 'dst' => $fileC, 'overwrite' => 1 ),
1134 // Now: A:<A>, B:<B>, C:<A>, D:<empty> (file:<orginal contents>)
1135 array( 'op' => 'copy', 'src' => $fileC, 'dst' => $fileA, 'overwriteSame' => 1 ),
1136 // Now: A:<A>, B:<B>, C:<A>, D:<empty>
1137 array( 'op' => 'move', 'src' => $fileC, 'dst' => $fileD, 'overwrite' => 1 ),
1138 // Now: A:<A>, B:<B>, C:<empty>, D:<A>
1139 array( 'op' => 'move', 'src' => $fileB, 'dst' => $fileC ),
1140 // Now: A:<A>, B:<empty>, C:<B>, D:<A>
1141 array( 'op' => 'move', 'src' => $fileD, 'dst' => $fileA, 'overwriteSame' => 1 ),
1142 // Now: A:<A>, B:<empty>, C:<B>, D:<empty>
1143 array( 'op' => 'move', 'src' => $fileC, 'dst' => $fileA, 'overwrite' => 1 ),
1144 // Now: A:<B>, B:<empty>, C:<empty>, D:<empty>
1145 array( 'op' => 'copy', 'src' => $fileA, 'dst' => $fileC ),
1146 // Now: A:<B>, B:<empty>, C:<B>, D:<empty>
1147 array( 'op' => 'move', 'src' => $fileA, 'dst' => $fileC, 'overwriteSame' => 1 ),
1148 // Now: A:<empty>, B:<empty>, C:<B>, D:<empty>
1149 array( 'op' => 'copy', 'src' => $fileC, 'dst' => $fileC, 'overwrite' => 1 ),
1151 array( 'op' => 'copy', 'src' => $fileC, 'dst' => $fileC, 'overwriteSame' => 1 ),
1153 array( 'op' => 'move', 'src' => $fileC, 'dst' => $fileC, 'overwrite' => 1 ),
1155 array( 'op' => 'move', 'src' => $fileC, 'dst' => $fileC, 'overwriteSame' => 1 ),
1157 array( 'op' => 'null' ),
1161 $this->assertGoodStatus( $status, "Operation batch succeeded" );
1162 $this->assertEquals( true, $status->isOK(), "Operation batch succeeded" );
1163 $this->assertEquals( 13, count( $status->success
),
1164 "Operation batch has correct success array" );
1166 $this->assertEquals( false, $this->backend
->fileExists( array( 'src' => $fileA ) ),
1167 "File does not exist at $fileA" );
1168 $this->assertEquals( false, $this->backend
->fileExists( array( 'src' => $fileB ) ),
1169 "File does not exist at $fileB" );
1170 $this->assertEquals( false, $this->backend
->fileExists( array( 'src' => $fileD ) ),
1171 "File does not exist at $fileD" );
1173 $this->assertEquals( true, $this->backend
->fileExists( array( 'src' => $fileC ) ),
1174 "File exists at $fileC" );
1175 $this->assertEquals( $fileBContents,
1176 $this->backend
->getFileContents( array( 'src' => $fileC ) ),
1177 "Correct file contents of $fileC" );
1178 $this->assertEquals( strlen( $fileBContents ),
1179 $this->backend
->getFileSize( array( 'src' => $fileC ) ),
1180 "Correct file size of $fileC" );
1181 $this->assertEquals( wfBaseConvert( sha1( $fileBContents ), 16, 36, 31 ),
1182 $this->backend
->getFileSha1Base36( array( 'src' => $fileC ) ),
1183 "Correct file SHA-1 of $fileC" );
1186 // concurrency orientated
1187 function doTestDoOperations2() {
1188 $base = $this->baseStorePath();
1190 $fileAContents = '3tqtmoeatmn4wg4qe-mg3qt3 tq';
1191 $fileBContents = 'g-jmq3gpqgt3qtg q3GT ';
1192 $fileCContents = 'eigna[ogmewt 3qt g3qg flew[ag';
1194 $tmpNameA = TempFSFile
::factory( "unittests_", 'txt' )->getPath();
1195 file_put_contents( $tmpNameA, $fileAContents );
1196 $tmpNameB = TempFSFile
::factory( "unittests_", 'txt' )->getPath();
1197 file_put_contents( $tmpNameB, $fileBContents );
1198 $tmpNameC = TempFSFile
::factory( "unittests_", 'txt' )->getPath();
1199 file_put_contents( $tmpNameC, $fileCContents );
1201 $this->filesToPrune
[] = $tmpNameA; # avoid file leaking
1202 $this->filesToPrune
[] = $tmpNameB; # avoid file leaking
1203 $this->filesToPrune
[] = $tmpNameC; # avoid file leaking
1205 $fileA = "$base/unittest-cont1/a/b/fileA.txt";
1206 $fileB = "$base/unittest-cont1/a/b/fileB.txt";
1207 $fileC = "$base/unittest-cont1/a/b/fileC.txt";
1208 $fileD = "$base/unittest-cont1/a/b/fileD.txt";
1210 $this->prepare( array( 'dir' => dirname( $fileA ) ) );
1211 $this->backend
->create( array( 'dst' => $fileA, 'content' => $fileAContents ) );
1212 $this->prepare( array( 'dir' => dirname( $fileB ) ) );
1213 $this->prepare( array( 'dir' => dirname( $fileC ) ) );
1214 $this->prepare( array( 'dir' => dirname( $fileD ) ) );
1216 $status = $this->backend
->doOperations( array(
1217 array( 'op' => 'store', 'src' => $tmpNameA, 'dst' => $fileA, 'overwriteSame' => 1 ),
1218 array( 'op' => 'store', 'src' => $tmpNameB, 'dst' => $fileB, 'overwrite' => 1 ),
1219 array( 'op' => 'store', 'src' => $tmpNameC, 'dst' => $fileC, 'overwrite' => 1 ),
1220 array( 'op' => 'copy', 'src' => $fileA, 'dst' => $fileC, 'overwrite' => 1 ),
1221 // Now: A:<A>, B:<B>, C:<A>, D:<empty> (file:<orginal contents>)
1222 array( 'op' => 'copy', 'src' => $fileC, 'dst' => $fileA, 'overwriteSame' => 1 ),
1223 // Now: A:<A>, B:<B>, C:<A>, D:<empty>
1224 array( 'op' => 'move', 'src' => $fileC, 'dst' => $fileD, 'overwrite' => 1 ),
1225 // Now: A:<A>, B:<B>, C:<empty>, D:<A>
1226 array( 'op' => 'move', 'src' => $fileB, 'dst' => $fileC ),
1227 // Now: A:<A>, B:<empty>, C:<B>, D:<A>
1228 array( 'op' => 'move', 'src' => $fileD, 'dst' => $fileA, 'overwriteSame' => 1 ),
1229 // Now: A:<A>, B:<empty>, C:<B>, D:<empty>
1230 array( 'op' => 'move', 'src' => $fileC, 'dst' => $fileA, 'overwrite' => 1 ),
1231 // Now: A:<B>, B:<empty>, C:<empty>, D:<empty>
1232 array( 'op' => 'copy', 'src' => $fileA, 'dst' => $fileC ),
1233 // Now: A:<B>, B:<empty>, C:<B>, D:<empty>
1234 array( 'op' => 'move', 'src' => $fileA, 'dst' => $fileC, 'overwriteSame' => 1 ),
1235 // Now: A:<empty>, B:<empty>, C:<B>, D:<empty>
1236 array( 'op' => 'copy', 'src' => $fileC, 'dst' => $fileC, 'overwrite' => 1 ),
1238 array( 'op' => 'copy', 'src' => $fileC, 'dst' => $fileC, 'overwriteSame' => 1 ),
1240 array( 'op' => 'move', 'src' => $fileC, 'dst' => $fileC, 'overwrite' => 1 ),
1242 array( 'op' => 'move', 'src' => $fileC, 'dst' => $fileC, 'overwriteSame' => 1 ),
1244 array( 'op' => 'null' ),
1248 $this->assertGoodStatus( $status, "Operation batch succeeded" );
1249 $this->assertEquals( true, $status->isOK(), "Operation batch succeeded" );
1250 $this->assertEquals( 16, count( $status->success
),
1251 "Operation batch has correct success array" );
1253 $this->assertEquals( false, $this->backend
->fileExists( array( 'src' => $fileA ) ),
1254 "File does not exist at $fileA" );
1255 $this->assertEquals( false, $this->backend
->fileExists( array( 'src' => $fileB ) ),
1256 "File does not exist at $fileB" );
1257 $this->assertEquals( false, $this->backend
->fileExists( array( 'src' => $fileD ) ),
1258 "File does not exist at $fileD" );
1260 $this->assertEquals( true, $this->backend
->fileExists( array( 'src' => $fileC ) ),
1261 "File exists at $fileC" );
1262 $this->assertEquals( $fileBContents,
1263 $this->backend
->getFileContents( array( 'src' => $fileC ) ),
1264 "Correct file contents of $fileC" );
1265 $this->assertEquals( strlen( $fileBContents ),
1266 $this->backend
->getFileSize( array( 'src' => $fileC ) ),
1267 "Correct file size of $fileC" );
1268 $this->assertEquals( wfBaseConvert( sha1( $fileBContents ), 16, 36, 31 ),
1269 $this->backend
->getFileSha1Base36( array( 'src' => $fileC ) ),
1270 "Correct file SHA-1 of $fileC" );
1273 function doTestDoOperationsFailing() {
1274 $base = $this->baseStorePath();
1276 $fileA = "$base/unittest-cont2/a/b/fileA.txt";
1277 $fileAContents = '3tqtmoeatmn4wg4qe-mg3qt3 tq';
1278 $fileB = "$base/unittest-cont2/a/b/fileB.txt";
1279 $fileBContents = 'g-jmq3gpqgt3qtg q3GT ';
1280 $fileC = "$base/unittest-cont2/a/b/fileC.txt";
1281 $fileCContents = 'eigna[ogmewt 3qt g3qg flew[ag';
1282 $fileD = "$base/unittest-cont2/a/b/fileD.txt";
1284 $this->prepare( array( 'dir' => dirname( $fileA ) ) );
1285 $this->backend
->create( array( 'dst' => $fileA, 'content' => $fileAContents ) );
1286 $this->prepare( array( 'dir' => dirname( $fileB ) ) );
1287 $this->backend
->create( array( 'dst' => $fileB, 'content' => $fileBContents ) );
1288 $this->prepare( array( 'dir' => dirname( $fileC ) ) );
1289 $this->backend
->create( array( 'dst' => $fileC, 'content' => $fileCContents ) );
1291 $status = $this->backend
->doOperations( array(
1292 array( 'op' => 'copy', 'src' => $fileA, 'dst' => $fileC, 'overwrite' => 1 ),
1293 // Now: A:<A>, B:<B>, C:<A>, D:<empty> (file:<orginal contents>)
1294 array( 'op' => 'copy', 'src' => $fileC, 'dst' => $fileA, 'overwriteSame' => 1 ),
1295 // Now: A:<A>, B:<B>, C:<A>, D:<empty>
1296 array( 'op' => 'copy', 'src' => $fileB, 'dst' => $fileD, 'overwrite' => 1 ),
1297 // Now: A:<A>, B:<B>, C:<A>, D:<B>
1298 array( 'op' => 'move', 'src' => $fileC, 'dst' => $fileD ),
1299 // Now: A:<A>, B:<B>, C:<A>, D:<empty> (failed)
1300 array( 'op' => 'move', 'src' => $fileB, 'dst' => $fileC, 'overwriteSame' => 1 ),
1301 // Now: A:<A>, B:<B>, C:<A>, D:<empty> (failed)
1302 array( 'op' => 'move', 'src' => $fileB, 'dst' => $fileA, 'overwrite' => 1 ),
1303 // Now: A:<B>, B:<empty>, C:<A>, D:<empty>
1304 array( 'op' => 'delete', 'src' => $fileD ),
1305 // Now: A:<B>, B:<empty>, C:<A>, D:<empty>
1306 array( 'op' => 'null' ),
1308 ), array( 'force' => 1 ) );
1310 $this->assertNotEquals( array(), $status->errors
, "Operation had warnings" );
1311 $this->assertEquals( true, $status->isOK(), "Operation batch succeeded" );
1312 $this->assertEquals( 8, count( $status->success
),
1313 "Operation batch has correct success array" );
1315 $this->assertEquals( false, $this->backend
->fileExists( array( 'src' => $fileB ) ),
1316 "File does not exist at $fileB" );
1317 $this->assertEquals( false, $this->backend
->fileExists( array( 'src' => $fileD ) ),
1318 "File does not exist at $fileD" );
1320 $this->assertEquals( true, $this->backend
->fileExists( array( 'src' => $fileA ) ),
1321 "File does not exist at $fileA" );
1322 $this->assertEquals( true, $this->backend
->fileExists( array( 'src' => $fileC ) ),
1323 "File exists at $fileC" );
1324 $this->assertEquals( $fileBContents,
1325 $this->backend
->getFileContents( array( 'src' => $fileA ) ),
1326 "Correct file contents of $fileA" );
1327 $this->assertEquals( strlen( $fileBContents ),
1328 $this->backend
->getFileSize( array( 'src' => $fileA ) ),
1329 "Correct file size of $fileA" );
1330 $this->assertEquals( wfBaseConvert( sha1( $fileBContents ), 16, 36, 31 ),
1331 $this->backend
->getFileSha1Base36( array( 'src' => $fileA ) ),
1332 "Correct file SHA-1 of $fileA" );
1335 public function testGetFileList() {
1336 $this->backend
= $this->singleBackend
;
1337 $this->tearDownFiles();
1338 $this->doTestGetFileList();
1339 $this->tearDownFiles();
1341 $this->backend
= $this->multiBackend
;
1342 $this->tearDownFiles();
1343 $this->doTestGetFileList();
1344 $this->tearDownFiles();
1347 private function doTestGetFileList() {
1348 $backendName = $this->backendClass();
1350 $base = $this->baseStorePath();
1352 "$base/unittest-cont1/test1.txt",
1353 "$base/unittest-cont1/test2.txt",
1354 "$base/unittest-cont1/test3.txt",
1355 "$base/unittest-cont1/subdir1/test1.txt",
1356 "$base/unittest-cont1/subdir1/test2.txt",
1357 "$base/unittest-cont1/subdir2/test3.txt",
1358 "$base/unittest-cont1/subdir2/test4.txt",
1359 "$base/unittest-cont1/subdir2/subdir/test1.txt",
1360 "$base/unittest-cont1/subdir2/subdir/test2.txt",
1361 "$base/unittest-cont1/subdir2/subdir/test3.txt",
1362 "$base/unittest-cont1/subdir2/subdir/test4.txt",
1363 "$base/unittest-cont1/subdir2/subdir/test5.txt",
1364 "$base/unittest-cont1/subdir2/subdir/sub/test0.txt",
1365 "$base/unittest-cont1/subdir2/subdir/sub/120-px-file.txt",
1370 foreach ( $files as $file ) {
1371 $this->prepare( array( 'dir' => dirname( $file ) ) );
1372 $ops[] = array( 'op' => 'create', 'content' => 'xxy', 'dst' => $file );
1374 $status = $this->backend
->doOperations( $ops );
1375 $this->assertGoodStatus( $status,
1376 "Creation of files succeeded ($backendName)." );
1377 $this->assertEquals( true, $status->isOK(),
1378 "Creation of files succeeded with OK status ($backendName)." );
1385 "subdir1/test1.txt",
1386 "subdir1/test2.txt",
1387 "subdir2/test3.txt",
1388 "subdir2/test4.txt",
1389 "subdir2/subdir/test1.txt",
1390 "subdir2/subdir/test2.txt",
1391 "subdir2/subdir/test3.txt",
1392 "subdir2/subdir/test4.txt",
1393 "subdir2/subdir/test5.txt",
1394 "subdir2/subdir/sub/test0.txt",
1395 "subdir2/subdir/sub/120-px-file.txt",
1399 // Actual listing (no trailing slash)
1401 $iter = $this->backend
->getFileList( array( 'dir' => "$base/unittest-cont1" ) );
1402 foreach ( $iter as $file ) {
1407 $this->assertEquals( $expected, $list, "Correct file listing ($backendName)." );
1409 // Actual listing (with trailing slash)
1411 $iter = $this->backend
->getFileList( array( 'dir' => "$base/unittest-cont1/" ) );
1412 foreach ( $iter as $file ) {
1417 $this->assertEquals( $expected, $list, "Correct file listing ($backendName)." );
1427 "sub/120-px-file.txt",
1431 // Actual listing (no trailing slash)
1433 $iter = $this->backend
->getFileList( array( 'dir' => "$base/unittest-cont1/subdir2/subdir" ) );
1434 foreach ( $iter as $file ) {
1439 $this->assertEquals( $expected, $list, "Correct file listing ($backendName)." );
1441 // Actual listing (with trailing slash)
1443 $iter = $this->backend
->getFileList( array( 'dir' => "$base/unittest-cont1/subdir2/subdir/" ) );
1444 foreach ( $iter as $file ) {
1449 $this->assertEquals( $expected, $list, "Correct file listing ($backendName)." );
1451 // Actual listing (using iterator second time)
1453 foreach ( $iter as $file ) {
1458 $this->assertEquals( $expected, $list, "Correct file listing ($backendName), second iteration." );
1460 // Expected listing (top files only)
1470 // Actual listing (top files only)
1472 $iter = $this->backend
->getTopFileList( array( 'dir' => "$base/unittest-cont1/subdir2/subdir" ) );
1473 foreach ( $iter as $file ) {
1478 $this->assertEquals( $expected, $list, "Correct top file listing ($backendName)." );
1480 foreach ( $files as $file ) { // clean up
1481 $this->backend
->doOperation( array( 'op' => 'delete', 'src' => $file ) );
1484 $iter = $this->backend
->getFileList( array( 'dir' => "$base/unittest-cont1/not/exists" ) );
1485 foreach ( $iter as $iter ) {} // no errors
1488 public function testGetDirectoryList() {
1489 $this->backend
= $this->singleBackend
;
1490 $this->tearDownFiles();
1491 $this->doTestGetDirectoryList();
1492 $this->tearDownFiles();
1494 $this->backend
= $this->multiBackend
;
1495 $this->tearDownFiles();
1496 $this->doTestGetDirectoryList();
1497 $this->tearDownFiles();
1500 private function doTestGetDirectoryList() {
1501 $backendName = $this->backendClass();
1503 $base = $this->baseStorePath();
1505 "$base/unittest-cont1/test1.txt",
1506 "$base/unittest-cont1/test2.txt",
1507 "$base/unittest-cont1/test3.txt",
1508 "$base/unittest-cont1/subdir1/test1.txt",
1509 "$base/unittest-cont1/subdir1/test2.txt",
1510 "$base/unittest-cont1/subdir2/test3.txt",
1511 "$base/unittest-cont1/subdir2/test4.txt",
1512 "$base/unittest-cont1/subdir2/subdir/test1.txt",
1513 "$base/unittest-cont1/subdir3/subdir/test2.txt",
1514 "$base/unittest-cont1/subdir4/subdir/test3.txt",
1515 "$base/unittest-cont1/subdir4/subdir/test4.txt",
1516 "$base/unittest-cont1/subdir4/subdir/test5.txt",
1517 "$base/unittest-cont1/subdir4/subdir/sub/test0.txt",
1518 "$base/unittest-cont1/subdir4/subdir/sub/120-px-file.txt",
1523 foreach ( $files as $file ) {
1524 $this->prepare( array( 'dir' => dirname( $file ) ) );
1525 $ops[] = array( 'op' => 'create', 'content' => 'xxy', 'dst' => $file );
1527 $status = $this->backend
->doOperations( $ops );
1528 $this->assertGoodStatus( $status,
1529 "Creation of files succeeded ($backendName)." );
1530 $this->assertEquals( true, $status->isOK(),
1531 "Creation of files succeeded with OK status ($backendName)." );
1542 $this->assertEquals( true,
1543 $this->backend
->directoryExists( array( 'dir' => "$base/unittest-cont1/subdir1" ) ),
1544 "Directory exists in ($backendName)." );
1545 $this->assertEquals( true,
1546 $this->backend
->directoryExists( array( 'dir' => "$base/unittest-cont1/subdir2/subdir" ) ),
1547 "Directory exists in ($backendName)." );
1548 $this->assertEquals( false,
1549 $this->backend
->directoryExists( array( 'dir' => "$base/unittest-cont1/subdir2/test1.txt" ) ),
1550 "Directory does not exists in ($backendName)." );
1552 // Actual listing (no trailing slash)
1554 $iter = $this->backend
->getTopDirectoryList( array( 'dir' => "$base/unittest-cont1" ) );
1555 foreach ( $iter as $file ) {
1560 $this->assertEquals( $expected, $list, "Correct top dir listing ($backendName)." );
1562 // Actual listing (with trailing slash)
1564 $iter = $this->backend
->getTopDirectoryList( array( 'dir' => "$base/unittest-cont1/" ) );
1565 foreach ( $iter as $file ) {
1570 $this->assertEquals( $expected, $list, "Correct top dir listing ($backendName)." );
1578 // Actual listing (no trailing slash)
1580 $iter = $this->backend
->getTopDirectoryList( array( 'dir' => "$base/unittest-cont1/subdir2" ) );
1581 foreach ( $iter as $file ) {
1586 $this->assertEquals( $expected, $list, "Correct top dir listing ($backendName)." );
1588 // Actual listing (with trailing slash)
1590 $iter = $this->backend
->getTopDirectoryList( array( 'dir' => "$base/unittest-cont1/subdir2/" ) );
1591 foreach ( $iter as $file ) {
1596 $this->assertEquals( $expected, $list, "Correct top dir listing ($backendName)." );
1598 // Actual listing (using iterator second time)
1600 foreach ( $iter as $file ) {
1605 $this->assertEquals( $expected, $list, "Correct top dir listing ($backendName), second iteration." );
1607 // Expected listing (recursive)
1616 "subdir4/subdir/sub",
1620 // Actual listing (recursive)
1622 $iter = $this->backend
->getDirectoryList( array( 'dir' => "$base/unittest-cont1/" ) );
1623 foreach ( $iter as $file ) {
1628 $this->assertEquals( $expected, $list, "Correct dir listing ($backendName)." );
1630 // Expected listing (recursive)
1637 // Actual listing (recursive)
1639 $iter = $this->backend
->getDirectoryList( array( 'dir' => "$base/unittest-cont1/subdir4" ) );
1640 foreach ( $iter as $file ) {
1645 $this->assertEquals( $expected, $list, "Correct dir listing ($backendName)." );
1647 // Actual listing (recursive, second time)
1649 foreach ( $iter as $file ) {
1654 $this->assertEquals( $expected, $list, "Correct dir listing ($backendName)." );
1656 foreach ( $files as $file ) { // clean up
1657 $this->backend
->doOperation( array( 'op' => 'delete', 'src' => $file ) );
1660 $iter = $this->backend
->getDirectoryList( array( 'dir' => "$base/unittest-cont1/not/exists" ) );
1661 foreach ( $iter as $iter ) {} // no errors
1664 public function testLockCalls() {
1665 $this->backend
= $this->singleBackend
;
1666 $this->doTestLockCalls();
1669 private function doTestLockCalls() {
1670 $backendName = $this->backendClass();
1672 for ( $i=0; $i<50; $i++
) {
1678 "subdir1", // duplicate
1679 "subdir1/test1.txt",
1680 "subdir1/test2.txt",
1682 "subdir2", // duplicate
1683 "subdir2/test3.txt",
1684 "subdir2/test4.txt",
1686 "subdir2/subdir/test1.txt",
1687 "subdir2/subdir/test2.txt",
1688 "subdir2/subdir/test3.txt",
1689 "subdir2/subdir/test4.txt",
1690 "subdir2/subdir/test5.txt",
1691 "subdir2/subdir/sub",
1692 "subdir2/subdir/sub/test0.txt",
1693 "subdir2/subdir/sub/120-px-file.txt",
1696 $status = $this->backend
->lockFiles( $paths, LockManager
::LOCK_EX
);
1697 $this->assertEquals( array(), $status->errors
,
1698 "Locking of files succeeded ($backendName)." );
1699 $this->assertEquals( true, $status->isOK(),
1700 "Locking of files succeeded with OK status ($backendName)." );
1702 $status = $this->backend
->lockFiles( $paths, LockManager
::LOCK_SH
);
1703 $this->assertEquals( array(), $status->errors
,
1704 "Locking of files succeeded ($backendName)." );
1705 $this->assertEquals( true, $status->isOK(),
1706 "Locking of files succeeded with OK status ($backendName)." );
1708 $status = $this->backend
->unlockFiles( $paths, LockManager
::LOCK_SH
);
1709 $this->assertEquals( array(), $status->errors
,
1710 "Locking of files succeeded ($backendName)." );
1711 $this->assertEquals( true, $status->isOK(),
1712 "Locking of files succeeded with OK status ($backendName)." );
1714 $status = $this->backend
->unlockFiles( $paths, LockManager
::LOCK_EX
);
1715 $this->assertEquals( array(), $status->errors
,
1716 "Locking of files succeeded ($backendName)." );
1717 $this->assertEquals( true, $status->isOK(),
1718 "Locking of files succeeded with OK status ($backendName)." );
1722 // test helper wrapper for backend prepare() function
1723 private function prepare( array $params ) {
1724 $this->dirsToPrune
[] = $params['dir'];
1725 return $this->backend
->prepare( $params );
1728 function tearDownFiles() {
1729 foreach ( $this->filesToPrune
as $file ) {
1732 $containers = array( 'unittest-cont1', 'unittest-cont2', 'unittest-cont3' );
1733 foreach ( $containers as $container ) {
1734 $this->deleteFiles( $container );
1736 foreach ( $this->dirsToPrune
as $dir ) {
1737 $this->recursiveClean( $dir );
1739 $this->filesToPrune
= $this->dirsToPrune
= array();
1742 private function deleteFiles( $container ) {
1743 $base = $this->baseStorePath();
1744 $iter = $this->backend
->getFileList( array( 'dir' => "$base/$container" ) );
1746 foreach ( $iter as $file ) {
1747 $this->backend
->delete( array( 'src' => "$base/$container/$file" ),
1748 array( 'force' => 1, 'nonLocking' => 1 ) );
1753 private function recursiveClean( $dir ) {
1754 $this->backend
->clean( array( 'dir' => $dir, 'recursive' => 1 ) );
1757 function assertGoodStatus( $status, $msg ) {
1758 $this->assertEquals( print_r( array(), 1 ), print_r( $status->errors
, 1 ), $msg );
1761 function tearDown() {