Index: trunk/phase3/tests/phpunit/includes/api/ApiTestCaseUpload.php |
— | — | @@ -0,0 +1,128 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +/** |
| 5 | + * * Abstract class to support upload tests |
| 6 | + */ |
| 7 | +require_once( 'ApiTestUser.php' ); |
| 8 | +require_once( 'ApiTestCase.php' ); |
| 9 | + |
| 10 | +abstract class ApiTestCaseUpload extends ApiTestCase { |
| 11 | + /** |
| 12 | + * Fixture -- run before every test |
| 13 | + */ |
| 14 | + public function setUp() { |
| 15 | + global $wgEnableUploads, $wgEnableAPI; |
| 16 | + parent::setUp(); |
| 17 | + |
| 18 | + $wgEnableUploads = true; |
| 19 | + $wgEnableAPI = true; |
| 20 | + wfSetupSession(); |
| 21 | + |
| 22 | + ini_set( 'log_errors', 1 ); |
| 23 | + ini_set( 'error_reporting', 1 ); |
| 24 | + ini_set( 'display_errors', 1 ); |
| 25 | + |
| 26 | + $this->clearFakeUploads(); |
| 27 | + } |
| 28 | + |
| 29 | + /** |
| 30 | + * Fixture -- run after every test |
| 31 | + * Clean up temporary files etc. |
| 32 | + */ |
| 33 | + function tearDown() { |
| 34 | + } |
| 35 | + |
| 36 | + |
| 37 | + /** |
| 38 | + * Helper function -- remove files and associated articles by Title |
| 39 | + * @param $title Title: title to be removed |
| 40 | + */ |
| 41 | + public function deleteFileByTitle( $title ) { |
| 42 | + if ( $title->exists() ) { |
| 43 | + $file = wfFindFile( $title, array( 'ignoreRedirect' => true ) ); |
| 44 | + $noOldArchive = ""; // yes this really needs to be set this way |
| 45 | + $comment = "removing for test"; |
| 46 | + $restrictDeletedVersions = false; |
| 47 | + $status = FileDeleteForm::doDelete( $title, $file, $noOldArchive, $comment, $restrictDeletedVersions ); |
| 48 | + if ( !$status->isGood() ) { |
| 49 | + return false; |
| 50 | + } |
| 51 | + $article = new Article( $title ); |
| 52 | + $article->doDeleteArticle( "removing for test" ); |
| 53 | + |
| 54 | + // see if it now doesn't exist; reload |
| 55 | + $title = Title::newFromText( $fileName, NS_FILE ); |
| 56 | + } |
| 57 | + return ! ( $title && $title instanceof Title && $title->exists() ); |
| 58 | + } |
| 59 | + |
| 60 | + /** |
| 61 | + * Helper function -- remove files and associated articles with a particular filename |
| 62 | + * @param $fileName String: filename to be removed |
| 63 | + */ |
| 64 | + public function deleteFileByFileName( $fileName ) { |
| 65 | + return $this->deleteFileByTitle( Title::newFromText( $fileName, NS_FILE ) ); |
| 66 | + } |
| 67 | + |
| 68 | + |
| 69 | + /** |
| 70 | + * Helper function -- given a file on the filesystem, find matching content in the db (and associated articles) and remove them. |
| 71 | + * @param $filePath String: path to file on the filesystem |
| 72 | + */ |
| 73 | + public function deleteFileByContent( $filePath ) { |
| 74 | + $hash = File::sha1Base36( $filePath ); |
| 75 | + $dupes = RepoGroup::singleton()->findBySha1( $hash ); |
| 76 | + $success = true; |
| 77 | + foreach ( $dupes as $dupe ) { |
| 78 | + $success &= $this->deleteFileByTitle( $dupe->getTitle() ); |
| 79 | + } |
| 80 | + return $success; |
| 81 | + } |
| 82 | + |
| 83 | + /** |
| 84 | + * Fake an upload by dumping the file into temp space, and adding info to $_FILES. |
| 85 | + * (This is what PHP would normally do). |
| 86 | + * @param $fieldName String: name this would have in the upload form |
| 87 | + * @param $fileName String: name to title this |
| 88 | + * @param $type String: mime type |
| 89 | + * @param $filePath String: path where to find file contents |
| 90 | + */ |
| 91 | + function fakeUploadFile( $fieldName, $fileName, $type, $filePath ) { |
| 92 | + $tmpName = tempnam( wfTempDir(), "" ); |
| 93 | + if ( !file_exists( $filePath ) ) { |
| 94 | + throw new Exception( "$filePath doesn't exist!" ); |
| 95 | + }; |
| 96 | + |
| 97 | + if ( !copy( $filePath, $tmpName ) ) { |
| 98 | + throw new Exception( "couldn't copy $filePath to $tmpName" ); |
| 99 | + } |
| 100 | + |
| 101 | + clearstatcache(); |
| 102 | + $size = filesize( $tmpName ); |
| 103 | + if ( $size === false ) { |
| 104 | + throw new Exception( "couldn't stat $tmpName" ); |
| 105 | + } |
| 106 | + |
| 107 | + $_FILES[ $fieldName ] = array( |
| 108 | + 'name' => $fileName, |
| 109 | + 'type' => $type, |
| 110 | + 'tmp_name' => $tmpName, |
| 111 | + 'size' => $size, |
| 112 | + 'error' => null |
| 113 | + ); |
| 114 | + |
| 115 | + return true; |
| 116 | + |
| 117 | + } |
| 118 | + |
| 119 | + /** |
| 120 | + * Remove traces of previous fake uploads |
| 121 | + */ |
| 122 | + function clearFakeUploads() { |
| 123 | + $_FILES = array(); |
| 124 | + } |
| 125 | + |
| 126 | + |
| 127 | + |
| 128 | + |
| 129 | +} |
Property changes on: trunk/phase3/tests/phpunit/includes/api/ApiTestCaseUpload.php |
___________________________________________________________________ |
Added: svn:eol-syle |
1 | 130 | + native |
Index: trunk/phase3/tests/phpunit/includes/api/ApiUploadTest.php |
— | — | @@ -14,164 +14,19 @@ |
15 | 15 | // This framework works better IMO and has less strangeness (such as test cases inheriting from "ApiSetup"...) |
16 | 16 | // (and in the case of the other Upload tests, this flat out just actually works... ) |
17 | 17 | |
18 | | -// TODO: refactor into several files |
19 | 18 | // TODO: port the other Upload tests, and other API tests to this framework |
20 | 19 | |
21 | | -/* Wraps the user object, so we can also retain full access to properties like password if we log in via the API */ |
22 | | -class ApiTestUser { |
23 | | - public $username; |
24 | | - public $password; |
25 | | - public $email; |
26 | | - public $groups; |
27 | | - public $user; |
| 20 | +require_once( 'ApiTestCaseUpload.php' ); |
28 | 21 | |
29 | | - function __construct( $username, $realname = 'Real Name', $email = 'sample@sample.com', $groups = array() ) { |
30 | | - $this->username = $username; |
31 | | - $this->realname = $realname; |
32 | | - $this->email = $email; |
33 | | - $this->groups = $groups; |
34 | | - |
35 | | - // don't allow user to hardcode or select passwords -- people sometimes run tests |
36 | | - // on live wikis. Sometimes we create sysop users in these tests. A sysop user with |
37 | | - // a known password would be a Bad Thing. |
38 | | - $this->password = User::randomPassword(); |
39 | | - |
40 | | - $this->user = User::newFromName( $this->username ); |
41 | | - $this->user->load(); |
42 | | - |
43 | | - // In an ideal world we'd have a new wiki (or mock data store) for every single test. |
44 | | - // But for now, we just need to create or update the user with the desired properties. |
45 | | - // we particularly need the new password, since we just generated it randomly. |
46 | | - // In core MediaWiki, there is no functionality to delete users, so this is the best we can do. |
47 | | - if ( !$this->user->getID() ) { |
48 | | - // create the user |
49 | | - $this->user = User::createNew( |
50 | | - $this->username, array( |
51 | | - "email" => $this->email, |
52 | | - "real_name" => $this->realname |
53 | | - ) |
54 | | - ); |
55 | | - if ( !$this->user ) { |
56 | | - throw new Exception( "error creating user" ); |
57 | | - } |
58 | | - } |
59 | | - |
60 | | - // update the user to use the new random password and other details |
61 | | - $this->user->setPassword( $this->password ); |
62 | | - $this->user->setEmail( $this->email ); |
63 | | - $this->user->setRealName( $this->realname ); |
64 | | - // remove all groups, replace with any groups specified |
65 | | - foreach ( $this->user->getGroups() as $group ) { |
66 | | - $this->user->removeGroup( $group ); |
67 | | - } |
68 | | - if ( count( $this->groups ) ) { |
69 | | - foreach ( $this->groups as $group ) { |
70 | | - $this->user->addGroup( $group ); |
71 | | - } |
72 | | - } |
73 | | - $this->user->saveSettings(); |
74 | | - |
75 | | - } |
76 | | - |
77 | | -} |
78 | | - |
79 | | -abstract class ApiTestCase extends MediaWikiTestCase { |
80 | | - public static $users; |
81 | | - |
82 | | - function setUp() { |
83 | | - global $wgContLang, $wgAuth, $wgMemc, $wgRequest, $wgUser; |
84 | | - |
85 | | - $wgMemc = new EmptyBagOStuff(); |
86 | | - $wgContLang = Language::factory( 'en' ); |
87 | | - $wgAuth = new StubObject( 'wgAuth', 'AuthPlugin' ); |
88 | | - $wgRequest = new FauxRequest( array() ); |
89 | | - |
90 | | - self::$users = array( |
91 | | - 'sysop' => new ApiTestUser( |
92 | | - 'Apitestsysop', |
93 | | - 'Api Test Sysop', |
94 | | - 'api_test_sysop@sample.com', |
95 | | - array( 'sysop' ) |
96 | | - ), |
97 | | - 'uploader' => new ApiTestUser( |
98 | | - 'Apitestuser', |
99 | | - 'Api Test User', |
100 | | - 'api_test_user@sample.com', |
101 | | - array() |
102 | | - ) |
103 | | - ); |
104 | | - |
105 | | - $wgUser = self::$users['sysop']->user; |
106 | | - |
107 | | - } |
108 | | - |
109 | | - protected function doApiRequest( $params, $session = null, $appendModule = false ) { |
110 | | - if ( is_null( $session ) ) { |
111 | | - $session = array(); |
112 | | - } |
113 | | - |
114 | | - $request = new FauxRequest( $params, true, $session ); |
115 | | - $module = new ApiMain( $request, true ); |
116 | | - $module->execute(); |
117 | | - |
118 | | - return array( $module->getResultData(), $request, $request->getSessionArray() ); |
119 | | - } |
120 | | - |
121 | | - /** |
122 | | - * Add an edit token to the API request |
123 | | - * This is cheating a bit -- we grab a token in the correct format and then add it to the pseudo-session and to the |
124 | | - * request, without actually requesting a "real" edit token |
125 | | - * @param $params: key-value API params |
126 | | - * @param $session: session array |
127 | | - */ |
128 | | - protected function doApiRequestWithToken( $params, $session ) { |
129 | | - if ( $session['wsToken'] ) { |
130 | | - // add edit token to fake session |
131 | | - $session['wsEditToken'] = $session['wsToken']; |
132 | | - // add token to request parameters |
133 | | - $params['token'] = md5( $session['wsToken'] ) . User::EDIT_TOKEN_SUFFIX; |
134 | | - return $this->doApiRequest( $params, $session ); |
135 | | - } else { |
136 | | - throw new Exception( "request data not in right format" ); |
137 | | - } |
138 | | - } |
139 | | - |
140 | | -} |
141 | | - |
142 | 22 | /** |
143 | 23 | * @group Database |
144 | 24 | * @group Destructive |
145 | 25 | * |
146 | 26 | * This is pretty sucky... needs to be prettified. |
147 | 27 | */ |
148 | | -class ApiUploadTest extends ApiTestCase { |
149 | | - /** |
150 | | - * Fixture -- run before every test |
151 | | - */ |
152 | | - public function setUp() { |
153 | | - global $wgEnableUploads, $wgEnableAPI; |
154 | | - parent::setUp(); |
| 28 | +class ApiUploadTest extends ApiTestCaseUpload { |
155 | 29 | |
156 | | - $wgEnableUploads = true; |
157 | | - $wgEnableAPI = true; |
158 | | - wfSetupSession(); |
159 | | - |
160 | | - ini_set( 'log_errors', 1 ); |
161 | | - ini_set( 'error_reporting', 1 ); |
162 | | - ini_set( 'display_errors', 1 ); |
163 | | - |
164 | | - $this->clearFakeUploads(); |
165 | | - } |
166 | | - |
167 | 30 | /** |
168 | | - * Fixture -- run after every test |
169 | | - * Clean up temporary files etc. |
170 | | - */ |
171 | | - function tearDown() { |
172 | | - } |
173 | | - |
174 | | - |
175 | | - /** |
176 | 31 | * Testing login |
177 | 32 | * XXX this is a funny way of getting session context |
178 | 33 | */ |
— | — | @@ -575,98 +430,5 @@ |
576 | 431 | $this->deleteFileByFilename( $fileName ); |
577 | 432 | unlink( $filePath ); |
578 | 433 | } |
579 | | - |
580 | | - |
581 | | - |
582 | | - /** |
583 | | - * Helper function -- remove files and associated articles by Title |
584 | | - * @param $title Title: title to be removed |
585 | | - */ |
586 | | - public function deleteFileByTitle( $title ) { |
587 | | - if ( $title->exists() ) { |
588 | | - $file = wfFindFile( $title, array( 'ignoreRedirect' => true ) ); |
589 | | - $noOldArchive = ""; // yes this really needs to be set this way |
590 | | - $comment = "removing for test"; |
591 | | - $restrictDeletedVersions = false; |
592 | | - $status = FileDeleteForm::doDelete( $title, $file, $noOldArchive, $comment, $restrictDeletedVersions ); |
593 | | - if ( !$status->isGood() ) { |
594 | | - return false; |
595 | | - } |
596 | | - $article = new Article( $title ); |
597 | | - $article->doDeleteArticle( "removing for test" ); |
598 | | - |
599 | | - // see if it now doesn't exist; reload |
600 | | - $title = Title::newFromText( $fileName, NS_FILE ); |
601 | | - } |
602 | | - return ! ( $title && $title instanceof Title && $title->exists() ); |
603 | | - } |
604 | | - |
605 | | - /** |
606 | | - * Helper function -- remove files and associated articles with a particular filename |
607 | | - * @param $fileName String: filename to be removed |
608 | | - */ |
609 | | - public function deleteFileByFileName( $fileName ) { |
610 | | - return $this->deleteFileByTitle( Title::newFromText( $fileName, NS_FILE ) ); |
611 | | - } |
612 | | - |
613 | | - |
614 | | - /** |
615 | | - * Helper function -- given a file on the filesystem, find matching content in the db (and associated articles) and remove them. |
616 | | - * @param $filePath String: path to file on the filesystem |
617 | | - */ |
618 | | - public function deleteFileByContent( $filePath ) { |
619 | | - $hash = File::sha1Base36( $filePath ); |
620 | | - $dupes = RepoGroup::singleton()->findBySha1( $hash ); |
621 | | - $success = true; |
622 | | - foreach ( $dupes as $dupe ) { |
623 | | - $success &= $this->deleteFileByTitle( $dupe->getTitle() ); |
624 | | - } |
625 | | - return $success; |
626 | | - } |
627 | | - |
628 | | - /** |
629 | | - * Fake an upload by dumping the file into temp space, and adding info to $_FILES. |
630 | | - * (This is what PHP would normally do). |
631 | | - * @param $fieldName String: name this would have in the upload form |
632 | | - * @param $fileName String: name to title this |
633 | | - * @param $type String: mime type |
634 | | - * @param $filePath String: path where to find file contents |
635 | | - */ |
636 | | - function fakeUploadFile( $fieldName, $fileName, $type, $filePath ) { |
637 | | - $tmpName = tempnam( wfTempDir(), "" ); |
638 | | - if ( !file_exists( $filePath ) ) { |
639 | | - throw new Exception( "$filePath doesn't exist!" ); |
640 | | - }; |
641 | | - |
642 | | - if ( !copy( $filePath, $tmpName ) ) { |
643 | | - throw new Exception( "couldn't copy $filePath to $tmpName" ); |
644 | | - } |
645 | | - |
646 | | - clearstatcache(); |
647 | | - $size = filesize( $tmpName ); |
648 | | - if ( $size === false ) { |
649 | | - throw new Exception( "couldn't stat $tmpName" ); |
650 | | - } |
651 | | - |
652 | | - $_FILES[ $fieldName ] = array( |
653 | | - 'name' => $fileName, |
654 | | - 'type' => $type, |
655 | | - 'tmp_name' => $tmpName, |
656 | | - 'size' => $size, |
657 | | - 'error' => null |
658 | | - ); |
659 | | - |
660 | | - return true; |
661 | | - |
662 | | - } |
663 | | - |
664 | | - /** |
665 | | - * Remove traces of previous fake uploads |
666 | | - */ |
667 | | - function clearFakeUploads() { |
668 | | - $_FILES = array(); |
669 | | - } |
670 | | - |
671 | | - |
672 | 434 | } |
673 | 435 | |
Index: trunk/phase3/tests/phpunit/includes/api/ApiTestCase.php |
— | — | @@ -0,0 +1,64 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +abstract class ApiTestCase extends MediaWikiTestCase { |
| 5 | + public static $users; |
| 6 | + |
| 7 | + function setUp() { |
| 8 | + global $wgContLang, $wgAuth, $wgMemc, $wgRequest, $wgUser; |
| 9 | + |
| 10 | + $wgMemc = new EmptyBagOStuff(); |
| 11 | + $wgContLang = Language::factory( 'en' ); |
| 12 | + $wgAuth = new StubObject( 'wgAuth', 'AuthPlugin' ); |
| 13 | + $wgRequest = new FauxRequest( array() ); |
| 14 | + |
| 15 | + self::$users = array( |
| 16 | + 'sysop' => new ApiTestUser( |
| 17 | + 'Apitestsysop', |
| 18 | + 'Api Test Sysop', |
| 19 | + 'api_test_sysop@sample.com', |
| 20 | + array( 'sysop' ) |
| 21 | + ), |
| 22 | + 'uploader' => new ApiTestUser( |
| 23 | + 'Apitestuser', |
| 24 | + 'Api Test User', |
| 25 | + 'api_test_user@sample.com', |
| 26 | + array() |
| 27 | + ) |
| 28 | + ); |
| 29 | + |
| 30 | + $wgUser = self::$users['sysop']->user; |
| 31 | + |
| 32 | + } |
| 33 | + |
| 34 | + protected function doApiRequest( $params, $session = null, $appendModule = false ) { |
| 35 | + if ( is_null( $session ) ) { |
| 36 | + $session = array(); |
| 37 | + } |
| 38 | + |
| 39 | + $request = new FauxRequest( $params, true, $session ); |
| 40 | + $module = new ApiMain( $request, true ); |
| 41 | + $module->execute(); |
| 42 | + |
| 43 | + return array( $module->getResultData(), $request, $request->getSessionArray() ); |
| 44 | + } |
| 45 | + |
| 46 | + /** |
| 47 | + * Add an edit token to the API request |
| 48 | + * This is cheating a bit -- we grab a token in the correct format and then add it to the pseudo-session and to the |
| 49 | + * request, without actually requesting a "real" edit token |
| 50 | + * @param $params: key-value API params |
| 51 | + * @param $session: session array |
| 52 | + */ |
| 53 | + protected function doApiRequestWithToken( $params, $session ) { |
| 54 | + if ( $session['wsToken'] ) { |
| 55 | + // add edit token to fake session |
| 56 | + $session['wsEditToken'] = $session['wsToken']; |
| 57 | + // add token to request parameters |
| 58 | + $params['token'] = md5( $session['wsToken'] ) . User::EDIT_TOKEN_SUFFIX; |
| 59 | + return $this->doApiRequest( $params, $session ); |
| 60 | + } else { |
| 61 | + throw new Exception( "request data not in right format" ); |
| 62 | + } |
| 63 | + } |
| 64 | + |
| 65 | +} |
Property changes on: trunk/phase3/tests/phpunit/includes/api/ApiTestCase.php |
___________________________________________________________________ |
Added: svn:eol-syle |
1 | 66 | + native |
Index: trunk/phase3/tests/phpunit/includes/api/ApiTestUser.php |
— | — | @@ -0,0 +1,59 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +/* Wraps the user object, so we can also retain full access to properties like password if we log in via the API */ |
| 5 | +class ApiTestUser { |
| 6 | + public $username; |
| 7 | + public $password; |
| 8 | + public $email; |
| 9 | + public $groups; |
| 10 | + public $user; |
| 11 | + |
| 12 | + function __construct( $username, $realname = 'Real Name', $email = 'sample@sample.com', $groups = array() ) { |
| 13 | + $this->username = $username; |
| 14 | + $this->realname = $realname; |
| 15 | + $this->email = $email; |
| 16 | + $this->groups = $groups; |
| 17 | + |
| 18 | + // don't allow user to hardcode or select passwords -- people sometimes run tests |
| 19 | + // on live wikis. Sometimes we create sysop users in these tests. A sysop user with |
| 20 | + // a known password would be a Bad Thing. |
| 21 | + $this->password = User::randomPassword(); |
| 22 | + |
| 23 | + $this->user = User::newFromName( $this->username ); |
| 24 | + $this->user->load(); |
| 25 | + |
| 26 | + // In an ideal world we'd have a new wiki (or mock data store) for every single test. |
| 27 | + // But for now, we just need to create or update the user with the desired properties. |
| 28 | + // we particularly need the new password, since we just generated it randomly. |
| 29 | + // In core MediaWiki, there is no functionality to delete users, so this is the best we can do. |
| 30 | + if ( !$this->user->getID() ) { |
| 31 | + // create the user |
| 32 | + $this->user = User::createNew( |
| 33 | + $this->username, array( |
| 34 | + "email" => $this->email, |
| 35 | + "real_name" => $this->realname |
| 36 | + ) |
| 37 | + ); |
| 38 | + if ( !$this->user ) { |
| 39 | + throw new Exception( "error creating user" ); |
| 40 | + } |
| 41 | + } |
| 42 | + |
| 43 | + // update the user to use the new random password and other details |
| 44 | + $this->user->setPassword( $this->password ); |
| 45 | + $this->user->setEmail( $this->email ); |
| 46 | + $this->user->setRealName( $this->realname ); |
| 47 | + // remove all groups, replace with any groups specified |
| 48 | + foreach ( $this->user->getGroups() as $group ) { |
| 49 | + $this->user->removeGroup( $group ); |
| 50 | + } |
| 51 | + if ( count( $this->groups ) ) { |
| 52 | + foreach ( $this->groups as $group ) { |
| 53 | + $this->user->addGroup( $group ); |
| 54 | + } |
| 55 | + } |
| 56 | + $this->user->saveSettings(); |
| 57 | + |
| 58 | + } |
| 59 | + |
| 60 | +} |
Property changes on: trunk/phase3/tests/phpunit/includes/api/ApiTestUser.php |
___________________________________________________________________ |
Added: svn:eol-syle |
1 | 61 | + native |