mod common;
use common::{make_fixture, run_loc};
#[test]
fn test_total_lines_reported() {
let fixture = make_fixture(&[
("a.py", "x = 1\ny = 2\nz = 3\n"), ("b.py", "print('hello')\nprint('bye')\n"), ]);
let out = run_loc(&[fixture.path().to_str().unwrap()]);
let stdout = String::from_utf8_lossy(&out.stdout);
assert!(
stdout.contains('5') || stdout.contains("5"),
"Expected total of 5 lines in output:\n{}",
stdout
);
}
#[test]
fn test_binary_files_skipped_in_line_count() {
let fixture = make_fixture(&[("image.png", "\x00\x00\x00\x00binary\x00")]);
let out = run_loc(&[fixture.path().to_str().unwrap()]);
assert!(out.status.success());
let stdout = String::from_utf8_lossy(&out.stdout);
assert!(
stdout.contains('0') || !stdout.contains("image.png"),
"Binary file should not contribute lines"
);
}
#[test]
fn test_empty_file() {
let fixture = make_fixture(&[("empty.txt", "")]);
let out = run_loc(&[fixture.path().to_str().unwrap()]);
assert!(out.status.success());
let stdout = String::from_utf8_lossy(&out.stdout);
assert!(stdout.contains('0'), "Empty file should show 0 lines");
}
#[test]
fn test_no_trailing_newline_integration() {
let fixture = make_fixture(&[("no_newline.txt", "line1\nline2")]);
let out = run_loc(&[fixture.path().to_str().unwrap()]);
assert!(out.status.success());
let stdout = String::from_utf8_lossy(&out.stdout);
assert!(
stdout.contains('2'),
"Expected 2 lines for no trailing newline file"
);
}
#[test]
fn test_lockfile_lines_excluded_from_stats() {
let fixture = make_fixture(&[
("main.rs", "fn main() {}\n"),
(
"Cargo.lock",
"# This file is automatically @generated by Cargo.\nversion = 3\n\n[[package]]\n",
),
]);
let out = run_loc(&[fixture.path().to_str().unwrap()]);
assert!(out.status.success());
let stdout = String::from_utf8_lossy(&out.stdout);
assert!(
stdout.contains('1'),
"Expected 1 line total (lockfile excluded):\n{}",
stdout
);
}
#[test]
fn test_lockfile_appears_in_tree_with_tag() {
let fixture = make_fixture(&[
("main.rs", "fn main() {}\n"),
("Cargo.lock", "version = 3\n"),
]);
let out = run_loc(&["--tree", fixture.path().to_str().unwrap()]);
assert!(out.status.success());
let stdout = String::from_utf8_lossy(&out.stdout);
assert!(
stdout.contains("Cargo.lock"),
"Cargo.lock should appear in tree:\n{}",
stdout
);
assert!(
stdout.contains("[lockfile]"),
"Cargo.lock should carry the [lockfile] tag:\n{}",
stdout
);
}
#[test]
fn test_lockfile_has_no_line_count_in_tree() {
let fixture = make_fixture(&[
("main.rs", "fn main() {}\n"),
(
"yarn.lock",
"# yarn lockfile v1\n\nsome-pkg@1.0.0:\n version \"1.0.0\"\n resolved \"\"\n",
),
]);
let out = run_loc(&["--tree", fixture.path().to_str().unwrap()]);
assert!(out.status.success());
let stdout = String::from_utf8_lossy(&out.stdout);
assert!(
!stdout.contains("(5)"),
"Lockfile should not show a line count in the tree:\n{}",
stdout
);
}
#[test]
fn test_lockfile_count_shown_in_summary() {
let fixture = make_fixture(&[
("main.rs", "fn main() {}\n"),
("Cargo.lock", "version = 3\n"),
("yarn.lock", "# yarn lockfile v1\n"),
]);
let out = run_loc(&[fixture.path().to_str().unwrap()]);
assert!(out.status.success());
let stdout = String::from_utf8_lossy(&out.stdout);
assert!(
stdout.contains("Lockfiles"),
"Summary should mention lockfile count:\n{}",
stdout
);
assert!(
stdout.contains('2'),
"Lockfile count should be 2:\n{}",
stdout
);
}
#[test]
fn test_multiple_lockfile_ecosystems() {
let fixture = make_fixture(&[
("app.py", "print('hi')\n"),
("Cargo.lock", "version = 3\n"),
("package-lock.json", "{}\n"),
("poetry.lock", "# poetry\n"),
("go.sum", "module hash\n"),
]);
let out = run_loc(&[fixture.path().to_str().unwrap()]);
assert!(out.status.success());
let stdout = String::from_utf8_lossy(&out.stdout);
assert!(
stdout.contains('1'),
"Only source file lines should count, not lockfiles:\n{}",
stdout
);
}