00001 <?php
00002
00003 class MockCookie extends Cookie {
00004 public function canServeDomain($arg) { return parent::canServeDomain($arg); }
00005 public function canServePath($arg) { return parent::canServePath($arg); }
00006 public function isUnExpired() { return parent::isUnExpired(); }
00007 }
00008
00009 class HttpTest extends PhpUnit_Framework_TestCase {
00010 static $content;
00011 static $headers;
00012 static $has_curl;
00013 static $has_fopen;
00014 static $has_proxy = false;
00015 static $proxy = "http://hulk:8080/";
00016 var $test_geturl = array(
00017 "http://www.example.com/",
00018 "http://pecl.php.net/feeds/pkg_apc.rss",
00019 "http://toolserver.org/~jan/poll/dev/main.php?page=wiki_output&id=3",
00020 "http://meta.wikimedia.org/w/index.php?title=Interwiki_map&action=raw",
00021 "http://www.mediawiki.org/w/api.php?action=query&list=categorymembers&cmtitle=Category:MediaWiki_hooks&format=php",
00022 );
00023 var $test_requesturl = array( "http://en.wikipedia.org/wiki/Special:Export/User:MarkAHershberger" );
00024
00025 var $test_posturl = array( "http://www.comp.leeds.ac.uk/cgi-bin/Perl/environment-example" => "review=test" );
00026
00027 function setup() {
00028 putenv("http_proxy");
00029 if ( is_array( self::$content ) ) {
00030 return;
00031 }
00032 self::$has_curl = function_exists( 'curl_init' );
00033 self::$has_fopen = wfIniGetBool( 'allow_url_fopen' );
00034
00035 if ( !file_exists("/usr/bin/curl") ) {
00036 $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.");
00037 }
00038
00039 $content = tempnam( wfTempDir(), "" );
00040 $headers = tempnam( wfTempDir(), "" );
00041 if ( !$content && !$headers ) {
00042 die( "Couldn't create temp file!" );
00043 }
00044
00045
00046 system("curl -0 -o $content -s ".self::$proxy);
00047 $out = file_get_contents( $content );
00048 if( $out ) {
00049 self::$has_proxy = true;
00050 }
00051
00052
00053 foreach ( $this->test_geturl as $u ) {
00054 system( "curl -0 -s -D $headers '$u' -o $content" );
00055 self::$content["GET $u"] = file_get_contents( $content );
00056 self::$headers["GET $u"] = file_get_contents( $headers );
00057 }
00058 foreach ( $this->test_requesturl as $u ) {
00059 system( "curl -0 -s -X POST -H 'Content-Length: 0' -D $headers '$u' -o $content" );
00060 self::$content["POST $u"] = file_get_contents( $content );
00061 self::$headers["POST $u"] = file_get_contents( $headers );
00062 }
00063 foreach ( $this->test_posturl as $u => $postData ) {
00064 system( "curl -0 -s -X POST -d '$postData' -D $headers '$u' -o $content" );
00065 self::$content["POST $u => $postData"] = file_get_contents( $content );
00066 self::$headers["POST $u => $postData"] = file_get_contents( $headers );
00067 }
00068 unlink( $content );
00069 unlink( $headers );
00070 }
00071
00072
00073 function testInstantiation() {
00074 Http::$httpEngine = false;
00075
00076 $r = HttpRequest::factory("http://www.example.com/");
00077 if ( self::$has_curl ) {
00078 $this->assertThat($r, $this->isInstanceOf( 'CurlHttpRequest' ));
00079 } else {
00080 $this->assertThat($r, $this->isInstanceOf( 'PhpHttpRequest' ));
00081 }
00082 unset($r);
00083
00084 if( !self::$has_fopen ) {
00085 $this->setExpectedException( 'MWException' );
00086 }
00087 Http::$httpEngine = 'php';
00088 $r = HttpRequest::factory("http://www.example.com/");
00089 $this->assertThat($r, $this->isInstanceOf( 'PhpHttpRequest' ));
00090 unset($r);
00091
00092 if( !self::$has_curl ) {
00093 $this->setExpectedException( 'MWException' );
00094 }
00095 Http::$httpEngine = 'curl';
00096 $r = HttpRequest::factory("http://www.example.com/");
00097 if( self::$has_curl ) {
00098 $this->assertThat($r, $this->isInstanceOf( 'CurlHttpRequest' ));
00099 }
00100 }
00101
00102 function runHTTPFailureChecks() {
00103
00104
00105 $timeout = 1;
00106 $start_time = time();
00107 $r = HTTP::get( "http://www.example.com:1/", $timeout);
00108 $end_time = time();
00109 $this->assertLessThan($timeout+2, $end_time - $start_time,
00110 "Request took less than {$timeout}s via ".Http::$httpEngine);
00111 $this->assertEquals($r, false, "false -- what we get on error from Http::get()");
00112
00113 $r = HTTP::get( "http://www.example.com/this-file-does-not-exist", $timeout);
00114 $this->assertFalse($r, "False on 404s");
00115
00116
00117 $r = HttpRequest::factory( "http://www.example.com/this-file-does-not-exist" );
00118 $er = $r->execute();
00119 if ( is_a($r, 'PhpHttpRequest') && version_compare( '5.2.10', phpversion(), '>' ) ) {
00120 $this->assertRegexp("/HTTP request failed/", $er->getWikiText());
00121 } else {
00122 $this->assertRegexp("/404 Not Found/", $er->getWikiText());
00123 }
00124 }
00125
00126 function testFailureDefault() {
00127 Http::$httpEngine = false;
00128 self::runHTTPFailureChecks();
00129 }
00130
00131 function testFailurePhp() {
00132 if ( !self::$has_fopen ) {
00133 $this->markTestIncomplete( "This test requires allow_url_fopen=true." );
00134 }
00135
00136 Http::$httpEngine = "php";
00137 self::runHTTPFailureChecks();
00138 }
00139
00140 function testFailureCurl() {
00141 if ( !self::$has_curl ) {
00142 $this->markTestIncomplete( "This test requires curl." );
00143 }
00144
00145 Http::$httpEngine = "curl";
00146 self::runHTTPFailureChecks();
00147 }
00148
00149
00150
00151
00152 function runHTTPRequests($proxy=null) {
00153 $opt = array();
00154
00155 if($proxy) {
00156 $opt['proxy'] = $proxy;
00157 } elseif( $proxy === false ) {
00158 $opt['noProxy'] = true;
00159 }
00160
00161
00162 foreach ( $this->test_requesturl as $u ) {
00163 $r = Http::request( "POST", $u, $opt );
00164 $this->assertEquals( self::$content["POST $u"], "$r", "POST $u with ".Http::$httpEngine );
00165 }
00166 }
00167
00168 function testRequestDefault() {
00169 Http::$httpEngine = false;
00170 self::runHTTPRequests();
00171 }
00172
00173 function testRequestPhp() {
00174 if ( !self::$has_fopen ) {
00175 $this->markTestIncomplete( "This test requires allow_url_fopen=true." );
00176 }
00177
00178 Http::$httpEngine = "php";
00179 self::runHTTPRequests();
00180 }
00181
00182 function testRequestCurl() {
00183 if ( !self::$has_curl ) {
00184 $this->markTestIncomplete( "This test requires curl." );
00185 }
00186
00187 Http::$httpEngine = "curl";
00188 self::runHTTPRequests();
00189 }
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235 function runHTTPGets($proxy=null) {
00236 $opt = array();
00237
00238 if($proxy) {
00239 $opt['proxy'] = $proxy;
00240 } elseif( $proxy === false ) {
00241 $opt['noProxy'] = true;
00242 }
00243
00244 foreach ( $this->test_geturl as $u ) {
00245 $r = Http::get( $u, 30, $opt );
00246 $this->assertEquals( self::$content["GET $u"], "$r", "Get $u with ".Http::$httpEngine );
00247 }
00248 }
00249
00250 function testGetDefault() {
00251 Http::$httpEngine = false;
00252 self::runHTTPGets();
00253 }
00254
00255 function testGetPhp() {
00256 if ( !self::$has_fopen ) {
00257 $this->markTestIncomplete( "This test requires allow_url_fopen=true." );
00258 }
00259
00260 Http::$httpEngine = "php";
00261 self::runHTTPGets();
00262 }
00263
00264 function testGetCurl() {
00265 if ( !self::$has_curl ) {
00266 $this->markTestIncomplete( "This test requires curl." );
00267 }
00268
00269 Http::$httpEngine = "curl";
00270 self::runHTTPGets();
00271 }
00272
00273
00274 function runHTTPPosts($proxy=null) {
00275 $opt = array();
00276
00277 if($proxy) {
00278 $opt['proxy'] = $proxy;
00279 } elseif( $proxy === false ) {
00280 $opt['noProxy'] = true;
00281 }
00282
00283 foreach ( $this->test_posturl as $u => $postData ) {
00284 $opt['postData'] = $postData;
00285 $r = Http::post( $u, $opt );
00286 $this->assertEquals( self::$content["POST $u => $postData"], "$r",
00287 "POST $u (postData=$postData) with ".Http::$httpEngine );
00288 }
00289 }
00290
00291 function testPostDefault() {
00292 Http::$httpEngine = false;
00293 self::runHTTPPosts();
00294 }
00295
00296 function testPostPhp() {
00297 if ( !self::$has_fopen ) {
00298 $this->markTestIncomplete( "This test requires allow_url_fopen=true." );
00299 }
00300
00301 Http::$httpEngine = "php";
00302 self::runHTTPPosts();
00303 }
00304
00305 function testPostCurl() {
00306 if ( !self::$has_curl ) {
00307 $this->markTestIncomplete( "This test requires curl." );
00308 }
00309
00310 Http::$httpEngine = "curl";
00311 self::runHTTPPosts();
00312 }
00313
00314 function runProxyRequests() {
00315 if(!self::$has_proxy) {
00316 $this->markTestIncomplete( "This test requires a proxy." );
00317 }
00318 self::runHTTPGets(self::$proxy);
00319 self::runHTTPPosts(self::$proxy);
00320 self::runHTTPRequests(self::$proxy);
00321
00322
00323 self::runHTTPGets(false);
00324 self::runHTTPPosts(false);
00325 self::runHTTPRequests(false);
00326 }
00327
00328 function testProxyDefault() {
00329 Http::$httpEngine = false;
00330 self::runProxyRequests();
00331 }
00332
00333 function testProxyPhp() {
00334 if ( !self::$has_fopen ) {
00335 $this->markTestIncomplete( "This test requires allow_url_fopen=true." );
00336 }
00337
00338 Http::$httpEngine = 'php';
00339 self::runProxyRequests();
00340 }
00341
00342 function testProxyCurl() {
00343 if ( !self::$has_curl ) {
00344 $this->markTestIncomplete( "This test requires curl." );
00345 }
00346
00347 Http::$httpEngine = 'curl';
00348 self::runProxyRequests();
00349 }
00350
00351 function testIsLocalUrl() {
00352 }
00353
00354
00355 function testUserAgent() {
00356 }
00357
00358 function testIsValidUrl() {
00359 }
00360
00361 function testValidateCookieDomain() {
00362 $this->assertFalse( Cookie::validateCookieDomain( "co.uk" ) );
00363 $this->assertFalse( Cookie::validateCookieDomain( ".co.uk" ) );
00364 $this->assertFalse( Cookie::validateCookieDomain( "gov.uk" ) );
00365 $this->assertFalse( Cookie::validateCookieDomain( ".gov.uk" ) );
00366 $this->assertTrue( Cookie::validateCookieDomain( "supermarket.uk" ) );
00367 $this->assertFalse( Cookie::validateCookieDomain( "uk" ) );
00368 $this->assertFalse( Cookie::validateCookieDomain( ".uk" ) );
00369 $this->assertFalse( Cookie::validateCookieDomain( "127.0.0." ) );
00370 $this->assertFalse( Cookie::validateCookieDomain( "127." ) );
00371 $this->assertFalse( Cookie::validateCookieDomain( "127.0.0.1." ) );
00372 $this->assertTrue( Cookie::validateCookieDomain( "127.0.0.1" ) );
00373 $this->assertFalse( Cookie::validateCookieDomain( "333.0.0.1" ) );
00374 $this->assertTrue( Cookie::validateCookieDomain( "example.com" ) );
00375 $this->assertFalse( Cookie::validateCookieDomain( "example.com." ) );
00376 $this->assertTrue( Cookie::validateCookieDomain( ".example.com" ) );
00377
00378 $this->assertTrue( Cookie::validateCookieDomain( ".example.com", "www.example.com" ) );
00379 $this->assertFalse( Cookie::validateCookieDomain( "example.com", "www.example.com" ) );
00380 $this->assertTrue( Cookie::validateCookieDomain( "127.0.0.1", "127.0.0.1" ) );
00381 $this->assertFalse( Cookie::validateCookieDomain( "127.0.0.1", "localhost" ) );
00382
00383
00384 }
00385
00386 function testSetCooke() {
00387 $c = new MockCookie( "name", "value",
00388 array(
00389 "domain" => "ac.th",
00390 "path" => "/path/",
00391 ) );
00392 $this->assertFalse($c->canServeDomain("ac.th"));
00393
00394 $c = new MockCookie( "name", "value",
00395 array(
00396 "domain" => "example.com",
00397 "path" => "/path/",
00398 ) );
00399
00400 $this->assertTrue($c->canServeDomain("example.com"));
00401 $this->assertFalse($c->canServeDomain("www.example.com"));
00402
00403 $c = new MockCookie( "name", "value",
00404 array(
00405 "domain" => ".example.com",
00406 "path" => "/path/",
00407 ) );
00408
00409 $this->assertFalse($c->canServeDomain("www.example.net"));
00410 $this->assertFalse($c->canServeDomain("example.com"));
00411 $this->assertTrue($c->canServeDomain("www.example.com"));
00412
00413 $this->assertFalse($c->canServePath("/"));
00414 $this->assertFalse($c->canServePath("/bogus/path/"));
00415 $this->assertFalse($c->canServePath("/path"));
00416 $this->assertTrue($c->canServePath("/path/"));
00417
00418 $this->assertTrue($c->isUnExpired());
00419
00420 $this->assertEquals("", $c->serializeToHttpRequest("/path/", "www.example.net"));
00421 $this->assertEquals("", $c->serializeToHttpRequest("/", "www.example.com"));
00422 $this->assertEquals("name=value", $c->serializeToHttpRequest("/path/", "www.example.com"));
00423
00424 $c = new MockCookie( "name", "value",
00425 array(
00426 "domain" => "www.example.com",
00427 "path" => "/path/",
00428 ) );
00429 $this->assertFalse($c->canServeDomain("example.com"));
00430 $this->assertFalse($c->canServeDomain("www.example.net"));
00431 $this->assertTrue($c->canServeDomain("www.example.com"));
00432
00433 $c = new MockCookie( "name", "value",
00434 array(
00435 "domain" => ".example.com",
00436 "path" => "/path/",
00437 "expires" => "-1 day",
00438 ) );
00439 $this->assertFalse($c->isUnExpired());
00440 $this->assertEquals("", $c->serializeToHttpRequest("/path/", "www.example.com"));
00441
00442 $c = new MockCookie( "name", "value",
00443 array(
00444 "domain" => ".example.com",
00445 "path" => "/path/",
00446 "expires" => "+1 day",
00447 ) );
00448 $this->assertTrue($c->isUnExpired());
00449 $this->assertEquals("name=value", $c->serializeToHttpRequest("/path/", "www.example.com"));
00450 }
00451
00452 function testCookieJarSetCookie() {
00453 $cj = new CookieJar;
00454 $cj->setCookie( "name", "value",
00455 array(
00456 "domain" => ".example.com",
00457 "path" => "/path/",
00458 ) );
00459 $cj->setCookie( "name2", "value",
00460 array(
00461 "domain" => ".example.com",
00462 "path" => "/path/sub",
00463 ) );
00464 $cj->setCookie( "name3", "value",
00465 array(
00466 "domain" => ".example.com",
00467 "path" => "/",
00468 ) );
00469 $cj->setCookie( "name4", "value",
00470 array(
00471 "domain" => ".example.net",
00472 "path" => "/path/",
00473 ) );
00474 $cj->setCookie( "name5", "value",
00475 array(
00476 "domain" => ".example.net",
00477 "path" => "/path/",
00478 "expires" => "-1 day",
00479 ) );
00480
00481 $this->assertEquals("name4=value", $cj->serializeToHttpRequest("/path/", "www.example.net"));
00482 $this->assertEquals("name3=value", $cj->serializeToHttpRequest("/", "www.example.com"));
00483 $this->assertEquals("name=value; name3=value", $cj->serializeToHttpRequest("/path/", "www.example.com"));
00484
00485 $cj->setCookie( "name5", "value",
00486 array(
00487 "domain" => ".example.net",
00488 "path" => "/path/",
00489 "expires" => "+1 day",
00490 ) );
00491 $this->assertEquals("name4=value; name5=value", $cj->serializeToHttpRequest("/path/", "www.example.net"));
00492
00493 $cj->setCookie( "name4", "value",
00494 array(
00495 "domain" => ".example.net",
00496 "path" => "/path/",
00497 "expires" => "-1 day",
00498 ) );
00499 $this->assertEquals("name5=value", $cj->serializeToHttpRequest("/path/", "www.example.net"));
00500 }
00501
00502 function testParseResponseHeader() {
00503 $cj = new CookieJar;
00504
00505 $h[] = "Set-Cookie: name4=value; domain=.example.com; path=/; expires=Mon, 09-Dec-2029 13:46:00 GMT";
00506 $cj->parseCookieResponseHeader( $h[0], "www.example.com" );
00507 $this->assertEquals("name4=value", $cj->serializeToHttpRequest("/", "www.example.com"));
00508
00509 $h[] = "name4=value2; domain=.example.com; path=/path/; expires=Mon, 09-Dec-2029 13:46:00 GMT";
00510 $cj->parseCookieResponseHeader( $h[1], "www.example.com" );
00511 $this->assertEquals("", $cj->serializeToHttpRequest("/", "www.example.com"));
00512 $this->assertEquals("name4=value2", $cj->serializeToHttpRequest("/path/", "www.example.com"));
00513
00514 $h[] = "name5=value3; domain=.example.com; path=/path/; expires=Mon, 09-Dec-2029 13:46:00 GMT";
00515 $cj->parseCookieResponseHeader( $h[2], "www.example.com" );
00516 $this->assertEquals("name4=value2; name5=value3", $cj->serializeToHttpRequest("/path/", "www.example.com"));
00517
00518 $h[] = "name6=value3; domain=.example.net; path=/path/; expires=Mon, 09-Dec-2029 13:46:00 GMT";
00519 $cj->parseCookieResponseHeader( $h[3], "www.example.com" );
00520 $this->assertEquals("", $cj->serializeToHttpRequest("/path/", "www.example.net"));
00521
00522 $h[] = "name6=value0; domain=.example.net; path=/path/; expires=Mon, 09-Dec-1999 13:46:00 GMT";
00523 $cj->parseCookieResponseHeader( $h[4], "www.example.net" );
00524 $this->assertEquals("", $cj->serializeToHttpRequest("/path/", "www.example.net"));
00525
00526 $h[] = "name6=value4; domain=.example.net; path=/path/; expires=Mon, 09-Dec-2029 13:46:00 GMT";
00527 $cj->parseCookieResponseHeader( $h[5], "www.example.net" );
00528 $this->assertEquals("name6=value4", $cj->serializeToHttpRequest("/path/", "www.example.net"));
00529 }
00530
00531 function runCookieRequests() {
00532 $r = HttpRequest::factory( "http://www.php.net/manual" );
00533 $r->execute();
00534
00535 $jar = $r->getCookieJar();
00536 $this->assertThat( $jar, $this->isInstanceOf( 'CookieJar' ) );
00537
00538 if ( is_a($r, 'PhpHttpRequest') && version_compare( '5.1.7', phpversion(), '>' ) ) {
00539 $this->markTestSkipped( 'Redirection fails or crashes PHP on 5.1.6 and prior' );
00540 }
00541 $serialized = $jar->serializeToHttpRequest( "/search?q=test", "www.php.net" );
00542 $this->assertRegExp( '/\bCOUNTRY=[^=;]+/', $serialized );
00543 $this->assertRegExp( '/\bLAST_LANG=[^=;]+/', $serialized );
00544 $this->assertEquals( '', $jar->serializeToHttpRequest( "/search?q=test", "www.php.com" ) );
00545 }
00546
00547 function testCookieRequestDefault() {
00548 Http::$httpEngine = false;
00549 self::runCookieRequests();
00550 }
00551 function testCookieRequestPhp() {
00552 if ( !self::$has_fopen ) {
00553 $this->markTestIncomplete( "This test requires allow_url_fopen=true." );
00554 }
00555
00556 Http::$httpEngine = 'php';
00557 self::runCookieRequests();
00558 }
00559 function testCookieRequestCurl() {
00560 if ( !self::$has_curl ) {
00561 $this->markTestIncomplete( "This test requires curl." );
00562 }
00563
00564 Http::$httpEngine = 'curl';
00565 self::runCookieRequests();
00566 }
00567 }