Coverage for tests / unit / tools / shfmt / test_error_handling.py: 100%

47 statements  

« prev     ^ index     » next       coverage.py v7.13.0, created at 2026-04-03 18:53 +0000

1"""Unit tests for shfmt plugin error handling.""" 

2 

3from __future__ import annotations 

4 

5import subprocess 

6from pathlib import Path 

7from typing import TYPE_CHECKING 

8from unittest.mock import patch 

9 

10from assertpy import assert_that 

11 

12from lintro.parsers.shfmt.shfmt_parser import parse_shfmt_output 

13from lintro.tools.definitions.shfmt import ShfmtPlugin 

14 

15if TYPE_CHECKING: 

16 pass 

17 

18 

19# ============================================================================= 

20# Tests for timeout handling 

21# ============================================================================= 

22 

23 

24def test_check_with_timeout( 

25 shfmt_plugin: ShfmtPlugin, 

26 tmp_path: Path, 

27) -> None: 

28 """Check handles timeout correctly. 

29 

30 Args: 

31 shfmt_plugin: The ShfmtPlugin instance to test. 

32 tmp_path: Temporary directory path for test files. 

33 """ 

34 test_file = tmp_path / "test_script.sh" 

35 test_file.write_text('#!/bin/bash\necho "hello"\n') 

36 

37 with patch( 

38 "lintro.plugins.execution_preparation.verify_tool_version", 

39 return_value=None, 

40 ): 

41 with patch.object( 

42 shfmt_plugin, 

43 "_run_subprocess", 

44 side_effect=subprocess.TimeoutExpired(cmd=["shfmt"], timeout=30), 

45 ): 

46 result = shfmt_plugin.check([str(test_file)], {}) 

47 

48 assert_that(result.success).is_false() 

49 

50 

51def test_fix_with_timeout( 

52 shfmt_plugin: ShfmtPlugin, 

53 tmp_path: Path, 

54) -> None: 

55 """Fix handles timeout correctly. 

56 

57 Args: 

58 shfmt_plugin: The ShfmtPlugin instance to test. 

59 tmp_path: Temporary directory path for test files. 

60 """ 

61 test_file = tmp_path / "test_script.sh" 

62 test_file.write_text('#!/bin/bash\necho "hello"\n') 

63 

64 with patch( 

65 "lintro.plugins.execution_preparation.verify_tool_version", 

66 return_value=None, 

67 ): 

68 with patch.object( 

69 shfmt_plugin, 

70 "_run_subprocess", 

71 side_effect=subprocess.TimeoutExpired(cmd=["shfmt"], timeout=30), 

72 ): 

73 result = shfmt_plugin.fix([str(test_file)], {}) 

74 

75 assert_that(result.success).is_false() 

76 

77 

78# ============================================================================= 

79# Tests for output parsing 

80# ============================================================================= 

81 

82 

83def test_parse_shfmt_output_single_file() -> None: 

84 """Parse single file diff from shfmt output.""" 

85 output = """--- script.sh 

86+++ script.sh 

87@@ -1,3 +1,3 @@ 

88-if [ "$foo" = "bar" ]; then 

89+if [ "$foo" = "bar" ]; then 

90 echo "match" 

91 fi""" 

92 issues = parse_shfmt_output(output) 

93 

94 assert_that(issues).is_length(1) 

95 assert_that(issues[0].file).is_equal_to("script.sh") 

96 assert_that(issues[0].line).is_equal_to(1) 

97 assert_that(issues[0].message).contains("Needs formatting") 

98 assert_that(issues[0].fixable).is_true() 

99 

100 

101def test_parse_shfmt_output_multiple_files() -> None: 

102 """Parse multiple files diff from shfmt output.""" 

103 output = """--- script1.sh 

104+++ script1.sh 

105@@ -1,2 +1,2 @@ 

106-echo "hello" 

107+echo "hello" 

108--- script2.sh 

109+++ script2.sh 

110@@ -1,2 +1,2 @@ 

111-if [ 1 ]; then 

112+if [ 1 ]; then""" 

113 issues = parse_shfmt_output(output) 

114 

115 assert_that(issues).is_length(2) 

116 assert_that(issues[0].file).is_equal_to("script1.sh") 

117 assert_that(issues[1].file).is_equal_to("script2.sh") 

118 

119 

120def test_parse_shfmt_output_empty() -> None: 

121 """Parse empty output returns empty list.""" 

122 issues = parse_shfmt_output("") 

123 

124 assert_that(issues).is_empty() 

125 

126 

127def test_parse_shfmt_output_none() -> None: 

128 """Parse None output returns empty list.""" 

129 issues = parse_shfmt_output(None) 

130 

131 assert_that(issues).is_empty() 

132 

133 

134def test_parse_shfmt_output_with_orig_suffix() -> None: 

135 """Parse diff with .orig suffix in header.""" 

136 output = """--- script.sh.orig 

137+++ script.sh 

138@@ -1,2 +1,2 @@ 

139-echo "hello" 

140+echo "hello" """ 

141 issues = parse_shfmt_output(output) 

142 

143 assert_that(issues).is_length(1) 

144 assert_that(issues[0].file).is_equal_to("script.sh")