Skip to content

Commit

Permalink
Add test based on the comparator op match logic
Browse files Browse the repository at this point in the history
  • Loading branch information
linyihai committed Jul 19, 2024
1 parent d43191a commit 7b4ad61
Show file tree
Hide file tree
Showing 2 changed files with 177 additions and 138 deletions.
44 changes: 20 additions & 24 deletions src/eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,30 +31,34 @@ pub(crate) fn matches_comparator(cmp: &Comparator, ver: &Version) -> bool {
matches_impl(cmp, ver) && (ver.pre.is_empty() || pre_is_compatible(cmp, ver))
}
// If VersionReq missing Minor, Patch, then filling them with 0
fn fill_partial_req(cmp: &mut Comparator) {
fn fill_partial_req(cmp: &Comparator) -> Comparator {
let mut cmp = cmp.clone();
if cmp.minor.is_none() {
cmp.minor = Some(0);
cmp.patch = Some(0);
} else if cmp.patch.is_none() {
cmp.patch = Some(0);
}
cmp
}

fn matches_prerelease_impl(cmp: &Comparator, ver: &Version) -> bool {
let cmp = &{
let mut cmp = cmp.clone();
match cmp.op {
Op::Greater | Op::GreaterEq | Op::Less | Op::LessEq => fill_partial_req(&mut cmp),
_ => {}
}
cmp
};
match cmp.op {
Op::Exact | Op::Wildcard => matches_exact_prerelease(cmp, ver),
Op::Greater => matches_greater(cmp, ver),
Op::GreaterEq => matches_exact(cmp, ver) || matches_greater(cmp, ver),
Op::Less => matches_less(cmp, ver),
Op::LessEq => matches_exact(cmp, ver) || matches_less(cmp, ver),
Op::GreaterEq => {
if matches_exact_prerelease(cmp, ver) {
return true;
}
matches_greater(cmp, ver)
}
Op::Less => matches_less(&fill_partial_req(cmp), ver),
Op::LessEq => {
if matches_exact_prerelease(cmp, ver) {
return true;
}
matches_less(&fill_partial_req(cmp), ver)
}
Op::Tilde => matches_tilde_prerelease(cmp, ver),
Op::Caret => matches_caret_prerelease(cmp, ver),
#[cfg(no_non_exhaustive)]
Expand Down Expand Up @@ -87,12 +91,7 @@ fn matches_exact_prerelease(cmp: &Comparator, ver: &Version) -> bool {
return false;
}

let mut lower = Comparator {
op: Op::Less,
..cmp.clone()
};
fill_partial_req(&mut lower);
if !matches_greater(&lower, ver) {
if !matches_greater(&fill_partial_req(cmp), ver) {
return false;
}

Expand Down Expand Up @@ -200,9 +199,7 @@ fn matches_tilde_prerelease(cmp: &Comparator, ver: &Version) -> bool {
return true;
}

let mut lower = cmp.clone();
fill_partial_req(&mut lower);
if !matches_greater(&lower, ver) {
if !matches_greater(&fill_partial_req(cmp), ver) {
return false;
}

Expand Down Expand Up @@ -252,9 +249,8 @@ fn matches_caret_prerelease(cmp: &Comparator, ver: &Version) -> bool {
if matches_exact(cmp, ver) {
return true;
}
let mut lower = cmp.clone();
fill_partial_req(&mut lower);
if !matches_greater(&lower, ver) {

if !matches_greater(&fill_partial_req(cmp), ver) {
return false;
}

Expand Down
271 changes: 157 additions & 114 deletions tests/test_matches_prerelease.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,16 +126,115 @@ fn major_caret() {
assert_prerelease_match_none(r, &["1.2.0", "2.0.0-0", "2.0.0"]);
}

#[test]
fn test_exact() {
// =I.J.K equivalent to >=I.J.K, <I.J.(K+1)-0
let ref r = req("=4.2.1");
assert_prerelease_match_all(r, &["4.2.1"]);
assert_prerelease_match_none(r, &["1.2.3", "4.2.1-pre", "4.2.2", "5.0.0"]);

// =I.J equivalent to >=I.J.0, <I.(J+1).0-0
let ref r = req("=4.2");
// Match >= 4.2.0, < 4.3.0-0
assert_prerelease_match_all(r, &["4.2.0", "4.2.1", "4.2.4-pre", "4.2.9"]);
// Not Match < 4.2.0
assert_prerelease_match_none(r, &["0.0.1", "2.1.2-pre", "4.0.0-pre"]);
// Not Match >= 4.3.0-0
assert_prerelease_match_none(r, &["4.3.0-0", "4.3.0", "5.0.0-0", "5.0.0"]);

// =I equivalent to >=I.0.0, <(I+1).0.0-0
let ref r = req("=4");
// Match >= 4.0.0, < 5.0.0-0
assert_prerelease_match_all(r, &["4.0.0", "4.2.1", "4.2.4-pre", "4.9.9"]);
// Not Match < 4.0.0
assert_prerelease_match_none(r, &["0.0.1", "2.1.2-pre", "4.0.0-pre"]);
// Not Match >= 5.0.0-0
assert_prerelease_match_none(r, &["5.0.0-0", "5.0.0", "5.0.1"]);

// =I.J.K-pre only match I.J.K-pre
let ref r = req("=4.2.1-0");
// Only exactly match 4.2.1-0
assert_prerelease_match_all(r, &["4.2.1-0"]);
// Not match others
assert_prerelease_match_none(r, &["1.2.3", "4.2.0", "4.2.1-1", "4.2.2", "4.3.5"]);
}

#[test]
fn test_greater() {
// >I.J.K
let ref r = req(">4.2.1");
assert_prerelease_match_all(r, &["4.2.2", "5.0.0-0", "5.0.0"]);
assert_prerelease_match_none(r, &["0.0.0", "4.2.1-pre", "4.2.1"]);
// >I.J equivalent to >=I.(J+1).0-0
let ref r = req(">4.2");
assert_prerelease_match_all(r, &["4.3.0-pre", "4.3.0", "5.0.0"]);
assert_prerelease_match_none(r, &["0.0.0", "4.2.1"]);
// >I equivalent to >=(I+1).0.0-0
let ref r = req(">4");
assert_prerelease_match_all(r, &["5.0.0-0", "5.0.0-1", "5.0.0"]);
assert_prerelease_match_none(r, &["0.0.0", "4.2.1"]);
}

#[test]
fn test_greater_eq() {
// >=I.J.K
let ref r = req(">=4.2.1");
assert_prerelease_match_all(r, &["4.2.1", "5.0.0-0", "5.0.0"]);
assert_prerelease_match_none(r, &["0.0.0", "4.2.1-pre"]);
// >=I.J equivalent to >=I.J.0
let ref r = req(">=4.2");
assert_prerelease_match_all(r, &["4.2.0", "4.2.1-pre", "4.3.0", "5.0.0"]);
assert_prerelease_match_none(r, &["0.0.0", "4.1.1", "4.2.0-0"]);
// >=I equivalent to >=I.0.0
let ref r = req(">=4");
assert_prerelease_match_all(r, &["4.0.0", "4.1.0-1", "5.0.0"]);
assert_prerelease_match_none(r, &["0.0.0", "4.0.0-pre"]);
}

#[test]
fn test_less() {
// <I.J.K
let ref r = req("<4.2.1");
assert_prerelease_match_all(r, &["0.0.0", "4.0.0", "4.2.1-pre"]);
assert_prerelease_match_none(r, &["4.2.2", "5.0.0-0", "5.0.0"]);
// <I.J equivalent to <I.J.0
let ref r = req("<4.2");
assert_prerelease_match_all(r, &["0.0.0", "4.2.0-pre"]);
assert_prerelease_match_none(r, &["4.2.0", "4.3.0-pre", "4.3.0"]);
// <I equivalent to <I.0.0
let ref r = req("<4");
assert_prerelease_match_all(r, &["0.0.0", "4.0.0-pre"]);
assert_prerelease_match_none(r, &["4.0.0", "5.0.0-1", "5.0.0"]);
}

#[test]
fn test_less_eq() {
// <=I.J.K
let ref r = req("<=4.2.1");
assert_prerelease_match_all(r, &["0.0.0", "4.2.1-pre", "4.2.1"]);
assert_prerelease_match_none(r, &["4.2.2", "5.0.0-0", "5.0.0"]);
// <=I.J equivalent to <I.(J+1).0-0
let ref r = req("<=4.2");
assert_prerelease_match_all(r, &["0.0.0", "4.2.0-pre"]);
assert_prerelease_match_none(r, &["4.3.0-0", "4.3.0", "4.4.0"]);
// <=I equivalent to <(I+1).0.0-0
let ref r = req("<=4");
assert_prerelease_match_all(r, &["0.0.0", "4.0.0-pre", "4.0.0"]);
assert_prerelease_match_none(r, &["5.0.0-1", "5.0.0"]);
}

#[test]
fn test_tilde() {
let ref r = req("~0.0.24");
// Match >= 0.0.24, < 0.1.0-0
assert_prerelease_match_all(r, &["0.0.24", "0.0.25-0", "0.0.25"]);
// Not Match < 0.0.24
assert_prerelease_match_none(r, &["0.0.1", "0.0.9", "0.0.24-pre"]);
// Not Match >= 0.1.0-0
assert_prerelease_match_none(r, &["0.1.0-0", "0.1.0", "1.2.3", "2.0.0"]);
// ~I.J.K — equivalent to >=I.J.K, <I.(J+1).0-0
let ref r = req("~1.2.3");
// Match >= 1.2.3, < 1.3.0-0
assert_prerelease_match_all(r, &["1.2.3", "1.2.4-pre", "1.2.4"]);
// Not Match < 1.2.3
assert_prerelease_match_none(r, &["0.0.1", "1.0.0-pre", "1.1.0-0", "1.1.0"]);
// Not Match >= 1.3.0-0
assert_prerelease_match_none(r, &["1.3.0-0", "1.3.0", "1.3.1-0", "1.3.1", "2.0.0"]);

// ~I.J — equivalent to >=I.J.0, <I.(J+1).0-0
let ref r = req("~0.24");
// Match >= 0.24.0, < 0.25.0-0
assert_prerelease_match_all(r, &["0.24.0", "0.24.1-pre", "0.24.1", "0.24.9"]);
Expand All @@ -144,6 +243,7 @@ fn test_tilde() {
// Not Match >= 0.25.0-0
assert_prerelease_match_none(r, &["0.25.0-0", "1.1.0", "1.2.3", "2.0.0"]);

// ~I — >=I.0.0, <(I+1).0.0-0
let ref r = req("~1");
// Match >= 1.0.0, < 2.0.0-0
assert_prerelease_match_all(r, &["1.0.0", "1.1.0-0", "1.1.0", "1.2.3"]);
Expand All @@ -152,22 +252,7 @@ fn test_tilde() {
// Not Match >= 2.0.0-0
assert_prerelease_match_none(r, &["2.0.0-0", "2.0.0", "2.0.1"]);

let ref r = req("~1.2");
// Match >= 1.2.0, < 1.3.0-0
assert_prerelease_match_all(r, &["1.2.0", "1.2.1", "1.2.2-pre", "1.2.9"]);
// Not Match < 1.2.0
assert_prerelease_match_none(r, &["0.0.1", "1.0.0-pre", "1.1.0-0", "1.1.0"]);
// Not Match >= 1.3.0-0
assert_prerelease_match_none(r, &["1.3.0-0", "1.3.0", "1.4.3-pre", "1.8.9", "2.0.0"]);

let ref r = req("~1.2.3");
// Match >= 1.2.3, < 1.3.0-0
assert_prerelease_match_all(r, &["1.2.3", "1.2.4-pre", "1.2.4"]);
// Not Match < 1.2.3
assert_prerelease_match_none(r, &["0.0.1", "1.0.0-pre", "1.1.0-0", "1.1.0"]);
// Not Match >= 1.3.0-0
assert_prerelease_match_none(r, &["1.3.0-0", "1.3.0", "1.3.1-0", "1.3.1", "2.0.0"]);

// ~I.J.K-[pre] — equivalent to >=I.J.K-[pre], <I.J.(K+1).0
let ref r = req("~1.2.3-0");
// Match >= 1.2.3-0, < 1.3.0-0
assert_prerelease_match_all(r, &["1.2.3-0", "1.2.3", "1.2.4-pre", "1.2.4"]);
Expand All @@ -178,105 +263,63 @@ fn test_tilde() {
}

#[test]
fn test_range() {
let ref r = req(">=1.0.0");
assert_prerelease_match_all(r, &["1.0.0", "1.0.1-pre", "2.0.0-0", "2.0.0"]);
assert_prerelease_match_none(r, &["0.9.9", "0.10.0", "1.0.0-pre.0"]);

let ref r = req(">=1.0.0-pre.1");
assert_prerelease_match_all(r, &["1.0.0-pre.1", "1.0.0", "1.0.1-pre", "2.0.0-0"]);
assert_prerelease_match_none(r, &["0.9.9", "0.10.0", "1.0.0-pre.0"]);

let ref r = req("<=1.0.0");
assert_prerelease_match_all(r, &["0.9.9", "0.10.0", "1.0.0-pre", "1.0.0"]);
assert_prerelease_match_none(r, &["1.0.1", "1.0.1-pre", "1.1.0", "2.0.0-0"]);

let ref r = req("<=1.0.0-0");
assert_prerelease_match_all(r, &["0.9.9", "0.1.0", "0.10.0", "1.0.0-0"]);
assert_prerelease_match_none(r, &["1.0.0-pre", "1.0.1-pre", "1.1.0", "2.0.0-0"]);

let ref r = req(">1.0.0-0,<=1.1.0-0");
assert_prerelease_match_all(r, &["1.0.0-pre", "1.0.0", "1.0.9", "1.1.0-0"]);
assert_prerelease_match_none(r, &["0.0.1", "1.0.0-0", "1.2.3-pre", "2.0.0"]);

let ref r = req(">=1.0.0,<1.1.0-0");
assert_prerelease_match_all(r, &["1.0.0", "1.0.0", "1.0.9"]);
assert_prerelease_match_none(r, &["0.0.1", "1.0.0-pre", "1.1.0-0", "1.1.0", "2.0.0"]);
fn test_caret() {
// ^I.J.K (for I>0) — equivalent to >=I.J.K, <(I+1).0.0-0
let ref r = req("^1.2.3");
assert_prerelease_match_all(r, &["1.2.3", "1.2.4-0", "1.8.9"]);
assert_prerelease_match_none(r, &["0.0.9", "1.1.1-0", "1.2.3-0", "2.0.0-pre", "2.1.1"]);

// ^0.J.K (for J>0) — equivalent to >=0.J.K, <0.(J+1).0-0
let ref r = req("^0.2.3");
assert_prerelease_match_all(r, &["0.2.3", "0.2.9-0", "0.2.9"]);
assert_prerelease_match_none(r, &["0.0.9", "0.2.3-0", "0.3.0-0", "0.3.11", "1.1.1"]);

// ^0.0.K — equivalent to >=0.0.K, <0.0.(K+1)-0
let ref r = req("^0.0.3");
assert_prerelease_match_all(r, &["0.0.3"]);
assert_prerelease_match_none(
r,
&["0.0.1", "0.0.4-0", "0.0.9", "0.3.0-0", "0.4.0-0", "1.1.1"],
);

// ^I.J (for I>0 or J>0) — equivalent to >=I.J.0, <(I+1).0.0-0)
let ref r = req("^1.2");
assert_prerelease_match_all(r, &["1.2.0", "1.9.0-0", "1.9.9"]);
assert_prerelease_match_none(r, &["0.0.1", "0.0.4-0", "1.2.0-0", "2.0.0-0", "4.0.1"]);

// ^0.0 — equivalent to >=0.0.0, <0.1.0-0
let ref r = req("^0.0");
assert_prerelease_match_all(r, &["0.0.0", "0.0.1", "0.0.4-0"]);
assert_prerelease_match_none(r, &["0.1.0-0", "0.1.0", "1.1.1"]);

// ^I — equivalent to >=I.0.0, <(I+1).0.0-0
let ref r = req("^1");
assert_prerelease_match_all(r, &["1.0.0", "1.0.1", "1.0.4-0"]);
assert_prerelease_match_none(r, &["0.1.0-0", "0.1.0", "2.0.0-0", "3.1.2"]);
}

#[test]
fn test_range_partial() {
let ref r = req(">=0.24");
assert_prerelease_match_all(r, &["0.24.0", "0.24.1", "2.0.0-0", "2.0.0"]);
assert_prerelease_match_none(r, &["0.9.9", "0.10.0", "0.24.0-pre.0"]);

let ref r = req(">=1");
assert_prerelease_match_all(r, &["1.0.0", "1.0.1-pre", "2.0.0-0", "2.0.0"]);
assert_prerelease_match_none(r, &["0.9.9", "0.10.0", "1.0.0-pre.0"]);

let ref r = req("<1");
assert_prerelease_match_none(r, &["1.0.0", "1.0.1-pre", "2.0.0-0", "2.0.0"]);
assert_prerelease_match_all(r, &["0.9.9", "0.10.0", "1.0.0-pre.0"]);

let ref r = req(">=1.1");
assert_prerelease_match_all(r, &["1.1.0", "1.1.1-pre", "2.0.0-0"]);
assert_prerelease_match_none(r, &["0.9.9", "0.10.0", "1.0.0-pre.0"]);

let ref r = req("<1.1");
assert_prerelease_match_none(r, &["1.1.0", "1.1.1-pre", "2.0.0-0"]);
assert_prerelease_match_all(r, &["0.9.9", "0.10.0", "1.0.0-pre.0"]);

let ref r = req(">1,<=1.1");
assert_prerelease_match_all(r, &["1.0.9", "1.1.0-0"]);
assert_prerelease_match_none(r, &["0.0.1", "1.0.0-0", "1.2.3-pre", "2.0.0"]);

let ref r = req(">=1.1,<2");
assert_prerelease_match_all(r, &["1.1.0", "1.2.9-pre", "1.2.9", "2.0.0-pre"]);
assert_prerelease_match_none(r, &["0.0.1", "1.0.0-pre", "1.1.0-pre"]);

let ref r = req("*");
assert_prerelease_match_all(r, &["0.0.1", "1.0.0", "1.2.9", "2.0.0-pre"]);

let ref r = req("^1, <=1.9");
assert_prerelease_match_all(r, &["1.1.1-pre", "1.1.1"]);
let ref r = req("^0, <=0.0.1-z0");
assert_prerelease_match_all(r, &["0.0.1-z0"]);
}

#[test]
fn test_exact() {
let ref r = req("=4");
// Match >= 4.0.0, < 5.0.0-0
assert_prerelease_match_all(r, &["4.0.0", "4.2.1", "4.2.4-pre", "4.9.9"]);
// Not Match < 4.0.0
assert_prerelease_match_none(r, &["0.0.1", "2.1.2-pre", "4.0.0-pre"]);
// Not Match >= 5.0.0-0
assert_prerelease_match_none(r, &["5.0.0-0", "5.0.0", "5.0.1"]);

let ref r = req("=4.2");
fn test_wildcard() {
// I.J.* — equivalent to =I.J
//
// =I.J equivalent to >=I.J.0, <I.(J+1).0-0
let ref r = req("4.2.*");
// Match >= 4.2.0, < 4.3.0-0
assert_prerelease_match_all(r, &["4.2.0", "4.2.1", "4.2.4-pre", "4.2.9"]);
// Not Match < 4.2.0
assert_prerelease_match_none(r, &["0.0.1", "2.1.2-pre", "4.0.0-pre"]);
// Not Match >= 4.3.0-0
assert_prerelease_match_none(r, &["4.3.0-0", "4.3.0", "5.0.0-0", "5.0.0", "5.0.1"]);

let ref r = req("=4.2.1");
assert_prerelease_match_all(r, &["4.2.1"]);
assert_prerelease_match_none(r, &["1.2.3", "4.2.1-pre", "4.2.2", "5.0.0"]);

let ref r = req("=4.2.1-0");
// Only exactly match 4.2.1-0
assert_prerelease_match_all(r, &["4.2.1-0"]);
// Not match others
assert_prerelease_match_none(r, &["1.2.3", "4.2.0", "4.2.1-1", "4.2.2", "4.3.5"]);

// Speicial Case
let ref r = req("=0");
// Match >= 0.0.0, < 1.0.0-0
assert_prerelease_match_all(r, &["0.0.0", "0.1.1", "0.9.9"]);
// Not Match < 0.0.0
assert_prerelease_match_none(r, &["0.0.0-0", "0.0.0-pre"]);
// Not Match >= 1.0.0-0
assert_prerelease_match_none(r, &["1.0.0-0", "1.0.0", "2.0.1"]);
// I.* or I.*.* — equivalent to =I
//
// =I equivalent to >=I.0.0, <(I+1).0.0-0
for r in &[req("4.*"), req("4.*.*")] {
// Match >= 4.0.0, < 5.0.0-0
assert_prerelease_match_all(r, &["4.0.0", "4.2.1", "4.2.4-pre", "4.9.9"]);
// Not Match < 4.0.0
assert_prerelease_match_none(r, &["0.0.1", "2.1.2-pre", "4.0.0-pre"]);
// Not Match >= 5.0.0-0
assert_prerelease_match_none(r, &["5.0.0-0", "5.0.0", "5.0.1"]);
}
}

0 comments on commit 7b4ad61

Please sign in to comment.