mod auxiliary;
use auxiliary::{assert_diff, trim};
use parse_changelog::{parse, parse_iter, Parser};
#[test]
fn success() {
let changelogs = [
"
# Changelog
## unreleased
## 0.2.0
0.2.0.
## 0.1.0
0.1.0.
",
"
# Changelog
# unreleased
# 0.2.0
0.2.0.
# 0.1.0
0.1.0.
",
"
# Changelog
# unreleased
# 0.2.0
0.2.0.
# 0.1.0
0.1.0.
",
"
Changelog
==
unreleased
--
0.2.0
--
0.2.0.
0.1.0
--
0.1.0.
",
"
Changelog
==
unreleased
==
0.2.0
==
0.2.0.
0.1.0
==
0.1.0.
",
"
Changelog
==
unreleased
==
0.2.0
==
0.2.0.
0.1.0
==
0.1.0.
",
];
for changelog in &changelogs {
let changelog = parse(changelog).unwrap();
assert_eq!(changelog[0].title, "0.2.0");
assert_eq!(trim(changelog[0].notes), "0.2.0.");
assert_eq!(changelog["0.2.0"].title, "0.2.0");
assert_eq!(trim(changelog["0.2.0"].notes), "0.2.0.");
assert_eq!(changelog["0.1.0"].title, "0.1.0");
assert_eq!(trim(changelog["0.1.0"].notes), "0.1.0.");
}
}
#[test]
fn failure() {
let changelogs = [
" ## 0.1.0\n",
" 0.1.0\n ==\n",
" 0.1.0\n==\n",
" 0.1.0\n--\n",
"0.1.0\n==?\n",
"0.1.0\n--?\n",
];
for changelog in &changelogs {
assert!(parse(changelog).unwrap_err().is_parse());
}
assert!(Parser::new().prefix_format("").is_ok());
assert!(Parser::new().prefix_format(" ").is_ok());
assert!(Parser::new().prefix_format("\t\n").is_ok());
assert!(Parser::new().prefix_format(r"\/").is_ok());
assert!(Parser::new().version_format("").unwrap_err().is_format());
assert!(Parser::new().version_format(" ").unwrap_err().is_format());
assert!(Parser::new().version_format("\t\n").unwrap_err().is_format());
assert!(Parser::new().version_format(r"\/").is_ok());
}
#[test]
fn multiple_heading() {
let changelogs = ["## 0.1.0\n## 0.1.0\n", "## 0.1.0\n## 0.1.0\n## 0.0.0\n"];
for changelog in &changelogs {
assert!(parse(changelog).unwrap_err().is_parse());
}
let changelogs = ["## 0.1.0\n##0.1.0\n", "##0.1.0\n## 0.1.0\n##0.0.0\n"];
for changelog in &changelogs {
assert_eq!(parse(changelog).unwrap().len(), 1);
}
}
#[test]
fn atx_heading() {
for level in 1..=6 {
let changelog = &format!("{} 0.1.0", "#".repeat(level));
assert_eq!(1, parse(changelog).unwrap().len());
}
let changelog = &format!("{} 0.1.0", "#".repeat(7));
assert!(parse(changelog).unwrap_err().is_parse());
}
#[test]
fn code_block() {
let changelog = "\
# 0.2.0
```
# 0.2.0
```
# 0.1.0
```
# 0.1.0
```
";
let changelog = parse(changelog).unwrap();
assert_eq!(changelog.len(), 2);
assert_eq!(changelog["0.2.0"].notes, "```\n# 0.2.0\n```");
assert_eq!(changelog["0.1.0"].notes, "```\n# 0.1.0\n```");
let changelog = "\
# 0.2.0
# 0.2.0
# 0.1.0
# 0.1.0
";
let changelog = parse(changelog).unwrap();
assert_eq!(changelog.len(), 2);
assert_eq!(changelog["0.2.0"].notes, " # 0.2.0");
assert_eq!(changelog["0.1.0"].notes, " # 0.1.0");
}
#[test]
fn comment() {
let changelog = "\
# 0.2.0
<!--
# 0.2.0
-->
# 0.1.0
<!--
# 0.1.0
-->
";
let changelog = parse(changelog).unwrap();
assert_eq!(changelog.len(), 2);
assert_eq!(changelog["0.2.0"].notes, "<!--\n# 0.2.0\n-->");
assert_eq!(changelog["0.1.0"].notes, "<!--\n# 0.1.0\n-->");
let changelog = "\
# 0.2.0
<!--
# 0.2.0-->
# 0.1.0
<!--
# 0.1.0-->
";
let changelog = parse(changelog).unwrap();
assert_eq!(changelog.len(), 2);
assert_eq!(changelog["0.2.0"].notes, "<!--\n# 0.2.0-->");
assert_eq!(changelog["0.1.0"].notes, "<!--\n# 0.1.0-->");
let changelog = "\
# 0.2.0
<!--
# 0.2.0 --> <!--
# 0.2.0 -->
# 0.1.0
<!--
# 0.1.0 --> <!--
# 0.1.0 -->
# 0.0.0
";
let changelog = parse(changelog).unwrap();
assert_eq!(changelog.len(), 3);
assert_eq!(changelog["0.2.0"].notes, "<!--\n# 0.2.0 --> <!--\n# 0.2.0 -->");
assert_eq!(changelog["0.1.0"].notes, "<!--\n# 0.1.0 --> <!--\n# 0.1.0 -->");
assert_eq!(changelog["0.0.0"].notes, "");
}
#[test]
fn link() {
let changelog = "\
# [Version 0.5.2 2022-01-01]
# [Version 0.5.1 2022-01-01][link]
# [Version 0.5.0 2022-01-01](link)
# Version [0.4.2 2022-01-01]
# Version [0.4.1 2022-01-01][link]
# Version [0.4.0 2022-01-01](link)
# [0.3.2 2022-01-01]
# [0.3.1 2022-01-01][link]
# [0.3.0 2022-01-01](link)
# [0.2.2] 2022-01-01
# [0.2.1][link] 2022-01-01
# [0.2.0](link) 2022-01-01
# [0.1.2]
# [0.1.1][link]
# [0.1.0](link)
";
let changelog = parse(changelog).unwrap();
assert_eq!(changelog.len(), 15);
assert_eq!(changelog["0.5.2"].version, "0.5.2");
assert_eq!(changelog["0.5.2"].title, "[Version 0.5.2 2022-01-01]");
assert_eq!(changelog["0.5.1"].version, "0.5.1");
assert_eq!(changelog["0.5.1"].title, "[Version 0.5.1 2022-01-01][link]");
assert_eq!(changelog["0.5.0"].version, "0.5.0");
assert_eq!(changelog["0.5.0"].title, "[Version 0.5.0 2022-01-01](link)");
assert_eq!(changelog["0.4.2"].version, "0.4.2");
assert_eq!(changelog["0.4.2"].title, "Version [0.4.2 2022-01-01]");
assert_eq!(changelog["0.4.1"].version, "0.4.1");
assert_eq!(changelog["0.4.1"].title, "Version [0.4.1 2022-01-01][link]");
assert_eq!(changelog["0.4.0"].version, "0.4.0");
assert_eq!(changelog["0.4.0"].title, "Version [0.4.0 2022-01-01](link)");
assert_eq!(changelog["0.3.2"].version, "0.3.2");
assert_eq!(changelog["0.3.2"].title, "[0.3.2 2022-01-01]");
assert_eq!(changelog["0.3.1"].version, "0.3.1");
assert_eq!(changelog["0.3.1"].title, "[0.3.1 2022-01-01][link]");
assert_eq!(changelog["0.3.0"].version, "0.3.0");
assert_eq!(changelog["0.3.0"].title, "[0.3.0 2022-01-01](link)");
assert_eq!(changelog["0.2.2"].version, "0.2.2");
assert_eq!(changelog["0.2.2"].title, "[0.2.2] 2022-01-01");
assert_eq!(changelog["0.2.1"].version, "0.2.1");
assert_eq!(changelog["0.2.1"].title, "[0.2.1][link] 2022-01-01");
assert_eq!(changelog["0.2.0"].version, "0.2.0");
assert_eq!(changelog["0.2.0"].title, "[0.2.0](link) 2022-01-01");
assert_eq!(changelog["0.1.2"].version, "0.1.2");
assert_eq!(changelog["0.1.2"].title, "[0.1.2]");
assert_eq!(changelog["0.1.1"].version, "0.1.1");
assert_eq!(changelog["0.1.1"].title, "[0.1.1][link]");
assert_eq!(changelog["0.1.0"].version, "0.1.0");
assert_eq!(changelog["0.1.0"].title, "[0.1.0](link)");
}
#[test]
#[cfg_attr(miri, ignore)] fn rust() {
let text = include_str!("fixtures/rust.md");
let map = parse(text).unwrap();
assert_eq!(map.len(), 72);
assert_diff("tests/fixtures/rust-1.46.0.md", map["1.46.0"].notes);
let vec: Vec<_> = parse_iter(text).collect();
assert_eq!(vec.len(), 72);
assert_eq!(vec[2], map["1.46.0"]);
let text = include_str!("fixtures/rust-atx.md");
let map = parse(text).unwrap();
assert_eq!(map.len(), 72);
assert_diff("tests/fixtures/rust-1.46.0-atx.md", map["1.46.0"].notes);
let vec: Vec<_> = parse_iter(text).collect();
assert_eq!(vec.len(), 72);
assert_eq!(vec[2], map["1.46.0"]);
}
#[test]
#[cfg_attr(miri, ignore)] fn pin_project() {
let text = include_str!("fixtures/pin-project.md");
let changelog = parse(text).unwrap();
assert_eq!(changelog.len(), 70);
assert_diff("tests/fixtures/pin-project-1.0.0.md", changelog["1.0.0"].notes);
let changelog = Parser::new().prefix_format("").unwrap().parse(text).unwrap();
assert_eq!(changelog.len(), 70);
assert_diff("tests/fixtures/pin-project-1.0.0.md", changelog["1.0.0"].notes);
}
#[test]
#[cfg_attr(miri, ignore)] fn cargo() {
let changelog = Parser::new()
.prefix_format("Cargo ")
.unwrap()
.version_format(r"^[0-9]+\.[0-9]+")
.unwrap()
.parse(include_str!("fixtures/cargo.md"))
.unwrap();
assert_eq!(changelog.len(), 21);
assert_diff("tests/fixtures/cargo-1.50.md", changelog["1.50"].notes);
}
#[test]
fn fuzz() {
let tests =
&[("1115.8.8 '9.\n-\n\u{c}\"----\u{19}\u{1f}<!--.4\n## 444.444.4\r\r \u{b}---->", Some(1))];
for &(test, expected_len) in tests {
let res = parse(test);
if let Some(expected_len) = expected_len {
assert_eq!(res.unwrap().len(), expected_len);
}
}
}
#[test]
#[cfg_attr(miri, ignore)] fn pathological_fake_heading() {
let text = &"#".repeat(1024 * 1024 * 128);
let now = std::time::Instant::now();
parse(text).unwrap_err();
eprintln!("{:?}", now.elapsed());
}