VersionSelectorTest.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  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\Package\Version;
  12. use Composer\Package\Version\VersionSelector;
  13. use Composer\Package\Package;
  14. use Composer\Package\Link;
  15. use Composer\Semver\VersionParser;
  16. use Composer\Test\TestCase;
  17. class VersionSelectorTest extends TestCase
  18. {
  19. // A) multiple versions, get the latest one
  20. // B) targetPackageVersion will pass to pool
  21. // C) No results, throw exception
  22. public function testLatestVersionIsReturned()
  23. {
  24. $packageName = 'foobar';
  25. $package1 = $this->createPackage('1.2.1');
  26. $package2 = $this->createPackage('1.2.2');
  27. $package3 = $this->createPackage('1.2.0');
  28. $packages = array($package1, $package2, $package3);
  29. $pool = $this->createMockPool();
  30. $pool->expects($this->once())
  31. ->method('whatProvides')
  32. ->with($packageName, null, true)
  33. ->will($this->returnValue($packages));
  34. $versionSelector = new VersionSelector($pool);
  35. $best = $versionSelector->findBestCandidate($packageName);
  36. // 1.2.2 should be returned because it's the latest of the returned versions
  37. $this->assertSame($package2, $best, 'Latest version should be 1.2.2');
  38. }
  39. public function testLatestVersionIsReturnedThatMatchesPhpRequirement()
  40. {
  41. $packageName = 'foobar';
  42. $parser = new VersionParser;
  43. $package1 = $this->createPackage('1.0.0');
  44. $package2 = $this->createPackage('2.0.0');
  45. $package1->setRequires(array('php' => new Link($packageName, 'php', $parser->parseConstraints('>=5.4'), 'requires', '>=5.4')));
  46. $package2->setRequires(array('php' => new Link($packageName, 'php', $parser->parseConstraints('>=5.6'), 'requires', '>=5.6')));
  47. $packages = array($package1, $package2);
  48. $pool = $this->createMockPool();
  49. $pool->expects($this->once())
  50. ->method('whatProvides')
  51. ->with($packageName, null, true)
  52. ->will($this->returnValue($packages));
  53. $versionSelector = new VersionSelector($pool);
  54. $best = $versionSelector->findBestCandidate($packageName, null, '5.5.0');
  55. $this->assertSame($package1, $best, 'Latest version supporting php 5.5 should be returned (1.0.0)');
  56. }
  57. public function testMostStableVersionIsReturned()
  58. {
  59. $packageName = 'foobar';
  60. $package1 = $this->createPackage('1.0.0');
  61. $package2 = $this->createPackage('1.1.0-beta');
  62. $packages = array($package1, $package2);
  63. $pool = $this->createMockPool();
  64. $pool->expects($this->once())
  65. ->method('whatProvides')
  66. ->with($packageName, null, true)
  67. ->will($this->returnValue($packages));
  68. $versionSelector = new VersionSelector($pool);
  69. $best = $versionSelector->findBestCandidate($packageName);
  70. $this->assertSame($package1, $best, 'Latest most stable version should be returned (1.0.0)');
  71. }
  72. public function testMostStableVersionIsReturnedRegardlessOfOrder()
  73. {
  74. $packageName = 'foobar';
  75. $package1 = $this->createPackage('2.x-dev');
  76. $package2 = $this->createPackage('2.0.0-beta3');
  77. $packages = array($package1, $package2);
  78. $pool = $this->createMockPool();
  79. $pool->expects($this->at(0))
  80. ->method('whatProvides')
  81. ->with($packageName, null, true)
  82. ->will($this->returnValue($packages));
  83. $pool->expects($this->at(1))
  84. ->method('whatProvides')
  85. ->with($packageName, null, true)
  86. ->will($this->returnValue(array_reverse($packages)));
  87. $versionSelector = new VersionSelector($pool);
  88. $best = $versionSelector->findBestCandidate($packageName, null, null);
  89. $this->assertSame($package2, $best, 'Expecting 2.0.0-beta3, cause beta is more stable than dev');
  90. $best = $versionSelector->findBestCandidate($packageName, null, null);
  91. $this->assertSame($package2, $best, 'Expecting 2.0.0-beta3, cause beta is more stable than dev');
  92. }
  93. public function testHighestVersionIsReturned()
  94. {
  95. $packageName = 'foobar';
  96. $package1 = $this->createPackage('1.0.0');
  97. $package2 = $this->createPackage('1.1.0-beta');
  98. $packages = array($package1, $package2);
  99. $pool = $this->createMockPool();
  100. $pool->expects($this->once())
  101. ->method('whatProvides')
  102. ->with($packageName, null, true)
  103. ->will($this->returnValue($packages));
  104. $versionSelector = new VersionSelector($pool);
  105. $best = $versionSelector->findBestCandidate($packageName, null, null, 'dev');
  106. $this->assertSame($package2, $best, 'Latest version should be returned (1.1.0-beta)');
  107. }
  108. public function testHighestVersionMatchingStabilityIsReturned()
  109. {
  110. $packageName = 'foobar';
  111. $package1 = $this->createPackage('1.0.0');
  112. $package2 = $this->createPackage('1.1.0-beta');
  113. $package3 = $this->createPackage('1.2.0-alpha');
  114. $packages = array($package1, $package2, $package3);
  115. $pool = $this->createMockPool();
  116. $pool->expects($this->once())
  117. ->method('whatProvides')
  118. ->with($packageName, null, true)
  119. ->will($this->returnValue($packages));
  120. $versionSelector = new VersionSelector($pool);
  121. $best = $versionSelector->findBestCandidate($packageName, null, null, 'beta');
  122. $this->assertSame($package2, $best, 'Latest version should be returned (1.1.0-beta)');
  123. }
  124. public function testMostStableUnstableVersionIsReturned()
  125. {
  126. $packageName = 'foobar';
  127. $package2 = $this->createPackage('1.1.0-beta');
  128. $package3 = $this->createPackage('1.2.0-alpha');
  129. $packages = array($package2, $package3);
  130. $pool = $this->createMockPool();
  131. $pool->expects($this->once())
  132. ->method('whatProvides')
  133. ->with($packageName, null, true)
  134. ->will($this->returnValue($packages));
  135. $versionSelector = new VersionSelector($pool);
  136. $best = $versionSelector->findBestCandidate($packageName, null, null, 'stable');
  137. $this->assertSame($package2, $best, 'Latest version should be returned (1.1.0-beta)');
  138. }
  139. public function testFalseReturnedOnNoPackages()
  140. {
  141. $pool = $this->createMockPool();
  142. $pool->expects($this->once())
  143. ->method('whatProvides')
  144. ->will($this->returnValue(array()));
  145. $versionSelector = new VersionSelector($pool);
  146. $best = $versionSelector->findBestCandidate('foobaz');
  147. $this->assertFalse($best, 'No versions are available returns false');
  148. }
  149. /**
  150. * @dataProvider getRecommendedRequireVersionPackages
  151. */
  152. public function testFindRecommendedRequireVersion($prettyVersion, $isDev, $stability, $expectedVersion, $branchAlias = null)
  153. {
  154. $pool = $this->createMockPool();
  155. $versionSelector = new VersionSelector($pool);
  156. $versionParser = new VersionParser();
  157. $package = $this->getMockBuilder('\Composer\Package\PackageInterface')->getMock();
  158. $package
  159. ->expects($this->any())
  160. ->method('getPrettyVersion')
  161. ->will($this->returnValue($prettyVersion));
  162. $package
  163. ->expects($this->any())
  164. ->method('getVersion')
  165. ->will($this->returnValue($versionParser->normalize($prettyVersion)));
  166. $package
  167. ->expects($this->any())
  168. ->method('isDev')
  169. ->will($this->returnValue($isDev));
  170. $package
  171. ->expects($this->any())
  172. ->method('getStability')
  173. ->will($this->returnValue($stability));
  174. $package
  175. ->expects($this->any())
  176. ->method('getTransportOptions')
  177. ->will($this->returnValue(array()));
  178. $branchAlias = $branchAlias === null ? array() : array('branch-alias' => array($prettyVersion => $branchAlias));
  179. $package->expects($this->any())
  180. ->method('getExtra')
  181. ->will($this->returnValue($branchAlias));
  182. $recommended = $versionSelector->findRecommendedRequireVersion($package);
  183. // assert that the recommended version is what we expect
  184. $this->assertSame($expectedVersion, $recommended);
  185. }
  186. public function getRecommendedRequireVersionPackages()
  187. {
  188. return array(
  189. // real version, is dev package, stability, expected recommendation, [branch-alias]
  190. array('1.2.1', false, 'stable', '^1.2'),
  191. array('1.2', false, 'stable', '^1.2'),
  192. array('v1.2.1', false, 'stable', '^1.2'),
  193. array('3.1.2-pl2', false, 'stable', '^3.1'),
  194. array('3.1.2-patch', false, 'stable', '^3.1'),
  195. array('2.0-beta.1', false, 'beta', '^2.0@beta'),
  196. array('3.1.2-alpha5', false, 'alpha', '^3.1@alpha'),
  197. array('3.0-RC2', false, 'RC', '^3.0@RC'),
  198. array('0.1.0', false, 'stable', '^0.1.0'),
  199. array('0.1.3', false, 'stable', '^0.1.3'),
  200. array('0.0.3', false, 'stable', '^0.0.3'),
  201. array('0.0.3-alpha', false, 'alpha', '^0.0.3@alpha'),
  202. // date-based versions are not touched at all
  203. array('v20121020', false, 'stable', 'v20121020'),
  204. array('v20121020.2', false, 'stable', 'v20121020.2'),
  205. // dev packages without alias are not touched at all
  206. array('dev-master', true, 'dev', 'dev-master'),
  207. array('3.1.2-dev', true, 'dev', '3.1.2-dev'),
  208. // dev packages with alias inherit the alias
  209. array('dev-master', true, 'dev', '^2.1@dev', '2.1.x-dev'),
  210. array('dev-master', true, 'dev', '^2.1@dev', '2.1-dev'),
  211. array('dev-master', true, 'dev', '^2.1@dev', '2.1.3.x-dev'),
  212. array('dev-master', true, 'dev', '^2.0@dev', '2.x-dev'),
  213. array('dev-master', true, 'dev', '^0.3.0@dev', '0.3.x-dev'),
  214. array('dev-master', true, 'dev', '^0.0.3@dev', '0.0.3.x-dev'),
  215. // numeric alias
  216. array('3.x-dev', true, 'dev', '^3.0@dev', '3.0.x-dev'),
  217. array('3.x-dev', true, 'dev', '^3.0@dev', '3.0-dev'),
  218. );
  219. }
  220. private function createPackage($version)
  221. {
  222. $parser = new VersionParser();
  223. return new Package('foo', $parser->normalize($version), $version);
  224. }
  225. private function createMockPool()
  226. {
  227. return $this->getMockBuilder('Composer\DependencyResolver\Pool')->getMock();
  228. }
  229. }