SubsetsTest.php 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. <?php
  2. /*
  3. * This file is part of composer/semver.
  4. *
  5. * (c) Composer <https://github.com/composer>
  6. *
  7. * For the full copyright and license information, please view
  8. * the LICENSE file that was distributed with this source code.
  9. */
  10. namespace Composer\Semver;
  11. use PHPUnit\Framework\TestCase;
  12. use Composer\Semver\Constraint\MatchNoneConstraint;
  13. use Composer\Semver\Constraint\MatchAllConstraint;
  14. class SubsetsTest extends TestCase
  15. {
  16. /**
  17. * @dataProvider subsets
  18. * @param string $aStr
  19. * @param string $bStr
  20. */
  21. public function testIsSubsetOf($aStr, $bStr)
  22. {
  23. $versionParser = new VersionParser;
  24. $a = $versionParser->parseConstraints($aStr);
  25. $b = $versionParser->parseConstraints($bStr);
  26. $this->assertTrue(Intervals::isSubsetOf($a, $b), $aStr.' ('.$a.') should be seen as a subset of '.$bStr.' ('.$b.')');
  27. }
  28. /**
  29. * @return array<mixed>
  30. */
  31. public function subsets()
  32. {
  33. return array(
  34. // x is subset of y
  35. array('*', '*'),
  36. array('*', '!= 1 || == 1'),
  37. array('1.0.0', '*'),
  38. array('1.0.*', '*'),
  39. array('^1.0 || ^2.0', '*'),
  40. array('^3.0', '^3.2 || *'),
  41. array('^1.0 || ^2.0', '^1.0 || ^2.0'),
  42. array('^1.0 || ^2.0', '^1.0 || ^2.0 || ^4.0'),
  43. array('^1.0 || ^2.1', '^1.0 || ^2.1 || ^4.0'),
  44. array('^1.2', '^1.0 || ^2.0'),
  45. array('1.2.3', '^1.0 || ^2.0'),
  46. array('2.0.0-dev', '^1.0 || ^2.0'),
  47. array('>= 2.1.0', '>= 2.0.0'),
  48. array('^2.0', '<3.0.0'),
  49. array('^3.0', '> 2.1.3'),
  50. array('3.0.0', '<= 3.0.0'),
  51. array('!= 3.0.0', '*'),
  52. array('!= 3.0.0', '!= 3.0'),
  53. array('!= 3.0, != 2.0', '!= 2.0, != 3.0'),
  54. array('>3', '^2 || ^3 || >=4'),
  55. array('>3', '>=3'),
  56. array('<3', '<=3'),
  57. array('= dev-foo', '= dev-foo'),
  58. array('!= dev-foo', '!= dev-foo'),
  59. array('< dev-foo', '= dev-foo'), // invalid range matches nothing so is a subset of any other
  60. array('1.5.*', '^1.4'),
  61. array('1.5.*', '1.3 - 1.6 || 1.8 - 1.9'),
  62. array('1.3.2', '1.3.0 || 1.3.1 || 1.3.2'),
  63. array('1.3.1', '1.3.0 || 1.3.1 || 1.3.2'),
  64. array('1.3.1 || 1.3.1', '1.3.1'),
  65. array('^1.0 || ^3.2', '^1.0 || ^3.0'),
  66. array('^1.3 || ^3.2', '>1.2'),
  67. array('^1.6', '<1.3 || >1.5'),
  68. array('>1.6', '<1.3 || >1.5'),
  69. array('>1.6', '>1.5, >1.4, !=1.1'),
  70. array('>1.6', '>1.5 || >1.7'),
  71. array('^1.1', '> 1.0.0'),
  72. array('^1.1, !=1.5.0', '> 1.0.0'),
  73. array('^1.1, !=0.5.0', '> 1.0.0'),
  74. array('^2.0 || dev-foo', '> 1.0 || dev-foo || dev-bar'),
  75. array('^1.0, ^1.2', '>=1.2'),
  76. array('^1.0, ^1.2', '^1.2'),
  77. array('^1.0, ^1.2 || ^1.3', '^1.2'),
  78. );
  79. }
  80. /**
  81. * @dataProvider notSubsets
  82. * @param string $aStr
  83. * @param string $bStr
  84. */
  85. public function testIsNotSubsetOf($aStr, $bStr)
  86. {
  87. $versionParser = new VersionParser;
  88. $a = $versionParser->parseConstraints($aStr);
  89. $b = $versionParser->parseConstraints($bStr);
  90. $this->assertFalse(Intervals::isSubsetOf($a, $b), $aStr.' ('.$a.') should not be seen as a subset of '.$bStr.' ('.$b.')');
  91. }
  92. /**
  93. * @return array<mixed>
  94. */
  95. public function notSubsets()
  96. {
  97. return array(
  98. // x is subset of y
  99. array('*', '>= 1 || < 1'), // it is a subset of the numeric interval, but * allows dev- branches while the latter does not
  100. array('*', '1.0.0'),
  101. array('*', '1.0.*'),
  102. array('*', '^1.0 || ^2.0'),
  103. array('^1.0 || ^2.0', '^1.0, ^2.0'), // buggy constraint on the right here, checking it does not match
  104. array('^1.0 || ^2.0', '^1.2'),
  105. array('^1.0 || ^2.0', '^1.0'),
  106. array('^1.0 || ^2.0', '1.2.3'),
  107. array('^1.0 || ^3.0', '1.2.3'),
  108. array('3.0.0', '^1.0 || ^2.0'),
  109. array('3.0.0', '< 3.0.0'),
  110. array('3.0.0', '>= 3.0.1'),
  111. array('!= 3.0.0', '> 3.0.0 || < 3.0.0-stable'), // it is a subset of the numeric interval, but != x allows dev- branches while the right side does not
  112. array('!= 3.0.0-dev', '^2.0 || <2 || >3.0-dev'), // it is a subset of the numeric interval, but != x allows dev- branches while the right side does not
  113. array('!= 3.0.0', '= 3.0.0'),
  114. array('!= 3.0.0', '!= 3.0.1'),
  115. array('!= 3.0.0', 'dev-foo || dev-bar'),
  116. array('!= 3.0.0', '<dev-foo || >dev-bar'),
  117. array('>= 1.0.0', '= 1.2.3'),
  118. array('< 2.0.0', '= 1.2.3'),
  119. array('>3', '^2 || ^3 || >4'),
  120. array('>=3', '>3'),
  121. array('<=3', '<3'),
  122. array('^2.1', '^2.0, !=2.1.3'),
  123. array('<2.0', '>=1.1'),
  124. array('!= dev-foo', '!= dev-bar'),
  125. array('!= dev-foo', '= dev-bar'),
  126. array('1.3.3', '1.3.0 || 1.3.1 || 1.3.2'),
  127. array('1.3.1 || 1.3.2', '1.3.1'),
  128. array('>1.6', '>1.5, >1.4, !=1.7'),
  129. array('>1.6', '>1.5, >1.7'),
  130. array('^1.0 || ^3.2', '^1.2 || ^3.0'),
  131. array('^1.0 || ^3.2', '^3.0'),
  132. array('^1.3 || ^3.2', '>1.4'),
  133. array('^2.0 || dev-foo', '> 1.0 || dev-bar'),
  134. );
  135. }
  136. public function testMatchNoneIsNoSubsetNorSupersetExceptOfMatchAll()
  137. {
  138. $versionParser = new VersionParser;
  139. $matchNone = new MatchNoneConstraint;
  140. $notSubsets = array(
  141. '1.0.0',
  142. '^1.0',
  143. '>3',
  144. '<3',
  145. 'dev-foo',
  146. '!= 1',
  147. '!= dev-foo',
  148. '<= dev-foo',
  149. );
  150. foreach ($notSubsets as $constraint) {
  151. $c = $versionParser->parseConstraints($constraint);
  152. $this->assertFalse(Intervals::isSubsetOf($c, $matchNone), $constraint.' ('.$c.') should not be seen as a subset of '.$matchNone);
  153. $this->assertFalse(Intervals::isSubsetOf($matchNone, $c), $matchNone.' should not be seen as a subset of '.$constraint.' ('.$c.')');
  154. }
  155. $empty = new MatchAllConstraint;
  156. $this->assertFalse(Intervals::isSubsetOf($empty, $matchNone), $empty.' should not be seen as a subset of '.$matchNone);
  157. $this->assertTrue(Intervals::isSubsetOf($matchNone, $empty), $matchNone.' should be seen as a subset of '.$empty);
  158. }
  159. }