From cdf6f7a26c7cf885dcc365ca4a874e29cbe7efc5 Mon Sep 17 00:00:00 2001 From: Semyon Proshev Date: Thu, 31 Mar 2016 16:30:51 +0300 Subject: [PATCH] Updated tests for PyRequirement: there are tests for requirement names, versions and extras. All previous tests have been saved but some of them were reworked and integrated into new ones. --- .../requirement/PyRequirementRelation.java | 4 +- .../jetbrains/python/PyRequirementTest.java | 272 +++++++++++++++++- 2 files changed, 267 insertions(+), 9 deletions(-) diff --git a/python/openapi/src/com/jetbrains/python/packaging/requirement/PyRequirementRelation.java b/python/openapi/src/com/jetbrains/python/packaging/requirement/PyRequirementRelation.java index 51c4c0c2b931..da56b973932a 100644 --- a/python/openapi/src/com/jetbrains/python/packaging/requirement/PyRequirementRelation.java +++ b/python/openapi/src/com/jetbrains/python/packaging/requirement/PyRequirementRelation.java @@ -25,7 +25,9 @@ public enum PyRequirementRelation { GT(">"), GTE(">="), EQ("=="), - NE("!="); + NE("!="), + COMPATIBLE("~="), + STR_EQ("==="); @NotNull private final String myValue; diff --git a/python/testSrc/com/jetbrains/python/PyRequirementTest.java b/python/testSrc/com/jetbrains/python/PyRequirementTest.java index 8be9b927e277..611528872206 100644 --- a/python/testSrc/com/jetbrains/python/PyRequirementTest.java +++ b/python/testSrc/com/jetbrains/python/PyRequirementTest.java @@ -15,16 +15,21 @@ */ package com.jetbrains.python; +import com.intellij.openapi.util.Pair; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.util.containers.ContainerUtil; import com.jetbrains.python.fixtures.PyTestCase; import com.jetbrains.python.packaging.PyPackage; import com.jetbrains.python.packaging.PyRequirement; import com.jetbrains.python.packaging.requirement.PyRequirementRelation; import com.jetbrains.python.packaging.requirement.PyRequirementVersionSpec; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.List; /** * @author vlan @@ -1037,24 +1042,231 @@ public class PyRequirementTest extends PyTestCase { // TODO: a sdist or wheel format archive // REQUIREMENT - // TODO: extras + // TODO: name normalization // TODO: hashes // TODO: multiline // TODO: https://pip.pypa.io/en/stable/reference/pip_install/#per-requirement-overrides + // https://www.python.org/dev/peps/pep-0508/#names public void testRequirement() { + assertEquals(new PyRequirement("Orange-Bioinformatics"), PyRequirement.fromString("Orange-Bioinformatics")); + assertEquals(new PyRequirement("MOCPy"), PyRequirement.fromString("MOCPy")); + assertEquals(new PyRequirement("score.webassets"), PyRequirement.fromString("score.webassets")); + assertEquals(new PyRequirement("pip_helpers"), PyRequirement.fromString("pip_helpers")); assertEquals(new PyRequirement("Django"), PyRequirement.fromString("Django")); assertEquals(new PyRequirement("django"), PyRequirement.fromString("django")); + assertEquals(new PyRequirement("pinax-utils"), PyRequirement.fromString("pinax-utils")); + assertEquals(new PyRequirement("no_limit_nester"), PyRequirement.fromString("no_limit_nester")); + assertEquals(new PyRequirement("Flask-Celery-py3"), PyRequirement.fromString("Flask-Celery-py3")); } - public void testRequirementWithVersion() { - assertEquals(new PyRequirement("Django", "1.3.1"), PyRequirement.fromString("Django==1.3.1")); + // https://www.python.org/dev/peps/pep-0440/ + public void testRequirementVersion() { + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5a20"), PyRequirement.fromString("Orange-Bioinformatics==2.5a20")); + assertEquals(new PyRequirement("MOCPy", "0.1.0.dev0"), PyRequirement.fromString("MOCPy==0.1.0.dev0")); + assertEquals(new PyRequirement("score.webassets", "0.2.3"), PyRequirement.fromString("score.webassets==0.2.3")); + assertEquals(new PyRequirement("pip_helpers", "0.5.post6"), PyRequirement.fromString("pip_helpers==0.5.post6")); + assertEquals(new PyRequirement("Django", "1.9rc1"), PyRequirement.fromString("Django==1.9rc1")); + assertEquals(new PyRequirement("django", "1!1"), PyRequirement.fromString("django==1!1")); + assertEquals(new PyRequirement("pinax-utils", "1.0b1.dev3"), PyRequirement.fromString("pinax-utils==1.0b1.dev3")); + assertEquals(new PyRequirement("Flask-Celery-py3", "0.1.*"), PyRequirement.fromString("Flask-Celery-py3==0.1.*")); + assertEquals(new PyRequirement("no_limit_nester", "1.0+local.version.10"), + PyRequirement.fromString("no_limit_nester==1.0+local.version.10")); + } - assertEquals(new PyRequirement("Django", Collections.singletonList(new PyRequirementVersionSpec(PyRequirementRelation.LT, "1.4"))), - PyRequirement.fromString(" Django < 1.4 ")); + // https://www.python.org/dev/peps/pep-0440/#normalization + public void testRequirementAlternatePreReleaseVersion() { + assertEquals(new PyRequirement("Django", "1.9rc1"), PyRequirement.fromString("Django==1.9RC1")); - assertEquals(new PyRequirement("Django", Arrays.asList(new PyRequirementVersionSpec(PyRequirementRelation.LT, "1.4"), - new PyRequirementVersionSpec(PyRequirementRelation.GTE, "1.3.1"))), - PyRequirement.fromString(" Django < 1.4 , >= 1.3.1 ")); + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5a20"), PyRequirement.fromString("Orange-Bioinformatics==2.5.a20")); + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5a20"), PyRequirement.fromString("Orange-Bioinformatics==2.5.a.20")); + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5a20"), PyRequirement.fromString("Orange-Bioinformatics==2.5-a20")); + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5a20"), PyRequirement.fromString("Orange-Bioinformatics==2.5-a_20")); + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5a20"), PyRequirement.fromString("Orange-Bioinformatics==2.5_a20")); + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5a20"), PyRequirement.fromString("Orange-Bioinformatics==2.5_a-20")); + + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5a20"), PyRequirement.fromString("Orange-Bioinformatics==2.5alpha20")); + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5a20"), PyRequirement.fromString("Orange-Bioinformatics==2.5.alpha20")); + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5a20"), PyRequirement.fromString("Orange-Bioinformatics==2.5.alpha.20")); + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5a20"), PyRequirement.fromString("Orange-Bioinformatics==2.5-alpha20")); + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5a20"), PyRequirement.fromString("Orange-Bioinformatics==2.5-alpha_20")); + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5a20"), PyRequirement.fromString("Orange-Bioinformatics==2.5_alpha20")); + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5a20"), PyRequirement.fromString("Orange-Bioinformatics==2.5_alpha-20")); + + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5b20"), PyRequirement.fromString("Orange-Bioinformatics==2.5beta20")); + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5b20"), PyRequirement.fromString("Orange-Bioinformatics==2.5.beta20")); + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5b20"), PyRequirement.fromString("Orange-Bioinformatics==2.5.beta.20")); + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5b20"), PyRequirement.fromString("Orange-Bioinformatics==2.5-beta20")); + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5b20"), PyRequirement.fromString("Orange-Bioinformatics==2.5-beta_20")); + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5b20"), PyRequirement.fromString("Orange-Bioinformatics==2.5_beta20")); + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5b20"), PyRequirement.fromString("Orange-Bioinformatics==2.5_beta-20")); + + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5rc20"), PyRequirement.fromString("Orange-Bioinformatics==2.5c20")); + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5rc20"), PyRequirement.fromString("Orange-Bioinformatics==2.5.c20")); + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5rc20"), PyRequirement.fromString("Orange-Bioinformatics==2.5.c.20")); + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5rc20"), PyRequirement.fromString("Orange-Bioinformatics==2.5-c20")); + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5rc20"), PyRequirement.fromString("Orange-Bioinformatics==2.5-c_20")); + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5rc20"), PyRequirement.fromString("Orange-Bioinformatics==2.5_c20")); + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5rc20"), PyRequirement.fromString("Orange-Bioinformatics==2.5_c-20")); + + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5rc20"), PyRequirement.fromString("Orange-Bioinformatics==2.5pre20")); + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5rc20"), PyRequirement.fromString("Orange-Bioinformatics==2.5.pre20")); + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5rc20"), PyRequirement.fromString("Orange-Bioinformatics==2.5.pre.20")); + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5rc20"), PyRequirement.fromString("Orange-Bioinformatics==2.5-pre20")); + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5rc20"), PyRequirement.fromString("Orange-Bioinformatics==2.5-pre_20")); + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5rc20"), PyRequirement.fromString("Orange-Bioinformatics==2.5_pre20")); + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5rc20"), PyRequirement.fromString("Orange-Bioinformatics==2.5_pre-20")); + + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5rc20"), PyRequirement.fromString("Orange-Bioinformatics==2.5preview20")); + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5rc20"), PyRequirement.fromString("Orange-Bioinformatics==2.5.preview20")); + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5rc20"), PyRequirement.fromString("Orange-Bioinformatics==2.5.preview.20")); + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5rc20"), PyRequirement.fromString("Orange-Bioinformatics==2.5-preview20")); + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5rc20"), PyRequirement.fromString("Orange-Bioinformatics==2.5-preview_20")); + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5rc20"), PyRequirement.fromString("Orange-Bioinformatics==2.5_preview20")); + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5rc20"), PyRequirement.fromString("Orange-Bioinformatics==2.5_preview-20")); + + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5a0"), PyRequirement.fromString("Orange-Bioinformatics==2.5a")); + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5a0"), PyRequirement.fromString("Orange-Bioinformatics==2.5.a")); + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5a0"), PyRequirement.fromString("Orange-Bioinformatics==2.5-a")); + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5a0"), PyRequirement.fromString("Orange-Bioinformatics==2.5_a")); + } + + // https://www.python.org/dev/peps/pep-0440/#normalization + public void testRequirementAlternatePostReleaseVersion() { + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5.post20"), PyRequirement.fromString("Orange-Bioinformatics==2.5-post20")); + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5.post20"), PyRequirement.fromString("Orange-Bioinformatics==2.5-post.20")); + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5.post20"), PyRequirement.fromString("Orange-Bioinformatics==2.5_post20")); + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5.post20"), PyRequirement.fromString("Orange-Bioinformatics==2.5_post_20")); + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5.post20"), PyRequirement.fromString("Orange-Bioinformatics==2.5post20")); + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5.post20"), PyRequirement.fromString("Orange-Bioinformatics==2.5post-20")); + + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5.post20"), PyRequirement.fromString("Orange-Bioinformatics==2.5.r20")); + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5.post20"), PyRequirement.fromString("Orange-Bioinformatics==2.5-r20")); + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5.post20"), PyRequirement.fromString("Orange-Bioinformatics==2.5-r.20")); + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5.post20"), PyRequirement.fromString("Orange-Bioinformatics==2.5_r20")); + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5.post20"), PyRequirement.fromString("Orange-Bioinformatics==2.5_r_20")); + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5.post20"), PyRequirement.fromString("Orange-Bioinformatics==2.5r20")); + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5.post20"), PyRequirement.fromString("Orange-Bioinformatics==2.5r-20")); + + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5.post20"), PyRequirement.fromString("Orange-Bioinformatics==2.5.rev20")); + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5.post20"), PyRequirement.fromString("Orange-Bioinformatics==2.5-rev20")); + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5.post20"), PyRequirement.fromString("Orange-Bioinformatics==2.5-rev.20")); + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5.post20"), PyRequirement.fromString("Orange-Bioinformatics==2.5_rev20")); + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5.post20"), PyRequirement.fromString("Orange-Bioinformatics==2.5_rev_20")); + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5.post20"), PyRequirement.fromString("Orange-Bioinformatics==2.5rev20")); + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5.post20"), PyRequirement.fromString("Orange-Bioinformatics==2.5rev-20")); + + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5.post0"), PyRequirement.fromString("Orange-Bioinformatics==2.5.post")); + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5.post0"), PyRequirement.fromString("Orange-Bioinformatics==2.5-post")); + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5.post0"), PyRequirement.fromString("Orange-Bioinformatics==2.5_post")); + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5.post0"), PyRequirement.fromString("Orange-Bioinformatics==2.5post")); + + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5.post20"), PyRequirement.fromString("Orange-Bioinformatics==2.5-20")); + } + + // https://www.python.org/dev/peps/pep-0440/#normalization + public void testRequirementAlternateDevelopmentVersion() { + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5.dev20"), PyRequirement.fromString("Orange-Bioinformatics==2.5-dev20")); + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5.dev20"), PyRequirement.fromString("Orange-Bioinformatics==2.5_dev20")); + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5.dev20"), PyRequirement.fromString("Orange-Bioinformatics==2.5dev20")); + + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5.dev0"), PyRequirement.fromString("Orange-Bioinformatics==2.5-dev")); + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5.dev0"), PyRequirement.fromString("Orange-Bioinformatics==2.5_dev")); + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5.dev0"), PyRequirement.fromString("Orange-Bioinformatics==2.5dev")); + } + + // https://www.python.org/dev/peps/pep-0440/#normalization + public void testRequirementAlternateLocalVersion() { + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5+local.version"), + PyRequirement.fromString("Orange-Bioinformatics==2.5+local-version")); + + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5+local.version"), + PyRequirement.fromString("Orange-Bioinformatics==2.5+local_version")); + } + + // https://www.python.org/dev/peps/pep-0440/#normalization + public void testRequirementAlternateVersionStart() { + assertEquals(new PyRequirement("Orange-Bioinformatics", "2.5a20"), PyRequirement.fromString("Orange-Bioinformatics==v2.5a20")); + assertEquals(new PyRequirement("MOCPy", "0.1.0.dev0"), PyRequirement.fromString("MOCPy==v0.1.0.dev0")); + assertEquals(new PyRequirement("score.webassets", "0.2.3"), PyRequirement.fromString("score.webassets==v0.2.3")); + assertEquals(new PyRequirement("pip_helpers", "0.5.post6"), PyRequirement.fromString("pip_helpers==v0.5.post6")); + assertEquals(new PyRequirement("Django", "1.9rc1"), PyRequirement.fromString("Django==v1.9rc1")); + assertEquals(new PyRequirement("django", "1!1"), PyRequirement.fromString("django==v1!1")); + assertEquals(new PyRequirement("pinax-utils", "1.0b1.dev3"), PyRequirement.fromString("pinax-utils==v1.0b1.dev3")); + assertEquals(new PyRequirement("no_limit_nester"), PyRequirement.fromString("no_limit_nester==v1.0+local.version.10")); + assertEquals(new PyRequirement("Flask-Celery-py3", "0.1.*"), PyRequirement.fromString("Flask-Celery-py3==v0.1.*")); + } + + // https://www.python.org/dev/peps/pep-0440/#version-specifiers + public void testRequirementRelation() { + doRequirementRelationTest(PyRequirementRelation.LT, "1.4"); + doRequirementRelationTest(PyRequirementRelation.LTE, "1.4"); + doRequirementRelationTest(PyRequirementRelation.NE, "1.4"); + doRequirementRelationTest(PyRequirementRelation.EQ, "1.4"); + doRequirementRelationTest(PyRequirementRelation.GT, "1.4"); + doRequirementRelationTest(PyRequirementRelation.GTE, "1.4"); + doRequirementRelationTest(PyRequirementRelation.COMPATIBLE, "1.*"); + doRequirementRelationTest(PyRequirementRelation.STR_EQ, "version"); + + doRequirementRelationTest(Arrays.asList(PyRequirementRelation.GTE, PyRequirementRelation.EQ), Arrays.asList("2.8.1", "2.8.*")); + doRequirementRelationTest(Arrays.asList(PyRequirementRelation.LT, PyRequirementRelation.GTE), Arrays.asList("1.4", "1.3.1")); + + doRequirementRelationTest(Arrays.asList(PyRequirementRelation.LT, PyRequirementRelation.GT, PyRequirementRelation.NE, + PyRequirementRelation.LT, PyRequirementRelation.EQ), + Arrays.asList("1.6", "1.9", "1.9.6", "2.0a0", "2.4rc1")); + + // PY-14583 + doRequirementRelationTest(Arrays.asList(PyRequirementRelation.GTE, PyRequirementRelation.LTE, PyRequirementRelation.GTE, + PyRequirementRelation.LTE), + Arrays.asList("0.8.4", "0.8.99", "0.9.7", "0.9.99")); + } + + // https://www.python.org/dev/peps/pep-0508/#extras + // PY-15674 + public void testRequirementExtras() { + final String name = "MyProject1"; + final List relations = Collections.emptyList(); + final List versions = Collections.emptyList(); + + doRequirementRelationTest(name, "[PDF]", relations, versions); + doRequirementRelationTest(name, " [extra1, extra2]", relations, versions); + doRequirementRelationTest(name, "[security,tests]", relations, versions); + } + + // https://www.python.org/dev/peps/pep-0508/#extras + // PY-15674 + public void testRequirementExtrasAndRelation() { + final String extras1 = "[PDF]"; + final String name1 = "MyPackage"; + + final String extras2 = " [foo, bar]"; + final String name2 = "Fizzy"; + + final String extras3 = " [security,tests]"; + final String name3 = "requests"; + + doRequirementRelationTest(name1, extras1, PyRequirementRelation.LT, "1.4"); + doRequirementRelationTest(name2, extras2, PyRequirementRelation.LTE, "1.4"); + doRequirementRelationTest(name3, extras3, PyRequirementRelation.NE, "1.4"); + doRequirementRelationTest(name1, extras1, PyRequirementRelation.EQ, "1.4"); + doRequirementRelationTest(name2, extras2, PyRequirementRelation.GT, "1.4"); + doRequirementRelationTest(name3, extras3, PyRequirementRelation.GTE, "1.4"); + doRequirementRelationTest(name1, extras1, PyRequirementRelation.COMPATIBLE, "1.*"); + doRequirementRelationTest(name2, extras2, PyRequirementRelation.STR_EQ, "version"); + + doRequirementRelationTest(name3, extras3, Arrays.asList(PyRequirementRelation.GTE, PyRequirementRelation.EQ), + Arrays.asList("2.8.1", "2.8.*")); + + doRequirementRelationTest(name1, extras1, Arrays.asList(PyRequirementRelation.LT, PyRequirementRelation.GTE), + Arrays.asList("1.4", "1.3.1")); + + doRequirementRelationTest(name2, extras2, Arrays.asList(PyRequirementRelation.LT, PyRequirementRelation.GT, PyRequirementRelation.NE, + PyRequirementRelation.LT, PyRequirementRelation.EQ), + Arrays.asList("1.6", "1.9", "1.9.6", "2.0a0", "2.4rc1")); + + // PY-14583 + doRequirementRelationTest(name3, extras3, Arrays.asList(PyRequirementRelation.GTE, PyRequirementRelation.LTE, PyRequirementRelation.GTE, + PyRequirementRelation.LTE), + Arrays.asList("0.8.4", "0.8.99", "0.9.7", "0.9.99")); } // PY-6355 @@ -1117,4 +1329,48 @@ public class PyRequirementTest extends PyTestCase { private static void doTest(@NotNull String options, boolean editable) { assertEquals(new PyRequirement("MyProject1", null, options, editable), PyRequirement.fromString(options)); } + + private static void doRequirementRelationTest(@NotNull PyRequirementRelation relation, @NotNull String version) { + doRequirementRelationTest("Django", null, Collections.singletonList(relation), Collections.singletonList(version)); + } + + private static void doRequirementRelationTest(@NotNull List relations, @NotNull List versions) { + doRequirementRelationTest("Django", null, relations, versions); + } + + private static void doRequirementRelationTest(@NotNull String name, + @Nullable String extras, + @NotNull PyRequirementRelation relation, + @NotNull String version) { + doRequirementRelationTest(name, extras, Collections.singletonList(relation), Collections.singletonList(version)); + } + + private static void doRequirementRelationTest(@NotNull String name, + @Nullable String extras, + @NotNull List relations, + @NotNull List versions) { + assertEquals(versions.size(), relations.size()); + + final StringBuilder sb = new StringBuilder(name); + final List expectedVersionSpecs = new ArrayList<>(); + + if (extras != null) sb.append(extras); + final int initialLength = sb.length(); + + for (Pair pair : ContainerUtil.zip(relations, versions)) { + final PyRequirementRelation relation = pair.getFirst(); + final String version = pair.getSecond(); + + sb.append(relation).append(version).append(","); + expectedVersionSpecs.add(new PyRequirementVersionSpec(relation, version)); + } + + if (sb.length() != initialLength) { + sb.setLength(sb.length() - 1); + } + + final String options = sb.toString(); + + assertEquals(new PyRequirement(name, options, expectedVersionSpecs), PyRequirement.fromString(options)); + } }