1#!/usr/bin/env python
2
3from __future__ import print_function
4
5import os
6import os.path
7import subprocess
8
9import util
10
11#
12# Utility Functions
13#
14
15def _test_truncation(filename, path_to_be_archived, bytes_to_chop, *args):
16	with util.archive_created(filename, path_to_be_archived) as path:
17		with open("/dev/null", "w") as bitbucket:
18			size = os.stat(path).st_size
19			while size > 0:
20				last_size = size
21				size = max(0, size - bytes_to_chop)
22				with open(path, "w+") as f:
23					f.truncate(size)
24
25				with util.directory_created("scratch") as directory:
26					returncode = subprocess.call(["xar", "-x", "-f", path, "-C", directory], stderr=bitbucket)
27					assert returncode != 0, "xar claimed to succeed when extracting a truncated archive"
28
29#
30# Test Cases
31#
32
33def large_uncompressed(filename):
34	_test_truncation(filename, "/usr/share/man/man1", 1024 * 1024, "--compression=none")
35
36def large_default_compression(filename):
37	_test_truncation(filename, "/usr/share/man/man1", 1024 * 1024)
38
39def large_gzip_compressed(filename):
40	util.skip_if_no_compression_support("gzip")
41	_test_truncation(filename, "/usr/share/man/man1", 1024 * 1024, "--compression=gzip")
42
43def large_bzip2_compressed(filename):
44	util.skip_if_no_compression_support("bzip2")
45	_test_truncation(filename, "/usr/share/man/man1", 1024 * 1024, "--compression=bzip2")
46
47def large_lzma_compressed(filename):
48	util.skip_if_no_compression_support("lzma")
49	_test_truncation(filename, "/usr/share/man/man1", 1024 * 1024, "--compression=lzma")
50
51# "small" variants use a non-base-2 size to try to catch issues that occur on uneven boundaries
52
53def small_uncompressed(filename):
54	_test_truncation(filename, "/bin", 43651, "--compression=none")
55
56def small_default_compression(filename):
57	_test_truncation(filename, "/bin", 43651)
58
59def small_gzip_compressed(filename):
60	util.skip_if_no_compression_support("gzip")
61	_test_truncation(filename, "/bin", 43651, "--compression=gzip")
62
63def small_bzip2_compressed(filename):
64	util.skip_if_no_compression_support("bzip2")
65	_test_truncation(filename, "/bin", 43651, "--compression=bzip2")
66
67def small_lzma_compressed(filename):
68	util.skip_if_no_compression_support("lzma")
69	_test_truncation(filename, "/bin", 43651, "--compression=lzma")
70
71
72TEST_CASES = (large_uncompressed, large_default_compression,
73              large_gzip_compressed, large_bzip2_compressed, large_lzma_compressed,
74              small_uncompressed, small_default_compression,
75              small_gzip_compressed, small_bzip2_compressed, small_lzma_compressed)
76
77if __name__ == "__main__":
78	for case in TEST_CASES:
79		try:
80			case("{f}.xar".format(f=case.func_name))
81			print("PASSED: {f}".format(f=case.func_name))
82		except (AssertionError, IOError, subprocess.CalledProcessError):
83			import sys, os
84			print("FAILED: {f}".format(f=case.func_name))
85			sys.excepthook(*sys.exc_info())
86			print("")
87		except util.TestCaseSkipError, e:
88			print("SKIPPED: {f}: {m}".format(f=case.func_name, m=e.message))
89