Merge "Move section ID fallbacks into headers themselves"
[lhc/web/wiklou.git] / tests / phpunit / includes / config / EtcdConfigTest.php
index 763bfa8..c13cf25 100644 (file)
@@ -1,5 +1,7 @@
 <?php
 
+use Wikimedia\TestingAccessWrapper;
+
 class EtcConfigTest extends PHPUnit_Framework_TestCase {
 
        private function createConfigMock( array $options = [] ) {
@@ -88,7 +90,7 @@ class EtcConfigTest extends PHPUnit_Framework_TestCase {
         */
        public function testConstructCacheSpec() {
                $config = $this->createConfigMock( [ 'cache' => [
-                       'class' =>  HashBagOStuff::class
+                       'class' => HashBagOStuff::class
                ] ] );
                $config->expects( $this->once() )->method( 'fetchAllFromEtcd' )
                        ->willReturn( [
@@ -359,4 +361,155 @@ class EtcConfigTest extends PHPUnit_Framework_TestCase {
 
                $this->assertSame( 'from-cache-expired', $mock->get( 'known' ) );
        }
+
+       public static function provideFetchFromServer() {
+               return [
+                       '200 OK - Success' => [
+                               'http' => [
+                                       'code' => 200,
+                                       'reason' => 'OK',
+                                       'headers' => [],
+                                       'body' => json_encode( [ 'node' => [ 'nodes' => [
+                                               [
+                                                       'key' => '/example/foo',
+                                                       'value' => json_encode( [ 'val' => true ] )
+                                               ],
+                                       ] ] ] ),
+                                       'error' => '',
+                               ],
+                               'expect' => [
+                                       [ 'foo' => true ], // data
+                                       null,
+                                       false // retry
+                               ],
+                       ],
+                       '200 OK - Skip dir' => [
+                               'http' => [
+                                       'code' => 200,
+                                       'reason' => 'OK',
+                                       'headers' => [],
+                                       'body' => json_encode( [ 'node' => [ 'nodes' => [
+                                               [
+                                                       'key' => '/example/foo',
+                                                       'value' => json_encode( [ 'val' => true ] )
+                                               ],
+                                               [
+                                                       'key' => '/example/sub',
+                                                       'dir' => true
+                                               ],
+                                               [
+                                                       'key' => '/example/bar',
+                                                       'value' => json_encode( [ 'val' => false ] )
+                                               ],
+                                       ] ] ] ),
+                                       'error' => '',
+                               ],
+                               'expect' => [
+                                       [ 'foo' => true, 'bar' => false ], // data
+                                       null,
+                                       false // retry
+                               ],
+                       ],
+                       '200 OK - Bad value' => [
+                               'http' => [
+                                       'code' => 200,
+                                       'reason' => 'OK',
+                                       'headers' => [],
+                                       'body' => json_encode( [ 'node' => [ 'nodes' => [
+                                               [
+                                                       'key' => '/example/foo',
+                                                       'value' => ';"broken{value'
+                                               ]
+                                       ] ] ] ),
+                                       'error' => '',
+                               ],
+                               'expect' => [
+                                       null, // data
+                                       "Failed to parse value for 'foo'.",
+                                       false // retry
+                               ],
+                       ],
+                       '200 OK - Empty node list' => [
+                               'http' => [
+                                       'code' => 200,
+                                       'reason' => 'OK',
+                                       'headers' => [],
+                                       'body' => '{"node":{"nodes":[]}}',
+                                       'error' => '',
+                               ],
+                               'expect' => [
+                                       [], // data
+                                       null,
+                                       false // retry
+                               ],
+                       ],
+                       '200 OK - Invalid JSON' => [
+                               'http' => [
+                                       'code' => 200,
+                                       'reason' => 'OK',
+                                       'headers' => [ 'content-length' => 0 ],
+                                       'body' => '',
+                                       'error' => '(curl error: no status set)',
+                               ],
+                               'expect' => [
+                                       null, // data
+                                       "Unexpected JSON response; missing 'nodes' list.",
+                                       false // retry
+                               ],
+                       ],
+                       '404 Not Found' => [
+                               'http' => [
+                                       'code' => 404,
+                                       'reason' => 'Not Found',
+                                       'headers' => [ 'content-length' => 0 ],
+                                       'body' => '',
+                                       'error' => '',
+                               ],
+                               'expect' => [
+                                       null, // data
+                                       'HTTP 404 (Not Found)',
+                                       false // retry
+                               ],
+                       ],
+                       '400 Bad Request - custom error' => [
+                               'http' => [
+                                       'code' => 400,
+                                       'reason' => 'Bad Request',
+                                       'headers' => [ 'content-length' => 0 ],
+                                       'body' => '',
+                                       'error' => 'No good reason',
+                               ],
+                               'expect' => [
+                                       null, // data
+                                       'No good reason',
+                                       true // retry
+                               ],
+                       ],
+               ];
+       }
+
+       /**
+        * @covers EtcdConfig::fetchAllFromEtcdServer
+        * @covers EtcdConfig::unserialize
+        * @dataProvider provideFetchFromServer
+        */
+       public function testFetchFromServer( array $httpResponse, array $expected ) {
+               $http = $this->getMockBuilder( MultiHttpClient::class )
+                       ->disableOriginalConstructor()
+                       ->getMock();
+               $http->expects( $this->once() )->method( 'run' )
+                       ->willReturn( array_values( $httpResponse ) );
+
+               $conf = $this->getMockBuilder( EtcdConfig::class )
+                       ->disableOriginalConstructor()
+                       ->getMock();
+               // Access for protected member and method
+               $conf = TestingAccessWrapper::newFromObject( $conf );
+               $conf->http = $http;
+
+               $this->assertSame(
+                       $expected,
+                       $conf->fetchAllFromEtcdServer( 'etcd-tcp.example.net' )
+               );
+       }
 }