443e322c
- commit
- 443e322c83489d94772f38e2e7c79b8402f657ff
- parent
- author
- Christopher K. Schmitt <me@shmish.dev>
- date
- 2026-07-29
- committer
- Christopher K. Schmitt <me@shmish.dev>
- date
- 2026-07-29
- changes
- 9
- insertions
- 574
- deletions
- 0
Msrc/filters.rs
~ plural.to_string()~ })~}++#[cfg(test)]+mod tests {+ use super::*;++ #[test]+ fn pluralize_singular() {+ assert_eq!(pluralize(&1, "item", "items").unwrap(), "item");+ }++ #[test]+ fn pluralize_zero() {+ assert_eq!(pluralize(&0, "item", "items").unwrap(), "items");+ }++ #[test]+ fn pluralize_multiple() {+ assert_eq!(pluralize(&3, "item", "items").unwrap(), "items");+ }+}
Msrc/git.rs
~~ Ok(entries)~}++#[cfg(test)]+mod tests {+ use super::*;++ #[test]+ fn validate_path_normal() {+ assert!(validate_path("foo").is_ok());+ }++ #[test]+ fn validate_path_nested() {+ assert!(validate_path("foo/bar").is_ok());+ }++ #[test]+ fn validate_path_empty() {+ assert!(validate_path("").is_ok());+ }++ #[test]+ fn validate_path_dotdot() {+ assert!(validate_path("..").is_err());+ }++ #[test]+ fn validate_path_dotdot_prefix() {+ assert!(validate_path("../foo").is_err());+ }++ #[test]+ fn validate_path_nested_dotdot() {+ assert!(validate_path("foo/../../bar").is_err());+ }++ #[test]+ fn validate_path_absolute() {+ assert!(validate_path("/absolute").is_err());+ }++ #[test]+ fn corrupt_ok() {+ let result: std::result::Result<i32, &str> = Ok(42);+ assert_eq!(result.corrupt().unwrap(), 42);+ }++ #[test]+ fn corrupt_err() {+ let result: std::result::Result<i32, &str> = Err("boom");+ let err = result.corrupt().unwrap_err();+ assert!(matches!(err, crate::error::Error::GitCorrupt(_)));+ }++ #[test]+ fn flatten_refs_skips_outer_err() {+ let result: std::result::Result<Vec<std::result::Result<i32, ()>>, ()> = Err(());+ let collected: Vec<i32> = flatten_refs(result).collect();+ assert!(collected.is_empty());+ }++ #[test]+ fn flatten_refs_skips_inner_err() {+ let result: std::result::Result<Vec<std::result::Result<i32, &str>>, ()> =+ Ok(vec![Ok(1), Err("skip"), Ok(3)]);+ let collected: Vec<i32> = flatten_refs(result).collect();+ assert_eq!(collected, vec![1, 3]);+ }++ #[test]+ fn commit_color_deterministic() {+ let c1 = commit_color("abc123");+ let c2 = commit_color("abc123");+ assert_eq!(c1, c2);+ }++ #[test]+ fn commit_color_in_palette() {+ let c = commit_color("xyz789");+ assert!(COLORS.contains(&c), "color {c} not in palette");+ }+}
Msrc/routes.rs
~ .route("/{repo}/{*path}", get(fallback))~ .with_state(state)~}++#[cfg(test)]+mod tests {+ use super::*;++ #[test]+ fn breadcrumbs_empty_path() {+ let crumbs = build_breadcrumbs("", "repo", "abc123", "");+ assert_eq!(crumbs.len(), 1);+ assert_eq!(crumbs[0].label, "tree");+ assert_eq!(crumbs[0].url, "/repo/commits/abc123/tree");+ }++ #[test]+ fn breadcrumbs_single_segment() {+ let crumbs = build_breadcrumbs("", "repo", "abc123", "src");+ assert_eq!(crumbs.len(), 2);+ assert_eq!(crumbs[0].label, "tree");+ assert_eq!(crumbs[1].label, "src");+ assert_eq!(crumbs[1].url, "/repo/commits/abc123/tree/src");+ }++ #[test]+ fn breadcrumbs_multiple_segments() {+ let crumbs = build_breadcrumbs("", "myrepo", "def456", "a/b/c");+ assert_eq!(crumbs.len(), 4);+ assert_eq!(crumbs[1].label, "a");+ assert_eq!(crumbs[1].url, "/myrepo/commits/def456/tree/a");+ assert_eq!(crumbs[2].url, "/myrepo/commits/def456/tree/a/b");+ assert_eq!(crumbs[3].url, "/myrepo/commits/def456/tree/a/b/c");+ }++ #[test]+ fn breadcrumbs_with_base_url() {+ let crumbs = build_breadcrumbs("/git", "repo", "abc", "src/lib");+ assert_eq!(crumbs[0].url, "/git/repo/commits/abc/tree");+ assert_eq!(crumbs[2].url, "/git/repo/commits/abc/tree/src/lib");+ }+}
Msrc/routes/archive.rs
~ body,~ ))~}++#[cfg(test)]+mod tests {+ use super::*;++ #[test]+ fn config_tar_gz() {+ let cfg = archive_config("tar.gz").unwrap();+ assert_eq!(cfg.content_type, "application/gzip");+ assert_eq!(cfg.extension, "tar.gz");+ assert!(!cfg.uses_xz);+ }++ #[test]+ fn config_tgz() {+ let cfg = archive_config("tgz").unwrap();+ assert_eq!(cfg.content_type, "application/gzip");+ assert!(!cfg.uses_xz);+ }++ #[test]+ fn config_tar_xz() {+ let cfg = archive_config("tar.xz").unwrap();+ assert_eq!(cfg.content_type, "application/x-xz");+ assert!(cfg.uses_xz);+ }++ #[test]+ fn config_txz() {+ let cfg = archive_config("txz").unwrap();+ assert_eq!(cfg.content_type, "application/x-xz");+ assert!(cfg.uses_xz);+ }++ #[test]+ fn config_zip() {+ let cfg = archive_config("zip").unwrap();+ assert_eq!(cfg.content_type, "application/zip");+ assert!(!cfg.uses_xz);+ }++ #[test]+ fn config_unsupported() {+ assert!(archive_config("rar").is_none());+ assert!(archive_config("tar").is_none());+ assert!(archive_config("").is_none());+ }++ #[test]+ fn sanitize_passes_clean() {+ assert_eq!(sanitize_filename_component("hello"), "hello");+ }++ #[test]+ fn sanitize_replaces_double_quote() {+ assert_eq!(sanitize_filename_component(r#"foo"bar"#), "foo-bar");+ }++ #[test]+ fn sanitize_replaces_backslash() {+ assert_eq!(sanitize_filename_component(r"a\b"), "a-b");+ }+}
Msrc/routes/commit.rs
~ site: state.site,~ })~}++#[cfg(test)]+mod tests {+ use super::*;++ fn commit(sha: &str, parents: &[&str]) -> git::CommitEntry {+ git::CommitEntry {+ sha: sha.to_string(),+ message: String::new(),+ date: String::new(),+ parents: parents.iter().map(|s| s.to_string()).collect(),+ }+ }++ // --- compute_layout ---++ #[test]+ fn layout_linear_chain() {+ let commits = vec![+ commit("C", &["B"]),+ commit("B", &["A"]),+ commit("A", &[]),+ ];+ let layout = compute_layout(&commits, 0);+ assert_eq!(layout.positions.len(), 3);+ assert_eq!(layout.positions.get("C"), Some(&(0, 0)));+ assert_eq!(layout.positions.get("B"), Some(&(1, 0)));+ assert_eq!(layout.positions.get("A"), Some(&(2, 0)));+ }++ #[test]+ fn layout_diamond_merge() {+ let commits = vec![+ commit("D", &["B", "C"]),+ commit("C", &["A"]),+ commit("B", &["A"]),+ commit("A", &[]),+ ];+ let layout = compute_layout(&commits, 0);+ assert_eq!(layout.positions.get("D"), Some(&(0, 0)));+ assert_eq!(layout.positions.get("C"), Some(&(1, 1)));+ assert_eq!(layout.positions.get("B"), Some(&(2, 0)));+ assert_eq!(layout.positions.get("A"), Some(&(3, 1)));+ }++ #[test]+ fn layout_root_commit() {+ let commits = vec![commit("A", &[])];+ let layout = compute_layout(&commits, 0);+ assert_eq!(layout.positions.get("A"), Some(&(0, 0)));+ assert!(layout.active_at_page_start.is_empty());+ }++ #[test]+ fn layout_octopus_merge() {+ let commits = vec![+ commit("E", &["B", "C", "D"]),+ commit("D", &["A"]),+ commit("C", &["A"]),+ commit("B", &["A"]),+ commit("A", &[]),+ ];+ let layout = compute_layout(&commits, 0);+ assert_eq!(layout.positions.get("E"), Some(&(0, 0)));+ assert_eq!(layout.positions.get("D"), Some(&(1, 2)));+ assert_eq!(layout.positions.get("C"), Some(&(2, 1)));+ assert_eq!(layout.positions.get("B"), Some(&(3, 0)));+ assert_eq!(layout.positions.get("A"), Some(&(4, 2)));+ }++ #[test]+ fn layout_empty_input() {+ let layout = compute_layout(&[], 0);+ assert!(layout.positions.is_empty());+ assert!(layout.active_at_page_start.is_empty());+ }++ #[test]+ fn layout_page_start_captures_active() {+ let commits = vec![+ commit("D", &["C"]),+ commit("C", &["B"]),+ commit("B", &["A"]),+ commit("A", &[]),+ ];+ let layout = compute_layout(&commits, 1);+ assert_eq!(layout.active_at_page_start.len(), 1);+ assert_eq!(layout.active_at_page_start[0], Some("C".to_string()));+ }++ #[test]+ fn layout_lane_steal_then_free() {+ let commits = vec![+ commit("C", &["B"]),+ commit("B", &["A"]),+ commit("A", &[]),+ ];+ let layout = compute_layout(&commits, 0);+ // C steals lane 0, B inherits it, A frees it+ assert_eq!(layout.positions.get("C"), Some(&(0, 0)));+ assert_eq!(layout.positions.get("B"), Some(&(1, 0)));+ assert_eq!(layout.positions.get("A"), Some(&(2, 0)));+ }++ // --- render_page_svg ---++ #[test]+ fn svg_empty_range() {+ let layout = compute_layout(&[], 0);+ assert_eq!(render_page_svg(&[], &layout, 0, 0), "");+ }++ #[test]+ fn svg_single_commit() {+ let commits = vec![commit("A", &[])];+ let layout = compute_layout(&commits, 0);+ let svg = render_page_svg(&commits, &layout, 0, 1);+ assert!(svg.starts_with(r#"<svg width="#), "expected SVG start, got: {svg}");+ assert!(svg.contains("<circle"), "expected circle element");+ assert!(svg.ends_with("</svg>"));+ }++ #[test]+ fn svg_two_commits_same_lane() {+ let commits = vec![commit("B", &["A"]), commit("A", &[])];+ let layout = compute_layout(&commits, 0);+ let svg = render_page_svg(&commits, &layout, 0, 2);+ assert!(svg.contains("<line"), "expected line element");+ assert_eq!(svg.matches("<line").count(), 1);+ assert_eq!(svg.matches("<circle").count(), 2);+ }++ // --- DiffHunkCollector ---++ #[test]+ fn diff_hunk_context_only() {+ let mut hunks = Vec::new();+ let mut added = 0;+ let mut removed = 0;+ let mut collector = DiffHunkCollector {+ hunks: &mut hunks,+ file_added: &mut added,+ file_removed: &mut removed,+ };+ let header = gix::diff::blob::unified_diff::HunkHeader {+ before_hunk_start: 1,+ before_hunk_len: 1,+ after_hunk_start: 1,+ after_hunk_len: 1,+ };+ collector+ .consume_hunk(header, &[(DiffLineKind::Context, b"keep")])+ .unwrap();+ assert_eq!(hunks.len(), 1);+ assert_eq!(hunks[0].len(), 1);+ assert_eq!(hunks[0][0].marker, "~");+ assert_eq!(hunks[0][0].content, "keep");+ assert_eq!(added, 0);+ assert_eq!(removed, 0);+ }++ #[test]+ fn diff_hunk_mixed_lines() {+ let mut hunks = Vec::new();+ let mut added = 0;+ let mut removed = 0;+ let mut collector = DiffHunkCollector {+ hunks: &mut hunks,+ file_added: &mut added,+ file_removed: &mut removed,+ };+ let header = gix::diff::blob::unified_diff::HunkHeader {+ before_hunk_start: 1,+ before_hunk_len: 2,+ after_hunk_start: 1,+ after_hunk_len: 2,+ };+ collector+ .consume_hunk(+ header,+ &[+ (DiffLineKind::Context, b"ctx"),+ (DiffLineKind::Add, b"new"),+ (DiffLineKind::Remove, b"old"),+ ],+ )+ .unwrap();+ assert_eq!(hunks.len(), 1);+ assert_eq!(hunks[0].len(), 3);+ assert_eq!(hunks[0][0].marker, "~");+ assert_eq!(hunks[0][1].marker, "+");+ assert_eq!(hunks[0][2].marker, "-");+ assert_eq!(added, 1);+ assert_eq!(removed, 1);+ }++ #[test]+ fn diff_hunk_binary_content() {+ let mut hunks = Vec::new();+ let mut added = 0;+ let mut removed = 0;+ let mut collector = DiffHunkCollector {+ hunks: &mut hunks,+ file_added: &mut added,+ file_removed: &mut removed,+ };+ let header = gix::diff::blob::unified_diff::HunkHeader {+ before_hunk_start: 1,+ before_hunk_len: 1,+ after_hunk_start: 1,+ after_hunk_len: 1,+ };+ collector+ .consume_hunk(header, &[(DiffLineKind::Add, b"\xff\xfe\x00\x01")])+ .unwrap();+ // Invalid UTF-8 should fall back to <binary>+ assert_eq!(hunks[0][0].content, "<binary>");+ }++ #[test]+ fn diff_hunk_empty_input() {+ let mut hunks = Vec::new();+ let mut added = 0;+ let mut removed = 0;+ let mut collector = DiffHunkCollector {+ hunks: &mut hunks,+ file_added: &mut added,+ file_removed: &mut removed,+ };+ let header = gix::diff::blob::unified_diff::HunkHeader {+ before_hunk_start: 0,+ before_hunk_len: 0,+ after_hunk_start: 0,+ after_hunk_len: 0,+ };+ collector.consume_hunk(header, &[]).unwrap();+ assert_eq!(hunks.len(), 1);+ assert!(hunks[0].is_empty());+ }+}
Msrc/routes/git_upload.rs
~ Body::from_stream(stream),~ ))~}++#[cfg(test)]+mod tests {+ use super::*;++ #[test]+ fn pkt_line_hello() {+ assert_eq!(pkt_line("hello"), b"0009hello");+ }++ #[test]+ fn pkt_line_empty() {+ assert_eq!(pkt_line(""), b"0004");+ }++ #[test]+ fn pkt_line_single_char() {+ assert_eq!(pkt_line("x"), b"0005x");+ }+}
Msrc/routes/raw.rs
~ _ => "application/octet-stream",~ }~}++#[cfg(test)]+mod tests {+ use super::*;++ #[test]+ fn content_type_png() {+ assert_eq!(content_type_for("image.png"), "image/png");+ }++ #[test]+ fn content_type_jpg() {+ assert_eq!(content_type_for("photo.jpg"), "image/jpeg");+ }++ #[test]+ fn content_type_jpeg() {+ assert_eq!(content_type_for("photo.jpeg"), "image/jpeg");+ }++ #[test]+ fn content_type_svg() {+ assert_eq!(content_type_for("graph.svg"), "image/svg+xml");+ }++ #[test]+ fn content_type_md() {+ assert_eq!(content_type_for("readme.md"), "text/plain; charset=utf-8");+ }++ #[test]+ fn content_type_unknown() {+ assert_eq!(content_type_for("file.xyz"), "application/octet-stream");+ }++ #[test]+ fn content_type_no_extension() {+ assert_eq!(content_type_for("Makefile"), "application/octet-stream");+ }+}
Msrc/routes/repo.rs
~~ Ok(RepoList { repos, site: state.site })~}++#[cfg(test)]+mod tests {+ use super::*;++ #[test]+ fn relative_http() {+ assert!(!is_relative_url("http://example.com"));+ }++ #[test]+ fn relative_https() {+ assert!(!is_relative_url("https://example.com"));+ }++ #[test]+ fn relative_http_case_sensitive() {+ // Known quirk: uppercase scheme not matched, treated as relative+ assert!(is_relative_url("Http://example.com"));+ }++ #[test]+ fn relative_hash() {+ assert!(!is_relative_url("#section"));+ }++ #[test]+ fn relative_mailto() {+ assert!(!is_relative_url("mailto:user@host"));+ }++ #[test]+ fn relative_data() {+ assert!(!is_relative_url("data:text/plain,hi"));+ }++ #[test]+ fn relative_path_relative() {+ assert!(is_relative_url("relative/path"));+ }++ #[test]+ fn relative_path_absolute() {+ assert!(is_relative_url("/absolute/path"));+ }+}
Msrc/routes/tree.rs
~ }~ }~}++#[cfg(test)]+mod tests {+ use super::*;++ #[test]+ fn size_zero() {+ assert_eq!(format_size(0), "0 B");+ }++ #[test]+ fn size_bytes() {+ assert_eq!(format_size(1023), "1023 B");+ }++ #[test]+ fn size_kb() {+ assert_eq!(format_size(1024), "1.0 KB");+ }++ #[test]+ fn size_mb() {+ assert_eq!(format_size(1_048_576), "1.0 MB");+ }+}