9 * n.b. Ensure that you can write to the images/ directory as the
10 * user that will run tests.
13 // Note for reviewers: this intentionally duplicates functionality already in "ApiSetup" and so on.
14 // This framework works better IMO and has less strangeness (such as test cases inheriting from "ApiSetup"...)
15 // (and in the case of the other Upload tests, this flat out just actually works... )
17 // TODO: port the other Upload tests, and other API tests to this framework
19 require_once( 'ApiTestCaseUpload.php' );
24 * Broken test, reports false errors from time to time.
25 * See https://bugzilla.wikimedia.org/26169
27 * This is pretty sucky... needs to be prettified.
29 class ApiUploadTest
extends ApiTestCaseUpload
{
33 * XXX this is a funny way of getting session context
35 function testLogin() {
36 $user = self
::$users['uploader'];
40 'lgname' => $user->username
,
41 'lgpassword' => $user->password
43 list( $result, , $session ) = $this->doApiRequest( $params );
44 $this->assertArrayHasKey( "login", $result );
45 $this->assertArrayHasKey( "result", $result['login'] );
46 $this->assertEquals( "NeedToken", $result['login']['result'] );
47 $token = $result['login']['token'];
52 'lgname' => $user->username
,
53 'lgpassword' => $user->password
55 list( $result, , $session ) = $this->doApiRequest( $params, $session );
56 $this->assertArrayHasKey( "login", $result );
57 $this->assertArrayHasKey( "result", $result['login'] );
58 $this->assertEquals( "Success", $result['login']['result'] );
59 $this->assertArrayHasKey( 'lgtoken', $result['login'] );
61 $this->assertNotEmpty( $session, 'API Login must return a session' );
69 public function testUploadRequiresToken( $session ) {
72 $this->doApiRequest( array(
75 } catch ( UsageException
$e ) {
77 $this->assertEquals( "The token parameter must be set", $e->getMessage() );
79 $this->assertTrue( $exception, "Got exception" );
85 public function testUploadMissingParams( $session ) {
88 $this->doApiRequestWithToken( array(
90 ), $session, self
::$users['uploader']->user
);
91 } catch ( UsageException
$e ) {
93 $this->assertEquals( "One of the parameters filekey, file, url, statuskey is required",
96 $this->assertTrue( $exception, "Got exception" );
103 public function testUpload( $session ) {
105 $mimeType = 'image/png';
108 $randomImageGenerator = new RandomImageGenerator();
109 $filePaths = $randomImageGenerator->writeImages( 1, $extension, wfTempDir() );
111 catch ( Exception
$e ) {
112 $this->markTestIncomplete( $e->getMessage() );
115 $filePath = $filePaths[0];
116 $fileSize = filesize( $filePath );
117 $fileName = basename( $filePath );
119 $this->deleteFileByFileName( $fileName );
120 $this->deleteFileByContent( $filePath );
123 if (! $this->fakeUploadFile( 'file', $fileName, $mimeType, $filePath ) ) {
124 $this->markTestIncomplete( "Couldn't upload file!\n" );
128 'action' => 'upload',
129 'filename' => $fileName,
130 'file' => 'dummy content',
131 'comment' => 'dummy comment',
132 'text' => "This is the page text for $fileName",
137 list( $result, , ) = $this->doApiRequestWithToken( $params, $session,
138 self
::$users['uploader']->user
);
139 } catch ( UsageException
$e ) {
142 $this->assertTrue( isset( $result['upload'] ) );
143 $this->assertEquals( 'Success', $result['upload']['result'] );
144 $this->assertEquals( $fileSize, ( int )$result['upload']['imageinfo']['size'] );
145 $this->assertEquals( $mimeType, $result['upload']['imageinfo']['mime'] );
146 $this->assertFalse( $exception );
149 $this->deleteFileByFilename( $fileName );
157 public function testUploadZeroLength( $session ) {
158 $mimeType = 'image/png';
160 $filePath = tempnam( wfTempDir(), "" );
161 $fileName = "apiTestUploadZeroLength.png";
163 $this->deleteFileByFileName( $fileName );
165 if (! $this->fakeUploadFile( 'file', $fileName, $mimeType, $filePath ) ) {
166 $this->markTestIncomplete( "Couldn't upload file!\n" );
170 'action' => 'upload',
171 'filename' => $fileName,
172 'file' => 'dummy content',
173 'comment' => 'dummy comment',
174 'text' => "This is the page text for $fileName",
179 $this->doApiRequestWithToken( $params, $session, self
::$users['uploader']->user
);
180 } catch ( UsageException
$e ) {
181 $this->assertContains( 'The file you submitted was empty', $e->getMessage() );
184 $this->assertTrue( $exception );
187 $this->deleteFileByFilename( $fileName );
195 public function testUploadSameFileName( $session ) {
197 $mimeType = 'image/png';
200 $randomImageGenerator = new RandomImageGenerator();
201 $filePaths = $randomImageGenerator->writeImages( 2, $extension, wfTempDir() );
203 catch ( Exception
$e ) {
204 $this->markTestIncomplete( $e->getMessage() );
207 // we'll reuse this filename
208 $fileName = basename( $filePaths[0] );
210 // clear any other files with the same name
211 $this->deleteFileByFileName( $fileName );
213 // we reuse these params
215 'action' => 'upload',
216 'filename' => $fileName,
217 'file' => 'dummy content',
218 'comment' => 'dummy comment',
219 'text' => "This is the page text for $fileName",
222 // first upload .... should succeed
224 if (! $this->fakeUploadFile( 'file', $fileName, $mimeType, $filePaths[0] ) ) {
225 $this->markTestIncomplete( "Couldn't upload file!\n" );
230 list( $result, , $session ) = $this->doApiRequestWithToken( $params, $session,
231 self
::$users['uploader']->user
);
232 } catch ( UsageException
$e ) {
235 $this->assertTrue( isset( $result['upload'] ) );
236 $this->assertEquals( 'Success', $result['upload']['result'] );
237 $this->assertFalse( $exception );
239 // second upload with the same name (but different content)
241 if (! $this->fakeUploadFile( 'file', $fileName, $mimeType, $filePaths[1] ) ) {
242 $this->markTestIncomplete( "Couldn't upload file!\n" );
247 list( $result, , ) = $this->doApiRequestWithToken( $params, $session,
248 self
::$users['uploader']->user
); // FIXME: leaks a temporary file
249 } catch ( UsageException
$e ) {
252 $this->assertTrue( isset( $result['upload'] ) );
253 $this->assertEquals( 'Warning', $result['upload']['result'] );
254 $this->assertTrue( isset( $result['upload']['warnings'] ) );
255 $this->assertTrue( isset( $result['upload']['warnings']['exists'] ) );
256 $this->assertFalse( $exception );
259 $this->deleteFileByFilename( $fileName );
260 unlink( $filePaths[0] );
261 unlink( $filePaths[1] );
268 public function testUploadSameContent( $session ) {
270 $mimeType = 'image/png';
273 $randomImageGenerator = new RandomImageGenerator();
274 $filePaths = $randomImageGenerator->writeImages( 1, $extension, wfTempDir() );
276 catch ( Exception
$e ) {
277 $this->markTestIncomplete( $e->getMessage() );
280 $fileNames[0] = basename( $filePaths[0] );
281 $fileNames[1] = "SameContentAs" . $fileNames[0];
283 // clear any other files with the same name or content
284 $this->deleteFileByContent( $filePaths[0] );
285 $this->deleteFileByFileName( $fileNames[0] );
286 $this->deleteFileByFileName( $fileNames[1] );
288 // first upload .... should succeed
291 'action' => 'upload',
292 'filename' => $fileNames[0],
293 'file' => 'dummy content',
294 'comment' => 'dummy comment',
295 'text' => "This is the page text for " . $fileNames[0],
298 if (! $this->fakeUploadFile( 'file', $fileNames[0], $mimeType, $filePaths[0] ) ) {
299 $this->markTestIncomplete( "Couldn't upload file!\n" );
304 list( $result, $request, $session ) = $this->doApiRequestWithToken( $params, $session,
305 self
::$users['uploader']->user
);
306 } catch ( UsageException
$e ) {
309 $this->assertTrue( isset( $result['upload'] ) );
310 $this->assertEquals( 'Success', $result['upload']['result'] );
311 $this->assertFalse( $exception );
314 // second upload with the same content (but different name)
316 if (! $this->fakeUploadFile( 'file', $fileNames[1], $mimeType, $filePaths[0] ) ) {
317 $this->markTestIncomplete( "Couldn't upload file!\n" );
321 'action' => 'upload',
322 'filename' => $fileNames[1],
323 'file' => 'dummy content',
324 'comment' => 'dummy comment',
325 'text' => "This is the page text for " . $fileNames[1],
330 list( $result, $request, $session ) = $this->doApiRequestWithToken( $params, $session,
331 self
::$users['uploader']->user
); // FIXME: leaks a temporary file
332 } catch ( UsageException
$e ) {
335 $this->assertTrue( isset( $result['upload'] ) );
336 $this->assertEquals( 'Warning', $result['upload']['result'] );
337 $this->assertTrue( isset( $result['upload']['warnings'] ) );
338 $this->assertTrue( isset( $result['upload']['warnings']['duplicate'] ) );
339 $this->assertFalse( $exception );
342 $this->deleteFileByFilename( $fileNames[0] );
343 $this->deleteFileByFilename( $fileNames[1] );
344 unlink( $filePaths[0] );
351 public function testUploadStash( $session ) {
352 $this->setMwGlobals( array(
353 'wgUser' => self
::$users['uploader']->user
, // @todo FIXME: still used somewhere
357 $mimeType = 'image/png';
360 $randomImageGenerator = new RandomImageGenerator();
361 $filePaths = $randomImageGenerator->writeImages( 1, $extension, wfTempDir() );
363 catch ( Exception
$e ) {
364 $this->markTestIncomplete( $e->getMessage() );
367 $filePath = $filePaths[0];
368 $fileSize = filesize( $filePath );
369 $fileName = basename( $filePath );
371 $this->deleteFileByFileName( $fileName );
372 $this->deleteFileByContent( $filePath );
374 if (! $this->fakeUploadFile( 'file', $fileName, $mimeType, $filePath ) ) {
375 $this->markTestIncomplete( "Couldn't upload file!\n" );
379 'action' => 'upload',
381 'filename' => $fileName,
382 'file' => 'dummy content',
383 'comment' => 'dummy comment',
384 'text' => "This is the page text for $fileName",
389 list( $result, $request, $session ) = $this->doApiRequestWithToken( $params, $session,
390 self
::$users['uploader']->user
); // FIXME: leaks a temporary file
391 } catch ( UsageException
$e ) {
394 $this->assertFalse( $exception );
395 $this->assertTrue( isset( $result['upload'] ) );
396 $this->assertEquals( 'Success', $result['upload']['result'] );
397 $this->assertEquals( $fileSize, ( int )$result['upload']['imageinfo']['size'] );
398 $this->assertEquals( $mimeType, $result['upload']['imageinfo']['mime'] );
399 $this->assertTrue( isset( $result['upload']['filekey'] ) );
400 $this->assertEquals( $result['upload']['sessionkey'], $result['upload']['filekey'] );
401 $filekey = $result['upload']['filekey'];
403 // it should be visible from Special:UploadStash
404 // XXX ...but how to test this, with a fake WebRequest with the session?
406 // now we should try to release the file from stash
408 'action' => 'upload',
409 'filekey' => $filekey,
410 'filename' => $fileName,
411 'comment' => 'dummy comment',
412 'text' => "This is the page text for $fileName, altered",
415 $this->clearFakeUploads();
418 list( $result, $request, $session ) = $this->doApiRequestWithToken( $params, $session,
419 self
::$users['uploader']->user
);
420 } catch ( UsageException
$e ) {
423 $this->assertTrue( isset( $result['upload'] ) );
424 $this->assertEquals( 'Success', $result['upload']['result'] );
425 $this->assertFalse( $exception, "No UsageException exception." );
428 $this->deleteFileByFilename( $fileName );
436 public function testUploadChunks( $session ) {
437 $this->setMwGlobals( array(
438 'wgUser' => self
::$users['uploader']->user
, // @todo FIXME: still used somewhere
441 $chunkSize = 1048576;
442 // Download a large image file
443 // ( using RandomImageGenerator for large files is not stable )
444 $mimeType = 'image/jpeg';
445 $url = 'http://upload.wikimedia.org/wikipedia/commons/e/ed/Oberaargletscher_from_Oberaar%2C_2010_07.JPG';
446 $filePath = wfTempDir() . '/Oberaargletscher_from_Oberaar.jpg';
448 // Only download if the file is not avaliable in the temp location:
449 if( !is_file( $filePath ) ){
450 copy($url, $filePath);
453 catch ( Exception
$e ) {
454 $this->markTestIncomplete( $e->getMessage() );
457 $fileSize = filesize( $filePath );
458 $fileName = basename( $filePath );
460 $this->deleteFileByFileName( $fileName );
461 $this->deleteFileByContent( $filePath );
463 // Base upload params:
465 'action' => 'upload',
467 'filename' => $fileName,
468 'filesize' => $fileSize,
473 $chunkSessionKey = false;
476 $handle = @fopen
($filePath, "r");
477 if( $handle === false ){
478 $this->markTestIncomplete( "could not open file: $filePath" );
480 while (!feof ($handle)) {
481 // Get the current chunk
482 $chunkData = @fread
( $handle, $chunkSize );
484 // Upload the current chunk into the $_FILE object:
485 $this->fakeUploadChunk( 'chunk', 'blob', $mimeType, $chunkData );
487 // Check for chunkSessionKey
488 if( !$chunkSessionKey ){
489 // Upload fist chunk ( and get the session key )
491 list( $result, $request, $session ) = $this->doApiRequestWithToken( $params, $session,
492 self
::$users['uploader']->user
);
493 } catch ( UsageException
$e ) {
494 $this->markTestIncomplete( $e->getMessage() );
496 // Make sure we got a valid chunk continue:
497 $this->assertTrue( isset( $result['upload'] ) );
498 $this->assertTrue( isset( $result['upload']['filekey'] ) );
499 // If we don't get a session key mark test incomplete.
500 if( ! isset( $result['upload']['filekey'] ) ){
501 $this->markTestIncomplete( "no filekey provided" );
503 $chunkSessionKey = $result['upload']['filekey'];
504 $this->assertEquals( 'Continue', $result['upload']['result'] );
505 // First chunk should have chunkSize == offset
506 $this->assertEquals( $chunkSize, $result['upload']['offset'] );
507 $resultOffset = $result['upload']['offset'];
510 // Filekey set to chunk session
511 $params['filekey'] = $chunkSessionKey;
512 // Update the offset ( always add chunkSize for subquent chunks should be in-sync with $result['upload']['offset'] )
513 $params['offset'] +
= $chunkSize;
514 // Make sure param offset is insync with resultOffset:
515 $this->assertEquals( $resultOffset, $params['offset'] );
516 // Upload current chunk
518 list( $result, $request, $session ) = $this->doApiRequestWithToken( $params, $session,
519 self
::$users['uploader']->user
);
520 } catch ( UsageException
$e ) {
521 $this->markTestIncomplete( $e->getMessage() );
523 // Make sure we got a valid chunk continue:
524 $this->assertTrue( isset( $result['upload'] ) );
525 $this->assertTrue( isset( $result['upload']['filekey'] ) );
527 // Check if we were on the last chunk:
528 if( $params['offset'] +
$chunkSize >= $fileSize ){
529 $this->assertEquals( 'Success', $result['upload']['result'] );
532 $this->assertEquals( 'Continue', $result['upload']['result'] );
533 // update $resultOffset
534 $resultOffset = $result['upload']['offset'];
539 // Check that we got a valid file result:
540 wfDebug( __METHOD__
. " hohoh filesize {$fileSize} info {$result['upload']['imageinfo']['size']}\n\n");
541 $this->assertEquals( $fileSize, $result['upload']['imageinfo']['size'] );
542 $this->assertEquals( $mimeType, $result['upload']['imageinfo']['mime'] );
543 $this->assertTrue( isset( $result['upload']['filekey'] ) );
544 $filekey = $result['upload']['filekey'];
546 // Now we should try to release the file from stash
548 'action' => 'upload',
549 'filekey' => $filekey,
550 'filename' => $fileName,
551 'comment' => 'dummy comment',
552 'text' => "This is the page text for $fileName, altered",
554 $this->clearFakeUploads();
557 list( $result, $request, $session ) = $this->doApiRequestWithToken( $params, $session,
558 self
::$users['uploader']->user
);
559 } catch ( UsageException
$e ) {
562 $this->assertTrue( isset( $result['upload'] ) );
563 $this->assertEquals( 'Success', $result['upload']['result'] );
564 $this->assertFalse( $exception );
567 $this->deleteFileByFilename( $fileName );
568 // don't remove downloaded temporary file for fast subquent tests.
569 //unlink( $filePath );