terraform-version 0.4.0

Parser and match calculator for terraform version constraint syntax
Documentation
use std::num::IntErrorKind;
use terraform_version::{
    Comparator, Error, NumericIdentifiers, Operator, Version, VersionRequirement,
};

#[test]
fn test_readme_deps() {
    version_sync::assert_markdown_deps_updated!("README.md");
}

#[test]
fn test_html_root_url() {
    version_sync::assert_html_root_url_updated!("src/lib.rs");
}

// Version tests
#[test]
fn test_parse_version_succeeds_without_suffix() {
    let version_str = "1.2.3";
    let version = Version {
        numeric_identifiers: NumericIdentifiers::new(vec![1, 2, 3]),
        suffix: None,
    };
    let result = Version::parse(version_str);
    assert_eq!(result, Ok(version));
}

#[test]
fn test_parse_version_succeeds_with_suffix() {
    let version_str = "1.2.3-beta+something.01";
    let version = Version {
        numeric_identifiers: NumericIdentifiers::new(vec![1, 2, 3]),
        suffix: Some("beta+something.01".to_string()),
    };
    let result = Version::parse(version_str);
    assert_eq!(result, Ok(version));
}

#[test]
fn test_parse_version_fails_invalid_version_number() {
    let version_str = "not.a.version";
    let result = Version::parse(version_str);
    assert!(
        matches!(result, Err(Error::ImpossibleNumericIdentifierParsing { text, ni, err }) if text == "not.a.version" && ni == "not" && err.kind() == &IntErrorKind::InvalidDigit)
    );
}

#[test]
fn test_parse_version_fails_empty_version() {
    let version_str = "";
    let result = Version::parse(version_str);
    assert_eq!(result, Err(Error::NoVersion));
}

// VersionRequirement tests

#[test]
fn test_parse_version_requirement_succeed() {
    let version_req_str = "> 1.2.3 , <= 8.5";
    let comp1 = Comparator {
        operator: Some(Operator::Greater),
        version: Version {
            numeric_identifiers: NumericIdentifiers::new(vec![1, 2, 3]),
            suffix: None,
        },
    };
    let comp2 = Comparator {
        operator: Some(Operator::LessEq),
        version: Version {
            numeric_identifiers: NumericIdentifiers::new(vec![8, 5]),
            suffix: None,
        },
    };
    let version_req = VersionRequirement {
        comparators: vec![comp1, comp2],
    };
    let result = VersionRequirement::parse(version_req_str);
    assert_eq!(result, Ok(version_req));
}

#[test]
fn test_parse_version_requirement_succeed_without_operator() {
    let version_req_str = "1.2.3";
    let comp1 = Comparator {
        operator: None,
        version: Version {
            numeric_identifiers: NumericIdentifiers::new(vec![1, 2, 3]),
            suffix: None,
        },
    };
    let version_req = VersionRequirement {
        comparators: vec![comp1],
    };
    let result = VersionRequirement::parse(version_req_str);
    assert_eq!(result, Ok(version_req));
}

#[test]
fn test_parse_version_requirement_fails_forbidden_operator() {
    let version_req_str = "> 1.2.3-alpha";
    let result = VersionRequirement::parse(version_req_str);
    assert_eq!(
        result,
        Err(Error::NotAllowedOperatorWithSuffix(Operator::Greater))
    );
}

#[test]
fn test_parse_version_requirement_fails_forbidden_operator_multiple_comparator() {
    let version_req_str = " = 1.2.3, < 1.5.6";
    let result = VersionRequirement::parse(version_req_str);
    assert_eq!(
        result,
        Err(Error::NotAllowedOperatorWithMultipleComparators(
            version_req_str.to_string()
        ))
    );
}

#[test]
fn test_parse_version_requirement_fails_invalid_operator() {
    let version_req_str = "+ 1.2.3";
    let result = VersionRequirement::parse(version_req_str);
    assert_eq!(result, Err(Error::InvalidOperator("+ 1.2.3".to_string())));
}

#[test]
fn test_parse_version_requirement_fails_empty() {
    let version_req_str = "";
    let result = VersionRequirement::parse(version_req_str);
    assert_eq!(result, Err(Error::NoVersionRequirement));
}

// matches tests
#[test]
fn test_match_succeeds_greater_equal() {
    let version = Version {
        numeric_identifiers: NumericIdentifiers::new(vec![1, 2, 3]),
        suffix: None,
    };
    let comp1 = Comparator {
        operator: Some(Operator::GreaterEq),
        version: Version {
            numeric_identifiers: NumericIdentifiers::new(vec![1, 2, 3]),
            suffix: None,
        },
    };
    let version_req = VersionRequirement {
        comparators: vec![comp1],
    };
    assert!(version.matches(&version_req));
}

#[test]
fn test_match_succeeds_rightmost() {
    let version = Version {
        numeric_identifiers: NumericIdentifiers::new(vec![1, 2, 3]),
        suffix: None,
    };
    let comp1 = Comparator {
        operator: Some(Operator::RightMost),
        version: Version {
            numeric_identifiers: NumericIdentifiers::new(vec![1, 2, 3]),
            suffix: None,
        },
    };
    let version_req = VersionRequirement {
        comparators: vec![comp1],
    };
    assert!(version.matches(&version_req));
}

#[test]
fn test_match_succeeds_different() {
    let version = Version {
        numeric_identifiers: NumericIdentifiers::new(vec![1, 2, 3]),
        suffix: Some("-beta".to_string()),
    };
    let comp1 = Comparator {
        operator: Some(Operator::Different),
        version: Version {
            numeric_identifiers: NumericIdentifiers::new(vec![1, 2, 3]),
            suffix: None,
        },
    };
    let version_req = VersionRequirement {
        comparators: vec![comp1],
    };
    assert!(version.matches(&version_req));
}

#[test]
fn test_match_fails_exact() {
    let version = Version {
        numeric_identifiers: NumericIdentifiers::new(vec![1, 2, 3]),
        suffix: Some("-beta".to_string()),
    };
    let comp1 = Comparator {
        operator: Some(Operator::Exact),
        version: Version {
            numeric_identifiers: NumericIdentifiers::new(vec![1, 2, 3]),
            suffix: None,
        },
    };
    let version_req = VersionRequirement {
        comparators: vec![comp1],
    };
    assert!(!version.matches(&version_req));
}

#[test]
fn test_match_fails_lesser() {
    let version = Version {
        numeric_identifiers: NumericIdentifiers::new(vec![1, 2, 3]),
        suffix: None,
    };
    let comp1 = Comparator {
        operator: Some(Operator::Less),
        version: Version {
            numeric_identifiers: NumericIdentifiers::new(vec![1, 2, 3]),
            suffix: None,
        },
    };
    let version_req = VersionRequirement {
        comparators: vec![comp1],
    };
    assert!(!version.matches(&version_req));
}

// test is_without_operator

#[test]
fn test_is_without_operator_succeeds() {
    let comp1 = Comparator {
        operator: None,
        version: Version {
            numeric_identifiers: NumericIdentifiers::new(vec![1, 2, 3]),
            suffix: None,
        },
    };
    let version_req = VersionRequirement {
        comparators: vec![comp1],
    };
    assert!(version_req.is_without_operator());
}

#[test]
fn test_is_without_operator_fails() {
    let comp1 = Comparator {
        operator: Some(Operator::Less),
        version: Version {
            numeric_identifiers: NumericIdentifiers::new(vec![1, 2, 3]),
            suffix: None,
        },
    };
    let version_req = VersionRequirement {
        comparators: vec![comp1],
    };
    assert!(!version_req.is_without_operator());
}