diff --git a/README.md b/README.md index 05c3f49..c412118 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,4 @@ -Intro -===== +## Intro *gzip-js* is a pure JavaScript implementation of the GZIP file format. It uses the DEFLATE algorithm for compressing data. @@ -7,13 +6,12 @@ Please note that since this is a pure JavaScript implementation, it should NOT b The main goal of this project is to bring GZIP compression to the browser. -API -=== +## API There is only one function so far, zip: function zip(data[, options]) - + * data- String of text or byte array to compress * options- object with options; options include: * level- compression level (1-9); default 6 @@ -23,11 +21,11 @@ function zip(data[, options]) Sample usage: var gzip = require('gzip-js'), - options = { - level: 3, - name: 'hello-world.txt', - timestamp: parseInt(Date.now() / 1000, 10) - }; - - // out will be a JavaScript Array of bytes - var out = gzip.zip('Hello world', options); + options = { + level: 3, + name: 'hello-world.txt', + timestamp: parseInt(Date.now() / 1000, 10) + }; + + // out will be a JavaScript Array of bytes + var out = gzip.zip('Hello world', options); diff --git a/bin/gunzip.js b/bin/gunzip.js index df6cf47..cfb3723 100755 --- a/bin/gunzip.js +++ b/bin/gunzip.js @@ -1,27 +1,27 @@ #!/usr/bin/env node + (function () { - 'use strict'; + "use strict"; - var fs = require('fs'), - optimist = require('optimist'), - gzip = require('../lib/gzip.js'), - argv, - level, - stat, - out; + var fs = require("fs"); + var optimist = require("optimist"); + var gzip = require("../lib/gzip.js"); + var argv; + var stat; + var out; - argv = optimist.usage('Usage: $0 --file [filename] --output [filename]') - .alias({ - 'f': 'file', - 'o': 'output' - }) - .demand(['file']).argv; + argv = optimist.usage("Usage: $0 --file [filename] --output [filename]") + .alias({ + "f": "file", + "o": "output" + }) + .demand(["file"]).argv; - stat = fs.statSync(argv.file); - out = gzip.unzip(fs.readFileSync(argv.file), { - name: argv.file, - timestamp: parseInt(Math.round(stat.mtime.getTime() / 1000)) - }); + stat = fs.statSync(argv.file); + out = gzip.unzip(fs.readFileSync(argv.file), { + name: argv.file, + timestamp: parseInt(Math.round(stat.mtime.getTime() / 1000)) + }); - fs.writeFileSync(argv.output || argv.file.replace(/\.gz$/, ''), new Buffer(out)); + fs.writeFileSync(argv.output || argv.file.replace(/\.gz$/, ""), new Buffer(out)); }()); diff --git a/bin/gzip.js b/bin/gzip.js index a098137..cfb3723 100755 --- a/bin/gzip.js +++ b/bin/gzip.js @@ -1,30 +1,27 @@ #!/usr/bin/env node + (function () { - 'use strict'; + "use strict"; - var fs = require('fs'), - optimist = require('optimist'), - gzip = require('../lib/gzip.js'), - argv, - level, - stat, - out; + var fs = require("fs"); + var optimist = require("optimist"); + var gzip = require("../lib/gzip.js"); + var argv; + var stat; + var out; - argv = optimist.usage('Usage: $0 --level [1-9] --file [filename] --output [filename]') - .alias({ - 'f': 'file', - 'o': 'output', - 'l': 'level' - }) - .default('level', gzip.DEFAULT_LEVEL) - .demand(['file']).argv; + argv = optimist.usage("Usage: $0 --file [filename] --output [filename]") + .alias({ + "f": "file", + "o": "output" + }) + .demand(["file"]).argv; - stat = fs.statSync(argv.file); - out = gzip.zip(fs.readFileSync(argv.file), { - name: argv.file, - level: argv.level, - timestamp: parseInt(Math.round(stat.mtime.getTime() / 1000)) - }); + stat = fs.statSync(argv.file); + out = gzip.unzip(fs.readFileSync(argv.file), { + name: argv.file, + timestamp: parseInt(Math.round(stat.mtime.getTime() / 1000)) + }); - fs.writeFileSync(argv.output || argv.file + '.gz', new Buffer(out)); + fs.writeFileSync(argv.output || argv.file.replace(/\.gz$/, ""), new Buffer(out)); }()); diff --git a/lib/gzip.js b/lib/gzip.js index 5b2006d..33f9be5 100644 --- a/lib/gzip.js +++ b/lib/gzip.js @@ -1,280 +1,280 @@ (function () { - 'use strict'; - - var crc32 = require('crc32'), - deflate = require('deflate-js'), - // magic numbers marking this file as GZIP - ID1 = 0x1F, - ID2 = 0x8B, - compressionMethods = { - 'deflate': 8 - }, - possibleFlags = { - 'FTEXT': 0x01, - 'FHCRC': 0x02, - 'FEXTRA': 0x04, - 'FNAME': 0x08, - 'FCOMMENT': 0x10 - }, - osMap = { - 'fat': 0, // FAT file system (DOS, OS/2, NT) + PKZIPW 2.50 VFAT, NTFS - 'amiga': 1, // Amiga - 'vmz': 2, // VMS (VAX or Alpha AXP) - 'unix': 3, // Unix - 'vm/cms': 4, // VM/CMS - 'atari': 5, // Atari - 'hpfs': 6, // HPFS file system (OS/2, NT 3.x) - 'macintosh': 7, // Macintosh - 'z-system': 8, // Z-System - 'cplm': 9, // CP/M - 'tops-20': 10, // TOPS-20 - 'ntfs': 11, // NTFS file system (NT) - 'qdos': 12, // SMS/QDOS - 'acorn': 13, // Acorn RISC OS - 'vfat': 14, // VFAT file system (Win95, NT) - 'vms': 15, // MVS (code also taken for PRIMOS) - 'beos': 16, // BeOS (BeBox or PowerMac) - 'tandem': 17, // Tandem/NSK - 'theos': 18 // THEOS - }, - os = 'unix', - DEFAULT_LEVEL = 6; - - function putByte(n, arr) { - arr.push(n & 0xFF); - } - - // LSB first - function putShort(n, arr) { - arr.push(n & 0xFF); - arr.push(n >>> 8); - } - - // LSB first - function putLong(n, arr) { - putShort(n & 0xffff, arr); - putShort(n >>> 16, arr); - } - - function putString(s, arr) { - var i, len = s.length; - for (i = 0; i < len; i += 1) { - putByte(s.charCodeAt(i), arr); - } - } - - function readByte(arr) { - return arr.shift(); - } - - function readShort(arr) { - return arr.shift() | (arr.shift() << 8); - } - - function readLong(arr) { - var n1 = readShort(arr), - n2 = readShort(arr); - - // JavaScript can't handle bits in the position 32 - // we'll emulate this by removing the left-most bit (if it exists) - // and add it back in via multiplication, which does work - if (n2 > 32768) { - n2 -= 32768; - - return ((n2 << 16) | n1) + 32768 * Math.pow(2, 16); - } - - return (n2 << 16) | n1; - } - - function readString(arr) { - var charArr = []; - - // turn all bytes into chars until the terminating null - while (arr[0] !== 0) { - charArr.push(String.fromCharCode(arr.shift())); - } - - // throw away terminating null - arr.shift(); - - // join all characters into a cohesive string - return charArr.join(''); - } - - /* - * Reads n number of bytes and return as an array. - * - * @param arr- Array of bytes to read from - * @param n- Number of bytes to read - */ - function readBytes(arr, n) { - var i, ret = []; - for (i = 0; i < n; i += 1) { - ret.push(arr.shift()); - } - - return ret; - } - - /* - * ZIPs a file in GZIP format. The format is as given by the spec, found at: - * http://www.gzip.org/zlib/rfc-gzip.html - * - * Omitted parts in this implementation: - */ - function zip(data, options) { - var flags = 0, - level, - crc, out = []; - - if (!options) { - options = {}; - } - level = options.level || DEFAULT_LEVEL; - - if (typeof data === 'string') { - data = Array.prototype.map.call(data, function (char) { - return char.charCodeAt(0); - }); - } - - // magic number marking this file as GZIP - putByte(ID1, out); - putByte(ID2, out); - - putByte(compressionMethods['deflate'], out); - - if (options.name) { - flags |= possibleFlags['FNAME']; - } - - putByte(flags, out); - putLong(options.timestamp || parseInt(Date.now() / 1000, 10), out); - - // put deflate args (extra flags) - if (level === 1) { - // fastest algorithm - putByte(4, out); - } else if (level === 9) { - // maximum compression (fastest algorithm) - putByte(2, out); - } else { - putByte(0, out); - } - - // OS identifier - putByte(osMap[os], out); - - if (options.name) { - // ignore the directory part - putString(options.name.substring(options.name.lastIndexOf('/') + 1), out); - - // terminating null - putByte(0, out); - } - - deflate.deflate(data, level).forEach(function (byte) { - putByte(byte, out); - }); - - putLong(parseInt(crc32(data), 16), out); - putLong(data.length, out); - - return out; - } - - function unzip(data) { - // start with a copy of the array - var arr = Array.prototype.slice.call(data, 0), - t, - compressionMethod, - flags, - mtime, - xFlags, - key, - os, - crc, - size, - res; - - // check the first two bytes for the magic numbers - if (readByte(arr) !== ID1 || readByte(arr) !== ID2) { - throw 'Not a GZIP file'; - } - - t = readByte(arr); - t = Object.keys(compressionMethods).some(function (key) { - compressionMethod = key; - return compressionMethods[key] === t; - }); - - if (!t) { - throw 'Unsupported compression method'; - } - - flags = readByte(arr); - mtime = readLong(arr); - xFlags = readByte(arr); - t = readByte(arr); - Object.keys(osMap).some(function (key) { - if (osMap[key] === t) { - os = key; - return true; - } - }); - - // just throw away the bytes for now - if (flags & possibleFlags['FEXTRA']) { - t = readShort(arr); - readBytes(arr, t); - } - - // just throw away for now - if (flags & possibleFlags['FNAME']) { - readString(arr); - } - - // just throw away for now - if (flags & possibleFlags['FCOMMENT']) { - readString(arr); - } - - // just throw away for now - if (flags & possibleFlags['FHCRC']) { - readShort(arr); - } - - if (compressionMethod === 'deflate') { - // give deflate everything but the last 8 bytes - // the last 8 bytes are for the CRC32 checksum and filesize - res = deflate.inflate(arr.splice(0, arr.length - 8)); - } - - if (flags & possibleFlags['FTEXT']) { - res = Array.prototype.map.call(res, function (byte) { - return String.fromCharCode(byte); - }).join(''); - } - - crc = readLong(arr) >>> 0; - if (crc !== parseInt(crc32(res), 16)) { - throw 'Checksum does not match'; - } - - size = readLong(arr); - if (size !== res.length) { - throw 'Size of decompressed file not correct'; - } - - return res; - } - - module.exports = { - zip: zip, - unzip: unzip, - get DEFAULT_LEVEL() { - return DEFAULT_LEVEL; - } - }; + 'use strict'; + + var crc32 = require('crc32'), + deflate = require('deflate-js'), + // magic numbers marking this file as GZIP + ID1 = 0x1F, + ID2 = 0x8B, + compressionMethods = { + 'deflate': 8 + }, + possibleFlags = { + 'FTEXT': 0x01, + 'FHCRC': 0x02, + 'FEXTRA': 0x04, + 'FNAME': 0x08, + 'FCOMMENT': 0x10 + }, + osMap = { + 'fat': 0, // FAT file system (DOS, OS/2, NT) + PKZIPW 2.50 VFAT, NTFS + 'amiga': 1, // Amiga + 'vmz': 2, // VMS (VAX or Alpha AXP) + 'unix': 3, // Unix + 'vm/cms': 4, // VM/CMS + 'atari': 5, // Atari + 'hpfs': 6, // HPFS file system (OS/2, NT 3.x) + 'macintosh': 7, // Macintosh + 'z-system': 8, // Z-System + 'cplm': 9, // CP/M + 'tops-20': 10, // TOPS-20 + 'ntfs': 11, // NTFS file system (NT) + 'qdos': 12, // SMS/QDOS + 'acorn': 13, // Acorn RISC OS + 'vfat': 14, // VFAT file system (Win95, NT) + 'vms': 15, // MVS (code also taken for PRIMOS) + 'beos': 16, // BeOS (BeBox or PowerMac) + 'tandem': 17, // Tandem/NSK + 'theos': 18 // THEOS + }, + os = 'unix', + DEFAULT_LEVEL = 6; + + function putByte(n, arr) { + arr.push(n & 0xFF); + } + + // LSB first + function putShort(n, arr) { + arr.push(n & 0xFF); + arr.push(n >>> 8); + } + + // LSB first + function putLong(n, arr) { + putShort(n & 0xffff, arr); + putShort(n >>> 16, arr); + } + + function putString(s, arr) { + var i, len = s.length; + for (i = 0; i < len; i += 1) { + putByte(s.charCodeAt(i), arr); + } + } + + function readByte(arr) { + return arr.shift(); + } + + function readShort(arr) { + return arr.shift() | (arr.shift() << 8); + } + + function readLong(arr) { + var n1 = readShort(arr), + n2 = readShort(arr); + + // JavaScript can't handle bits in the position 32 + // we'll emulate this by removing the left-most bit (if it exists) + // and add it back in via multiplication, which does work + if (n2 > 32768) { + n2 -= 32768; + + return ((n2 << 16) | n1) + 32768 * Math.pow(2, 16); + } + + return (n2 << 16) | n1; + } + + function readString(arr) { + var charArr = []; + + // turn all bytes into chars until the terminating null + while (arr[0] !== 0) { + charArr.push(String.fromCharCode(arr.shift())); + } + + // throw away terminating null + arr.shift(); + + // join all characters into a cohesive string + return charArr.join(''); + } + + /* + * Reads n number of bytes and return as an array. + * + * @param arr- Array of bytes to read from + * @param n- Number of bytes to read + */ + function readBytes(arr, n) { + var i, ret = []; + for (i = 0; i < n; i += 1) { + ret.push(arr.shift()); + } + + return ret; + } + + /* + * ZIPs a file in GZIP format. The format is as given by the spec, found at: + * http://www.gzip.org/zlib/rfc-gzip.html + * + * Omitted parts in this implementation: + */ + function zip(data, options) { + var flags = 0, + level, + out = []; + + if (!options) { + options = {}; + } + level = options.level || DEFAULT_LEVEL; + + if (typeof data === 'string') { + data = Array.prototype.map.call(data, function (char) { + return char.charCodeAt(0); + }); + } + + // magic number marking this file as GZIP + putByte(ID1, out); + putByte(ID2, out); + + putByte(compressionMethods.deflate, out); + + if (options.name) { + flags |= possibleFlags.FNAME; + } + + putByte(flags, out); + putLong(options.timestamp || parseInt(Date.now() / 1000, 10), out); + + // put deflate args (extra flags) + if (level === 1) { + // fastest algorithm + putByte(4, out); + } else if (level === 9) { + // maximum compression (fastest algorithm) + putByte(2, out); + } else { + putByte(0, out); + } + + // OS identifier + putByte(osMap[os], out); + + if (options.name) { + // ignore the directory part + putString(options.name.substring(options.name.lastIndexOf('/') + 1), out); + + // terminating null + putByte(0, out); + } + + deflate.deflate(data, level).forEach(function (byte) { + putByte(byte, out); + }); + + putLong(parseInt(crc32(data), 16), out); + putLong(data.length, out); + + return out; + } + + function unzip(data) { + // start with a copy of the array + var arr = Array.prototype.slice.call(data, 0), + t, + compressionMethod, + flags, + mtime, + xFlags, + key, + os, + crc, + size, + res; + + // check the first two bytes for the magic numbers + if (readByte(arr) !== ID1 || readByte(arr) !== ID2) { + throw 'Not a GZIP file'; + } + + t = readByte(arr); + t = Object.keys(compressionMethods).some(function (key) { + compressionMethod = key; + return compressionMethods[key] === t; + }); + + if (!t) { + throw 'Unsupported compression method'; + } + + flags = readByte(arr); + mtime = readLong(arr); + xFlags = readByte(arr); + t = readByte(arr); + Object.keys(osMap).some(function (key) { + if (osMap[key] === t) { + os = key; + return true; + } + }); + + // just throw away the bytes for now + if (flags & possibleFlags.FEXTRA) { + t = readShort(arr); + readBytes(arr, t); + } + + // just throw away for now + if (flags & possibleFlags.FNAME) { + readString(arr); + } + + // just throw away for now + if (flags & possibleFlags.FCOMMENT) { + readString(arr); + } + + // just throw away for now + if (flags & possibleFlags.FHCRC) { + readShort(arr); + } + + if (compressionMethod === 'deflate') { + // give deflate everything but the last 8 bytes + // the last 8 bytes are for the CRC32 checksum and filesize + res = deflate.inflate(arr.splice(0, arr.length - 8)); + } + + if (flags & possibleFlags.FTEXT) { + res = Array.prototype.map.call(res, function (byte) { + return String.fromCharCode(byte); + }).join(''); + } + + crc = readLong(arr) >>> 0; + if (crc !== parseInt(crc32(res), 16)) { + throw 'Checksum does not match'; + } + + size = readLong(arr); + if (size !== res.length) { + throw 'Size of decompressed file not correct'; + } + + return res; + } + + module.exports = { + zip: zip, + unzip: unzip, + get DEFAULT_LEVEL() { + return DEFAULT_LEVEL; + } + }; }()); diff --git a/package.json b/package.json index 6535823..168b94a 100644 --- a/package.json +++ b/package.json @@ -1,29 +1,29 @@ { - "author": "T. Jameson Little ", - "name": "gzip-js", - "description": "GZIP in pure JavaScript (works in the browser)", - "version": "0.3.2", - "license": "GPL", - "repository": { - "type": "git", - "url": "git://github.com/beatgammit/gzip-js.git" - }, - "main": "./lib/gzip.js", - "bin": { - "gzip-js": "./bin/gzip.js", - "gunzip-js": "./bin/gunzip.js" - }, - "scripts": { - "test": "cd test; ./runner.py; cd -" - }, - "engines": { - "node": ">= 0.4.0" - }, - "dependencies": { - "crc32": ">= 0.2.2", - "deflate-js": ">= 0.2.2" - }, - "devDependencies": { - "optimist": "~0.2" - } + "author": "T. Jameson Little ", + "name": "gzip-js", + "description": "GZIP in pure JavaScript (works in the browser)", + "version": "0.3.2", + "license": "GPL", + "repository": { + "type": "git", + "url": "git://github.com/beatgammit/gzip-js.git" + }, + "main": "./lib/gzip.js", + "bin": { + "gzip-js": "./bin/gzip.js", + "gunzip-js": "./bin/gunzip.js" + }, + "scripts": { + "test": "cd test; ./runner.py; cd -" + }, + "engines": { + "node": ">= 0.4.0" + }, + "dependencies": { + "crc32": ">= 0.2.2", + "deflate-js": ">= 0.2.2" + }, + "devDependencies": { + "optimist": "0.2.8" + } } diff --git a/renovate.json b/renovate.json new file mode 100644 index 0000000..f45d8f1 --- /dev/null +++ b/renovate.json @@ -0,0 +1,5 @@ +{ + "extends": [ + "config:base" + ] +} diff --git a/test/helpers.py b/test/helpers.py index e69d5f3..555c74c 100644 --- a/test/helpers.py +++ b/test/helpers.py @@ -2,14 +2,15 @@ """ Convenience function for running a command bash-like - @param command- string version of a command to run on -@param shell- Whether to run this through the shell; used in subprocess.Popen (default: true) +@param shell- Whether to run this through the shell; +used in subprocess.Popen (default: true) @return Object with properties 'returncode', 'stdout', and 'stderr' """ -def run_cmd(command, shell=True): - process = sp.Popen(command, shell=shell, stdout = sp.PIPE, stderr = sp.PIPE) - stdout, stderr = process.communicate() - returncode = process.returncode - return {'returncode' : returncode, 'stdout' : stdout, 'stderr' : stderr} + +def run_cmd(command, shell=True): + process = sp.Popen(command, shell=shell, stdout=sp.PIPE, stderr=sp.PIPE) + stdout, stderr = process.communicate() + returncode = process.returncode + return {'returncode': returncode, 'stdout': stdout, 'stderr': stderr} diff --git a/test/runner.py b/test/runner.py index c072e55..fab8f3b 100755 --- a/test/runner.py +++ b/test/runner.py @@ -3,55 +3,55 @@ import os import sys import shutil -from colorama import Fore import argparse +from colorama import Fore import zipTest import unzipTest -parser = argparse.ArgumentParser(description='Process command-line arguments') -parser.add_argument('--file', '-f', metavar='path/to/file', type=str, nargs='?', help='Path to file to use for test') -parser.add_argument('--level', '-l', metavar='#', type=int, nargs='?', help='Compression level') -parser.add_argument('--no-delete', const=True, default=False, nargs='?', help='Don\'t delete files produced for test') -parser.add_argument('--test', default='both', nargs='?', help='Which test to run (zip, unzip, both)') +PARSER = argparse.ArgumentParser(description='Process command-line arguments') +PARSER.add_argument('--file', '-f', metavar='path/to/file', type=str, nargs='?', help='Path to file to use for test') +PARSER.add_argument('--level', '-l', metavar='#', type=int, nargs='?', help='Compression level') +PARSER.add_argument('--no-delete', const=True, default=False, nargs='?', help='Don\'t delete files produced for test') +PARSER.add_argument('--test', default='both', nargs='?', help='Which test to run (zip, unzip, both)') -args = parser.parse_args() +ARGS = PARSER.parse_args() -allPassed = True +ALL_PASSED = True -outDir = 'test-outs' +OUT_DIR = 'test-outs' # make the test-outs directory try: - os.mkdir(outDir) + os.mkdir(OUT_DIR) except: - pass - -delete = not getattr(args, 'no_delete') -level = getattr(args, 'level') -inFile = getattr(args, 'file') -test = getattr(args, 'test') - -if test == 'zip' or test == 'both': - print Fore.CYAN + 'Running zip tests' + Fore.RESET - # if the user specifies a file, only run that test - if inFile != None: - allPassed = zipTest.runTest(inFile, level) - else: - allPassed = zipTest.runAll(level) - -if test == 'unzip' or test == 'both': - print Fore.CYAN + 'Running unzip tests' + Fore.RESET - # if the user specifies a file, only run that test - if inFile != None: - allPassed = unzipTest.runTest(inFile, level) - else: - allPassed = unzipTest.runAll(level) - -if delete: - shutil.rmtree(outDir) - -if allPassed: - print Fore.GREEN + 'All tests passed!' + Fore.RESET + pass + +DELETE = not getattr(ARGS, 'no_delete') +LEVEL = getattr(ARGS, 'level') +IN_FILE = getattr(ARGS, 'file') +TEST = getattr(ARGS, 'test') + +if TEST in ('zip', 'both'): + print(Fore.CYAN + 'Running zip tests' + Fore.RESET) + # if the user specifies a file, only run that test + if IN_FILE is not None: + ALL_PASSED = zipTest.run_test(IN_FILE, LEVEL) + else: + ALL_PASSED = zipTest.run_all(LEVEL) + +if TEST in ('unzip', 'both'): + print(Fore.CYAN + 'Running unzip tests' + Fore.RESET) + # if the user specifies a file, only run that test + if IN_FILE is not None: + ALL_PASSED = unzipTest.run_test(IN_FILE, LEVEL) + else: + ALL_PASSED = unzipTest.run_all(LEVEL) + +if DELETE: + shutil.rmtree(OUT_DIR) + +if ALL_PASSED: + print(Fore.GREEN + 'All tests passed!' + Fore.RESET) else: - print Fore.RED + 'Automated test failed' + Fore.RESET - sys.exit(1) + print(Fore.RED + 'Automated test failed' + Fore.RESET) + sys.exit(1) diff --git a/test/unzipTest.py b/test/unzipTest.py index 5230134..9cad437 100644 --- a/test/unzipTest.py +++ b/test/unzipTest.py @@ -2,59 +2,68 @@ from colorama import Fore from helpers import run_cmd -outDirDefault = 'test-outs' -testDirDefault = 'test-files' +OUT_DIR_DEFAULT = 'test-outs' +TEST_DIR_DEFAULT = 'test-files' """ Run a single test - -@param tFile- required; the file to check against (uncompressed data) +@param t_file- required; the file to check against (uncompressed data) @param level- optional (default: all); the compression level [1-9] @return True if all tests passed; False if at least one test failed """ -def runTest(tFile, level=None, outDir=outDirDefault): - passed = True - if level == None: - for x in range(1, 10): - if runTest(tFile, x) == False: - passed = False - return passed +def run_test(t_file, level=None, out_dir=OUT_DIR_DEFAULT): + passed = True - out1 = os.path.join(outDir, '%(file)s.%(level)d.gz' % {'file': os.path.basename(tFile), 'level' : level}) - out2 = os.path.join(outDir, '%(file)s.%(level)d' % {'file' : os.path.basename(tFile), 'level' : level}) + if level is None: + for x in range(1, 10): + if run_test(t_file, x) is False: + passed = False - run_cmd('gzip -%(level)d -c %(file)s >> %(output)s' % {'level' : level, 'file' : tFile, 'output' : out1}) - run_cmd('../bin/gunzip.js --file %(file)s --output %(output)s' % {'level' : level, 'file' : out1, 'output' : out2}) + return passed - result = run_cmd('diff %(file1)s %(file2)s' % {'file1' : tFile, 'file2' : out2}) - if result['returncode'] == 0: - status = Fore.GREEN + 'PASSED' + Fore.RESET - else: - passed = False - status = Fore.RED + 'FAILED' + Fore.RESET - - print 'Level %(level)d: %(status)s' % {'level' : level, 'status' : status} + out1 = os.path.join(out_dir, '%(file)s.%(level)d.gz' + % {'file': os.path.basename(t_file), 'level': level}) + out2 = os.path.join(out_dir, '%(file)s.%(level)d' + % {'file': os.path.basename(t_file), 'level': level}) - return passed + run_cmd('gzip -%(level)d -c %(file)s >> %(output)s' + % {'level': level, 'file': t_file, 'output': out1}) + run_cmd('../bin/gunzip.js --file %(file)s --output %(output)s' + % {'level': level, 'file': out1, 'output': out2}) + + result = run_cmd('diff %(file1)s %(file2)s' + % {'file1': t_file, 'file2': out2}) + if result['returncode'] == 0: + status = Fore.GREEN + 'PASSED' + Fore.RESET + else: + passed = False + status = Fore.RED + 'FAILED' + Fore.RESET + + print 'Level %(level)d: %(status)s' % {'level': level, 'status': status} + + return passed -""" -Runs all tests on the given level. This iterates throuth the testDir directory defined above. +""" +Runs all tests on the given level. This iterates throuth the test_dir directory +defined above. @param level- The level to run on [1-9] (default: None, runs on all levels all) @return True if all levels passed, False if at least one failed """ -def runAll(level=None, testDir=testDirDefault, outDir=outDirDefault): - passed = True - for tFile in os.listdir(testDir): - fullPath = os.path.join(testDir, tFile) - print Fore.YELLOW + tFile + Fore.RESET - if runTest(fullPath, level) == False: - passed = False +def run_all(level=None, test_dir=TEST_DIR_DEFAULT, out_dir=OUT_DIR_DEFAULT): + passed = True + for t_file in os.listdir(test_dir): + full_path = os.path.join(test_dir, t_file) + + print Fore.YELLOW + t_file + Fore.RESET + + if run_test(full_path, level) is False: + passed = False + + print '' - print '' - - return passed + return passed diff --git a/test/zipTest.py b/test/zipTest.py index a5b221f..335f7d0 100644 --- a/test/zipTest.py +++ b/test/zipTest.py @@ -1,60 +1,68 @@ import os -from helpers import run_cmd from colorama import Fore +from helpers import run_cmd -defaultTestDir = 'test-files' -defaultOutDir = 'test-outs' +DEFAULT_TEST_DIR = 'test-files' +DEFAULT_OUT_DIR = 'test-outs' """ Run a single test -@param tFile- required; the full path to the file to run +@param t_file- required; the full path to the file to run @param level- optional (default: all); the compression level [1-9] @return True if all tests passed; False if at least one test failed """ -def runTest(tFile, level=None, outDir=defaultOutDir): - passed = True - if level == None: - for x in range(1, 10): - if runTest(tFile, x, outDir) == False: - passed = False - return passed - out1 = os.path.join(outDir, '%(file)s.%(level)d.gz' % {'file': os.path.basename(tFile), 'level' : level}) - out2 = os.path.join(outDir, '%(file)s.%(level)d.out.gz' % {'file': os.path.basename(tFile), 'level' : level}) +def run_test(t_file, level=None, out_dir=DEFAULT_OUT_DIR): + passed = True + if level is None: + for x in range(1, 10): + if run_test(t_file, x, out_dir) is False: + passed = False - run_cmd('gzip -c -%(level)d %(file)s > %(outfile)s' % {'level' : level, 'file' : tFile, 'outfile' : out1}) - run_cmd('../bin/gzip.js --level %(level)d --file %(file)s --output %(output)s' % {'level' : level, 'file' : tFile, 'output' : out2}) + return passed - result = run_cmd('diff %(file1)s %(file2)s' % {'file1' : out1, 'file2' : out2}) - if result['returncode'] == 0: - status = Fore.GREEN + 'PASSED' + Fore.RESET - else: - passed = False - status = Fore.RED + 'FAILED' + Fore.RESET - - print 'Level %(level)d: %(status)s' % {'level' : level, 'status' : status} + out1 = os.path.join(out_dir, '%(file)s.%(level)d.gz' + % {'file': os.path.basename(t_file), 'level': level}) + out2 = os.path.join(out_dir, '%(file)s.%(level)d.out.gz' + % {'file': os.path.basename(t_file), 'level': level}) - return passed + run_cmd('gzip -c -%(level)d %(file)s > %(outfile)s' + % {'level': level, 'file': t_file, 'outfile': out1}) + run_cmd('../bin/gzip.js --level %(level)d --file %(file)s --output %(output)s' % {'level': level, 'file': t_file, 'output': out2}) -""" -Runs all tests on the given level. This iterates throuth the testDir directory defined above. + result = run_cmd('diff %(file1)s %(file2)s' + % {'file1': out1, 'file2': out2}) + if result['returncode'] == 0: + status = Fore.GREEN + 'PASSED' + Fore.RESET + else: + passed = False + status = Fore.RED + 'FAILED' + Fore.RESET + + print('Level %(level)d: %(status)s' % {'level': level, 'status': status}) + + return passed + +""" +Runs all tests on the given level. This iterates through the test_dir directory +defined above. @param level- The level to run on [1-9] (default: None, runs on all levels all) @return True if all levels passed, False if at least one failed """ -def runAll(level=None, testDir=defaultTestDir): - passed = True - for tFile in os.listdir(testDir): - fullPath = os.path.join(testDir, tFile) - print Fore.YELLOW + tFile + Fore.RESET - if runTest(fullPath, level) == False: - passed = False +def run_all(level=None, test_dir=DEFAULT_TEST_DIR): + passed = True + for t_file in os.listdir(test_dir): + full_path = os.path.join(test_dir, t_file) + + print Fore.YELLOW + t_file + Fore.RESET + + if run_test(full_path, level) is False: + passed = False - print '' - - return passed + print('') + return passed