MediaWiki
REL1_20
|
00001 <?php 00002 00008 class FileBackendTest extends MediaWikiTestCase { 00009 private $backend, $multiBackend; 00010 private $filesToPrune = array(); 00011 private static $backendToUse; 00012 00013 function setUp() { 00014 global $wgFileBackends; 00015 parent::setUp(); 00016 $tmpPrefix = wfTempDir() . '/filebackend-unittest-' . time() . '-' . mt_rand(); 00017 if ( $this->getCliArg( 'use-filebackend=' ) ) { 00018 if ( self::$backendToUse ) { 00019 $this->singleBackend = self::$backendToUse; 00020 } else { 00021 $name = $this->getCliArg( 'use-filebackend=' ); 00022 $useConfig = array(); 00023 foreach ( $wgFileBackends as $conf ) { 00024 if ( $conf['name'] == $name ) { 00025 $useConfig = $conf; 00026 break; 00027 } 00028 } 00029 $useConfig['name'] = 'localtesting'; // swap name 00030 $useConfig['shardViaHashLevels'] = array( // test sharding 00031 'unittest-cont1' => array( 'levels' => 1, 'base' => 16, 'repeat' => 1 ) 00032 ); 00033 $class = $useConfig['class']; 00034 self::$backendToUse = new $class( $useConfig ); 00035 $this->singleBackend = self::$backendToUse; 00036 } 00037 } else { 00038 $this->singleBackend = new FSFileBackend( array( 00039 'name' => 'localtesting', 00040 'lockManager' => 'fsLockManager', 00041 #'parallelize' => 'implicit', 00042 'containerPaths' => array( 00043 'unittest-cont1' => "{$tmpPrefix}-localtesting-cont1", 00044 'unittest-cont2' => "{$tmpPrefix}-localtesting-cont2" ) 00045 ) ); 00046 } 00047 $this->multiBackend = new FileBackendMultiWrite( array( 00048 'name' => 'localtesting', 00049 'lockManager' => 'fsLockManager', 00050 'parallelize' => 'implicit', 00051 'backends' => array( 00052 array( 00053 'name' => 'localmutlitesting1', 00054 'class' => 'FSFileBackend', 00055 'lockManager' => 'nullLockManager', 00056 'containerPaths' => array( 00057 'unittest-cont1' => "{$tmpPrefix}-localtestingmulti1-cont1", 00058 'unittest-cont2' => "{$tmpPrefix}-localtestingmulti1-cont2" ), 00059 'isMultiMaster' => false 00060 ), 00061 array( 00062 'name' => 'localmutlitesting2', 00063 'class' => 'FSFileBackend', 00064 'lockManager' => 'nullLockManager', 00065 'containerPaths' => array( 00066 'unittest-cont1' => "{$tmpPrefix}-localtestingmulti2-cont1", 00067 'unittest-cont2' => "{$tmpPrefix}-localtestingmulti2-cont2" ), 00068 'isMultiMaster' => true 00069 ) 00070 ) 00071 ) ); 00072 $this->filesToPrune = array(); 00073 } 00074 00075 private function baseStorePath() { 00076 return 'mwstore://localtesting'; 00077 } 00078 00079 private function backendClass() { 00080 return get_class( $this->backend ); 00081 } 00082 00086 public function testIsStoragePath( $path, $isStorePath ) { 00087 $this->assertEquals( $isStorePath, FileBackend::isStoragePath( $path ), 00088 "FileBackend::isStoragePath on path '$path'" ); 00089 } 00090 00091 function provider_testIsStoragePath() { 00092 return array( 00093 array( 'mwstore://', true ), 00094 array( 'mwstore://backend', true ), 00095 array( 'mwstore://backend/container', true ), 00096 array( 'mwstore://backend/container/', true ), 00097 array( 'mwstore://backend/container/path', true ), 00098 array( 'mwstore://backend//container/', true ), 00099 array( 'mwstore://backend//container//', true ), 00100 array( 'mwstore://backend//container//path', true ), 00101 array( 'mwstore:///', true ), 00102 array( 'mwstore:/', false ), 00103 array( 'mwstore:', false ), 00104 ); 00105 } 00106 00110 public function testSplitStoragePath( $path, $res ) { 00111 $this->assertEquals( $res, FileBackend::splitStoragePath( $path ), 00112 "FileBackend::splitStoragePath on path '$path'" ); 00113 } 00114 00115 function provider_testSplitStoragePath() { 00116 return array( 00117 array( 'mwstore://backend/container', array( 'backend', 'container', '' ) ), 00118 array( 'mwstore://backend/container/', array( 'backend', 'container', '' ) ), 00119 array( 'mwstore://backend/container/path', array( 'backend', 'container', 'path' ) ), 00120 array( 'mwstore://backend/container//path', array( 'backend', 'container', '/path' ) ), 00121 array( 'mwstore://backend//container/path', array( null, null, null ) ), 00122 array( 'mwstore://backend//container//path', array( null, null, null ) ), 00123 array( 'mwstore://', array( null, null, null ) ), 00124 array( 'mwstore://backend', array( null, null, null ) ), 00125 array( 'mwstore:///', array( null, null, null ) ), 00126 array( 'mwstore:/', array( null, null, null ) ), 00127 array( 'mwstore:', array( null, null, null ) ) 00128 ); 00129 } 00130 00134 public function testNormalizeStoragePath( $path, $res ) { 00135 $this->assertEquals( $res, FileBackend::normalizeStoragePath( $path ), 00136 "FileBackend::normalizeStoragePath on path '$path'" ); 00137 } 00138 00139 function provider_normalizeStoragePath() { 00140 return array( 00141 array( 'mwstore://backend/container', 'mwstore://backend/container' ), 00142 array( 'mwstore://backend/container/', 'mwstore://backend/container' ), 00143 array( 'mwstore://backend/container/path', 'mwstore://backend/container/path' ), 00144 array( 'mwstore://backend/container//path', 'mwstore://backend/container/path' ), 00145 array( 'mwstore://backend/container///path', 'mwstore://backend/container/path' ), 00146 array( 'mwstore://backend/container///path//to///obj', 'mwstore://backend/container/path/to/obj', 00147 array( 'mwstore://', null ), 00148 array( 'mwstore://backend', null ), 00149 array( 'mwstore://backend//container/path', null ), 00150 array( 'mwstore://backend//container//path', null ), 00151 array( 'mwstore:///', null ), 00152 array( 'mwstore:/', null ), 00153 array( 'mwstore:', null ), ) 00154 ); 00155 } 00156 00160 public function testParentStoragePath( $path, $res ) { 00161 $this->assertEquals( $res, FileBackend::parentStoragePath( $path ), 00162 "FileBackend::parentStoragePath on path '$path'" ); 00163 } 00164 00165 function provider_testParentStoragePath() { 00166 return array( 00167 array( 'mwstore://backend/container/path/to/obj', 'mwstore://backend/container/path/to' ), 00168 array( 'mwstore://backend/container/path/to', 'mwstore://backend/container/path' ), 00169 array( 'mwstore://backend/container/path', 'mwstore://backend/container' ), 00170 array( 'mwstore://backend/container', null ), 00171 array( 'mwstore://backend/container/path/to/obj/', 'mwstore://backend/container/path/to' ), 00172 array( 'mwstore://backend/container/path/to/', 'mwstore://backend/container/path' ), 00173 array( 'mwstore://backend/container/path/', 'mwstore://backend/container' ), 00174 array( 'mwstore://backend/container/', null ), 00175 ); 00176 } 00177 00181 public function testExtensionFromPath( $path, $res ) { 00182 $this->assertEquals( $res, FileBackend::extensionFromPath( $path ), 00183 "FileBackend::extensionFromPath on path '$path'" ); 00184 } 00185 00186 function provider_testExtensionFromPath() { 00187 return array( 00188 array( 'mwstore://backend/container/path.txt', 'txt' ), 00189 array( 'mwstore://backend/container/path.svg.png', 'png' ), 00190 array( 'mwstore://backend/container/path', '' ), 00191 array( 'mwstore://backend/container/path.', '' ), 00192 ); 00193 } 00194 00198 public function testStore( $op ) { 00199 $this->filesToPrune[] = $op['src']; 00200 00201 $this->backend = $this->singleBackend; 00202 $this->tearDownFiles(); 00203 $this->doTestStore( $op ); 00204 $this->tearDownFiles(); 00205 00206 $this->backend = $this->multiBackend; 00207 $this->tearDownFiles(); 00208 $this->doTestStore( $op ); 00209 $this->filesToPrune[] = $op['src']; # avoid file leaking 00210 $this->tearDownFiles(); 00211 } 00212 00213 private function doTestStore( $op ) { 00214 $backendName = $this->backendClass(); 00215 00216 $source = $op['src']; 00217 $dest = $op['dst']; 00218 $this->prepare( array( 'dir' => dirname( $dest ) ) ); 00219 00220 file_put_contents( $source, "Unit test file" ); 00221 00222 if ( isset( $op['overwrite'] ) || isset( $op['overwriteSame'] ) ) { 00223 $this->backend->store( $op ); 00224 } 00225 00226 $status = $this->backend->doOperation( $op ); 00227 00228 $this->assertGoodStatus( $status, 00229 "Store from $source to $dest succeeded without warnings ($backendName)." ); 00230 $this->assertEquals( true, $status->isOK(), 00231 "Store from $source to $dest succeeded ($backendName)." ); 00232 $this->assertEquals( array( 0 => true ), $status->success, 00233 "Store from $source to $dest has proper 'success' field in Status ($backendName)." ); 00234 $this->assertEquals( true, file_exists( $source ), 00235 "Source file $source still exists ($backendName)." ); 00236 $this->assertEquals( true, $this->backend->fileExists( array( 'src' => $dest ) ), 00237 "Destination file $dest exists ($backendName)." ); 00238 00239 $this->assertEquals( filesize( $source ), 00240 $this->backend->getFileSize( array( 'src' => $dest ) ), 00241 "Destination file $dest has correct size ($backendName)." ); 00242 00243 $props1 = FSFile::getPropsFromPath( $source ); 00244 $props2 = $this->backend->getFileProps( array( 'src' => $dest ) ); 00245 $this->assertEquals( $props1, $props2, 00246 "Source and destination have the same props ($backendName)." ); 00247 00248 $this->assertBackendPathsConsistent( array( $dest ) ); 00249 } 00250 00251 public function provider_testStore() { 00252 $cases = array(); 00253 00254 $tmpName = TempFSFile::factory( "unittests_", 'txt' )->getPath(); 00255 $toPath = $this->baseStorePath() . '/unittest-cont1/e/fun/obj1.txt'; 00256 $op = array( 'op' => 'store', 'src' => $tmpName, 'dst' => $toPath ); 00257 $cases[] = array( 00258 $op, // operation 00259 $tmpName, // source 00260 $toPath, // dest 00261 ); 00262 00263 $op2 = $op; 00264 $op2['overwrite'] = true; 00265 $cases[] = array( 00266 $op2, // operation 00267 $tmpName, // source 00268 $toPath, // dest 00269 ); 00270 00271 $op2 = $op; 00272 $op2['overwriteSame'] = true; 00273 $cases[] = array( 00274 $op2, // operation 00275 $tmpName, // source 00276 $toPath, // dest 00277 ); 00278 00279 return $cases; 00280 } 00281 00285 public function testCopy( $op ) { 00286 $this->backend = $this->singleBackend; 00287 $this->tearDownFiles(); 00288 $this->doTestCopy( $op ); 00289 $this->tearDownFiles(); 00290 00291 $this->backend = $this->multiBackend; 00292 $this->tearDownFiles(); 00293 $this->doTestCopy( $op ); 00294 $this->tearDownFiles(); 00295 } 00296 00297 private function doTestCopy( $op ) { 00298 $backendName = $this->backendClass(); 00299 00300 $source = $op['src']; 00301 $dest = $op['dst']; 00302 $this->prepare( array( 'dir' => dirname( $source ) ) ); 00303 $this->prepare( array( 'dir' => dirname( $dest ) ) ); 00304 00305 $status = $this->backend->doOperation( 00306 array( 'op' => 'create', 'content' => 'blahblah', 'dst' => $source ) ); 00307 $this->assertGoodStatus( $status, 00308 "Creation of file at $source succeeded ($backendName)." ); 00309 00310 if ( isset( $op['overwrite'] ) || isset( $op['overwriteSame'] ) ) { 00311 $this->backend->copy( $op ); 00312 } 00313 00314 $status = $this->backend->doOperation( $op ); 00315 00316 $this->assertGoodStatus( $status, 00317 "Copy from $source to $dest succeeded without warnings ($backendName)." ); 00318 $this->assertEquals( true, $status->isOK(), 00319 "Copy from $source to $dest succeeded ($backendName)." ); 00320 $this->assertEquals( array( 0 => true ), $status->success, 00321 "Copy from $source to $dest has proper 'success' field in Status ($backendName)." ); 00322 $this->assertEquals( true, $this->backend->fileExists( array( 'src' => $source ) ), 00323 "Source file $source still exists ($backendName)." ); 00324 $this->assertEquals( true, $this->backend->fileExists( array( 'src' => $dest ) ), 00325 "Destination file $dest exists after copy ($backendName)." ); 00326 00327 $this->assertEquals( 00328 $this->backend->getFileSize( array( 'src' => $source ) ), 00329 $this->backend->getFileSize( array( 'src' => $dest ) ), 00330 "Destination file $dest has correct size ($backendName)." ); 00331 00332 $props1 = $this->backend->getFileProps( array( 'src' => $source ) ); 00333 $props2 = $this->backend->getFileProps( array( 'src' => $dest ) ); 00334 $this->assertEquals( $props1, $props2, 00335 "Source and destination have the same props ($backendName)." ); 00336 00337 $this->assertBackendPathsConsistent( array( $source, $dest ) ); 00338 } 00339 00340 public function provider_testCopy() { 00341 $cases = array(); 00342 00343 $source = $this->baseStorePath() . '/unittest-cont1/e/file.txt'; 00344 $dest = $this->baseStorePath() . '/unittest-cont2/a/fileMoved.txt'; 00345 00346 $op = array( 'op' => 'copy', 'src' => $source, 'dst' => $dest ); 00347 $cases[] = array( 00348 $op, // operation 00349 $source, // source 00350 $dest, // dest 00351 ); 00352 00353 $op2 = $op; 00354 $op2['overwrite'] = true; 00355 $cases[] = array( 00356 $op2, // operation 00357 $source, // source 00358 $dest, // dest 00359 ); 00360 00361 $op2 = $op; 00362 $op2['overwriteSame'] = true; 00363 $cases[] = array( 00364 $op2, // operation 00365 $source, // source 00366 $dest, // dest 00367 ); 00368 00369 return $cases; 00370 } 00371 00375 public function testMove( $op ) { 00376 $this->backend = $this->singleBackend; 00377 $this->tearDownFiles(); 00378 $this->doTestMove( $op ); 00379 $this->tearDownFiles(); 00380 00381 $this->backend = $this->multiBackend; 00382 $this->tearDownFiles(); 00383 $this->doTestMove( $op ); 00384 $this->tearDownFiles(); 00385 } 00386 00387 private function doTestMove( $op ) { 00388 $backendName = $this->backendClass(); 00389 00390 $source = $op['src']; 00391 $dest = $op['dst']; 00392 $this->prepare( array( 'dir' => dirname( $source ) ) ); 00393 $this->prepare( array( 'dir' => dirname( $dest ) ) ); 00394 00395 $status = $this->backend->doOperation( 00396 array( 'op' => 'create', 'content' => 'blahblah', 'dst' => $source ) ); 00397 $this->assertGoodStatus( $status, 00398 "Creation of file at $source succeeded ($backendName)." ); 00399 00400 if ( isset( $op['overwrite'] ) || isset( $op['overwriteSame'] ) ) { 00401 $this->backend->copy( $op ); 00402 } 00403 00404 $status = $this->backend->doOperation( $op ); 00405 $this->assertGoodStatus( $status, 00406 "Move from $source to $dest succeeded without warnings ($backendName)." ); 00407 $this->assertEquals( true, $status->isOK(), 00408 "Move from $source to $dest succeeded ($backendName)." ); 00409 $this->assertEquals( array( 0 => true ), $status->success, 00410 "Move from $source to $dest has proper 'success' field in Status ($backendName)." ); 00411 $this->assertEquals( false, $this->backend->fileExists( array( 'src' => $source ) ), 00412 "Source file $source does not still exists ($backendName)." ); 00413 $this->assertEquals( true, $this->backend->fileExists( array( 'src' => $dest ) ), 00414 "Destination file $dest exists after move ($backendName)." ); 00415 00416 $this->assertNotEquals( 00417 $this->backend->getFileSize( array( 'src' => $source ) ), 00418 $this->backend->getFileSize( array( 'src' => $dest ) ), 00419 "Destination file $dest has correct size ($backendName)." ); 00420 00421 $props1 = $this->backend->getFileProps( array( 'src' => $source ) ); 00422 $props2 = $this->backend->getFileProps( array( 'src' => $dest ) ); 00423 $this->assertEquals( false, $props1['fileExists'], 00424 "Source file does not exist accourding to props ($backendName)." ); 00425 $this->assertEquals( true, $props2['fileExists'], 00426 "Destination file exists accourding to props ($backendName)." ); 00427 00428 $this->assertBackendPathsConsistent( array( $source, $dest ) ); 00429 } 00430 00431 public function provider_testMove() { 00432 $cases = array(); 00433 00434 $source = $this->baseStorePath() . '/unittest-cont1/e/file.txt'; 00435 $dest = $this->baseStorePath() . '/unittest-cont2/a/fileMoved.txt'; 00436 00437 $op = array( 'op' => 'move', 'src' => $source, 'dst' => $dest ); 00438 $cases[] = array( 00439 $op, // operation 00440 $source, // source 00441 $dest, // dest 00442 ); 00443 00444 $op2 = $op; 00445 $op2['overwrite'] = true; 00446 $cases[] = array( 00447 $op2, // operation 00448 $source, // source 00449 $dest, // dest 00450 ); 00451 00452 $op2 = $op; 00453 $op2['overwriteSame'] = true; 00454 $cases[] = array( 00455 $op2, // operation 00456 $source, // source 00457 $dest, // dest 00458 ); 00459 00460 return $cases; 00461 } 00462 00466 public function testDelete( $op, $withSource, $okStatus ) { 00467 $this->backend = $this->singleBackend; 00468 $this->tearDownFiles(); 00469 $this->doTestDelete( $op, $withSource, $okStatus ); 00470 $this->tearDownFiles(); 00471 00472 $this->backend = $this->multiBackend; 00473 $this->tearDownFiles(); 00474 $this->doTestDelete( $op, $withSource, $okStatus ); 00475 $this->tearDownFiles(); 00476 } 00477 00478 private function doTestDelete( $op, $withSource, $okStatus ) { 00479 $backendName = $this->backendClass(); 00480 00481 $source = $op['src']; 00482 $this->prepare( array( 'dir' => dirname( $source ) ) ); 00483 00484 if ( $withSource ) { 00485 $status = $this->backend->doOperation( 00486 array( 'op' => 'create', 'content' => 'blahblah', 'dst' => $source ) ); 00487 $this->assertGoodStatus( $status, 00488 "Creation of file at $source succeeded ($backendName)." ); 00489 } 00490 00491 $status = $this->backend->doOperation( $op ); 00492 if ( $okStatus ) { 00493 $this->assertGoodStatus( $status, 00494 "Deletion of file at $source succeeded without warnings ($backendName)." ); 00495 $this->assertEquals( true, $status->isOK(), 00496 "Deletion of file at $source succeeded ($backendName)." ); 00497 $this->assertEquals( array( 0 => true ), $status->success, 00498 "Deletion of file at $source has proper 'success' field in Status ($backendName)." ); 00499 } else { 00500 $this->assertEquals( false, $status->isOK(), 00501 "Deletion of file at $source failed ($backendName)." ); 00502 } 00503 00504 $this->assertEquals( false, $this->backend->fileExists( array( 'src' => $source ) ), 00505 "Source file $source does not exist after move ($backendName)." ); 00506 00507 $this->assertFalse( 00508 $this->backend->getFileSize( array( 'src' => $source ) ), 00509 "Source file $source has correct size (false) ($backendName)." ); 00510 00511 $props1 = $this->backend->getFileProps( array( 'src' => $source ) ); 00512 $this->assertFalse( $props1['fileExists'], 00513 "Source file $source does not exist according to props ($backendName)." ); 00514 00515 $this->assertBackendPathsConsistent( array( $source ) ); 00516 } 00517 00518 public function provider_testDelete() { 00519 $cases = array(); 00520 00521 $source = $this->baseStorePath() . '/unittest-cont1/e/myfacefile.txt'; 00522 00523 $op = array( 'op' => 'delete', 'src' => $source ); 00524 $cases[] = array( 00525 $op, // operation 00526 true, // with source 00527 true // succeeds 00528 ); 00529 00530 $cases[] = array( 00531 $op, // operation 00532 false, // without source 00533 false // fails 00534 ); 00535 00536 $op['ignoreMissingSource'] = true; 00537 $cases[] = array( 00538 $op, // operation 00539 false, // without source 00540 true // succeeds 00541 ); 00542 00543 return $cases; 00544 } 00545 00549 public function testCreate( $op, $alreadyExists, $okStatus, $newSize ) { 00550 $this->backend = $this->singleBackend; 00551 $this->tearDownFiles(); 00552 $this->doTestCreate( $op, $alreadyExists, $okStatus, $newSize ); 00553 $this->tearDownFiles(); 00554 00555 $this->backend = $this->multiBackend; 00556 $this->tearDownFiles(); 00557 $this->doTestCreate( $op, $alreadyExists, $okStatus, $newSize ); 00558 $this->tearDownFiles(); 00559 } 00560 00561 private function doTestCreate( $op, $alreadyExists, $okStatus, $newSize ) { 00562 $backendName = $this->backendClass(); 00563 00564 $dest = $op['dst']; 00565 $this->prepare( array( 'dir' => dirname( $dest ) ) ); 00566 00567 $oldText = 'blah...blah...waahwaah'; 00568 if ( $alreadyExists ) { 00569 $status = $this->backend->doOperation( 00570 array( 'op' => 'create', 'content' => $oldText, 'dst' => $dest ) ); 00571 $this->assertGoodStatus( $status, 00572 "Creation of file at $dest succeeded ($backendName)." ); 00573 } 00574 00575 $status = $this->backend->doOperation( $op ); 00576 if ( $okStatus ) { 00577 $this->assertGoodStatus( $status, 00578 "Creation of file at $dest succeeded without warnings ($backendName)." ); 00579 $this->assertEquals( true, $status->isOK(), 00580 "Creation of file at $dest succeeded ($backendName)." ); 00581 $this->assertEquals( array( 0 => true ), $status->success, 00582 "Creation of file at $dest has proper 'success' field in Status ($backendName)." ); 00583 } else { 00584 $this->assertEquals( false, $status->isOK(), 00585 "Creation of file at $dest failed ($backendName)." ); 00586 } 00587 00588 $this->assertEquals( true, $this->backend->fileExists( array( 'src' => $dest ) ), 00589 "Destination file $dest exists after creation ($backendName)." ); 00590 00591 $props1 = $this->backend->getFileProps( array( 'src' => $dest ) ); 00592 $this->assertEquals( true, $props1['fileExists'], 00593 "Destination file $dest exists according to props ($backendName)." ); 00594 if ( $okStatus ) { // file content is what we saved 00595 $this->assertEquals( $newSize, $props1['size'], 00596 "Destination file $dest has expected size according to props ($backendName)." ); 00597 $this->assertEquals( $newSize, 00598 $this->backend->getFileSize( array( 'src' => $dest ) ), 00599 "Destination file $dest has correct size ($backendName)." ); 00600 } else { // file content is some other previous text 00601 $this->assertEquals( strlen( $oldText ), $props1['size'], 00602 "Destination file $dest has original size according to props ($backendName)." ); 00603 $this->assertEquals( strlen( $oldText ), 00604 $this->backend->getFileSize( array( 'src' => $dest ) ), 00605 "Destination file $dest has original size according to props ($backendName)." ); 00606 } 00607 00608 $this->assertBackendPathsConsistent( array( $dest ) ); 00609 } 00610 00614 public function provider_testCreate() { 00615 $cases = array(); 00616 00617 $dest = $this->baseStorePath() . '/unittest-cont2/a/myspacefile.txt'; 00618 00619 $op = array( 'op' => 'create', 'content' => 'test test testing', 'dst' => $dest ); 00620 $cases[] = array( 00621 $op, // operation 00622 false, // no dest already exists 00623 true, // succeeds 00624 strlen( $op['content'] ) 00625 ); 00626 00627 $op2 = $op; 00628 $op2['content'] = "\n"; 00629 $cases[] = array( 00630 $op2, // operation 00631 false, // no dest already exists 00632 true, // succeeds 00633 strlen( $op2['content'] ) 00634 ); 00635 00636 $op2 = $op; 00637 $op2['content'] = "fsf\n waf 3kt"; 00638 $cases[] = array( 00639 $op2, // operation 00640 true, // dest already exists 00641 false, // fails 00642 strlen( $op2['content'] ) 00643 ); 00644 00645 $op2 = $op; 00646 $op2['content'] = "egm'g gkpe gpqg eqwgwqg"; 00647 $op2['overwrite'] = true; 00648 $cases[] = array( 00649 $op2, // operation 00650 true, // dest already exists 00651 true, // succeeds 00652 strlen( $op2['content'] ) 00653 ); 00654 00655 $op2 = $op; 00656 $op2['content'] = "39qjmg3-qg"; 00657 $op2['overwriteSame'] = true; 00658 $cases[] = array( 00659 $op2, // operation 00660 true, // dest already exists 00661 false, // succeeds 00662 strlen( $op2['content'] ) 00663 ); 00664 00665 return $cases; 00666 } 00667 00668 public function testDoQuickOperations() { 00669 $this->backend = $this->singleBackend; 00670 $this->doTestDoQuickOperations(); 00671 $this->tearDownFiles(); 00672 00673 $this->backend = $this->multiBackend; 00674 $this->doTestDoQuickOperations(); 00675 $this->tearDownFiles(); 00676 } 00677 00678 private function doTestDoQuickOperations() { 00679 $backendName = $this->backendClass(); 00680 00681 $base = $this->baseStorePath(); 00682 $files = array( 00683 "$base/unittest-cont1/e/fileA.a", 00684 "$base/unittest-cont1/e/fileB.a", 00685 "$base/unittest-cont1/e/fileC.a" 00686 ); 00687 $ops = array(); 00688 $purgeOps = array(); 00689 foreach ( $files as $path ) { 00690 $status = $this->prepare( array( 'dir' => dirname( $path ) ) ); 00691 $this->assertGoodStatus( $status, 00692 "Preparing $path succeeded without warnings ($backendName)." ); 00693 $ops[] = array( 'op' => 'create', 'dst' => $path, 'content' => mt_rand(0,50000) ); 00694 $purgeOps[] = array( 'op' => 'delete', 'src' => $path ); 00695 } 00696 $purgeOps[] = array( 'op' => 'null' ); 00697 $status = $this->backend->doQuickOperations( $ops ); 00698 $this->assertGoodStatus( $status, 00699 "Creation of source files succeeded ($backendName)." ); 00700 00701 foreach ( $files as $file ) { 00702 $this->assertTrue( $this->backend->fileExists( array( 'src' => $file ) ), 00703 "File $file exists." ); 00704 } 00705 00706 $status = $this->backend->doQuickOperations( $purgeOps ); 00707 $this->assertGoodStatus( $status, 00708 "Quick deletion of source files succeeded ($backendName)." ); 00709 00710 foreach ( $files as $file ) { 00711 $this->assertFalse( $this->backend->fileExists( array( 'src' => $file ) ), 00712 "File $file purged." ); 00713 } 00714 } 00715 00719 public function testConcatenate( $op, $srcs, $srcsContent, $alreadyExists, $okStatus ) { 00720 $this->filesToPrune[] = $op['dst']; 00721 00722 $this->backend = $this->singleBackend; 00723 $this->tearDownFiles(); 00724 $this->doTestConcatenate( $op, $srcs, $srcsContent, $alreadyExists, $okStatus ); 00725 $this->tearDownFiles(); 00726 00727 $this->backend = $this->multiBackend; 00728 $this->tearDownFiles(); 00729 $this->doTestConcatenate( $op, $srcs, $srcsContent, $alreadyExists, $okStatus ); 00730 $this->filesToPrune[] = $op['dst']; # avoid file leaking 00731 $this->tearDownFiles(); 00732 } 00733 00734 private function doTestConcatenate( $params, $srcs, $srcsContent, $alreadyExists, $okStatus ) { 00735 $backendName = $this->backendClass(); 00736 00737 $expContent = ''; 00738 // Create sources 00739 $ops = array(); 00740 foreach ( $srcs as $i => $source ) { 00741 $this->prepare( array( 'dir' => dirname( $source ) ) ); 00742 $ops[] = array( 00743 'op' => 'create', // operation 00744 'dst' => $source, // source 00745 'content' => $srcsContent[$i] 00746 ); 00747 $expContent .= $srcsContent[$i]; 00748 } 00749 $status = $this->backend->doOperations( $ops ); 00750 00751 $this->assertGoodStatus( $status, 00752 "Creation of source files succeeded ($backendName)." ); 00753 00754 $dest = $params['dst']; 00755 if ( $alreadyExists ) { 00756 $ok = file_put_contents( $dest, 'blah...blah...waahwaah' ) !== false; 00757 $this->assertEquals( true, $ok, 00758 "Creation of file at $dest succeeded ($backendName)." ); 00759 } else { 00760 $ok = file_put_contents( $dest, '' ) !== false; 00761 $this->assertEquals( true, $ok, 00762 "Creation of 0-byte file at $dest succeeded ($backendName)." ); 00763 } 00764 00765 // Combine the files into one 00766 $status = $this->backend->concatenate( $params ); 00767 if ( $okStatus ) { 00768 $this->assertGoodStatus( $status, 00769 "Creation of concat file at $dest succeeded without warnings ($backendName)." ); 00770 $this->assertEquals( true, $status->isOK(), 00771 "Creation of concat file at $dest succeeded ($backendName)." ); 00772 } else { 00773 $this->assertEquals( false, $status->isOK(), 00774 "Creation of concat file at $dest failed ($backendName)." ); 00775 } 00776 00777 if ( $okStatus ) { 00778 $this->assertEquals( true, is_file( $dest ), 00779 "Dest concat file $dest exists after creation ($backendName)." ); 00780 } else { 00781 $this->assertEquals( true, is_file( $dest ), 00782 "Dest concat file $dest exists after failed creation ($backendName)." ); 00783 } 00784 00785 $contents = file_get_contents( $dest ); 00786 $this->assertNotEquals( false, $contents, "File at $dest exists ($backendName)." ); 00787 00788 if ( $okStatus ) { 00789 $this->assertEquals( $expContent, $contents, 00790 "Concat file at $dest has correct contents ($backendName)." ); 00791 } else { 00792 $this->assertNotEquals( $expContent, $contents, 00793 "Concat file at $dest has correct contents ($backendName)." ); 00794 } 00795 } 00796 00797 function provider_testConcatenate() { 00798 $cases = array(); 00799 00800 $rand = mt_rand( 0, 2000000000 ) . time(); 00801 $dest = wfTempDir() . "/randomfile!$rand.txt"; 00802 $srcs = array( 00803 $this->baseStorePath() . '/unittest-cont1/e/file1.txt', 00804 $this->baseStorePath() . '/unittest-cont1/e/file2.txt', 00805 $this->baseStorePath() . '/unittest-cont1/e/file3.txt', 00806 $this->baseStorePath() . '/unittest-cont1/e/file4.txt', 00807 $this->baseStorePath() . '/unittest-cont1/e/file5.txt', 00808 $this->baseStorePath() . '/unittest-cont1/e/file6.txt', 00809 $this->baseStorePath() . '/unittest-cont1/e/file7.txt', 00810 $this->baseStorePath() . '/unittest-cont1/e/file8.txt', 00811 $this->baseStorePath() . '/unittest-cont1/e/file9.txt', 00812 $this->baseStorePath() . '/unittest-cont1/e/file10.txt' 00813 ); 00814 $content = array( 00815 'egfage', 00816 'ageageag', 00817 'rhokohlr', 00818 'shgmslkg', 00819 'kenga', 00820 'owagmal', 00821 'kgmae', 00822 'g eak;g', 00823 'lkaem;a', 00824 'legma' 00825 ); 00826 $params = array( 'srcs' => $srcs, 'dst' => $dest ); 00827 00828 $cases[] = array( 00829 $params, // operation 00830 $srcs, // sources 00831 $content, // content for each source 00832 false, // no dest already exists 00833 true, // succeeds 00834 ); 00835 00836 $cases[] = array( 00837 $params, // operation 00838 $srcs, // sources 00839 $content, // content for each source 00840 true, // dest already exists 00841 false, // succeeds 00842 ); 00843 00844 return $cases; 00845 } 00846 00850 public function testGetFileStat( $path, $content, $alreadyExists ) { 00851 $this->backend = $this->singleBackend; 00852 $this->tearDownFiles(); 00853 $this->doTestGetFileStat( $path, $content, $alreadyExists ); 00854 $this->tearDownFiles(); 00855 00856 $this->backend = $this->multiBackend; 00857 $this->tearDownFiles(); 00858 $this->doTestGetFileStat( $path, $content, $alreadyExists ); 00859 $this->tearDownFiles(); 00860 } 00861 00862 private function doTestGetFileStat( $path, $content, $alreadyExists ) { 00863 $backendName = $this->backendClass(); 00864 00865 if ( $alreadyExists ) { 00866 $this->prepare( array( 'dir' => dirname( $path ) ) ); 00867 $status = $this->create( array( 'dst' => $path, 'content' => $content ) ); 00868 $this->assertGoodStatus( $status, 00869 "Creation of file at $path succeeded ($backendName)." ); 00870 00871 $size = $this->backend->getFileSize( array( 'src' => $path ) ); 00872 $time = $this->backend->getFileTimestamp( array( 'src' => $path ) ); 00873 $stat = $this->backend->getFileStat( array( 'src' => $path ) ); 00874 00875 $this->assertEquals( strlen( $content ), $size, 00876 "Correct file size of '$path'" ); 00877 $this->assertTrue( abs( time() - wfTimestamp( TS_UNIX, $time ) ) < 10, 00878 "Correct file timestamp of '$path'" ); 00879 00880 $size = $stat['size']; 00881 $time = $stat['mtime']; 00882 $this->assertEquals( strlen( $content ), $size, 00883 "Correct file size of '$path'" ); 00884 $this->assertTrue( abs( time() - wfTimestamp( TS_UNIX, $time ) ) < 10, 00885 "Correct file timestamp of '$path'" ); 00886 00887 $this->backend->clearCache( array( $path ) ); 00888 00889 $size = $this->backend->getFileSize( array( 'src' => $path ) ); 00890 00891 $this->assertEquals( strlen( $content ), $size, 00892 "Correct file size of '$path'" ); 00893 00894 $this->backend->preloadCache( array( $path ) ); 00895 00896 $size = $this->backend->getFileSize( array( 'src' => $path ) ); 00897 00898 $this->assertEquals( strlen( $content ), $size, 00899 "Correct file size of '$path'" ); 00900 } else { 00901 $size = $this->backend->getFileSize( array( 'src' => $path ) ); 00902 $time = $this->backend->getFileTimestamp( array( 'src' => $path ) ); 00903 $stat = $this->backend->getFileStat( array( 'src' => $path ) ); 00904 00905 $this->assertFalse( $size, "Correct file size of '$path'" ); 00906 $this->assertFalse( $time, "Correct file timestamp of '$path'" ); 00907 $this->assertFalse( $stat, "Correct file stat of '$path'" ); 00908 } 00909 } 00910 00911 function provider_testGetFileStat() { 00912 $cases = array(); 00913 00914 $base = $this->baseStorePath(); 00915 $cases[] = array( "$base/unittest-cont1/e/b/z/some_file.txt", "some file contents", true ); 00916 $cases[] = array( "$base/unittest-cont1/e/b/some-other_file.txt", "", true ); 00917 $cases[] = array( "$base/unittest-cont1/e/b/some-diff_file.txt", null, false ); 00918 00919 return $cases; 00920 } 00921 00925 public function testGetFileContents( $source, $content ) { 00926 $this->backend = $this->singleBackend; 00927 $this->tearDownFiles(); 00928 $this->doTestGetFileContents( $source, $content ); 00929 $this->tearDownFiles(); 00930 00931 $this->backend = $this->multiBackend; 00932 $this->tearDownFiles(); 00933 $this->doTestGetFileContents( $source, $content ); 00934 $this->tearDownFiles(); 00935 } 00936 00937 private function doTestGetFileContents( $source, $content ) { 00938 $backendName = $this->backendClass(); 00939 00940 $this->prepare( array( 'dir' => dirname( $source ) ) ); 00941 00942 $status = $this->backend->doOperation( 00943 array( 'op' => 'create', 'content' => $content, 'dst' => $source ) ); 00944 $this->assertGoodStatus( $status, 00945 "Creation of file at $source succeeded ($backendName)." ); 00946 $this->assertEquals( true, $status->isOK(), 00947 "Creation of file at $source succeeded with OK status ($backendName)." ); 00948 00949 $newContents = $this->backend->getFileContents( array( 'src' => $source, 'latest' => 1 ) ); 00950 $this->assertNotEquals( false, $newContents, 00951 "Read of file at $source succeeded ($backendName)." ); 00952 00953 $this->assertEquals( $content, $newContents, 00954 "Contents read match data at $source ($backendName)." ); 00955 } 00956 00957 function provider_testGetFileContents() { 00958 $cases = array(); 00959 00960 $base = $this->baseStorePath(); 00961 $cases[] = array( "$base/unittest-cont1/e/b/z/some_file.txt", "some file contents" ); 00962 $cases[] = array( "$base/unittest-cont1/e/b/some-other_file.txt", "more file contents" ); 00963 00964 return $cases; 00965 } 00966 00970 public function testGetLocalCopy( $source, $content ) { 00971 $this->backend = $this->singleBackend; 00972 $this->tearDownFiles(); 00973 $this->doTestGetLocalCopy( $source, $content ); 00974 $this->tearDownFiles(); 00975 00976 $this->backend = $this->multiBackend; 00977 $this->tearDownFiles(); 00978 $this->doTestGetLocalCopy( $source, $content ); 00979 $this->tearDownFiles(); 00980 } 00981 00982 private function doTestGetLocalCopy( $source, $content ) { 00983 $backendName = $this->backendClass(); 00984 00985 $this->prepare( array( 'dir' => dirname( $source ) ) ); 00986 00987 $status = $this->backend->doOperation( 00988 array( 'op' => 'create', 'content' => $content, 'dst' => $source ) ); 00989 $this->assertGoodStatus( $status, 00990 "Creation of file at $source succeeded ($backendName)." ); 00991 00992 $tmpFile = $this->backend->getLocalCopy( array( 'src' => $source ) ); 00993 $this->assertNotNull( $tmpFile, 00994 "Creation of local copy of $source succeeded ($backendName)." ); 00995 00996 $contents = file_get_contents( $tmpFile->getPath() ); 00997 $this->assertNotEquals( false, $contents, "Local copy of $source exists ($backendName)." ); 00998 } 00999 01000 function provider_testGetLocalCopy() { 01001 $cases = array(); 01002 01003 $base = $this->baseStorePath(); 01004 $cases[] = array( "$base/unittest-cont1/e/a/z/some_file.txt", "some file contents" ); 01005 $cases[] = array( "$base/unittest-cont1/e/a/some-other_file.txt", "more file contents" ); 01006 01007 return $cases; 01008 } 01009 01013 public function testGetLocalReference( $source, $content ) { 01014 $this->backend = $this->singleBackend; 01015 $this->tearDownFiles(); 01016 $this->doTestGetLocalReference( $source, $content ); 01017 $this->tearDownFiles(); 01018 01019 $this->backend = $this->multiBackend; 01020 $this->tearDownFiles(); 01021 $this->doTestGetLocalReference( $source, $content ); 01022 $this->tearDownFiles(); 01023 } 01024 01025 private function doTestGetLocalReference( $source, $content ) { 01026 $backendName = $this->backendClass(); 01027 01028 $this->prepare( array( 'dir' => dirname( $source ) ) ); 01029 01030 $status = $this->create( array( 'content' => $content, 'dst' => $source ) ); 01031 $this->assertGoodStatus( $status, 01032 "Creation of file at $source succeeded ($backendName)." ); 01033 01034 $tmpFile = $this->backend->getLocalReference( array( 'src' => $source ) ); 01035 $this->assertNotNull( $tmpFile, 01036 "Creation of local copy of $source succeeded ($backendName)." ); 01037 01038 $contents = file_get_contents( $tmpFile->getPath() ); 01039 $this->assertNotEquals( false, $contents, "Local copy of $source exists ($backendName)." ); 01040 } 01041 01042 function provider_testGetLocalReference() { 01043 $cases = array(); 01044 01045 $base = $this->baseStorePath(); 01046 $cases[] = array( "$base/unittest-cont1/e/a/z/some_file.txt", "some file contents" ); 01047 $cases[] = array( "$base/unittest-cont1/e/a/some-other_file.txt", "more file contents" ); 01048 01049 return $cases; 01050 } 01051 01055 public function testPrepareAndClean( $path, $isOK ) { 01056 $this->backend = $this->singleBackend; 01057 $this->doTestPrepareAndClean( $path, $isOK ); 01058 $this->tearDownFiles(); 01059 01060 $this->backend = $this->multiBackend; 01061 $this->doTestPrepareAndClean( $path, $isOK ); 01062 $this->tearDownFiles(); 01063 } 01064 01065 function provider_testPrepareAndClean() { 01066 $base = $this->baseStorePath(); 01067 return array( 01068 array( "$base/unittest-cont1/e/a/z/some_file1.txt", true ), 01069 array( "$base/unittest-cont2/a/z/some_file2.txt", true ), 01070 # Specific to FS backend with no basePath field set 01071 #array( "$base/unittest-cont3/a/z/some_file3.txt", false ), 01072 ); 01073 } 01074 01075 private function doTestPrepareAndClean( $path, $isOK ) { 01076 $backendName = $this->backendClass(); 01077 01078 $status = $this->prepare( array( 'dir' => dirname( $path ) ) ); 01079 if ( $isOK ) { 01080 $this->assertGoodStatus( $status, 01081 "Preparing dir $path succeeded without warnings ($backendName)." ); 01082 $this->assertEquals( true, $status->isOK(), 01083 "Preparing dir $path succeeded ($backendName)." ); 01084 } else { 01085 $this->assertEquals( false, $status->isOK(), 01086 "Preparing dir $path failed ($backendName)." ); 01087 } 01088 01089 $status = $this->backend->clean( array( 'dir' => dirname( $path ) ) ); 01090 if ( $isOK ) { 01091 $this->assertGoodStatus( $status, 01092 "Cleaning dir $path succeeded without warnings ($backendName)." ); 01093 $this->assertEquals( true, $status->isOK(), 01094 "Cleaning dir $path succeeded ($backendName)." ); 01095 } else { 01096 $this->assertEquals( false, $status->isOK(), 01097 "Cleaning dir $path failed ($backendName)." ); 01098 } 01099 } 01100 01101 public function testRecursiveClean() { 01102 $this->backend = $this->singleBackend; 01103 $this->doTestRecursiveClean(); 01104 $this->tearDownFiles(); 01105 01106 $this->backend = $this->multiBackend; 01107 $this->doTestRecursiveClean(); 01108 $this->tearDownFiles(); 01109 } 01110 01111 private function doTestRecursiveClean() { 01112 $backendName = $this->backendClass(); 01113 01114 $base = $this->baseStorePath(); 01115 $dirs = array( 01116 "$base/unittest-cont1/e/a", 01117 "$base/unittest-cont1/e/a/b", 01118 "$base/unittest-cont1/e/a/b/c", 01119 "$base/unittest-cont1/e/a/b/c/d0", 01120 "$base/unittest-cont1/e/a/b/c/d1", 01121 "$base/unittest-cont1/e/a/b/c/d2", 01122 "$base/unittest-cont1/e/a/b/c/d0/1", 01123 "$base/unittest-cont1/e/a/b/c/d0/2", 01124 "$base/unittest-cont1/e/a/b/c/d1/3", 01125 "$base/unittest-cont1/e/a/b/c/d1/4", 01126 "$base/unittest-cont1/e/a/b/c/d2/5", 01127 "$base/unittest-cont1/e/a/b/c/d2/6" 01128 ); 01129 foreach ( $dirs as $dir ) { 01130 $status = $this->prepare( array( 'dir' => $dir ) ); 01131 $this->assertGoodStatus( $status, 01132 "Preparing dir $dir succeeded without warnings ($backendName)." ); 01133 } 01134 01135 if ( $this->backend instanceof FSFileBackend ) { 01136 foreach ( $dirs as $dir ) { 01137 $this->assertEquals( true, $this->backend->directoryExists( array( 'dir' => $dir ) ), 01138 "Dir $dir exists ($backendName)." ); 01139 } 01140 } 01141 01142 $status = $this->backend->clean( 01143 array( 'dir' => "$base/unittest-cont1", 'recursive' => 1 ) ); 01144 $this->assertGoodStatus( $status, 01145 "Recursive cleaning of dir $dir succeeded without warnings ($backendName)." ); 01146 01147 foreach ( $dirs as $dir ) { 01148 $this->assertEquals( false, $this->backend->directoryExists( array( 'dir' => $dir ) ), 01149 "Dir $dir no longer exists ($backendName)." ); 01150 } 01151 } 01152 01153 // @TODO: testSecure 01154 01155 public function testDoOperations() { 01156 $this->backend = $this->singleBackend; 01157 $this->tearDownFiles(); 01158 $this->doTestDoOperations(); 01159 $this->tearDownFiles(); 01160 01161 $this->backend = $this->multiBackend; 01162 $this->tearDownFiles(); 01163 $this->doTestDoOperations(); 01164 $this->tearDownFiles(); 01165 } 01166 01167 private function doTestDoOperations() { 01168 $base = $this->baseStorePath(); 01169 01170 $fileA = "$base/unittest-cont1/e/a/b/fileA.txt"; 01171 $fileAContents = '3tqtmoeatmn4wg4qe-mg3qt3 tq'; 01172 $fileB = "$base/unittest-cont1/e/a/b/fileB.txt"; 01173 $fileBContents = 'g-jmq3gpqgt3qtg q3GT '; 01174 $fileC = "$base/unittest-cont1/e/a/b/fileC.txt"; 01175 $fileCContents = 'eigna[ogmewt 3qt g3qg flew[ag'; 01176 $fileD = "$base/unittest-cont1/e/a/b/fileD.txt"; 01177 01178 $this->prepare( array( 'dir' => dirname( $fileA ) ) ); 01179 $this->create( array( 'dst' => $fileA, 'content' => $fileAContents ) ); 01180 $this->prepare( array( 'dir' => dirname( $fileB ) ) ); 01181 $this->create( array( 'dst' => $fileB, 'content' => $fileBContents ) ); 01182 $this->prepare( array( 'dir' => dirname( $fileC ) ) ); 01183 $this->create( array( 'dst' => $fileC, 'content' => $fileCContents ) ); 01184 $this->prepare( array( 'dir' => dirname( $fileD ) ) ); 01185 01186 $status = $this->backend->doOperations( array( 01187 array( 'op' => 'copy', 'src' => $fileA, 'dst' => $fileC, 'overwrite' => 1 ), 01188 // Now: A:<A>, B:<B>, C:<A>, D:<empty> (file:<orginal contents>) 01189 array( 'op' => 'copy', 'src' => $fileC, 'dst' => $fileA, 'overwriteSame' => 1 ), 01190 // Now: A:<A>, B:<B>, C:<A>, D:<empty> 01191 array( 'op' => 'move', 'src' => $fileC, 'dst' => $fileD, 'overwrite' => 1 ), 01192 // Now: A:<A>, B:<B>, C:<empty>, D:<A> 01193 array( 'op' => 'move', 'src' => $fileB, 'dst' => $fileC ), 01194 // Now: A:<A>, B:<empty>, C:<B>, D:<A> 01195 array( 'op' => 'move', 'src' => $fileD, 'dst' => $fileA, 'overwriteSame' => 1 ), 01196 // Now: A:<A>, B:<empty>, C:<B>, D:<empty> 01197 array( 'op' => 'move', 'src' => $fileC, 'dst' => $fileA, 'overwrite' => 1 ), 01198 // Now: A:<B>, B:<empty>, C:<empty>, D:<empty> 01199 array( 'op' => 'copy', 'src' => $fileA, 'dst' => $fileC ), 01200 // Now: A:<B>, B:<empty>, C:<B>, D:<empty> 01201 array( 'op' => 'move', 'src' => $fileA, 'dst' => $fileC, 'overwriteSame' => 1 ), 01202 // Now: A:<empty>, B:<empty>, C:<B>, D:<empty> 01203 array( 'op' => 'copy', 'src' => $fileC, 'dst' => $fileC, 'overwrite' => 1 ), 01204 // Does nothing 01205 array( 'op' => 'copy', 'src' => $fileC, 'dst' => $fileC, 'overwriteSame' => 1 ), 01206 // Does nothing 01207 array( 'op' => 'move', 'src' => $fileC, 'dst' => $fileC, 'overwrite' => 1 ), 01208 // Does nothing 01209 array( 'op' => 'move', 'src' => $fileC, 'dst' => $fileC, 'overwriteSame' => 1 ), 01210 // Does nothing 01211 array( 'op' => 'null' ), 01212 // Does nothing 01213 ) ); 01214 01215 $this->assertGoodStatus( $status, "Operation batch succeeded" ); 01216 $this->assertEquals( true, $status->isOK(), "Operation batch succeeded" ); 01217 $this->assertEquals( 13, count( $status->success ), 01218 "Operation batch has correct success array" ); 01219 01220 $this->assertEquals( false, $this->backend->fileExists( array( 'src' => $fileA ) ), 01221 "File does not exist at $fileA" ); 01222 $this->assertEquals( false, $this->backend->fileExists( array( 'src' => $fileB ) ), 01223 "File does not exist at $fileB" ); 01224 $this->assertEquals( false, $this->backend->fileExists( array( 'src' => $fileD ) ), 01225 "File does not exist at $fileD" ); 01226 01227 $this->assertEquals( true, $this->backend->fileExists( array( 'src' => $fileC ) ), 01228 "File exists at $fileC" ); 01229 $this->assertEquals( $fileBContents, 01230 $this->backend->getFileContents( array( 'src' => $fileC ) ), 01231 "Correct file contents of $fileC" ); 01232 $this->assertEquals( strlen( $fileBContents ), 01233 $this->backend->getFileSize( array( 'src' => $fileC ) ), 01234 "Correct file size of $fileC" ); 01235 $this->assertEquals( wfBaseConvert( sha1( $fileBContents ), 16, 36, 31 ), 01236 $this->backend->getFileSha1Base36( array( 'src' => $fileC ) ), 01237 "Correct file SHA-1 of $fileC" ); 01238 } 01239 01240 public function testDoOperationsPipeline() { 01241 $this->backend = $this->singleBackend; 01242 $this->tearDownFiles(); 01243 $this->doTestDoOperationsPipeline(); 01244 $this->tearDownFiles(); 01245 01246 $this->backend = $this->multiBackend; 01247 $this->tearDownFiles(); 01248 $this->doTestDoOperationsPipeline(); 01249 $this->tearDownFiles(); 01250 } 01251 01252 // concurrency orientated 01253 private function doTestDoOperationsPipeline() { 01254 $base = $this->baseStorePath(); 01255 01256 $fileAContents = '3tqtmoeatmn4wg4qe-mg3qt3 tq'; 01257 $fileBContents = 'g-jmq3gpqgt3qtg q3GT '; 01258 $fileCContents = 'eigna[ogmewt 3qt g3qg flew[ag'; 01259 01260 $tmpNameA = TempFSFile::factory( "unittests_", 'txt' )->getPath(); 01261 file_put_contents( $tmpNameA, $fileAContents ); 01262 $tmpNameB = TempFSFile::factory( "unittests_", 'txt' )->getPath(); 01263 file_put_contents( $tmpNameB, $fileBContents ); 01264 $tmpNameC = TempFSFile::factory( "unittests_", 'txt' )->getPath(); 01265 file_put_contents( $tmpNameC, $fileCContents ); 01266 01267 $this->filesToPrune[] = $tmpNameA; # avoid file leaking 01268 $this->filesToPrune[] = $tmpNameB; # avoid file leaking 01269 $this->filesToPrune[] = $tmpNameC; # avoid file leaking 01270 01271 $fileA = "$base/unittest-cont1/e/a/b/fileA.txt"; 01272 $fileB = "$base/unittest-cont1/e/a/b/fileB.txt"; 01273 $fileC = "$base/unittest-cont1/e/a/b/fileC.txt"; 01274 $fileD = "$base/unittest-cont1/e/a/b/fileD.txt"; 01275 01276 $this->prepare( array( 'dir' => dirname( $fileA ) ) ); 01277 $this->create( array( 'dst' => $fileA, 'content' => $fileAContents ) ); 01278 $this->prepare( array( 'dir' => dirname( $fileB ) ) ); 01279 $this->prepare( array( 'dir' => dirname( $fileC ) ) ); 01280 $this->prepare( array( 'dir' => dirname( $fileD ) ) ); 01281 01282 $status = $this->backend->doOperations( array( 01283 array( 'op' => 'store', 'src' => $tmpNameA, 'dst' => $fileA, 'overwriteSame' => 1 ), 01284 array( 'op' => 'store', 'src' => $tmpNameB, 'dst' => $fileB, 'overwrite' => 1 ), 01285 array( 'op' => 'store', 'src' => $tmpNameC, 'dst' => $fileC, 'overwrite' => 1 ), 01286 array( 'op' => 'copy', 'src' => $fileA, 'dst' => $fileC, 'overwrite' => 1 ), 01287 // Now: A:<A>, B:<B>, C:<A>, D:<empty> (file:<orginal contents>) 01288 array( 'op' => 'copy', 'src' => $fileC, 'dst' => $fileA, 'overwriteSame' => 1 ), 01289 // Now: A:<A>, B:<B>, C:<A>, D:<empty> 01290 array( 'op' => 'move', 'src' => $fileC, 'dst' => $fileD, 'overwrite' => 1 ), 01291 // Now: A:<A>, B:<B>, C:<empty>, D:<A> 01292 array( 'op' => 'move', 'src' => $fileB, 'dst' => $fileC ), 01293 // Now: A:<A>, B:<empty>, C:<B>, D:<A> 01294 array( 'op' => 'move', 'src' => $fileD, 'dst' => $fileA, 'overwriteSame' => 1 ), 01295 // Now: A:<A>, B:<empty>, C:<B>, D:<empty> 01296 array( 'op' => 'move', 'src' => $fileC, 'dst' => $fileA, 'overwrite' => 1 ), 01297 // Now: A:<B>, B:<empty>, C:<empty>, D:<empty> 01298 array( 'op' => 'copy', 'src' => $fileA, 'dst' => $fileC ), 01299 // Now: A:<B>, B:<empty>, C:<B>, D:<empty> 01300 array( 'op' => 'move', 'src' => $fileA, 'dst' => $fileC, 'overwriteSame' => 1 ), 01301 // Now: A:<empty>, B:<empty>, C:<B>, D:<empty> 01302 array( 'op' => 'copy', 'src' => $fileC, 'dst' => $fileC, 'overwrite' => 1 ), 01303 // Does nothing 01304 array( 'op' => 'copy', 'src' => $fileC, 'dst' => $fileC, 'overwriteSame' => 1 ), 01305 // Does nothing 01306 array( 'op' => 'move', 'src' => $fileC, 'dst' => $fileC, 'overwrite' => 1 ), 01307 // Does nothing 01308 array( 'op' => 'move', 'src' => $fileC, 'dst' => $fileC, 'overwriteSame' => 1 ), 01309 // Does nothing 01310 array( 'op' => 'null' ), 01311 // Does nothing 01312 ) ); 01313 01314 $this->assertGoodStatus( $status, "Operation batch succeeded" ); 01315 $this->assertEquals( true, $status->isOK(), "Operation batch succeeded" ); 01316 $this->assertEquals( 16, count( $status->success ), 01317 "Operation batch has correct success array" ); 01318 01319 $this->assertEquals( false, $this->backend->fileExists( array( 'src' => $fileA ) ), 01320 "File does not exist at $fileA" ); 01321 $this->assertEquals( false, $this->backend->fileExists( array( 'src' => $fileB ) ), 01322 "File does not exist at $fileB" ); 01323 $this->assertEquals( false, $this->backend->fileExists( array( 'src' => $fileD ) ), 01324 "File does not exist at $fileD" ); 01325 01326 $this->assertEquals( true, $this->backend->fileExists( array( 'src' => $fileC ) ), 01327 "File exists at $fileC" ); 01328 $this->assertEquals( $fileBContents, 01329 $this->backend->getFileContents( array( 'src' => $fileC ) ), 01330 "Correct file contents of $fileC" ); 01331 $this->assertEquals( strlen( $fileBContents ), 01332 $this->backend->getFileSize( array( 'src' => $fileC ) ), 01333 "Correct file size of $fileC" ); 01334 $this->assertEquals( wfBaseConvert( sha1( $fileBContents ), 16, 36, 31 ), 01335 $this->backend->getFileSha1Base36( array( 'src' => $fileC ) ), 01336 "Correct file SHA-1 of $fileC" ); 01337 } 01338 01339 public function testDoOperationsFailing() { 01340 $this->backend = $this->singleBackend; 01341 $this->tearDownFiles(); 01342 $this->doTestDoOperationsFailing(); 01343 $this->tearDownFiles(); 01344 01345 $this->backend = $this->multiBackend; 01346 $this->tearDownFiles(); 01347 $this->doTestDoOperationsFailing(); 01348 $this->tearDownFiles(); 01349 } 01350 01351 private function doTestDoOperationsFailing() { 01352 $base = $this->baseStorePath(); 01353 01354 $fileA = "$base/unittest-cont2/a/b/fileA.txt"; 01355 $fileAContents = '3tqtmoeatmn4wg4qe-mg3qt3 tq'; 01356 $fileB = "$base/unittest-cont2/a/b/fileB.txt"; 01357 $fileBContents = 'g-jmq3gpqgt3qtg q3GT '; 01358 $fileC = "$base/unittest-cont2/a/b/fileC.txt"; 01359 $fileCContents = 'eigna[ogmewt 3qt g3qg flew[ag'; 01360 $fileD = "$base/unittest-cont2/a/b/fileD.txt"; 01361 01362 $this->prepare( array( 'dir' => dirname( $fileA ) ) ); 01363 $this->create( array( 'dst' => $fileA, 'content' => $fileAContents ) ); 01364 $this->prepare( array( 'dir' => dirname( $fileB ) ) ); 01365 $this->create( array( 'dst' => $fileB, 'content' => $fileBContents ) ); 01366 $this->prepare( array( 'dir' => dirname( $fileC ) ) ); 01367 $this->create( array( 'dst' => $fileC, 'content' => $fileCContents ) ); 01368 01369 $status = $this->backend->doOperations( array( 01370 array( 'op' => 'copy', 'src' => $fileA, 'dst' => $fileC, 'overwrite' => 1 ), 01371 // Now: A:<A>, B:<B>, C:<A>, D:<empty> (file:<orginal contents>) 01372 array( 'op' => 'copy', 'src' => $fileC, 'dst' => $fileA, 'overwriteSame' => 1 ), 01373 // Now: A:<A>, B:<B>, C:<A>, D:<empty> 01374 array( 'op' => 'copy', 'src' => $fileB, 'dst' => $fileD, 'overwrite' => 1 ), 01375 // Now: A:<A>, B:<B>, C:<A>, D:<B> 01376 array( 'op' => 'move', 'src' => $fileC, 'dst' => $fileD ), 01377 // Now: A:<A>, B:<B>, C:<A>, D:<empty> (failed) 01378 array( 'op' => 'move', 'src' => $fileB, 'dst' => $fileC, 'overwriteSame' => 1 ), 01379 // Now: A:<A>, B:<B>, C:<A>, D:<empty> (failed) 01380 array( 'op' => 'move', 'src' => $fileB, 'dst' => $fileA, 'overwrite' => 1 ), 01381 // Now: A:<B>, B:<empty>, C:<A>, D:<empty> 01382 array( 'op' => 'delete', 'src' => $fileD ), 01383 // Now: A:<B>, B:<empty>, C:<A>, D:<empty> 01384 array( 'op' => 'null' ), 01385 // Does nothing 01386 ), array( 'force' => 1 ) ); 01387 01388 $this->assertNotEquals( array(), $status->errors, "Operation had warnings" ); 01389 $this->assertEquals( true, $status->isOK(), "Operation batch succeeded" ); 01390 $this->assertEquals( 8, count( $status->success ), 01391 "Operation batch has correct success array" ); 01392 01393 $this->assertEquals( false, $this->backend->fileExists( array( 'src' => $fileB ) ), 01394 "File does not exist at $fileB" ); 01395 $this->assertEquals( false, $this->backend->fileExists( array( 'src' => $fileD ) ), 01396 "File does not exist at $fileD" ); 01397 01398 $this->assertEquals( true, $this->backend->fileExists( array( 'src' => $fileA ) ), 01399 "File does not exist at $fileA" ); 01400 $this->assertEquals( true, $this->backend->fileExists( array( 'src' => $fileC ) ), 01401 "File exists at $fileC" ); 01402 $this->assertEquals( $fileBContents, 01403 $this->backend->getFileContents( array( 'src' => $fileA ) ), 01404 "Correct file contents of $fileA" ); 01405 $this->assertEquals( strlen( $fileBContents ), 01406 $this->backend->getFileSize( array( 'src' => $fileA ) ), 01407 "Correct file size of $fileA" ); 01408 $this->assertEquals( wfBaseConvert( sha1( $fileBContents ), 16, 36, 31 ), 01409 $this->backend->getFileSha1Base36( array( 'src' => $fileA ) ), 01410 "Correct file SHA-1 of $fileA" ); 01411 } 01412 01413 public function testGetFileList() { 01414 $this->backend = $this->singleBackend; 01415 $this->tearDownFiles(); 01416 $this->doTestGetFileList(); 01417 $this->tearDownFiles(); 01418 01419 $this->backend = $this->multiBackend; 01420 $this->tearDownFiles(); 01421 $this->doTestGetFileList(); 01422 $this->tearDownFiles(); 01423 } 01424 01425 private function doTestGetFileList() { 01426 $backendName = $this->backendClass(); 01427 $base = $this->baseStorePath(); 01428 01429 // Should have no errors 01430 $iter = $this->backend->getFileList( array( 'dir' => "$base/unittest-cont-notexists" ) ); 01431 01432 $files = array( 01433 "$base/unittest-cont1/e/test1.txt", 01434 "$base/unittest-cont1/e/test2.txt", 01435 "$base/unittest-cont1/e/test3.txt", 01436 "$base/unittest-cont1/e/subdir1/test1.txt", 01437 "$base/unittest-cont1/e/subdir1/test2.txt", 01438 "$base/unittest-cont1/e/subdir2/test3.txt", 01439 "$base/unittest-cont1/e/subdir2/test4.txt", 01440 "$base/unittest-cont1/e/subdir2/subdir/test1.txt", 01441 "$base/unittest-cont1/e/subdir2/subdir/test2.txt", 01442 "$base/unittest-cont1/e/subdir2/subdir/test3.txt", 01443 "$base/unittest-cont1/e/subdir2/subdir/test4.txt", 01444 "$base/unittest-cont1/e/subdir2/subdir/test5.txt", 01445 "$base/unittest-cont1/e/subdir2/subdir/sub/test0.txt", 01446 "$base/unittest-cont1/e/subdir2/subdir/sub/120-px-file.txt", 01447 ); 01448 01449 // Add the files 01450 $ops = array(); 01451 foreach ( $files as $file ) { 01452 $this->prepare( array( 'dir' => dirname( $file ) ) ); 01453 $ops[] = array( 'op' => 'create', 'content' => 'xxy', 'dst' => $file ); 01454 } 01455 $status = $this->backend->doQuickOperations( $ops ); 01456 $this->assertGoodStatus( $status, 01457 "Creation of files succeeded ($backendName)." ); 01458 $this->assertEquals( true, $status->isOK(), 01459 "Creation of files succeeded with OK status ($backendName)." ); 01460 01461 // Expected listing 01462 $expected = array( 01463 "e/test1.txt", 01464 "e/test2.txt", 01465 "e/test3.txt", 01466 "e/subdir1/test1.txt", 01467 "e/subdir1/test2.txt", 01468 "e/subdir2/test3.txt", 01469 "e/subdir2/test4.txt", 01470 "e/subdir2/subdir/test1.txt", 01471 "e/subdir2/subdir/test2.txt", 01472 "e/subdir2/subdir/test3.txt", 01473 "e/subdir2/subdir/test4.txt", 01474 "e/subdir2/subdir/test5.txt", 01475 "e/subdir2/subdir/sub/test0.txt", 01476 "e/subdir2/subdir/sub/120-px-file.txt", 01477 ); 01478 sort( $expected ); 01479 01480 // Actual listing (no trailing slash) 01481 $list = array(); 01482 $iter = $this->backend->getFileList( array( 'dir' => "$base/unittest-cont1" ) ); 01483 foreach ( $iter as $file ) { 01484 $list[] = $file; 01485 } 01486 sort( $list ); 01487 01488 $this->assertEquals( $expected, $list, "Correct file listing ($backendName)." ); 01489 01490 // Actual listing (with trailing slash) 01491 $list = array(); 01492 $iter = $this->backend->getFileList( array( 'dir' => "$base/unittest-cont1/" ) ); 01493 foreach ( $iter as $file ) { 01494 $list[] = $file; 01495 } 01496 sort( $list ); 01497 01498 $this->assertEquals( $expected, $list, "Correct file listing ($backendName)." ); 01499 01500 // Expected listing 01501 $expected = array( 01502 "test1.txt", 01503 "test2.txt", 01504 "test3.txt", 01505 "test4.txt", 01506 "test5.txt", 01507 "sub/test0.txt", 01508 "sub/120-px-file.txt", 01509 ); 01510 sort( $expected ); 01511 01512 // Actual listing (no trailing slash) 01513 $list = array(); 01514 $iter = $this->backend->getFileList( array( 'dir' => "$base/unittest-cont1/e/subdir2/subdir" ) ); 01515 foreach ( $iter as $file ) { 01516 $list[] = $file; 01517 } 01518 sort( $list ); 01519 01520 $this->assertEquals( $expected, $list, "Correct file listing ($backendName)." ); 01521 01522 // Actual listing (with trailing slash) 01523 $list = array(); 01524 $iter = $this->backend->getFileList( array( 'dir' => "$base/unittest-cont1/e/subdir2/subdir/" ) ); 01525 foreach ( $iter as $file ) { 01526 $list[] = $file; 01527 } 01528 sort( $list ); 01529 01530 $this->assertEquals( $expected, $list, "Correct file listing ($backendName)." ); 01531 01532 // Actual listing (using iterator second time) 01533 $list = array(); 01534 foreach ( $iter as $file ) { 01535 $list[] = $file; 01536 } 01537 sort( $list ); 01538 01539 $this->assertEquals( $expected, $list, "Correct file listing ($backendName), second iteration." ); 01540 01541 // Expected listing (top files only) 01542 $expected = array( 01543 "test1.txt", 01544 "test2.txt", 01545 "test3.txt", 01546 "test4.txt", 01547 "test5.txt" 01548 ); 01549 sort( $expected ); 01550 01551 // Actual listing (top files only) 01552 $list = array(); 01553 $iter = $this->backend->getTopFileList( array( 'dir' => "$base/unittest-cont1/e/subdir2/subdir" ) ); 01554 foreach ( $iter as $file ) { 01555 $list[] = $file; 01556 } 01557 sort( $list ); 01558 01559 $this->assertEquals( $expected, $list, "Correct top file listing ($backendName)." ); 01560 01561 foreach ( $files as $file ) { // clean up 01562 $this->backend->doOperation( array( 'op' => 'delete', 'src' => $file ) ); 01563 } 01564 01565 $iter = $this->backend->getFileList( array( 'dir' => "$base/unittest-cont1/not/exists" ) ); 01566 foreach ( $iter as $iter ) {} // no errors 01567 } 01568 01569 public function testGetDirectoryList() { 01570 $this->backend = $this->singleBackend; 01571 $this->tearDownFiles(); 01572 $this->doTestGetDirectoryList(); 01573 $this->tearDownFiles(); 01574 01575 $this->backend = $this->multiBackend; 01576 $this->tearDownFiles(); 01577 $this->doTestGetDirectoryList(); 01578 $this->tearDownFiles(); 01579 } 01580 01581 private function doTestGetDirectoryList() { 01582 $backendName = $this->backendClass(); 01583 01584 $base = $this->baseStorePath(); 01585 $files = array( 01586 "$base/unittest-cont1/e/test1.txt", 01587 "$base/unittest-cont1/e/test2.txt", 01588 "$base/unittest-cont1/e/test3.txt", 01589 "$base/unittest-cont1/e/subdir1/test1.txt", 01590 "$base/unittest-cont1/e/subdir1/test2.txt", 01591 "$base/unittest-cont1/e/subdir2/test3.txt", 01592 "$base/unittest-cont1/e/subdir2/test4.txt", 01593 "$base/unittest-cont1/e/subdir2/subdir/test1.txt", 01594 "$base/unittest-cont1/e/subdir3/subdir/test2.txt", 01595 "$base/unittest-cont1/e/subdir4/subdir/test3.txt", 01596 "$base/unittest-cont1/e/subdir4/subdir/test4.txt", 01597 "$base/unittest-cont1/e/subdir4/subdir/test5.txt", 01598 "$base/unittest-cont1/e/subdir4/subdir/sub/test0.txt", 01599 "$base/unittest-cont1/e/subdir4/subdir/sub/120-px-file.txt", 01600 ); 01601 01602 // Add the files 01603 $ops = array(); 01604 foreach ( $files as $file ) { 01605 $this->prepare( array( 'dir' => dirname( $file ) ) ); 01606 $ops[] = array( 'op' => 'create', 'content' => 'xxy', 'dst' => $file ); 01607 } 01608 $status = $this->backend->doQuickOperations( $ops ); 01609 $this->assertGoodStatus( $status, 01610 "Creation of files succeeded ($backendName)." ); 01611 $this->assertEquals( true, $status->isOK(), 01612 "Creation of files succeeded with OK status ($backendName)." ); 01613 01614 $this->assertEquals( true, 01615 $this->backend->directoryExists( array( 'dir' => "$base/unittest-cont1/e/subdir1" ) ), 01616 "Directory exists in ($backendName)." ); 01617 $this->assertEquals( true, 01618 $this->backend->directoryExists( array( 'dir' => "$base/unittest-cont1/e/subdir2/subdir" ) ), 01619 "Directory exists in ($backendName)." ); 01620 $this->assertEquals( false, 01621 $this->backend->directoryExists( array( 'dir' => "$base/unittest-cont1/e/subdir2/test1.txt" ) ), 01622 "Directory does not exists in ($backendName)." ); 01623 01624 // Expected listing 01625 $expected = array( 01626 "e", 01627 ); 01628 sort( $expected ); 01629 01630 // Actual listing (no trailing slash) 01631 $list = array(); 01632 $iter = $this->backend->getTopDirectoryList( array( 'dir' => "$base/unittest-cont1" ) ); 01633 foreach ( $iter as $file ) { 01634 $list[] = $file; 01635 } 01636 sort( $list ); 01637 01638 $this->assertEquals( $expected, $list, "Correct top dir listing ($backendName)." ); 01639 01640 // Expected listing 01641 $expected = array( 01642 "subdir1", 01643 "subdir2", 01644 "subdir3", 01645 "subdir4", 01646 ); 01647 sort( $expected ); 01648 01649 // Actual listing (no trailing slash) 01650 $list = array(); 01651 $iter = $this->backend->getTopDirectoryList( array( 'dir' => "$base/unittest-cont1/e" ) ); 01652 foreach ( $iter as $file ) { 01653 $list[] = $file; 01654 } 01655 sort( $list ); 01656 01657 $this->assertEquals( $expected, $list, "Correct top dir listing ($backendName)." ); 01658 01659 // Actual listing (with trailing slash) 01660 $list = array(); 01661 $iter = $this->backend->getTopDirectoryList( array( 'dir' => "$base/unittest-cont1/e/" ) ); 01662 foreach ( $iter as $file ) { 01663 $list[] = $file; 01664 } 01665 sort( $list ); 01666 01667 $this->assertEquals( $expected, $list, "Correct top dir listing ($backendName)." ); 01668 01669 // Expected listing 01670 $expected = array( 01671 "subdir", 01672 ); 01673 sort( $expected ); 01674 01675 // Actual listing (no trailing slash) 01676 $list = array(); 01677 $iter = $this->backend->getTopDirectoryList( array( 'dir' => "$base/unittest-cont1/e/subdir2" ) ); 01678 foreach ( $iter as $file ) { 01679 $list[] = $file; 01680 } 01681 sort( $list ); 01682 01683 $this->assertEquals( $expected, $list, "Correct top dir listing ($backendName)." ); 01684 01685 // Actual listing (with trailing slash) 01686 $list = array(); 01687 $iter = $this->backend->getTopDirectoryList( array( 'dir' => "$base/unittest-cont1/e/subdir2/" ) ); 01688 foreach ( $iter as $file ) { 01689 $list[] = $file; 01690 } 01691 sort( $list ); 01692 01693 $this->assertEquals( $expected, $list, "Correct top dir listing ($backendName)." ); 01694 01695 // Actual listing (using iterator second time) 01696 $list = array(); 01697 foreach ( $iter as $file ) { 01698 $list[] = $file; 01699 } 01700 sort( $list ); 01701 01702 $this->assertEquals( $expected, $list, "Correct top dir listing ($backendName), second iteration." ); 01703 01704 // Expected listing (recursive) 01705 $expected = array( 01706 "e", 01707 "e/subdir1", 01708 "e/subdir2", 01709 "e/subdir3", 01710 "e/subdir4", 01711 "e/subdir2/subdir", 01712 "e/subdir3/subdir", 01713 "e/subdir4/subdir", 01714 "e/subdir4/subdir/sub", 01715 ); 01716 sort( $expected ); 01717 01718 // Actual listing (recursive) 01719 $list = array(); 01720 $iter = $this->backend->getDirectoryList( array( 'dir' => "$base/unittest-cont1/" ) ); 01721 foreach ( $iter as $file ) { 01722 $list[] = $file; 01723 } 01724 sort( $list ); 01725 01726 $this->assertEquals( $expected, $list, "Correct dir listing ($backendName)." ); 01727 01728 // Expected listing (recursive) 01729 $expected = array( 01730 "subdir", 01731 "subdir/sub", 01732 ); 01733 sort( $expected ); 01734 01735 // Actual listing (recursive) 01736 $list = array(); 01737 $iter = $this->backend->getDirectoryList( array( 'dir' => "$base/unittest-cont1/e/subdir4" ) ); 01738 foreach ( $iter as $file ) { 01739 $list[] = $file; 01740 } 01741 sort( $list ); 01742 01743 $this->assertEquals( $expected, $list, "Correct dir listing ($backendName)." ); 01744 01745 // Actual listing (recursive, second time) 01746 $list = array(); 01747 foreach ( $iter as $file ) { 01748 $list[] = $file; 01749 } 01750 sort( $list ); 01751 01752 $this->assertEquals( $expected, $list, "Correct dir listing ($backendName)." ); 01753 01754 foreach ( $files as $file ) { // clean up 01755 $this->backend->doOperation( array( 'op' => 'delete', 'src' => $file ) ); 01756 } 01757 01758 $iter = $this->backend->getDirectoryList( array( 'dir' => "$base/unittest-cont1/not/exists" ) ); 01759 foreach ( $iter as $iter ) {} // no errors 01760 } 01761 01762 public function testLockCalls() { 01763 $this->backend = $this->singleBackend; 01764 $this->doTestLockCalls(); 01765 } 01766 01767 private function doTestLockCalls() { 01768 $backendName = $this->backendClass(); 01769 01770 for ( $i=0; $i<50; $i++ ) { 01771 $paths = array( 01772 "test1.txt", 01773 "test2.txt", 01774 "test3.txt", 01775 "subdir1", 01776 "subdir1", // duplicate 01777 "subdir1/test1.txt", 01778 "subdir1/test2.txt", 01779 "subdir2", 01780 "subdir2", // duplicate 01781 "subdir2/test3.txt", 01782 "subdir2/test4.txt", 01783 "subdir2/subdir", 01784 "subdir2/subdir/test1.txt", 01785 "subdir2/subdir/test2.txt", 01786 "subdir2/subdir/test3.txt", 01787 "subdir2/subdir/test4.txt", 01788 "subdir2/subdir/test5.txt", 01789 "subdir2/subdir/sub", 01790 "subdir2/subdir/sub/test0.txt", 01791 "subdir2/subdir/sub/120-px-file.txt", 01792 ); 01793 01794 $status = $this->backend->lockFiles( $paths, LockManager::LOCK_EX ); 01795 $this->assertEquals( array(), $status->errors, 01796 "Locking of files succeeded ($backendName)." ); 01797 $this->assertEquals( true, $status->isOK(), 01798 "Locking of files succeeded with OK status ($backendName)." ); 01799 01800 $status = $this->backend->lockFiles( $paths, LockManager::LOCK_SH ); 01801 $this->assertEquals( array(), $status->errors, 01802 "Locking of files succeeded ($backendName)." ); 01803 $this->assertEquals( true, $status->isOK(), 01804 "Locking of files succeeded with OK status ($backendName)." ); 01805 01806 $status = $this->backend->unlockFiles( $paths, LockManager::LOCK_SH ); 01807 $this->assertEquals( array(), $status->errors, 01808 "Locking of files succeeded ($backendName)." ); 01809 $this->assertEquals( true, $status->isOK(), 01810 "Locking of files succeeded with OK status ($backendName)." ); 01811 01812 $status = $this->backend->unlockFiles( $paths, LockManager::LOCK_EX ); 01813 $this->assertEquals( array(), $status->errors, 01814 "Locking of files succeeded ($backendName)." ); 01815 $this->assertEquals( true, $status->isOK(), 01816 "Locking of files succeeded with OK status ($backendName)." ); 01817 } 01818 } 01819 01820 // test helper wrapper for backend prepare() function 01821 private function prepare( array $params ) { 01822 return $this->backend->prepare( $params ); 01823 } 01824 01825 // test helper wrapper for backend prepare() function 01826 private function create( array $params ) { 01827 $params['op'] = 'create'; 01828 return $this->backend->doQuickOperations( array( $params ) ); 01829 } 01830 01831 function tearDownFiles() { 01832 foreach ( $this->filesToPrune as $file ) { 01833 @unlink( $file ); 01834 } 01835 $containers = array( 'unittest-cont1', 'unittest-cont2', 'unittest-cont3' ); 01836 foreach ( $containers as $container ) { 01837 $this->deleteFiles( $container ); 01838 } 01839 $this->filesToPrune = array(); 01840 } 01841 01842 private function deleteFiles( $container ) { 01843 $base = $this->baseStorePath(); 01844 $iter = $this->backend->getFileList( array( 'dir' => "$base/$container" ) ); 01845 if ( $iter ) { 01846 foreach ( $iter as $file ) { 01847 $this->backend->delete( array( 'src' => "$base/$container/$file" ), 01848 array( 'force' => 1, 'nonLocking' => 1 ) ); 01849 } 01850 } 01851 $this->backend->clean( array( 'dir' => "$base/$container", 'recursive' => 1 ) ); 01852 } 01853 01854 function assertBackendPathsConsistent( array $paths ) { 01855 if ( $this->backend instanceof FileBackendMultiWrite ) { 01856 $status = $this->backend->consistencyCheck( $paths ); 01857 $this->assertGoodStatus( $status, "Files synced: " . implode( ',', $paths ) ); 01858 } 01859 } 01860 01861 function assertGoodStatus( $status, $msg ) { 01862 $this->assertEquals( print_r( array(), 1 ), print_r( $status->errors, 1 ), $msg ); 01863 } 01864 01865 function tearDown() { 01866 parent::tearDown(); 01867 } 01868 }