MultiHttpClientTest.php 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. <?php
  2. /**
  3. * Tests for MultiHttpClient
  4. *
  5. * The urls herein are not actually called, because we mock the return results.
  6. *
  7. * @covers MultiHttpClient
  8. */
  9. class MultiHttpClientTest extends MediaWikiTestCase {
  10. protected $client;
  11. protected function setUp() {
  12. parent::setUp();
  13. $client = $this->getMockBuilder( MultiHttpClient::class )
  14. ->setConstructorArgs( [ [] ] )
  15. ->setMethods( [ 'isCurlEnabled' ] )->getMock();
  16. $client->method( 'isCurlEnabled' )->willReturn( false );
  17. $this->client = $client;
  18. }
  19. private function getHttpRequest( $statusValue, $statusCode, $headers = [] ) {
  20. $httpRequest = $this->getMockBuilder( PhpHttpRequest::class )
  21. ->setConstructorArgs( [ '', [] ] )
  22. ->getMock();
  23. $httpRequest->expects( $this->any() )
  24. ->method( 'execute' )
  25. ->willReturn( Status::wrap( $statusValue ) );
  26. $httpRequest->expects( $this->any() )
  27. ->method( 'getResponseHeaders' )
  28. ->willReturn( $headers );
  29. $httpRequest->expects( $this->any() )
  30. ->method( 'getStatus' )
  31. ->willReturn( $statusCode );
  32. return $httpRequest;
  33. }
  34. private function mockHttpRequestFactory( $httpRequest ) {
  35. $factory = $this->getMockBuilder( MediaWiki\Http\HttpRequestFactory::class )
  36. ->getMock();
  37. $factory->expects( $this->any() )
  38. ->method( 'create' )
  39. ->willReturn( $httpRequest );
  40. return $factory;
  41. }
  42. /**
  43. * Test call of a single url that should succeed
  44. */
  45. public function testMultiHttpClientSingleSuccess() {
  46. // Mock success
  47. $httpRequest = $this->getHttpRequest( StatusValue::newGood( 200 ), 200 );
  48. $this->setService( 'HttpRequestFactory', $this->mockHttpRequestFactory( $httpRequest ) );
  49. list( $rcode, $rdesc, /* $rhdrs */, $rbody, $rerr ) = $this->client->run( [
  50. 'method' => 'GET',
  51. 'url' => "http://example.test",
  52. ] );
  53. $this->assertEquals( 200, $rcode );
  54. }
  55. /**
  56. * Test call of a single url that should not exist, and therefore fail
  57. */
  58. public function testMultiHttpClientSingleFailure() {
  59. // Mock an invalid tld
  60. $httpRequest = $this->getHttpRequest(
  61. StatusValue::newFatal( 'http-invalid-url', 'http://www.example.test' ), 0 );
  62. $this->setService( 'HttpRequestFactory', $this->mockHttpRequestFactory( $httpRequest ) );
  63. list( $rcode, $rdesc, /* $rhdrs */, $rbody, $rerr ) = $this->client->run( [
  64. 'method' => 'GET',
  65. 'url' => "http://www.example.test",
  66. ] );
  67. $failure = $rcode < 200 || $rcode >= 400;
  68. $this->assertTrue( $failure );
  69. }
  70. /**
  71. * Test call of multiple urls that should all succeed
  72. */
  73. public function testMultiHttpClientMultipleSuccess() {
  74. // Mock success
  75. $httpRequest = $this->getHttpRequest( StatusValue::newGood( 200 ), 200 );
  76. $this->setService( 'HttpRequestFactory', $this->mockHttpRequestFactory( $httpRequest ) );
  77. $reqs = [
  78. [
  79. 'method' => 'GET',
  80. 'url' => 'http://example.test',
  81. ],
  82. [
  83. 'method' => 'GET',
  84. 'url' => 'https://get.test',
  85. ],
  86. ];
  87. $responses = $this->client->runMulti( $reqs );
  88. foreach ( $responses as $response ) {
  89. list( $rcode, $rdesc, /* $rhdrs */, $rbody, $rerr ) = $response['response'];
  90. $this->assertEquals( 200, $rcode );
  91. }
  92. }
  93. /**
  94. * Test call of multiple urls that should all fail
  95. */
  96. public function testMultiHttpClientMultipleFailure() {
  97. // Mock page not found
  98. $httpRequest = $this->getHttpRequest(
  99. StatusValue::newFatal( "http-bad-status", 404, 'Not Found' ), 404 );
  100. $this->setService( 'HttpRequestFactory', $this->mockHttpRequestFactory( $httpRequest ) );
  101. $reqs = [
  102. [
  103. 'method' => 'GET',
  104. 'url' => 'http://example.test/12345',
  105. ],
  106. [
  107. 'method' => 'GET',
  108. 'url' => 'http://example.test/67890' ,
  109. ]
  110. ];
  111. $responses = $this->client->runMulti( $reqs );
  112. foreach ( $responses as $response ) {
  113. list( $rcode, $rdesc, /* $rhdrs */, $rbody, $rerr ) = $response['response'];
  114. $failure = $rcode < 200 || $rcode >= 400;
  115. $this->assertTrue( $failure );
  116. }
  117. }
  118. /**
  119. * Test of response header handling
  120. */
  121. public function testMultiHttpClientHeaders() {
  122. // Represenative headers for typical requests, per MWHttpRequest::getResponseHeaders()
  123. $headers = [
  124. 'content-type' => [
  125. 'text/html; charset=utf-8',
  126. ],
  127. 'date' => [
  128. 'Wed, 18 Jul 2018 14:52:41 GMT',
  129. ],
  130. 'set-cookie' => [
  131. 'COUNTRY=NAe6; expires=Wed, 25-Jul-2018 14:52:41 GMT; path=/; domain=.example.test',
  132. 'LAST_NEWS=1531925562; expires=Thu, 18-Jul-2019 14:52:41 GMT; path=/; domain=.example.test',
  133. ]
  134. ];
  135. // Mock success with specific headers
  136. $httpRequest = $this->getHttpRequest( StatusValue::newGood( 200 ), 200, $headers );
  137. $this->setService( 'HttpRequestFactory', $this->mockHttpRequestFactory( $httpRequest ) );
  138. list( $rcode, $rdesc, $rhdrs, $rbody, $rerr ) = $this->client->run( [
  139. 'method' => 'GET',
  140. 'url' => 'http://example.test',
  141. ] );
  142. $this->assertEquals( 200, $rcode );
  143. $this->assertEquals( count( $headers ), count( $rhdrs ) );
  144. foreach ( $headers as $name => $values ) {
  145. $value = implode( ', ', $values );
  146. $this->assertArrayHasKey( $name, $rhdrs );
  147. $this->assertEquals( $value, $rhdrs[$name] );
  148. }
  149. }
  150. }