follow-up r61655 fill out the rest of the missing messages
[lhc/web/wiklou.git] / tests / HttpTest.php
1 <?php
2
3 class MockCookie extends Cookie {
4 public function canServeDomain($arg) { return parent::canServeDomain($arg); }
5 public function canServePath($arg) { return parent::canServePath($arg); }
6 public function isUnExpired() { return parent::isUnExpired(); }
7 }
8
9 class HttpTest extends PhpUnit_Framework_TestCase {
10 static $content;
11 static $headers;
12 static $has_curl;
13 static $has_proxy = false;
14 static $proxy = "http://hulk:8080/";
15 var $test_geturl = array(
16 "http://www.example.com/",
17 "http://pecl.php.net/feeds/pkg_apc.rss",
18 "http://toolserver.org/~jan/poll/dev/main.php?page=wiki_output&id=3",
19 "http://meta.wikimedia.org/w/index.php?title=Interwiki_map&action=raw",
20 "http://www.mediawiki.org/w/api.php?action=query&list=categorymembers&cmtitle=Category:MediaWiki_hooks&format=php",
21 );
22 var $test_requesturl = array( "http://en.wikipedia.org/wiki/Special:Export/User:MarkAHershberger" );
23
24 var $test_posturl = array( "http://www.comp.leeds.ac.uk/cgi-bin/Perl/environment-example" => "review=test" );
25
26 function setup() {
27 putenv("http_proxy"); /* Remove any proxy env var, so curl doesn't get confused */
28 if ( is_array( self::$content ) ) {
29 return;
30 }
31 self::$has_curl = function_exists( 'curl_init' );
32
33 if ( !file_exists("/usr/bin/curl") ) {
34 $this->markTestIncomplete("This test requires the curl binary at /usr/bin/curl. If you have curl, please file a bug on this test, or, better yet, provide a patch.");
35 }
36
37 $content = tempnam( wfTempDir(), "" );
38 $headers = tempnam( wfTempDir(), "" );
39 if ( !$content && !$headers ) {
40 die( "Couldn't create temp file!" );
41 }
42
43 // This probably isn't the best test for a proxy, but it works on my system!
44 system("curl -0 -o $content -s ".self::$proxy);
45 $out = file_get_contents( $content );
46 if( $out ) {
47 self::$has_proxy = true;
48 }
49
50 /* Maybe use wget instead of curl here ... just to use a different codebase? */
51 foreach ( $this->test_geturl as $u ) {
52 system( "curl -0 -s -D $headers '$u' -o $content" );
53 self::$content["GET $u"] = file_get_contents( $content );
54 self::$headers["GET $u"] = file_get_contents( $headers );
55 }
56 foreach ( $this->test_requesturl as $u ) {
57 system( "curl -0 -s -X POST -H 'Content-Length: 0' -D $headers '$u' -o $content" );
58 self::$content["POST $u"] = file_get_contents( $content );
59 self::$headers["POST $u"] = file_get_contents( $headers );
60 }
61 foreach ( $this->test_posturl as $u => $postData ) {
62 system( "curl -0 -s -X POST -d '$postData' -D $headers '$u' -o $content" );
63 self::$content["POST $u => $postData"] = file_get_contents( $content );
64 self::$headers["POST $u => $postData"] = file_get_contents( $headers );
65 }
66 unlink( $content );
67 unlink( $headers );
68 }
69
70
71 function testInstantiation() {
72 Http::$httpEngine = false;
73
74 $r = HttpRequest::factory("http://www.example.com/");
75 if ( self::$has_curl ) {
76 $this->assertThat($r, $this->isInstanceOf( 'CurlHttpRequest' ));
77 } else {
78 $this->assertThat($r, $this->isInstanceOf( 'PhpHttpRequest' ));
79 }
80 unset($r);
81
82 Http::$httpEngine = 'php';
83 $r = HttpRequest::factory("http://www.example.com/");
84 $this->assertThat($r, $this->isInstanceOf( 'PhpHttpRequest' ));
85 unset($r);
86
87 if( !self::$has_curl ) {
88 $this->setExpectedException( 'MWException' );
89 }
90 Http::$httpEngine = 'curl';
91 $r = HttpRequest::factory("http://www.example.com/");
92 if( self::$has_curl ) {
93 $this->assertThat($r, $this->isInstanceOf( 'CurlHttpRequest' ));
94 }
95 }
96
97 function runHTTPFailureChecks() {
98 // Each of the following requests should result in a failure.
99
100 $timeout = 1;
101 $start_time = time();
102 $r = HTTP::get( "http://www.example.com:1/", $timeout);
103 $end_time = time();
104 $this->assertLessThan($timeout+2, $end_time - $start_time,
105 "Request took less than {$timeout}s via ".Http::$httpEngine);
106 $this->assertEquals($r, false, "false -- what we get on error from Http::get()");
107 }
108
109 function testFailureDefault() {
110 Http::$httpEngine = false;
111 self::runHTTPFailureChecks();
112 }
113
114 function testFailurePhp() {
115 Http::$httpEngine = "php";
116 self::runHTTPFailureChecks();
117 }
118
119 function testFailureCurl() {
120 if (!self::$has_curl ) {
121 $this->markTestIncomplete("This test requires curl.");
122 }
123
124 Http::$httpEngine = "curl";
125 self::runHTTPFailureChecks();
126 }
127
128 /* ./phase3/includes/Import.php:1108: $data = Http::request( $method, $url ); */
129 /* ./includes/Import.php:1124: $link = Title::newFromText( "$interwiki:Special:Export/$page" ); */
130 /* ./includes/Import.php:1134: return ImportStreamSource::newFromURL( $url, "POST" ); */
131 function runHTTPRequests($proxy=null) {
132 $opt = array();
133
134 if($proxy) {
135 $opt['proxy'] = $proxy;
136 } elseif( $proxy === false ) {
137 $opt['noProxy'] = true;
138 }
139
140 /* no postData here because the only request I could find in code so far didn't have any */
141 foreach ( $this->test_requesturl as $u ) {
142 $r = Http::request( "POST", $u, $opt );
143 $this->assertEquals( self::$content["POST $u"], "$r", "POST $u with ".Http::$httpEngine );
144 }
145 }
146
147 function testRequestDefault() {
148 Http::$httpEngine = false;
149 self::runHTTPRequests();
150 }
151
152 function testRequestPhp() {
153 Http::$httpEngine = "php";
154 self::runHTTPRequests();
155 }
156
157 function testRequestCurl() {
158 if (!self::$has_curl ) {
159 $this->markTestIncomplete("This test requires curl.");
160 }
161
162 Http::$httpEngine = "curl";
163 self::runHTTPRequests();
164 }
165
166 /* ./extensions/SpamBlacklist/SpamBlacklist_body.php:164: $httpText = Http::get( $fileName ); */
167 /* ./extensions/ApiSVGProxy/ApiSVGProxy.body.php:44: $contents = Http::get( $file->getFullUrl() ); */
168 /* ./extensions/BookInformation/drivers/IsbnDb.php:24: if( ( $xml = Http::get( $uri ) ) !== false ) { */
169 /* ./extensions/BookInformation/drivers/Amazon.php:23: if( ( $xml = Http::get( $uri ) ) !== false ) { */
170 /* ./extensions/TitleBlacklist/TitleBlacklist.list.php:217: $result = Http::get( $url ); */
171 /* ./extensions/TSPoll/TSPoll.php:68: $get_server = Http::get( 'http://toolserver.org/~jan/poll/dev/main.php?page=wiki_output&id='.$id ); */
172 /* ./extensions/TSPoll/TSPoll.php:70: $get_server = Http::get( 'http://toolserver.org/~jan/poll/main.php?page=wiki_output&id='.$id ); */
173 /* ./extensions/DoubleWiki/DoubleWiki.php:56: $translation = Http::get( $url.$sep.'action=render' ); */
174 /* ./extensions/ExternalPages/ExternalPages_body.php:177: $serializedText = Http::get( $this->mPageURL ); */
175 /* ./extensions/Translate/utils/TranslationHelpers.php:143: $suggestions = Http::get( $url, $timeout ); */
176 /* ./extensions/Translate/SpecialImportTranslations.php:169: $filedata = Http::get( $url ); ; */
177 /* ./extensions/Translate/TranslateEditAddons.php:338: $suggestions = Http::get( $url, $timeout ); */
178 /* ./extensions/SecurePoll/includes/user/Auth.php:283: $value = Http::get( $url, 20, $curlParams ); */
179 /* ./extensions/DumpHTML/dumpHTML.inc:778: $contents = Http::get( $url ); */
180 /* ./extensions/DumpHTML/dumpHTML.inc:1298: $contents = Http::get( $sourceUrl ); */
181 /* ./extensions/DumpHTML/dumpHTML.inc:1373: $contents = Http::get( $sourceUrl ); */
182 /* ./phase3/maintenance/rebuildInterwiki.inc:101: $intermap = Http::get( 'http://meta.wikimedia.org/w/index.php?title=Interwiki_map&action=raw', 30 ); */
183 /* ./phase3/maintenance/findhooks.php:98: $allhookdata = Http::get( 'http://www.mediawiki.org/w/api.php?action=query&list=categorymembers&cmtitle=Category:MediaWiki_hooks&cmlimit=500&format=php' ); */
184 /* ./phase3/maintenance/findhooks.php:109: $oldhookdata = Http::get( 'http://www.mediawiki.org/w/api.php?action=query&list=categorymembers&cmtitle=Category:Removed_hooks&cmlimit=500&format=php' ); */
185 /* ./phase3/maintenance/dumpInterwiki.inc:95: $intermap = Http::get( 'http://meta.wikimedia.org/w/index.php?title=Interwiki_map&action=raw', 30 ); */
186 /* ./phase3/includes/parser/Parser.php:3204: $text = Http::get($url); */
187 /* ./phase3/includes/filerepo/ForeignAPIRepo.php:131: $data = Http::get( $url ); */
188 /* ./phase3/includes/filerepo/ForeignAPIRepo.php:205: $thumb = Http::get( $foreignUrl ); */
189 /* ./phase3/includes/filerepo/File.php:1105: $res = Http::get( $renderUrl ); */
190 /* ./phase3/includes/GlobalFunctions.php:2760: * @deprecated Use Http::get() instead */
191 /* ./phase3/includes/GlobalFunctions.php:2764: return Http::get( $url ); */
192 /* ./phase3/includes/ExternalStoreHttp.php:18: $ret = Http::get( $url ); */
193 /* ./phase3/includes/Import.php:357: $data = Http::get( $src ); */
194 /* ./extensions/ExternalData/ED_Utils.php:291: return Http::get( $url, 'default', array(CURLOPT_SSL_VERIFYPEER => false) ); */
195 /* ./extensions/ExternalData/ED_Utils.php:293: return Http::get( $url ); */
196 /* ./extensions/ExternalData/ED_Utils.php:306: $page = Http::get( $url, 'default', array(CURLOPT_SSL_VERIFYPEER => false) ); */
197 /* ./extensions/ExternalData/ED_Utils.php:308: $page = Http::get( $url ); */
198 /* ./extensions/CodeReview/backend/Subversion.php:320: $blob = Http::get( $target, $this->mTimeout ); */
199 /* ./extensions/AmazonPlus/AmazonPlus.php:214: $this->response = Http::get( $urlstr ); */
200 /* ./extensions/StaticWiki/StaticWiki.php:24: $text = Http::get( $url ) ; */
201 /* ./extensions/StaticWiki/StaticWiki.php:64: $history = Http::get ( $wgStaticWikiExternalSite . "index.php?title=" . urlencode ( $url_title ) . "&action=history" ) ; */
202 /* ./extensions/Configure/scripts/findSettings.php:126: $cont = Http::get( "http://www.mediawiki.org/w/index.php?title={$page}&action=raw" ); */
203 /* ./extensions/TorBlock/TorBlock.class.php:148: $data = Http::get( $url ); */
204 /* ./extensions/HoneypotIntegration/HoneypotIntegration.class.php:60: $data = Http::get( $wgHoneypotURLSource, 'default', */
205 /* ./extensions/SemanticForms/includes/SF_Utils.inc:378: $page_contents = Http::get($url); */
206 /* ./extensions/LocalisationUpdate/LocalisationUpdate.class.php:172: $basefilecontents = Http::get( $basefile ); */
207 /* ./extensions/APC/SpecialAPC.php:245: $rss = Http::get( 'http://pecl.php.net/feeds/pkg_apc.rss' ); */
208 /* ./extensions/Interlanguage/Interlanguage.php:56: $a = Http::get( $url ); */
209 /* ./extensions/MWSearch/MWSearch_body.php:492: $data = Http::get( $searchUrl, $wgLuceneSearchTimeout, $httpOpts); */
210 function runHTTPGets($proxy=null) {
211 $opt = array();
212
213 if($proxy) {
214 $opt['proxy'] = $proxy;
215 } elseif( $proxy === false ) {
216 $opt['noProxy'] = true;
217 }
218
219 foreach ( $this->test_geturl as $u ) {
220 $r = Http::get( $u, 30, $opt ); /* timeout of 30s */
221 $this->assertEquals( self::$content["GET $u"], "$r", "Get $u with ".Http::$httpEngine );
222 }
223 }
224
225 function testGetDefault() {
226 Http::$httpEngine = false;
227 self::runHTTPGets();
228 }
229
230 function testGetPhp() {
231 Http::$httpEngine = "php";
232 self::runHTTPGets();
233 }
234
235 function testGetCurl() {
236 if (!self::$has_curl ) {
237 $this->markTestIncomplete("This test requires curl.");
238 }
239
240 Http::$httpEngine = "curl";
241 self::runHTTPGets();
242 }
243
244 /* ./phase3/maintenance/parserTests.inc:1618: return Http::post( $url, array( 'postData' => wfArrayToCGI( $data ) ) ); */
245 function runHTTPPosts($proxy=null) {
246 $opt = array();
247
248 if($proxy) {
249 $opt['proxy'] = $proxy;
250 } elseif( $proxy === false ) {
251 $opt['noProxy'] = true;
252 }
253
254 foreach ( $this->test_posturl as $u => $postData ) {
255 $opt['postData'] = $postData;
256 $r = Http::post( $u, $opt );
257 $this->assertEquals( self::$content["POST $u => $postData"], "$r",
258 "POST $u (postData=$postData) with ".Http::$httpEngine );
259 }
260 }
261
262 function testPostDefault() {
263 Http::$httpEngine = false;
264 self::runHTTPPosts();
265 }
266
267 function testPostPhp() {
268 Http::$httpEngine = "php";
269 self::runHTTPPosts();
270 }
271
272 function testPostCurl() {
273 if (!self::$has_curl ) {
274 $this->markTestIncomplete("This test requires curl.");
275 }
276
277 Http::$httpEngine = "curl";
278 self::runHTTPPosts();
279 }
280
281 function runProxyRequests() {
282 if(!self::$has_proxy) {
283 $this->markTestIncomplete("This test requires a proxy.");
284 }
285 self::runHTTPGets(self::$proxy);
286 self::runHTTPPosts(self::$proxy);
287 self::runHTTPRequests(self::$proxy);
288
289 // Set false here to do noProxy
290 self::runHTTPGets(false);
291 self::runHTTPPosts(false);
292 self::runHTTPRequests(false);
293 }
294
295 function testProxyDefault() {
296 Http::$httpEngine = false;
297 self::runProxyRequests();
298 }
299
300 function testProxyPhp() {
301 Http::$httpEngine = 'php';
302 self::runProxyRequests();
303 }
304
305 function testProxyCurl() {
306 if (!self::$has_curl ) {
307 $this->markTestIncomplete("This test requires curl.");
308 }
309
310 Http::$httpEngine = 'curl';
311 self::runProxyRequests();
312 }
313
314 function testIsLocalUrl() {
315 }
316
317 /* ./extensions/DonationInterface/payflowpro_gateway/payflowpro_gateway.body.php:559: $user_agent = Http::userAgent(); */
318 function testUserAgent() {
319 }
320
321 function testIsValidUrl() {
322 }
323
324 function testSetCookie() {
325 $c = new MockCookie( "name", "value",
326 array(
327 "domain" => ".example.com",
328 "path" => "/path/",
329 ) );
330
331 $this->assertFalse($c->canServeDomain("example.com"));
332 $this->assertFalse($c->canServeDomain("www.example.net"));
333 $this->assertTrue($c->canServeDomain("www.example.com"));
334
335 $this->assertFalse($c->canServePath("/"));
336 $this->assertFalse($c->canServePath("/bogus/path/"));
337 $this->assertFalse($c->canServePath("/path"));
338 $this->assertTrue($c->canServePath("/path/"));
339
340 $this->assertTrue($c->isUnExpired());
341
342 $this->assertEquals("", $c->serializeToHttpRequest("/path/", "www.example.net"));
343 $this->assertEquals("", $c->serializeToHttpRequest("/", "www.example.com"));
344 $this->assertEquals("name=value", $c->serializeToHttpRequest("/path/", "www.example.com"));
345
346 $c = new MockCookie( "name", "value",
347 array(
348 "domain" => ".example.com",
349 "path" => "/path/",
350 "expires" => "January 1, 1990",
351 ) );
352 $this->assertFalse($c->isUnExpired());
353 $this->assertEquals("", $c->serializeToHttpRequest("/path/", "www.example.com"));
354
355 $c = new MockCookie( "name", "value",
356 array(
357 "domain" => ".example.com",
358 "path" => "/path/",
359 "expires" => "January 1, 2999",
360 ) );
361 $this->assertTrue($c->isUnExpired());
362 $this->assertEquals("name=value", $c->serializeToHttpRequest("/path/", "www.example.com"));
363
364
365 }
366
367 function testCookieJarSetCookie() {
368 $cj = new CookieJar;
369 $cj->setCookie( "name", "value",
370 array(
371 "domain" => ".example.com",
372 "path" => "/path/",
373 ) );
374 $cj->setCookie( "name2", "value",
375 array(
376 "domain" => ".example.com",
377 "path" => "/path/sub",
378 ) );
379 $cj->setCookie( "name3", "value",
380 array(
381 "domain" => ".example.com",
382 "path" => "/",
383 ) );
384 $cj->setCookie( "name4", "value",
385 array(
386 "domain" => ".example.net",
387 "path" => "/path/",
388 ) );
389 $cj->setCookie( "name5", "value",
390 array(
391 "domain" => ".example.net",
392 "path" => "/path/",
393 "expires" => "January 1, 1999",
394 ) );
395
396 $this->assertEquals("name4=value", $cj->serializeToHttpRequest("/path/", "www.example.net"));
397 $this->assertEquals("name3=value", $cj->serializeToHttpRequest("/", "www.example.com"));
398 $this->assertEquals("name=value; name3=value", $cj->serializeToHttpRequest("/path/", "www.example.com"));
399
400 $cj->setCookie( "name5", "value",
401 array(
402 "domain" => ".example.net",
403 "path" => "/path/",
404 "expires" => "January 1, 2999",
405 ) );
406 $this->assertEquals("name4=value; name5=value", $cj->serializeToHttpRequest("/path/", "www.example.net"));
407
408 $cj->setCookie( "name4", "value",
409 array(
410 "domain" => ".example.net",
411 "path" => "/path/",
412 "expires" => "January 1, 1999",
413 ) );
414 $this->assertEquals("name5=value", $cj->serializeToHttpRequest("/path/", "www.example.net"));
415 }
416
417 function testParseResponseHeader() {
418 $cj = new CookieJar;
419
420 $h[] = "Set-Cookie: name4=value; domain=.example.com; path=/; expires=Mon, 09-Dec-2999 13:46:00 GMT";
421 $cj->parseCookieResponseHeader( $h[0] );
422 $this->assertEquals("name4=value", $cj->serializeToHttpRequest("/", "www.example.com"));
423
424 $h[] = "name4=value2; domain=.example.com; path=/path/; expires=Mon, 09-Dec-2999 13:46:00 GMT";
425 $cj->parseCookieResponseHeader( $h[1] );
426 $this->assertEquals("", $cj->serializeToHttpRequest("/", "www.example.com"));
427 $this->assertEquals("name4=value2", $cj->serializeToHttpRequest("/path/", "www.example.com"));
428
429 $h[] = "name5=value3; domain=.example.com; path=/path/; expires=Mon, 09-Dec-2999 13:46:00 GMT";
430 $cj->parseCookieResponseHeader( $h[2] );
431 $this->assertEquals("name4=value2; name5=value3", $cj->serializeToHttpRequest("/path/", "www.example.com"));
432
433 $h[] = "name6=value3; domain=.example.net; path=/path/; expires=Mon, 09-Dec-1999 13:46:00 GMT";
434 $cj->parseCookieResponseHeader( $h[3] );
435 $this->assertEquals("", $cj->serializeToHttpRequest("/path/", "www.example.net"));
436
437 $h[] = "name6=value4; domain=.example.net; path=/path/; expires=Mon, 09-Dec-2999 13:46:00 GMT";
438 $cj->parseCookieResponseHeader( $h[4] );
439 $this->assertEquals("name6=value4", $cj->serializeToHttpRequest("/path/", "www.example.net"));
440 }
441
442 function runCookieRequests() {
443 $r = HttpRequest::factory( "http://www.php.net/manual" );
444 $r->execute();
445
446 $jar = $r->getCookieJar();
447
448 $this->assertThat( $jar, $this->isInstanceOf( 'CookieJar' ) );
449 $this->assertRegExp( '/^COUNTRY=.*; LAST_LANG=.*$/', $jar->serializeToHttpRequest( "/search?q=test", "www.php.net" ) );
450 $this->assertEquals( '', $jar->serializeToHttpRequest( "/search?q=test", "www.php.com" ) );
451 }
452
453 function testCookieRequestDefault() {
454 Http::$httpEngine = false;
455 self::runCookieRequests();
456 }
457 function testCookieRequestPhp() {
458 Http::$httpEngine = 'php';
459 self::runCookieRequests();
460 }
461 function testCookieRequestCurl() {
462 if (!self::$has_curl ) {
463 $this->markTestIncomplete("This test requires curl.");
464 }
465
466 Http::$httpEngine = 'curl';
467 self::runCookieRequests();
468 }
469
470 }