1#!/usr/bin/env python 2 3from __future__ import print_function 4 5import glob 6import os 7import os.path 8import re 9import shutil 10import subprocess 11 12import util 13 14 15# 16# Utility Functions 17# 18 19def _file_offsets_for_archive(path, xsl_path): 20 subprocess.check_call(["xar", "--dump-toc=heap_toc.xml", "-f", path]) 21 try: 22 offsets = subprocess.check_output(["xsltproc", os.path.realpath(xsl_path), "heap_toc.xml"]) 23 matches = [re.match("^(.+)\s([^\s]+)$", offset) for offset in offsets.splitlines()] 24 offsets = [(match.groups()[0], int(match.groups()[1])) for match in matches] 25 return offsets 26 finally: 27 os.unlink("heap_toc.xml") 28 29# 30# Test Cases 31# 32 33def normal_heap(filename): 34 with util.directory_created("scratch") as directory: 35 shutil.copy("/bin/ls", os.path.join(directory, "ls")) 36 shutil.copy(os.path.join(directory, "ls"), os.path.join(directory, "foo")) 37 with util.chdir(directory): 38 with util.archive_created(os.path.join("..", "heap.xar"), ".") as path: 39 # Verify file offsets are as we expect 40 offsets = _file_offsets_for_archive(path, os.path.join("..", "heap1.xsl")) 41 (f1, o1) = offsets[0] 42 (f2, o2) = offsets[1] 43 44 assert o1 < o2, "offset for first file \"{f1}\" ({o1}) greater than or equal to offset for last file \"{f2}\" ({o2})".format(f1=f1, o1=o1, f2=f2, o2=o2) 45 46 # Make sure extraction goes all right 47 with util.directory_created("extracted") as extracted: 48 subprocess.check_call(["xar", "-x", "-f", path, "-C", extracted]) 49 50def coalesce_heap(filename): 51 with util.directory_created("scratch") as directory: 52 shutil.copy("/bin/ls", os.path.join(directory, "ls")) 53 shutil.copy(os.path.join(directory, "ls"), os.path.join(directory, "foo")) 54 with util.chdir(directory): 55 with util.archive_created(os.path.join("..", "heap.xar"), ".", "--coalesce-heap") as path: 56 # Verify file offsets are as we expect 57 offsets = _file_offsets_for_archive(path, os.path.join("..", "heap1.xsl")) 58 (f1, o1) = offsets[0] 59 (f2, o2) = offsets[1] 60 61 # Make sure extraction goes all right 62 with util.directory_created("extracted") as extracted: 63 subprocess.check_call(["xar", "-x", "-f", path, "-C", extracted]) 64 65TEST_CASES = (normal_heap, coalesce_heap) 66 67if __name__ == "__main__": 68 for case in TEST_CASES: 69 try: 70 case("{f}.xar".format(f=case.func_name)) 71 print("PASSED: {f}".format(f=case.func_name)) 72 except (AssertionError, IOError, subprocess.CalledProcessError): 73 import sys, os 74 print("FAILED: {f}".format(f=case.func_name)) 75 sys.excepthook(*sys.exc_info()) 76 print("") 77