// License: see LICENSE file at root directory of `master` branch

extern crate dia_semver;

use {
    core::str::FromStr,
    dia_semver::{Semver, SemverErrorKind},
};

#[cfg(feature="std")]
use {
    std::ffi::{CString, OsStr, OsString},
};

#[test]
fn parser() {
    assert_eq!(Semver::from_str("1.2.3").unwrap(), Semver::from_str("         1.2.3            ").unwrap());
    assert_ne!(Semver::from_str("   \t  1.2.3   \r\n").unwrap(), Semver::from_str("4.5.6").unwrap());

    assert_eq!(Semver::from_str("        999       ").unwrap(), Semver::new(999, 0, 0));
    assert_eq!(Semver::from_str("        999.1       ").unwrap(), Semver::new(999, 1, 0));
    assert_eq!(Semver::from_str("        999.1.9       ").unwrap(), Semver::new(999, 1, 9));

    assert_ne!(Semver::from_str("        999.1.9-abc       ").unwrap(), Semver::new(999, 1, 9));

    assert_eq!(Semver::from_str("1.2.3").unwrap(), "1.2.3".parse().unwrap());

    let s: Semver = "4.5.6-999+abc".to_string().parse().unwrap();
    assert_eq!(s, "4.5.6-999".to_string().parse().unwrap());
    assert_eq!(s, "4.5.6-999+xyz".parse().unwrap());

    assert_eq!(Semver::parse(String::from("01.2.3")).unwrap_err().kind, SemverErrorKind::InvalidMajor);
    assert_eq!(Semver::parse("1.002.3").unwrap_err().kind, SemverErrorKind::InvalidMinor);
    assert_eq!(Semver::parse("1.2.013".to_string()).unwrap_err().kind, SemverErrorKind::InvalidPatch);
    Semver::parse(String::from("0.0.0")).unwrap();
    Semver::parse("0.0.1").unwrap();

    #[cfg(feature="std")]
    {
        Semver::parse_os_str(OsString::from("1.2.3")).unwrap();
        Semver::from_os_str(OsStr::new("        1.2.3       ")).unwrap();
        assert_eq!(Semver::parse_os_str(OsString::from("           1.2.3          ")).unwrap_err().kind, SemverErrorKind::InvalidMajor);

        Semver::parse_c_str(CString::new("4.5.6").unwrap()).unwrap();
        Semver::from_c_str(CString::new("           4.5.6      ").unwrap().as_c_str()).unwrap();
        assert_eq!(
            Semver::parse_c_str(CString::new("          4.5.6         ").unwrap().as_c_str()).unwrap_err().kind, SemverErrorKind::InvalidMajor
        );
    }

    assert_eq!(Semver::from_str("1.2.3+a.b.c").unwrap(), Semver::from_str("1.2.3").unwrap());
    assert_ne!(Semver::from_str("1.2.3-a.b.c").unwrap(), Semver::from_str("1.2.3+a.b.c").unwrap());
    assert_eq!(Semver::from_str("1.2.3-a.b.c+x.y.z").unwrap(), Semver::from_str("1.2.3-a.b.c").unwrap());

    assert_eq!(Semver::from_str("1.0.0").unwrap().to_string(), "1.0.0");
    assert_eq!(Semver::from_str("1.1").unwrap().to_string(), "1.1.0");
    assert_eq!(Semver::from_str("2").unwrap().to_string(), "2.0.0");
    assert_eq!(Semver::from_str("3.0.0-ids").unwrap().to_string(), "3.0.0-ids");
    assert_eq!(Semver::from_str("3.1-abc").unwrap().to_string(), "3.1.0-abc");
    assert_eq!(Semver::from_str("4-xyz").unwrap().to_string(), "4.0.0-xyz");
    assert_eq!(Semver::from_str("5.0.0+ids-abc").unwrap().to_string(), "5.0.0+ids-abc");
    assert_eq!(Semver::from_str("5.0.0+ids-abc-abc").unwrap().to_string(), "5.0.0+ids-abc-abc");
    assert_eq!(Semver::from_str("5.0.0-ids+abc").unwrap().to_string(), "5.0.0-ids+abc");
    assert_eq!(Semver::from_str("5.0.0-ids+abc-xyz").unwrap().to_string(), "5.0.0-ids+abc-xyz");

    assert_eq!(Semver::from_str("5.0.0+ids+abc").unwrap_err().kind, SemverErrorKind::InvalidBuildMetadata);
    assert_eq!(Semver::from_str("5.0.0-ids+abc+abc").unwrap_err().kind, SemverErrorKind::InvalidBuildMetadata);
    assert_eq!(Semver::from_str("5.1-*)(").unwrap_err().kind, SemverErrorKind::InvalidPreRelease);
    assert_eq!(Semver::from_str("5.1-099)(").unwrap_err().kind, SemverErrorKind::InvalidPreRelease);
    assert_eq!(Semver::from_str("6-").unwrap_err().kind, SemverErrorKind::InvalidPreRelease);
    assert_eq!(Semver::from_str("6*").unwrap_err().kind, SemverErrorKind::InvalidToken);
    assert_eq!(Semver::from_str("1.2.3-abc-").unwrap_err().kind, SemverErrorKind::InvalidPreRelease);
    assert_eq!(Semver::from_str("1.2.3-abc-.123-").unwrap_err().kind, SemverErrorKind::InvalidPreRelease);

    assert_eq!(Semver::parse("1.2.x-abc").unwrap_err().kind, SemverErrorKind::InvalidPatch);
    assert_eq!(Semver::parse("1.2-abc").unwrap_err().kind, SemverErrorKind::InvalidPatch);
    assert_eq!(Semver::parse("1.x-abc").unwrap_err().kind, SemverErrorKind::InvalidMinor);
    assert_eq!(Semver::parse("1-abc").unwrap_err().kind, SemverErrorKind::InvalidMinor);
    assert_eq!(Semver::parse("x-abc").unwrap_err().kind, SemverErrorKind::InvalidMajor);
    assert_eq!(Semver::from_str("x-abc").unwrap_err().kind, SemverErrorKind::InvalidMajor);

    // Overflow
    let max_version_number = Semver::default().major().wrapping_sub(1);
    assert_eq!(Semver::from_str(&format!("{}0.0.0", max_version_number)).unwrap_err().kind, SemverErrorKind::InvalidMajor);
    assert_eq!(Semver::from_str(&format!("0.{}0.0", max_version_number)).unwrap_err().kind, SemverErrorKind::InvalidMinor);
    assert_eq!(Semver::from_str(&format!("0.0.{}0", max_version_number)).unwrap_err().kind, SemverErrorKind::InvalidPatch);

    let zeros = {
        let mut tmp = String::new();
        for _ in 0..Semver::MAX_INPUT_STR_LEN { tmp.push('0'); }
        tmp
    };
    assert_eq!(Semver::from_str(&format!("0.0.0+{}", zeros)).unwrap_err().kind, SemverErrorKind::TooLarge);
}
