diff options
author | Amin Hassani <ahassani@google.com> | 2018-02-16 12:00:55 -0800 |
---|---|---|
committer | Amin Hassani <ahassani@google.com> | 2018-02-21 17:37:13 -0800 |
commit | 8ae416c7e73a78c688178b51de1cae7a7a686f6d (patch) | |
tree | 264da56891aac8f88c8e09bd1ba2800e797a1a1d | |
parent | fb877fc98cc72462d3e58e7d744184908408d72f (diff) | |
download | platform_external_puffin-8ae416c7e73a78c688178b51de1cae7a7a686f6d.tar.gz platform_external_puffin-8ae416c7e73a78c688178b51de1cae7a7a686f6d.tar.bz2 platform_external_puffin-8ae416c7e73a78c688178b51de1cae7a7a686f6d.zip |
Add test_corpus.py script for testing a corpus of compressed files.
This test has two tests: puffhuff and puffdiff.
- puffhuff runs the puffhuff operation of puffin to make sure a puffed and
huffed file matches the origial one.
- puffdiff runs the puffdiff followed by puffpatch operation of puffin to
make sure diffing and patching files works correctly. For now each pair of
file in the corpus is tested.
$ ./test_corpus.py --help
usage: test_corpus.py [-h] [-d [[...]]] [--cache_size SIZE] [--debug] CORPUS
positional arguments:
CORPUS A corpus directory containing compressed files
optional arguments:
-h, --help show this help message and exit
-d [ [ ...]], --disabled_tests [ [ ...]]
Space separated list of tests to disable. Allowed
options include: puffhuff, puffdiff
--cache_size SIZE The size of the cache for puffpatch operations.
--debug Turns on verbosity.
Bug: 73487244
Test: ./test_corpus.py --debug ~/trunk/images/deflates/puffin_corpus
Change-Id: I2b0adc4b48d9b9a4c446b3604fa2e6132f843be8
-rwxr-xr-x | scripts/test_corpus.py | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/scripts/test_corpus.py b/scripts/test_corpus.py new file mode 100755 index 0000000..e62b680 --- /dev/null +++ b/scripts/test_corpus.py @@ -0,0 +1,141 @@ +#!/usr/bin/env python3 +# +# Copyright 2018 The Chromium OS Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# + +"""A tool for running puffin tests in a corpus of deflate compressed files.""" + +import argparse +import filecmp +import logging +import os +import subprocess +import sys +import tempfile + +_PUFFHUFF = 'puffhuff' +_PUFFDIFF = 'puffdiff' +TESTS = (_PUFFHUFF, _PUFFDIFF) + + +class Error(Exception): + """Puffin general processing error.""" + + +def ParseArguments(argv): + """Parses and Validates command line arguments. + + Args: + argv: command line arguments to parse. + + Returns: + The arguments list. + """ + parser = argparse.ArgumentParser() + + parser.add_argument('corpus', metavar='CORPUS', + help='A corpus directory containing compressed files') + parser.add_argument('-d', '--disabled_tests', default=(), metavar='', + nargs='*', + help=('Space separated list of tests to disable. ' + 'Allowed options include: ' + ', '.join(TESTS)), + choices=TESTS) + parser.add_argument('--cache_size', type=int, metavar='SIZE', + help='The size (in bytes) of the cache for puffpatch ' + 'operations.') + parser.add_argument('--debug', action='store_true', + help='Turns on verbosity.') + + # Parse command-line arguments. + args = parser.parse_args(argv) + + if not os.path.isdir(args.corpus): + raise Error('Corpus directory {} is non-existent or inaccesible' + .format(args.corpus)) + return args + + +def main(argv): + """The main function.""" + args = ParseArguments(argv[1:]) + + if args.debug: + logging.getLogger().setLevel(logging.DEBUG) + + # Construct list of appropriate files. + files = list(filter(os.path.isfile, [os.path.join(args.corpus, f) + for f in os.listdir(args.corpus)])) + + # For each file in corpus run puffhuff. + if _PUFFHUFF not in args.disabled_tests: + for src in files: + with tempfile.NamedTemporaryFile() as tgt_file: + + operation = 'puffhuff' + logging.debug('Running %s on %s', operation, src) + cmd = ['puffin', + '--operation={}'.format(operation), + '--src_file={}'.format(src), + '--dst_file={}'.format(tgt_file.name)] + if subprocess.call(cmd) != 0: + raise Error('Puffin failed to do {} command: {}' + .format(operation, cmd)) + + if not filecmp.cmp(src, tgt_file.name): + raise Error('The generated file {} is not equivalent to the original ' + 'file {} after {} operation.' + .format(tgt_file.name, src, operation)) + + if _PUFFDIFF not in args.disabled_tests: + # Run puffdiff and puffpatch for each pairs of files in the corpus. + for src in files: + for tgt in files: + with tempfile.NamedTemporaryFile() as patch, \ + tempfile.NamedTemporaryFile() as new_tgt: + + operation = 'puffdiff' + logging.debug('Running %s on %s (%d) and %s (%d)', + operation, + os.path.basename(src), os.stat(src).st_size, + os.path.basename(tgt), os.stat(tgt).st_size) + cmd = ['puffin', + '--operation={}'.format(operation), + '--src_file={}'.format(src), + '--dst_file={}'.format(tgt), + '--patch_file={}'.format(patch.name)] + + # Running the puffdiff operation + if subprocess.call(cmd) != 0: + raise Error('Puffin failed to do {} command: {}' + .format(operation, cmd)) + + logging.debug('Patch size is: %d', os.stat(patch.name).st_size) + + operation = 'puffpatch' + logging.debug('Running %s on src file %s and patch %s', + operation, os.path.basename(src), patch.name) + cmd = ['puffin', + '--operation={}'.format(operation), + '--src_file={}'.format(src), + '--dst_file={}'.format(new_tgt.name), + '--patch_file={}'.format(patch.name)] + if args.cache_size: + cmd += ['--cache_size={}'.format(args.cache_size)] + + # Running the puffpatch operation + if subprocess.call(cmd) != 0: + raise Error('Puffin failed to do {} command: {}' + .format(operation, cmd)) + + if not filecmp.cmp(tgt, new_tgt.name): + raise Error('The generated file {} is not equivalent to the ' + 'original file {} after puffpatch operation.' + .format(new_tgt.name, tgt)) + + return 0 + + +if __name__ == '__main__': + sys.exit(main(sys.argv)) |