diff --git a/composer_pub.go b/composer_pub.go index 08ff3b4..131eac4 100644 --- a/composer_pub.go +++ b/composer_pub.go @@ -27,6 +27,7 @@ const ( const ( composerTildeBumpOffset = 2 + composerVersionParts = 4 composerQualifierDev = "dev" composerQualifierPatch = "patch" composerQualifierStable = "stable" @@ -170,6 +171,12 @@ func splitComposerStabilityFlag(constraint string) (string, string) { // parseComposerCaretRange expands a Composer caret constraint and uses a dev // upper bound so prereleases of the next breaking version are excluded. func parseComposerCaretRange(version string) (*Range, error) { + if lower, parts, ok := composerDevWildcardBound(version); ok { + upper := incrementComposerRelease(parts[:1], 0) + return rangeWithScheme(NewRange([]Interval{ + NewInterval(lower, upper, true, false), + }), schemeComposer), nil + } parts, ok := composerReleaseParts(version) if !ok { return nil, fmt.Errorf("invalid composer caret version: %s", version) @@ -192,6 +199,17 @@ func parseComposerCaretRange(version string) (*Range, error) { // components allow the next major; longer versions allow the penultimate // component to increase. func parseComposerTildeRange(version string) (*Range, error) { + if lower, parts, ok := composerDevWildcardBound(version); ok { + prefixLength := 0 + for prefixLength < len(parts) && parts[prefixLength] != "9999999" { + prefixLength++ + } + upperParts := parts[:prefixLength] + upper := incrementComposerRelease(upperParts, len(upperParts)-1) + return rangeWithScheme(NewRange([]Interval{ + NewInterval(lower, upper, true, false), + }), schemeComposer), nil + } parts, ok := composerReleaseParts(version) if !ok { return nil, fmt.Errorf("invalid composer tilde version: %s", version) @@ -256,19 +274,63 @@ func composerWildcardReleaseParts(constraint string) ([]string, bool) { // version behaves as a wildcard, while a complete upper version is inclusive. func parseComposerHyphenRange(lower, upper string) (*Range, error) { _, lowerOK := composerReleaseParts(lower) + min, lowerWildcardParts, lowerWildcard := composerDevWildcardBound(lower) + if lowerWildcard { + lowerOK = len(lowerWildcardParts) > 0 + } else { + min, _ = canonicalComposerNumericVersion(lower, composerQualifierDev) + } upperParts, upperOK := composerReleaseParts(upper) + max, _, upperWildcard := composerDevWildcardBound(upper) + if upperWildcard { + upperOK = true + } if !lowerOK || !upperOK { return nil, fmt.Errorf("invalid composer hyphen range: %s - %s", lower, upper) } - min, _ := canonicalComposerNumericVersion(lower, composerQualifierDev) + if upperWildcard { + return rangeWithScheme(NewRange([]Interval{NewInterval(min, max, true, true)}), schemeComposer), nil + } if len(upperParts) < 3 && !hasComposerStability(upper) { //nolint:mnd - max := incrementComposerRelease(upperParts, len(upperParts)-1) + max = incrementComposerRelease(upperParts, len(upperParts)-1) return rangeWithScheme(NewRange([]Interval{NewInterval(min, max, true, false)}), schemeComposer), nil } - max, _ := canonicalComposerNumericVersion(upper, "") + max, _ = canonicalComposerNumericVersion(upper, "") return rangeWithScheme(NewRange([]Interval{NewInterval(min, max, true, true)}), schemeComposer), nil } +func composerDevWildcardBound(version string) (string, []string, bool) { + version = normalizeComposerLower(version) + if !strings.HasSuffix(strings.ToLower(version), "-dev") { + return "", nil, false + } + release := version[:len(version)-len("-dev")] + segments := strings.Split(release, ".") + parts := make([]string, 0, composerVersionParts) + wildcard := false + for _, segment := range segments { + if segment == "*" || strings.EqualFold(segment, "x") { + if len(parts) == 0 { + return "", nil, false + } + wildcard = true + parts = append(parts, "9999999") + continue + } + if wildcard || !isDigits(segment) { + return "", nil, false + } + parts = append(parts, trimLeadingZeros(segment)) + } + if !wildcard || len(parts) > composerVersionParts { + return "", nil, false + } + for len(parts) < composerVersionParts { + parts = append(parts, "9999999") + } + return strings.Join(parts, ".") + "-dev", parts, true +} + // hasComposerStability reports whether a numeric Composer version has an // explicit stability suffix. func hasComposerStability(version string) bool { diff --git a/composer_pub_test.go b/composer_pub_test.go index 5329792..eda3d7c 100644 --- a/composer_pub_test.go +++ b/composer_pub_test.go @@ -3,7 +3,7 @@ package vers import "testing" func TestParseComposerRangeErrors(t *testing.T) { - for _, constraint := range []string{">=2.*", "^", "1.0 -", ">=1.0 ||"} { + for _, constraint := range []string{">=2.*", "^", "~x-dev", "1.0 -", ">=1.0 ||"} { if _, err := ParseNative(constraint, schemeComposer); err == nil { t.Errorf("ParseNative(%q, composer) succeeded", constraint) } @@ -113,3 +113,27 @@ func TestComposerAndPubVersRoundTrip(t *testing.T) { } } } + +func TestComposerDevWildcardRanges(t *testing.T) { + tests := []struct { + constraint string + version string + want bool + }{ + {constraint: "~2.x-dev", version: "2.9999999.9999999.9999999-dev", want: true}, + {constraint: "~2.x-dev", version: "3.0.0.0-dev", want: false}, + {constraint: "~2.0.x-dev", version: "2.1.0.0-dev", want: false}, + {constraint: "^2.0.x-dev", version: "2.0.9999999.9999999-dev", want: true}, + {constraint: "^2.0.x-dev", version: "3.0.0.0-dev", want: false}, + {constraint: "2.x-dev - 3.x-dev", version: "3.9999999.9999999.9999999-dev", want: true}, + } + for _, test := range tests { + r, err := ParseNative(test.constraint, schemeComposer) + if err != nil { + t.Fatalf("ParseNative(%q, composer): %v", test.constraint, err) + } + if got := r.Contains(test.version); got != test.want { + t.Errorf("ParseNative(%q, composer).Contains(%q) = %v, want %v", test.constraint, test.version, got, test.want) + } + } +} diff --git a/parser.go b/parser.go index 56c6c0c..e62eb0f 100644 --- a/parser.go +++ b/parser.go @@ -4,6 +4,7 @@ import ( "fmt" "net/url" "regexp" + "strconv" "strings" ) @@ -419,7 +420,7 @@ func (p *Parser) parseNpmRange(s string) (*Range, error) { } // Handle space-separated AND constraints - if strings.Contains(s, " ") && !strings.Contains(s, " - ") { + if strings.ContainsAny(s, " \t\r\n") && !strings.Contains(s, " - ") { parts := tokenizeNpmConstraints(s) var result *Range for _, part := range parts { @@ -468,7 +469,7 @@ func tokenizeNpmConstraints(s string) []string { // isOperatorOnly checks if a string is just an operator without a version. func isOperatorOnly(s string) bool { switch s { - case ">=", "<=", ">", "<", "=", "!=": + case ">=", "<=", ">", "<", "=", "!=", "~", "~>", "^": return true } return false @@ -486,22 +487,24 @@ func extractOperator(s string) (string, string) { } func (p *Parser) parseNpmSingleRange(s string) (*Range, error) { + s = strings.TrimSpace(s) // Caret range: ^1.2.3 if strings.HasPrefix(s, "^") { return p.parseCaretRange(s[1:]) } - // Tilde range: ~1.2.3 + // Tilde range: ~1.2.3 or ~>1.2.3 + if strings.HasPrefix(s, "~>") { + return p.parseTildeRange(strings.TrimSpace(s[2:])) + } if strings.HasPrefix(s, "~") { - return p.parseTildeRange(s[1:]) + return p.parseTildeRange(strings.TrimSpace(s[1:])) } // Hyphen range: 1.2.3 - 2.0.0 if strings.Contains(s, " - ") { parts := strings.SplitN(s, " - ", 2) //nolint:mnd - return NewRange([]Interval{ - NewInterval(strings.TrimSpace(parts[0]), strings.TrimSpace(parts[1]), true, true), - }), nil + return p.parseNpmHyphenRange(strings.TrimSpace(parts[0]), strings.TrimSpace(parts[1])) } // X-range: 1.x, 1.2.x (also handle operator + x-range like >=1.x) @@ -509,17 +512,19 @@ func (p *Parser) parseNpmSingleRange(s string) (*Range, error) { // Check if there's an operator prefix op, version := extractOperator(s) if op != "" { - // For >=X.x or >X.x, the x-range defines the minimum - xRange, err := p.parseXRange(version) - if err != nil { - return nil, err - } - // >=2.2.x means >=2.2.0 (start of the x-range) - // The x-range itself is the answer for >= with x-range - return xRange, nil + return p.parseNpmPartialRange(version, op) } return p.parseXRange(s) } + if op, version := extractOperator(s); isPartialNpmVersion(version) { + return p.parseNpmPartialRange(version, op) + } + if isPartialNpmVersion(s) { + return p.parseNpmPartialRange(s, "") + } + if op, version := extractOperator(s); op != "" { + s = op + strings.TrimSpace(version) + } // Standard constraint constraint, err := ParseConstraint(s) @@ -538,16 +543,26 @@ func (p *Parser) parseNpmSingleRange(s string) (*Range, error) { // ^1.2.3 := >=1.2.3 <2.0.0 func (p *Parser) parseCaretRange(version string) (*Range, error) { + if version == "" || version == "*" || version == "x" || version == "X" { + return Unbounded(), nil + } + if strings.HasSuffix(version, ".x") || strings.HasSuffix(version, ".X") || strings.HasSuffix(version, ".*") { + return p.parseXRange(version) + } + v, err := ParseVersion(version) if err != nil { return nil, err } + base := strings.SplitN(version, "+", 2)[0] //nolint:mnd + base = strings.SplitN(base, "-", 2)[0] //nolint:mnd + segments := strings.Count(base, ".") + 1 var upper string switch { - case v.Major > 0: + case segments == 1 || v.Major > 0: upper = fmt.Sprintf("%d.0.0", v.Major+1) - case v.Minor > 0: + case segments == 2 || v.Minor > 0: //nolint:mnd upper = fmt.Sprintf("0.%d.0", v.Minor+1) default: upper = fmt.Sprintf("0.0.%d", v.Patch+1) @@ -561,29 +576,21 @@ func (p *Parser) parseCaretRange(version string) (*Range, error) { // ~1.2.3 := >=1.2.3 <1.3.0 // ~1.2.3-pre := >=1.2.3-pre <1.2.3 OR >=1.2.3 <1.2.4 (for prerelease handling) func (p *Parser) parseTildeRange(version string) (*Range, error) { + if version == "" || version == "*" || version == "x" || version == "X" { + return Unbounded(), nil + } + if strings.HasSuffix(version, ".x") || strings.HasSuffix(version, ".X") || strings.HasSuffix(version, ".*") { + return p.parseXRange(version) + } + v, err := ParseVersion(version) if err != nil { return nil, err } - // If there's a prerelease, we need special handling - // npm semver only matches prereleases if they're on the same major.minor.patch - if v.Prerelease != "" { - // Create two intervals: - // 1. Prereleases from the specified version to the release version - // 2. Release versions for patch updates - baseVersion := fmt.Sprintf("%d.%d.%d", v.Major, v.Minor, v.Patch) - nextPatch := fmt.Sprintf("%d.%d.%d", v.Major, v.Minor, v.Patch+1) - - return NewRange([]Interval{ - // Prerelease interval: >=version =baseVersion = 2 { //nolint:mnd @@ -596,36 +603,150 @@ func (p *Parser) parseTildeRange(version string) (*Range, error) { upper = fmt.Sprintf("%d.0.0", v.Major+1) } - return NewRange([]Interval{ + r := NewRange([]Interval{ NewInterval(version, upper, true, false), - }), nil + }) + if v.Prerelease != "" { + baseVersion := fmt.Sprintf("%d.%d.%d", v.Major, v.Minor, v.Patch) + nextPatch := fmt.Sprintf("%d.%d.%d", v.Major, v.Minor, v.Patch+1) + r.RawConstraints = []Interval{ + NewInterval(version, baseVersion, true, false), + NewInterval(baseVersion, nextPatch, true, false), + } + } + return r, nil } // 1.x := >=1.0.0 <2.0.0 func (p *Parser) parseXRange(s string) (*Range, error) { - s = strings.TrimSuffix(s, ".x") - s = strings.TrimSuffix(s, ".X") - s = strings.TrimSuffix(s, ".*") + return p.parseNpmPartialRange(s, "") +} - parts := strings.Split(s, ".") - if len(parts) == 1 { - major := parts[0] - v, err := ParseVersion(major) +func (p *Parser) parseNpmPartialRange(version, operator string) (*Range, error) { + lower, upper, err := npmPartialBounds(version) + if err != nil { + return nil, err + } + if lower == "" { + return Unbounded(), nil + } + var r *Range + switch operator { + case "", "=": + r = NewRange([]Interval{NewInterval(lower, upper, true, false)}) + case ">=": + r = NewRange([]Interval{NewInterval(lower, "", true, false)}) + case ">": + r = NewRange([]Interval{NewInterval(upper, "", true, false)}) + case "<=": + r = NewRange([]Interval{NewInterval("", upper, false, false)}) + case "<": + r = NewRange([]Interval{NewInterval("", lower, false, false)}) + default: + return nil, fmt.Errorf("invalid operator for npm partial range: %s", operator) + } + // Keep the established native-to-VERS rendering while containment uses + // the expanded interval above. + hasWildcard := strings.ContainsAny(version, "xX*") + switch { + case hasWildcard: + r.RawConstraints = []Interval{NewInterval(lower, upper, true, false)} + case operator == "" || operator == "=": + r.RawConstraints = []Interval{ExactInterval(lower)} + case operator == ">=": + r.RawConstraints = []Interval{NewInterval(lower, "", true, false)} + case operator == ">": + r.RawConstraints = []Interval{NewInterval(lower, "", false, false)} + case operator == "<=": + r.RawConstraints = []Interval{NewInterval("", lower, false, true)} + case operator == "<": + r.RawConstraints = []Interval{NewInterval("", lower, false, false)} + } + return r, nil +} + +func npmPartialBounds(version string) (string, string, error) { + version = strings.TrimSpace(version) + if version == "" || version == "*" || version == "x" || version == "X" { + return "", "", nil + } + version = strings.TrimPrefix(strings.TrimPrefix(version, "v"), "V") + segments := strings.Split(version, ".") + if len(segments) > 3 { //nolint:mnd + return "", "", fmt.Errorf("invalid npm partial version: %s", version) + } + parts := make([]int, 0, len(segments)) + wildcard := false + for _, segment := range segments { + if segment == "*" || strings.EqualFold(segment, "x") { + wildcard = true + continue + } + if wildcard || !isDigits(segment) { + return "", "", fmt.Errorf("invalid npm partial version: %s", version) + } + value, err := strconv.Atoi(segment) if err != nil { - return nil, err + return "", "", fmt.Errorf("invalid npm partial version: %s", version) } - return NewRange([]Interval{ - NewInterval(fmt.Sprintf("%d.0.0", v.Major), fmt.Sprintf("%d.0.0", v.Major+1), true, false), - }), nil + parts = append(parts, value) } + if len(parts) == 0 { + return "", "", nil + } + lowerParts := append([]int(nil), parts...) + for len(lowerParts) < 3 { //nolint:mnd + lowerParts = append(lowerParts, 0) + } + upperParts := append([]int(nil), lowerParts...) + upperParts[len(parts)-1]++ + for index := len(parts); index < len(upperParts); index++ { + upperParts[index] = 0 + } + return fmt.Sprintf("%d.%d.%d", lowerParts[0], lowerParts[1], lowerParts[2]), + fmt.Sprintf("%d.%d.%d", upperParts[0], upperParts[1], upperParts[2]), nil +} - v, err := ParseVersion(s) - if err != nil { - return nil, err +func isPartialNpmVersion(version string) bool { + version = strings.TrimSpace(version) + version = strings.TrimPrefix(strings.TrimPrefix(version, "v"), "V") + segments := strings.Split(version, ".") + if len(segments) > 3 { //nolint:mnd + return false } - return NewRange([]Interval{ - NewInterval(fmt.Sprintf("%d.%d.0", v.Major, v.Minor), fmt.Sprintf("%d.%d.0", v.Major, v.Minor+1), true, false), - }), nil + partial := len(segments) < 3 //nolint:mnd + for _, segment := range segments { + if segment == "*" || strings.EqualFold(segment, "x") { + partial = true + continue + } + if !isDigits(segment) { + return false + } + } + return partial +} + +func (p *Parser) parseNpmHyphenRange(lower, upper string) (*Range, error) { + min := lower + if isPartialNpmVersion(lower) { + var err error + min, _, err = npmPartialBounds(lower) + if err != nil { + return nil, err + } + } + max := upper + maxInclusive := true + if isPartialNpmVersion(upper) { + var err error + _, max, err = npmPartialBounds(upper) + if err != nil { + return nil, err + } + maxInclusive = false + } + return NewRange([]Interval{NewInterval(min, max, true, maxInclusive)}), nil } // gem: ~> 1.2, >= 1.0, < 2.0 @@ -683,9 +804,13 @@ func (p *Parser) parseGemPessimisticRange(version string) (*Range, error) { head[len(head)-1] = incNumStr(head[len(head)-1]) upper = strings.Join(head, ".") } + upper += ".a" return &Range{ Intervals: []Interval{NewInterval(version, upper, true, false)}, - Scheme: schemeGem, + // RubyGems applies the upper bound to Version#release for ~>, while + // the established VERS rendering uses the bare bumped version. + RawConstraints: []Interval{NewInterval(version, strings.TrimSuffix(upper, ".a"), true, false)}, + Scheme: schemeGem, }, nil } @@ -743,6 +868,12 @@ func (p *Parser) parsePypiRange(s string) (*Range, error) { if strings.HasPrefix(s, "===") { return nil, fmt.Errorf("pypi arbitrary equality constraints are not supported: %s", s) } + if strings.HasPrefix(s, "==") && strings.HasSuffix(strings.TrimSpace(s[2:]), ".*") { + return parsePypiPrefixRange(strings.TrimSpace(s[2:]), false) + } + if strings.HasPrefix(s, "!=") && strings.HasSuffix(strings.TrimSpace(s[2:]), ".*") { + return parsePypiPrefixRange(strings.TrimSpace(s[2:]), true) + } if strings.HasPrefix(s, "==") { s = "=" + strings.TrimSpace(s[2:]) } @@ -750,6 +881,35 @@ func (p *Parser) parsePypiRange(s string) (*Range, error) { return p.parseConstraints(s, schemePyPI) } +func parsePypiPrefixRange(version string, exclude bool) (*Range, error) { + prefix := strings.TrimSuffix(version, ".*") + v, ok := parsePEP440(prefix) + if !ok || v.hasPre || v.hasPost || v.hasDev || len(v.local) > 0 { + return nil, fmt.Errorf("invalid pypi prefix constraint: %s", version) + } + lower := prefix + ".dev0" + upperRelease := append([]string(nil), v.release...) + upperRelease[len(upperRelease)-1] = incNumStr(upperRelease[len(upperRelease)-1]) + upper := strings.Join(upperRelease, ".") + ".dev0" + if bang := strings.IndexByte(prefix, '!'); bang >= 0 { + epoch := trimLeadingZeros(v.epoch) + lower = epoch + "!" + prefix[bang+1:] + ".dev0" + upper = epoch + "!" + upper + } + if !exclude { + return &Range{ + Intervals: []Interval{NewInterval(lower, upper, true, false)}, Scheme: schemePyPI, + }, nil + } + return &Range{ + Intervals: []Interval{ + NewInterval("", lower, false, false), + NewInterval(upper, "", true, false), + }, + Scheme: schemePyPI, + }, nil +} + // parsePypiCompatibleRelease handles PEP 440 ~= by deriving the upper bound // from release segments (ignoring pre/post/dev) and preserving the epoch. func (p *Parser) parsePypiCompatibleRelease(version string) (*Range, error) { @@ -849,6 +1009,13 @@ func (p *Parser) parseCargoRange(s string) (*Range, error) { if s != "" && !strings.ContainsAny(s, "^~*<>=") { return p.parseCaretRange(s) } + if operator, version := extractOperator(s); operator == "<" && isPartialNpmVersion(version) { + lower, _, err := npmPartialBounds(version) + if err != nil { + return nil, err + } + return NewRange([]Interval{NewInterval("", lower+"-0", false, false)}), nil + } return p.parseNpmRange(s) } diff --git a/parser_test.go b/parser_test.go index a83e074..bfdc802 100644 --- a/parser_test.go +++ b/parser_test.go @@ -75,6 +75,11 @@ func TestParseNpmRange(t *testing.T) { {"^0.2.3 includes patch", "^0.2.3", "0.2.5", true}, {"^0.2.3 excludes minor", "^0.2.3", "0.3.0", false}, {"^0.0.3 excludes patch", "^0.0.3", "0.0.4", false}, + {"^x matches all", "^x", "999.0.0", true}, + {"^0 includes zero major", "^0", "0.9.0", true}, + {"^0 excludes next major", "^0", "1.0.0", false}, + {"^0.0 includes patch", "^0.0", "0.0.9", true}, + {"^0.0 excludes minor", "^0.0", "0.1.0", false}, // Tilde ranges {"~1.2.3 includes patch", "~1.2.3", "1.2.5", true}, @@ -87,6 +92,9 @@ func TestParseNpmRange(t *testing.T) { {"~1.0 excludes minor", "~1.0", "1.1.0", false}, {"~1 includes minor", "~1", "1.9.0", true}, {"~1 excludes major", "~1", "2.0.0", false}, + {"~x matches all", "~x", "999.0.0", true}, + {"~>1 includes minor", "~>1", "1.9.0", true}, + {"~>1 excludes major", "~>1", "2.0.0", false}, // X-ranges {"1.x includes 1.0.0", "1.x", "1.0.0", true}, @@ -94,12 +102,19 @@ func TestParseNpmRange(t *testing.T) { {"1.x excludes 2.0.0", "1.x", "2.0.0", false}, {"1.2.x includes 1.2.0", "1.2.x", "1.2.0", true}, {"1.2.x excludes 1.3.0", "1.2.x", "1.3.0", false}, + {"2.x.x includes 2.9.0", "2.x.x", "2.9.0", true}, + {"2 includes minor", "2", "2.9.0", true}, + {"2.3 includes patch", "2.3", "2.3.9", true}, + {"less than partial excludes its release line", "<1.2", "1.2.1", false}, + {"less than or equal wildcard includes earlier", "<=0.7.x", "0.6.2", true}, // Hyphen ranges {"1.0.0 - 2.0.0 includes min", "1.0.0 - 2.0.0", "1.0.0", true}, {"1.0.0 - 2.0.0 includes max", "1.0.0 - 2.0.0", "2.0.0", true}, {"1.0.0 - 2.0.0 includes middle", "1.0.0 - 2.0.0", "1.5.0", true}, {"1.0.0 - 2.0.0 excludes below", "1.0.0 - 2.0.0", "0.9.0", false}, + {"partial hyphen includes upper line", "1 - 2", "2.9.0", true}, + {"partial hyphen excludes next major", "1 - 2", "3.0.0", false}, // OR ranges {"|| includes first", "1.0.0 || 2.0.0", "1.0.0", true}, @@ -114,6 +129,9 @@ func TestParseNpmRange(t *testing.T) { // Wildcards {"* matches all", "*", "999.0.0", true}, {"x matches all", "x", "999.0.0", true}, + {"wildcard excludes prerelease", "*", "1.0.0-pre", false}, + {"caret excludes next-major prerelease", "^1.2.3", "2.0.0-alpha", false}, + {"tab-separated operator", "<\t2.0.0", "0.2.9", true}, } parser := NewParser() @@ -131,6 +149,14 @@ func TestParseNpmRange(t *testing.T) { } } +func TestParseNpmRangeErrors(t *testing.T) { + for _, constraint := range []string{"1.x.2", "1.2.3.x"} { + if _, err := ParseNative(constraint, schemeNPM); err == nil { + t.Errorf("ParseNative(%q, npm) succeeded", constraint) + } + } +} + func TestParseGemRange(t *testing.T) { tests := []struct { name string @@ -143,6 +169,8 @@ func TestParseGemRange(t *testing.T) { {"~> 1.2.3 excludes minor", "~> 1.2.3", "1.3.0", false}, {"~> 1.2 includes minor", "~> 1.2", "1.5.0", true}, {"~> 1.2 excludes major", "~> 1.2", "2.0.0", false}, + {"~> 1.0.0 excludes next-minor prerelease", "~> 1.0.0", "1.1.pre", false}, + {"~> 1.0 excludes next-major prerelease", "~> 1.0", "2.0.a", false}, // Standard constraints {">= 1.0.0 includes", ">= 1.0.0", "1.5.0", true}, @@ -187,6 +215,13 @@ func TestParsePypiRange(t *testing.T) { {"<2.0.0 includes", "<2.0.0", "1.9.9", true}, {"!=1.5.0 excludes", "!=1.5.0", "1.5.0", false}, {"!=1.5.0 includes other", "!=1.5.0", "1.4.0", true}, + {"==2 ignores candidate local", "==2", "2.0+deadbeef", true}, + {"!=2 excludes candidate local", "!=2", "2.0+deadbeef", false}, + {"==2.* includes prerelease", "==2.*", "2rc1", true}, + {"==2.0.* excludes next minor", "==2.0.*", "2.1", false}, + {"!=2.* excludes matching prerelease", "!=2.*", "2a1", false}, + {">2 excludes same-release post", ">2", "2.0.post1", false}, + {"<2 excludes same-release prerelease", "<2", "2.0rc1", false}, // Comma-separated {">=1.0.0,<2.0.0 includes", ">=1.0.0,<2.0.0", "1.5.0", true}, @@ -292,6 +327,8 @@ func TestParseCargoRange(t *testing.T) { {"^1.2.3 excludes major", "^1.2.3", "2.0.0", false}, {"~1.2.3 includes patch", "~1.2.3", "1.2.9", true}, {"~1.2.3 excludes minor", "~1.2.3", "1.3.0", false}, + {"exact ignores build metadata", "=0.1.0+meta", "0.1.0+other", true}, + {"partial upper excludes same-release prerelease", ">1.0.0-alpha, <1.0", "1.0.0-beta", false}, } parser := NewParser() diff --git a/pypi_test.go b/pypi_test.go index 0303015..c4712bb 100644 --- a/pypi_test.go +++ b/pypi_test.go @@ -250,8 +250,8 @@ func TestPyPIRangeContains(t *testing.T) { // constraint order reversed (as in the issue) {"vers:pypi/<5.2b1|>=5.1", "6.0.3", false}, {"vers:pypi/<5.2b1|>=5.1", "5.1.5", true}, - // upper bound is a release, prereleases of that release are inside - {"vers:pypi/>=1.0|<2.0", "2.0a1", true}, + // An exclusive release bound excludes prereleases of that release. + {"vers:pypi/>=1.0|<2.0", "2.0a1", false}, {"vers:pypi/>=1.0|<2.0", "2.0", false}, {"vers:pypi/>=1.0|<2.0", "1.0", true}, // dev release below lower bound @@ -477,7 +477,7 @@ func TestPyPINativeRangeContains(t *testing.T) { }{ {">=5.1,<5.2b1", "5.1.5", true}, {">=5.1,<5.2b1", "6.0.3", false}, - {">=1.0,<2.0", "2.0a1", true}, + {">=1.0,<2.0", "2.0a1", false}, {">=1.0,<2.0", "2.0", false}, } for _, tt := range tests { diff --git a/range.go b/range.go index db6e15a..9327323 100644 --- a/range.go +++ b/range.go @@ -25,18 +25,34 @@ func NewRange(intervals []Interval) *Range { // Contains checks if the range contains the given version. func (r *Range) Contains(version string) bool { + scheme := canonicalScheme(r.Scheme) cmp := compareFuncFor(r.Scheme) + if scheme == schemeCargo { + cmp = compareSemver + } + if scheme == schemeNPM || scheme == schemeCargo { + if _, err := ParseVersion(version); err != nil { + return false + } + } // Check exclusions first for _, exc := range r.Exclusions { - if cmp(version, exc) == 0 { + if scheme == schemePyPI && pep440SpecifierEqual(version, exc) || scheme != schemePyPI && cmp(version, exc) == 0 { return false } } // Check if version is in any interval for _, interval := range r.Intervals { - if interval.containsCmp(version, cmp) { + contains := interval.containsCmp(version, cmp) + if scheme == schemePyPI { + contains = pypiIntervalContains(interval, version) + } + if contains && (scheme == schemeNPM || scheme == schemeCargo) && !semverIntervalAllowsPrerelease(interval, version) { + contains = false + } + if contains { return true } } @@ -44,6 +60,95 @@ func (r *Range) Contains(version string) bool { return false } +func semverIntervalAllowsPrerelease(interval Interval, version string) bool { + candidate, err := ParseVersion(version) + if err != nil || candidate.Prerelease == "" { + return err == nil + } + for _, bound := range []string{interval.Min, interval.Max} { + parsed, parseErr := ParseVersion(bound) + if parseErr == nil && parsed.Prerelease != "" && + parsed.Major == candidate.Major && parsed.Minor == candidate.Minor && parsed.Patch == candidate.Patch { + return true + } + } + return false +} + +func pypiIntervalContains(interval Interval, version string) bool { + if interval.Min != "" && interval.Max != "" && interval.MinInclusive && interval.MaxInclusive && + comparePyPI(interval.Min, interval.Max) == 0 { + return pep440SpecifierEqual(version, interval.Min) + } + if !interval.containsCmp(version, comparePyPI) { + return false + } + candidate, candidateOK := parsePEP440(version) + if !candidateOK { + return false + } + if interval.Min != "" && !interval.MinInclusive { + bound, boundOK := parsePEP440(interval.Min) + if boundOK { + if pep440SpecifierEqual(version, interval.Min) { + return false + } + withoutPost := candidate + withoutPost.hasPost = false + withoutPost.post = "" + withoutPost.hasDev = false + withoutPost.dev = "" + withoutPost.local = nil + if candidate.hasPost && pep440VersionsEqual(withoutPost, bound, true) { + return false + } + } + } + if interval.Max != "" && !interval.MaxInclusive { + bound, boundOK := parsePEP440(interval.Max) + if boundOK { + if !bound.hasPre && !bound.hasPost && !bound.hasDev && + samePEP440Release(candidate, bound) && (candidate.hasPre || candidate.hasDev) { + return false + } + withoutDev := candidate + withoutDev.hasDev = false + withoutDev.dev = "" + withoutDev.local = nil + if candidate.hasDev && pep440VersionsEqual(withoutDev, bound, true) { + return false + } + } + } + return true +} + +func pep440SpecifierEqual(version, specifier string) bool { + candidate, candidateOK := parsePEP440(version) + bound, boundOK := parsePEP440(specifier) + if !candidateOK || !boundOK { + return comparePyPI(version, specifier) == 0 + } + return pep440VersionsEqual(candidate, bound, len(bound.local) == 0) +} + +func pep440VersionsEqual(left, right pep440Version, ignoreLocal bool) bool { + if ignoreLocal { + left.local = nil + right.local = nil + } + return cmpNumStr(left.epoch, right.epoch) == 0 && + cmpNumStrSlice(left.release, right.release) == 0 && + cmpPEP440Pre(left, right) == 0 && + cmpPEP440Post(left, right) == 0 && + cmpPEP440Dev(left, right) == 0 && + cmpPEP440Local(left.local, right.local) == 0 +} + +func samePEP440Release(left, right pep440Version) bool { + return cmpNumStr(left.epoch, right.epoch) == 0 && cmpNumStrSlice(left.release, right.release) == 0 +} + // IsEmpty returns true if this range matches no versions. func (r *Range) IsEmpty() bool { if len(r.Intervals) == 0 { diff --git a/testdata/local/provenance.json b/testdata/local/provenance.json index a9dbdd9..428480e 100644 --- a/testdata/local/provenance.json +++ b/testdata/local/provenance.json @@ -20,10 +20,13 @@ "license": "ISC", "source_files": [ "test/fixtures/comparisons.js", - "test/fixtures/equality.js" + "test/fixtures/equality.js", + "test/fixtures/range-include.js", + "test/fixtures/range-exclude.js" ], "generated_files": [ - "tests/npm_version_cmp_test.json" + "tests/npm_version_cmp_test.json", + "tests/npm_range_reference_test.json" ] }, { @@ -31,10 +34,12 @@ "commit": "55cbf1b9426f44455fa1a9e0836f1fc082cc8452", "license": "Apache-2.0 OR BSD-2-Clause", "source_files": [ - "tests/test_version.py" + "tests/test_version.py", + "tests/test_specifiers.py" ], "generated_files": [ - "tests/pypi_version_cmp_test.json" + "tests/pypi_version_cmp_test.json", + "tests/pypi_range_reference_test.json" ] }, { @@ -42,10 +47,12 @@ "commit": "370fe6876eec1714cd0f8824c3f19f4d368dfe7c", "license": "MIT", "source_files": [ - "test/rubygems/test_gem_version.rb" + "test/rubygems/test_gem_version.rb", + "test/rubygems/test_gem_requirement.rb" ], "generated_files": [ - "tests/gem_version_cmp_test.json" + "tests/gem_version_cmp_test.json", + "tests/gem_range_reference_test.json" ] }, { @@ -53,10 +60,12 @@ "commit": "1cbc9b575a27458074d21a3bab95b847c8de387c", "license": "MIT", "source_files": [ - "tests/ComparatorTest.php" + "tests/ComparatorTest.php", + "tests/VersionParserTest.php" ], "generated_files": [ - "tests/composer_version_cmp_test.json" + "tests/composer_version_cmp_test.json", + "tests/composer_range_reference_test.json" ] }, { @@ -64,10 +73,14 @@ "commit": "a22c3a687dc1b35630fb34c296157d66565429cd", "license": "BSD-3-Clause", "source_files": [ - "pkgs/pub_semver/test/version_test.dart" + "pkgs/pub_semver/test/version_test.dart", + "pkgs/pub_semver/test/version_range_test.dart", + "pkgs/pub_semver/test/version_constraint_test.dart", + "pkgs/pub_semver/test/utils.dart" ], "generated_files": [ - "tests/pub_version_cmp_test.json" + "tests/pub_version_cmp_test.json", + "tests/pub_range_reference_test.json" ] }, { @@ -75,10 +88,23 @@ "commit": "280ebcb6edac3aa4cdc545dbff8a26c5ac4861fe", "license": "MIT OR Apache-2.0", "source_files": [ - "tests/test_version.rs" + "tests/test_version.rs", + "tests/test_version_req.rs" ], "generated_files": [ - "tests/cargo_version_cmp_test.json" + "tests/cargo_version_cmp_test.json", + "tests/cargo_range_reference_test.json" + ] + }, + { + "repository": "https://github.com/apache/maven.git", + "commit": "48514f63b2799844c9f8d7746f73a95123526df7", + "license": "Apache-2.0", + "source_files": [ + "compat/maven-artifact/src/test/java/org/apache/maven/artifact/versioning/VersionRangeTest.java" + ], + "generated_files": [ + "tests/maven_range_reference_test.json" ] }, { diff --git a/testdata/local/tests/cargo_range_reference_test.json b/testdata/local/tests/cargo_range_reference_test.json new file mode 100644 index 0000000..de04636 --- /dev/null +++ b/testdata/local/tests/cargo_range_reference_test.json @@ -0,0 +1,1965 @@ +{ + "$schema": "https://packageurl.org/schemas/vers-test.schema-0.2.json", + "tests": [ + { + "description": "semver range \"1.0.0\" contains \"1.0.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.0.0|\u003c2.0.0", + "version": "1.0.0" + }, + "expected_output": true + }, + { + "description": "semver range \"1.0.0\" contains \"1.1.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.0.0|\u003c2.0.0", + "version": "1.1.0" + }, + "expected_output": true + }, + { + "description": "semver range \"1.0.0\" contains \"1.0.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.0.0|\u003c2.0.0", + "version": "1.0.1" + }, + "expected_output": true + }, + { + "description": "semver range \"1.0.0\" excludes \"0.9.9\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.0.0|\u003c2.0.0", + "version": "0.9.9" + }, + "expected_output": false + }, + { + "description": "semver range \"1.0.0\" excludes \"0.10.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.0.0|\u003c2.0.0", + "version": "0.10.0" + }, + "expected_output": false + }, + { + "description": "semver range \"1.0.0\" excludes \"0.1.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.0.0|\u003c2.0.0", + "version": "0.1.0" + }, + "expected_output": false + }, + { + "description": "semver range \"1.0.0\" excludes \"1.0.0-pre\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.0.0|\u003c2.0.0", + "version": "1.0.0-pre" + }, + "expected_output": false + }, + { + "description": "semver range \"1.0.0\" excludes \"1.0.1-pre\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.0.0|\u003c2.0.0", + "version": "1.0.1-pre" + }, + "expected_output": false + }, + { + "description": "semver range \"=1.0.0\" contains \"1.0.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/1.0.0", + "version": "1.0.0" + }, + "expected_output": true + }, + { + "description": "semver range \"=1.0.0\" excludes \"1.0.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/1.0.0", + "version": "1.0.1" + }, + "expected_output": false + }, + { + "description": "semver range \"=1.0.0\" excludes \"0.9.9\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/1.0.0", + "version": "0.9.9" + }, + "expected_output": false + }, + { + "description": "semver range \"=1.0.0\" excludes \"0.10.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/1.0.0", + "version": "0.10.0" + }, + "expected_output": false + }, + { + "description": "semver range \"=1.0.0\" excludes \"0.1.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/1.0.0", + "version": "0.1.0" + }, + "expected_output": false + }, + { + "description": "semver range \"=1.0.0\" excludes \"1.0.0-pre\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/1.0.0", + "version": "1.0.0-pre" + }, + "expected_output": false + }, + { + "description": "semver range \"=0.9.0\" contains \"0.9.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/0.9.0", + "version": "0.9.0" + }, + "expected_output": true + }, + { + "description": "semver range \"=0.9.0\" excludes \"0.9.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/0.9.0", + "version": "0.9.1" + }, + "expected_output": false + }, + { + "description": "semver range \"=0.9.0\" excludes \"1.9.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/0.9.0", + "version": "1.9.0" + }, + "expected_output": false + }, + { + "description": "semver range \"=0.9.0\" excludes \"0.0.9\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/0.9.0", + "version": "0.0.9" + }, + "expected_output": false + }, + { + "description": "semver range \"=0.9.0\" excludes \"0.9.0-pre\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/0.9.0", + "version": "0.9.0-pre" + }, + "expected_output": false + }, + { + "description": "semver range \"=0.0.2\" contains \"0.0.2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/0.0.2", + "version": "0.0.2" + }, + "expected_output": true + }, + { + "description": "semver range \"=0.0.2\" excludes \"0.0.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/0.0.2", + "version": "0.0.1" + }, + "expected_output": false + }, + { + "description": "semver range \"=0.0.2\" excludes \"0.0.3\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/0.0.2", + "version": "0.0.3" + }, + "expected_output": false + }, + { + "description": "semver range \"=0.0.2\" excludes \"0.0.2-pre\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/0.0.2", + "version": "0.0.2-pre" + }, + "expected_output": false + }, + { + "description": "semver range \"=0.1.0-beta2.a\" contains \"0.1.0-beta2.a\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/0.1.0-beta2.a", + "version": "0.1.0-beta2.a" + }, + "expected_output": true + }, + { + "description": "semver range \"=0.1.0-beta2.a\" excludes \"0.9.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/0.1.0-beta2.a", + "version": "0.9.1" + }, + "expected_output": false + }, + { + "description": "semver range \"=0.1.0-beta2.a\" excludes \"0.1.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/0.1.0-beta2.a", + "version": "0.1.0" + }, + "expected_output": false + }, + { + "description": "semver range \"=0.1.0-beta2.a\" excludes \"0.1.1-beta2.a\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/0.1.0-beta2.a", + "version": "0.1.1-beta2.a" + }, + "expected_output": false + }, + { + "description": "semver range \"=0.1.0-beta2.a\" excludes \"0.1.0-beta2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/0.1.0-beta2.a", + "version": "0.1.0-beta2" + }, + "expected_output": false + }, + { + "description": "semver range \"=0.1.0+meta\" contains \"0.1.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/0.1.0+meta", + "version": "0.1.0" + }, + "expected_output": true + }, + { + "description": "semver range \"=0.1.0+meta\" contains \"0.1.0+meta\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/0.1.0+meta", + "version": "0.1.0+meta" + }, + "expected_output": true + }, + { + "description": "semver range \"=0.1.0+meta\" contains \"0.1.0+any\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/0.1.0+meta", + "version": "0.1.0+any" + }, + "expected_output": true + }, + { + "description": "semver range \"\u003e= 1.0.0\" contains \"1.0.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.0.0", + "version": "1.0.0" + }, + "expected_output": true + }, + { + "description": "semver range \"\u003e= 1.0.0\" contains \"2.0.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.0.0", + "version": "2.0.0" + }, + "expected_output": true + }, + { + "description": "semver range \"\u003e= 1.0.0\" excludes \"0.1.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.0.0", + "version": "0.1.0" + }, + "expected_output": false + }, + { + "description": "semver range \"\u003e= 1.0.0\" excludes \"0.0.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.0.0", + "version": "0.0.1" + }, + "expected_output": false + }, + { + "description": "semver range \"\u003e= 1.0.0\" excludes \"1.0.0-pre\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.0.0", + "version": "1.0.0-pre" + }, + "expected_output": false + }, + { + "description": "semver range \"\u003e= 1.0.0\" excludes \"2.0.0-pre\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.0.0", + "version": "2.0.0-pre" + }, + "expected_output": false + }, + { + "description": "semver range \"\u003e= 2.1.0-alpha2\" contains \"2.1.0-alpha2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=2.1.0-alpha2", + "version": "2.1.0-alpha2" + }, + "expected_output": true + }, + { + "description": "semver range \"\u003e= 2.1.0-alpha2\" contains \"2.1.0-alpha3\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=2.1.0-alpha2", + "version": "2.1.0-alpha3" + }, + "expected_output": true + }, + { + "description": "semver range \"\u003e= 2.1.0-alpha2\" contains \"2.1.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=2.1.0-alpha2", + "version": "2.1.0" + }, + "expected_output": true + }, + { + "description": "semver range \"\u003e= 2.1.0-alpha2\" contains \"3.0.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=2.1.0-alpha2", + "version": "3.0.0" + }, + "expected_output": true + }, + { + "description": "semver range \"\u003e= 2.1.0-alpha2\" excludes \"2.0.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=2.1.0-alpha2", + "version": "2.0.0" + }, + "expected_output": false + }, + { + "description": "semver range \"\u003e= 2.1.0-alpha2\" excludes \"2.1.0-alpha1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=2.1.0-alpha2", + "version": "2.1.0-alpha1" + }, + "expected_output": false + }, + { + "description": "semver range \"\u003e= 2.1.0-alpha2\" excludes \"2.0.0-alpha2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=2.1.0-alpha2", + "version": "2.0.0-alpha2" + }, + "expected_output": false + }, + { + "description": "semver range \"\u003e= 2.1.0-alpha2\" excludes \"3.0.0-alpha2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=2.1.0-alpha2", + "version": "3.0.0-alpha2" + }, + "expected_output": false + }, + { + "description": "semver range \"\u003c 1.0.0\" contains \"0.1.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003c1.0.0", + "version": "0.1.0" + }, + "expected_output": true + }, + { + "description": "semver range \"\u003c 1.0.0\" contains \"0.0.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003c1.0.0", + "version": "0.0.1" + }, + "expected_output": true + }, + { + "description": "semver range \"\u003c 1.0.0\" excludes \"1.0.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003c1.0.0", + "version": "1.0.0" + }, + "expected_output": false + }, + { + "description": "semver range \"\u003c 1.0.0\" excludes \"1.0.0-beta\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003c1.0.0", + "version": "1.0.0-beta" + }, + "expected_output": false + }, + { + "description": "semver range \"\u003c 1.0.0\" excludes \"1.0.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003c1.0.0", + "version": "1.0.1" + }, + "expected_output": false + }, + { + "description": "semver range \"\u003c 1.0.0\" excludes \"0.9.9-alpha\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003c1.0.0", + "version": "0.9.9-alpha" + }, + "expected_output": false + }, + { + "description": "semver range \"\u003c= 2.1.0-alpha2\" contains \"2.1.0-alpha2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003c=2.1.0-alpha2", + "version": "2.1.0-alpha2" + }, + "expected_output": true + }, + { + "description": "semver range \"\u003c= 2.1.0-alpha2\" contains \"2.1.0-alpha1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003c=2.1.0-alpha2", + "version": "2.1.0-alpha1" + }, + "expected_output": true + }, + { + "description": "semver range \"\u003c= 2.1.0-alpha2\" contains \"2.0.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003c=2.1.0-alpha2", + "version": "2.0.0" + }, + "expected_output": true + }, + { + "description": "semver range \"\u003c= 2.1.0-alpha2\" contains \"1.0.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003c=2.1.0-alpha2", + "version": "1.0.0" + }, + "expected_output": true + }, + { + "description": "semver range \"\u003c= 2.1.0-alpha2\" excludes \"2.1.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003c=2.1.0-alpha2", + "version": "2.1.0" + }, + "expected_output": false + }, + { + "description": "semver range \"\u003c= 2.1.0-alpha2\" excludes \"2.2.0-alpha1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003c=2.1.0-alpha2", + "version": "2.2.0-alpha1" + }, + "expected_output": false + }, + { + "description": "semver range \"\u003c= 2.1.0-alpha2\" excludes \"2.0.0-alpha2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003c=2.1.0-alpha2", + "version": "2.0.0-alpha2" + }, + "expected_output": false + }, + { + "description": "semver range \"\u003c= 2.1.0-alpha2\" excludes \"1.0.0-alpha2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003c=2.1.0-alpha2", + "version": "1.0.0-alpha2" + }, + "expected_output": false + }, + { + "description": "semver range \"\u003e1.0.0-alpha, \u003c1.0.0\" contains \"1.0.0-beta\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e1.0.0-alpha|\u003c1.0.0", + "version": "1.0.0-beta" + }, + "expected_output": true + }, + { + "description": "semver range \"\u003e1.0.0-alpha, \u003c1.0\" excludes \"1.0.0-beta\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/!=0.0.0|0.0.0", + "version": "1.0.0-beta" + }, + "expected_output": false + }, + { + "description": "semver range \"\u003e 0.0.9, \u003c= 2.5.3\" contains \"0.0.10\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e0.0.9|\u003c=2.5.3", + "version": "0.0.10" + }, + "expected_output": true + }, + { + "description": "semver range \"\u003e 0.0.9, \u003c= 2.5.3\" contains \"1.0.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e0.0.9|\u003c=2.5.3", + "version": "1.0.0" + }, + "expected_output": true + }, + { + "description": "semver range \"\u003e 0.0.9, \u003c= 2.5.3\" contains \"2.5.3\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e0.0.9|\u003c=2.5.3", + "version": "2.5.3" + }, + "expected_output": true + }, + { + "description": "semver range \"\u003e 0.0.9, \u003c= 2.5.3\" excludes \"0.0.8\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e0.0.9|\u003c=2.5.3", + "version": "0.0.8" + }, + "expected_output": false + }, + { + "description": "semver range \"\u003e 0.0.9, \u003c= 2.5.3\" excludes \"2.5.4\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e0.0.9|\u003c=2.5.3", + "version": "2.5.4" + }, + "expected_output": false + }, + { + "description": "semver range \"0.3.0, 0.4.0\" excludes \"0.0.8\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/!=0.0.0|0.0.0", + "version": "0.0.8" + }, + "expected_output": false + }, + { + "description": "semver range \"0.3.0, 0.4.0\" excludes \"0.3.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/!=0.0.0|0.0.0", + "version": "0.3.0" + }, + "expected_output": false + }, + { + "description": "semver range \"0.3.0, 0.4.0\" excludes \"0.4.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/!=0.0.0|0.0.0", + "version": "0.4.0" + }, + "expected_output": false + }, + { + "description": "semver range \"\u003c= 0.2.0, \u003e= 0.5.0\" excludes \"0.5.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/!=0.0.0|0.0.0", + "version": "0.5.1" + }, + "expected_output": false + }, + { + "description": "semver range \"0.1.0, 0.1.4, 0.1.6\" contains \"0.1.6\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=0.1.6|\u003c0.2.0", + "version": "0.1.6" + }, + "expected_output": true + }, + { + "description": "semver range \"0.1.0, 0.1.4, 0.1.6\" contains \"0.1.9\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=0.1.6|\u003c0.2.0", + "version": "0.1.9" + }, + "expected_output": true + }, + { + "description": "semver range \"0.1.0, 0.1.4, 0.1.6\" excludes \"0.1.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=0.1.6|\u003c0.2.0", + "version": "0.1.0" + }, + "expected_output": false + }, + { + "description": "semver range \"0.1.0, 0.1.4, 0.1.6\" excludes \"0.1.4\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=0.1.6|\u003c0.2.0", + "version": "0.1.4" + }, + "expected_output": false + }, + { + "description": "semver range \"0.1.0, 0.1.4, 0.1.6\" excludes \"0.2.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=0.1.6|\u003c0.2.0", + "version": "0.2.0" + }, + "expected_output": false + }, + { + "description": "semver range \"\u003e=0.5.1-alpha3, \u003c0.6\" contains \"0.5.1-alpha3\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=0.5.1-alpha3|\u003c0.6.0-0", + "version": "0.5.1-alpha3" + }, + "expected_output": true + }, + { + "description": "semver range \"\u003e=0.5.1-alpha3, \u003c0.6\" contains \"0.5.1-alpha4\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=0.5.1-alpha3|\u003c0.6.0-0", + "version": "0.5.1-alpha4" + }, + "expected_output": true + }, + { + "description": "semver range \"\u003e=0.5.1-alpha3, \u003c0.6\" contains \"0.5.1-beta\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=0.5.1-alpha3|\u003c0.6.0-0", + "version": "0.5.1-beta" + }, + "expected_output": true + }, + { + "description": "semver range \"\u003e=0.5.1-alpha3, \u003c0.6\" contains \"0.5.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=0.5.1-alpha3|\u003c0.6.0-0", + "version": "0.5.1" + }, + "expected_output": true + }, + { + "description": "semver range \"\u003e=0.5.1-alpha3, \u003c0.6\" contains \"0.5.5\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=0.5.1-alpha3|\u003c0.6.0-0", + "version": "0.5.5" + }, + "expected_output": true + }, + { + "description": "semver range \"\u003e=0.5.1-alpha3, \u003c0.6\" excludes \"0.5.1-alpha1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=0.5.1-alpha3|\u003c0.6.0-0", + "version": "0.5.1-alpha1" + }, + "expected_output": false + }, + { + "description": "semver range \"\u003e=0.5.1-alpha3, \u003c0.6\" excludes \"0.5.2-alpha3\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=0.5.1-alpha3|\u003c0.6.0-0", + "version": "0.5.2-alpha3" + }, + "expected_output": false + }, + { + "description": "semver range \"\u003e=0.5.1-alpha3, \u003c0.6\" excludes \"0.5.5-pre\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=0.5.1-alpha3|\u003c0.6.0-0", + "version": "0.5.5-pre" + }, + "expected_output": false + }, + { + "description": "semver range \"\u003e=0.5.1-alpha3, \u003c0.6\" excludes \"0.5.0-pre\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=0.5.1-alpha3|\u003c0.6.0-0", + "version": "0.5.0-pre" + }, + "expected_output": false + }, + { + "description": "semver range \"\u003e=0.5.1-alpha3, \u003c0.6\" excludes \"0.6.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=0.5.1-alpha3|\u003c0.6.0-0", + "version": "0.6.0" + }, + "expected_output": false + }, + { + "description": "semver range \"\u003e=0.5.1-alpha3, \u003c0.6\" excludes \"0.6.0-pre\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=0.5.1-alpha3|\u003c0.6.0-0", + "version": "0.6.0-pre" + }, + "expected_output": false + }, + { + "description": "semver range \"~1\" contains \"1.1.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.0.0|\u003c2.0.0", + "version": "1.1.1" + }, + "expected_output": true + }, + { + "description": "semver range \"~1\" excludes \"0.9.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.0.0|\u003c2.0.0", + "version": "0.9.1" + }, + "expected_output": false + }, + { + "description": "semver range \"~1\" excludes \"2.9.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.0.0|\u003c2.0.0", + "version": "2.9.0" + }, + "expected_output": false + }, + { + "description": "semver range \"~1\" excludes \"0.0.9\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.0.0|\u003c2.0.0", + "version": "0.0.9" + }, + "expected_output": false + }, + { + "description": "semver range \"~1.2\" contains \"1.2.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.2.0|\u003c1.3.0", + "version": "1.2.0" + }, + "expected_output": true + }, + { + "description": "semver range \"~1.2\" contains \"1.2.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.2.0|\u003c1.3.0", + "version": "1.2.1" + }, + "expected_output": true + }, + { + "description": "semver range \"~1.2\" excludes \"1.1.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.2.0|\u003c1.3.0", + "version": "1.1.1" + }, + "expected_output": false + }, + { + "description": "semver range \"~1.2\" excludes \"1.3.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.2.0|\u003c1.3.0", + "version": "1.3.0" + }, + "expected_output": false + }, + { + "description": "semver range \"~1.2\" excludes \"0.0.9\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.2.0|\u003c1.3.0", + "version": "0.0.9" + }, + "expected_output": false + }, + { + "description": "semver range \"~1.2.2\" contains \"1.2.2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.2.2|\u003c1.3.0", + "version": "1.2.2" + }, + "expected_output": true + }, + { + "description": "semver range \"~1.2.2\" contains \"1.2.4\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.2.2|\u003c1.3.0", + "version": "1.2.4" + }, + "expected_output": true + }, + { + "description": "semver range \"~1.2.2\" excludes \"1.2.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.2.2|\u003c1.3.0", + "version": "1.2.1" + }, + "expected_output": false + }, + { + "description": "semver range \"~1.2.2\" excludes \"1.9.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.2.2|\u003c1.3.0", + "version": "1.9.0" + }, + "expected_output": false + }, + { + "description": "semver range \"~1.2.2\" excludes \"1.0.9\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.2.2|\u003c1.3.0", + "version": "1.0.9" + }, + "expected_output": false + }, + { + "description": "semver range \"~1.2.2\" excludes \"2.0.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.2.2|\u003c1.3.0", + "version": "2.0.1" + }, + "expected_output": false + }, + { + "description": "semver range \"~1.2.2\" excludes \"0.1.3\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.2.2|\u003c1.3.0", + "version": "0.1.3" + }, + "expected_output": false + }, + { + "description": "semver range \"~1.2.3-beta.2\" contains \"1.2.3\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.2.3-beta.2|\u003c1.3.0", + "version": "1.2.3" + }, + "expected_output": true + }, + { + "description": "semver range \"~1.2.3-beta.2\" contains \"1.2.4\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.2.3-beta.2|\u003c1.3.0", + "version": "1.2.4" + }, + "expected_output": true + }, + { + "description": "semver range \"~1.2.3-beta.2\" contains \"1.2.3-beta.2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.2.3-beta.2|\u003c1.3.0", + "version": "1.2.3-beta.2" + }, + "expected_output": true + }, + { + "description": "semver range \"~1.2.3-beta.2\" contains \"1.2.3-beta.4\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.2.3-beta.2|\u003c1.3.0", + "version": "1.2.3-beta.4" + }, + "expected_output": true + }, + { + "description": "semver range \"~1.2.3-beta.2\" excludes \"1.3.3\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.2.3-beta.2|\u003c1.3.0", + "version": "1.3.3" + }, + "expected_output": false + }, + { + "description": "semver range \"~1.2.3-beta.2\" excludes \"1.1.4\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.2.3-beta.2|\u003c1.3.0", + "version": "1.1.4" + }, + "expected_output": false + }, + { + "description": "semver range \"~1.2.3-beta.2\" excludes \"1.2.3-beta.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.2.3-beta.2|\u003c1.3.0", + "version": "1.2.3-beta.1" + }, + "expected_output": false + }, + { + "description": "semver range \"~1.2.3-beta.2\" excludes \"1.2.4-beta.2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.2.3-beta.2|\u003c1.3.0", + "version": "1.2.4-beta.2" + }, + "expected_output": false + }, + { + "description": "semver range \"^1\" contains \"1.1.2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.0.0|\u003c2.0.0", + "version": "1.1.2" + }, + "expected_output": true + }, + { + "description": "semver range \"^1\" contains \"1.2.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.0.0|\u003c2.0.0", + "version": "1.2.1" + }, + "expected_output": true + }, + { + "description": "semver range \"^1\" excludes \"0.1.4\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.0.0|\u003c2.0.0", + "version": "0.1.4" + }, + "expected_output": false + }, + { + "description": "semver range \"^1\" excludes \"1.0.0-beta1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.0.0|\u003c2.0.0", + "version": "1.0.0-beta1" + }, + "expected_output": false + }, + { + "description": "semver range \"^1\" excludes \"0.1.0-alpha\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.0.0|\u003c2.0.0", + "version": "0.1.0-alpha" + }, + "expected_output": false + }, + { + "description": "semver range \"^1.1\" contains \"1.1.2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.1.0|\u003c2.0.0", + "version": "1.1.2" + }, + "expected_output": true + }, + { + "description": "semver range \"^1.1\" contains \"1.1.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.1.0|\u003c2.0.0", + "version": "1.1.0" + }, + "expected_output": true + }, + { + "description": "semver range \"^1.1\" contains \"1.2.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.1.0|\u003c2.0.0", + "version": "1.2.1" + }, + "expected_output": true + }, + { + "description": "semver range \"^1.1\" excludes \"0.9.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.1.0|\u003c2.0.0", + "version": "0.9.1" + }, + "expected_output": false + }, + { + "description": "semver range \"^1.1\" excludes \"2.9.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.1.0|\u003c2.0.0", + "version": "2.9.0" + }, + "expected_output": false + }, + { + "description": "semver range \"^1.1\" excludes \"1.0.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.1.0|\u003c2.0.0", + "version": "1.0.1" + }, + "expected_output": false + }, + { + "description": "semver range \"^1.1\" excludes \"0.1.4\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.1.0|\u003c2.0.0", + "version": "0.1.4" + }, + "expected_output": false + }, + { + "description": "semver range \"^1.1.2\" contains \"1.1.2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.1.2|\u003c2.0.0", + "version": "1.1.2" + }, + "expected_output": true + }, + { + "description": "semver range \"^1.1.2\" contains \"1.1.4\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.1.2|\u003c2.0.0", + "version": "1.1.4" + }, + "expected_output": true + }, + { + "description": "semver range \"^1.1.2\" contains \"1.2.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.1.2|\u003c2.0.0", + "version": "1.2.1" + }, + "expected_output": true + }, + { + "description": "semver range \"^1.1.2\" excludes \"0.9.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.1.2|\u003c2.0.0", + "version": "0.9.1" + }, + "expected_output": false + }, + { + "description": "semver range \"^1.1.2\" excludes \"2.9.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.1.2|\u003c2.0.0", + "version": "2.9.0" + }, + "expected_output": false + }, + { + "description": "semver range \"^1.1.2\" excludes \"1.1.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.1.2|\u003c2.0.0", + "version": "1.1.1" + }, + "expected_output": false + }, + { + "description": "semver range \"^1.1.2\" excludes \"0.0.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.1.2|\u003c2.0.0", + "version": "0.0.1" + }, + "expected_output": false + }, + { + "description": "semver range \"^1.1.2\" excludes \"1.1.2-alpha1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.1.2|\u003c2.0.0", + "version": "1.1.2-alpha1" + }, + "expected_output": false + }, + { + "description": "semver range \"^1.1.2\" excludes \"1.1.3-alpha1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.1.2|\u003c2.0.0", + "version": "1.1.3-alpha1" + }, + "expected_output": false + }, + { + "description": "semver range \"^1.1.2\" excludes \"2.9.0-alpha1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.1.2|\u003c2.0.0", + "version": "2.9.0-alpha1" + }, + "expected_output": false + }, + { + "description": "semver range \"^0.1.2\" contains \"0.1.2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=0.1.2|\u003c0.2.0", + "version": "0.1.2" + }, + "expected_output": true + }, + { + "description": "semver range \"^0.1.2\" contains \"0.1.4\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=0.1.2|\u003c0.2.0", + "version": "0.1.4" + }, + "expected_output": true + }, + { + "description": "semver range \"^0.1.2\" excludes \"0.9.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=0.1.2|\u003c0.2.0", + "version": "0.9.1" + }, + "expected_output": false + }, + { + "description": "semver range \"^0.1.2\" excludes \"2.9.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=0.1.2|\u003c0.2.0", + "version": "2.9.0" + }, + "expected_output": false + }, + { + "description": "semver range \"^0.1.2\" excludes \"1.1.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=0.1.2|\u003c0.2.0", + "version": "1.1.1" + }, + "expected_output": false + }, + { + "description": "semver range \"^0.1.2\" excludes \"0.0.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=0.1.2|\u003c0.2.0", + "version": "0.0.1" + }, + "expected_output": false + }, + { + "description": "semver range \"^0.1.2\" excludes \"0.1.2-beta\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=0.1.2|\u003c0.2.0", + "version": "0.1.2-beta" + }, + "expected_output": false + }, + { + "description": "semver range \"^0.1.2\" excludes \"0.1.3-alpha\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=0.1.2|\u003c0.2.0", + "version": "0.1.3-alpha" + }, + "expected_output": false + }, + { + "description": "semver range \"^0.1.2\" excludes \"0.2.0-pre\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=0.1.2|\u003c0.2.0", + "version": "0.2.0-pre" + }, + "expected_output": false + }, + { + "description": "semver range \"^0.5.1-alpha3\" contains \"0.5.1-alpha3\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=0.5.1-alpha3|\u003c0.6.0", + "version": "0.5.1-alpha3" + }, + "expected_output": true + }, + { + "description": "semver range \"^0.5.1-alpha3\" contains \"0.5.1-alpha4\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=0.5.1-alpha3|\u003c0.6.0", + "version": "0.5.1-alpha4" + }, + "expected_output": true + }, + { + "description": "semver range \"^0.5.1-alpha3\" contains \"0.5.1-beta\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=0.5.1-alpha3|\u003c0.6.0", + "version": "0.5.1-beta" + }, + "expected_output": true + }, + { + "description": "semver range \"^0.5.1-alpha3\" contains \"0.5.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=0.5.1-alpha3|\u003c0.6.0", + "version": "0.5.1" + }, + "expected_output": true + }, + { + "description": "semver range \"^0.5.1-alpha3\" contains \"0.5.5\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=0.5.1-alpha3|\u003c0.6.0", + "version": "0.5.5" + }, + "expected_output": true + }, + { + "description": "semver range \"^0.5.1-alpha3\" excludes \"0.5.1-alpha1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=0.5.1-alpha3|\u003c0.6.0", + "version": "0.5.1-alpha1" + }, + "expected_output": false + }, + { + "description": "semver range \"^0.5.1-alpha3\" excludes \"0.5.2-alpha3\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=0.5.1-alpha3|\u003c0.6.0", + "version": "0.5.2-alpha3" + }, + "expected_output": false + }, + { + "description": "semver range \"^0.5.1-alpha3\" excludes \"0.5.5-pre\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=0.5.1-alpha3|\u003c0.6.0", + "version": "0.5.5-pre" + }, + "expected_output": false + }, + { + "description": "semver range \"^0.5.1-alpha3\" excludes \"0.5.0-pre\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=0.5.1-alpha3|\u003c0.6.0", + "version": "0.5.0-pre" + }, + "expected_output": false + }, + { + "description": "semver range \"^0.5.1-alpha3\" excludes \"0.6.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=0.5.1-alpha3|\u003c0.6.0", + "version": "0.6.0" + }, + "expected_output": false + }, + { + "description": "semver range \"^0.0.2\" contains \"0.0.2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=0.0.2|\u003c0.0.3", + "version": "0.0.2" + }, + "expected_output": true + }, + { + "description": "semver range \"^0.0.2\" excludes \"0.9.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=0.0.2|\u003c0.0.3", + "version": "0.9.1" + }, + "expected_output": false + }, + { + "description": "semver range \"^0.0.2\" excludes \"2.9.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=0.0.2|\u003c0.0.3", + "version": "2.9.0" + }, + "expected_output": false + }, + { + "description": "semver range \"^0.0.2\" excludes \"1.1.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=0.0.2|\u003c0.0.3", + "version": "1.1.1" + }, + "expected_output": false + }, + { + "description": "semver range \"^0.0.2\" excludes \"0.0.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=0.0.2|\u003c0.0.3", + "version": "0.0.1" + }, + "expected_output": false + }, + { + "description": "semver range \"^0.0.2\" excludes \"0.1.4\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=0.0.2|\u003c0.0.3", + "version": "0.1.4" + }, + "expected_output": false + }, + { + "description": "semver range \"^0.0\" contains \"0.0.2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=0.0.0|\u003c0.1.0", + "version": "0.0.2" + }, + "expected_output": true + }, + { + "description": "semver range \"^0.0\" contains \"0.0.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=0.0.0|\u003c0.1.0", + "version": "0.0.0" + }, + "expected_output": true + }, + { + "description": "semver range \"^0.0\" excludes \"0.9.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=0.0.0|\u003c0.1.0", + "version": "0.9.1" + }, + "expected_output": false + }, + { + "description": "semver range \"^0.0\" excludes \"2.9.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=0.0.0|\u003c0.1.0", + "version": "2.9.0" + }, + "expected_output": false + }, + { + "description": "semver range \"^0.0\" excludes \"1.1.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=0.0.0|\u003c0.1.0", + "version": "1.1.1" + }, + "expected_output": false + }, + { + "description": "semver range \"^0.0\" excludes \"0.1.4\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=0.0.0|\u003c0.1.0", + "version": "0.1.4" + }, + "expected_output": false + }, + { + "description": "semver range \"^0\" contains \"0.9.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=0.0.0|\u003c1.0.0", + "version": "0.9.1" + }, + "expected_output": true + }, + { + "description": "semver range \"^0\" contains \"0.0.2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=0.0.0|\u003c1.0.0", + "version": "0.0.2" + }, + "expected_output": true + }, + { + "description": "semver range \"^0\" contains \"0.0.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=0.0.0|\u003c1.0.0", + "version": "0.0.0" + }, + "expected_output": true + }, + { + "description": "semver range \"^0\" excludes \"2.9.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=0.0.0|\u003c1.0.0", + "version": "2.9.0" + }, + "expected_output": false + }, + { + "description": "semver range \"^0\" excludes \"1.1.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=0.0.0|\u003c1.0.0", + "version": "1.1.1" + }, + "expected_output": false + }, + { + "description": "semver range \"^1.4.2-beta.5\" contains \"1.4.2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.4.2-beta.5|\u003c2.0.0", + "version": "1.4.2" + }, + "expected_output": true + }, + { + "description": "semver range \"^1.4.2-beta.5\" contains \"1.4.3\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.4.2-beta.5|\u003c2.0.0", + "version": "1.4.3" + }, + "expected_output": true + }, + { + "description": "semver range \"^1.4.2-beta.5\" contains \"1.4.2-beta.5\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.4.2-beta.5|\u003c2.0.0", + "version": "1.4.2-beta.5" + }, + "expected_output": true + }, + { + "description": "semver range \"^1.4.2-beta.5\" contains \"1.4.2-beta.6\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.4.2-beta.5|\u003c2.0.0", + "version": "1.4.2-beta.6" + }, + "expected_output": true + }, + { + "description": "semver range \"^1.4.2-beta.5\" contains \"1.4.2-c\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.4.2-beta.5|\u003c2.0.0", + "version": "1.4.2-c" + }, + "expected_output": true + }, + { + "description": "semver range \"^1.4.2-beta.5\" excludes \"0.9.9\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.4.2-beta.5|\u003c2.0.0", + "version": "0.9.9" + }, + "expected_output": false + }, + { + "description": "semver range \"^1.4.2-beta.5\" excludes \"2.0.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.4.2-beta.5|\u003c2.0.0", + "version": "2.0.0" + }, + "expected_output": false + }, + { + "description": "semver range \"^1.4.2-beta.5\" excludes \"1.4.2-alpha\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.4.2-beta.5|\u003c2.0.0", + "version": "1.4.2-alpha" + }, + "expected_output": false + }, + { + "description": "semver range \"^1.4.2-beta.5\" excludes \"1.4.2-beta.4\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.4.2-beta.5|\u003c2.0.0", + "version": "1.4.2-beta.4" + }, + "expected_output": false + }, + { + "description": "semver range \"^1.4.2-beta.5\" excludes \"1.4.3-beta.5\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.4.2-beta.5|\u003c2.0.0", + "version": "1.4.3-beta.5" + }, + "expected_output": false + }, + { + "description": "semver range \"*\" contains \"0.9.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/*", + "version": "0.9.1" + }, + "expected_output": true + }, + { + "description": "semver range \"*\" contains \"2.9.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/*", + "version": "2.9.0" + }, + "expected_output": true + }, + { + "description": "semver range \"*\" contains \"0.0.9\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/*", + "version": "0.0.9" + }, + "expected_output": true + }, + { + "description": "semver range \"*\" contains \"1.0.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/*", + "version": "1.0.1" + }, + "expected_output": true + }, + { + "description": "semver range \"*\" contains \"1.1.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/*", + "version": "1.1.1" + }, + "expected_output": true + }, + { + "description": "semver range \"*\" excludes \"1.0.0-pre\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/*", + "version": "1.0.0-pre" + }, + "expected_output": false + }, + { + "description": "semver range \"1.*\" contains \"1.2.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.0.0|\u003c2.0.0", + "version": "1.2.0" + }, + "expected_output": true + }, + { + "description": "semver range \"1.*\" contains \"1.3.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.0.0|\u003c2.0.0", + "version": "1.3.0" + }, + "expected_output": true + }, + { + "description": "semver range \"1.*\" excludes \"1.2.0-pre\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.0.0|\u003c2.0.0", + "version": "1.2.0-pre" + }, + "expected_output": false + }, + { + "description": "semver range \"1.2.*\" contains \"1.2.2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.2.0|\u003c1.3.0", + "version": "1.2.2" + }, + "expected_output": true + }, + { + "description": "semver range \"1.2.*\" contains \"1.2.4\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.2.0|\u003c1.3.0", + "version": "1.2.4" + }, + "expected_output": true + }, + { + "description": "semver range \"1.2.*\" excludes \"1.9.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.2.0|\u003c1.3.0", + "version": "1.9.0" + }, + "expected_output": false + }, + { + "description": "semver range \"1.2.*\" excludes \"1.0.9\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.2.0|\u003c1.3.0", + "version": "1.0.9" + }, + "expected_output": false + }, + { + "description": "semver range \"1.2.*\" excludes \"2.0.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.2.0|\u003c1.3.0", + "version": "2.0.1" + }, + "expected_output": false + }, + { + "description": "semver range \"1.2.*\" excludes \"0.1.3\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.2.0|\u003c1.3.0", + "version": "0.1.3" + }, + "expected_output": false + }, + { + "description": "semver range \"1.2.*\" excludes \"1.2.2-pre\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=1.2.0|\u003c1.3.0", + "version": "1.2.2-pre" + }, + "expected_output": false + }, + { + "description": "semver range \"=2.1.1-really.0\" contains \"2.1.1-really.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/2.1.1-really.0", + "version": "2.1.1-really.0" + }, + "expected_output": true + }, + { + "description": "semver range \"0.*.*\" contains \"0.5.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:cargo/\u003e=0.0.0|\u003c1.0.0", + "version": "0.5.0" + }, + "expected_output": true + } + ] +} diff --git a/testdata/local/tests/composer_range_reference_test.json b/testdata/local/tests/composer_range_reference_test.json new file mode 100644 index 0000000..6a736c1 --- /dev/null +++ b/testdata/local/tests/composer_range_reference_test.json @@ -0,0 +1,1205 @@ +{ + "$schema": "https://packageurl.org/schemas/vers-test.schema-0.2.json", + "tests": [ + { + "description": "composer/semver range \"v*\" contains \"0.0.0.0-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/*", + "version": "0.0.0.0-dev" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"\u003c\u003e1.0.0\" excludes \"1.0.0.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/!=1.0.0", + "version": "1.0.0.0" + }, + "expected_output": false + }, + { + "description": "composer/semver range \"\u003e1.0.0\" excludes \"1.0.0.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e1.0.0", + "version": "1.0.0.0" + }, + "expected_output": false + }, + { + "description": "composer/semver range \"\u003c1.2.3.4\" excludes \"1.2.3.4-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003c1.2.3.4-dev", + "version": "1.2.3.4-dev" + }, + "expected_output": false + }, + { + "description": "composer/semver range \"\u003c=1.2.3\" contains \"1.2.3.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003c=1.2.3", + "version": "1.2.3.0" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"\u003e=1.2.3\" contains \"1.2.3.0-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=1.2.3-dev", + "version": "1.2.3.0-dev" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"=1.2.3\" contains \"1.2.3.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/1.2.3", + "version": "1.2.3.0" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"=1.0\" contains \"1.0.0.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/1.0.0", + "version": "1.0.0.0" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"1.2.3b5\" contains \"1.2.3.0-beta5\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/1.2.3-beta5", + "version": "1.2.3.0-beta5" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"1.2.3a1\" contains \"1.2.3.0-alpha1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/1.2.3-alpha1", + "version": "1.2.3.0-alpha1" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"1.2.3p1234\" contains \"1.2.3.0-patch1234\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/1.2.3-patch1234", + "version": "1.2.3.0-patch1234" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"\u003c 1.2.3\" excludes \"1.2.3.0-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003c1.2.3-dev", + "version": "1.2.3.0-dev" + }, + "expected_output": false + }, + { + "description": "composer/semver range \"\u003e 1.2.3\" excludes \"1.2.3.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e1.2.3", + "version": "1.2.3.0" + }, + "expected_output": false + }, + { + "description": "composer/semver range \"\u003e=dev-master\" contains \"dev-master\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=dev-master", + "version": "dev-master" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"dev-master\" contains \"dev-master\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/dev-master", + "version": "dev-master" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"dev-feature-a\" contains \"dev-feature-a\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/dev-feature-a", + "version": "dev-feature-a" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"dev-some-fix\" contains \"dev-some-fix\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/dev-some-fix", + "version": "dev-some-fix" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"dev-CAPS\" contains \"dev-CAPS\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/dev-CAPS", + "version": "dev-CAPS" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"\u003c1.2.3.4-stable\" excludes \"1.2.3.4\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003c1.2.3.4", + "version": "1.2.3.4" + }, + "expected_output": false + }, + { + "description": "composer/semver range \"\u003e=1.2.3.4-stable\" contains \"1.2.3.4\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=1.2.3.4", + "version": "1.2.3.4" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"v2.*\" contains \"2.0.0.0-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=2.0.0-dev|\u003c3.0.0-dev", + "version": "2.0.0.0-dev" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"v2.*\" excludes \"3.0.0.0-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=2.0.0-dev|\u003c3.0.0-dev", + "version": "3.0.0.0-dev" + }, + "expected_output": false + }, + { + "description": "composer/semver range \"20.*\" contains \"20.0.0.0-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=20.0.0-dev|\u003c21.0.0-dev", + "version": "20.0.0.0-dev" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"20.*\" excludes \"21.0.0.0-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=20.0.0-dev|\u003c21.0.0-dev", + "version": "21.0.0.0-dev" + }, + "expected_output": false + }, + { + "description": "composer/semver range \"2.0.*\" contains \"2.0.0.0-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=2.0.0-dev|\u003c2.1.0-dev", + "version": "2.0.0.0-dev" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"2.0.*\" excludes \"2.1.0.0-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=2.0.0-dev|\u003c2.1.0-dev", + "version": "2.1.0.0-dev" + }, + "expected_output": false + }, + { + "description": "composer/semver range \"2.2.x\" contains \"2.2.0.0-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=2.2.0-dev|\u003c2.3.0-dev", + "version": "2.2.0.0-dev" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"2.2.x\" excludes \"2.3.0.0-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=2.2.0-dev|\u003c2.3.0-dev", + "version": "2.3.0.0-dev" + }, + "expected_output": false + }, + { + "description": "composer/semver range \"2.10.X\" contains \"2.10.0.0-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=2.10.0-dev|\u003c2.11.0-dev", + "version": "2.10.0.0-dev" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"2.10.X\" excludes \"2.11.0.0-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=2.10.0-dev|\u003c2.11.0-dev", + "version": "2.11.0.0-dev" + }, + "expected_output": false + }, + { + "description": "composer/semver range \"2.1.3.*\" contains \"2.1.3.0-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=2.1.3-dev|\u003c2.1.4-dev", + "version": "2.1.3.0-dev" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"2.1.3.*\" excludes \"2.1.4.0-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=2.1.3-dev|\u003c2.1.4-dev", + "version": "2.1.4.0-dev" + }, + "expected_output": false + }, + { + "description": "composer/semver range \"0.*\" excludes \"1.0.0.0-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=0.0.0-dev|\u003c1.0.0-dev", + "version": "1.0.0.0-dev" + }, + "expected_output": false + }, + { + "description": "composer/semver range \"~v1\" contains \"1.0.0.0-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=1.0.0-dev|\u003c2.0.0-dev", + "version": "1.0.0.0-dev" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"~v1\" excludes \"2.0.0.0-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=1.0.0-dev|\u003c2.0.0-dev", + "version": "2.0.0.0-dev" + }, + "expected_output": false + }, + { + "description": "composer/semver range \"~1.0.0\" contains \"1.0.0.0-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=1.0.0-dev|\u003c1.1.0-dev", + "version": "1.0.0.0-dev" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"~1.0.0\" excludes \"1.1.0.0-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=1.0.0-dev|\u003c1.1.0-dev", + "version": "1.1.0.0-dev" + }, + "expected_output": false + }, + { + "description": "composer/semver range \"~1.2\" contains \"1.2.0.0-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=1.2.0-dev|\u003c2.0.0-dev", + "version": "1.2.0.0-dev" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"~1.2\" excludes \"2.0.0.0-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=1.2.0-dev|\u003c2.0.0-dev", + "version": "2.0.0.0-dev" + }, + "expected_output": false + }, + { + "description": "composer/semver range \"~1.2.3\" contains \"1.2.3.0-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=1.2.3-dev|\u003c1.3.0-dev", + "version": "1.2.3.0-dev" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"~1.2.3\" excludes \"1.3.0.0-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=1.2.3-dev|\u003c1.3.0-dev", + "version": "1.3.0.0-dev" + }, + "expected_output": false + }, + { + "description": "composer/semver range \"~1.2.3.4\" contains \"1.2.3.4-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=1.2.3.4-dev|\u003c1.2.4.0-dev", + "version": "1.2.3.4-dev" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"~1.2.3.4\" excludes \"1.2.4.0-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=1.2.3.4-dev|\u003c1.2.4.0-dev", + "version": "1.2.4.0-dev" + }, + "expected_output": false + }, + { + "description": "composer/semver range \"~1.2-beta\" contains \"1.2.0.0-beta\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=1.2.0-beta|\u003c2.0.0-dev", + "version": "1.2.0.0-beta" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"~1.2-beta\" excludes \"2.0.0.0-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=1.2.0-beta|\u003c2.0.0-dev", + "version": "2.0.0.0-dev" + }, + "expected_output": false + }, + { + "description": "composer/semver range \"~1.2-b2\" contains \"1.2.0.0-beta2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=1.2.0-beta2|\u003c2.0.0-dev", + "version": "1.2.0.0-beta2" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"~1.2-b2\" excludes \"2.0.0.0-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=1.2.0-beta2|\u003c2.0.0-dev", + "version": "2.0.0.0-dev" + }, + "expected_output": false + }, + { + "description": "composer/semver range \"~1.2.2-dev\" contains \"1.2.2.0-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=1.2.2-dev|\u003c1.3.0-dev", + "version": "1.2.2.0-dev" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"~1.2.2-dev\" excludes \"1.3.0.0-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=1.2.2-dev|\u003c1.3.0-dev", + "version": "1.3.0.0-dev" + }, + "expected_output": false + }, + { + "description": "composer/semver range \"~1.2.2-stable\" contains \"1.2.2.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=1.2.2|\u003c1.3.0-dev", + "version": "1.2.2.0" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"~1.2.2-stable\" excludes \"1.3.0.0-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=1.2.2|\u003c1.3.0-dev", + "version": "1.3.0.0-dev" + }, + "expected_output": false + }, + { + "description": "composer/semver range \"~201903.0\" contains \"201903.0-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=201903.0.0-dev|\u003c201904.0.0-dev", + "version": "201903.0-dev" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"~201903.0\" excludes \"201904.0.0.0-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=201903.0.0-dev|\u003c201904.0.0-dev", + "version": "201904.0.0.0-dev" + }, + "expected_output": false + }, + { + "description": "composer/semver range \"~201903.0-beta\" contains \"201903.0-beta\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=201903.0.0-beta|\u003c201904.0.0-dev", + "version": "201903.0-beta" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"~201903.0-beta\" excludes \"201904.0.0.0-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=201903.0.0-beta|\u003c201904.0.0-dev", + "version": "201904.0.0.0-dev" + }, + "expected_output": false + }, + { + "description": "composer/semver range \"~201903.0-stable\" contains \"201903.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=201903.0.0|\u003c201904.0.0-dev", + "version": "201903.0" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"~201903.0-stable\" excludes \"201904.0.0.0-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=201903.0.0|\u003c201904.0.0-dev", + "version": "201904.0.0.0-dev" + }, + "expected_output": false + }, + { + "description": "composer/semver range \"~201903.205830.1-stable\" contains \"201903.205830.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=201903.205830.1|\u003c201903.205831.0-dev", + "version": "201903.205830.1" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"~201903.205830.1-stable\" excludes \"201903.205831.0.0-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=201903.205830.1|\u003c201903.205831.0-dev", + "version": "201903.205831.0.0-dev" + }, + "expected_output": false + }, + { + "description": "composer/semver range \"~2.x-dev\" contains \"2.9999999.9999999.9999999-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=2.9999999.9999999.9999999-dev|\u003c3.0.0-dev", + "version": "2.9999999.9999999.9999999-dev" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"~2.x-dev\" excludes \"3.0.0.0-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=2.9999999.9999999.9999999-dev|\u003c3.0.0-dev", + "version": "3.0.0.0-dev" + }, + "expected_output": false + }, + { + "description": "composer/semver range \"~2.0.x-dev\" contains \"2.0.9999999.9999999-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=2.0.9999999.9999999-dev|\u003c2.1.0-dev", + "version": "2.0.9999999.9999999-dev" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"~2.0.x-dev\" excludes \"2.1.0.0-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=2.0.9999999.9999999-dev|\u003c2.1.0-dev", + "version": "2.1.0.0-dev" + }, + "expected_output": false + }, + { + "description": "composer/semver range \"~2.0.3.x-dev\" contains \"2.0.3.9999999-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=2.0.3.9999999-dev|\u003c2.0.4-dev", + "version": "2.0.3.9999999-dev" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"~2.0.3.x-dev\" excludes \"2.0.4.0-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=2.0.3.9999999-dev|\u003c2.0.4-dev", + "version": "2.0.4.0-dev" + }, + "expected_output": false + }, + { + "description": "composer/semver range \"~0.x-dev\" contains \"0.9999999.9999999.9999999-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=0.9999999.9999999.9999999-dev|\u003c1.0.0-dev", + "version": "0.9999999.9999999.9999999-dev" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"~0.x-dev\" excludes \"1.0.0.0-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=0.9999999.9999999.9999999-dev|\u003c1.0.0-dev", + "version": "1.0.0.0-dev" + }, + "expected_output": false + }, + { + "description": "composer/semver range \"^0\" contains \"0.0.0.0-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=0.0.0-dev|\u003c1.0.0-dev", + "version": "0.0.0.0-dev" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"^0.0\" contains \"0.0.0.0-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=0.0.0-dev|\u003c0.1.0-dev", + "version": "0.0.0.0-dev" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"^0.0\" excludes \"0.1.0.0-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=0.0.0-dev|\u003c0.1.0-dev", + "version": "0.1.0.0-dev" + }, + "expected_output": false + }, + { + "description": "composer/semver range \"^1.2.3-beta.2\" contains \"1.2.3.0-beta2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=1.2.3-beta2|\u003c2.0.0-dev", + "version": "1.2.3.0-beta2" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"^1.2.3-beta.2\" excludes \"2.0.0.0-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=1.2.3-beta2|\u003c2.0.0-dev", + "version": "2.0.0.0-dev" + }, + "expected_output": false + }, + { + "description": "composer/semver range \"^1.2.3.4\" contains \"1.2.3.4-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=1.2.3.4-dev|\u003c2.0.0.0-dev", + "version": "1.2.3.4-dev" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"^1.2.3.4\" excludes \"2.0.0.0-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=1.2.3.4-dev|\u003c2.0.0.0-dev", + "version": "2.0.0.0-dev" + }, + "expected_output": false + }, + { + "description": "composer/semver range \"^1.2.3\" contains \"1.2.3.0-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=1.2.3-dev|\u003c2.0.0-dev", + "version": "1.2.3.0-dev" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"^1.2.3\" excludes \"2.0.0.0-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=1.2.3-dev|\u003c2.0.0-dev", + "version": "2.0.0.0-dev" + }, + "expected_output": false + }, + { + "description": "composer/semver range \"^0.2.3\" contains \"0.2.3.0-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=0.2.3-dev|\u003c0.3.0-dev", + "version": "0.2.3.0-dev" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"^0.2.3\" excludes \"0.3.0.0-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=0.2.3-dev|\u003c0.3.0-dev", + "version": "0.3.0.0-dev" + }, + "expected_output": false + }, + { + "description": "composer/semver range \"^0.2\" contains \"0.2.0.0-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=0.2.0-dev|\u003c0.3.0-dev", + "version": "0.2.0.0-dev" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"^0.2\" excludes \"0.3.0.0-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=0.2.0-dev|\u003c0.3.0-dev", + "version": "0.3.0.0-dev" + }, + "expected_output": false + }, + { + "description": "composer/semver range \"^0.0.3\" contains \"0.0.3.0-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=0.0.3-dev|\u003c0.0.4-dev", + "version": "0.0.3.0-dev" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"^0.0.3\" excludes \"0.0.4.0-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=0.0.3-dev|\u003c0.0.4-dev", + "version": "0.0.4.0-dev" + }, + "expected_output": false + }, + { + "description": "composer/semver range \"^0.0.3-alpha\" contains \"0.0.3.0-alpha\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=0.0.3-alpha|\u003c0.0.4-dev", + "version": "0.0.3.0-alpha" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"^0.0.3-alpha\" excludes \"0.0.4.0-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=0.0.3-alpha|\u003c0.0.4-dev", + "version": "0.0.4.0-dev" + }, + "expected_output": false + }, + { + "description": "composer/semver range \"^0.0.3-stable\" contains \"0.0.3.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=0.0.3|\u003c0.0.4-dev", + "version": "0.0.3.0" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"^0.0.3-stable\" excludes \"0.0.4.0-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=0.0.3|\u003c0.0.4-dev", + "version": "0.0.4.0-dev" + }, + "expected_output": false + }, + { + "description": "composer/semver range \"^201903.205830.1-stable\" contains \"201903.205830.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=201903.205830.1|\u003c201904.0.0-dev", + "version": "201903.205830.1" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"^201903.205830.1-stable\" excludes \"201904.0.0.0-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=201903.205830.1|\u003c201904.0.0-dev", + "version": "201904.0.0.0-dev" + }, + "expected_output": false + }, + { + "description": "composer/semver range \"^2.0.*-dev\" contains \"2.0.9999999.9999999-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=2.0.9999999.9999999-dev|\u003c3.0.0-dev", + "version": "2.0.9999999.9999999-dev" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"^2.0.*-dev\" excludes \"3.0.0.0-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=2.0.9999999.9999999-dev|\u003c3.0.0-dev", + "version": "3.0.0.0-dev" + }, + "expected_output": false + }, + { + "description": "composer/semver range \"^2.0.3.x-dev\" contains \"2.0.3.9999999-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=2.0.3.9999999-dev|\u003c3.0.0-dev", + "version": "2.0.3.9999999-dev" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"^2.0.3.x-dev\" excludes \"3.0.0.0-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=2.0.3.9999999-dev|\u003c3.0.0-dev", + "version": "3.0.0.0-dev" + }, + "expected_output": false + }, + { + "description": "composer/semver range \"v1 - v2\" contains \"1.0.0.0-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=1.0.0-dev|\u003c3.0.0-dev", + "version": "1.0.0.0-dev" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"v1 - v2\" excludes \"3.0.0.0-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=1.0.0-dev|\u003c3.0.0-dev", + "version": "3.0.0.0-dev" + }, + "expected_output": false + }, + { + "description": "composer/semver range \"1.2.3 - 2.3.4.5\" contains \"1.2.3.0-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=1.2.3-dev|\u003c=2.3.4.5", + "version": "1.2.3.0-dev" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"1.2.3 - 2.3.4.5\" contains \"2.3.4.5\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=1.2.3-dev|\u003c=2.3.4.5", + "version": "2.3.4.5" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"1.2-beta - 2.3\" contains \"1.2.0.0-beta\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=1.2.0-beta|\u003c2.4.0-dev", + "version": "1.2.0.0-beta" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"1.2-beta - 2.3\" excludes \"2.4.0.0-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=1.2.0-beta|\u003c2.4.0-dev", + "version": "2.4.0.0-dev" + }, + "expected_output": false + }, + { + "description": "composer/semver range \"1.2-beta - 2.3-dev\" contains \"1.2.0.0-beta\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=1.2.0-beta|\u003c=2.3.0-dev", + "version": "1.2.0.0-beta" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"1.2-beta - 2.3-dev\" contains \"2.3.0.0-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=1.2.0-beta|\u003c=2.3.0-dev", + "version": "2.3.0.0-dev" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"1.2-RC - 2.3.1\" contains \"1.2.0.0-RC\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=1.2.0-RC|\u003c=2.3.1", + "version": "1.2.0.0-RC" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"1.2-RC - 2.3.1\" contains \"2.3.1.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=1.2.0-RC|\u003c=2.3.1", + "version": "2.3.1.0" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"1.2.3-alpha - 2.3-RC\" contains \"1.2.3.0-alpha\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=1.2.3-alpha|\u003c=2.3.0-RC", + "version": "1.2.3.0-alpha" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"1.2.3-alpha - 2.3-RC\" contains \"2.3.0.0-RC\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=1.2.3-alpha|\u003c=2.3.0-RC", + "version": "2.3.0.0-RC" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"1 - 2.0\" contains \"1.0.0.0-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=1.0.0-dev|\u003c2.1.0-dev", + "version": "1.0.0.0-dev" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"1 - 2.0\" excludes \"2.1.0.0-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=1.0.0-dev|\u003c2.1.0-dev", + "version": "2.1.0.0-dev" + }, + "expected_output": false + }, + { + "description": "composer/semver range \"1 - 2.1\" contains \"1.0.0.0-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=1.0.0-dev|\u003c2.2.0-dev", + "version": "1.0.0.0-dev" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"1 - 2.1\" excludes \"2.2.0.0-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=1.0.0-dev|\u003c2.2.0-dev", + "version": "2.2.0.0-dev" + }, + "expected_output": false + }, + { + "description": "composer/semver range \"1.2 - 2.1.0\" contains \"1.2.0.0-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=1.2.0-dev|\u003c=2.1.0", + "version": "1.2.0.0-dev" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"1.2 - 2.1.0\" contains \"2.1.0.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=1.2.0-dev|\u003c=2.1.0", + "version": "2.1.0.0" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"1.3 - 2.1.3\" contains \"1.3.0.0-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=1.3.0-dev|\u003c=2.1.3", + "version": "1.3.0.0-dev" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"1.3 - 2.1.3\" contains \"2.1.3.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=1.3.0-dev|\u003c=2.1.3", + "version": "2.1.3.0" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"2.0.3.x-dev - 3.0.3.x-dev\" contains \"2.0.3.9999999-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=2.0.3.9999999-dev|\u003c=3.0.3.9999999-dev", + "version": "2.0.3.9999999-dev" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"2.0.3.x-dev - 3.0.3.x-dev\" contains \"3.0.3.9999999-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=2.0.3.9999999-dev|\u003c=3.0.3.9999999-dev", + "version": "3.0.3.9999999-dev" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"2.0.x-dev - 3.0.x-dev\" contains \"2.0.9999999.9999999-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=2.0.9999999.9999999-dev|\u003c=3.0.9999999.9999999-dev", + "version": "2.0.9999999.9999999-dev" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"2.0.x-dev - 3.0.x-dev\" contains \"3.0.9999999.9999999-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=2.0.9999999.9999999-dev|\u003c=3.0.9999999.9999999-dev", + "version": "3.0.9999999.9999999-dev" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"2.x-dev - 3.x-dev\" contains \"2.9999999.9999999.9999999-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=2.9999999.9999999.9999999-dev|\u003c=3.9999999.9999999.9999999-dev", + "version": "2.9999999.9999999.9999999-dev" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"2.x-dev - 3.x-dev\" contains \"3.9999999.9999999.9999999-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=2.9999999.9999999.9999999-dev|\u003c=3.9999999.9999999.9999999-dev", + "version": "3.9999999.9999999.9999999-dev" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"0.x-dev - 1.x-dev\" contains \"0.9999999.9999999.9999999-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=0.9999999.9999999.9999999-dev|\u003c=1.9999999.9999999.9999999-dev", + "version": "0.9999999.9999999.9999999-dev" + }, + "expected_output": true + }, + { + "description": "composer/semver range \"0.x-dev - 1.x-dev\" contains \"1.9999999.9999999.9999999-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:composer/\u003e=0.9999999.9999999.9999999-dev|\u003c=1.9999999.9999999.9999999-dev", + "version": "1.9999999.9999999.9999999-dev" + }, + "expected_output": true + } + ] +} diff --git a/testdata/local/tests/gem_range_reference_test.json b/testdata/local/tests/gem_range_reference_test.json new file mode 100644 index 0000000..afe6fcb --- /dev/null +++ b/testdata/local/tests/gem_range_reference_test.json @@ -0,0 +1,640 @@ +{ + "$schema": "https://packageurl.org/schemas/vers-test.schema-0.2.json", + "tests": [ + { + "description": "RubyGems range \"= 0.2.33\" contains \"0.2.33\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:gem/0.2.33", + "version": "0.2.33" + }, + "expected_output": true + }, + { + "description": "RubyGems range \"\u003e 0.2.33\" contains \"0.2.34\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:gem/\u003e0.2.33", + "version": "0.2.34" + }, + "expected_output": true + }, + { + "description": "RubyGems range \"= 1.0\" contains \"1.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:gem/1.0", + "version": "1.0" + }, + "expected_output": true + }, + { + "description": "RubyGems range \"= 1.0\" contains \"1.0.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:gem/1.0", + "version": "1.0.0" + }, + "expected_output": true + }, + { + "description": "RubyGems range \"= 1.0.0\" contains \"1.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:gem/1.0.0", + "version": "1.0" + }, + "expected_output": true + }, + { + "description": "RubyGems range \"\u003e 1.8.0\" contains \"1.8.2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:gem/\u003e1.8.0", + "version": "1.8.2" + }, + "expected_output": true + }, + { + "description": "RubyGems range \"\u003e 1.111\" contains \"1.112\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:gem/\u003e1.111", + "version": "1.112" + }, + "expected_output": true + }, + { + "description": "RubyGems range \"\u003e 0.0.0\" contains \"0.2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:gem/\u003e0.0.0", + "version": "0.2" + }, + "expected_output": true + }, + { + "description": "RubyGems range \"\u003e 0.0.0\" contains \"0.0.0.0.0.2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:gem/\u003e0.0.0", + "version": "0.0.0.0.0.2" + }, + "expected_output": true + }, + { + "description": "RubyGems range \"\u003e 0.0.0.1\" contains \"0.0.1.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:gem/\u003e0.0.0.1", + "version": "0.0.1.0" + }, + "expected_output": true + }, + { + "description": "RubyGems range \"\u003e 9.3.2\" contains \"10.3.2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:gem/\u003e9.3.2", + "version": "10.3.2" + }, + "expected_output": true + }, + { + "description": "RubyGems range \"= 1.0\" contains \"1.0.0.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:gem/1.0", + "version": "1.0.0.0" + }, + "expected_output": true + }, + { + "description": "RubyGems range \"!= 9.3.4\" contains \"10.3.2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:gem/!=9.3.4", + "version": "10.3.2" + }, + "expected_output": true + }, + { + "description": "RubyGems range \"\u003e= 9.3.2\" contains \" 9.3.2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:gem/\u003e=9.3.2", + "version": " 9.3.2" + }, + "expected_output": true + }, + { + "description": "RubyGems range \"\u003e= 9.3.2\" contains \"9.3.2 \".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:gem/\u003e=9.3.2", + "version": "9.3.2 " + }, + "expected_output": true + }, + { + "description": "RubyGems range \"= 0\" contains \"\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:gem/0" + }, + "expected_output": true + }, + { + "description": "RubyGems range \"\u003c 0.1\" contains \"\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:gem/\u003c0.1" + }, + "expected_output": true + }, + { + "description": "RubyGems range \"\u003c 0.1 \" contains \" \".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:gem/\u003c0.1", + "version": " " + }, + "expected_output": true + }, + { + "description": "RubyGems range \"\u003e 0.a \" contains \" \".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:gem/\u003e0.a", + "version": " " + }, + "expected_output": true + }, + { + "description": "RubyGems range \" \u003e 0.a\" contains \"\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:gem/\u003e0.a" + }, + "expected_output": true + }, + { + "description": "RubyGems range \"\u003c 3.2.rc1\" contains \"3.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:gem/\u003c3.2.rc1", + "version": "3.1" + }, + "expected_output": true + }, + { + "description": "RubyGems range \"\u003e 3.2.0.rc1\" contains \"3.2.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:gem/\u003e3.2.0.rc1", + "version": "3.2.0" + }, + "expected_output": true + }, + { + "description": "RubyGems range \"\u003e 3.2.0.rc1\" contains \"3.2.0.rc2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:gem/\u003e3.2.0.rc1", + "version": "3.2.0.rc2" + }, + "expected_output": true + }, + { + "description": "RubyGems range \"\u003c 3.0\" contains \"3.0.rc2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:gem/\u003c3.0", + "version": "3.0.rc2" + }, + "expected_output": true + }, + { + "description": "RubyGems range \"\u003c 3.0.0\" contains \"3.0.rc2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:gem/\u003c3.0.0", + "version": "3.0.rc2" + }, + "expected_output": true + }, + { + "description": "RubyGems range \"\u003c 3.0.1\" contains \"3.0.rc2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:gem/\u003c3.0.1", + "version": "3.0.rc2" + }, + "expected_output": true + }, + { + "description": "RubyGems range \"\u003e 0\" contains \"3.0.rc2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:gem/\u003e0", + "version": "3.0.rc2" + }, + "expected_output": true + }, + { + "description": "RubyGems range \"~\u003e 5.a\" contains \"5.0.0.rc2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:gem/\u003e=5.a|\u003c6.a", + "version": "5.0.0.rc2" + }, + "expected_output": true + }, + { + "description": "RubyGems range \"~\u003e 5.x\" excludes \"5.0.0.rc2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:gem/\u003e=5.x|\u003c6.a", + "version": "5.0.0.rc2" + }, + "expected_output": false + }, + { + "description": "RubyGems range \"~\u003e 5.a\" contains \"5.0.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:gem/\u003e=5.a|\u003c6.a", + "version": "5.0.0" + }, + "expected_output": true + }, + { + "description": "RubyGems range \"~\u003e 5.x\" contains \"5.0.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:gem/\u003e=5.x|\u003c6.a", + "version": "5.0.0" + }, + "expected_output": true + }, + { + "description": "RubyGems range \"~\u003e 1.4\" excludes \"1.3\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:gem/\u003e=1.4|\u003c2.a", + "version": "1.3" + }, + "expected_output": false + }, + { + "description": "RubyGems range \"~\u003e 1.4\" contains \"1.4\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:gem/\u003e=1.4|\u003c2.a", + "version": "1.4" + }, + "expected_output": true + }, + { + "description": "RubyGems range \"~\u003e 1.4\" contains \"1.5\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:gem/\u003e=1.4|\u003c2.a", + "version": "1.5" + }, + "expected_output": true + }, + { + "description": "RubyGems range \"~\u003e 1.4\" excludes \"2.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:gem/\u003e=1.4|\u003c2.a", + "version": "2.0" + }, + "expected_output": false + }, + { + "description": "RubyGems range \"~\u003e 1.4.4\" excludes \"1.3\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:gem/\u003e=1.4.4|\u003c1.5.a", + "version": "1.3" + }, + "expected_output": false + }, + { + "description": "RubyGems range \"~\u003e 1.4.4\" excludes \"1.4\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:gem/\u003e=1.4.4|\u003c1.5.a", + "version": "1.4" + }, + "expected_output": false + }, + { + "description": "RubyGems range \"~\u003e 1.4.4\" contains \"1.4.4\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:gem/\u003e=1.4.4|\u003c1.5.a", + "version": "1.4.4" + }, + "expected_output": true + }, + { + "description": "RubyGems range \"~\u003e 1.4.4\" contains \"1.4.5\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:gem/\u003e=1.4.4|\u003c1.5.a", + "version": "1.4.5" + }, + "expected_output": true + }, + { + "description": "RubyGems range \"~\u003e 1.4.4\" excludes \"1.5\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:gem/\u003e=1.4.4|\u003c1.5.a", + "version": "1.5" + }, + "expected_output": false + }, + { + "description": "RubyGems range \"~\u003e 1.4.4\" excludes \"2.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:gem/\u003e=1.4.4|\u003c1.5.a", + "version": "2.0" + }, + "expected_output": false + }, + { + "description": "RubyGems range \"~\u003e 1.0.0\" excludes \"1.1.pre\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:gem/\u003e=1.0.0|\u003c1.1.a", + "version": "1.1.pre" + }, + "expected_output": false + }, + { + "description": "RubyGems range \"~\u003e 1.1\" excludes \"1.1.pre\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:gem/\u003e=1.1|\u003c2.a", + "version": "1.1.pre" + }, + "expected_output": false + }, + { + "description": "RubyGems range \"~\u003e 1.0\" excludes \"2.0.a\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:gem/\u003e=1.0|\u003c2.a", + "version": "2.0.a" + }, + "expected_output": false + }, + { + "description": "RubyGems range \"~\u003e 2.0\" excludes \"2.0.a\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:gem/\u003e=2.0|\u003c3.a", + "version": "2.0.a" + }, + "expected_output": false + }, + { + "description": "RubyGems range \"~\u003e 1\" excludes \"0.9\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:gem/\u003e=1|\u003c2.a", + "version": "0.9" + }, + "expected_output": false + }, + { + "description": "RubyGems range \"~\u003e 1\" contains \"1.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:gem/\u003e=1|\u003c2.a", + "version": "1.0" + }, + "expected_output": true + }, + { + "description": "RubyGems range \"~\u003e 1\" contains \"1.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:gem/\u003e=1|\u003c2.a", + "version": "1.1" + }, + "expected_output": true + }, + { + "description": "RubyGems range \"~\u003e 1\" excludes \"2.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:gem/\u003e=1|\u003c2.a", + "version": "2.0" + }, + "expected_output": false + }, + { + "description": "RubyGems range \"~\u003e 1.4\" contains \"1.4.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:gem/\u003e=1.4|\u003c2.a", + "version": "1.4.0" + }, + "expected_output": true + }, + { + "description": "RubyGems range \"\u003e 0.1\" excludes \"\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:gem/\u003e0.1" + }, + "expected_output": false + }, + { + "description": "RubyGems range \"!= 1.2.3\" excludes \"1.2.3\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:gem/!=1.2.3", + "version": "1.2.3" + }, + "expected_output": false + }, + { + "description": "RubyGems range \"!= 1.02.3\" excludes \"1.2.003.0.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:gem/!=1.02.3", + "version": "1.2.003.0.0" + }, + "expected_output": false + }, + { + "description": "RubyGems range \"\u003c 1.2.3\" excludes \"4.5.6\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:gem/\u003c1.2.3", + "version": "4.5.6" + }, + "expected_output": false + }, + { + "description": "RubyGems range \"\u003e 1.1\" excludes \"1.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:gem/\u003e1.1", + "version": "1.0" + }, + "expected_output": false + }, + { + "description": "RubyGems range \"= 0.1\" excludes \"\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:gem/0.1" + }, + "expected_output": false + }, + { + "description": "RubyGems range \"\u003e 1.1.1\" excludes \"1.1.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:gem/\u003e1.1.1", + "version": "1.1.1" + }, + "expected_output": false + }, + { + "description": "RubyGems range \"= 1.1\" excludes \"1.2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:gem/1.1", + "version": "1.2" + }, + "expected_output": false + }, + { + "description": "RubyGems range \"= 1.1\" excludes \"1.40\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:gem/1.1", + "version": "1.40" + }, + "expected_output": false + }, + { + "description": "RubyGems range \"= 1.40\" excludes \"1.3\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:gem/1.40", + "version": "1.3" + }, + "expected_output": false + }, + { + "description": "RubyGems range \"\u003c= 9.3.2\" excludes \"9.3.3\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:gem/\u003c=9.3.2", + "version": "9.3.3" + }, + "expected_output": false + }, + { + "description": "RubyGems range \"\u003e= 9.3.2\" excludes \"9.3.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:gem/\u003e=9.3.2", + "version": "9.3.1" + }, + "expected_output": false + }, + { + "description": "RubyGems range \"\u003c= 9.3.2\" excludes \"9.3.03\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:gem/\u003c=9.3.2", + "version": "9.3.03" + }, + "expected_output": false + }, + { + "description": "RubyGems range \"= 1.0\" excludes \"1.0.0.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:gem/1.0", + "version": "1.0.0.1" + }, + "expected_output": false + } + ] +} diff --git a/testdata/local/tests/maven_range_reference_test.json b/testdata/local/tests/maven_range_reference_test.json new file mode 100644 index 0000000..c65a449 --- /dev/null +++ b/testdata/local/tests/maven_range_reference_test.json @@ -0,0 +1,115 @@ +{ + "$schema": "https://packageurl.org/schemas/vers-test.schema-0.2.json", + "tests": [ + { + "description": "maven-artifact range \"[1.0,)\" excludes \"1.0-SNAPSHOT\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:maven/\u003e=1.0", + "version": "1.0-SNAPSHOT" + }, + "expected_output": false + }, + { + "description": "maven-artifact range \"[1.0,1.1-SNAPSHOT]\" contains \"1.1-SNAPSHOT\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:maven/\u003e=1.0|\u003c=1.1-SNAPSHOT", + "version": "1.1-SNAPSHOT" + }, + "expected_output": true + }, + { + "description": "maven-artifact range \"[5.0.9.0,5.0.10.0)\" contains \"5.0.9.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:maven/\u003e=5.0.9.0|\u003c5.0.10.0", + "version": "5.0.9.0" + }, + "expected_output": true + }, + { + "description": "maven-artifact range \"[1.0,1.2]\" contains \"1.1-SNAPSHOT\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:maven/\u003e=1.0|\u003c=1.2", + "version": "1.1-SNAPSHOT" + }, + "expected_output": true + }, + { + "description": "maven-artifact range \"[1.0,1.2]\" contains \"1.2-SNAPSHOT\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:maven/\u003e=1.0|\u003c=1.2", + "version": "1.2-SNAPSHOT" + }, + "expected_output": true + }, + { + "description": "maven-artifact range \"[1.0,1.2]\" excludes \"1.0-SNAPSHOT\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:maven/\u003e=1.0|\u003c=1.2", + "version": "1.0-SNAPSHOT" + }, + "expected_output": false + }, + { + "description": "maven-artifact range \"[1.0,1.2-SNAPSHOT]\" contains \"1.1-SNAPSHOT\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:maven/\u003e=1.0|\u003c=1.2-SNAPSHOT", + "version": "1.1-SNAPSHOT" + }, + "expected_output": true + }, + { + "description": "maven-artifact range \"[1.0,1.2-SNAPSHOT]\" contains \"1.2-SNAPSHOT\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:maven/\u003e=1.0|\u003c=1.2-SNAPSHOT", + "version": "1.2-SNAPSHOT" + }, + "expected_output": true + }, + { + "description": "maven-artifact range \"[1.0-SNAPSHOT,1.2]\" contains \"1.0-SNAPSHOT\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:maven/\u003e=1.0-SNAPSHOT|\u003c=1.2", + "version": "1.0-SNAPSHOT" + }, + "expected_output": true + }, + { + "description": "maven-artifact range \"[1.0-SNAPSHOT,1.2]\" contains \"1.1-SNAPSHOT\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:maven/\u003e=1.0-SNAPSHOT|\u003c=1.2", + "version": "1.1-SNAPSHOT" + }, + "expected_output": true + }, + { + "description": "maven-artifact range \"1.0-SNAPSHOT\" contains \"1.0-SNAPSHOT\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:maven/\u003e=1.0-SNAPSHOT", + "version": "1.0-SNAPSHOT" + }, + "expected_output": true + } + ] +} diff --git a/testdata/local/tests/npm_range_reference_test.json b/testdata/local/tests/npm_range_reference_test.json new file mode 100644 index 0000000..643a44d --- /dev/null +++ b/testdata/local/tests/npm_range_reference_test.json @@ -0,0 +1,1395 @@ +{ + "$schema": "https://packageurl.org/schemas/vers-test.schema-0.2.json", + "tests": [ + { + "description": "node-semver range \"1.0.0 - 2.0.0\" contains \"1.2.3\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=1.0.0|\u003c=2.0.0", + "version": "1.2.3" + }, + "expected_output": true + }, + { + "description": "node-semver range \"^1.2.3+build\" contains \"1.2.3\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=1.2.3+build|\u003c2.0.0", + "version": "1.2.3" + }, + "expected_output": true + }, + { + "description": "node-semver range \"^1.2.3+build\" contains \"1.3.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=1.2.3+build|\u003c2.0.0", + "version": "1.3.0" + }, + "expected_output": true + }, + { + "description": "node-semver range \"1.2.3-pre+asdf - 2.4.3-pre+asdf\" contains \"1.2.3\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=1.2.3-pre+asdf|\u003c=2.4.3-pre+asdf", + "version": "1.2.3" + }, + "expected_output": true + }, + { + "description": "node-semver range \"1.2.3-pre+asdf - 2.4.3-pre+asdf\" contains \"1.2.3-pre.2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=1.2.3-pre+asdf|\u003c=2.4.3-pre+asdf", + "version": "1.2.3-pre.2" + }, + "expected_output": true + }, + { + "description": "node-semver range \"1.2.3-pre+asdf - 2.4.3-pre+asdf\" contains \"2.4.3-alpha\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=1.2.3-pre+asdf|\u003c=2.4.3-pre+asdf", + "version": "2.4.3-alpha" + }, + "expected_output": true + }, + { + "description": "node-semver range \"1.2.3+asdf - 2.4.3+asdf\" contains \"1.2.3\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=1.2.3+asdf|\u003c=2.4.3+asdf", + "version": "1.2.3" + }, + "expected_output": true + }, + { + "description": "node-semver range \"1.0.0\" contains \"1.0.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/1.0.0", + "version": "1.0.0" + }, + "expected_output": true + }, + { + "description": "node-semver range \"\u003e=*\" contains \"0.2.4\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/*", + "version": "0.2.4" + }, + "expected_output": true + }, + { + "description": "node-semver range \"\" contains \"1.0.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/*", + "version": "1.0.0" + }, + "expected_output": true + }, + { + "description": "node-semver range \"*\" contains \"1.2.3\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/*", + "version": "1.2.3" + }, + "expected_output": true + }, + { + "description": "node-semver range \"\u003e=1.0.0\" contains \"1.0.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=1.0.0", + "version": "1.0.1" + }, + "expected_output": true + }, + { + "description": "node-semver range \"\u003e=1.0.0\" contains \"1.1.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=1.0.0", + "version": "1.1.0" + }, + "expected_output": true + }, + { + "description": "node-semver range \"\u003e1.0.0\" contains \"1.0.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e1.0.0", + "version": "1.0.1" + }, + "expected_output": true + }, + { + "description": "node-semver range \"\u003e1.0.0\" contains \"1.1.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e1.0.0", + "version": "1.1.0" + }, + "expected_output": true + }, + { + "description": "node-semver range \"\u003c=2.0.0\" contains \"2.0.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003c=2.0.0", + "version": "2.0.0" + }, + "expected_output": true + }, + { + "description": "node-semver range \"\u003c=2.0.0\" contains \"1.9999.9999\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003c=2.0.0", + "version": "1.9999.9999" + }, + "expected_output": true + }, + { + "description": "node-semver range \"\u003c=2.0.0\" contains \"0.2.9\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003c=2.0.0", + "version": "0.2.9" + }, + "expected_output": true + }, + { + "description": "node-semver range \"\u003c2.0.0\" contains \"1.9999.9999\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003c2.0.0", + "version": "1.9999.9999" + }, + "expected_output": true + }, + { + "description": "node-semver range \"\u003c2.0.0\" contains \"0.2.9\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003c2.0.0", + "version": "0.2.9" + }, + "expected_output": true + }, + { + "description": "node-semver range \"\u003e= 1.0.0\" contains \"1.0.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=1.0.0", + "version": "1.0.0" + }, + "expected_output": true + }, + { + "description": "node-semver range \"\u003e=0.1.97\" contains \"0.1.97\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=0.1.97", + "version": "0.1.97" + }, + "expected_output": true + }, + { + "description": "node-semver range \"0.1.20 || 1.2.4\" contains \"1.2.4\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/0.1.20|1.2.4", + "version": "1.2.4" + }, + "expected_output": true + }, + { + "description": "node-semver range \"\u003e=0.2.3 || \u003c0.0.1\" contains \"0.0.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003c0.0.1|\u003e=0.2.3", + "version": "0.0.0" + }, + "expected_output": true + }, + { + "description": "node-semver range \"\u003e=0.2.3 || \u003c0.0.1\" contains \"0.2.3\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003c0.0.1|\u003e=0.2.3", + "version": "0.2.3" + }, + "expected_output": true + }, + { + "description": "node-semver range \"\u003e=0.2.3 || \u003c0.0.1\" contains \"0.2.4\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003c0.0.1|\u003e=0.2.3", + "version": "0.2.4" + }, + "expected_output": true + }, + { + "description": "node-semver range \"||\" contains \"1.3.4\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/*", + "version": "1.3.4" + }, + "expected_output": true + }, + { + "description": "node-semver range \"2.x.x\" contains \"2.1.3\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=2.0.0|\u003c3.0.0", + "version": "2.1.3" + }, + "expected_output": true + }, + { + "description": "node-semver range \"1.2.x\" contains \"1.2.3\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=1.2.0|\u003c1.3.0", + "version": "1.2.3" + }, + "expected_output": true + }, + { + "description": "node-semver range \"1.2.x || 2.x\" contains \"2.1.3\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=1.2.0|\u003c1.3.0|\u003e=2.0.0|\u003c3.0.0", + "version": "2.1.3" + }, + "expected_output": true + }, + { + "description": "node-semver range \"1.2.x || 2.x\" contains \"1.2.3\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=1.2.0|\u003c1.3.0|\u003e=2.0.0|\u003c3.0.0", + "version": "1.2.3" + }, + "expected_output": true + }, + { + "description": "node-semver range \"2\" contains \"2.1.2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=2.0.0|\u003c3.0.0", + "version": "2.1.2" + }, + "expected_output": true + }, + { + "description": "node-semver range \"2.3\" contains \"2.3.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=2.3.0|\u003c2.4.0", + "version": "2.3.1" + }, + "expected_output": true + }, + { + "description": "node-semver range \"~0.0.1\" contains \"0.0.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=0.0.1|\u003c0.1.0", + "version": "0.0.1" + }, + "expected_output": true + }, + { + "description": "node-semver range \"~0.0.1\" contains \"0.0.2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=0.0.1|\u003c0.1.0", + "version": "0.0.2" + }, + "expected_output": true + }, + { + "description": "node-semver range \"~x\" contains \"0.0.9\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/*", + "version": "0.0.9" + }, + "expected_output": true + }, + { + "description": "node-semver range \"~2\" contains \"2.0.9\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=2.0.0|\u003c3.0.0", + "version": "2.0.9" + }, + "expected_output": true + }, + { + "description": "node-semver range \"~2.4\" contains \"2.4.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=2.4.0|\u003c2.5.0", + "version": "2.4.0" + }, + "expected_output": true + }, + { + "description": "node-semver range \"~2.4\" contains \"2.4.5\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=2.4.0|\u003c2.5.0", + "version": "2.4.5" + }, + "expected_output": true + }, + { + "description": "node-semver range \"~\u003e3.2.1\" contains \"3.2.2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=3.2.1|\u003c3.3.0", + "version": "3.2.2" + }, + "expected_output": true + }, + { + "description": "node-semver range \"~1\" contains \"1.2.3\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=1.0.0|\u003c2.0.0", + "version": "1.2.3" + }, + "expected_output": true + }, + { + "description": "node-semver range \"~1.0\" contains \"1.0.2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=1.0.0|\u003c1.1.0", + "version": "1.0.2" + }, + "expected_output": true + }, + { + "description": "node-semver range \"~ 1.0.3\" contains \"1.0.12\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=1.0.3|\u003c1.1.0", + "version": "1.0.12" + }, + "expected_output": true + }, + { + "description": "node-semver range \"\u003c1.2\" contains \"1.1.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003c1.2.0", + "version": "1.1.1" + }, + "expected_output": true + }, + { + "description": "node-semver range \"~v0.5.4-pre\" contains \"0.5.5\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=v0.5.4-pre|\u003c0.6.0", + "version": "0.5.5" + }, + "expected_output": true + }, + { + "description": "node-semver range \"~v0.5.4-pre\" contains \"0.5.4\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=v0.5.4-pre|\u003c0.6.0", + "version": "0.5.4" + }, + "expected_output": true + }, + { + "description": "node-semver range \"=0.7.x\" contains \"0.7.2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=0.7.0|\u003c0.8.0", + "version": "0.7.2" + }, + "expected_output": true + }, + { + "description": "node-semver range \"\u003c=0.7.x\" contains \"0.7.2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003c0.8.0", + "version": "0.7.2" + }, + "expected_output": true + }, + { + "description": "node-semver range \"\u003e=0.7.x\" contains \"0.7.2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=0.7.0", + "version": "0.7.2" + }, + "expected_output": true + }, + { + "description": "node-semver range \"\u003c=0.7.x\" contains \"0.6.2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003c0.8.0", + "version": "0.6.2" + }, + "expected_output": true + }, + { + "description": "node-semver range \"~1.2.1 \u003e=1.2.3\" contains \"1.2.3\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=1.2.3|\u003c1.3.0", + "version": "1.2.3" + }, + "expected_output": true + }, + { + "description": "node-semver range \"~1.2.1 =1.2.3\" contains \"1.2.3\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/1.2.3", + "version": "1.2.3" + }, + "expected_output": true + }, + { + "description": "node-semver range \"\u003e=1.2.3 \u003e=1.2.1\" contains \"1.2.3\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=1.2.3", + "version": "1.2.3" + }, + "expected_output": true + }, + { + "description": "node-semver range \"\u003e=1.2\" contains \"1.2.8\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=1.2.0", + "version": "1.2.8" + }, + "expected_output": true + }, + { + "description": "node-semver range \"^1.2.3\" contains \"1.8.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=1.2.3|\u003c2.0.0", + "version": "1.8.1" + }, + "expected_output": true + }, + { + "description": "node-semver range \"^0.1.2\" contains \"0.1.2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=0.1.2|\u003c0.2.0", + "version": "0.1.2" + }, + "expected_output": true + }, + { + "description": "node-semver range \"^0.1\" contains \"0.1.2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=0.1.0|\u003c0.2.0", + "version": "0.1.2" + }, + "expected_output": true + }, + { + "description": "node-semver range \"^0.0.1\" contains \"0.0.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=0.0.1|\u003c0.0.2", + "version": "0.0.1" + }, + "expected_output": true + }, + { + "description": "node-semver range \"^1.2\" contains \"1.4.2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=1.2.0|\u003c2.0.0", + "version": "1.4.2" + }, + "expected_output": true + }, + { + "description": "node-semver range \"^1.2.3-alpha\" contains \"1.2.3-pre\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=1.2.3-alpha|\u003c2.0.0", + "version": "1.2.3-pre" + }, + "expected_output": true + }, + { + "description": "node-semver range \"^1.2.0-alpha\" contains \"1.2.0-pre\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=1.2.0-alpha|\u003c2.0.0", + "version": "1.2.0-pre" + }, + "expected_output": true + }, + { + "description": "node-semver range \"^0.0.1-alpha\" contains \"0.0.1-beta\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=0.0.1-alpha|\u003c0.0.2", + "version": "0.0.1-beta" + }, + "expected_output": true + }, + { + "description": "node-semver range \"^0.0.1-alpha\" contains \"0.0.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=0.0.1-alpha|\u003c0.0.2", + "version": "0.0.1" + }, + "expected_output": true + }, + { + "description": "node-semver range \"^0.1.1-alpha\" contains \"0.1.1-beta\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=0.1.1-alpha|\u003c0.2.0", + "version": "0.1.1-beta" + }, + "expected_output": true + }, + { + "description": "node-semver range \"x - 1.0.0\" contains \"0.9.7\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003c=1.0.0", + "version": "0.9.7" + }, + "expected_output": true + }, + { + "description": "node-semver range \"x - 1.x\" contains \"0.9.7\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003c2.0.0", + "version": "0.9.7" + }, + "expected_output": true + }, + { + "description": "node-semver range \"1.0.0 - x\" contains \"1.9.7\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=1.0.0", + "version": "1.9.7" + }, + "expected_output": true + }, + { + "description": "node-semver range \"\u003c=7.x\" contains \"7.9.9\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003c8.0.0", + "version": "7.9.9" + }, + "expected_output": true + }, + { + "description": "node-semver range \"1.0.0 - 2.0.0\" excludes \"2.2.3\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=1.0.0|\u003c=2.0.0", + "version": "2.2.3" + }, + "expected_output": false + }, + { + "description": "node-semver range \"1.2.3+asdf - 2.4.3+asdf\" excludes \"1.2.3-pre.2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=1.2.3+asdf|\u003c=2.4.3+asdf", + "version": "1.2.3-pre.2" + }, + "expected_output": false + }, + { + "description": "node-semver range \"1.2.3+asdf - 2.4.3+asdf\" excludes \"2.4.3-alpha\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=1.2.3+asdf|\u003c=2.4.3+asdf", + "version": "2.4.3-alpha" + }, + "expected_output": false + }, + { + "description": "node-semver range \"^1.2.3+build\" excludes \"2.0.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=1.2.3+build|\u003c2.0.0", + "version": "2.0.0" + }, + "expected_output": false + }, + { + "description": "node-semver range \"^1.2.3+build\" excludes \"1.2.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=1.2.3+build|\u003c2.0.0", + "version": "1.2.0" + }, + "expected_output": false + }, + { + "description": "node-semver range \"^1.2.3\" excludes \"1.2.3-pre\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=1.2.3|\u003c2.0.0", + "version": "1.2.3-pre" + }, + "expected_output": false + }, + { + "description": "node-semver range \"^1.2\" excludes \"1.2.0-pre\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=1.2.0|\u003c2.0.0", + "version": "1.2.0-pre" + }, + "expected_output": false + }, + { + "description": "node-semver range \"\u003e1.2\" excludes \"1.3.0-beta\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=1.3.0", + "version": "1.3.0-beta" + }, + "expected_output": false + }, + { + "description": "node-semver range \"\u003c=1.2.3\" excludes \"1.2.3-beta\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003c=1.2.3", + "version": "1.2.3-beta" + }, + "expected_output": false + }, + { + "description": "node-semver range \"^1.2.3\" excludes \"1.2.3-beta\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=1.2.3|\u003c2.0.0", + "version": "1.2.3-beta" + }, + "expected_output": false + }, + { + "description": "node-semver range \"=0.7.x\" excludes \"0.7.0-asdf\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=0.7.0|\u003c0.8.0", + "version": "0.7.0-asdf" + }, + "expected_output": false + }, + { + "description": "node-semver range \"\u003e=0.7.x\" excludes \"0.7.0-asdf\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=0.7.0", + "version": "0.7.0-asdf" + }, + "expected_output": false + }, + { + "description": "node-semver range \"\u003c=0.7.x\" excludes \"0.7.0-asdf\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003c0.8.0", + "version": "0.7.0-asdf" + }, + "expected_output": false + }, + { + "description": "node-semver range \"1.0.0\" excludes \"1.0.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/1.0.0", + "version": "1.0.1" + }, + "expected_output": false + }, + { + "description": "node-semver range \"\u003e=1.0.0\" excludes \"0.0.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=1.0.0", + "version": "0.0.0" + }, + "expected_output": false + }, + { + "description": "node-semver range \"\u003e=1.0.0\" excludes \"0.0.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=1.0.0", + "version": "0.0.1" + }, + "expected_output": false + }, + { + "description": "node-semver range \"\u003e=1.0.0\" excludes \"0.1.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=1.0.0", + "version": "0.1.0" + }, + "expected_output": false + }, + { + "description": "node-semver range \"\u003e1.0.0\" excludes \"0.0.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e1.0.0", + "version": "0.0.1" + }, + "expected_output": false + }, + { + "description": "node-semver range \"\u003e1.0.0\" excludes \"0.1.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e1.0.0", + "version": "0.1.0" + }, + "expected_output": false + }, + { + "description": "node-semver range \"\u003c=2.0.0\" excludes \"3.0.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003c=2.0.0", + "version": "3.0.0" + }, + "expected_output": false + }, + { + "description": "node-semver range \"\u003c=2.0.0\" excludes \"2.9999.9999\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003c=2.0.0", + "version": "2.9999.9999" + }, + "expected_output": false + }, + { + "description": "node-semver range \"\u003c=2.0.0\" excludes \"2.2.9\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003c=2.0.0", + "version": "2.2.9" + }, + "expected_output": false + }, + { + "description": "node-semver range \"\u003c2.0.0\" excludes \"2.9999.9999\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003c2.0.0", + "version": "2.9999.9999" + }, + "expected_output": false + }, + { + "description": "node-semver range \"\u003c2.0.0\" excludes \"2.2.9\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003c2.0.0", + "version": "2.2.9" + }, + "expected_output": false + }, + { + "description": "node-semver range \"\u003e=0.1.97\" excludes \"0.1.93\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=0.1.97", + "version": "0.1.93" + }, + "expected_output": false + }, + { + "description": "node-semver range \"0.1.20 || 1.2.4\" excludes \"1.2.3\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/0.1.20|1.2.4", + "version": "1.2.3" + }, + "expected_output": false + }, + { + "description": "node-semver range \"\u003e=0.2.3 || \u003c0.0.1\" excludes \"0.0.3\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003c0.0.1|\u003e=0.2.3", + "version": "0.0.3" + }, + "expected_output": false + }, + { + "description": "node-semver range \"\u003e=0.2.3 || \u003c0.0.1\" excludes \"0.2.2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003c0.0.1|\u003e=0.2.3", + "version": "0.2.2" + }, + "expected_output": false + }, + { + "description": "node-semver range \"2.x.x\" excludes \"3.1.3\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=2.0.0|\u003c3.0.0", + "version": "3.1.3" + }, + "expected_output": false + }, + { + "description": "node-semver range \"1.2.x\" excludes \"1.3.3\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=1.2.0|\u003c1.3.0", + "version": "1.3.3" + }, + "expected_output": false + }, + { + "description": "node-semver range \"1.2.x || 2.x\" excludes \"3.1.3\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=1.2.0|\u003c1.3.0|\u003e=2.0.0|\u003c3.0.0", + "version": "3.1.3" + }, + "expected_output": false + }, + { + "description": "node-semver range \"1.2.x || 2.x\" excludes \"1.1.3\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=1.2.0|\u003c1.3.0|\u003e=2.0.0|\u003c3.0.0", + "version": "1.1.3" + }, + "expected_output": false + }, + { + "description": "node-semver range \"2.*.*\" excludes \"1.1.3\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=2.0.0|\u003c3.0.0", + "version": "1.1.3" + }, + "expected_output": false + }, + { + "description": "node-semver range \"2\" excludes \"1.1.2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=2.0.0|\u003c3.0.0", + "version": "1.1.2" + }, + "expected_output": false + }, + { + "description": "node-semver range \"2.3\" excludes \"2.4.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=2.3.0|\u003c2.4.0", + "version": "2.4.1" + }, + "expected_output": false + }, + { + "description": "node-semver range \"~0.0.1\" excludes \"0.1.0-alpha\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=0.0.1|\u003c0.1.0", + "version": "0.1.0-alpha" + }, + "expected_output": false + }, + { + "description": "node-semver range \"~0.0.1\" excludes \"0.1.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=0.0.1|\u003c0.1.0", + "version": "0.1.0" + }, + "expected_output": false + }, + { + "description": "node-semver range \"~2.4\" excludes \"2.5.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=2.4.0|\u003c2.5.0", + "version": "2.5.0" + }, + "expected_output": false + }, + { + "description": "node-semver range \"~2.4\" excludes \"2.3.9\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=2.4.0|\u003c2.5.0", + "version": "2.3.9" + }, + "expected_output": false + }, + { + "description": "node-semver range \"~\u003e3.2.1\" excludes \"3.3.2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=3.2.1|\u003c3.3.0", + "version": "3.3.2" + }, + "expected_output": false + }, + { + "description": "node-semver range \"~\u003e3.2.1\" excludes \"3.2.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=3.2.1|\u003c3.3.0", + "version": "3.2.0" + }, + "expected_output": false + }, + { + "description": "node-semver range \"~1\" excludes \"0.2.3\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=1.0.0|\u003c2.0.0", + "version": "0.2.3" + }, + "expected_output": false + }, + { + "description": "node-semver range \"~\u003e1\" excludes \"2.2.3\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=1.0.0|\u003c2.0.0", + "version": "2.2.3" + }, + "expected_output": false + }, + { + "description": "node-semver range \"~1.0\" excludes \"1.1.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=1.0.0|\u003c1.1.0", + "version": "1.1.0" + }, + "expected_output": false + }, + { + "description": "node-semver range \"\u003c1\" excludes \"1.0.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003c1.0.0", + "version": "1.0.0" + }, + "expected_output": false + }, + { + "description": "node-semver range \"\u003e=1.2\" excludes \"1.1.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=1.2.0", + "version": "1.1.1" + }, + "expected_output": false + }, + { + "description": "node-semver range \"~v0.5.4-beta\" excludes \"0.5.4-alpha\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=v0.5.4-beta|\u003c0.6.0", + "version": "0.5.4-alpha" + }, + "expected_output": false + }, + { + "description": "node-semver range \"=0.7.x\" excludes \"0.8.2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=0.7.0|\u003c0.8.0", + "version": "0.8.2" + }, + "expected_output": false + }, + { + "description": "node-semver range \"\u003e=0.7.x\" excludes \"0.6.2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=0.7.0", + "version": "0.6.2" + }, + "expected_output": false + }, + { + "description": "node-semver range \"\u003c0.7.x\" excludes \"0.7.2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003c0.7.0", + "version": "0.7.2" + }, + "expected_output": false + }, + { + "description": "node-semver range \"\u003c1.2.3\" excludes \"1.2.3-beta\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003c1.2.3", + "version": "1.2.3-beta" + }, + "expected_output": false + }, + { + "description": "node-semver range \"=1.2.3\" excludes \"1.2.3-beta\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/1.2.3", + "version": "1.2.3-beta" + }, + "expected_output": false + }, + { + "description": "node-semver range \"\u003e1.2\" excludes \"1.2.8\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=1.3.0", + "version": "1.2.8" + }, + "expected_output": false + }, + { + "description": "node-semver range \"^0.0.1\" excludes \"0.0.2-alpha\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=0.0.1|\u003c0.0.2", + "version": "0.0.2-alpha" + }, + "expected_output": false + }, + { + "description": "node-semver range \"^0.0.1\" excludes \"0.0.2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=0.0.1|\u003c0.0.2", + "version": "0.0.2" + }, + "expected_output": false + }, + { + "description": "node-semver range \"^1.2.3\" excludes \"2.0.0-alpha\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=1.2.3|\u003c2.0.0", + "version": "2.0.0-alpha" + }, + "expected_output": false + }, + { + "description": "node-semver range \"^1.2.3\" excludes \"1.2.2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=1.2.3|\u003c2.0.0", + "version": "1.2.2" + }, + "expected_output": false + }, + { + "description": "node-semver range \"^1.2\" excludes \"1.1.9\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=1.2.0|\u003c2.0.0", + "version": "1.1.9" + }, + "expected_output": false + }, + { + "description": "node-semver range \"*\" excludes \"not a version\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/*", + "version": "not a version" + }, + "expected_output": false + }, + { + "description": "node-semver range \"\u003e=2\" excludes \"glorp\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=2.0.0", + "version": "glorp" + }, + "expected_output": false + }, + { + "description": "node-semver range \"^1.0.0\" excludes \"2.0.0-rc1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=1.0.0|\u003c2.0.0", + "version": "2.0.0-rc1" + }, + "expected_output": false + }, + { + "description": "node-semver range \"1 - 2\" excludes \"2.0.0-pre\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=1.0.0|\u003c3.0.0", + "version": "2.0.0-pre" + }, + "expected_output": false + }, + { + "description": "node-semver range \"1 - 2\" excludes \"1.0.0-pre\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=1.0.0|\u003c3.0.0", + "version": "1.0.0-pre" + }, + "expected_output": false + }, + { + "description": "node-semver range \"1.1.x\" excludes \"1.0.0-a\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=1.1.0|\u003c1.2.0", + "version": "1.0.0-a" + }, + "expected_output": false + }, + { + "description": "node-semver range \"1.1.x\" excludes \"1.1.0-a\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=1.1.0|\u003c1.2.0", + "version": "1.1.0-a" + }, + "expected_output": false + }, + { + "description": "node-semver range \"1.1.x\" excludes \"1.2.0-a\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=1.1.0|\u003c1.2.0", + "version": "1.2.0-a" + }, + "expected_output": false + }, + { + "description": "node-semver range \"1.x\" excludes \"1.0.0-a\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=1.0.0|\u003c2.0.0", + "version": "1.0.0-a" + }, + "expected_output": false + }, + { + "description": "node-semver range \"1.x\" excludes \"1.1.0-a\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=1.0.0|\u003c2.0.0", + "version": "1.1.0-a" + }, + "expected_output": false + }, + { + "description": "node-semver range \"1.x\" excludes \"1.2.0-a\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=1.0.0|\u003c2.0.0", + "version": "1.2.0-a" + }, + "expected_output": false + }, + { + "description": "node-semver range \"\u003e=1.0.0 \u003c1.1.0\" excludes \"1.1.0-pre\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=1.0.0|\u003c1.1.0", + "version": "1.1.0-pre" + }, + "expected_output": false + }, + { + "description": "node-semver range \"\u003e=1.0.0 \u003c1.1.0-pre\" excludes \"1.1.0-pre\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:npm/\u003e=1.0.0|\u003c1.1.0-pre", + "version": "1.1.0-pre" + }, + "expected_output": false + } + ] +} diff --git a/testdata/local/tests/pub_range_reference_test.json b/testdata/local/tests/pub_range_reference_test.json new file mode 100644 index 0000000..1d6df59 --- /dev/null +++ b/testdata/local/tests/pub_range_reference_test.json @@ -0,0 +1,605 @@ +{ + "$schema": "https://packageurl.org/schemas/vers-test.schema-0.2.json", + "tests": [ + { + "description": "pub_semver range \"any\" contains \"0.0.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pub/*", + "version": "0.0.0" + }, + "expected_output": true + }, + { + "description": "pub_semver range \"any\" contains \"1.2.3\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pub/*", + "version": "1.2.3" + }, + "expected_output": true + }, + { + "description": "pub_semver range \"any\" contains \"12345.678.90\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pub/*", + "version": "12345.678.90" + }, + "expected_output": true + }, + { + "description": "pub_semver range \"\u003e1.2.3\" contains \"1.2.3+foo\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pub/\u003e1.2.3", + "version": "1.2.3+foo" + }, + "expected_output": true + }, + { + "description": "pub_semver range \"\u003e1.2.3\" contains \"1.2.4\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pub/\u003e1.2.3", + "version": "1.2.4" + }, + "expected_output": true + }, + { + "description": "pub_semver range \"\u003e1.2.3\" excludes \"1.2.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pub/\u003e1.2.3", + "version": "1.2.1" + }, + "expected_output": false + }, + { + "description": "pub_semver range \"\u003e1.2.3\" excludes \"1.2.3-build\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pub/\u003e1.2.3", + "version": "1.2.3-build" + }, + "expected_output": false + }, + { + "description": "pub_semver range \"\u003e1.2.3\" excludes \"1.2.3\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pub/\u003e1.2.3", + "version": "1.2.3" + }, + "expected_output": false + }, + { + "description": "pub_semver range \"\u003e=1.2.3\" contains \"1.2.3\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pub/\u003e=1.2.3", + "version": "1.2.3" + }, + "expected_output": true + }, + { + "description": "pub_semver range \"\u003e=1.2.3\" contains \"1.2.3+foo\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pub/\u003e=1.2.3", + "version": "1.2.3+foo" + }, + "expected_output": true + }, + { + "description": "pub_semver range \"\u003e=1.2.3\" contains \"1.2.4\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pub/\u003e=1.2.3", + "version": "1.2.4" + }, + "expected_output": true + }, + { + "description": "pub_semver range \"\u003e=1.2.3\" excludes \"1.2.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pub/\u003e=1.2.3", + "version": "1.2.1" + }, + "expected_output": false + }, + { + "description": "pub_semver range \"\u003e=1.2.3\" excludes \"1.2.3-build\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pub/\u003e=1.2.3", + "version": "1.2.3-build" + }, + "expected_output": false + }, + { + "description": "pub_semver range \"\u003c1.2.3\" contains \"1.2.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pub/\u003c1.2.3-0", + "version": "1.2.1" + }, + "expected_output": true + }, + { + "description": "pub_semver range \"\u003c1.2.3\" contains \"1.2.2+foo\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pub/\u003c1.2.3-0", + "version": "1.2.2+foo" + }, + "expected_output": true + }, + { + "description": "pub_semver range \"\u003c1.2.3\" excludes \"1.2.3\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pub/\u003c1.2.3-0", + "version": "1.2.3" + }, + "expected_output": false + }, + { + "description": "pub_semver range \"\u003c1.2.3\" excludes \"1.2.3+foo\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pub/\u003c1.2.3-0", + "version": "1.2.3+foo" + }, + "expected_output": false + }, + { + "description": "pub_semver range \"\u003c1.2.3\" excludes \"1.2.4\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pub/\u003c1.2.3-0", + "version": "1.2.4" + }, + "expected_output": false + }, + { + "description": "pub_semver range \"\u003c=1.2.3\" contains \"1.2.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pub/\u003c=1.2.3", + "version": "1.2.1" + }, + "expected_output": true + }, + { + "description": "pub_semver range \"\u003c=1.2.3\" contains \"1.2.3-build\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pub/\u003c=1.2.3", + "version": "1.2.3-build" + }, + "expected_output": true + }, + { + "description": "pub_semver range \"\u003c=1.2.3\" contains \"1.2.3\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pub/\u003c=1.2.3", + "version": "1.2.3" + }, + "expected_output": true + }, + { + "description": "pub_semver range \"\u003c=1.2.3\" excludes \"1.2.3+foo\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pub/\u003c=1.2.3", + "version": "1.2.3+foo" + }, + "expected_output": false + }, + { + "description": "pub_semver range \"\u003c=1.2.3\" excludes \"1.2.4\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pub/\u003c=1.2.3", + "version": "1.2.4" + }, + "expected_output": false + }, + { + "description": "pub_semver range \"\u003e1.0.0 \u003e=1.2.3 \u003c1.3.0\" contains \"1.2.3\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pub/\u003e=1.2.3|\u003c1.3.0-0", + "version": "1.2.3" + }, + "expected_output": true + }, + { + "description": "pub_semver range \"\u003e1.0.0 \u003e=1.2.3 \u003c1.3.0\" contains \"1.2.5\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pub/\u003e=1.2.3|\u003c1.3.0-0", + "version": "1.2.5" + }, + "expected_output": true + }, + { + "description": "pub_semver range \"\u003e1.0.0 \u003e=1.2.3 \u003c1.3.0\" excludes \"1.2.3-pre\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pub/\u003e=1.2.3|\u003c1.3.0-0", + "version": "1.2.3-pre" + }, + "expected_output": false + }, + { + "description": "pub_semver range \"\u003e1.0.0 \u003e=1.2.3 \u003c1.3.0\" excludes \"1.3.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pub/\u003e=1.2.3|\u003c1.3.0-0", + "version": "1.3.0" + }, + "expected_output": false + }, + { + "description": "pub_semver range \"\u003e1.0.0 \u003e=1.2.3 \u003c1.3.0\" excludes \"3.4.5\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pub/\u003e=1.2.3|\u003c1.3.0-0", + "version": "3.4.5" + }, + "expected_output": false + }, + { + "description": "pub_semver range \"\u003e=1.0.0-dev.2 \u003c1.0.0\" contains \"1.0.0-dev.2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pub/\u003e=1.0.0-dev.2|\u003c1.0.0", + "version": "1.0.0-dev.2" + }, + "expected_output": true + }, + { + "description": "pub_semver range \"\u003e=1.0.0-dev.2 \u003c1.0.0\" contains \"1.0.0-dev.3\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pub/\u003e=1.0.0-dev.2|\u003c1.0.0", + "version": "1.0.0-dev.3" + }, + "expected_output": true + }, + { + "description": "pub_semver range \"\u003e=1.0.0-dev.2 \u003c1.0.0\" excludes \"1.0.0-dev.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pub/\u003e=1.0.0-dev.2|\u003c1.0.0", + "version": "1.0.0-dev.1" + }, + "expected_output": false + }, + { + "description": "pub_semver range \"\u003e=1.0.0-dev.2 \u003c1.0.0\" excludes \"1.0.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pub/\u003e=1.0.0-dev.2|\u003c1.0.0", + "version": "1.0.0" + }, + "expected_output": false + }, + { + "description": "pub_semver range \"\u003e1.2.3\" contains \"1.3.3\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pub/\u003e1.2.3", + "version": "1.3.3" + }, + "expected_output": true + }, + { + "description": "pub_semver range \"\u003e1.2.3\" contains \"2.3.3\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pub/\u003e1.2.3", + "version": "2.3.3" + }, + "expected_output": true + }, + { + "description": "pub_semver range \"\u003e1.2.3\" excludes \"1.2.2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pub/\u003e1.2.3", + "version": "1.2.2" + }, + "expected_output": false + }, + { + "description": "pub_semver range \"\u003e=1.2.3\" contains \"1.3.3\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pub/\u003e=1.2.3", + "version": "1.3.3" + }, + "expected_output": true + }, + { + "description": "pub_semver range \"\u003e=1.2.3\" contains \"2.3.3\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pub/\u003e=1.2.3", + "version": "2.3.3" + }, + "expected_output": true + }, + { + "description": "pub_semver range \"\u003e=1.2.3\" excludes \"1.2.2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pub/\u003e=1.2.3", + "version": "1.2.2" + }, + "expected_output": false + }, + { + "description": "pub_semver range \"\u003e=1.2.3\" contains \"1.2.4-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pub/\u003e=1.2.3", + "version": "1.2.4-dev" + }, + "expected_output": true + }, + { + "description": "pub_semver range \"\u003e=1.2.3\" excludes \"1.2.3-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pub/\u003e=1.2.3", + "version": "1.2.3-dev" + }, + "expected_output": false + }, + { + "description": "pub_semver range \"\u003c2.3.4\" contains \"2.3.3\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pub/\u003c2.3.4-0", + "version": "2.3.3" + }, + "expected_output": true + }, + { + "description": "pub_semver range \"\u003c2.3.4\" excludes \"2.3.4\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pub/\u003c2.3.4-0", + "version": "2.3.4" + }, + "expected_output": false + }, + { + "description": "pub_semver range \"\u003c2.3.4\" excludes \"2.4.3\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pub/\u003c2.3.4-0", + "version": "2.4.3" + }, + "expected_output": false + }, + { + "description": "pub_semver range \"\u003c2.3.4\" excludes \"2.3.4-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pub/\u003c2.3.4-0", + "version": "2.3.4-dev" + }, + "expected_output": false + }, + { + "description": "pub_semver range \"\u003c2.3.4\" excludes \"2.3.4--1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pub/\u003c2.3.4-0", + "version": "2.3.4--1" + }, + "expected_output": false + }, + { + "description": "pub_semver range \"\u003c2.3.4\" excludes \"2.3.4-0xA\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pub/\u003c2.3.4-0", + "version": "2.3.4-0xA" + }, + "expected_output": false + }, + { + "description": "pub_semver range \"\u003e2.3.4-dev.0 \u003c2.3.4\" contains \"2.3.4-dev.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pub/\u003e2.3.4-dev.0|\u003c2.3.4", + "version": "2.3.4-dev.1" + }, + "expected_output": true + }, + { + "description": "pub_semver range \"\u003e2.3.4-dev.0 \u003c2.3.4\" excludes \"2.3.3\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pub/\u003e2.3.4-dev.0|\u003c2.3.4", + "version": "2.3.3" + }, + "expected_output": false + }, + { + "description": "pub_semver range \"\u003e2.3.4-dev.0 \u003c2.3.4\" excludes \"2.3.4-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pub/\u003e2.3.4-dev.0|\u003c2.3.4", + "version": "2.3.4-dev" + }, + "expected_output": false + }, + { + "description": "pub_semver range \"\u003e2.3.4-dev.0 \u003c2.3.4\" excludes \"2.3.4\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pub/\u003e2.3.4-dev.0|\u003c2.3.4", + "version": "2.3.4" + }, + "expected_output": false + }, + { + "description": "pub_semver range \"\u003c2.3.4-dev.2\" contains \"2.3.4-dev.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pub/\u003c2.3.4-dev.2", + "version": "2.3.4-dev.1" + }, + "expected_output": true + }, + { + "description": "pub_semver range \"\u003c2.3.4-dev.2\" excludes \"2.3.4-dev.2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pub/\u003c2.3.4-dev.2", + "version": "2.3.4-dev.2" + }, + "expected_output": false + }, + { + "description": "pub_semver range \"\u003c2.3.4-dev.2\" excludes \"2.3.4-dev.3\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pub/\u003c2.3.4-dev.2", + "version": "2.3.4-dev.3" + }, + "expected_output": false + }, + { + "description": "pub_semver range \"\u003e1.2.3 \u003c=2.3.4\" contains \"2.3.3\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pub/\u003e1.2.3|\u003c=2.3.4", + "version": "2.3.3" + }, + "expected_output": true + }, + { + "description": "pub_semver range \"\u003e1.2.3 \u003c=2.3.4\" contains \"2.3.4\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pub/\u003e1.2.3|\u003c=2.3.4", + "version": "2.3.4" + }, + "expected_output": true + }, + { + "description": "pub_semver range \"\u003e1.2.3 \u003c=2.3.4\" contains \"2.3.4-dev\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pub/\u003e1.2.3|\u003c=2.3.4", + "version": "2.3.4-dev" + }, + "expected_output": true + }, + { + "description": "pub_semver range \"\u003e1.2.3 \u003c=2.3.4\" excludes \"2.4.3\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pub/\u003e1.2.3|\u003c=2.3.4", + "version": "2.4.3" + }, + "expected_output": false + }, + { + "description": "pub_semver range \"\u003c1.2.3\" contains \"0.0.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pub/\u003c1.2.3-0", + "version": "0.0.0" + }, + "expected_output": true + }, + { + "description": "pub_semver range \"\u003e1.2.3\" contains \"999.3.3\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pub/\u003e1.2.3", + "version": "999.3.3" + }, + "expected_output": true + }, + { + "description": "pub_semver range \"any\" contains \"999.99.9\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pub/*", + "version": "999.99.9" + }, + "expected_output": true + } + ] +} diff --git a/testdata/local/tests/pypi_range_reference_test.json b/testdata/local/tests/pypi_range_reference_test.json new file mode 100644 index 0000000..6dc747a --- /dev/null +++ b/testdata/local/tests/pypi_range_reference_test.json @@ -0,0 +1,1885 @@ +{ + "$schema": "https://packageurl.org/schemas/vers-test.schema-0.2.json", + "tests": [ + { + "description": "packaging range \"==2\" contains \"2.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/2", + "version": "2.0" + }, + "expected_output": true + }, + { + "description": "packaging range \"==2.0\" contains \"2.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/2.0", + "version": "2.0" + }, + "expected_output": true + }, + { + "description": "packaging range \"==2.0.0\" contains \"2.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/2.0.0", + "version": "2.0" + }, + "expected_output": true + }, + { + "description": "packaging range \"==2\" contains \"2.0+deadbeef\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/2", + "version": "2.0+deadbeef" + }, + "expected_output": true + }, + { + "description": "packaging range \"==2.0\" contains \"2.0+deadbeef\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/2.0", + "version": "2.0+deadbeef" + }, + "expected_output": true + }, + { + "description": "packaging range \"==2.0.0\" contains \"2.0+deadbeef\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/2.0.0", + "version": "2.0+deadbeef" + }, + "expected_output": true + }, + { + "description": "packaging range \"==2+deadbeef\" contains \"2.0+deadbeef\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/2+deadbeef", + "version": "2.0+deadbeef" + }, + "expected_output": true + }, + { + "description": "packaging range \"==2.0+deadbeef\" contains \"2.0+deadbeef\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/2.0+deadbeef", + "version": "2.0+deadbeef" + }, + "expected_output": true + }, + { + "description": "packaging range \"==2.0.0+deadbeef\" contains \"2.0+deadbeef\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/2.0.0+deadbeef", + "version": "2.0+deadbeef" + }, + "expected_output": true + }, + { + "description": "packaging range \"==2.0.0+deadbeef.00\" contains \"2.0+deadbeef.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/2.0.0+deadbeef.00", + "version": "2.0+deadbeef.0" + }, + "expected_output": true + }, + { + "description": "packaging range \"==2.*\" contains \"2.dev1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e=2.dev0|\u003c3.dev0", + "version": "2.dev1" + }, + "expected_output": true + }, + { + "description": "packaging range \"==2.*\" contains \"2a1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e=2.dev0|\u003c3.dev0", + "version": "2a1" + }, + "expected_output": true + }, + { + "description": "packaging range \"==2.*\" contains \"2a1.post1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e=2.dev0|\u003c3.dev0", + "version": "2a1.post1" + }, + "expected_output": true + }, + { + "description": "packaging range \"==2.*\" contains \"2b1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e=2.dev0|\u003c3.dev0", + "version": "2b1" + }, + "expected_output": true + }, + { + "description": "packaging range \"==2.*\" contains \"2b1.dev1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e=2.dev0|\u003c3.dev0", + "version": "2b1.dev1" + }, + "expected_output": true + }, + { + "description": "packaging range \"==2.*\" contains \"2c1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e=2.dev0|\u003c3.dev0", + "version": "2c1" + }, + "expected_output": true + }, + { + "description": "packaging range \"==2.*\" contains \"2c1.post1.dev1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e=2.dev0|\u003c3.dev0", + "version": "2c1.post1.dev1" + }, + "expected_output": true + }, + { + "description": "packaging range \"==2.0.*\" contains \"2c1.post1.dev1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e=2.0.dev0|\u003c2.1.dev0", + "version": "2c1.post1.dev1" + }, + "expected_output": true + }, + { + "description": "packaging range \"==2.*\" contains \"2rc1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e=2.dev0|\u003c3.dev0", + "version": "2rc1" + }, + "expected_output": true + }, + { + "description": "packaging range \"==2.0.*\" contains \"2rc1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e=2.0.dev0|\u003c2.1.dev0", + "version": "2rc1" + }, + "expected_output": true + }, + { + "description": "packaging range \"==2.*\" contains \"2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e=2.dev0|\u003c3.dev0", + "version": "2" + }, + "expected_output": true + }, + { + "description": "packaging range \"==2.0.*\" contains \"2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e=2.0.dev0|\u003c2.1.dev0", + "version": "2" + }, + "expected_output": true + }, + { + "description": "packaging range \"==2.0.0.*\" contains \"2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e=2.0.0.dev0|\u003c2.0.1.dev0", + "version": "2" + }, + "expected_output": true + }, + { + "description": "packaging range \"==0!2.*\" contains \"2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e=0%212.dev0|\u003c0%213.dev0", + "version": "2" + }, + "expected_output": true + }, + { + "description": "packaging range \"==2.*\" contains \"0!2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e=2.dev0|\u003c3.dev0", + "version": "0!2" + }, + "expected_output": true + }, + { + "description": "packaging range \"==2.*\" contains \"2.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e=2.dev0|\u003c3.dev0", + "version": "2.0" + }, + "expected_output": true + }, + { + "description": "packaging range \"==2.*\" contains \"2.0.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e=2.dev0|\u003c3.dev0", + "version": "2.0.0" + }, + "expected_output": true + }, + { + "description": "packaging range \"==2.0.*\" contains \"2.0.0.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e=2.0.dev0|\u003c2.1.dev0", + "version": "2.0.0.0" + }, + "expected_output": true + }, + { + "description": "packaging range \"==2.1.*\" contains \"2.1+local.version\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e=2.1.dev0|\u003c2.2.dev0", + "version": "2.1+local.version" + }, + "expected_output": true + }, + { + "description": "packaging range \"!=2\" contains \"2.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/!=2", + "version": "2.1" + }, + "expected_output": true + }, + { + "description": "packaging range \"!=2.0\" contains \"2.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/!=2.0", + "version": "2.1" + }, + "expected_output": true + }, + { + "description": "packaging range \"!=2\" contains \"2.0.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/!=2", + "version": "2.0.1" + }, + "expected_output": true + }, + { + "description": "packaging range \"!=2.0\" contains \"2.0.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/!=2.0", + "version": "2.0.1" + }, + "expected_output": true + }, + { + "description": "packaging range \"!=2.0.0\" contains \"2.0.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/!=2.0.0", + "version": "2.0.1" + }, + "expected_output": true + }, + { + "description": "packaging range \"!=2.0+deadbeef\" contains \"2.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/!=2.0+deadbeef", + "version": "2.0" + }, + "expected_output": true + }, + { + "description": "packaging range \"!=3.*\" contains \"2.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003c3.dev0|\u003e=4.dev0", + "version": "2.0" + }, + "expected_output": true + }, + { + "description": "packaging range \"!=2.0.*\" contains \"2.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003c2.0.dev0|\u003e=2.1.dev0", + "version": "2.1" + }, + "expected_output": true + }, + { + "description": "packaging range \"!=2.0.0.*\" contains \"3\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003c2.0.0.dev0|\u003e=2.0.1.dev0", + "version": "3" + }, + "expected_output": true + }, + { + "description": "packaging range \"!=2.0.*\" contains \"2.1.0.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003c2.0.dev0|\u003e=2.1.dev0", + "version": "2.1.0.0" + }, + "expected_output": true + }, + { + "description": "packaging range \"\u003e=2\" contains \"2.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e=2", + "version": "2.0" + }, + "expected_output": true + }, + { + "description": "packaging range \"\u003e=2.0\" contains \"2.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e=2.0", + "version": "2.0" + }, + "expected_output": true + }, + { + "description": "packaging range \"\u003e=2.0.0\" contains \"2.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e=2.0.0", + "version": "2.0" + }, + "expected_output": true + }, + { + "description": "packaging range \"\u003e=2\" contains \"2.0.post1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e=2", + "version": "2.0.post1" + }, + "expected_output": true + }, + { + "description": "packaging range \"\u003e=2\" contains \"2.0.post1.dev1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e=2", + "version": "2.0.post1.dev1" + }, + "expected_output": true + }, + { + "description": "packaging range \"\u003e=2\" contains \"3\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e=2", + "version": "3" + }, + "expected_output": true + }, + { + "description": "packaging range \"\u003e=3.0.0a7\" contains \"3.0.0a8\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e=3.0.0a7", + "version": "3.0.0a8" + }, + "expected_output": true + }, + { + "description": "packaging range \"\u003c=2\" contains \"2.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003c=2", + "version": "2.0" + }, + "expected_output": true + }, + { + "description": "packaging range \"\u003c=2.0\" contains \"2.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003c=2.0", + "version": "2.0" + }, + "expected_output": true + }, + { + "description": "packaging range \"\u003c=2.0.0\" contains \"2.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003c=2.0.0", + "version": "2.0" + }, + "expected_output": true + }, + { + "description": "packaging range \"\u003c=2\" contains \"2.0.dev1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003c=2", + "version": "2.0.dev1" + }, + "expected_output": true + }, + { + "description": "packaging range \"\u003c=2\" contains \"2.0a1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003c=2", + "version": "2.0a1" + }, + "expected_output": true + }, + { + "description": "packaging range \"\u003c=2\" contains \"2.0a1.dev1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003c=2", + "version": "2.0a1.dev1" + }, + "expected_output": true + }, + { + "description": "packaging range \"\u003c=2\" contains \"2.0b1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003c=2", + "version": "2.0b1" + }, + "expected_output": true + }, + { + "description": "packaging range \"\u003c=2\" contains \"2.0b1.post1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003c=2", + "version": "2.0b1.post1" + }, + "expected_output": true + }, + { + "description": "packaging range \"\u003c=2\" contains \"2.0c1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003c=2", + "version": "2.0c1" + }, + "expected_output": true + }, + { + "description": "packaging range \"\u003c=2\" contains \"2.0c1.post1.dev1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003c=2", + "version": "2.0c1.post1.dev1" + }, + "expected_output": true + }, + { + "description": "packaging range \"\u003c=2\" contains \"2.0rc1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003c=2", + "version": "2.0rc1" + }, + "expected_output": true + }, + { + "description": "packaging range \"\u003c=2\" contains \"1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003c=2", + "version": "1" + }, + "expected_output": true + }, + { + "description": "packaging range \"\u003c=3.0.0a8\" contains \"3.0.0a7\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003c=3.0.0a8", + "version": "3.0.0a7" + }, + "expected_output": true + }, + { + "description": "packaging range \"\u003e2\" contains \"3\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e2", + "version": "3" + }, + "expected_output": true + }, + { + "description": "packaging range \"\u003e2.0\" contains \"2.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e2.0", + "version": "2.1" + }, + "expected_output": true + }, + { + "description": "packaging range \"\u003e2\" contains \"2.0.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e2", + "version": "2.0.1" + }, + "expected_output": true + }, + { + "description": "packaging range \"\u003e2\" contains \"2.1.post1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e2", + "version": "2.1.post1" + }, + "expected_output": true + }, + { + "description": "packaging range \"\u003e2\" contains \"2.1+local.version\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e2", + "version": "2.1+local.version" + }, + "expected_output": true + }, + { + "description": "packaging range \"\u003e3.0.0a7\" contains \"3.0.0a8\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e3.0.0a7", + "version": "3.0.0a8" + }, + "expected_output": true + }, + { + "description": "packaging range \"\u003c2\" contains \"1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003c2", + "version": "1" + }, + "expected_output": true + }, + { + "description": "packaging range \"\u003c2.1\" contains \"2.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003c2.1", + "version": "2.0" + }, + "expected_output": true + }, + { + "description": "packaging range \"\u003c2.1\" contains \"2.0.dev0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003c2.1", + "version": "2.0.dev0" + }, + "expected_output": true + }, + { + "description": "packaging range \"\u003c3.0.0a8\" contains \"3.0.0a7\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003c3.0.0a8", + "version": "3.0.0a7" + }, + "expected_output": true + }, + { + "description": "packaging range \"~=1.0\" contains \"1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e=1.0|\u003c2", + "version": "1" + }, + "expected_output": true + }, + { + "description": "packaging range \"~=1.0\" contains \"1.0.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e=1.0|\u003c2", + "version": "1.0.1" + }, + "expected_output": true + }, + { + "description": "packaging range \"~=1.0\" contains \"1.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e=1.0|\u003c2", + "version": "1.1" + }, + "expected_output": true + }, + { + "description": "packaging range \"~=1.0\" contains \"1.9999999\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e=1.0|\u003c2", + "version": "1.9999999" + }, + "expected_output": true + }, + { + "description": "packaging range \"~=1.0a1\" contains \"1.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e=1.0a1|\u003c2", + "version": "1.1" + }, + "expected_output": true + }, + { + "description": "packaging range \"~=2022.01.01\" contains \"2022.01.01\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e=2022.01.01|\u003c2022.2", + "version": "2022.01.01" + }, + "expected_output": true + }, + { + "description": "packaging range \"~=2!1.0\" contains \"2!1.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e=2%211.0|\u003c2%212", + "version": "2!1.0" + }, + "expected_output": true + }, + { + "description": "packaging range \"==2!1.*\" contains \"2!1.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e=2%211.dev0|\u003c2%212.dev0", + "version": "2!1.0" + }, + "expected_output": true + }, + { + "description": "packaging range \"==2!1.0\" contains \"2!1.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/2%211.0", + "version": "2!1.0" + }, + "expected_output": true + }, + { + "description": "packaging range \"!=1.0\" contains \"2!1.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/!=1.0", + "version": "2!1.0" + }, + "expected_output": true + }, + { + "description": "packaging range \"==2!1.0.0.0.*\" contains \"2!1.0.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e=2%211.0.0.0.dev0|\u003c2%211.0.0.1.dev0", + "version": "2!1.0.0" + }, + "expected_output": true + }, + { + "description": "packaging range \"==2!1.0.*\" contains \"2!1.0.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e=2%211.0.dev0|\u003c2%211.1.dev0", + "version": "2!1.0.0" + }, + "expected_output": true + }, + { + "description": "packaging range \"==2!1.*\" contains \"2!1.0.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e=2%211.dev0|\u003c2%212.dev0", + "version": "2!1.0.0" + }, + "expected_output": true + }, + { + "description": "packaging range \"!=2!1.0\" contains \"1.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/!=2%211.0", + "version": "1.0" + }, + "expected_output": true + }, + { + "description": "packaging range \"\u003c=2!0.1\" contains \"1.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003c=2%210.1", + "version": "1.0" + }, + "expected_output": true + }, + { + "description": "packaging range \"\u003e=2.0\" contains \"2!1.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e=2.0", + "version": "2!1.0" + }, + "expected_output": true + }, + { + "description": "packaging range \"\u003c2!0.1\" contains \"1.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003c2%210.1", + "version": "1.0" + }, + "expected_output": true + }, + { + "description": "packaging range \"\u003e2.0\" contains \"2!1.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e2.0", + "version": "2!1.0" + }, + "expected_output": true + }, + { + "description": "packaging range \"\u003e2.0dev\" contains \"2.0.5\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e2.0dev", + "version": "2.0.5" + }, + "expected_output": true + }, + { + "description": "packaging range \"\u003e1.0.dev1\" contains \"1.0+local\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e1.0.dev1", + "version": "1.0+local" + }, + "expected_output": true + }, + { + "description": "packaging range \"\u003e4.1.0a2.dev1234\" contains \"4.1.0a2.dev1235+local\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e4.1.0a2.dev1234", + "version": "4.1.0a2.dev1235+local" + }, + "expected_output": true + }, + { + "description": "packaging range \"\u003e1.0a1\" contains \"1.0a2+local\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e1.0a1", + "version": "1.0a2+local" + }, + "expected_output": true + }, + { + "description": "packaging range \"\u003e1.0b1\" contains \"1.0b2+local\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e1.0b1", + "version": "1.0b2+local" + }, + "expected_output": true + }, + { + "description": "packaging range \"\u003e1.0rc1\" contains \"1.0rc2+local\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e1.0rc1", + "version": "1.0rc2+local" + }, + "expected_output": true + }, + { + "description": "packaging range \"\u003e1.0.post1\" contains \"1.0.post2+local\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e1.0.post1", + "version": "1.0.post2+local" + }, + "expected_output": true + }, + { + "description": "packaging range \"\u003e1.0.dev1\" contains \"1.0.dev2+local\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e1.0.dev1", + "version": "1.0.dev2+local" + }, + "expected_output": true + }, + { + "description": "packaging range \"\u003e1.0a1.dev1\" contains \"1.0a1.dev2+local\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e1.0a1.dev1", + "version": "1.0a1.dev2+local" + }, + "expected_output": true + }, + { + "description": "packaging range \"\u003e1.0.post1.dev1\" contains \"1.0.post1.dev2+local\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e1.0.post1.dev1", + "version": "1.0.post1.dev2+local" + }, + "expected_output": true + }, + { + "description": "packaging range \"==2\" excludes \"2.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/2", + "version": "2.1" + }, + "expected_output": false + }, + { + "description": "packaging range \"==2.0\" excludes \"2.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/2.0", + "version": "2.1" + }, + "expected_output": false + }, + { + "description": "packaging range \"==2.0.0\" excludes \"2.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/2.0.0", + "version": "2.1" + }, + "expected_output": false + }, + { + "description": "packaging range \"==2.0+deadbeef\" excludes \"2.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/2.0+deadbeef", + "version": "2.0" + }, + "expected_output": false + }, + { + "description": "packaging range \"==3.*\" excludes \"2.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e=3.dev0|\u003c4.dev0", + "version": "2.0" + }, + "expected_output": false + }, + { + "description": "packaging range \"==2.0.*\" excludes \"2.1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e=2.0.dev0|\u003c2.1.dev0", + "version": "2.1" + }, + "expected_output": false + }, + { + "description": "packaging range \"==2.0.0.*\" excludes \"3\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e=2.0.0.dev0|\u003c2.0.1.dev0", + "version": "3" + }, + "expected_output": false + }, + { + "description": "packaging range \"==2.0.*\" excludes \"2.1.0.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e=2.0.dev0|\u003c2.1.dev0", + "version": "2.1.0.0" + }, + "expected_output": false + }, + { + "description": "packaging range \"!=2\" excludes \"2.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/!=2", + "version": "2.0" + }, + "expected_output": false + }, + { + "description": "packaging range \"!=2.0\" excludes \"2.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/!=2.0", + "version": "2.0" + }, + "expected_output": false + }, + { + "description": "packaging range \"!=2.0.0\" excludes \"2.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/!=2.0.0", + "version": "2.0" + }, + "expected_output": false + }, + { + "description": "packaging range \"!=2\" excludes \"2.0+deadbeef\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/!=2", + "version": "2.0+deadbeef" + }, + "expected_output": false + }, + { + "description": "packaging range \"!=2.0\" excludes \"2.0+deadbeef\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/!=2.0", + "version": "2.0+deadbeef" + }, + "expected_output": false + }, + { + "description": "packaging range \"!=2.0.0\" excludes \"2.0+deadbeef\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/!=2.0.0", + "version": "2.0+deadbeef" + }, + "expected_output": false + }, + { + "description": "packaging range \"!=2+deadbeef\" excludes \"2.0+deadbeef\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/!=2+deadbeef", + "version": "2.0+deadbeef" + }, + "expected_output": false + }, + { + "description": "packaging range \"!=2.0+deadbeef\" excludes \"2.0+deadbeef\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/!=2.0+deadbeef", + "version": "2.0+deadbeef" + }, + "expected_output": false + }, + { + "description": "packaging range \"!=2.0.0+deadbeef\" excludes \"2.0+deadbeef\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/!=2.0.0+deadbeef", + "version": "2.0+deadbeef" + }, + "expected_output": false + }, + { + "description": "packaging range \"!=2.0.0+deadbeef.00\" excludes \"2.0+deadbeef.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/!=2.0.0+deadbeef.00", + "version": "2.0+deadbeef.0" + }, + "expected_output": false + }, + { + "description": "packaging range \"!=2.*\" excludes \"2.dev1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003c2.dev0|\u003e=3.dev0", + "version": "2.dev1" + }, + "expected_output": false + }, + { + "description": "packaging range \"!=2.*\" excludes \"2a1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003c2.dev0|\u003e=3.dev0", + "version": "2a1" + }, + "expected_output": false + }, + { + "description": "packaging range \"!=2.*\" excludes \"2a1.post1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003c2.dev0|\u003e=3.dev0", + "version": "2a1.post1" + }, + "expected_output": false + }, + { + "description": "packaging range \"!=2.*\" excludes \"2b1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003c2.dev0|\u003e=3.dev0", + "version": "2b1" + }, + "expected_output": false + }, + { + "description": "packaging range \"!=2.*\" excludes \"2b1.dev1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003c2.dev0|\u003e=3.dev0", + "version": "2b1.dev1" + }, + "expected_output": false + }, + { + "description": "packaging range \"!=2.*\" excludes \"2c1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003c2.dev0|\u003e=3.dev0", + "version": "2c1" + }, + "expected_output": false + }, + { + "description": "packaging range \"!=2.*\" excludes \"2c1.post1.dev1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003c2.dev0|\u003e=3.dev0", + "version": "2c1.post1.dev1" + }, + "expected_output": false + }, + { + "description": "packaging range \"!=2.0.*\" excludes \"2c1.post1.dev1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003c2.0.dev0|\u003e=2.1.dev0", + "version": "2c1.post1.dev1" + }, + "expected_output": false + }, + { + "description": "packaging range \"!=2.*\" excludes \"2rc1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003c2.dev0|\u003e=3.dev0", + "version": "2rc1" + }, + "expected_output": false + }, + { + "description": "packaging range \"!=2.0.*\" excludes \"2rc1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003c2.0.dev0|\u003e=2.1.dev0", + "version": "2rc1" + }, + "expected_output": false + }, + { + "description": "packaging range \"!=2.*\" excludes \"2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003c2.dev0|\u003e=3.dev0", + "version": "2" + }, + "expected_output": false + }, + { + "description": "packaging range \"!=2.0.*\" excludes \"2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003c2.0.dev0|\u003e=2.1.dev0", + "version": "2" + }, + "expected_output": false + }, + { + "description": "packaging range \"!=2.0.0.*\" excludes \"2\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003c2.0.0.dev0|\u003e=2.0.1.dev0", + "version": "2" + }, + "expected_output": false + }, + { + "description": "packaging range \"!=2.*\" excludes \"2.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003c2.dev0|\u003e=3.dev0", + "version": "2.0" + }, + "expected_output": false + }, + { + "description": "packaging range \"!=2.*\" excludes \"2.0.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003c2.dev0|\u003e=3.dev0", + "version": "2.0.0" + }, + "expected_output": false + }, + { + "description": "packaging range \"!=2.0.*\" excludes \"2.0.0.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003c2.0.dev0|\u003e=2.1.dev0", + "version": "2.0.0.0" + }, + "expected_output": false + }, + { + "description": "packaging range \"\u003e=2\" excludes \"2.0.dev1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e=2", + "version": "2.0.dev1" + }, + "expected_output": false + }, + { + "description": "packaging range \"\u003e=2\" excludes \"2.0a1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e=2", + "version": "2.0a1" + }, + "expected_output": false + }, + { + "description": "packaging range \"\u003e=2\" excludes \"2.0a1.dev1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e=2", + "version": "2.0a1.dev1" + }, + "expected_output": false + }, + { + "description": "packaging range \"\u003e=2\" excludes \"2.0b1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e=2", + "version": "2.0b1" + }, + "expected_output": false + }, + { + "description": "packaging range \"\u003e=2\" excludes \"2.0b1.post1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e=2", + "version": "2.0b1.post1" + }, + "expected_output": false + }, + { + "description": "packaging range \"\u003e=2\" excludes \"2.0c1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e=2", + "version": "2.0c1" + }, + "expected_output": false + }, + { + "description": "packaging range \"\u003e=2\" excludes \"2.0c1.post1.dev1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e=2", + "version": "2.0c1.post1.dev1" + }, + "expected_output": false + }, + { + "description": "packaging range \"\u003e=2\" excludes \"2.0rc1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e=2", + "version": "2.0rc1" + }, + "expected_output": false + }, + { + "description": "packaging range \"\u003e=2\" excludes \"1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e=2", + "version": "1" + }, + "expected_output": false + }, + { + "description": "packaging range \"\u003c=2\" excludes \"2.0.post1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003c=2", + "version": "2.0.post1" + }, + "expected_output": false + }, + { + "description": "packaging range \"\u003c=2\" excludes \"2.0.post1.dev1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003c=2", + "version": "2.0.post1.dev1" + }, + "expected_output": false + }, + { + "description": "packaging range \"\u003c=2\" excludes \"3\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003c=2", + "version": "3" + }, + "expected_output": false + }, + { + "description": "packaging range \"\u003e2\" excludes \"1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e2", + "version": "1" + }, + "expected_output": false + }, + { + "description": "packaging range \"\u003e2\" excludes \"2.0.dev1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e2", + "version": "2.0.dev1" + }, + "expected_output": false + }, + { + "description": "packaging range \"\u003e2\" excludes \"2.0a1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e2", + "version": "2.0a1" + }, + "expected_output": false + }, + { + "description": "packaging range \"\u003e2\" excludes \"2.0a1.post1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e2", + "version": "2.0a1.post1" + }, + "expected_output": false + }, + { + "description": "packaging range \"\u003e2\" excludes \"2.0b1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e2", + "version": "2.0b1" + }, + "expected_output": false + }, + { + "description": "packaging range \"\u003e2\" excludes \"2.0b1.dev1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e2", + "version": "2.0b1.dev1" + }, + "expected_output": false + }, + { + "description": "packaging range \"\u003e2\" excludes \"2.0c1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e2", + "version": "2.0c1" + }, + "expected_output": false + }, + { + "description": "packaging range \"\u003e2\" excludes \"2.0c1.post1.dev1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e2", + "version": "2.0c1.post1.dev1" + }, + "expected_output": false + }, + { + "description": "packaging range \"\u003e2\" excludes \"2.0rc1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e2", + "version": "2.0rc1" + }, + "expected_output": false + }, + { + "description": "packaging range \"\u003e2\" excludes \"2.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e2", + "version": "2.0" + }, + "expected_output": false + }, + { + "description": "packaging range \"\u003e2\" excludes \"2.0.post1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e2", + "version": "2.0.post1" + }, + "expected_output": false + }, + { + "description": "packaging range \"\u003e2\" excludes \"2.0.post1.dev1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e2", + "version": "2.0.post1.dev1" + }, + "expected_output": false + }, + { + "description": "packaging range \"\u003e2\" excludes \"2.0+local.version\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e2", + "version": "2.0+local.version" + }, + "expected_output": false + }, + { + "description": "packaging range \"\u003e4.1.0a2.dev1234\" excludes \"4.1.0a2.dev1234+local\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e4.1.0a2.dev1234", + "version": "4.1.0a2.dev1234+local" + }, + "expected_output": false + }, + { + "description": "packaging range \"\u003e1.0a1\" excludes \"1.0a1+local\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e1.0a1", + "version": "1.0a1+local" + }, + "expected_output": false + }, + { + "description": "packaging range \"\u003e1.0b1\" excludes \"1.0b1+local\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e1.0b1", + "version": "1.0b1+local" + }, + "expected_output": false + }, + { + "description": "packaging range \"\u003e1.0rc1\" excludes \"1.0rc1+local\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e1.0rc1", + "version": "1.0rc1+local" + }, + "expected_output": false + }, + { + "description": "packaging range \"\u003e1.0.post1\" excludes \"1.0.post1+local\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e1.0.post1", + "version": "1.0.post1+local" + }, + "expected_output": false + }, + { + "description": "packaging range \"\u003e1.0.dev1\" excludes \"1.0.dev1+local\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e1.0.dev1", + "version": "1.0.dev1+local" + }, + "expected_output": false + }, + { + "description": "packaging range \"\u003e1.0a1.dev1\" excludes \"1.0a1.dev1+local\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e1.0a1.dev1", + "version": "1.0a1.dev1+local" + }, + "expected_output": false + }, + { + "description": "packaging range \"\u003e1.0.post1.dev1\" excludes \"1.0.post1.dev1+local\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e1.0.post1.dev1", + "version": "1.0.post1.dev1+local" + }, + "expected_output": false + }, + { + "description": "packaging range \"\u003c2\" excludes \"2.0.dev1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003c2", + "version": "2.0.dev1" + }, + "expected_output": false + }, + { + "description": "packaging range \"\u003c2\" excludes \"2.0a1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003c2", + "version": "2.0a1" + }, + "expected_output": false + }, + { + "description": "packaging range \"\u003c2\" excludes \"2.0a1.post1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003c2", + "version": "2.0a1.post1" + }, + "expected_output": false + }, + { + "description": "packaging range \"\u003c2\" excludes \"2.0b1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003c2", + "version": "2.0b1" + }, + "expected_output": false + }, + { + "description": "packaging range \"\u003c2\" excludes \"2.0b2.dev1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003c2", + "version": "2.0b2.dev1" + }, + "expected_output": false + }, + { + "description": "packaging range \"\u003c2\" excludes \"2.0c1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003c2", + "version": "2.0c1" + }, + "expected_output": false + }, + { + "description": "packaging range \"\u003c2\" excludes \"2.0c1.post1.dev1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003c2", + "version": "2.0c1.post1.dev1" + }, + "expected_output": false + }, + { + "description": "packaging range \"\u003c2\" excludes \"2.0rc1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003c2", + "version": "2.0rc1" + }, + "expected_output": false + }, + { + "description": "packaging range \"\u003c2\" excludes \"2.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003c2", + "version": "2.0" + }, + "expected_output": false + }, + { + "description": "packaging range \"\u003c2\" excludes \"2.post1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003c2", + "version": "2.post1" + }, + "expected_output": false + }, + { + "description": "packaging range \"\u003c2\" excludes \"2.post1.dev1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003c2", + "version": "2.post1.dev1" + }, + "expected_output": false + }, + { + "description": "packaging range \"\u003c2\" excludes \"3\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003c2", + "version": "3" + }, + "expected_output": false + }, + { + "description": "packaging range \"~=1.0\" excludes \"2.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e=1.0|\u003c2", + "version": "2.0" + }, + "expected_output": false + }, + { + "description": "packaging range \"~=1.0.0\" excludes \"1.1.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e=1.0.0|\u003c1.1", + "version": "1.1.0" + }, + "expected_output": false + }, + { + "description": "packaging range \"~=1.0.0\" excludes \"1.1.post1\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e=1.0.0|\u003c1.1", + "version": "1.1.post1" + }, + "expected_output": false + }, + { + "description": "packaging range \"~=2!1.0\" excludes \"1.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e=2%211.0|\u003c2%212", + "version": "1.0" + }, + "expected_output": false + }, + { + "description": "packaging range \"~=1.0\" excludes \"2!1.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e=1.0|\u003c2", + "version": "2!1.0" + }, + "expected_output": false + }, + { + "description": "packaging range \"==1.0\" excludes \"2!1.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/1.0", + "version": "2!1.0" + }, + "expected_output": false + }, + { + "description": "packaging range \"==2!1.0\" excludes \"1.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/2%211.0", + "version": "1.0" + }, + "expected_output": false + }, + { + "description": "packaging range \"==1.0.0.*\" excludes \"2!1.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e=1.0.0.dev0|\u003c1.0.1.dev0", + "version": "2!1.0" + }, + "expected_output": false + }, + { + "description": "packaging range \"==2!1.0.0.*\" excludes \"1.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e=2%211.0.0.dev0|\u003c2%211.0.1.dev0", + "version": "1.0" + }, + "expected_output": false + }, + { + "description": "packaging range \"==1.*\" excludes \"2!1.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e=1.dev0|\u003c2.dev0", + "version": "2!1.0" + }, + "expected_output": false + }, + { + "description": "packaging range \"==2!1.*\" excludes \"1.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/\u003e=2%211.dev0|\u003c2%212.dev0", + "version": "1.0" + }, + "expected_output": false + }, + { + "description": "packaging range \"!=2!1.0\" excludes \"2!1.0\".", + "test_group": "recommended", + "test_type": "containment", + "input": { + "vers": "vers:pypi/!=2%211.0", + "version": "2!1.0" + }, + "expected_output": false + } + ] +} diff --git a/tools/harvest/extract.go b/tools/harvest/extract.go index cad7c22..00e1705 100644 --- a/tools/harvest/extract.go +++ b/tools/harvest/extract.go @@ -185,6 +185,346 @@ func extractGo(files map[string]string) ([]comparison, error) { return requireComparisons(items) } +func extractNodeSemverRanges(files map[string]string) ([]nativeRangeAssertion, error) { + row := regexp.MustCompile(`^\s*\[\s*'([^']*)'\s*,\s*'([^']*)'(?:\s*,\s*(.*?))?\s*\],?(?:\s*//.*)?$`) + var assertions []nativeRangeAssertion + for _, source := range []struct { + filename string + contains bool + }{ + {"test/fixtures/range-include.js", true}, + {"test/fixtures/range-exclude.js", false}, + } { + for _, line := range strings.Split(files[source.filename], "\n") { + match := row.FindStringSubmatch(line) + if match == nil || !supportedNodeSemverOptions(match[3]) { + continue + } + assertions = append(assertions, nativeRangeAssertion{ + nativeRange: decodeJavaScriptString(match[1]), + version: decodeJavaScriptString(match[2]), + contains: source.contains, + }) + } + } + return requireRangeAssertions(assertions) +} + +func decodeJavaScriptString(value string) string { + decoded, err := strconv.Unquote(`"` + strings.ReplaceAll(value, `"`, `\"`) + `"`) + if err != nil { + return value + } + return decoded +} + +func supportedNodeSemverOptions(options string) bool { + switch strings.TrimSpace(options) { + case "", "{}", "{ loose: false }", "{ loose: null }", "{ loose: 0 }", "{ loose: undefined }": + return true + default: + return false + } +} + +func extractPyPIRanges(files map[string]string) ([]nativeRangeAssertion, error) { + content := files["tests/test_specifiers.py"] + start := strings.Index(content, `("version", "spec_str", "expected")`) + if start < 0 { + return nil, fmt.Errorf("specifier containment table not found") + } + end := strings.Index(content[start:], "def test_specifiers(") + if end < 0 { + return nil, fmt.Errorf("specifier containment table is not closed") + } + block := content[start : start+end] + falseStart := strings.Index(block, "(v, s, False)") + if falseStart < 0 { + return nil, fmt.Errorf("false specifier cases not found") + } + pair := regexp.MustCompile(`\("([^"]*)",\s*"([^"]*)"\)`) + assertions := make([]nativeRangeAssertion, 0) + for _, group := range []struct { + content string + contains bool + }{ + {block[:falseStart], true}, + {block[falseStart:], false}, + } { + for _, match := range pair.FindAllStringSubmatch(group.content, -1) { + assertions = append(assertions, nativeRangeAssertion{ + nativeRange: match[2], version: match[1], contains: group.contains, + }) + } + } + return requireRangeAssertions(assertions) +} + +func extractRubyGemsRanges(files map[string]string) ([]nativeRangeAssertion, error) { + content := files["test/rubygems/test_gem_requirement.rb"] + row := regexp.MustCompile(`(?m)^\s*(assert|refute)_satisfied_by\s+"([^"]*)",\s+"([^"]*)"`) + assertions := make([]nativeRangeAssertion, 0) + for _, match := range row.FindAllStringSubmatch(content, -1) { + assertions = append(assertions, nativeRangeAssertion{ + nativeRange: match[3], version: match[2], contains: match[1] == "assert", + }) + } + return requireRangeAssertions(assertions) +} + +func extractComposerRanges(files map[string]string) ([]nativeRangeAssertion, error) { + content := files["tests/VersionParserTest.php"] + rowStart := regexp.MustCompile(`array\('([^']*)'`) + constraint := regexp.MustCompile(`new Constraint\('([^']+)',\s*'([^']+)'\)`) + assertions := make([]nativeRangeAssertion, 0) + for _, provider := range []string{ + "simpleConstraints", "wildcardConstraints", "tildeConstraints", "caretConstraints", "hyphenConstraints", + } { + block := functionBlock(content, "function "+provider+"()") + for _, line := range strings.Split(block, "\n") { + input := rowStart.FindStringSubmatch(line) + if input == nil { + continue + } + for _, match := range constraint.FindAllStringSubmatch(line, -1) { + assertions = append(assertions, nativeRangeAssertion{ + nativeRange: input[1], version: match[2], contains: composerConstraintContainsBound(match[1]), + }) + } + } + } + return requireRangeAssertions(assertions) +} + +func composerConstraintContainsBound(operator string) bool { + switch operator { + case "=", "==", ">=", "<=": + return true + default: + return false + } +} + +func extractPubRanges(files map[string]string) ([]nativeRangeAssertion, error) { + content := files["pkgs/pub_semver/test/version_constraint_test.dart"] + assignment := regexp.MustCompile(`var constraint = VersionConstraint\.parse\('([^']+)'\);`) + matches := assignment.FindAllStringSubmatchIndex(content, -1) + assertions := make([]nativeRangeAssertion, 0) + version := regexp.MustCompile(`Version\.parse\('([^']+)'\)`) + for index, match := range matches { + end := len(content) + if index+1 < len(matches) { + end = matches[index+1][0] + } + if testEnd := strings.Index(content[match[1]:end], "\n test("); testEnd >= 0 { + end = match[1] + testEnd + } + block := content[match[1]:end] + nativeRange := content[match[2]:match[3]] + for _, call := range balancedCalls(block, "allows(") { + for _, parsed := range version.FindAllStringSubmatch(call, -1) { + assertions = append(assertions, nativeRangeAssertion{ + nativeRange: nativeRange, version: parsed[1], contains: true, + }) + } + } + for _, call := range balancedCalls(block, "doesNotAllow(") { + for _, parsed := range version.FindAllStringSubmatch(call, -1) { + assertions = append(assertions, nativeRangeAssertion{ + nativeRange: nativeRange, version: parsed[1], contains: false, + }) + } + } + } + constructorAssertions, err := extractPubVersionRangeAssertions(files) + if err != nil { + return nil, err + } + assertions = append(assertions, constructorAssertions...) + return requireRangeAssertions(assertions) +} + +func extractPubVersionRangeAssertions(files map[string]string) ([]nativeRangeAssertion, error) { + content := files["pkgs/pub_semver/test/version_range_test.dart"] + utilityContent := files["pkgs/pub_semver/test/utils.dart"] + constant := regexp.MustCompile(`final (v\d+) = Version\.parse\('([^']+)'\);`) + versions := make(map[string]string) + for _, match := range constant.FindAllStringSubmatch(utilityContent, -1) { + versions[match[1]] = match[2] + } + assignment := regexp.MustCompile(`(?s)var range = VersionRange\((.*?)\);`) + matches := assignment.FindAllStringSubmatchIndex(content, -1) + version := regexp.MustCompile(`Version\.parse\('([^']+)'\)`) + assertions := make([]nativeRangeAssertion, 0) + for index, match := range matches { + end := len(content) + if index+1 < len(matches) { + end = matches[index+1][0] + } + if testEnd := strings.Index(content[match[1]:end], "\n test("); testEnd >= 0 { + end = match[1] + testEnd + } + nativeRange, err := pubConstructorRange(content[match[2]:match[3]], versions) + if err != nil { + return nil, err + } + block := content[match[1]:end] + for _, call := range balancedCalls(block, "allows(") { + for _, parsed := range version.FindAllStringSubmatch(call, -1) { + assertions = append(assertions, nativeRangeAssertion{ + nativeRange: nativeRange, version: parsed[1], contains: true, + }) + } + } + for _, call := range balancedCalls(block, "doesNotAllow(") { + for _, parsed := range version.FindAllStringSubmatch(call, -1) { + assertions = append(assertions, nativeRangeAssertion{ + nativeRange: nativeRange, version: parsed[1], contains: false, + }) + } + } + } + return assertions, nil +} + +func pubConstructorRange(arguments string, versions map[string]string) (string, error) { + bound := regexp.MustCompile(`(?:min|max):\s*(Version\.parse\('[^']+'\)|v\d+)`) + var minimum, maximum string + for _, match := range bound.FindAllStringSubmatch(arguments, -1) { + value, err := pubVersionExpression(match[1], versions) + if err != nil { + return "", err + } + if strings.HasPrefix(strings.TrimSpace(match[0]), "min:") { + minimum = value + } else { + maximum = value + } + } + var constraints []string + if minimum != "" { + operator := ">" + if strings.Contains(arguments, "includeMin: true") { + operator = ">=" + } + constraints = append(constraints, operator+minimum) + } + if maximum != "" { + operator := "<" + if strings.Contains(arguments, "includeMax: true") { + operator = "<=" + } + constraints = append(constraints, operator+maximum) + } + if len(constraints) == 0 { + return "any", nil + } + return strings.Join(constraints, " "), nil +} + +func pubVersionExpression(expression string, versions map[string]string) (string, error) { + expression = strings.TrimSpace(expression) + if strings.HasPrefix(expression, "Version.parse('") { + return strings.TrimSuffix(strings.TrimPrefix(expression, "Version.parse('"), "')"), nil + } + if version, ok := versions[expression]; ok { + return version, nil + } + return "", fmt.Errorf("unknown Pub version expression %q", expression) +} + +func extractCargoRanges(files map[string]string) ([]nativeRangeAssertion, error) { + content := files["tests/test_version_req.rs"] + rangeStart := regexp.MustCompile(`let ref r = req\("([^"]*)"\);`) + assertion := regexp.MustCompile(`(?s)assert_match_(all|none)\(\s*r,\s*&\[(.*?)\]\s*,?\s*\);`) + value := regexp.MustCompile(`"([^"]+)"`) + assertions := make([]nativeRangeAssertion, 0) + ranges := rangeStart.FindAllStringSubmatchIndex(content, -1) + for index, item := range ranges { + end := len(content) + if index+1 < len(ranges) { + end = ranges[index+1][0] + } + if functionEnd := strings.Index(content[item[1]:end], "\n}"); functionEnd >= 0 { + end = item[1] + functionEnd + } + block := content[item[1]:end] + nativeRange := content[item[2]:item[3]] + for _, match := range assertion.FindAllStringSubmatch(block, -1) { + for _, version := range value.FindAllStringSubmatch(match[2], -1) { + assertions = append(assertions, nativeRangeAssertion{ + nativeRange: nativeRange, version: version[1], contains: match[1] == "all", + }) + } + } + } + return requireRangeAssertions(assertions) +} + +func extractMavenRanges(files map[string]string) ([]nativeRangeAssertion, error) { + content := files["compat/maven-artifact/src/test/java/org/apache/maven/artifact/versioning/VersionRangeTest.java"] + assignment := regexp.MustCompile(`(?:VersionRange\s+)?range\s*=\s*VersionRange\.createFromVersionSpec\("([^"]+)"\);`) + containment := regexp.MustCompile(`assert(True|False)\(range\.containsVersion\(new DefaultArtifactVersion\("([^"]+)"\)\)\);`) + assertions := make([]nativeRangeAssertion, 0) + currentRange := "" + for _, line := range strings.Split(content, "\n") { + if match := assignment.FindStringSubmatch(line); match != nil { + currentRange = match[1] + } + if match := containment.FindStringSubmatch(line); match != nil && currentRange != "" { + assertions = append(assertions, nativeRangeAssertion{ + nativeRange: currentRange, version: match[2], contains: match[1] == "True", + }) + } + } + return requireRangeAssertions(assertions) +} + +func balancedCalls(content, marker string) []string { + var calls []string + for offset := 0; offset < len(content); { + relative := strings.Index(content[offset:], marker) + if relative < 0 { + break + } + start := offset + relative + if start > 0 && content[start-1] == '.' { + offset = start + len(marker) + continue + } + open := start + len(marker) - 1 + depth := 0 + end := -1 + for index := open; index < len(content); index++ { + switch content[index] { + case '(': + depth++ + case ')': + depth-- + if depth == 0 { + end = index + } + } + if end >= 0 { + break + } + } + if end < 0 { + break + } + calls = append(calls, content[open+1:end]) + offset = end + 1 + } + return calls +} + +func requireRangeAssertions(assertions []nativeRangeAssertion) ([]nativeRangeAssertion, error) { + if len(assertions) == 0 { + return nil, fmt.Errorf("no native range assertions found") + } + return assertions, nil +} + func quotedListAfter(content, marker string) ([]string, error) { start := strings.Index(content, marker) if start < 0 { diff --git a/tools/harvest/extract_test.go b/tools/harvest/extract_test.go index 5650406..142c9fc 100644 --- a/tools/harvest/extract_test.go +++ b/tools/harvest/extract_test.go @@ -94,6 +94,161 @@ func TestBuildTestFileNormalizesResultsAndDeduplicates(t *testing.T) { } } +func TestRangeExtractors(t *testing.T) { + tests := []struct { + name string + extract func(map[string]string) ([]nativeRangeAssertion, error) + files map[string]string + want []nativeRangeAssertion + }{ + { + name: "node-semver", extract: extractNodeSemverRanges, + files: map[string]string{ + "test/fixtures/range-include.js": "['^1.0.0', '1.2.0']\n['<\\t2.0.0', '0.2.9']\n['*', '1.0.0-a', { includePrerelease: true }]\n", + "test/fixtures/range-exclude.js": "['^1.0.0', '2.0.0']\n", + }, + want: []nativeRangeAssertion{ + {nativeRange: "^1.0.0", version: "1.2.0", contains: true}, + {nativeRange: "<\t2.0.0", version: "0.2.9", contains: true}, + {nativeRange: "^1.0.0", version: "2.0.0", contains: false}, + }, + }, + { + name: "pypi", extract: extractPyPIRanges, + files: map[string]string{"tests/test_specifiers.py": ` +("version", "spec_str", "expected") +[(v, s, True) for v, s in [("1.2", ">=1")]] ++ [(v, s, False) for v, s in [("0.9", ">=1")]] +def test_specifiers(self): +`}, + want: []nativeRangeAssertion{ + {nativeRange: ">=1", version: "1.2", contains: true}, + {nativeRange: ">=1", version: "0.9", contains: false}, + }, + }, + { + name: "rubygems", extract: extractRubyGemsRanges, + files: map[string]string{"test/rubygems/test_gem_requirement.rb": ` +assert_satisfied_by "1.5", "~> 1.4" +refute_satisfied_by "2.0", "~> 1.4" +`}, + want: []nativeRangeAssertion{ + {nativeRange: "~> 1.4", version: "1.5", contains: true}, + {nativeRange: "~> 1.4", version: "2.0", contains: false}, + }, + }, + { + name: "composer", extract: extractComposerRanges, + files: map[string]string{"tests/VersionParserTest.php": ` +function simpleConstraints() + { + array('>=1.2', new Constraint('>=', '1.2.0.0-dev')), + array('<2', new Constraint('<', '2.0.0.0-dev')), + } +`}, + want: []nativeRangeAssertion{ + {nativeRange: ">=1.2", version: "1.2.0.0-dev", contains: true}, + {nativeRange: "<2", version: "2.0.0.0-dev", contains: false}, + }, + }, + { + name: "pub", extract: extractPubRanges, + files: map[string]string{ + "pkgs/pub_semver/test/version_constraint_test.dart": ` +var constraint = VersionConstraint.parse('>=1.2.3'); +expect(constraint, allows(Version.parse('1.2.3'), Version.parse('2.0.0'))); +expect(constraint, doesNotAllow(Version.parse('1.2.2'))); +expect(constraint.allows(Version.parse('3.0.0')), isFalse); + test('next', () { +expect(constraint, allows(Version.parse('4.0.0'))); + `, + "pkgs/pub_semver/test/version_range_test.dart": ` +var range = VersionRange(min: v123, includeMin: true, + max: Version.parse('2.0.0')); +expect(range, allows(Version.parse('1.2.3'))); +expect(range, doesNotAllow(Version.parse('2.0.0'))); +`, + "pkgs/pub_semver/test/utils.dart": "final v123 = Version.parse('1.2.3');\n", + }, + want: []nativeRangeAssertion{ + {nativeRange: ">=1.2.3", version: "1.2.3", contains: true}, + {nativeRange: ">=1.2.3", version: "2.0.0", contains: true}, + {nativeRange: ">=1.2.3", version: "1.2.2", contains: false}, + {nativeRange: ">=1.2.3 <2.0.0", version: "1.2.3", contains: true}, + {nativeRange: ">=1.2.3 <2.0.0", version: "2.0.0", contains: false}, + }, + }, + { + name: "cargo", extract: extractCargoRanges, + files: map[string]string{"tests/test_version_req.rs": ` +let ref r = req("^1.0.0"); +assert_match_all(r, &["1.0.0", "1.2.0"]); +assert_match_none(r, &["2.0.0"]); +} +`}, + want: []nativeRangeAssertion{ + {nativeRange: "^1.0.0", version: "1.0.0", contains: true}, + {nativeRange: "^1.0.0", version: "1.2.0", contains: true}, + {nativeRange: "^1.0.0", version: "2.0.0", contains: false}, + }, + }, + { + name: "maven", extract: extractMavenRanges, + files: map[string]string{"compat/maven-artifact/src/test/java/org/apache/maven/artifact/versioning/VersionRangeTest.java": ` +VersionRange range = VersionRange.createFromVersionSpec("[1.0,2.0)"); +assertTrue(range.containsVersion(new DefaultArtifactVersion("1.5"))); +assertFalse(range.containsVersion(new DefaultArtifactVersion("2.0"))); +`}, + want: []nativeRangeAssertion{ + {nativeRange: "[1.0,2.0)", version: "1.5", contains: true}, + {nativeRange: "[1.0,2.0)", version: "2.0", contains: false}, + }, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + got, err := test.extract(test.files) + if err != nil { + t.Fatal(err) + } + if !reflect.DeepEqual(got, test.want) { + t.Errorf("range assertions = %#v, want %#v", got, test.want) + } + }) + } +} + +func TestBuildRangeTestFileNormalizesAndDeduplicates(t *testing.T) { + source := sourceSpec{name: "reference", scheme: "npm"} + file, err := buildRangeTestFile(source, []nativeRangeAssertion{ + {nativeRange: "^1.0.0", version: "1.2.0", contains: true}, + {nativeRange: "^1.0.0", version: "1.2.0", contains: true}, + }) + if err != nil { + t.Fatal(err) + } + if len(file.Tests) != 1 { + t.Fatalf("got %d tests, want 1", len(file.Tests)) + } + if got := file.Tests[0].Input.Vers; got != "vers:npm/>=1.0.0|<2.0.0" { + t.Errorf("VERS input = %q", got) + } +} + +func TestBuildRangeTestFileRepresentsEmptyRange(t *testing.T) { + source := sourceSpec{name: "reference", scheme: "cargo"} + file, err := buildRangeTestFile(source, []nativeRangeAssertion{ + {nativeRange: "0.3.0, 0.4.0", version: "0.3.0", contains: false}, + }) + if err != nil { + t.Fatal(err) + } + if got := file.Tests[0].Input.Vers; got == "vers:cargo/" { + t.Errorf("empty native range encoded as unbounded VERS %q", got) + } +} + func TestExtractGoReportsMissingTable(t *testing.T) { _, err := extractGo(map[string]string{"semver/semver_test.go": "package semver\n"}) if err == nil { diff --git a/tools/harvest/main.go b/tools/harvest/main.go index b5f974a..ed84067 100644 --- a/tools/harvest/main.go +++ b/tools/harvest/main.go @@ -8,11 +8,15 @@ import ( "os" "os/exec" "path/filepath" + "strconv" + + vers "github.com/git-pkgs/vers" ) const ( schemaURL = "https://packageurl.org/schemas/vers-test.schema-0.2.json" testTypeEquality = "equality" + testTypeContainment = "containment" testGroupRecommended = "recommended" licenseMIT = "MIT" testsPerComparison = 2 @@ -21,15 +25,17 @@ const ( ) type sourceSpec struct { - name string - scheme string - repository string - commit string - license string - localPath string - sourceFiles []string - outputFile string - extract func(map[string]string) ([]comparison, error) + name string + scheme string + repository string + commit string + license string + localPath string + sourceFiles []string + outputFile string + extract func(map[string]string) ([]comparison, error) + rangeOutputFile string + extractRanges func(map[string]string) ([]nativeRangeAssertion, error) } type comparison struct { @@ -39,22 +45,30 @@ type comparison struct { differentOnly bool } +type nativeRangeAssertion struct { + nativeRange string + version string + contains bool +} + type testFile struct { Schema string `json:"$schema"` Tests []testCase `json:"tests"` } type testCase struct { - Description string `json:"description"` - TestGroup string `json:"test_group"` - TestType string `json:"test_type"` - Input comparisonInput `json:"input"` - ExpectedOutput any `json:"expected_output"` + Description string `json:"description"` + TestGroup string `json:"test_group"` + TestType string `json:"test_type"` + Input testInput `json:"input"` + ExpectedOutput any `json:"expected_output"` } -type comparisonInput struct { - InputType string `json:"input_type"` - Versions []string `json:"versions"` +type testInput struct { + InputType string `json:"input_type,omitempty"` + Versions []string `json:"versions,omitempty"` + Vers string `json:"vers,omitempty"` + Version string `json:"version,omitempty"` } type provenanceFile struct { @@ -74,44 +88,70 @@ var sources = []sourceSpec{ name: "node-semver", scheme: "npm", repository: "https://github.com/npm/node-semver.git", commit: "6e05b7637396ac66522cff8731f07cfe0ef49a29", license: "ISC", - localPath: "npm/node-semver", - sourceFiles: []string{"test/fixtures/comparisons.js", "test/fixtures/equality.js"}, - outputFile: "npm_version_cmp_test.json", extract: extractNodeSemver, + localPath: "npm/node-semver", + sourceFiles: []string{ + "test/fixtures/comparisons.js", "test/fixtures/equality.js", + "test/fixtures/range-include.js", "test/fixtures/range-exclude.js", + }, + outputFile: "npm_version_cmp_test.json", extract: extractNodeSemver, + rangeOutputFile: "npm_range_reference_test.json", extractRanges: extractNodeSemverRanges, }, { name: "packaging", scheme: "pypi", repository: "https://github.com/pypa/packaging.git", commit: "55cbf1b9426f44455fa1a9e0836f1fc082cc8452", license: "Apache-2.0 OR BSD-2-Clause", - localPath: "pypa/packaging", sourceFiles: []string{"tests/test_version.py"}, + localPath: "pypa/packaging", sourceFiles: []string{"tests/test_version.py", "tests/test_specifiers.py"}, outputFile: "pypi_version_cmp_test.json", extract: extractPyPI, + rangeOutputFile: "pypi_range_reference_test.json", extractRanges: extractPyPIRanges, }, { name: "RubyGems", scheme: "gem", repository: "https://github.com/rubygems/rubygems.git", commit: "370fe6876eec1714cd0f8824c3f19f4d368dfe7c", license: licenseMIT, - localPath: "rubygems/rubygems", sourceFiles: []string{"test/rubygems/test_gem_version.rb"}, + localPath: "rubygems/rubygems", sourceFiles: []string{ + "test/rubygems/test_gem_version.rb", "test/rubygems/test_gem_requirement.rb", + }, outputFile: "gem_version_cmp_test.json", extract: extractRubyGems, + rangeOutputFile: "gem_range_reference_test.json", extractRanges: extractRubyGemsRanges, }, { name: "composer/semver", scheme: "composer", repository: "https://github.com/composer/semver.git", commit: "1cbc9b575a27458074d21a3bab95b847c8de387c", license: licenseMIT, - localPath: "composer/semver", sourceFiles: []string{"tests/ComparatorTest.php"}, + localPath: "composer/semver", sourceFiles: []string{"tests/ComparatorTest.php", "tests/VersionParserTest.php"}, outputFile: "composer_version_cmp_test.json", extract: extractComposer, + rangeOutputFile: "composer_range_reference_test.json", extractRanges: extractComposerRanges, }, { name: "pub_semver", scheme: "pub", repository: "https://github.com/dart-lang/tools.git", commit: "a22c3a687dc1b35630fb34c296157d66565429cd", license: "BSD-3-Clause", - localPath: "dart-lang/tools", sourceFiles: []string{"pkgs/pub_semver/test/version_test.dart"}, + localPath: "dart-lang/tools", sourceFiles: []string{ + "pkgs/pub_semver/test/version_test.dart", + "pkgs/pub_semver/test/version_range_test.dart", + "pkgs/pub_semver/test/version_constraint_test.dart", + "pkgs/pub_semver/test/utils.dart", + }, outputFile: "pub_version_cmp_test.json", extract: extractPub, + rangeOutputFile: "pub_range_reference_test.json", extractRanges: extractPubRanges, }, { name: "semver", scheme: "cargo", repository: "https://github.com/dtolnay/semver.git", commit: "280ebcb6edac3aa4cdc545dbff8a26c5ac4861fe", license: "MIT OR Apache-2.0", - localPath: "dtolnay/semver", sourceFiles: []string{"tests/test_version.rs"}, + localPath: "dtolnay/semver", sourceFiles: []string{"tests/test_version.rs", "tests/test_version_req.rs"}, outputFile: "cargo_version_cmp_test.json", extract: extractCargo, + rangeOutputFile: "cargo_range_reference_test.json", extractRanges: extractCargoRanges, + }, + { + name: "maven-artifact", scheme: "maven", + repository: "https://github.com/apache/maven.git", + commit: "48514f63b2799844c9f8d7746f73a95123526df7", license: "Apache-2.0", + localPath: "apache/maven", + sourceFiles: []string{ + "compat/maven-artifact/src/test/java/org/apache/maven/artifact/versioning/VersionRangeTest.java", + }, + rangeOutputFile: "maven_range_reference_test.json", extractRanges: extractMavenRanges, }, { name: "dpkg", scheme: "deb", @@ -173,16 +213,34 @@ func run(sourceRoot, outputRoot string) error { if err != nil { return fmt.Errorf("read %s: %w", source.name, err) } - comparisons, err := source.extract(files) - if err != nil { - return fmt.Errorf("extract %s: %w", source.name, err) + var generatedFiles []string + if source.extract != nil { + comparisons, err := source.extract(files) + if err != nil { + return fmt.Errorf("extract %s comparisons: %w", source.name, err) + } + if err := writeJSON(filepath.Join(testsDir, source.outputFile), buildTestFile(source, comparisons)); err != nil { + return err + } + generatedFiles = append(generatedFiles, filepath.ToSlash(filepath.Join("tests", source.outputFile))) } - if err := writeJSON(filepath.Join(testsDir, source.outputFile), buildTestFile(source, comparisons)); err != nil { - return err + if source.extractRanges != nil { + assertions, err := source.extractRanges(files) + if err != nil { + return fmt.Errorf("extract %s ranges: %w", source.name, err) + } + file, err := buildRangeTestFile(source, assertions) + if err != nil { + return fmt.Errorf("build %s ranges: %w", source.name, err) + } + if err := writeJSON(filepath.Join(testsDir, source.rangeOutputFile), file); err != nil { + return err + } + generatedFiles = append(generatedFiles, filepath.ToSlash(filepath.Join("tests", source.rangeOutputFile))) } provenance.Sources = append(provenance.Sources, provenanceSource{ Repository: source.repository, Commit: source.commit, License: source.license, - SourceFiles: source.sourceFiles, GeneratedFiles: []string{filepath.ToSlash(filepath.Join("tests", source.outputFile))}, + SourceFiles: source.sourceFiles, GeneratedFiles: generatedFiles, }) } @@ -266,7 +324,7 @@ func buildTestFile(source sourceSpec, comparisons []comparison) testFile { appendTest(testCase{ Description: fmt.Sprintf("%s treats %q and %q as different.", source.name, left, right), TestGroup: testGroupRecommended, TestType: testTypeEquality, - Input: comparisonInput{InputType: source.scheme, Versions: []string{left, right}}, + Input: testInput{InputType: source.scheme, Versions: []string{left, right}}, ExpectedOutput: false, }) continue @@ -290,13 +348,13 @@ func buildTestFile(source sourceSpec, comparisons []comparison) testFile { appendTest(testCase{ Description: description, TestGroup: testGroupRecommended, TestType: testType, - Input: comparisonInput{InputType: source.scheme, Versions: input}, ExpectedOutput: expected, + Input: testInput{InputType: source.scheme, Versions: input}, ExpectedOutput: expected, }) if result != 0 { appendTest(testCase{ Description: fmt.Sprintf("%s treats %q and %q as different.", source.name, item.left, item.right), TestGroup: testGroupRecommended, TestType: testTypeEquality, - Input: comparisonInput{InputType: source.scheme, Versions: []string{item.left, item.right}}, + Input: testInput{InputType: source.scheme, Versions: []string{item.left, item.right}}, ExpectedOutput: false, }) } @@ -304,6 +362,45 @@ func buildTestFile(source sourceSpec, comparisons []comparison) testFile { return testFile{Schema: schemaURL, Tests: tests} } +func buildRangeTestFile(source sourceSpec, assertions []nativeRangeAssertion) (testFile, error) { + tests := make([]testCase, 0, len(assertions)) + seen := make(map[string]bool, len(assertions)) + for _, assertion := range assertions { + r, err := vers.ParseNative(assertion.nativeRange, source.scheme) + if err != nil { + return testFile{}, fmt.Errorf("parse native range %q: %w", assertion.nativeRange, err) + } + // RawConstraints preserve legacy from-native rendering. Containment + // fixtures need the expanded intervals that implement native behavior. + containmentRange := *r + containmentRange.RawConstraints = nil + if r.IsEmpty() { + containmentRange = *vers.NewRange([]vers.Interval{vers.ExactInterval("0.0.0")}) + containmentRange.Exclusions = []string{"0.0.0"} + containmentRange.Scheme = source.scheme + } + versURI := vers.ToVersString(&containmentRange, source.scheme) + key := versURI + "\x00" + assertion.version + "\x00" + strconv.FormatBool(assertion.contains) + if seen[key] { + continue + } + seen[key] = true + verb := "excludes" + if assertion.contains { + verb = "contains" + } + tests = append(tests, testCase{ + Description: fmt.Sprintf("%s range %q %s %q.", source.name, assertion.nativeRange, verb, assertion.version), + TestGroup: testGroupRecommended, TestType: testTypeContainment, + Input: testInput{Vers: versURI, Version: assertion.version}, ExpectedOutput: assertion.contains, + }) + } + if len(tests) == 0 { + return testFile{}, errors.New("no native range assertions found") + } + return testFile{Schema: schemaURL, Tests: tests}, nil +} + func writeJSON(filename string, value any) error { data, err := json.MarshalIndent(value, "", " ") if err != nil {