Coverage for tsfpga/test/test_system_utils.py: 97%

114 statements  

« prev     ^ index     » next       coverage.py v7.10.6, created at 2025-08-29 20:51 +0000

1# -------------------------------------------------------------------------------------------------- 

2# Copyright (c) Lukas Vik. All rights reserved. 

3# 

4# This file is part of the tsfpga project, a project platform for modern FPGA development. 

5# https://tsfpga.com 

6# https://github.com/tsfpga/tsfpga 

7# -------------------------------------------------------------------------------------------------- 

8 

9import subprocess 

10from pathlib import Path 

11 

12import pytest 

13 

14from tsfpga.system_utils import ( 

15 create_directory, 

16 create_file, 

17 delete, 

18 file_is_in_directory, 

19 path_relative_to, 

20 prepend_file, 

21 read_file, 

22 read_last_lines_of_file, 

23 run_command, 

24 system_is_windows, 

25) 

26 

27 

28def test_delete_files_and_folders(tmp_path): 

29 # Test deleting a file, with and without wait 

30 path = create_file(tmp_path / "temp.txt") 

31 assert path.exists() 

32 delete(path) 

33 assert not path.exists() 

34 

35 path = create_file(tmp_path / "temp.txt") 

36 assert path.exists() 

37 delete(path, wait_until_deleted=True) 

38 assert not path.exists() 

39 

40 # Test deleting a directory, with and without wait 

41 path = create_directory(tmp_path / "temp_dir") 

42 assert path.exists() 

43 delete(path) 

44 assert not path.exists() 

45 

46 path = create_directory(tmp_path / "temp_dir") 

47 assert path.exists() 

48 delete(path, wait_until_deleted=True) 

49 assert not path.exists() 

50 

51 

52def test_create_directory_plain(tmp_path): 

53 path = tmp_path / "temp_dir" 

54 assert not path.exists() 

55 

56 create_directory(path) 

57 assert path.exists() 

58 assert path.is_dir() 

59 

60 

61def test_create_directory_that_exists_without_empty(tmp_path): 

62 path = tmp_path / "temp_dir" 

63 sub_path = create_directory(path / "sub") 

64 

65 create_directory(path, empty=False) 

66 assert sub_path.exists() 

67 

68 

69def test_create_directory_that_exists_with_empty(tmp_path): 

70 path = tmp_path / "temp_dir" 

71 sub_path = create_directory(path / "sub") 

72 

73 create_directory(path) 

74 assert path.exists() 

75 assert not sub_path.exists() 

76 

77 

78def test_create_directory_without_empty_when_path_is_a_file(tmp_path): 

79 path = create_file(tmp_path / "file.txt", contents="data") 

80 

81 with pytest.raises(FileExistsError) as exception_info: 

82 create_directory(path, empty=False) 

83 assert str(exception_info.value) == f"Requested directory path already exists as a file: {path}" 

84 

85 assert read_file(path) == "data" 

86 

87 

88def test_file_is_in_directory(tmp_path): 

89 assert file_is_in_directory(tmp_path / "file.txt", [tmp_path]) 

90 assert not file_is_in_directory(tmp_path / "file.txt", [tmp_path / "sub"]) 

91 

92 assert file_is_in_directory( 

93 tmp_path / "sub" / "file.txt", [tmp_path / "sub", tmp_path / "sub2"] 

94 ) 

95 assert not file_is_in_directory(tmp_path / "file.txt", [tmp_path / "sub", tmp_path / "sub2"]) 

96 assert not file_is_in_directory( 

97 tmp_path / "sub" / "file.txt", [tmp_path / "sub2", tmp_path / "sub3"] 

98 ) 

99 

100 

101def test_path_relative_to(): 

102 this_file = Path(__file__) 

103 this_dir = this_file.parent 

104 parent = this_dir.parent 

105 

106 assert path_relative_to(this_file, this_dir) == Path(this_file.name) 

107 assert path_relative_to(this_file, parent) == Path(this_dir.name) / this_file.name 

108 assert ( 

109 path_relative_to(this_file, parent / "whatever") 

110 == Path("..") / this_dir.name / this_file.name 

111 ) 

112 

113 

114@pytest.mark.skipif(not system_is_windows(), reason="Path manipulation is different on Windows") 

115def test_path_relative_to_on_different_windows_drive(): 

116 path = Path("C:/apa/hest.vhd") 

117 other = Path("D:/zebra") 

118 

119 assert path_relative_to(path, other) == path 

120 

121 

122def test_path_relative_to_on_different_linux_mount(): 

123 path = Path("/home/apa/hest.vhd") 

124 other = Path("/mnt/zebra") 

125 

126 assert path_relative_to(path, other) == Path("../../home/apa/hest.vhd") 

127 

128 

129def test_read_last_lines_of_file_with_short_file(tmp_path): 

130 # A file that is smaller than the buffer size 

131 data = "a\nb\nc" 

132 file = create_file(tmp_path / "data.txt", contents=data) 

133 assert read_last_lines_of_file(file, num_lines=10) == data 

134 

135 

136def test_read_last_lines_of_file_with_long_file(tmp_path): 

137 # A file that is larger than the buffer size 

138 data_trash = (("a" * 700) + "\n") * 3000 

139 data_last_lines = (("b" * 700) + "\n") * 10 

140 file = create_file(tmp_path / "data.txt", contents=data_trash + data_last_lines) 

141 assert read_last_lines_of_file(file, num_lines=10) == data_last_lines 

142 

143 

144def test_read_last_lines_of_file_with_trailing_newlines(tmp_path): 

145 # A file that is smaller than the buffer size 

146 data = "a\nb\n\n \n\n" 

147 file = create_file(tmp_path / "data.txt", contents=data) 

148 assert read_last_lines_of_file(file, num_lines=10) == data 

149 

150 

151def test_read_last_lines_of_file_with_empty_file(tmp_path): 

152 data = "" 

153 file = create_file(tmp_path / "data.txt", contents=data) 

154 assert read_last_lines_of_file(file, num_lines=10) == data 

155 

156 data = "\n" 

157 file = create_file(tmp_path / "data.txt", contents=data) 

158 assert read_last_lines_of_file(file, num_lines=10) == data 

159 

160 

161def test_prepend_file(tmp_path): 

162 assert ( 

163 read_file( 

164 prepend_file( 

165 file_path=create_file(tmp_path / "data.txt", contents="data"), text="hello\nmy_" 

166 ) 

167 ) 

168 == "hello\nmy_data" 

169 ) 

170 

171 

172def test_prepend_file_with_empty_file(tmp_path): 

173 assert read_file(prepend_file(file_path=create_file(tmp_path / "data.txt"), text="a")) == "a" 

174 

175 

176def test_run_command_called_with_nonexisting_binary_should_raise_exception(): 

177 cmd = ["/apa/hest/zebra.exe", "foobar"] 

178 with pytest.raises(FileNotFoundError): 

179 run_command(cmd) 

180 

181 

182def test_run_command_with_non_zero_return_code_should_raise_exception(): 

183 cmd = ["ls", "/apa/hest/zebra"] 

184 with pytest.raises(subprocess.CalledProcessError): 

185 run_command(cmd) 

186 

187 

188def test_run_command_called_with_non_list_should_raise_exception(): 

189 cmd = ["ls", "-la"] 

190 run_command(cmd) 

191 

192 cmd = "ls -la" 

193 with pytest.raises(TypeError) as exception_info: 

194 run_command(cmd) 

195 assert str(exception_info.value).startswith("Must be called with a list") 

196 

197 

198def test_run_command_should_capture_output_as_strings(): 

199 this_dir = Path(__file__).parent.resolve() 

200 

201 cmd = ["ls", str(this_dir)] 

202 result = run_command(cmd, capture_output=True) 

203 

204 assert isinstance(result.stdout, str) 

205 assert isinstance(result.stderr, str) 

206 

207 assert result.stderr == "" 

208 

209 # Show that it is regular text with regular newlines. 

210 assert "\ntest_system_utils.py\n" in result.stdout 

211 assert "\ntest_ip_core_file.py\n" in result.stdout