2012-06-09 05:48:04 +00:00
< ? php
/*
* This file is part of Composer .
*
* ( c ) Nils Adermann < naderman @ naderman . de >
* Jordi Boggiano < j . boggiano @ seld . be >
*
* For the full copyright and license information , please view the LICENSE
* file that was distributed with this source code .
*/
namespace Composer\Test\Mock ;
2021-12-09 16:09:07 +00:00
use Composer\Config ;
use Composer\IO\BufferIO ;
use Composer\IO\IOInterface ;
2018-10-31 11:44:54 +00:00
use Composer\Util\HttpDownloader ;
use Composer\Util\Http\Response ;
2012-06-09 05:48:52 +00:00
use Composer\Downloader\TransportException ;
2021-12-09 16:09:07 +00:00
use PHPUnit\Framework\Assert ;
use PHPUnit\Framework\AssertionFailedError ;
2012-06-09 05:48:04 +00:00
2018-10-31 11:44:54 +00:00
class HttpDownloaderMock extends HttpDownloader
2012-06-09 05:48:04 +00:00
{
2021-10-16 08:16:06 +00:00
/**
2021-12-09 16:09:07 +00:00
* @ var array < array { url : string , options : array < mixed >| null , status : int , body : string , headers : list < string > } >| null
2021-10-16 08:16:06 +00:00
*/
2021-12-09 16:09:07 +00:00
private $expectations = null ;
/**
* @ var bool
*/
private $strict = false ;
/**
* @ var array { status : int , body : string , headers : array < string > }
*/
private $defaultHandler = array ( 'status' => 200 , 'body' => '' , 'headers' => []);
/**
* @ var string []
*/
private $log = array ();
public function __construct ( IOInterface $io = null , Config $config = null )
{
if ( $io === null ) {
$io = new BufferIO ();
}
if ( $config === null ) {
$config = new Config ( false );
}
parent :: __construct ( $io , $config );
}
2018-01-06 14:05:39 +00:00
2012-06-09 05:48:04 +00:00
/**
2021-12-09 16:09:07 +00:00
* @ param array < array { url : string , options ? : array < mixed > , status ? : int , body ? : string , headers ? : array < string > } > $expectations
* @ param bool $strict set to true if you want to provide * all * expected http requests , and not just a subset you are interested in testing
* @ param array { status ? : int , body ? : string , headers ? : array < string > } $defaultHandler default URL handler for undefined requests if not in strict mode
2012-06-09 05:48:04 +00:00
*/
2021-12-09 21:14:04 +00:00
public function expects ( array $expectations , bool $strict = false , array $defaultHandler = array ( 'status' => 200 , 'body' => '' , 'headers' => [])) : void
2012-06-09 05:48:04 +00:00
{
2021-12-09 16:09:07 +00:00
$default = [ 'url' => '' , 'options' => null , 'status' => 200 , 'body' => '' , 'headers' => [ '' ]];
$this -> expectations = array_map ( function ( array $expect ) use ( $default ) : array {
2021-12-09 21:14:04 +00:00
if ( count ( $diff = array_diff_key ( array_merge ( $default , $expect ), $default )) > 0 ) {
2021-12-09 16:09:07 +00:00
throw new \UnexpectedValueException ( 'Unexpected keys in process execution step: ' . implode ( ', ' , array_keys ( $diff )));
}
2022-02-16 12:24:57 +00:00
// set defaults in a PHPStan-happy way (array_merge is not well supported)
$expect [ 'url' ] = $expect [ 'url' ] ? ? $default [ 'url' ];
$expect [ 'options' ] = $expect [ 'options' ] ? ? $default [ 'options' ];
$expect [ 'status' ] = $expect [ 'status' ] ? ? $default [ 'status' ];
$expect [ 'body' ] = $expect [ 'body' ] ? ? $default [ 'body' ];
$expect [ 'headers' ] = $expect [ 'headers' ] ? ? $default [ 'headers' ];
return $expect ;
2021-12-09 16:09:07 +00:00
}, $expectations );
$this -> strict = $strict ;
2022-02-16 12:24:57 +00:00
// set defaults in a PHPStan-happy way (array_merge is not well supported)
$defaultHandler [ 'status' ] = $defaultHandler [ 'status' ] ? ? $this -> defaultHandler [ 'status' ];
$defaultHandler [ 'body' ] = $defaultHandler [ 'body' ] ? ? $this -> defaultHandler [ 'body' ];
$defaultHandler [ 'headers' ] = $defaultHandler [ 'headers' ] ? ? $this -> defaultHandler [ 'headers' ];
$this -> defaultHandler = $defaultHandler ;
2012-06-09 05:48:04 +00:00
}
2021-12-09 16:09:07 +00:00
public function assertComplete () : void
2012-06-09 05:48:04 +00:00
{
2021-12-09 16:09:07 +00:00
// this was not configured to expect anything, so no need to react here
if ( ! is_array ( $this -> expectations )) {
return ;
2012-06-09 05:48:52 +00:00
}
2012-06-09 05:48:04 +00:00
2021-12-09 16:09:07 +00:00
if ( count ( $this -> expectations ) > 0 ) {
2022-02-21 12:42:28 +00:00
$expectations = array_map ( function ( $expect ) : string {
2021-12-09 16:09:07 +00:00
return $expect [ 'url' ];
}, $this -> expectations );
throw new AssertionFailedError (
'There are still ' . count ( $this -> expectations ) . ' expected HTTP requests which have not been consumed:' . PHP_EOL .
implode ( PHP_EOL , $expectations ) . PHP_EOL . PHP_EOL .
'Received calls:' . PHP_EOL . implode ( PHP_EOL , $this -> log )
);
}
// dummy assertion to ensure the test is not marked as having no assertions
2021-12-09 21:14:04 +00:00
Assert :: assertTrue ( true ); // @phpstan-ignore-line
2021-12-09 16:09:07 +00:00
}
public function get ( $fileUrl , $options = array ()) : Response
{
$this -> log [] = $fileUrl ;
if ( is_array ( $this -> expectations ) && count ( $this -> expectations ) > 0 && $fileUrl === $this -> expectations [ 0 ][ 'url' ] && ( $this -> expectations [ 0 ][ 'options' ] === null || $options === $this -> expectations [ 0 ][ 'options' ])) {
$expect = array_shift ( $this -> expectations );
return $this -> respond ( $fileUrl , $expect [ 'status' ], $expect [ 'headers' ], $expect [ 'body' ]);
}
if ( ! $this -> strict ) {
return $this -> respond ( $fileUrl , $this -> defaultHandler [ 'status' ], $this -> defaultHandler [ 'headers' ], $this -> defaultHandler [ 'body' ]);
}
throw new AssertionFailedError (
'Received unexpected request for "' . $fileUrl . '"' . PHP_EOL .
( is_array ( $this -> expectations ) && count ( $this -> expectations ) > 0 ? 'Expected "' . $this -> expectations [ 0 ][ 'url' ] . '" at this point.' : 'Expected no more calls at this point.' ) . PHP_EOL .
'Received calls:' . PHP_EOL . implode ( PHP_EOL , array_slice ( $this -> log , 0 , - 1 ))
);
}
/**
* @ param string [] $headers
*/
private function respond ( string $url , int $status , array $headers , string $body ) : Response
{
if ( $status < 400 ) {
return new Response ( array ( 'url' => $url ), $status , $headers , $body );
}
$e = new TransportException ( 'The "' . $url . '" file could not be downloaded' , $status );
$e -> setHeaders ( $headers );
$e -> setResponse ( $body );
throw $e ;
2012-06-09 05:48:04 +00:00
}
}