ComposerRepositoryTest.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. <?php
  2. /*
  3. * This file is part of Composer.
  4. *
  5. * (c) Nils Adermann <naderman@naderman.de>
  6. * Jordi Boggiano <j.boggiano@seld.be>
  7. *
  8. * For the full copyright and license information, please view the LICENSE
  9. * file that was distributed with this source code.
  10. */
  11. namespace Composer\Test\Repository;
  12. use Composer\IO\NullIO;
  13. use Composer\Repository\ComposerRepository;
  14. use Composer\Repository\RepositoryInterface;
  15. use Composer\Test\Mock\FactoryMock;
  16. use Composer\Test\TestCase;
  17. use Composer\Package\Loader\ArrayLoader;
  18. use Composer\Package\Version\VersionParser;
  19. class ComposerRepositoryTest extends TestCase
  20. {
  21. /**
  22. * @dataProvider loadDataProvider
  23. */
  24. public function testLoadData(array $expected, array $repoPackages)
  25. {
  26. $repoConfig = array(
  27. 'url' => 'http://example.org',
  28. );
  29. $repository = $this->getMockBuilder('Composer\Repository\ComposerRepository')
  30. ->setMethods(array('loadRootServerFile', 'createPackages'))
  31. ->setConstructorArgs(array(
  32. $repoConfig,
  33. new NullIO,
  34. FactoryMock::createConfig(),
  35. $this->getMockBuilder('Composer\Util\HttpDownloader')->disableOriginalConstructor()->getMock(),
  36. $this->getMockBuilder('Composer\EventDispatcher\EventDispatcher')->disableOriginalConstructor()->getMock()
  37. ))
  38. ->getMock();
  39. $repository
  40. ->expects($this->exactly(2))
  41. ->method('loadRootServerFile')
  42. ->will($this->returnValue($repoPackages));
  43. $stubs = array();
  44. foreach ($expected as $at => $arg) {
  45. $stubs[] = $this->getPackage('stub/stub', '1.0.0');
  46. }
  47. $repository
  48. ->expects($this->at(2))
  49. ->method('createPackages')
  50. ->with($this->identicalTo($expected), $this->equalTo('Composer\Package\CompletePackage'))
  51. ->will($this->returnValue($stubs));
  52. // Triggers initialization
  53. $packages = $repository->getPackages();
  54. // Final sanity check, ensure the correct number of packages were added.
  55. $this->assertCount(count($expected), $packages);
  56. }
  57. public function loadDataProvider()
  58. {
  59. return array(
  60. // Old repository format
  61. array(
  62. array(
  63. array('name' => 'foo/bar', 'version' => '1.0.0'),
  64. ),
  65. array('foo/bar' => array(
  66. 'name' => 'foo/bar',
  67. 'versions' => array(
  68. '1.0.0' => array('name' => 'foo/bar', 'version' => '1.0.0'),
  69. ),
  70. )),
  71. ),
  72. // New repository format
  73. array(
  74. array(
  75. array('name' => 'bar/foo', 'version' => '3.14'),
  76. array('name' => 'bar/foo', 'version' => '3.145'),
  77. ),
  78. array('packages' => array(
  79. 'bar/foo' => array(
  80. '3.14' => array('name' => 'bar/foo', 'version' => '3.14'),
  81. '3.145' => array('name' => 'bar/foo', 'version' => '3.145'),
  82. ),
  83. )),
  84. ),
  85. );
  86. }
  87. public function testWhatProvides()
  88. {
  89. $repo = $this->getMockBuilder('Composer\Repository\ComposerRepository')
  90. ->setConstructorArgs(array(
  91. array('url' => 'https://dummy.test.link'),
  92. new NullIO,
  93. FactoryMock::createConfig(),
  94. $this->getMockBuilder('Composer\Util\HttpDownloader')->disableOriginalConstructor()->getMock(),
  95. $this->getMockBuilder('Composer\EventDispatcher\EventDispatcher')->disableOriginalConstructor()->getMock()
  96. ))
  97. ->setMethods(array('fetchFile'))
  98. ->getMock();
  99. $cache = $this->getMockBuilder('Composer\Cache')->disableOriginalConstructor()->getMock();
  100. $cache->expects($this->any())
  101. ->method('sha256')
  102. ->will($this->returnValue(false));
  103. $properties = array(
  104. 'cache' => $cache,
  105. 'loader' => new ArrayLoader(),
  106. 'providerListing' => array('a' => array('sha256' => 'xxx')),
  107. 'providersUrl' => 'https://dummy.test.link/to/%package%/file',
  108. );
  109. foreach ($properties as $property => $value) {
  110. $ref = new \ReflectionProperty($repo, $property);
  111. $ref->setAccessible(true);
  112. $ref->setValue($repo, $value);
  113. }
  114. $repo->expects($this->any())
  115. ->method('fetchFile')
  116. ->will($this->returnValue(array(
  117. 'packages' => array(
  118. array(array(
  119. 'uid' => 1,
  120. 'name' => 'a',
  121. 'version' => 'dev-master',
  122. 'extra' => array('branch-alias' => array('dev-master' => '1.0.x-dev')),
  123. )),
  124. array(array(
  125. 'uid' => 2,
  126. 'name' => 'a',
  127. 'version' => 'dev-develop',
  128. 'extra' => array('branch-alias' => array('dev-develop' => '1.1.x-dev')),
  129. )),
  130. array(array(
  131. 'uid' => 3,
  132. 'name' => 'a',
  133. 'version' => '0.6',
  134. )),
  135. ),
  136. )));
  137. $versionParser = new VersionParser();
  138. $reflMethod = new \ReflectionMethod($repo, 'whatProvides');
  139. $reflMethod->setAccessible(true);
  140. $packages = $reflMethod->invoke($repo, 'a');
  141. $this->assertCount(5, $packages);
  142. $this->assertEquals(array('1', '1-alias', '2', '2-alias', '3'), array_keys($packages));
  143. $this->assertSame($packages['2'], $packages['2-alias']->getAliasOf());
  144. }
  145. public function isPackageAcceptableReturnTrue()
  146. {
  147. return true;
  148. }
  149. public function testSearchWithType()
  150. {
  151. $repoConfig = array(
  152. 'url' => 'http://example.org',
  153. );
  154. $result = array(
  155. 'results' => array(
  156. array(
  157. 'name' => 'foo',
  158. 'description' => null,
  159. ),
  160. ),
  161. );
  162. $httpDownloader = $this->getMockBuilder('Composer\Util\HttpDownloader')
  163. ->disableOriginalConstructor()
  164. ->getMock();
  165. $eventDispatcher = $this->getMockBuilder('Composer\EventDispatcher\EventDispatcher')
  166. ->disableOriginalConstructor()
  167. ->getMock();
  168. $httpDownloader->expects($this->at(0))
  169. ->method('get')
  170. ->with($url = 'http://example.org/packages.json')
  171. ->willReturn(new \Composer\Util\Http\Response(array('url' => $url), 200, array(), json_encode(array('search' => '/search.json?q=%query%&type=%type%'))));
  172. $httpDownloader->expects($this->at(1))
  173. ->method('get')
  174. ->with($url = 'http://example.org/search.json?q=foo&type=composer-plugin')
  175. ->willReturn(new \Composer\Util\Http\Response(array('url' => $url), 200, array(), json_encode($result)));
  176. $httpDownloader->expects($this->at(2))
  177. ->method('get')
  178. ->with($url = 'http://example.org/search.json?q=foo&type=library')
  179. ->willReturn(new \Composer\Util\Http\Response(array('url' => $url), 200, array(), json_encode(array())));
  180. $repository = new ComposerRepository($repoConfig, new NullIO, FactoryMock::createConfig(), $httpDownloader, $eventDispatcher);
  181. $this->assertSame(
  182. array(array('name' => 'foo', 'description' => null)),
  183. $repository->search('foo', RepositoryInterface::SEARCH_FULLTEXT, 'composer-plugin')
  184. );
  185. $this->assertEmpty(
  186. $repository->search('foo', RepositoryInterface::SEARCH_FULLTEXT, 'library')
  187. );
  188. }
  189. /**
  190. * @dataProvider canonicalizeUrlProvider
  191. *
  192. * @param string $expected
  193. * @param string $url
  194. * @param string $repositoryUrl
  195. */
  196. public function testCanonicalizeUrl($expected, $url, $repositoryUrl)
  197. {
  198. $repository = new ComposerRepository(
  199. array('url' => $repositoryUrl),
  200. new NullIO(),
  201. FactoryMock::createConfig(),
  202. $this->getMockBuilder('Composer\Util\HttpDownloader')->disableOriginalConstructor()->getMock(),
  203. $this->getMockBuilder('Composer\EventDispatcher\EventDispatcher')->disableOriginalConstructor()->getMock()
  204. );
  205. $object = new \ReflectionObject($repository);
  206. $method = $object->getMethod('canonicalizeUrl');
  207. $method->setAccessible(true);
  208. // ComposerRepository::__construct ensures that the repository URL has a
  209. // protocol, so reset it here in order to test all cases.
  210. $property = $object->getProperty('url');
  211. $property->setAccessible(true);
  212. $property->setValue($repository, $repositoryUrl);
  213. $this->assertSame($expected, $method->invoke($repository, $url));
  214. }
  215. public function canonicalizeUrlProvider()
  216. {
  217. return array(
  218. array(
  219. 'https://example.org/path/to/file',
  220. '/path/to/file',
  221. 'https://example.org',
  222. ),
  223. array(
  224. 'https://example.org/canonic_url',
  225. 'https://example.org/canonic_url',
  226. 'https://should-not-see-me.test',
  227. ),
  228. array(
  229. 'file:///path/to/repository/file',
  230. '/path/to/repository/file',
  231. 'file:///path/to/repository',
  232. ),
  233. array(
  234. // Assert that the repository URL is returned unchanged if it is
  235. // not a URL.
  236. // (Backward compatibility test)
  237. 'invalid_repo_url',
  238. '/path/to/file',
  239. 'invalid_repo_url',
  240. ),
  241. array(
  242. // Assert that URLs can contain sequences resembling pattern
  243. // references as understood by preg_replace() without messing up
  244. // the result.
  245. // (Regression test)
  246. 'https://example.org/path/to/unusual_$0_filename',
  247. '/path/to/unusual_$0_filename',
  248. 'https://example.org',
  249. ),
  250. );
  251. }
  252. public function testGetProviderNamesWillReturnPartialPackageNames()
  253. {
  254. $httpDownloader = $this->getMockBuilder('Composer\Util\HttpDownloader')
  255. ->disableOriginalConstructor()
  256. ->getMock();
  257. $httpDownloader->expects($this->at(0))
  258. ->method('get')
  259. ->with($url = 'http://example.org/packages.json')
  260. ->willReturn(new \Composer\Util\Http\Response(array('url' => $url), 200, array(), json_encode(array(
  261. 'providers-lazy-url' => '/foo/p/%package%.json',
  262. 'packages' => array('foo/bar' => array(
  263. 'dev-branch' => array('name' => 'foo/bar'),
  264. 'v1.0.0' => array('name' => 'foo/bar'),
  265. ))
  266. ))));
  267. $repository = new ComposerRepository(
  268. array('url' => 'http://example.org/packages.json'),
  269. new NullIO(),
  270. FactoryMock::createConfig(),
  271. $httpDownloader
  272. );
  273. $this->assertEquals(array('foo/bar'), $repository->getPackageNames());
  274. }
  275. }