Coverage for tests / unit / parsers / test_cargo_deny_parser.py: 100%
48 statements
« prev ^ index » next coverage.py v7.13.0, created at 2026-04-03 18:53 +0000
« prev ^ index » next coverage.py v7.13.0, created at 2026-04-03 18:53 +0000
1"""Unit tests for cargo-deny parser."""
3from __future__ import annotations
5import pytest
6from assertpy import assert_that
8from lintro.parsers.cargo_deny.cargo_deny_parser import parse_cargo_deny_output
11def test_parse_cargo_deny_output_single_diagnostic() -> None:
12 """Parse a single cargo-deny diagnostic from JSON Lines."""
13 output = (
14 '{"type":"diagnostic","fields":{"severity":"error","code":"L001",'
15 '"message":"license \'GPL-3.0\' is not allowed",'
16 '"labels":[{"span":{"start":0,"end":10},"message":"crate foo"}]}}'
17 )
18 issues = parse_cargo_deny_output(output)
19 assert_that(issues).is_length(1)
20 assert_that(issues[0].file).is_equal_to("Cargo.toml")
21 assert_that(issues[0].code).is_equal_to("L001")
22 assert_that(issues[0].severity).is_equal_to("error")
23 assert_that(issues[0].message).contains("license")
24 assert_that(issues[0].crate_name).is_equal_to("foo")
27def test_parse_cargo_deny_output_advisory() -> None:
28 """Parse a security advisory from JSON Lines."""
29 output = (
30 '{"type":"advisory","fields":{"advisory":{"id":"RUSTSEC-2021-0001",'
31 '"severity":"HIGH"},"versions":{"patched":[">=1.0.1"]},'
32 '"package":{"name":"vulnerable-crate","version":"0.9.0"}}}'
33 )
34 issues = parse_cargo_deny_output(output)
35 assert_that(issues).is_length(1)
36 assert_that(issues[0].advisory_id).is_equal_to("RUSTSEC-2021-0001")
37 assert_that(issues[0].advisory_severity).is_equal_to("HIGH")
38 assert_that(issues[0].crate_name).is_equal_to("vulnerable-crate")
39 assert_that(issues[0].crate_version).is_equal_to("0.9.0")
40 assert_that(issues[0].patched_versions).contains(">=1.0.1")
43def test_parse_cargo_deny_output_multiple_issues() -> None:
44 """Parse multiple issues from JSON Lines."""
45 output = (
46 '{"type":"diagnostic","fields":{"severity":"error","code":"L001",'
47 '"message":"license issue","labels":[{"message":"crate foo"}]}}\n'
48 '{"type":"diagnostic","fields":{"severity":"warning","code":"B001",'
49 '"message":"banned dependency","labels":[{"message":"crate bar@1.0.0"}]}}'
50 )
51 issues = parse_cargo_deny_output(output)
52 assert_that(issues).is_length(2)
53 assert_that(issues[0].crate_name).is_equal_to("foo")
54 assert_that(issues[1].crate_name).is_equal_to("bar")
55 assert_that(issues[1].crate_version).is_equal_to("1.0.0")
58def test_parse_cargo_deny_output_ignores_non_issues() -> None:
59 """Ignore non-issue types like summary."""
60 output = (
61 '{"type":"summary","fields":{"errors":1,"warnings":0}}\n'
62 '{"type":"diagnostic","fields":{"severity":"error","code":"L001",'
63 '"message":"license issue","labels":[{"message":"crate foo"}]}}'
64 )
65 issues = parse_cargo_deny_output(output)
66 assert_that(issues).is_length(1)
67 assert_that(issues[0].code).is_equal_to("L001")
70@pytest.mark.parametrize(
71 ("output", "expected_count"),
72 [
73 pytest.param("", 0, id="empty_string"),
74 pytest.param("\n\n", 0, id="only_newlines"),
75 ],
76)
77def test_parse_cargo_deny_output_empty_cases(
78 output: str,
79 expected_count: int,
80) -> None:
81 """Handle empty output."""
82 result = parse_cargo_deny_output(output)
83 assert_that(result).is_length(expected_count)
86def test_parse_cargo_deny_output_invalid_json() -> None:
87 """Skip invalid JSON lines."""
88 output = (
89 '{"type":"diagnostic","fields":{"severity":"error","code":"L001",'
90 '"message":"issue","labels":[{"message":"crate foo"}]}}\n'
91 "not valid json\n"
92 '{"type":"diagnostic","fields":{"severity":"warning","code":"B001",'
93 '"message":"another issue","labels":[{"message":"crate bar"}]}}'
94 )
95 issues = parse_cargo_deny_output(output)
96 assert_that(issues).is_length(2)
99def test_parse_cargo_deny_output_crate_with_version() -> None:
100 """Parse crate info with version from labels."""
101 output = (
102 '{"type":"diagnostic","fields":{"severity":"error","code":"D001",'
103 '"message":"duplicate dependency",'
104 '"labels":[{"message":"crate serde@1.0.150"}]}}'
105 )
106 issues = parse_cargo_deny_output(output)
107 assert_that(issues).is_length(1)
108 assert_that(issues[0].crate_name).is_equal_to("serde")
109 assert_that(issues[0].crate_version).is_equal_to("1.0.150")