821 lines
31 KiB
JavaScript
821 lines
31 KiB
JavaScript
"use strict";
|
|
|
|
var grunt = require("grunt"),
|
|
fs = require("fs"),
|
|
gzip = require("gzip-js"),
|
|
exec = require("child_process").exec,
|
|
_ = require("lodash"),
|
|
files = [ "tasks/compare-size.js", "test/compare-size.js" ],
|
|
compressors = [ "", "gz" ],
|
|
sizecache = ".sizecache.json",
|
|
harness = "harness/harness.js",
|
|
rfileLine = /^\s*((?:[-+=?0-9]+\s+)+)(.*)/,
|
|
overwritten = {},
|
|
cacheEntry_0_3 = {},
|
|
cacheEntry = {};
|
|
|
|
function configureHarness() {
|
|
grunt.file.write( harness, "module.exports = " + [].join.call( arguments, "\n" ));
|
|
}
|
|
|
|
function indexOf( array, re ) {
|
|
var i = 0,
|
|
len = array.length;
|
|
for ( ; i < len; i++ ) {
|
|
if ( re.test( array[i] ) ) {
|
|
return i;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
function formatDelta( delta ) {
|
|
return delta ?
|
|
delta > 0 ? "+" + delta : delta :
|
|
delta === 0 ? "=" : "?";
|
|
}
|
|
|
|
function backfillCompression( cache, test ) {
|
|
Object.keys( cache ).forEach(function( label ) {
|
|
// Skip metadata
|
|
if ( !label ) {
|
|
return;
|
|
}
|
|
|
|
// Skip the last file (which was always compressed)
|
|
files.slice( 0, -1 ).forEach(function( file ) {
|
|
compressors.forEach(function( compressor ) {
|
|
// Make sure that compressed data is not already present
|
|
if ( compressor && compressor in cache[ label ][ file ] ) {
|
|
test.strictEqual( cache[ label ][ file ][ compressor ], undefined, "No " + compressor + " data" );
|
|
// ...and add it
|
|
} else if ( compressor ) {
|
|
cache[ label ][ file ][ compressor ] = cacheEntry[ file ][ compressor ];
|
|
}
|
|
});
|
|
});
|
|
});
|
|
}
|
|
|
|
function augmentCache( key, head, cache ) {
|
|
cache = cache || { "": { version: 0.4, tips: {} } };
|
|
cache[ key ] = _.cloneDeep( cacheEntry );
|
|
if ( head ) {
|
|
cache[""].tips[ key ] = head;
|
|
}
|
|
return cache;
|
|
}
|
|
|
|
function testTask( test, task, args, success, failure ) {
|
|
exec("grunt " + task + " " + (args || []).join(" "), {}, function( err, stdout ) {
|
|
console.log( ("\n\nOUTPUT:")["bold"] +
|
|
( "\n" + stdout ).replace( /\n/g, "\n " ) );
|
|
|
|
// No error; send output to success callback
|
|
if ( !err ) {
|
|
success( stdout );
|
|
|
|
// Expected error; send output to failure callback
|
|
} else if ( failure ) {
|
|
failure( stdout );
|
|
|
|
// Unexpected error
|
|
} else {
|
|
test.ok( false, "Error: " + err );
|
|
test.done();
|
|
}
|
|
});
|
|
}
|
|
|
|
function testCompare( test, beforeCache, args, standardTests, success ) {
|
|
if ( beforeCache == null ) {
|
|
if ( fs.existsSync( sizecache ) ) {
|
|
fs.unlinkSync( sizecache );
|
|
}
|
|
} else {
|
|
grunt.file.write( sizecache, JSON.stringify( beforeCache ) );
|
|
}
|
|
|
|
testTask( test, [ "compare_size" ].concat( args || [] ).join(":"), [], function( result ) {
|
|
var expected = {},
|
|
lines = grunt.log.uncolor( result ).split("\n").map(function( line ) { return line.trim(); }),
|
|
details = {
|
|
headers: lines.filter(function( line ) {
|
|
return (/ Sizes| Compared/).test( line );
|
|
}),
|
|
saves: lines.filter(function( line ) {
|
|
return (/^Saved as: /).test( line );
|
|
}),
|
|
deltas: {}
|
|
},
|
|
cache = grunt.file.readJSON( sizecache );
|
|
|
|
// Store the array of deltas output per file per label for easy comparison
|
|
details.headers.forEach(function( header ) {
|
|
var parts,
|
|
i = lines.indexOf( header ) + 1;
|
|
details.deltas[ header ] = {};
|
|
for ( ; (parts = rfileLine.exec( lines[ i ] )); i++ ) {
|
|
details.deltas[ header ][ parts[ 2 ] ] = parts[ 1 ].match( /\S+/g );
|
|
}
|
|
});
|
|
|
|
// Conditional sanity checks for cache/output consistency
|
|
if ( standardTests ) {
|
|
// Promote beforeCache to labeled (0.3) format
|
|
if ( beforeCache && !beforeCache[""] ) {
|
|
beforeCache = { "": undefined, " last run": beforeCache };
|
|
}
|
|
|
|
// Check command-line output
|
|
test.ok( (/ Sizes$/).test( details.headers[ 0 ] ), "Raw sizes first" );
|
|
Object.keys( beforeCache || {} ).forEach(function( label ) {
|
|
var testLabel = label.replace( /^ /, "" ) || "raw",
|
|
rlabel = label ? new RegExp( " Compared to " + testLabel + "( .*)?" ) : / Sizes/,
|
|
index = indexOf( lines, rlabel ),
|
|
outputCompressors = [""].concat(
|
|
( lines[ index ] || "" ).replace( rlabel, "" ).replace( /raw/, "" ).match( /\S+/g )
|
|
),
|
|
detail = {
|
|
lines: lines.slice( index + 1, index + 1 + files.length ),
|
|
files: [],
|
|
values: {}
|
|
},
|
|
expectedValues = {};
|
|
|
|
// Get files and values from the comparison lines
|
|
detail.lines.forEach(function( line ) {
|
|
var match = rfileLine.exec( line ) || [],
|
|
sizes = ( match[ 1 ] || "" ).match( /\S+/g ) || [],
|
|
file = match[ 2 ],
|
|
values = detail.values[ file ] = {};
|
|
|
|
detail.files.push( file );
|
|
outputCompressors.forEach(function( label, i ) {
|
|
values[ label ] = sizes[ i ];
|
|
});
|
|
});
|
|
|
|
|
|
test.ok( index >= 0, testLabel );
|
|
test.deepEqual( detail.files, files, testLabel + ": all files output" );
|
|
test.ok( !lines[ index + 1 + files.length ], testLabel + ": no unexpected files output" );
|
|
|
|
// Check raw sizes
|
|
if ( !label ) {
|
|
test.deepEqual( detail.values, cacheEntry, testLabel + ": all sizes match cache" );
|
|
|
|
// Check size comparisons
|
|
} else {
|
|
files.forEach(function( file ) {
|
|
var sizeBefore = ( beforeCache[ label ] || {} )[ file ],
|
|
expected = {};
|
|
|
|
// 0.4 format
|
|
if ( typeof sizeBefore === "object" ) {
|
|
Object.keys( sizeBefore ).forEach(function( compressor ) {
|
|
expected[ compressor ] = formatDelta( cacheEntry[ file ][ compressor ] -
|
|
sizeBefore[ compressor ] );
|
|
});
|
|
|
|
// Pre-0.4 format
|
|
} else {
|
|
expected = { "": formatDelta( cacheEntry[ file ][""] - sizeBefore ) };
|
|
outputCompressors.forEach(function( compressor ) {
|
|
expected[ compressor ] = formatDelta( cacheEntry[ file ][ compressor ] -
|
|
( beforeCache[ label ] || {} )[ file + "." + compressor ] );
|
|
});
|
|
}
|
|
|
|
test.deepEqual( detail.values[ file ], expected, testLabel + ": all deltas match cache for " + file );
|
|
});
|
|
}
|
|
});
|
|
|
|
// Check expected deltas
|
|
if ( typeof standardTests === "object" ) {
|
|
test.equal( details.headers.length, Object.keys( standardTests ).length + 1, "Header count" );
|
|
Object.keys( standardTests ).forEach(function( label, i ) {
|
|
var headerIndex = i + 1,
|
|
tip = beforeCache[""].tips[ label ],
|
|
re = " Compared to " + label.replace( /^\s/, "" ) + ( tip ? " @ " + tip : "" ) + "$";
|
|
test.ok( (new RegExp( re )).test( details.headers[ headerIndex ] ),
|
|
"Correct sequence: " + label );
|
|
test.deepEqual( details.deltas[ details.headers[ headerIndex ] ], standardTests[ label ],
|
|
"Deltas correct: " + label );
|
|
});
|
|
}
|
|
|
|
// Check cache contents
|
|
test.equal( typeof cache, "object", "Size cache exists" );
|
|
test.equal( typeof cache[""], "object", "Size cache has metadata" );
|
|
test.equal( cache[""].version, 0.4, "Size cache is correctly versioned" );
|
|
test.equal( typeof cache[""].tips, "object", "Size cache identifies branch tips" );
|
|
test.deepEqual( cache[" last run"], cacheEntry, "Size cache includes 'last' data" );
|
|
}
|
|
|
|
// Test-specific assertions
|
|
success( lines, cache, details );
|
|
});
|
|
}
|
|
|
|
module.exports["compare_size"] = {
|
|
"setup": function( test ) {
|
|
// Store about-to-be-overwritten data
|
|
[ sizecache, harness ].forEach(function( old ) {
|
|
overwritten[ old ] = fs.existsSync( old ) ? grunt.file.read( old ) : undefined;
|
|
});
|
|
|
|
// Get file sizes for later comparison
|
|
files.forEach(function( file, i ) {
|
|
var contents = fs.existsSync( file ) ? grunt.file.read( file ) : "",
|
|
compressed = contents ? gzip.zip( contents, {} ) : "";
|
|
cacheEntry[ file ] = { "": contents.length, "gz": compressed.length };
|
|
cacheEntry_0_3[ file ] = contents.length;
|
|
if ( i + 1 === files.length ) {
|
|
cacheEntry_0_3[ file + ".gz" ] = compressed.length;
|
|
}
|
|
});
|
|
|
|
test.done();
|
|
},
|
|
|
|
"off-tip/working-changes, old-format cache": function( test ) {
|
|
var expectedDeltas = { " last run": {} },
|
|
harnesses = [
|
|
// Off-tip
|
|
"function( done ) { done('branch not found'); };",
|
|
// Working-changes
|
|
"function( done ) { done( null, { branch: 'wip', head: 'deadbeef', changed: true }); };"
|
|
];
|
|
|
|
files.forEach(function( file, index ) {
|
|
expectedDeltas[" last run"][ file ] = compressors.map(function( compressor ) {
|
|
// Pre-0.4 caches only stored compressed data for the last file in the list
|
|
return !compressor || index + 1 === files.length ?
|
|
"=" :
|
|
"?";
|
|
});
|
|
});
|
|
|
|
next();
|
|
|
|
function next() {
|
|
if ( harnesses.length ) {
|
|
configureHarness( harnesses.shift() );
|
|
testCompare( test, cacheEntry_0_3, [], false, check );
|
|
} else {
|
|
test.done();
|
|
}
|
|
}
|
|
|
|
function check( lines, cache, detail ) {
|
|
// Output tests
|
|
test.equal( detail.headers.length, 2, "Header count" );
|
|
test.ok( (/ Sizes$/).test( detail.headers[ 0 ] ), "Correct placement: Sizes" );
|
|
test.ok( (/ Compared to last run$/).test( detail.headers[ 1 ] ), "Cache interpreted as last run" );
|
|
test.deepEqual( detail.deltas[ detail.headers[ 1 ] ], expectedDeltas[" last run"], "Deltas correct: last run" );
|
|
test.deepEqual( detail.saves, [], "Only saved to last run" );
|
|
|
|
// Cache tests
|
|
test.deepEqual( cache[""].tips, {}, "No recorded branch tips" );
|
|
test.deepEqual( cache, augmentCache(" last run"), "No unexpected data" );
|
|
|
|
next();
|
|
}
|
|
},
|
|
|
|
"off-tip/working-changes, no cache": function( test ) {
|
|
var harnesses = [
|
|
// Off-tip
|
|
"function( done ) { done('branch not found'); };",
|
|
// Working-changes
|
|
"function( done ) { done( null, { branch: 'wip', head: 'deadbeef', changed: true }); };"
|
|
];
|
|
|
|
next();
|
|
|
|
function next() {
|
|
if ( harnesses.length ) {
|
|
configureHarness( harnesses.shift() );
|
|
testCompare( test, undefined, [], true, check );
|
|
} else {
|
|
test.done();
|
|
}
|
|
}
|
|
|
|
function check( lines, cache, detail ) {
|
|
// Output tests
|
|
test.equal( detail.headers.length, 1, "Header count" );
|
|
test.ok( (/ Sizes$/).test( detail.headers[ 0 ] ), "Correct placement: Sizes" );
|
|
test.deepEqual( detail.saves, [], "Only saved to last run" );
|
|
|
|
// Cache tests
|
|
test.deepEqual( cache[""].tips, {}, "No recorded branch tips" );
|
|
test.deepEqual( cache, augmentCache(" last run"), "No unexpected data" );
|
|
|
|
next();
|
|
}
|
|
},
|
|
|
|
"off-tip/working-changes, zero cache": function( test ) {
|
|
var labels = ["zeroes"],
|
|
expectedDeltas = _.zipObject( labels, labels.map(function() { return {}; }) ),
|
|
base = augmentCache("zeroes"),
|
|
expected = augmentCache( " last run", false, augmentCache("zeroes") ),
|
|
harnesses = [
|
|
// Off-tip
|
|
"function( done ) { done('branch not found'); };",
|
|
// Working-changes
|
|
"function( done ) { done( null, { branch: 'wip', head: 'deadbeef', changed: true }); };"
|
|
];
|
|
|
|
files.forEach(function( file ) {
|
|
_.values( expectedDeltas ).forEach(function( obj ) {
|
|
obj[ file ] = [];
|
|
});
|
|
compressors.forEach(function( compressor ) {
|
|
base["zeroes"][ file ][ compressor ] = expected["zeroes"][ file ][ compressor ] = 0;
|
|
expectedDeltas["zeroes"][ file ].push( "+" + cacheEntry[ file ][ compressor ] );
|
|
});
|
|
});
|
|
|
|
next();
|
|
|
|
function next() {
|
|
if ( harnesses.length ) {
|
|
configureHarness( harnesses.shift() );
|
|
testCompare( test, base, [], expectedDeltas, check );
|
|
} else {
|
|
test.done();
|
|
}
|
|
}
|
|
|
|
function check( lines, cache, detail ) {
|
|
// Branch logging
|
|
test.deepEqual( detail.saves, [], "Only saved to last run" );
|
|
|
|
// New cache contents
|
|
test.deepEqual( cache[""].tips, {}, "No recorded branch tips" );
|
|
test.deepEqual( cache, expected, "No unexpected data" );
|
|
|
|
next();
|
|
}
|
|
},
|
|
|
|
"off-tip/working-changes, hash cache": function( test ) {
|
|
var labels = [ "branch", "zeroes", "ones", " last run" ],
|
|
expectedDeltas = _.zipObject( labels, labels.map(function() { return {}; }) ),
|
|
base = augmentCache( "branch", "tip",
|
|
augmentCache(" last run", false,
|
|
augmentCache( "ones", false, augmentCache("zeroes") )
|
|
)
|
|
),
|
|
expected = augmentCache( "branch", "tip",
|
|
augmentCache(" last run", false,
|
|
augmentCache( "ones", false, augmentCache("zeroes") )
|
|
)
|
|
),
|
|
harnesses = [
|
|
// Off-tip
|
|
"function( done ) { done('branch not found'); };",
|
|
// Working-changes
|
|
"function( done ) { done( null, { branch: 'wip', head: 'deadbeef', changed: true }); };"
|
|
];
|
|
|
|
files.forEach(function( file, index ) {
|
|
_.values( expectedDeltas ).forEach(function( obj ) {
|
|
obj[ file ] = [];
|
|
});
|
|
compressors.forEach(function( compressor ) {
|
|
expectedDeltas["branch"][ file ].push("=");
|
|
|
|
base["zeroes"][ file ][ compressor ] = expected["zeroes"][ file ][ compressor ] = 0;
|
|
expectedDeltas["zeroes"][ file ].push( "+" + cacheEntry[ file ][ compressor ] );
|
|
|
|
base["ones"][ file ][ compressor ] = expected["ones"][ file ][ compressor ] = cacheEntry[ file ][ compressor ] + 1;
|
|
expectedDeltas["ones"][ file ].push("-1");
|
|
|
|
base[" last run"][ file ][ compressor ] = cacheEntry[ file ][ compressor ] - index;
|
|
expectedDeltas[" last run"][ file ].push( index ? "+" + index : "=" );
|
|
});
|
|
});
|
|
|
|
next();
|
|
|
|
function next() {
|
|
if ( harnesses.length ) {
|
|
configureHarness( harnesses.shift() );
|
|
testCompare( test, base, [], expectedDeltas, check );
|
|
} else {
|
|
test.done();
|
|
}
|
|
}
|
|
|
|
function check( lines, cache, detail ) {
|
|
// Branch logging
|
|
test.deepEqual( detail.saves, [], "Only saved to last run" );
|
|
|
|
// New cache contents
|
|
test.deepEqual( cache[""].tips, { branch: "tip" }, "Branch tips unchanged" );
|
|
test.deepEqual( cache, expected, "No unexpected data" );
|
|
|
|
next();
|
|
}
|
|
},
|
|
|
|
"at-tip, old-format cache": function( test ) {
|
|
var expectedDeltas = { " last run": {} };
|
|
|
|
files.forEach(function( file, index ) {
|
|
expectedDeltas[" last run"][ file ] = compressors.map(function( compressor ) {
|
|
// Pre-0.4 caches only stored compressed data for the last file in the list
|
|
return !compressor || index + 1 === files.length ?
|
|
"=" :
|
|
"?";
|
|
});
|
|
});
|
|
|
|
configureHarness('function( done ) { done( null, { branch: "branch", head: "tip", changed: false }); };');
|
|
testCompare( test, cacheEntry_0_3, [], false, function( lines, cache, detail ) {
|
|
// Output tests
|
|
test.equal( detail.headers.length, 2, "Header count" );
|
|
test.ok( (/ Sizes$/).test( detail.headers[ 0 ] ), "Correct placement: Sizes" );
|
|
test.ok( (/ Compared to last run$/).test( detail.headers[ 1 ] ), "Cache interpreted as last run" );
|
|
test.deepEqual( detail.deltas[ detail.headers[ 1 ] ], expectedDeltas[" last run"], "Deltas correct: last run" );
|
|
test.deepEqual( detail.saves, ["Saved as: branch"], "Saved to branch label" );
|
|
|
|
// Cache tests
|
|
test.deepEqual( cache[""].tips, { branch: "tip" }, "New tip saved" );
|
|
test.deepEqual( cache.branch, cacheEntry, "Sizes updated for active branch" );
|
|
test.deepEqual( cache, augmentCache( "branch", "tip", augmentCache(" last run") ), "No unexpected data" );
|
|
|
|
test.done();
|
|
});
|
|
},
|
|
|
|
"at-tip, no cache": function( test ) {
|
|
var expected = augmentCache( " last run", false, augmentCache( "branch", "tip" ) );
|
|
|
|
configureHarness('function( done ) { done( null, { branch: "branch", head: "tip", changed: false }); };');
|
|
testCompare( test, undefined, [], true, function( lines, cache, detail ) {
|
|
// Output tests
|
|
test.equal( detail.headers.length, 1, "Header count" );
|
|
test.ok( (/ Sizes$/).test( detail.headers[ 0 ] ), "Correct placement: Sizes" );
|
|
test.deepEqual( detail.saves, ["Saved as: branch"], "Saved to branch label" );
|
|
|
|
// Cache tests
|
|
test.deepEqual( cache[""].tips, { branch: "tip" }, "New tip saved" );
|
|
test.deepEqual( cache.branch, cacheEntry, "Sizes updated for active branch" );
|
|
test.deepEqual( cache, expected, "No unexpected data" );
|
|
|
|
test.done();
|
|
});
|
|
},
|
|
|
|
"at-tip, zero cache": function( test ) {
|
|
var labels = ["zeroes"],
|
|
expectedDeltas = _.zipObject( labels, labels.map(function() { return {}; }) ),
|
|
base = augmentCache( "zeroes", "old-tip" ),
|
|
expected = augmentCache( " last run", false, augmentCache( "zeroes", "new-tip" ) );
|
|
|
|
files.forEach(function( file ) {
|
|
_.values( expectedDeltas ).forEach(function( obj ) {
|
|
obj[ file ] = [];
|
|
});
|
|
compressors.forEach(function( compressor ) {
|
|
base["zeroes"][ file ][ compressor ] = 0;
|
|
expectedDeltas["zeroes"][ file ].push( "+" + cacheEntry[ file ][ compressor ] );
|
|
});
|
|
});
|
|
|
|
configureHarness('function( done ) { done( null, { branch: "zeroes", head: "new-tip", changed: false }); };');
|
|
testCompare( test, base, [], expectedDeltas, function( lines, cache, detail ) {
|
|
// Branch logging
|
|
test.deepEqual( detail.saves, ["Saved as: zeroes"], "Saved to branch label" );
|
|
|
|
// New cache contents
|
|
test.deepEqual( cache[""].tips, { zeroes: "new-tip" }, "New tip saved" );
|
|
test.deepEqual( cache.zeroes, cacheEntry, "Sizes updated for active branch" );
|
|
test.deepEqual( cache, expected, "No unexpected data" );
|
|
|
|
test.done();
|
|
});
|
|
},
|
|
|
|
"at-tip, hash cache": function( test ) {
|
|
var labels = [ "ones", "stale", "zeroes", " last run" ],
|
|
expectedDeltas = _.zipObject( labels, labels.map(function() { return {}; }) ),
|
|
base = augmentCache( "stale", "tip",
|
|
augmentCache(" last run", false,
|
|
augmentCache( "ones", "old-tip", augmentCache("zeroes") )
|
|
)
|
|
),
|
|
expected = augmentCache( "stale", "tip",
|
|
augmentCache(" last run", false,
|
|
augmentCache( "ones", "new-tip", augmentCache("zeroes") )
|
|
)
|
|
);
|
|
|
|
files.forEach(function( file, index ) {
|
|
_.values( expectedDeltas ).forEach(function( obj ) {
|
|
obj[ file ] = [];
|
|
});
|
|
compressors.forEach(function( compressor ) {
|
|
base["stale"][ file ][ compressor ] = expected["stale"][ file ][ compressor ] = cacheEntry[ file ][ compressor ] + 1;
|
|
expectedDeltas["stale"][ file ].push("-1");
|
|
|
|
base["zeroes"][ file ][ compressor ] = expected["zeroes"][ file ][ compressor ] = 0;
|
|
expectedDeltas["zeroes"][ file ].push( "+" + cacheEntry[ file ][ compressor ] );
|
|
|
|
base["ones"][ file ][ compressor ] = cacheEntry[ file ][ compressor ] + 1;
|
|
expectedDeltas["ones"][ file ].push("-1");
|
|
|
|
base[" last run"][ file ][ compressor ] = cacheEntry[ file ][ compressor ] - index;
|
|
expectedDeltas[" last run"][ file ].push( index ? "+" + index : "=" );
|
|
});
|
|
});
|
|
|
|
configureHarness('function( done ) { done( null, { branch: "ones", head: "new-tip", changed: false }); };');
|
|
testCompare( test, base, [], expectedDeltas, function( lines, cache, detail ) {
|
|
// Branch logging
|
|
test.deepEqual( detail.saves, ["Saved as: ones"], "Saved to branch label" );
|
|
|
|
// New cache contents
|
|
test.deepEqual( cache[""].tips, { stale: "tip", ones: "new-tip" }, "New tip saved" );
|
|
test.deepEqual( cache.ones, cacheEntry, "Sizes updated for active branch" );
|
|
test.deepEqual( cache.stale, expected.stale, "Sizes not updated for inactive branch" );
|
|
test.deepEqual( cache, expected, "No unexpected data" );
|
|
|
|
test.done();
|
|
});
|
|
},
|
|
|
|
"single file": function( test ) {
|
|
var singleFile = files[0],
|
|
labels = [ "branch", "zeroes", "ones", " last run" ],
|
|
expectedDeltas = _.zipObject( labels, labels.map(function() { return {}; }) ),
|
|
base = augmentCache( "branch", "tip",
|
|
augmentCache(" last run", false,
|
|
augmentCache( "ones", false, augmentCache("zeroes") )
|
|
)
|
|
),
|
|
expected = augmentCache( "branch", "tip",
|
|
augmentCache(" last run", false,
|
|
augmentCache( "ones", false, augmentCache("zeroes") )
|
|
)
|
|
);
|
|
|
|
files.forEach(function( file, index ) {
|
|
_.values( expectedDeltas ).forEach(function( obj ) {
|
|
obj[ file ] = [];
|
|
});
|
|
compressors.forEach(function( compressor ) {
|
|
expectedDeltas["branch"][ file ].push("=");
|
|
|
|
base["zeroes"][ file ][ compressor ] = expected["zeroes"][ file ][ compressor ] = 0;
|
|
expectedDeltas["zeroes"][ file ].push( "+" + cacheEntry[ file ][ compressor ] );
|
|
|
|
base["ones"][ file ][ compressor ] = expected["ones"][ file ][ compressor ] = cacheEntry[ file ][ compressor ] + 1;
|
|
expectedDeltas["ones"][ file ].push("-1");
|
|
|
|
base[" last run"][ file ][ compressor ] = cacheEntry[ file ][ compressor ] - index;
|
|
expectedDeltas[" last run"][ file ].push( index ? "+" + index : "=" );
|
|
});
|
|
});
|
|
|
|
// Configure state
|
|
configureHarness("function( done ) { done( null, { branch: 'wip', head: 'deadbeef', changed: true }); };");
|
|
grunt.file.write( sizecache, JSON.stringify( base ) );
|
|
|
|
testCompare( test, base, [ "", singleFile ], false, function( lines, cache, details ) {
|
|
var headerIndex = indexOf( lines, /raw/ ),
|
|
outputCompressors = headerIndex >= 0 ?
|
|
[""].concat( lines[ headerIndex ].replace( "raw", "" ).match( /\S+/g ) ) :
|
|
[];
|
|
|
|
// Check command-line output
|
|
test.ok( !/\d/.test( lines[ headerIndex ] ), "Header row" );
|
|
test.equal( lines[ headerIndex + 1 ].slice( -singleFile.length - 1 ), " " + singleFile,
|
|
"Raw sizes for file" );
|
|
Object.keys( base ).forEach(function( label ) {
|
|
var testLabel = label.replace( /^ /, "" ) || "raw",
|
|
rlabel = new RegExp( " " + ( label ? testLabel : singleFile ) + "( .*)?" ),
|
|
index = indexOf( lines, rlabel ),
|
|
line = lines[ index ] || "",
|
|
lineSizes = line.match( /[-+=0-9]+/g ),
|
|
sizeBefore = base[ label ][ singleFile ];
|
|
|
|
test.ok( index >= 0, testLabel );
|
|
|
|
// Check raw sizes
|
|
if ( !label ) {
|
|
test.deepEqual( _.zipObject( outputCompressors, lineSizes ),
|
|
cacheEntry[ singleFile ], "sizes match cache" );
|
|
|
|
// Check size comparisions
|
|
} else {
|
|
test.deepEqual( lineSizes, Object.keys( cacheEntry[ singleFile ] ).map(function( compressor ) {
|
|
return formatDelta( cacheEntry[ singleFile ][ compressor ] - sizeBefore[ compressor ] );
|
|
}), testLabel + ": deltas match cache" );
|
|
}
|
|
});
|
|
|
|
// Check branch logging
|
|
test.deepEqual( details.saves, [], "Only saved to last run" );
|
|
|
|
// Check cache contents
|
|
test.equal( typeof cache, "object", "Size cache exists" );
|
|
test.equal( typeof cache[""], "object", "Size cache has metadata" );
|
|
test.equal( cache[""].version, 0.4, "Size cache is correctly versioned" );
|
|
test.equal( typeof cache[""].tips, "object", "Size cache identifies branch tips" );
|
|
test.deepEqual( cache[" last run"], cacheEntry, "Size cache includes 'last' data" );
|
|
test.deepEqual( cache[""].tips, { branch: "tip" }, "Branch tips unchanged" );
|
|
test.deepEqual( cache, expected, "No unexpected data" );
|
|
|
|
test.done();
|
|
});
|
|
},
|
|
|
|
"list": function( test ) {
|
|
var cache = augmentCache( "label", false, augmentCache( "branch", "tip", augmentCache(" last run") ) );
|
|
|
|
grunt.file.write( sizecache, JSON.stringify( cache ) );
|
|
testTask( test, "compare_size:list", [], function( result ) {
|
|
var lines = result.toString().split("\n").map(function( line ) { return line.trim(); }),
|
|
index = lines.indexOf("label");
|
|
|
|
// Output tests
|
|
test.ok( (/^branch.*@ tip/).test( lines[ index - 1 ] ), "Found branch with correct tip" );
|
|
test.ok( index >= 0, "Found custom label" );
|
|
test.ok( !lines[ index + 1 ], "Last run not listed" );
|
|
|
|
// Cache tests
|
|
test.deepEqual( JSON.parse( grunt.file.read( sizecache ) ), cache, "Size cache untouched" );
|
|
|
|
test.done();
|
|
});
|
|
},
|
|
|
|
"add, old-format cache": function( test ) {
|
|
grunt.file.write( sizecache, JSON.stringify( cacheEntry_0_3 ) );
|
|
testTask( test, "compare_size:add:custom", [], function( result ) {
|
|
var lines = result.toString().split("\n").map(function( line ) { return line.trim(); }),
|
|
cache = grunt.file.readJSON( sizecache ),
|
|
index = lines.indexOf("Last run saved as: custom");
|
|
|
|
// Output tests
|
|
test.ok( index >= 0, "Added with correct label" );
|
|
test.ok( !(/^Last run saved/).test( lines[ index - 1 ] ), "No antecedent adds" );
|
|
test.ok( !lines[ index + 1 ], "No subsequent adds" );
|
|
|
|
// Cache tests
|
|
backfillCompression( cache, test );
|
|
test.deepEqual( cache[""].tips, {}, "No recorded branch tips" );
|
|
test.deepEqual( cache[" last run"], cacheEntry, "Last run unchanged" );
|
|
test.deepEqual( cache["custom"], cacheEntry, "Custom data stored" );
|
|
test.deepEqual( cache, augmentCache( "custom", false, augmentCache(" last run") ), "No unexpected data" );
|
|
|
|
test.done();
|
|
});
|
|
},
|
|
|
|
"add, no cache": function( test ) {
|
|
fs.unlinkSync( sizecache );
|
|
testTask( test, "compare_size:add:custom", [], function() {
|
|
test.ok( false, "Error expected" );
|
|
}, function( err ) {
|
|
// Output tests
|
|
test.ok( (/No size data found/).test( err ), "Error found" );
|
|
|
|
// Cache tests
|
|
test.ok( !fs.existsSync( sizecache ), "Cache not created" );
|
|
|
|
test.done();
|
|
});
|
|
},
|
|
|
|
"add, hash cache": function( test ) {
|
|
grunt.file.write( sizecache, JSON.stringify(
|
|
augmentCache( "branch", "tip", augmentCache( "replaced", "tip", augmentCache(" last run") ) ) )
|
|
);
|
|
testTask( test, "compare_size:add:custom:replaced", [], function( result ) {
|
|
var lines = result.toString().split("\n").map(function( line ) { return line.trim(); }),
|
|
cache = grunt.file.readJSON( sizecache ),
|
|
index = lines.indexOf("Last run saved as: custom");
|
|
|
|
// Output tests
|
|
test.ok( index >= 0, "First label" );
|
|
test.equal( lines[ index + 1 ], "(removed branch data) Last run saved as: replaced", "Second label" );
|
|
test.ok( !(/^Last run saved/).test( lines[ index - 1 ] ), "No antecedent adds" );
|
|
test.ok( !lines[ index + 2 ], "No subsequent adds" );
|
|
|
|
// Cache tests
|
|
test.deepEqual( cache[""].tips, { branch: "tip" }, "Removed branch data" );
|
|
test.deepEqual( cache[" last run"], cacheEntry, "Last run unchanged" );
|
|
test.deepEqual( cache["custom"], cacheEntry, "Custom data stored" );
|
|
test.deepEqual( cache["replaced"], cacheEntry, "Replaced data stored" );
|
|
test.deepEqual( cache, augmentCache( "custom", false,
|
|
augmentCache( "branch", "tip", augmentCache( "replaced", false, augmentCache(" last run") ) ) ),
|
|
"No unexpected data" );
|
|
|
|
test.done();
|
|
});
|
|
},
|
|
|
|
"remove": function( test ) {
|
|
grunt.file.write( sizecache, JSON.stringify(
|
|
augmentCache( "branch", "tip", augmentCache( "removed", "tip", augmentCache(" last run") ) ) )
|
|
);
|
|
testTask( test, "compare_size:remove:removed", [], function( result ) {
|
|
var lines = result.toString().split("\n").map(function( line ) { return line.trim(); }),
|
|
cache = grunt.file.readJSON( sizecache ),
|
|
index = lines.indexOf("Removed: removed");
|
|
|
|
// Output tests
|
|
test.ok( index >= 0, "Removed label" );
|
|
test.ok( !(/^Last run saved/).test( lines[ index - 1 ] ), "No antecedent removes" );
|
|
test.ok( !lines[ index + 1 ], "No subsequent removes" );
|
|
|
|
// Cache tests
|
|
test.deepEqual( cache[""].tips, { branch: "tip" }, "No recorded branch tips" );
|
|
test.deepEqual( cache[" last run"], cacheEntry, "Last run unchanged" );
|
|
test.deepEqual( cache["branch"], cacheEntry, "Branch data retained" );
|
|
test.ok( !( "removed" in cache ), "Data removed" );
|
|
test.deepEqual( cache, augmentCache( "branch", "tip", augmentCache(" last run") ),
|
|
"No unexpected data" );
|
|
|
|
test.done();
|
|
});
|
|
},
|
|
|
|
"empty": function( test ) {
|
|
grunt.file.write( sizecache, JSON.stringify(
|
|
augmentCache( "branch", "tip", augmentCache( "removed", "tip", augmentCache(" last run") ) ) )
|
|
);
|
|
testTask( test, "compare_size:empty", [], function() {
|
|
// Cache tests
|
|
test.ok( !fs.existsSync( sizecache ), "Size cache removed" );
|
|
|
|
test.done();
|
|
});
|
|
},
|
|
|
|
"indiscriminate prune": function( test ) {
|
|
grunt.file.write( sizecache, JSON.stringify(
|
|
augmentCache( "branch", "tip", augmentCache( "removed", "tip", augmentCache(" last run") ) ) )
|
|
);
|
|
testTask( test, "compare_size:prune", [], function( result ) {
|
|
var lines = result.toString().split("\n").map(function( line ) { return line.trim(); }),
|
|
removes = lines.filter(function( line ) { return (/^Removed:/).test( line ); });
|
|
|
|
// output tests
|
|
test.deepEqual( removes, [], "No per-label output" );
|
|
|
|
// cache tests
|
|
test.ok( !fs.existsSync( sizecache ), "Size cache removed" );
|
|
|
|
test.done();
|
|
});
|
|
},
|
|
|
|
"selective prune": function( test ) {
|
|
grunt.file.write( sizecache, JSON.stringify(
|
|
augmentCache( "foo", false, augmentCache( "branch", "tip", augmentCache( "removed", "tip", augmentCache(" last run") ) ) ) )
|
|
);
|
|
testTask( test, "compare_size:prune:bar:branch", [], function( result ) {
|
|
var lines = result.toString().split("\n").map(function( line ) { return line.trim(); }),
|
|
removes = lines.filter(function( line ) { return (/^Removed:/).test( line ); }),
|
|
cache = grunt.file.readJSON( sizecache );
|
|
|
|
// output tests
|
|
test.deepEqual( removes.sort(), [ "Removed: foo", "Removed: removed" ], "Explicit per-label output" );
|
|
|
|
// cache tests
|
|
test.deepEqual( cache[""].tips, { branch: "tip" }, "Specified branches preserved" );
|
|
test.deepEqual( cache[" last run"], cacheEntry, "Last run unchanged" );
|
|
test.deepEqual( cache["branch"], cacheEntry, "Branch data retained" );
|
|
test.ok( !( "removed" in cache ) && !( "foo" in cache ), "Data removed" );
|
|
test.deepEqual( cache, augmentCache( "branch", "tip", augmentCache(" last run") ),
|
|
"No unexpected data" );
|
|
|
|
test.done();
|
|
});
|
|
},
|
|
|
|
"teardown": function( test ) {
|
|
// Restore overwritten data
|
|
Object.keys( overwritten ).forEach(function( old ) {
|
|
if ( overwritten[ old ] == null ) {
|
|
if ( fs.existsSync( old ) ) {
|
|
fs.unlinkSync( old );
|
|
}
|
|
} else {
|
|
grunt.file.write( old, overwritten[ old ] );
|
|
}
|
|
});
|
|
|
|
test.done();
|
|
}
|
|
};
|