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