* Added 'basePath' config param to FSFileBackend and tweaked it to behave more simila...
[lhc/web/wiklou.git] / tests / phpunit / includes / filerepo / FileBackendTest.php
1 <?php
2
3 /**
4 * @group FileRepo
5 * @TODO: fix empty dir leakage
6 */
7 class FileBackendTest extends MediaWikiTestCase {
8 private $backend, $multiBackend;
9 private $filesToPrune, $pathsToPrune;
10
11 function setUp() {
12 parent::setUp();
13 $tmpDir = wfTempDir() . '/' . time() . '-' . mt_rand();
14 $this->singleBackend = new FSFileBackend( array(
15 'name' => 'localtesting',
16 'lockManager' => 'fsLockManager',
17 'containerPaths' => array(
18 'cont1' => "$tmpDir/localtesting/cont1",
19 'cont2' => "$tmpDir/localtesting/cont2" )
20 ) );
21 $this->multiBackend = new FileBackendMultiWrite( array(
22 'name' => 'localtesting',
23 'lockManager' => 'fsLockManager',
24 'backends' => array(
25 array(
26 'name' => 'localmutlitesting1',
27 'class' => 'FSFileBackend',
28 'lockManager' => 'nullLockManager',
29 'containerPaths' => array(
30 'cont1' => "$tmpDir/localtestingmulti1/cont1",
31 'cont2' => "$tmpDir/localtestingmulti1/cont2" ),
32 'isMultiMaster' => false
33 ),
34 array(
35 'name' => 'localmutlitesting2',
36 'class' => 'FSFileBackend',
37 'lockManager' => 'nullLockManager',
38 'containerPaths' => array(
39 'cont1' => "$tmpDir/localtestingmulti2/cont1",
40 'cont2' => "$tmpDir/localtestingmulti2/cont2" ),
41 'isMultiMaster' => true
42 )
43 )
44 ) );
45 $this->filesToPrune = $this->pathsToPrune = array();
46 }
47
48 private function baseStorePath() {
49 return 'mwstore://localtesting';
50 }
51
52 private function backendClass() {
53 return get_class( $this->backend );
54 }
55
56 /**
57 * @dataProvider provider_testStore
58 */
59 public function testStore( $op, $source, $dest ) {
60 $this->filesToPrune[] = $source;
61 $this->pathsToPrune[] = $dest;
62
63 $this->backend = $this->singleBackend;
64 $this->doTestStore( $op, $source, $dest );
65 $this->tearDownFiles();
66
67 $this->backend = $this->multiBackend;
68 $this->doTestStore( $op, $source, $dest );
69 $this->tearDownFiles();
70 }
71
72 function doTestStore( $op, $source, $dest ) {
73 $backendName = $this->backendClass();
74
75 file_put_contents( $source, "Unit test file" );
76 $status = $this->backend->doOperation( $op );
77
78 $this->assertEquals( array(), $status->errors,
79 "Store from $source to $dest succeeded without warnings ($backendName)." );
80 $this->assertEquals( true, $status->isOK(),
81 "Store from $source to $dest succeeded ($backendName)." );
82 $this->assertEquals( array( 0 => true ), $status->success,
83 "Store from $source to $dest has proper 'success' field in Status ($backendName)." );
84 $this->assertEquals( true, file_exists( $source ),
85 "Source file $source still exists ($backendName)." );
86 $this->assertEquals( true, $this->backend->fileExists( array( 'src' => $dest ) ),
87 "Destination file $dest exists ($backendName)." );
88
89 $this->assertEquals( filesize( $source ),
90 $this->backend->getFileSize( array( 'src' => $dest ) ),
91 "Destination file $dest has correct size ($backendName)." );
92
93 $props1 = FSFile::getPropsFromPath( $source );
94 $props2 = $this->backend->getFileProps( array( 'src' => $dest ) );
95 $this->assertEquals( $props1, $props2,
96 "Source and destination have the same props ($backendName)." );
97 }
98
99 public function provider_testStore() {
100 $cases = array();
101
102 $tmpName = TempFSFile::factory( "unittests_", 'txt' )->getPath();
103 $toPath = $this->baseStorePath() . '/cont1/fun/obj1.txt';
104 $op = array( 'op' => 'store', 'src' => $tmpName, 'dst' => $toPath );
105 $cases[] = array(
106 $op, // operation
107 $tmpName, // source
108 $toPath, // dest
109 );
110
111 $op['overwriteDest'] = true;
112 $cases[] = array(
113 $op, // operation
114 $tmpName, // source
115 $toPath, // dest
116 );
117
118 return $cases;
119 }
120
121 /**
122 * @dataProvider provider_testCopy
123 */
124 public function testCopy( $op, $source, $dest ) {
125 $this->pathsToPrune[] = $source;
126 $this->pathsToPrune[] = $dest;
127
128 $this->backend = $this->singleBackend;
129 $this->doTestCopy( $op, $source, $dest );
130 $this->tearDownFiles();
131
132 $this->backend = $this->multiBackend;
133 $this->doTestCopy( $op, $source, $dest );
134 $this->tearDownFiles();
135 }
136
137 function doTestCopy( $op, $source, $dest ) {
138 $backendName = $this->backendClass();
139
140 $status = $this->backend->doOperation(
141 array( 'op' => 'create', 'content' => 'blahblah', 'dst' => $source ) );
142 $this->assertEquals( true, $status->isOK(),
143 "Creation of file at $source succeeded ($backendName)." );
144
145 $status = $this->backend->doOperation( $op );
146 $this->assertEquals( array(), $status->errors,
147 "Copy from $source to $dest succeeded without warnings ($backendName)." );
148 $this->assertEquals( true, $status->isOK(),
149 "Copy from $source to $dest succeeded ($backendName)." );
150 $this->assertEquals( array( 0 => true ), $status->success,
151 "Copy from $source to $dest has proper 'success' field in Status ($backendName)." );
152 $this->assertEquals( true, $this->backend->fileExists( array( 'src' => $source ) ),
153 "Source file $source still exists ($backendName)." );
154 $this->assertEquals( true, $this->backend->fileExists( array( 'src' => $dest ) ),
155 "Destination file $dest exists after copy ($backendName)." );
156
157 $this->assertEquals(
158 $this->backend->getFileSize( array( 'src' => $source ) ),
159 $this->backend->getFileSize( array( 'src' => $dest ) ),
160 "Destination file $dest has correct size ($backendName)." );
161
162 $props1 = $this->backend->getFileProps( array( 'src' => $source ) );
163 $props2 = $this->backend->getFileProps( array( 'src' => $dest ) );
164 $this->assertEquals( $props1, $props2,
165 "Source and destination have the same props ($backendName)." );
166 }
167
168 public function provider_testCopy() {
169 $cases = array();
170
171 $source = $this->baseStorePath() . '/cont1/file.txt';
172 $dest = $this->baseStorePath() . '/cont2/fileMoved.txt';
173
174 $op = array( 'op' => 'copy', 'src' => $source, 'dst' => $dest );
175 $cases[] = array(
176 $op, // operation
177 $source, // source
178 $dest, // dest
179 );
180
181 $op['overwriteDest'] = true;
182 $cases[] = array(
183 $op, // operation
184 $source, // source
185 $dest, // dest
186 );
187
188 return $cases;
189 }
190
191 /**
192 * @dataProvider provider_testMove
193 */
194 public function testMove( $op, $source, $dest ) {
195 $this->pathsToPrune[] = $source;
196 $this->pathsToPrune[] = $dest;
197
198 $this->backend = $this->singleBackend;
199 $this->doTestMove( $op, $source, $dest );
200 $this->tearDownFiles();
201
202 $this->backend = $this->multiBackend;
203 $this->doTestMove( $op, $source, $dest );
204 $this->tearDownFiles();
205 }
206
207 public function doTestMove( $op, $source, $dest ) {
208 $backendName = $this->backendClass();
209
210 $status = $this->backend->doOperation(
211 array( 'op' => 'create', 'content' => 'blahblah', 'dst' => $source ) );
212 $this->assertEquals( true, $status->isOK(),
213 "Creation of file at $source succeeded ($backendName)." );
214
215 $status = $this->backend->doOperation( $op );
216 $this->assertEquals( array(), $status->errors,
217 "Move from $source to $dest succeeded without warnings ($backendName)." );
218 $this->assertEquals( true, $status->isOK(),
219 "Move from $source to $dest succeeded ($backendName)." );
220 $this->assertEquals( array( 0 => true ), $status->success,
221 "Move from $source to $dest has proper 'success' field in Status ($backendName)." );
222 $this->assertEquals( false, $this->backend->fileExists( array( 'src' => $source ) ),
223 "Source file $source does not still exists ($backendName)." );
224 $this->assertEquals( true, $this->backend->fileExists( array( 'src' => $dest ) ),
225 "Destination file $dest exists after move ($backendName)." );
226
227 $this->assertNotEquals(
228 $this->backend->getFileSize( array( 'src' => $source ) ),
229 $this->backend->getFileSize( array( 'src' => $dest ) ),
230 "Destination file $dest has correct size ($backendName)." );
231
232 $props1 = $this->backend->getFileProps( array( 'src' => $source ) );
233 $props2 = $this->backend->getFileProps( array( 'src' => $dest ) );
234 $this->assertEquals( false, $props1['fileExists'],
235 "Source file does not exist accourding to props ($backendName)." );
236 $this->assertEquals( true, $props2['fileExists'],
237 "Destination file exists accourding to props ($backendName)." );
238 }
239
240 public function provider_testMove() {
241 $cases = array();
242
243 $source = $this->baseStorePath() . '/cont1/file.txt';
244 $dest = $this->baseStorePath() . '/cont2/fileMoved.txt';
245
246 $op = array( 'op' => 'move', 'src' => $source, 'dst' => $dest );
247 $cases[] = array(
248 $op, // operation
249 $source, // source
250 $dest, // dest
251 );
252
253 $op['overwriteDest'] = true;
254 $cases[] = array(
255 $op, // operation
256 $source, // source
257 $dest, // dest
258 );
259
260 return $cases;
261 }
262
263 /**
264 * @dataProvider provider_testDelete
265 */
266 public function testDelete( $op, $source, $withSource, $okStatus ) {
267 $this->pathsToPrune[] = $source;
268
269 $this->backend = $this->singleBackend;
270 $this->doTestDelete( $op, $source, $withSource, $okStatus );
271 $this->tearDownFiles();
272
273 $this->backend = $this->multiBackend;
274 $this->doTestDelete( $op, $source, $withSource, $okStatus );
275 $this->tearDownFiles();
276 }
277
278 public function doTestDelete( $op, $source, $withSource, $okStatus ) {
279 $backendName = $this->backendClass();
280
281 if ( $withSource ) {
282 $status = $this->backend->doOperation(
283 array( 'op' => 'create', 'content' => 'blahblah', 'dst' => $source ) );
284 $this->assertEquals( true, $status->isOK(),
285 "Creation of file at $source succeeded ($backendName)." );
286 }
287
288 $status = $this->backend->doOperation( $op );
289 if ( $okStatus ) {
290 $this->assertEquals( array(), $status->errors,
291 "Deletion of file at $source succeeded without warnings ($backendName)." );
292 $this->assertEquals( true, $status->isOK(),
293 "Deletion of file at $source succeeded ($backendName)." );
294 $this->assertEquals( array( 0 => true ), $status->success,
295 "Deletion of file at $source has proper 'success' field in Status ($backendName)." );
296 } else {
297 $this->assertEquals( false, $status->isOK(),
298 "Deletion of file at $source failed ($backendName)." );
299 }
300
301 $this->assertEquals( false, $this->backend->fileExists( array( 'src' => $source ) ),
302 "Source file $source does not exist after move ($backendName)." );
303
304 $this->assertFalse(
305 $this->backend->getFileSize( array( 'src' => $source ) ),
306 "Source file $source has correct size (false) ($backendName)." );
307
308 $props1 = $this->backend->getFileProps( array( 'src' => $source ) );
309 $this->assertFalse( $props1['fileExists'],
310 "Source file $source does not exist according to props ($backendName)." );
311 }
312
313 public function provider_testDelete() {
314 $cases = array();
315
316 $source = $this->baseStorePath() . '/cont1/myfacefile.txt';
317
318 $op = array( 'op' => 'delete', 'src' => $source );
319 $cases[] = array(
320 $op, // operation
321 $source, // source
322 true, // with source
323 true // succeeds
324 );
325
326 $cases[] = array(
327 $op, // operation
328 $source, // source
329 false, // without source
330 false // fails
331 );
332
333 $op['ignoreMissingSource'] = true;
334 $cases[] = array(
335 $op, // operation
336 $source, // source
337 false, // without source
338 true // succeeds
339 );
340
341 return $cases;
342 }
343
344 /**
345 * @dataProvider provider_testCreate
346 */
347 public function testCreate( $op, $dest, $alreadyExists, $okStatus, $newSize ) {
348 $this->pathsToPrune[] = $dest;
349
350 $this->backend = $this->singleBackend;
351 $this->doTestCreate( $op, $dest, $alreadyExists, $okStatus, $newSize );
352 $this->tearDownFiles();
353
354 $this->backend = $this->multiBackend;
355 $this->doTestCreate( $op, $dest, $alreadyExists, $okStatus, $newSize );
356 $this->tearDownFiles();
357 }
358
359 public function doTestCreate( $op, $dest, $alreadyExists, $okStatus, $newSize ) {
360 $backendName = $this->backendClass();
361
362 $oldText = 'blah...blah...waahwaah';
363 if ( $alreadyExists ) {
364 $status = $this->backend->doOperation(
365 array( 'op' => 'create', 'content' => $oldText, 'dst' => $dest ) );
366 $this->assertEquals( true, $status->isOK(),
367 "Creation of file at $dest succeeded ($backendName)." );
368 }
369
370 $status = $this->backend->doOperation( $op );
371 if ( $okStatus ) {
372 $this->assertEquals( array(), $status->errors,
373 "Creation of file at $dest succeeded without warnings ($backendName)." );
374 $this->assertEquals( true, $status->isOK(),
375 "Creation of file at $dest succeeded ($backendName)." );
376 $this->assertEquals( array( 0 => true ), $status->success,
377 "Creation of file at $dest has proper 'success' field in Status ($backendName)." );
378 } else {
379 $this->assertEquals( false, $status->isOK(),
380 "Creation of file at $dest failed ($backendName)." );
381 }
382
383 $this->assertEquals( true, $this->backend->fileExists( array( 'src' => $dest ) ),
384 "Destination file $dest exists after creation ($backendName)." );
385
386 $props1 = $this->backend->getFileProps( array( 'src' => $dest ) );
387 $this->assertEquals( true, $props1['fileExists'],
388 "Destination file $dest exists according to props ($backendName)." );
389 if ( $okStatus ) { // file content is what we saved
390 $this->assertEquals( $newSize, $props1['size'],
391 "Destination file $dest has expected size according to props ($backendName)." );
392 $this->assertEquals( $newSize,
393 $this->backend->getFileSize( array( 'src' => $dest ) ),
394 "Destination file $dest has correct size ($backendName)." );
395 } else { // file content is some other previous text
396 $this->assertEquals( strlen( $oldText ), $props1['size'],
397 "Destination file $dest has original size according to props ($backendName)." );
398 $this->assertEquals( strlen( $oldText ),
399 $this->backend->getFileSize( array( 'src' => $dest ) ),
400 "Destination file $dest has original size according to props ($backendName)." );
401 }
402 }
403
404 /**
405 * @dataProvider provider_testCreate
406 */
407 public function provider_testCreate() {
408 $cases = array();
409
410 $source = $this->baseStorePath() . '/cont2/myspacefile.txt';
411
412 $dummyText = 'hey hey';
413 $op = array( 'op' => 'create', 'content' => $dummyText, 'dst' => $source );
414 $cases[] = array(
415 $op, // operation
416 $source, // source
417 false, // no dest already exists
418 true, // succeeds
419 strlen( $dummyText )
420 );
421
422 $cases[] = array(
423 $op, // operation
424 $source, // source
425 true, // dest already exists
426 false, // fails
427 strlen( $dummyText )
428 );
429
430 $op['overwriteDest'] = true;
431 $cases[] = array(
432 $op, // operation
433 $source, // source
434 true, // dest already exists
435 true, // succeeds
436 strlen( $dummyText )
437 );
438
439 return $cases;
440 }
441
442 /**
443 * @dataProvider provider_testConcatenate
444 */
445 public function testConcatenate( $op, $srcs, $srcsContent, $alreadyExists, $okStatus ) {
446 $this->pathsToPrune = array_merge( $this->pathsToPrune, $srcs );
447 $this->filesToPrune[] = $op['dst'];
448
449 $this->backend = $this->singleBackend;
450 $this->doTestConcatenate( $op, $srcs, $srcsContent, $alreadyExists, $okStatus );
451 $this->tearDownFiles();
452
453 $this->backend = $this->multiBackend;
454 $this->doTestConcatenate( $op, $srcs, $srcsContent, $alreadyExists, $okStatus );
455 $this->tearDownFiles();
456 }
457
458 public function doTestConcatenate( $params, $srcs, $srcsContent, $alreadyExists, $okStatus ) {
459 $backendName = $this->backendClass();
460
461 $expContent = '';
462 // Create sources
463 $ops = array();
464 foreach ( $srcs as $i => $source ) {
465 $ops[] = array(
466 'op' => 'create', // operation
467 'dst' => $source, // source
468 'content' => $srcsContent[$i]
469 );
470 $expContent .= $srcsContent[$i];
471 }
472 $status = $this->backend->doOperations( $ops );
473
474 $this->assertEquals( true, $status->isOK(),
475 "Creation of source files succeeded ($backendName)." );
476
477 $dest = $params['dst'];
478 if ( $alreadyExists ) {
479 $ok = file_put_contents( $dest, 'blah...blah...waahwaah' ) !== false;
480 $this->assertEquals( true, $ok,
481 "Creation of file at $dest succeeded ($backendName)." );
482 } else {
483 $ok = file_put_contents( $dest, '' ) !== false;
484 $this->assertEquals( true, $ok,
485 "Creation of 0-byte file at $dest succeeded ($backendName)." );
486 }
487
488 // Combine the files into one
489 $status = $this->backend->concatenate( $params );
490 if ( $okStatus ) {
491 $this->assertEquals( array(), $status->errors,
492 "Creation of concat file at $dest succeeded without warnings ($backendName)." );
493 $this->assertEquals( true, $status->isOK(),
494 "Creation of concat file at $dest succeeded ($backendName)." );
495 } else {
496 $this->assertEquals( false, $status->isOK(),
497 "Creation of concat file at $dest failed ($backendName)." );
498 }
499
500 if ( $okStatus ) {
501 $this->assertEquals( true, is_file( $dest ),
502 "Dest concat file $dest exists after creation ($backendName)." );
503 } else {
504 $this->assertEquals( true, is_file( $dest ),
505 "Dest concat file $dest exists after failed creation ($backendName)." );
506 }
507
508 $contents = file_get_contents( $dest );
509 $this->assertNotEquals( false, $contents, "File at $dest exists ($backendName)." );
510
511 if ( $okStatus ) {
512 $this->assertEquals( $expContent, $contents,
513 "Concat file at $dest has correct contents ($backendName)." );
514 } else {
515 $this->assertNotEquals( $expContent, $contents,
516 "Concat file at $dest has correct contents ($backendName)." );
517 }
518 }
519
520 function provider_testConcatenate() {
521 $cases = array();
522
523 $rand = mt_rand( 0, 2000000000 ) . time();
524 $dest = wfTempDir() . "/randomfile!$rand.txt";
525 $srcs = array(
526 $this->baseStorePath() . '/cont1/file1.txt',
527 $this->baseStorePath() . '/cont1/file2.txt',
528 $this->baseStorePath() . '/cont1/file3.txt',
529 $this->baseStorePath() . '/cont1/file4.txt',
530 $this->baseStorePath() . '/cont1/file5.txt',
531 $this->baseStorePath() . '/cont1/file6.txt',
532 $this->baseStorePath() . '/cont1/file7.txt',
533 $this->baseStorePath() . '/cont1/file8.txt',
534 $this->baseStorePath() . '/cont1/file9.txt',
535 $this->baseStorePath() . '/cont1/file10.txt'
536 );
537 $content = array(
538 'egfage',
539 'ageageag',
540 'rhokohlr',
541 'shgmslkg',
542 'kenga',
543 'owagmal',
544 'kgmae',
545 'g eak;g',
546 'lkaem;a',
547 'legma'
548 );
549 $params = array( 'srcs' => $srcs, 'dst' => $dest );
550
551 $cases[] = array(
552 $params, // operation
553 $srcs, // sources
554 $content, // content for each source
555 false, // no dest already exists
556 true, // succeeds
557 );
558
559 $cases[] = array(
560 $params, // operation
561 $srcs, // sources
562 $content, // content for each source
563 true, // dest already exists
564 false, // succeeds
565 );
566
567 return $cases;
568 }
569
570 /**
571 * @dataProvider provider_testGetFileContents
572 */
573 public function testGetFileContents( $src, $content ) {
574 $this->pathsToPrune[] = $src;
575
576 $this->backend = $this->singleBackend;
577 $this->doTestGetFileContents( $src, $content );
578 $this->tearDownFiles();
579
580 $this->backend = $this->multiBackend;
581 $this->doTestGetFileContents( $src, $content );
582 $this->tearDownFiles();
583 }
584
585 /**
586 * @dataProvider provider_testGetFileContents
587 */
588 public function doTestGetFileContents( $src, $content ) {
589 $backendName = $this->backendClass();
590
591 $status = $this->backend->doOperation(
592 array( 'op' => 'create', 'content' => $content, 'dst' => $src ) );
593 $this->assertEquals( true, $status->isOK(),
594 "Creation of file at $src succeeded ($backendName)." );
595
596 $newContents = $this->backend->getFileContents( array( 'src' => $src ) );
597 $this->assertNotEquals( false, $newContents,
598 "Read of file at $src succeeded ($backendName)." );
599
600 $this->assertEquals( $content, $newContents,
601 "Contents read match data at $src ($backendName)." );
602 }
603
604 function provider_testGetFileContents() {
605 $cases = array();
606
607 $base = $this->baseStorePath();
608 $cases[] = array( "$base/cont1/b/z/some_file.txt", "some file contents" );
609 $cases[] = array( "$base/cont1/b/some-other_file.txt", "more file contents" );
610
611 return $cases;
612 }
613
614 /**
615 * @dataProvider provider_testGetLocalCopy
616 */
617 public function testGetLocalCopy( $src, $content ) {
618 $this->pathsToPrune[] = $src;
619
620 $this->backend = $this->singleBackend;
621 $this->doTestGetLocalCopy( $src, $content );
622 $this->tearDownFiles();
623
624 $this->backend = $this->multiBackend;
625 $this->doTestGetLocalCopy( $src, $content );
626 $this->tearDownFiles();
627 }
628
629 public function doTestGetLocalCopy( $src, $content ) {
630 $backendName = $this->backendClass();
631
632 $status = $this->backend->doOperation(
633 array( 'op' => 'create', 'content' => $content, 'dst' => $src ) );
634 $this->assertEquals( true, $status->isOK(),
635 "Creation of file at $src succeeded ($backendName)." );
636
637 $tmpFile = $this->backend->getLocalCopy( array( 'src' => $src ) );
638 $this->assertNotNull( $tmpFile,
639 "Creation of local copy of $src succeeded ($backendName)." );
640
641 $contents = file_get_contents( $tmpFile->getPath() );
642 $this->assertNotEquals( false, $contents, "Local copy of $src exists ($backendName)." );
643 }
644
645 function provider_testGetLocalCopy() {
646 $cases = array();
647
648 $base = $this->baseStorePath();
649 $cases[] = array( "$base/cont1/a/z/some_file.txt", "some file contents" );
650 $cases[] = array( "$base/cont1/a/some-other_file.txt", "more file contents" );
651
652 return $cases;
653 }
654
655 /**
656 * @dataProvider provider_testGetLocalReference
657 */
658 public function testGetLocalReference( $src, $content ) {
659 $this->pathsToPrune[] = $src;
660
661 $this->backend = $this->singleBackend;
662 $this->doTestGetLocalReference( $src, $content );
663 $this->tearDownFiles();
664
665 $this->backend = $this->multiBackend;
666 $this->doTestGetLocalReference( $src, $content );
667 $this->tearDownFiles();
668 }
669
670 public function doTestGetLocalReference( $src, $content ) {
671 $backendName = $this->backendClass();
672
673 $status = $this->backend->doOperation(
674 array( 'op' => 'create', 'content' => $content, 'dst' => $src ) );
675 $this->assertEquals( true, $status->isOK(),
676 "Creation of file at $src succeeded ($backendName)." );
677
678 $tmpFile = $this->backend->getLocalReference( array( 'src' => $src ) );
679 $this->assertNotNull( $tmpFile,
680 "Creation of local copy of $src succeeded ($backendName)." );
681
682 $contents = file_get_contents( $tmpFile->getPath() );
683 $this->assertNotEquals( false, $contents, "Local copy of $src exists ($backendName)." );
684 }
685
686 function provider_testGetLocalReference() {
687 $cases = array();
688
689 $base = $this->baseStorePath();
690 $cases[] = array( "$base/cont1/a/z/some_file.txt", "some file contents" );
691 $cases[] = array( "$base/cont1/a/some-other_file.txt", "more file contents" );
692
693 return $cases;
694 }
695
696 /**
697 * @dataProvider provider_testPrepareAndClean
698 */
699 public function testPrepareAndClean( $path, $isOK ) {
700 $this->backend = $this->singleBackend;
701 $this->doTestPrepareAndClean( $path, $isOK );
702
703 $this->backend = $this->multiBackend;
704 $this->doTestPrepareAndClean( $path, $isOK );
705 }
706
707 function provider_testPrepareAndClean() {
708 $base = $this->baseStorePath();
709 return array(
710 array( "$base/cont1/a/z/some_file1.txt", true ),
711 array( "$base/cont2/a/z/some_file2.txt", true ),
712 array( "$base/cont3/a/z/some_file3.txt", false ),
713 );
714 }
715
716 function doTestPrepareAndClean( $path, $isOK ) {
717 $backendName = $this->backendClass();
718
719 $status = $this->backend->prepare( array( 'dir' => $path ) );
720 if ( $isOK ) {
721 $this->assertEquals( array(), $status->errors,
722 "Preparing dir $path succeeded without warnings ($backendName)." );
723 $this->assertEquals( true, $status->isOK(),
724 "Preparing dir $path succeeded ($backendName)." );
725 } else {
726 $this->assertEquals( false, $status->isOK(),
727 "Preparing dir $path failed ($backendName)." );
728 }
729
730 $status = $this->backend->clean( array( 'dir' => $path ) );
731 if ( $isOK ) {
732 $this->assertEquals( array(), $status->errors,
733 "Cleaning dir $path succeeded without warnings ($backendName)." );
734 $this->assertEquals( true, $status->isOK(),
735 "Cleaning dir $path succeeded ($backendName)." );
736 } else {
737 $this->assertEquals( false, $status->isOK(),
738 "Cleaning dir $path failed ($backendName)." );
739 }
740 }
741
742 // @TODO: testSecure
743
744 // @TODO: testDoOperations
745
746 public function testGetFileList() {
747 $this->backend = $this->singleBackend;
748 $this->doTestGetFileList();
749 $this->tearDownFiles();
750
751 $this->backend = $this->multiBackend;
752 $this->doTestGetFileList();
753 $this->tearDownFiles();
754 }
755
756 public function doTestGetFileList() {
757 $backendName = $this->backendClass();
758
759 $base = $this->baseStorePath();
760 $files = array(
761 "$base/cont1/test1.txt",
762 "$base/cont1/test2.txt",
763 "$base/cont1/test3.txt",
764 "$base/cont1/subdir1/test1.txt",
765 "$base/cont1/subdir1/test2.txt",
766 "$base/cont1/subdir2/test3.txt",
767 "$base/cont1/subdir2/test4.txt",
768 "$base/cont1/subdir2/subdir/test1.txt",
769 "$base/cont1/subdir2/subdir/test2.txt",
770 "$base/cont1/subdir2/subdir/test3.txt",
771 "$base/cont1/subdir2/subdir/test4.txt",
772 "$base/cont1/subdir2/subdir/test5.txt",
773 "$base/cont1/subdir2/subdir/sub/test0.txt",
774 "$base/cont1/subdir2/subdir/sub/120-px-file.txt",
775 );
776 $this->pathsToPrune = array_merge( $this->pathsToPrune, $files );
777
778 // Add the files
779 $ops = array();
780 foreach ( $files as $file ) {
781 $ops[] = array( 'op' => 'create', 'content' => 'xxy', 'dst' => $file );
782 }
783 $status = $this->backend->doOperations( $ops );
784 $this->assertEquals( true, $status->isOK(),
785 "Creation of files succeeded ($backendName)." );
786
787 // Expected listing
788 $expected = array(
789 "test1.txt",
790 "test2.txt",
791 "test3.txt",
792 "subdir1/test1.txt",
793 "subdir1/test2.txt",
794 "subdir2/test3.txt",
795 "subdir2/test4.txt",
796 "subdir2/subdir/test1.txt",
797 "subdir2/subdir/test2.txt",
798 "subdir2/subdir/test3.txt",
799 "subdir2/subdir/test4.txt",
800 "subdir2/subdir/test5.txt",
801 "subdir2/subdir/sub/test0.txt",
802 "subdir2/subdir/sub/120-px-file.txt",
803 );
804 sort( $expected );
805
806 // Actual listing (no trailing slash)
807 $list = array();
808 $iter = $this->backend->getFileList( array( 'dir' => "$base/cont1" ) );
809 foreach ( $iter as $file ) {
810 $list[] = $file;
811 }
812 sort( $list );
813
814 $this->assertEquals( $expected, $list, "Correct file listing ($backendName)." );
815
816 // Actual listing (with trailing slash)
817 $list = array();
818 $iter = $this->backend->getFileList( array( 'dir' => "$base/cont1/" ) );
819 foreach ( $iter as $file ) {
820 $list[] = $file;
821 }
822 sort( $list );
823
824 $this->assertEquals( $expected, $list, "Correct file listing ($backendName)." );
825
826 foreach ( $files as $file ) {
827 $this->backend->doOperation( array( 'op' => 'delete', 'src' => "$base/$file" ) );
828 }
829
830 $iter = $this->backend->getFileList( array( 'dir' => "$base/cont1/not/exists" ) );
831 foreach ( $iter as $iter ) {} // no errors
832 }
833
834 function tearDownFiles() {
835 foreach ( $this->filesToPrune as $file ) {
836 @unlink( $file );
837 }
838 foreach ( $this->pathsToPrune as $file ) {
839 $this->backend->doOperation( array( 'op' => 'delete', 'src' => $file ) );
840 }
841 }
842
843 function tearDown() {
844 parent::tearDown();
845 }
846 }