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

1"""Unit tests for cargo-deny parser.""" 

2 

3from __future__ import annotations 

4 

5import pytest 

6from assertpy import assert_that 

7 

8from lintro.parsers.cargo_deny.cargo_deny_parser import parse_cargo_deny_output 

9 

10 

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") 

25 

26 

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") 

41 

42 

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") 

56 

57 

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") 

68 

69 

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) 

84 

85 

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) 

97 

98 

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")