MCPcopy
hub / github.com/borgbackup/borg / test_sparse_file

Function test_sparse_file

src/borg/testsuite/archiver/extract_cmd_test.py:185–238  ·  view source on GitHub ↗
(archivers, request)

Source from the content-addressed store, hash-verified

183
184
185def test_sparse_file(archivers, request):
186 archiver = request.getfixturevalue(archivers)
187
188 def is_sparse(fn, total_size, hole_size):
189 st = os.stat(fn)
190 assert st.st_size == total_size
191 sparse = True
192 if sparse and hasattr(st, "st_blocks") and st.st_blocks * 512 >= st.st_size:
193 sparse = False
194 if sparse and has_seek_hole:
195 with open(fn, "rb") as fd:
196 # only check if the first hole is as expected, because the 2nd hole check
197 # is problematic on xfs due to its "dynamic speculative EOF pre-allocation
198 try:
199 if fd.seek(0, os.SEEK_HOLE) != 0:
200 sparse = False
201 if fd.seek(0, os.SEEK_DATA) != hole_size:
202 sparse = False
203 except OSError:
204 # OS/FS does not really support SEEK_HOLE/SEEK_DATA
205 sparse = False
206 return sparse
207
208 filename_in = os.path.join(archiver.input_path, "sparse")
209 content = b"foobar"
210 hole_size = 5 * (1 << CHUNK_MAX_EXP) # 5 full chunker buffers
211 total_size = hole_size + len(content) + hole_size
212 with open(filename_in, "wb") as fd:
213 # create a file that has a hole at the beginning and end (if the
214 # OS and filesystem supports sparse files)
215 fd.seek(hole_size, 1)
216 fd.write(content)
217 fd.seek(hole_size, 1)
218 pos = fd.tell()
219 fd.truncate(pos)
220 # we first check if we could create a sparse input file:
221 sparse_support = is_sparse(filename_in, total_size, hole_size)
222 if sparse_support:
223 # we could create a sparse input file, so creating a backup of it and
224 # extracting it again (as sparse) should also work:
225 cmd(archiver, "repo-create", RK_ENCRYPTION)
226 cmd(archiver, "create", "test", "input")
227 with changedir(archiver.output_path):
228 cmd(archiver, "extract", "test", "--sparse")
229 assert_dirs_equal("input", "output/input")
230 filename_out = os.path.join(archiver.output_path, "input", "sparse")
231 with open(filename_out, "rb") as fd:
232 # check if file contents are as expected
233 assert fd.read(hole_size) == b"\0" * hole_size
234 assert fd.read(len(content)) == content
235 assert fd.read(hole_size) == b"\0" * hole_size
236 assert is_sparse(filename_out, total_size, hole_size)
237 os.unlink(filename_out) # save space on TMPDIR
238 os.unlink(filename_in) # save space on TMPDIR
239
240
241def test_unusual_filenames(archivers, request):

Callers

nothing calls this directly

Calls 9

is_sparseFunction · 0.85
cmdFunction · 0.85
changedirFunction · 0.85
assert_dirs_equalFunction · 0.85
truncateMethod · 0.80
seekMethod · 0.45
writeMethod · 0.45
tellMethod · 0.45
readMethod · 0.45

Tested by

no test coverage detected