IntervalsTest.php 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809
  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\ConstraintInterface;
  13. use Composer\Semver\Constraint\MultiConstraint;
  14. use Composer\Semver\Constraint\Constraint;
  15. use Composer\Semver\Constraint\MatchNoneConstraint;
  16. use Composer\Semver\Constraint\AnyDevConstraint;
  17. class IntervalsTest extends TestCase
  18. {
  19. const INTERVAL_ANY = '*/dev*';
  20. const INTERVAL_ANY_NODEV = '*';
  21. const INTERVAL_NONE = '';
  22. const COMPACT_NONE = '';
  23. /**
  24. * @dataProvider compactProvider
  25. * @param string $expected
  26. * @param array<string> $toCompact
  27. * @param bool $conjunctive
  28. */
  29. public function testCompactConstraint($expected, $toCompact, $conjunctive)
  30. {
  31. $parser = new VersionParser;
  32. $parts = array();
  33. foreach ($toCompact as $part) {
  34. $parts[] = $parser->parseConstraints($part);
  35. }
  36. if ($expected === self::COMPACT_NONE) {
  37. $expected = new MatchNoneConstraint;
  38. } else {
  39. $expected = $parser->parseConstraints($expected);
  40. }
  41. $new = Intervals::compactConstraint(new MultiConstraint($parts, $conjunctive));
  42. $this->assertSame((string) $expected, (string) $new);
  43. }
  44. public function compactProvider()
  45. {
  46. return array(
  47. 'simple disjunctive multi' => array(
  48. '1.0 - 1.2 || ^1.5',
  49. array('1.0 - 1.2 || ^1.5', '1.8 - 1.9 || ^1.12'),
  50. false
  51. ),
  52. 'simple conjunctive multi' => array(
  53. '1.8 - 1.9 || ^1.12',
  54. array('1.0 - 1.2 || ^1.5', '1.8 - 1.9 || ^1.12'),
  55. true
  56. ),
  57. 'dev constraints propagate, disjunctive' => array(
  58. '1.8 - 1.9 || ^1.12 || dev-master || dev-foo',
  59. array('1.8 - 1.9 || ^1.12', 'dev-master', 'dev-foo'),
  60. false
  61. ),
  62. 'dev constraints + numeric constraint, conjunctive results in match-none' => array(
  63. self::COMPACT_NONE,
  64. array('1.8 - 1.9 || ^1.12', 'dev-master', 'dev-foo'),
  65. true
  66. ),
  67. 'conflicting numeric constraint, conjunctive results in match-none' => array(
  68. self::COMPACT_NONE,
  69. array('1.0', '2.0'),
  70. true
  71. ),
  72. 'simple disjunctive results in same output' => array(
  73. '1.0 || 2.0',
  74. array('1.0', '2.0'),
  75. false
  76. ),
  77. 'simple conjunctive results in same output' => array(
  78. '!= 1.2, != 1.6',
  79. array('!= 1.2', '!= 1.6'),
  80. true
  81. ),
  82. 'simple conjunctive results in same output/2' => array(
  83. '!= 1.0, != 2.0',
  84. array('!= 1.0', '!= 2.0'),
  85. true
  86. ),
  87. 'switches to conjunctive if more than != x is present' => array(
  88. '>1.5, != 2.0',
  89. array('!= 2.0', '> 1.5'),
  90. true
  91. ),
  92. 'complex conjunctive with dev' => array(
  93. '!= 1.0, != 2.0',
  94. array('!= 1.0', '!= 2.0'),
  95. true
  96. ),
  97. 'simple disjunctive with negation' => array(
  98. '!= 1.0',
  99. array('!= 1.0', '!= 1.0'),
  100. false
  101. ),
  102. 'disjunctive with complex negation' => array(
  103. '*',
  104. array('!= 1.0', '!= 1.0', '!= dev-foo', '1.0.5.*'),
  105. false
  106. ),
  107. 'conjunctive with complex negation' => array(
  108. '1.0.5.*',
  109. array('!= 1.0', '!= 1.0', '!= dev-foo', '1.0.5.*'),
  110. true
  111. ),
  112. 'conjunctive with complex negation/2' => array(
  113. '>= 1.0-dev, != 1.2-stable, <2',
  114. array('!= 1.2', '!= dev-foo', '!= dev-bar', '1.*'),
  115. true
  116. ),
  117. 'conjunctive with complex negation/3' => array(
  118. '!= 1.2, != dev-foo, != dev-bar',
  119. array('!= 1.2', '!= dev-foo', '!= dev-bar'),
  120. true
  121. ),
  122. 'disjunctive with complex negation/3' => array(
  123. '*',
  124. array('!= 1.2', '!= dev-foo', '!= dev-bar'),
  125. false
  126. ),
  127. 'conjunctive with complex negation/4' => array(
  128. '== dev-foo',
  129. array('!= 1.2', '== dev-foo', '!= dev-bar'),
  130. true
  131. ),
  132. 'disjunctive with complex negation and dev ==' => array(
  133. '*',
  134. array('!= 1.0', '!= 1.0', '!= dev-foo', '1.0.5.*', '== dev-bla'),
  135. false
  136. ),
  137. 'conjunctive with complex negation and dev ==' => array(
  138. 'dev-bla',
  139. array('!= 1.0', '!= 1.0', '!= dev-foo', '== dev-bla'),
  140. true
  141. ),
  142. 'complex conjunctive which can not match anything' => array(
  143. self::COMPACT_NONE,
  144. array('!= 1.0', '!= 1.0', '!= dev-foo', '1.0.5.*', '== dev-bla'),
  145. true
  146. ),
  147. 'conjunctive with more than one dev negation' => array(
  148. '!= dev-master, != dev-foo',
  149. array('!= dev-master', '!= dev-foo'),
  150. true
  151. ),
  152. 'conjunctive with mix of devs' => array(
  153. '== dev-foo',
  154. array('!= dev-master', '== dev-foo'),
  155. true
  156. ),
  157. 'disjunctive with mix of devs' => array(
  158. '!= dev-master',
  159. array('!= dev-master', '== dev-foo'),
  160. false
  161. ),
  162. 'conjunctive with more than one dev negation, and numeric constraint' => array(
  163. '> 5',
  164. array('!= dev-master', '!= dev-foo', '> 5'),
  165. true
  166. ),
  167. 'conjunctive with more than one of the same dev negation' => array(
  168. '!= dev-foo',
  169. array('!= dev-foo', '!= dev-foo'),
  170. true
  171. ),
  172. 'switches to conjunctive when excluding versions and complex' => array(
  173. '!= 3-stable, <5 || >=6, <9',
  174. array('!= 3, <5', '>=6, <9'),
  175. false
  176. ),
  177. 'conjunctive with multiple numeric negations and a disjunctive exact match for dev versions' => array(
  178. '== dev-foo || == dev-bar',
  179. array('!= 1.0', '!= 2.0', '==dev-foo || ==dev-bar'),
  180. true,
  181. ),
  182. );
  183. }
  184. /**
  185. * @dataProvider intervalsProvider
  186. * @param array<mixed>|self::INTERVAL_* $expected
  187. * @param string $constraint
  188. */
  189. public function testGetIntervals($expected, $constraint)
  190. {
  191. if (is_string($constraint)) {
  192. $parser = new VersionParser;
  193. $constraint = $parser->parseConstraints($constraint);
  194. }
  195. $result = Intervals::get($constraint);
  196. if (is_array($result)) {
  197. array_walk_recursive($result, function (&$c) {
  198. if ($c instanceof Interval) {
  199. $c = array('start' => (string) $c->getStart(), 'end' => (string) $c->getEnd());
  200. }
  201. });
  202. }
  203. if ($expected === self::INTERVAL_ANY) {
  204. $expected = array('numeric' => array(
  205. array(
  206. 'start' => '>= 0.0.0.0-dev',
  207. 'end' => '< '.PHP_INT_MAX.'.0.0.0',
  208. ),
  209. ), 'branches' => Interval::anyDev());
  210. }
  211. if ($expected === self::INTERVAL_ANY_NODEV) {
  212. $expected = array('numeric' => array(
  213. array(
  214. 'start' => '>= 0.0.0.0-dev',
  215. 'end' => '< '.PHP_INT_MAX.'.0.0.0',
  216. ),
  217. ), 'branches' => Interval::noDev());
  218. }
  219. if ($expected === self::INTERVAL_NONE) {
  220. $expected = array('numeric' => array(), 'branches' => Interval::noDev());
  221. }
  222. $this->assertSame($expected, $result);
  223. }
  224. public function intervalsProvider()
  225. {
  226. return array(
  227. 'simple case' => array(
  228. array('numeric' => array(
  229. array(
  230. 'start' => '>= 1.0.0.0-dev',
  231. 'end' => '< 2.0.0.0-dev',
  232. ),
  233. ), 'branches' => Interval::noDev()),
  234. '^1.0'
  235. ),
  236. 'simple case/2' => array(
  237. array('numeric' => array(
  238. array(
  239. 'start' => '> 1.0.0.0',
  240. 'end' => '< '.PHP_INT_MAX.'.0.0.0',
  241. ),
  242. ), 'branches' => Interval::noDev()),
  243. '> 1.0'
  244. ),
  245. 'intervals should be sorted' => array(
  246. array('numeric' => array(
  247. array(
  248. 'start' => '>= 0.9.0.0-dev',
  249. 'end' => '< 1.0.0.0-dev',
  250. ),
  251. array(
  252. 'start' => '>= 1.2.3.0',
  253. 'end' => '<= 1.2.3.0',
  254. ),
  255. array(
  256. 'start' => '>= 1.3.4.0',
  257. 'end' => '<= 1.3.4.0',
  258. ),
  259. array(
  260. 'start' => '> 2.3.0.0',
  261. 'end' => '< 2.5.0.0-dev',
  262. ),
  263. ), 'branches' => Interval::noDev()),
  264. '1.3.4 || 1.2.3 || >2.3,<2.5 || <1,>=0.9'
  265. ),
  266. 'intervals should be sorted and consecutive ones merged' => array(
  267. array('numeric' => array(
  268. array(
  269. 'start' => '>= 1.0.0.0-dev',
  270. 'end' => '< 2.0.0.0-dev',
  271. ),
  272. array(
  273. 'start' => '>= 3.0.0.0-dev',
  274. 'end' => '< 5.0.0.0-dev',
  275. ),
  276. ), 'branches' => Interval::noDev()),
  277. '^4.0 || ^1.0 || ^3.0'
  278. ),
  279. 'consecutive intervals should be merged even if one has no end' => array(
  280. array('numeric' => array(
  281. array(
  282. 'start' => '>= 4.0.0.0-dev',
  283. 'end' => '< '.PHP_INT_MAX.'.0.0.0',
  284. ),
  285. ), 'branches' => Interval::noDev()),
  286. '^4.0 || >= 5'
  287. ),
  288. 'consecutive intervals should be merged even if one has no start' => array(
  289. array('numeric' => array(
  290. array(
  291. 'start' => '>= 0.0.0.0-dev',
  292. 'end' => '< 6.0.0.0-dev',
  293. ),
  294. ), 'branches' => Interval::noDev()),
  295. '>= 5,< 6 || < 5'
  296. ),
  297. 'consecutive intervals representing everything should become *' => array(
  298. self::INTERVAL_ANY_NODEV,
  299. '>= 5 || < 5'
  300. ),
  301. 'intervals should be sorted and overlapping ones merged' => array(
  302. array('numeric' => array(
  303. array(
  304. 'start' => '>= 1.1.0.0-dev',
  305. 'end' => '< 2.0.0.0-dev',
  306. ),
  307. array(
  308. 'start' => '>= 3.0.0.0-dev',
  309. 'end' => '< 5.0.0.0-dev',
  310. ),
  311. ), 'branches' => Interval::noDev()),
  312. '^4.0 || ^1.1 || ^3.0 || ^1.2'
  313. ),
  314. 'intervals should be sorted and overlapping ones merged/2' => array(
  315. array('numeric' => array(
  316. array(
  317. 'start' => '>= 1.0.0.0-dev',
  318. 'end' => '< 1.5.0.0-dev',
  319. ),
  320. ), 'branches' => Interval::noDev()),
  321. '1.2 - 1.4 || 1.0 - 1.3'
  322. ),
  323. 'overlapping intervals should be merged even if the last has no end' => array(
  324. array('numeric' => array(
  325. array(
  326. 'start' => '>= 4.0.0.0-dev',
  327. 'end' => '< '.PHP_INT_MAX.'.0.0.0',
  328. ),
  329. ), 'branches' => Interval::noDev()),
  330. '^4.0 || >= 4.5'
  331. ),
  332. 'overlapping intervals should be merged even if the first has no start' => array(
  333. array('numeric' => array(
  334. array(
  335. 'start' => '>= 0.0.0.0-dev',
  336. 'end' => '< 6.0.0.0-dev',
  337. ),
  338. ), 'branches' => Interval::noDev()),
  339. '>= 5,< 6 || < 5.3'
  340. ),
  341. 'overlapping intervals representing everything should become *' => array(
  342. self::INTERVAL_ANY_NODEV,
  343. '>= 5 || <= 5'
  344. ),
  345. 'equal intervals should be merged' => array(
  346. array('numeric' => array(
  347. array(
  348. 'start' => '>= 1.0.0.0-dev',
  349. 'end' => '< 2.0.0.0-dev',
  350. ),
  351. ), 'branches' => Interval::noDev()),
  352. '^1.0 || ^1.0'
  353. ),
  354. 'weird input order should still be a good result' => array(
  355. array('numeric' => array(
  356. array(
  357. 'start' => '>= 0.0.0.0-dev',
  358. 'end' => '< 2.0.0.0-dev',
  359. ),
  360. ), 'branches' => Interval::noDev()),
  361. '< 2.0 || < 1.2'
  362. ),
  363. 'weird input order should still be a good result, matches everything' => array(
  364. self::INTERVAL_ANY_NODEV,
  365. '< 2.0 || >= 1'
  366. ),
  367. 'weird input order should still be a good result, conjunctive' => array(
  368. array('numeric' => array(
  369. array(
  370. 'start' => '>= 1.0.0.0-dev',
  371. 'end' => '< 2.0.0.0-dev',
  372. ),
  373. ), 'branches' => Interval::noDev()),
  374. '< 2.0, >= 1'
  375. ),
  376. 'conjunctive constraints result in no interval if conflicting' => array(
  377. self::INTERVAL_NONE,
  378. '^1.0, ^2.0'
  379. ),
  380. 'conjunctive constraints result in no interval if conflicting/2' => array(
  381. self::INTERVAL_NONE,
  382. '^1.0, ^3.0'
  383. ),
  384. 'conjunctive constraints result in no interval if conflicting/3' => array(
  385. self::INTERVAL_NONE,
  386. '== 1.0, != 1.0'
  387. ),
  388. 'conjunctive constraints result in no interval if conflicting/4' => array(
  389. self::INTERVAL_NONE,
  390. '> 1.0, dev-master'
  391. ),
  392. 'conjunctive constraints result in no branches interval if numeric is provided' => array(
  393. array('numeric' => array(
  394. array(
  395. 'start' => '> 5.0.0.0',
  396. 'end' => '< '.PHP_INT_MAX.'.0.0.0',
  397. ),
  398. ), 'branches' => Interval::noDev()),
  399. '!= dev-master, != dev-foo, > 5'
  400. ),
  401. 'conjunctive constraints result in no branches interval if numeric is provided, even if one matches dev*' => array(
  402. array('numeric' => array(
  403. array(
  404. 'start' => '> 5.0.0.0',
  405. 'end' => '< 6.0.0.0',
  406. ),
  407. array(
  408. 'start' => '> 6.0.0.0',
  409. 'end' => '< '.PHP_INT_MAX.'.0.0.0',
  410. ),
  411. ), 'branches' => Interval::noDev()),
  412. '!= 6, > 5'
  413. ),
  414. 'disjunctive constraints keeps branch intervals if numeric is provided' => array(
  415. array('numeric' => array(
  416. array(
  417. 'start' => '>= 0.0.0.0-dev',
  418. 'end' => '< '.PHP_INT_MAX.'.0.0.0',
  419. ),
  420. ), 'branches' => array('names' => array('dev-master', 'dev-foo'), 'exclude' => true)),
  421. '!= dev-master, != dev-foo || > 5'
  422. ),
  423. 'conjunctive constraints should be intersected' => array(
  424. array('numeric' => array(
  425. array(
  426. 'start' => '>= 1.2.0.0-dev',
  427. 'end' => '< 2.0.0.0-dev',
  428. ),
  429. ), 'branches' => Interval::noDev()),
  430. '^1.0, ^1.2'
  431. ),
  432. 'conjunctive constraints should be intersected/2' => array(
  433. array('numeric' => array(
  434. array(
  435. 'start' => '>= 1.5.0.0-dev',
  436. 'end' => '< 1.7.0.0-dev',
  437. ),
  438. ), 'branches' => Interval::noDev()),
  439. '^1.0, ^1.2, 1.4 - 1.8, 1.5 - 1.6, 1.5 - 2'
  440. ),
  441. 'conjunctive constraints should be intersected, not flattened by version parser' => array(
  442. array('numeric' => array(
  443. array(
  444. 'start' => '>= 1.5.0.0-dev',
  445. 'end' => '< 1.7.0.0-dev',
  446. ),
  447. ), 'branches' => Interval::noDev()),
  448. new MultiConstraint(array(
  449. new MultiConstraint(array(
  450. new Constraint('>=', '1.0.0.0-dev'),
  451. new Constraint('<', '2.0.0.0-dev'),
  452. ), true),
  453. new MultiConstraint(array(
  454. new Constraint('>=', '1.2.0.0-dev'),
  455. new Constraint('<', '2.0.0.0-dev'),
  456. ), true),
  457. new MultiConstraint(array(
  458. new Constraint('>=', '1.4.0.0-dev'),
  459. new Constraint('<', '1.9.0.0-dev'),
  460. ), true),
  461. new MultiConstraint(array(
  462. new Constraint('>=', '1.5.0.0-dev'),
  463. new Constraint('<', '1.7.0.0-dev'),
  464. ), true),
  465. new MultiConstraint(array(
  466. new Constraint('>=', '1.5.0.0-dev'),
  467. new Constraint('<', '3.0.0.0-dev'),
  468. ), true),
  469. ), true),
  470. ),
  471. 'conjunctive constraints with disjunctive subcomponents should be intersected, not flattened by version parser' => array(
  472. array('numeric' => array(
  473. array(
  474. 'start' => '>= 1.8.0.0-dev',
  475. 'end' => '< 1.10.0.0-dev',
  476. ),
  477. array(
  478. 'start' => '>= 1.12.0.0-dev',
  479. 'end' => '< 2.0.0.0-dev',
  480. ),
  481. ), 'branches' => Interval::noDev()),
  482. new MultiConstraint(array(
  483. new MultiConstraint(array( // 1.0 - 1.2 || ^1.5
  484. new MultiConstraint(array(
  485. new Constraint('>=', '1.0.0.0-dev'),
  486. new Constraint('<', '1.3.0.0-dev'),
  487. ), true),
  488. new MultiConstraint(array(
  489. new Constraint('>=', '1.5.0.0-dev'),
  490. new Constraint('<', '2.0.0.0-dev'),
  491. ), true),
  492. ), false),
  493. new MultiConstraint(array( // 1.8 - 1.9 || ^1.12
  494. new MultiConstraint(array(
  495. new Constraint('>=', '1.8.0.0-dev'),
  496. new Constraint('<', '1.10.0.0-dev'),
  497. ), true),
  498. new MultiConstraint(array(
  499. new Constraint('>=', '1.12.0.0-dev'),
  500. new Constraint('<', '2.0.0.0-dev'),
  501. ), true),
  502. ), false),
  503. ), true),
  504. ),
  505. 'conjunctive constraints with equal constraints' => array(
  506. array('numeric' => array(
  507. array(
  508. 'start' => '>= 1.3.2.0-dev',
  509. 'end' => '<= 1.3.2.0-dev',
  510. ),
  511. ), 'branches' => Interval::noDev()),
  512. new MultiConstraint(array(
  513. new MultiConstraint(array(
  514. new Constraint('==', '1.3.1.0-dev'),
  515. new Constraint('==', '1.3.2.0-dev'),
  516. new Constraint('==', '1.3.3.0-dev'),
  517. ), false),
  518. new Constraint('==', '1.3.2.0-dev'),
  519. ), true),
  520. ),
  521. 'conjunctive constraints simple' => array(
  522. array('numeric' => array(
  523. array(
  524. 'start' => '>= 1.5.0.0-dev',
  525. 'end' => '< 3.0.0.0-dev',
  526. ),
  527. ), 'branches' => Interval::noDev()),
  528. '1.5 - 2'
  529. ),
  530. 'conjunctive constraints with dev exclusions' => array(
  531. array('numeric' => array(
  532. array(
  533. 'start' => '>= 1.0.0.0-dev',
  534. 'end' => '< 1.2.3.0',
  535. ),
  536. array(
  537. 'start' => '> 1.2.3.0',
  538. 'end' => '< 1.4.5.0',
  539. ),
  540. array(
  541. 'start' => '> 1.4.5.0',
  542. 'end' => '< 2.0.0.0-dev',
  543. ),
  544. ), 'branches' => Interval::noDev()),
  545. '!= 1.4.5, ^1.0, != 1.2.3, != 2.3, != dev-foo, != dev-master'
  546. ),
  547. 'conjunctive constraints with dev exact versions suppresses the number scope matches' => array(
  548. self::INTERVAL_NONE,
  549. '!= 1.4.5, ^1.0, != 1.2.3, != 2.3, == dev-foo, == dev-foo'
  550. ),
  551. 'conjunctive constraints with dev exact versions suppresses the number scope matches, but keeps dev- match if number constraints allowed dev*' => array(
  552. array('numeric' => array(
  553. ), 'branches' => array('names' => array('dev-foo'), 'exclude' => false)),
  554. '!= 1.2.3, != 2.3, == dev-foo, == dev-foo'
  555. ),
  556. 'disjunctive constraints with exclusions in dev constraints makes the number scope match *' => array(
  557. array('numeric' => array(
  558. array(
  559. 'start' => '>= 0.0.0.0-dev',
  560. 'end' => '< '.PHP_INT_MAX.'.0.0.0',
  561. ),
  562. ), 'branches' => array('names' => array('dev-foo'), 'exclude' => true)),
  563. '^1.0 || != dev-foo'
  564. ),
  565. 'disjunctive constraints with exclusions in dev constraints makes number scope match *' => array(
  566. array('numeric' => array(
  567. array(
  568. 'start' => '>= 0.0.0.0-dev',
  569. 'end' => '< '.PHP_INT_MAX.'.0.0.0',
  570. ),
  571. ), 'branches' => array('names' => array('dev-foo'), 'exclude' => true)),
  572. '^1.0 || != dev-foo'
  573. ),
  574. 'disjunctive constraints with exclusions, if matches * in number scope and dev scope, then * is returned' => array(
  575. self::INTERVAL_ANY,
  576. '!= 1.4.5 || ^1.0 || != dev-foo || != dev-master || == dev-master'
  577. ),
  578. 'disjunctive constraints with exclusions, if dev constraints match *, then * is returned for everything' => array(
  579. self::INTERVAL_ANY,
  580. '^1.0 || != dev-master || == dev-master'
  581. ),
  582. 'disjunctive constraints with exclusions, if dev constraints match * except in dev scope, then * is returned for number scope' => array(
  583. array('numeric' => array(
  584. array(
  585. 'start' => '>= 0.0.0.0-dev',
  586. 'end' => '< '.PHP_INT_MAX.'.0.0.0',
  587. ),
  588. ), 'branches' => array('names' => array('dev-foo'), 'exclude' => true)),
  589. '^1.0 || != dev-foo || == dev-master'
  590. ),
  591. 'disjunctive constraints with exact dev matches returns number scope as it should and unique dev constraints' => array(
  592. array('numeric' => array(
  593. array(
  594. 'start' => '>= 1.0.0.0-dev',
  595. 'end' => '< 2.0.0.0-dev',
  596. ),
  597. ), 'branches' => array('names' => array('dev-foo', 'dev-master'), 'exclude' => false)),
  598. '^1.0 || == dev-foo || == dev-master || == dev-master'
  599. ),
  600. 'conjunctive constraints with exact versions' => array(
  601. self::INTERVAL_NONE,
  602. 'dev-master, ^1.0'
  603. ),
  604. 'conjunctive constraints with exact versions, dev only, diff version should result in no interval and no constraints' => array(
  605. self::INTERVAL_NONE,
  606. 'dev-master, dev-foo'
  607. ),
  608. 'conjunctive constraints with exact versions, dev only, same version should pass through' => array(
  609. array('numeric' => array(), 'branches' => array('names' => array('dev-master'), 'exclude' => false)),
  610. 'dev-master, dev-master'
  611. ),
  612. 'conjunctive constraints with same dev exclusion, should result in * with dev exclusion' => array(
  613. array('numeric' => array(
  614. array(
  615. 'start' => '>= 0.0.0.0-dev',
  616. 'end' => '< '.PHP_INT_MAX.'.0.0.0',
  617. ),
  618. ), 'branches' => array('names' => array('dev-master'), 'exclude' => true)),
  619. '!= dev-master, != dev-master'
  620. ),
  621. 'conjunctive constraints with different dev exclusion, should result in * with dev exclusions' => array(
  622. array('numeric' => array(
  623. array(
  624. 'start' => '>= 0.0.0.0-dev',
  625. 'end' => '< '.PHP_INT_MAX.'.0.0.0',
  626. ),
  627. ), 'branches' => array('names' => array('dev-master', 'dev-foo'), 'exclude' => true)),
  628. '!= dev-master, != dev-foo'
  629. ),
  630. 'disjunctive constraints with exact versions' => array(
  631. array('numeric' => array(
  632. array(
  633. 'start' => '>= 1.0.0.0-dev',
  634. 'end' => '< 2.0.0.0-dev',
  635. ),
  636. ), 'branches' => array('names' => array('dev-master', 'dev-foo'), 'exclude' => false)),
  637. 'dev-master || ^1.0 || dev-foo || dev-master'
  638. ),
  639. 'conjunctive constraints with * should skip it' => array(
  640. array('numeric' => array(
  641. array(
  642. 'start' => '>= 1.0.0.0-dev',
  643. 'end' => '< 2.0.0.0-dev',
  644. ),
  645. ), 'branches' => Interval::noDev()),
  646. '^1.0, *'
  647. ),
  648. 'disjunctive constraints with * should result in *' => array(
  649. self::INTERVAL_ANY,
  650. '^1.0 || *'
  651. ),
  652. 'conjunctive constraints with only * should result in *' => array(
  653. self::INTERVAL_ANY,
  654. '*, *'
  655. ),
  656. 'conjunctive constraints equivalent of * should result in *' => array(
  657. self::INTERVAL_ANY_NODEV,
  658. new MultiConstraint(array(new Constraint('>=', '0.0.0.0-dev'), new Constraint('<', PHP_INT_MAX.'.0.0.0'))),
  659. ),
  660. 'disjunctive constraints with * and dev exclusion should not return the dev exclusion' => array(
  661. self::INTERVAL_ANY,
  662. '!= dev-foo || *'
  663. ),
  664. 'conjunctive constraints with various dev constraints/2' => array(
  665. array('numeric' => array(
  666. array(
  667. 'start' => '> 5.0.0.0',
  668. 'end' => '< '.PHP_INT_MAX.'.0.0.0',
  669. ),
  670. ), 'branches' => Interval::noDev()),
  671. '> 5, *'
  672. ),
  673. 'conjunctive constraints with various dev constraints/3' => array(
  674. array('numeric' => array(
  675. array(
  676. 'start' => '> 5.0.0.0',
  677. 'end' => '< '.PHP_INT_MAX.'.0.0.0',
  678. ),
  679. ), 'branches' => Interval::noDev()),
  680. '!= dev-foo, > 5'
  681. ),
  682. 'conjunctive constraints with various dev constraints/4' => array(
  683. array('numeric' => array(
  684. array(
  685. 'start' => '>= 0.0.0.0-dev',
  686. 'end' => '< '.PHP_INT_MAX.'.0.0.0',
  687. ),
  688. ), 'branches' => array('names' => array('dev-foo'), 'exclude' => true)),
  689. '!= dev-foo, != dev-foo'
  690. ),
  691. 'conjunctive constraints with various dev constraints/5' => array(
  692. array('numeric' => array(
  693. array(
  694. 'start' => '>= 0.0.0.0-dev',
  695. 'end' => '< '.PHP_INT_MAX.'.0.0.0',
  696. ),
  697. ), 'branches' => array('names' => array('dev-foo', 'dev-bar'), 'exclude' => true)),
  698. '!= dev-foo, != dev-bar'
  699. ),
  700. 'conjunctive constraints with various dev constraints/6' => array(
  701. array('numeric' => array(), 'branches' => array('names' => array('dev-bar'), 'exclude' => false)),
  702. '!= dev-foo, == dev-bar'
  703. ),
  704. 'conjunctive constraints with various dev constraints/7' => array(
  705. self::INTERVAL_NONE,
  706. 'dev-foo, > 5'
  707. ),
  708. 'complex conjunctive which can not match anything' => array(
  709. self::INTERVAL_NONE,
  710. '!= 1.0, != 1.0, != dev-foo, 1.0.5.*, == dev-bla'
  711. ),
  712. 'conjunctive with more than one dev negation' => array(
  713. array('numeric' => array(
  714. array(
  715. 'start' => '>= 0.0.0.0-dev',
  716. 'end' => '< '.PHP_INT_MAX.'.0.0.0',
  717. ),
  718. ), 'branches' => array('names' => array('dev-master', 'dev-foo'), 'exclude' => true)),
  719. '!= dev-master, != dev-foo'
  720. ),
  721. 'disjunctive constraints with various dev constraints' => array(
  722. array('numeric' => array(
  723. array(
  724. 'start' => '>= 0.0.0.0-dev',
  725. 'end' => '< '.PHP_INT_MAX.'.0.0.0',
  726. ),
  727. ), 'branches' => array('names' => array('dev-foo'), 'exclude' => true)),
  728. '!= dev-foo, != dev-bar || != dev-foo'
  729. ),
  730. 'disjunctive constraints with various dev constraints/2' => array(
  731. array('numeric' => array(
  732. array(
  733. 'start' => '>= 0.0.0.0-dev',
  734. 'end' => '< '.PHP_INT_MAX.'.0.0.0',
  735. ),
  736. ), 'branches' => array('names' => array('dev-foo', 'dev-bar'), 'exclude' => true)),
  737. '!= dev-foo, != dev-bar || != dev-foo, != dev-bar'
  738. ),
  739. 'disjunctive constraints with various dev constraints/3' => array(
  740. self::INTERVAL_ANY,
  741. new MultiConstraint(array(new Constraint('!=', 'dev-foo'), new Constraint('!=', 'dev-bar')), false),
  742. ),
  743. 'disjunctive constraints with various dev constraints/4' => array(
  744. array('numeric' => array(),
  745. 'branches' => array('names' => array('dev-foo', 'dev-bar'), 'exclude' => false),
  746. ),
  747. '== dev-foo || == dev-bar'
  748. ),
  749. 'disjunctive constraints with various dev constraints/5' => array(
  750. self::INTERVAL_ANY,
  751. '== dev-foo || != dev-foo'
  752. ),
  753. 'disjunctive constraints with various dev constraints/6' => array(
  754. array('numeric' => array(
  755. array(
  756. 'start' => '>= 0.0.0.0-dev',
  757. 'end' => '< '.PHP_INT_MAX.'.0.0.0',
  758. ),
  759. ), 'branches' => array('names' => array('dev-bar'), 'exclude' => true)),
  760. '== dev-foo || != dev-bar'
  761. ),
  762. 'disjunctive constraints with various dev constraints/7' => array(
  763. array('numeric' => array(
  764. array(
  765. 'start' => '>= 0.0.0.0-dev',
  766. 'end' => '< '.PHP_INT_MAX.'.0.0.0',
  767. ),
  768. ), 'branches' => array('names' => array('dev-bar'), 'exclude' => true)),
  769. '== dev-foo || != dev-bar || != dev-bar'
  770. ),
  771. 'disjunctive constraints with various dev constraints/8' => array(
  772. self::INTERVAL_ANY,
  773. '== dev-foo || != dev-bar || != dev-foo'
  774. ),
  775. 'match-none constraints result in no interval' => array(
  776. self::INTERVAL_NONE,
  777. new MatchNoneConstraint
  778. ),
  779. 'match-none constraint inside conjunctive multi results in no interval' => array(
  780. self::INTERVAL_NONE,
  781. new MultiConstraint(array(
  782. new MultiConstraint(array(
  783. new Constraint('==', '1.3.1.0-dev'),
  784. new Constraint('==', '1.3.2.0-dev'),
  785. new Constraint('==', '1.3.3.0-dev'),
  786. ), false),
  787. new MatchNoneConstraint,
  788. ), true),
  789. ),
  790. );
  791. }
  792. }