Created
July 25, 2014 18:07
-
-
Save graue/6ed6230a616bd920a674 to your computer and use it in GitHub Desktop.
Gentest bundle for browsers
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ | |
window.gentest = require('./index'); | |
},{"./index":2}],2:[function(require,module,exports){ | |
exports.run = require('./lib/run'); | |
exports.sample = require('./lib/sample'); | |
exports.types = require('./lib/types'); | |
var errors = require('./lib/errors'); | |
exports.FailureError = errors.FailureError; | |
exports.GentestError = errors.GentestError; | |
},{"./lib/errors":3,"./lib/run":4,"./lib/sample":5,"./lib/types":6}],3:[function(require,module,exports){ | |
// Remove library code from the provided stack trace. | |
// This is a bit voodoo since the precise contents of the stack trace | |
// string vary by browser vendor. | |
// | |
// Example: We want to keep the first line and every line starting from | |
// "at Context.<anonymous>" (note that it's in a different project), | |
// but elide lines 2-6 in between. | |
// | |
// Error: property (anonymous function) failed to hold | |
// at FailureError.Error (<anonymous>) | |
// at FailureError.GentestError (/home/sf/code/immutable/node_modules/gentest/lib/errors.js:22:41) | |
// at new FailureError (/home/sf/code/immutable/node_modules/gentest/lib/errors.js:32:38) | |
// at _run (/home/sf/code/immutable/node_modules/gentest/lib/run.js:59:15) | |
// at Object.run (/home/sf/code/immutable/node_modules/gentest/lib/run.js:37:10) | |
// at Context.<anonymous> (/home/sf/code/immutable/test/index.js:44:20) | |
// [... more lines not shown ...] | |
// | |
// TODO: Test to make sure this does reasonable things in browsers | |
// as well as Node. | |
// | |
function cleanupStack(str, errorName) { | |
if (typeof str !== 'string') return str; | |
var isLibraryCode = function(line) { | |
return line.match(/\/gentest\//) || | |
line.match(/at( new)? (\w+)Error/); | |
}; | |
var lines = str.split(/\n/); | |
var i = 1; | |
while (i < lines.length && isLibraryCode(lines[i])) { | |
i++; | |
} | |
return [lines[0]].concat(lines.slice(i)).join('\n'); | |
} | |
var ErrorSubclass = function ErrorSubclass() {}; | |
ErrorSubclass.prototype = Error.prototype; | |
var GentestError = function GentestError() { | |
if (!this instanceof GentestError) { | |
throw new TypeError('GentestError must be called via new'); | |
} | |
var tmp = Error.prototype.constructor.apply(this, arguments); | |
if (tmp.stack) { | |
this.stack = cleanupStack(tmp.stack).replace(/^Error/, 'GentestError'); | |
} | |
if (tmp.message) { | |
this.message = tmp.message; | |
} | |
this.name = 'GentestError'; | |
return this; | |
}; | |
GentestError.prototype = new ErrorSubclass(); | |
GentestError.prototype.constructor = GentestError; | |
var FailureError = function FailureError() { | |
GentestError.prototype.constructor.apply(this, arguments); | |
if (this.stack) { | |
this.stack = this.stack.replace(/^GentestError/, 'FailureError'); | |
} | |
this.name = 'FailureError'; | |
}; | |
FailureError.prototype = new GentestError(); | |
FailureError.prototype.constructor = FailureError; | |
exports.GentestError = GentestError; | |
exports.FailureError = FailureError; | |
},{}],4:[function(require,module,exports){ | |
var PRNG = require('burtleprng'); | |
var errors = require('./errors'); | |
// TODO: add a maxSize parameter somehow. | |
// Returns true if all tests passed. | |
function run(func, numTests, seed) { | |
// Mess with arguments. Varargs are generators, | |
// and numTests and seed are optional so may also be | |
// generators. | |
// (However, numTests must be provided if seed is.) | |
var generators = [].slice.call(arguments, 3); | |
var defaultSeed = Date.now(); | |
if (typeof seed === 'function') { | |
generators.unshift(seed); | |
seed = defaultSeed; | |
} else if (typeof seed === 'undefined') { | |
seed = defaultSeed; | |
} else if (typeof seed !== 'number') { | |
throw new TypeError('seed must be a number'); | |
} | |
seed &= 0xffffffff; | |
var DEFAULT_NUM_TESTS = 100; | |
if (typeof numTests === 'function') { | |
generators.unshift(numTests); | |
numTests = DEFAULT_NUM_TESTS; | |
} else if (typeof numTests === 'undefined') { | |
// This suggests your tests use no generators at all, | |
// which seems an unlikely case, but whatever. | |
numTests = DEFAULT_NUM_TESTS; | |
} else if (typeof numTests !== 'number' || numTests < 1) { | |
throw new TypeError('numTests must be a positive number'); | |
} | |
numTests >>>= 0; | |
return _run(func, numTests, seed, generators); | |
} | |
function _run(func, numTests, seed, gens) { | |
var prng = new PRNG(seed); | |
for (var x = 0; x < numTests; x++) { | |
var size = Math.floor(x/2) + 1; | |
var values = gens.map(function(gen) { | |
return gen(prng, size); | |
}); | |
if (!func.apply(null, values)) { | |
var msg = 'property ' + (func.name ? func.name + ' ' : '') + | |
'violated'; | |
var e = new errors.FailureError(msg); | |
e.testCase = values; | |
e.property = func.name; | |
throw e; | |
} | |
} | |
return true; | |
} | |
module.exports = run; | |
},{"./errors":3,"burtleprng":7}],5:[function(require,module,exports){ | |
var PRNG = require('burtleprng'); | |
var DEFAULT_COUNT = 10; | |
// TODO: should this have a size parameter? Should gentest.run be modified | |
// to use this routine instead of doing its own sampling? | |
function sample(gen, count) { | |
if (arguments.length < 2) { | |
count = DEFAULT_COUNT; | |
} | |
var rng = new PRNG(Date.now() & 0xffffffff); | |
var results = new Array(count); | |
for (var i = 0; i < count; i++) { | |
results[i] = gen(rng, Math.floor(i/2) + 1); | |
} | |
return results; | |
} | |
module.exports = sample; | |
},{"burtleprng":7}],6:[function(require,module,exports){ | |
var errors = require('./errors'); | |
// Using the given PRNG, picks an int from low to high, inclusive. | |
function choose(prng, low, high) { | |
return Math.floor(prng.float() * (high - low + 1) + low); | |
} | |
var t = {}; | |
t.number = function(rng, size) { | |
return rng.float() * size*2 - size; | |
}; | |
t.number.nonNegative = function(rng, size) { | |
return rng.float() * size; | |
}; | |
t.suchThat = function(pred, gen, maxTries) { | |
if (arguments.length < 3) maxTries = 10; | |
return function(rng, size) { | |
var triesLeft = maxTries; | |
var val; | |
do { | |
val = gen(rng, size); | |
if (pred(val)) { | |
return val; | |
} | |
} while(--triesLeft > 0); | |
throw new errors.GentestError('suchThat: could not find a suitable value'); | |
}; | |
}; | |
function isNonzero(x) { | |
return x !== 0; | |
} | |
t.number.nonZero = t.suchThat(isNonzero, t.number); | |
t.number.positive = t.suchThat(isNonzero, t.number.nonNegative); | |
t.int = function(rng, size) { | |
return choose(rng, -size, size); | |
}; | |
t.int.nonNegative = function(rng, size) { | |
return choose(rng, 0, size); | |
}; | |
t.int.nonZero = t.suchThat(isNonzero, t.int); | |
t.int.positive = function(rng, size) { | |
return choose(rng, 1, size + 1); | |
}; | |
// FIXME: This should eventually generate non-ASCII characters, I guess. | |
t.char = function(rng, _) { | |
return String.fromCharCode(choose(rng, 32, 126)); | |
}; | |
t.arrayOf = function(elemGen) { | |
return function(rng, size) { | |
var len = t.int.nonNegative(rng, size); | |
var array = new Array(len); | |
for (var i = 0; i < len; i++) { | |
array[i] = elemGen(rng, size); | |
} | |
return array; | |
}; | |
}; | |
t.fmap = function(fun, gen) { | |
return function(rng, size) { | |
return fun(gen(rng, size)); | |
}; | |
}; | |
t.string = t.fmap(function(chars) { | |
return chars.join(''); | |
}, t.arrayOf(t.char)); | |
function constantly(x) { | |
return function(_, _) { | |
return x; | |
}; | |
} | |
t.oneOf = function(gens) { | |
return function(rng, size) { | |
var which = choose(rng, 0, gens.length-1); | |
return gens[which](rng, size); | |
}; | |
}; | |
t.elements = function(elems) { | |
return t.oneOf(elems.map(constantly)); | |
}; | |
t.bool = t.elements([false, true]); | |
t.shape = function(obj) { | |
return function(rng, size) { | |
var out = {}; | |
Object.keys(obj).forEach(function(key) { | |
out[key] = obj[key](rng, size); | |
}); | |
return out; | |
}; | |
}; | |
module.exports = t; | |
},{"./errors":3}],7:[function(require,module,exports){ | |
function BurtlePRNG(seed) { | |
seed >>>= 0; | |
var ctx = this.ctx = new Array(4); | |
ctx[0] = 0xf1ea5eed; | |
ctx[1] = ctx[2] = ctx[3] = seed; | |
for (var i = 0; i < 20; i++) { | |
this.next(); | |
} | |
return this; | |
} | |
function rot(x, k) { | |
return (x << k) | (x >> (32-k)); | |
} | |
BurtlePRNG.prototype.next = function() { | |
var ctx = this.ctx; | |
var e = (ctx[0] - rot(ctx[1], 27))>>>0; | |
ctx[0] = (ctx[1] ^ rot(ctx[2], 17))>>>0; | |
ctx[1] = (ctx[2] + ctx[3])>>>0; | |
ctx[2] = (ctx[3] + e)>>>0; | |
ctx[3] = (e + ctx[0])>>>0; | |
return ctx[3]; | |
}; | |
BurtlePRNG.prototype['float'] = function() { | |
return this.next() / 4294967296.0; | |
}; | |
if (typeof module === 'object') { | |
module.exports = BurtlePRNG; | |
} | |
},{}]},{},[1]) | |
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3NmLy5udm0vdjAuMTAuMjgvbGliL25vZGVfbW9kdWxlcy9icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCIvaG9tZS9zZi9jb2RlL2dlbnRlc3QvYnJvd3Nlci5qcyIsIi9ob21lL3NmL2NvZGUvZ2VudGVzdC9pbmRleC5qcyIsIi9ob21lL3NmL2NvZGUvZ2VudGVzdC9saWIvZXJyb3JzLmpzIiwiL2hvbWUvc2YvY29kZS9nZW50ZXN0L2xpYi9ydW4uanMiLCIvaG9tZS9zZi9jb2RlL2dlbnRlc3QvbGliL3NhbXBsZS5qcyIsIi9ob21lL3NmL2NvZGUvZ2VudGVzdC9saWIvdHlwZXMuanMiLCIvaG9tZS9zZi9jb2RlL2dlbnRlc3Qvbm9kZV9tb2R1bGVzL2J1cnRsZXBybmcvQnVydGxlUFJORy5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtBQ0FBO0FBQ0E7O0FDREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNQQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcEVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzlHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJmaWxlIjoiZ2VuZXJhdGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXNDb250ZW50IjpbIihmdW5jdGlvbiBlKHQsbixyKXtmdW5jdGlvbiBzKG8sdSl7aWYoIW5bb10pe2lmKCF0W29dKXt2YXIgYT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2lmKCF1JiZhKXJldHVybiBhKG8sITApO2lmKGkpcmV0dXJuIGkobywhMCk7dmFyIGY9bmV3IEVycm9yKFwiQ2Fubm90IGZpbmQgbW9kdWxlICdcIitvK1wiJ1wiKTt0aHJvdyBmLmNvZGU9XCJNT0RVTEVfTk9UX0ZPVU5EXCIsZn12YXIgbD1uW29dPXtleHBvcnRzOnt9fTt0W29dWzBdLmNhbGwobC5leHBvcnRzLGZ1bmN0aW9uKGUpe3ZhciBuPXRbb11bMV1bZV07cmV0dXJuIHMobj9uOmUpfSxsLGwuZXhwb3J0cyxlLHQsbixyKX1yZXR1cm4gbltvXS5leHBvcnRzfXZhciBpPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7Zm9yKHZhciBvPTA7bzxyLmxlbmd0aDtvKyspcyhyW29dKTtyZXR1cm4gc30pIiwid2luZG93LmdlbnRlc3QgPSByZXF1aXJlKCcuL2luZGV4Jyk7XG4iLCJleHBvcnRzLnJ1biA9IHJlcXVpcmUoJy4vbGliL3J1bicpO1xuZXhwb3J0cy5zYW1wbGUgPSByZXF1aXJlKCcuL2xpYi9zYW1wbGUnKTtcbmV4cG9ydHMudHlwZXMgPSByZXF1aXJlKCcuL2xpYi90eXBlcycpO1xuXG52YXIgZXJyb3JzID0gcmVxdWlyZSgnLi9saWIvZXJyb3JzJyk7XG5leHBvcnRzLkZhaWx1cmVFcnJvciA9IGVycm9ycy5GYWlsdXJlRXJyb3I7XG5leHBvcnRzLkdlbnRlc3RFcnJvciA9IGVycm9ycy5HZW50ZXN0RXJyb3I7XG4iLCIvLyBSZW1vdmUgbGlicmFyeSBjb2RlIGZyb20gdGhlIHByb3ZpZGVkIHN0YWNrIHRyYWNlLlxuLy8gVGhpcyBpcyBhIGJpdCB2b29kb28gc2luY2UgdGhlIHByZWNpc2UgY29udGVudHMgb2YgdGhlIHN0YWNrIHRyYWNlXG4vLyBzdHJpbmcgdmFyeSBieSBicm93c2VyIHZlbmRvci5cbi8vXG4vLyBFeGFtcGxlOiBXZSB3YW50IHRvIGtlZXAgdGhlIGZpcnN0IGxpbmUgYW5kIGV2ZXJ5IGxpbmUgc3RhcnRpbmcgZnJvbVxuLy8gXCJhdCBDb250ZXh0Ljxhbm9ueW1vdXM+XCIgKG5vdGUgdGhhdCBpdCdzIGluIGEgZGlmZmVyZW50IHByb2plY3QpLFxuLy8gYnV0IGVsaWRlIGxpbmVzIDItNiBpbiBiZXR3ZWVuLlxuLy9cbi8vIEVycm9yOiBwcm9wZXJ0eSAoYW5vbnltb3VzIGZ1bmN0aW9uKSBmYWlsZWQgdG8gaG9sZFxuLy8gICAgIGF0IEZhaWx1cmVFcnJvci5FcnJvciAoPGFub255bW91cz4pXG4vLyAgICAgYXQgRmFpbHVyZUVycm9yLkdlbnRlc3RFcnJvciAoL2hvbWUvc2YvY29kZS9pbW11dGFibGUvbm9kZV9tb2R1bGVzL2dlbnRlc3QvbGliL2Vycm9ycy5qczoyMjo0MSlcbi8vICAgICBhdCBuZXcgRmFpbHVyZUVycm9yICgvaG9tZS9zZi9jb2RlL2ltbXV0YWJsZS9ub2RlX21vZHVsZXMvZ2VudGVzdC9saWIvZXJyb3JzLmpzOjMyOjM4KVxuLy8gICAgIGF0IF9ydW4gKC9ob21lL3NmL2NvZGUvaW1tdXRhYmxlL25vZGVfbW9kdWxlcy9nZW50ZXN0L2xpYi9ydW4uanM6NTk6MTUpXG4vLyAgICAgYXQgT2JqZWN0LnJ1biAoL2hvbWUvc2YvY29kZS9pbW11dGFibGUvbm9kZV9tb2R1bGVzL2dlbnRlc3QvbGliL3J1bi5qczozNzoxMClcbi8vICAgICBhdCBDb250ZXh0Ljxhbm9ueW1vdXM+ICgvaG9tZS9zZi9jb2RlL2ltbXV0YWJsZS90ZXN0L2luZGV4LmpzOjQ0OjIwKVxuLy8gICAgIFsuLi4gbW9yZSBsaW5lcyBub3Qgc2hvd24gLi4uXVxuLy9cbi8vIFRPRE86IFRlc3QgdG8gbWFrZSBzdXJlIHRoaXMgZG9lcyByZWFzb25hYmxlIHRoaW5ncyBpbiBicm93c2Vyc1xuLy8gYXMgd2VsbCBhcyBOb2RlLlxuLy9cbmZ1bmN0aW9uIGNsZWFudXBTdGFjayhzdHIsIGVycm9yTmFtZSkge1xuICBpZiAodHlwZW9mIHN0ciAhPT0gJ3N0cmluZycpIHJldHVybiBzdHI7XG5cbiAgdmFyIGlzTGlicmFyeUNvZGUgPSBmdW5jdGlvbihsaW5lKSB7XG4gICAgcmV0dXJuIGxpbmUubWF0Y2goL1xcL2dlbnRlc3RcXC8vKSB8fFxuICAgICAgICAgICBsaW5lLm1hdGNoKC9hdCggbmV3KT8gKFxcdyspRXJyb3IvKTtcbiAgfTtcblxuICB2YXIgbGluZXMgPSBzdHIuc3BsaXQoL1xcbi8pO1xuICB2YXIgaSA9IDE7XG4gIHdoaWxlIChpIDwgbGluZXMubGVuZ3RoICYmIGlzTGlicmFyeUNvZGUobGluZXNbaV0pKSB7XG4gICAgaSsrO1xuICB9XG4gIHJldHVybiBbbGluZXNbMF1dLmNvbmNhdChsaW5lcy5zbGljZShpKSkuam9pbignXFxuJyk7XG59XG5cbnZhciBFcnJvclN1YmNsYXNzID0gZnVuY3Rpb24gRXJyb3JTdWJjbGFzcygpIHt9O1xuRXJyb3JTdWJjbGFzcy5wcm90b3R5cGUgPSBFcnJvci5wcm90b3R5cGU7XG5cbnZhciBHZW50ZXN0RXJyb3IgPSBmdW5jdGlvbiBHZW50ZXN0RXJyb3IoKSB7XG4gIGlmICghdGhpcyBpbnN0YW5jZW9mIEdlbnRlc3RFcnJvcikge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ0dlbnRlc3RFcnJvciBtdXN0IGJlIGNhbGxlZCB2aWEgbmV3Jyk7XG4gIH1cbiAgdmFyIHRtcCA9IEVycm9yLnByb3RvdHlwZS5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICBpZiAodG1wLnN0YWNrKSB7XG4gICAgdGhpcy5zdGFjayA9IGNsZWFudXBTdGFjayh0bXAuc3RhY2spLnJlcGxhY2UoL15FcnJvci8sICdHZW50ZXN0RXJyb3InKTtcbiAgfVxuICBpZiAodG1wLm1lc3NhZ2UpIHtcbiAgICB0aGlzLm1lc3NhZ2UgPSB0bXAubWVzc2FnZTtcbiAgfVxuICB0aGlzLm5hbWUgPSAnR2VudGVzdEVycm9yJztcbiAgcmV0dXJuIHRoaXM7XG59O1xuR2VudGVzdEVycm9yLnByb3RvdHlwZSA9IG5ldyBFcnJvclN1YmNsYXNzKCk7XG5HZW50ZXN0RXJyb3IucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gR2VudGVzdEVycm9yO1xuXG52YXIgRmFpbHVyZUVycm9yID0gZnVuY3Rpb24gRmFpbHVyZUVycm9yKCkge1xuICBHZW50ZXN0RXJyb3IucHJvdG90eXBlLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gIGlmICh0aGlzLnN0YWNrKSB7XG4gICAgdGhpcy5zdGFjayA9IHRoaXMuc3RhY2sucmVwbGFjZSgvXkdlbnRlc3RFcnJvci8sICdGYWlsdXJlRXJyb3InKTtcbiAgfVxuICB0aGlzLm5hbWUgPSAnRmFpbHVyZUVycm9yJztcbn07XG5GYWlsdXJlRXJyb3IucHJvdG90eXBlID0gbmV3IEdlbnRlc3RFcnJvcigpO1xuRmFpbHVyZUVycm9yLnByb3RvdHlwZS5jb25zdHJ1Y3RvciA9IEZhaWx1cmVFcnJvcjtcblxuZXhwb3J0cy5HZW50ZXN0RXJyb3IgPSBHZW50ZXN0RXJyb3I7XG5leHBvcnRzLkZhaWx1cmVFcnJvciA9IEZhaWx1cmVFcnJvcjtcbiIsInZhciBQUk5HID0gcmVxdWlyZSgnYnVydGxlcHJuZycpO1xudmFyIGVycm9ycyA9IHJlcXVpcmUoJy4vZXJyb3JzJyk7XG5cbi8vIFRPRE86IGFkZCBhIG1heFNpemUgcGFyYW1ldGVyIHNvbWVob3cuXG4vLyBSZXR1cm5zIHRydWUgaWYgYWxsIHRlc3RzIHBhc3NlZC5cbmZ1bmN0aW9uIHJ1bihmdW5jLCBudW1UZXN0cywgc2VlZCkge1xuICAvLyBNZXNzIHdpdGggYXJndW1lbnRzLiBWYXJhcmdzIGFyZSBnZW5lcmF0b3JzLFxuICAvLyBhbmQgbnVtVGVzdHMgYW5kIHNlZWQgYXJlIG9wdGlvbmFsIHNvIG1heSBhbHNvIGJlXG4gIC8vIGdlbmVyYXRvcnMuXG4gIC8vIChIb3dldmVyLCBudW1UZXN0cyBtdXN0IGJlIHByb3ZpZGVkIGlmIHNlZWQgaXMuKVxuICB2YXIgZ2VuZXJhdG9ycyA9IFtdLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAzKTtcblxuICB2YXIgZGVmYXVsdFNlZWQgPSBEYXRlLm5vdygpO1xuICBpZiAodHlwZW9mIHNlZWQgPT09ICdmdW5jdGlvbicpIHtcbiAgICBnZW5lcmF0b3JzLnVuc2hpZnQoc2VlZCk7XG4gICAgc2VlZCA9IGRlZmF1bHRTZWVkO1xuICB9IGVsc2UgaWYgKHR5cGVvZiBzZWVkID09PSAndW5kZWZpbmVkJykge1xuICAgIHNlZWQgPSBkZWZhdWx0U2VlZDtcbiAgfSBlbHNlIGlmICh0eXBlb2Ygc2VlZCAhPT0gJ251bWJlcicpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdzZWVkIG11c3QgYmUgYSBudW1iZXInKTtcbiAgfVxuICBzZWVkICY9IDB4ZmZmZmZmZmY7XG5cbiAgdmFyIERFRkFVTFRfTlVNX1RFU1RTID0gMTAwO1xuICBpZiAodHlwZW9mIG51bVRlc3RzID09PSAnZnVuY3Rpb24nKSB7XG4gICAgZ2VuZXJhdG9ycy51bnNoaWZ0KG51bVRlc3RzKTtcbiAgICBudW1UZXN0cyA9IERFRkFVTFRfTlVNX1RFU1RTO1xuICB9IGVsc2UgaWYgKHR5cGVvZiBudW1UZXN0cyA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAvLyBUaGlzIHN1Z2dlc3RzIHlvdXIgdGVzdHMgdXNlIG5vIGdlbmVyYXRvcnMgYXQgYWxsLFxuICAgIC8vIHdoaWNoIHNlZW1zIGFuIHVubGlrZWx5IGNhc2UsIGJ1dCB3aGF0ZXZlci5cbiAgICBudW1UZXN0cyA9IERFRkFVTFRfTlVNX1RFU1RTO1xuICB9IGVsc2UgaWYgKHR5cGVvZiBudW1UZXN0cyAhPT0gJ251bWJlcicgfHwgbnVtVGVzdHMgPCAxKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignbnVtVGVzdHMgbXVzdCBiZSBhIHBvc2l0aXZlIG51bWJlcicpO1xuICB9XG4gIG51bVRlc3RzID4+Pj0gMDtcblxuICByZXR1cm4gX3J1bihmdW5jLCBudW1UZXN0cywgc2VlZCwgZ2VuZXJhdG9ycyk7XG59XG5cbmZ1bmN0aW9uIF9ydW4oZnVuYywgbnVtVGVzdHMsIHNlZWQsIGdlbnMpIHtcbiAgdmFyIHBybmcgPSBuZXcgUFJORyhzZWVkKTtcblxuICBmb3IgKHZhciB4ID0gMDsgeCA8IG51bVRlc3RzOyB4KyspIHtcbiAgICB2YXIgc2l6ZSA9IE1hdGguZmxvb3IoeC8yKSArIDE7XG4gICAgdmFyIHZhbHVlcyA9IGdlbnMubWFwKGZ1bmN0aW9uKGdlbikge1xuICAgICAgcmV0dXJuIGdlbihwcm5nLCBzaXplKTtcbiAgICB9KTtcbiAgICBpZiAoIWZ1bmMuYXBwbHkobnVsbCwgdmFsdWVzKSkge1xuICAgICAgdmFyIG1zZyA9ICdwcm9wZXJ0eSAnICsgKGZ1bmMubmFtZSA/IGZ1bmMubmFtZSArICcgJyA6ICcnKSArXG4gICAgICAgICAgICAgICAgJ3Zpb2xhdGVkJztcbiAgICAgIHZhciBlID0gbmV3IGVycm9ycy5GYWlsdXJlRXJyb3IobXNnKTtcbiAgICAgIGUudGVzdENhc2UgPSB2YWx1ZXM7XG4gICAgICBlLnByb3BlcnR5ID0gZnVuYy5uYW1lO1xuICAgICAgdGhyb3cgZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gdHJ1ZTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBydW47XG4iLCJ2YXIgUFJORyA9IHJlcXVpcmUoJ2J1cnRsZXBybmcnKTtcblxudmFyIERFRkFVTFRfQ09VTlQgPSAxMDtcblxuLy8gVE9ETzogc2hvdWxkIHRoaXMgaGF2ZSBhIHNpemUgcGFyYW1ldGVyPyBTaG91bGQgZ2VudGVzdC5ydW4gYmUgbW9kaWZpZWRcbi8vIHRvIHVzZSB0aGlzIHJvdXRpbmUgaW5zdGVhZCBvZiBkb2luZyBpdHMgb3duIHNhbXBsaW5nP1xuZnVuY3Rpb24gc2FtcGxlKGdlbiwgY291bnQpIHtcbiAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPCAyKSB7XG4gICAgY291bnQgPSBERUZBVUxUX0NPVU5UO1xuICB9XG5cbiAgdmFyIHJuZyA9IG5ldyBQUk5HKERhdGUubm93KCkgJiAweGZmZmZmZmZmKTtcbiAgdmFyIHJlc3VsdHMgPSBuZXcgQXJyYXkoY291bnQpO1xuICBmb3IgKHZhciBpID0gMDsgaSA8IGNvdW50OyBpKyspIHtcbiAgICByZXN1bHRzW2ldID0gZ2VuKHJuZywgTWF0aC5mbG9vcihpLzIpICsgMSk7XG4gIH1cbiAgcmV0dXJuIHJlc3VsdHM7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gc2FtcGxlO1xuIiwidmFyIGVycm9ycyA9IHJlcXVpcmUoJy4vZXJyb3JzJyk7XG5cbi8vIFVzaW5nIHRoZSBnaXZlbiBQUk5HLCBwaWNrcyBhbiBpbnQgZnJvbSBsb3cgdG8gaGlnaCwgaW5jbHVzaXZlLlxuZnVuY3Rpb24gY2hvb3NlKHBybmcsIGxvdywgaGlnaCkge1xuICByZXR1cm4gTWF0aC5mbG9vcihwcm5nLmZsb2F0KCkgKiAoaGlnaCAtIGxvdyArIDEpICsgbG93KTtcbn1cblxudmFyIHQgPSB7fTtcblxudC5udW1iZXIgPSBmdW5jdGlvbihybmcsIHNpemUpIHtcbiAgcmV0dXJuIHJuZy5mbG9hdCgpICogc2l6ZSoyIC0gc2l6ZTtcbn07XG5cbnQubnVtYmVyLm5vbk5lZ2F0aXZlID0gZnVuY3Rpb24ocm5nLCBzaXplKSB7XG4gIHJldHVybiBybmcuZmxvYXQoKSAqIHNpemU7XG59O1xuXG50LnN1Y2hUaGF0ID0gZnVuY3Rpb24ocHJlZCwgZ2VuLCBtYXhUcmllcykge1xuICBpZiAoYXJndW1lbnRzLmxlbmd0aCA8IDMpIG1heFRyaWVzID0gMTA7XG5cbiAgcmV0dXJuIGZ1bmN0aW9uKHJuZywgc2l6ZSkge1xuICAgIHZhciB0cmllc0xlZnQgPSBtYXhUcmllcztcbiAgICB2YXIgdmFsO1xuICAgIGRvIHtcbiAgICAgIHZhbCA9IGdlbihybmcsIHNpemUpO1xuICAgICAgaWYgKHByZWQodmFsKSkge1xuICAgICAgICByZXR1cm4gdmFsO1xuICAgICAgfVxuICAgIH0gd2hpbGUoLS10cmllc0xlZnQgPiAwKTtcbiAgICB0aHJvdyBuZXcgZXJyb3JzLkdlbnRlc3RFcnJvcignc3VjaFRoYXQ6IGNvdWxkIG5vdCBmaW5kIGEgc3VpdGFibGUgdmFsdWUnKTtcbiAgfTtcbn07XG5cbmZ1bmN0aW9uIGlzTm9uemVybyh4KSB7XG4gIHJldHVybiB4ICE9PSAwO1xufVxuXG50Lm51bWJlci5ub25aZXJvID0gdC5zdWNoVGhhdChpc05vbnplcm8sIHQubnVtYmVyKTtcbnQubnVtYmVyLnBvc2l0aXZlID0gdC5zdWNoVGhhdChpc05vbnplcm8sIHQubnVtYmVyLm5vbk5lZ2F0aXZlKTtcblxudC5pbnQgPSBmdW5jdGlvbihybmcsIHNpemUpIHtcbiAgcmV0dXJuIGNob29zZShybmcsIC1zaXplLCBzaXplKTtcbn07XG5cbnQuaW50Lm5vbk5lZ2F0aXZlID0gZnVuY3Rpb24ocm5nLCBzaXplKSB7XG4gIHJldHVybiBjaG9vc2Uocm5nLCAwLCBzaXplKTtcbn07XG5cbnQuaW50Lm5vblplcm8gPSB0LnN1Y2hUaGF0KGlzTm9uemVybywgdC5pbnQpO1xuXG50LmludC5wb3NpdGl2ZSA9IGZ1bmN0aW9uKHJuZywgc2l6ZSkge1xuICByZXR1cm4gY2hvb3NlKHJuZywgMSwgc2l6ZSArIDEpO1xufTtcblxuLy8gRklYTUU6IFRoaXMgc2hvdWxkIGV2ZW50dWFsbHkgZ2VuZXJhdGUgbm9uLUFTQ0lJIGNoYXJhY3RlcnMsIEkgZ3Vlc3MuXG50LmNoYXIgPSBmdW5jdGlvbihybmcsIF8pIHtcbiAgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUoY2hvb3NlKHJuZywgMzIsIDEyNikpO1xufTtcblxudC5hcnJheU9mID0gZnVuY3Rpb24oZWxlbUdlbikge1xuICByZXR1cm4gZnVuY3Rpb24ocm5nLCBzaXplKSB7XG4gICAgdmFyIGxlbiA9IHQuaW50Lm5vbk5lZ2F0aXZlKHJuZywgc2l6ZSk7XG4gICAgdmFyIGFycmF5ID0gbmV3IEFycmF5KGxlbik7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgYXJyYXlbaV0gPSBlbGVtR2VuKHJuZywgc2l6ZSk7XG4gICAgfVxuICAgIHJldHVybiBhcnJheTtcbiAgfTtcbn07XG5cbnQuZm1hcCA9IGZ1bmN0aW9uKGZ1biwgZ2VuKSB7XG4gIHJldHVybiBmdW5jdGlvbihybmcsIHNpemUpIHtcbiAgICByZXR1cm4gZnVuKGdlbihybmcsIHNpemUpKTtcbiAgfTtcbn07XG5cbnQuc3RyaW5nID0gdC5mbWFwKGZ1bmN0aW9uKGNoYXJzKSB7XG4gIHJldHVybiBjaGFycy5qb2luKCcnKTtcbn0sIHQuYXJyYXlPZih0LmNoYXIpKTtcblxuZnVuY3Rpb24gY29uc3RhbnRseSh4KSB7XG4gIHJldHVybiBmdW5jdGlvbihfLCBfKSB7XG4gICAgcmV0dXJuIHg7XG4gIH07XG59XG5cbnQub25lT2YgPSBmdW5jdGlvbihnZW5zKSB7XG4gIHJldHVybiBmdW5jdGlvbihybmcsIHNpemUpIHtcbiAgICB2YXIgd2hpY2ggPSBjaG9vc2Uocm5nLCAwLCBnZW5zLmxlbmd0aC0xKTtcbiAgICByZXR1cm4gZ2Vuc1t3aGljaF0ocm5nLCBzaXplKTtcbiAgfTtcbn07XG5cbnQuZWxlbWVudHMgPSBmdW5jdGlvbihlbGVtcykge1xuICByZXR1cm4gdC5vbmVPZihlbGVtcy5tYXAoY29uc3RhbnRseSkpO1xufTtcblxudC5ib29sID0gdC5lbGVtZW50cyhbZmFsc2UsIHRydWVdKTtcblxudC5zaGFwZSA9IGZ1bmN0aW9uKG9iaikge1xuICByZXR1cm4gZnVuY3Rpb24ocm5nLCBzaXplKSB7XG4gICAgdmFyIG91dCA9IHt9O1xuICAgIE9iamVjdC5rZXlzKG9iaikuZm9yRWFjaChmdW5jdGlvbihrZXkpIHtcbiAgICAgIG91dFtrZXldID0gb2JqW2tleV0ocm5nLCBzaXplKTtcbiAgICB9KTtcbiAgICByZXR1cm4gb3V0O1xuICB9O1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSB0O1xuIiwiZnVuY3Rpb24gQnVydGxlUFJORyhzZWVkKSB7XG4gIHNlZWQgPj4+PSAwO1xuICB2YXIgY3R4ID0gdGhpcy5jdHggPSBuZXcgQXJyYXkoNCk7XG4gIGN0eFswXSA9IDB4ZjFlYTVlZWQ7XG4gIGN0eFsxXSA9IGN0eFsyXSA9IGN0eFszXSA9IHNlZWQ7XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgMjA7IGkrKykge1xuICAgIHRoaXMubmV4dCgpO1xuICB9XG4gIHJldHVybiB0aGlzO1xufVxuXG5mdW5jdGlvbiByb3QoeCwgaykge1xuICByZXR1cm4gKHggPDwgaykgfCAoeCA+PiAoMzItaykpO1xufVxuXG5CdXJ0bGVQUk5HLnByb3RvdHlwZS5uZXh0ID0gZnVuY3Rpb24oKSB7XG4gIHZhciBjdHggPSB0aGlzLmN0eDtcbiAgdmFyIGUgPSAgICAgICAgICAgKGN0eFswXSAtIHJvdChjdHhbMV0sIDI3KSk+Pj4wO1xuICBjdHhbMF0gPSAoY3R4WzFdIF4gcm90KGN0eFsyXSwgMTcpKT4+PjA7XG4gIGN0eFsxXSA9IChjdHhbMl0gKyBjdHhbM10pPj4+MDtcbiAgY3R4WzJdID0gKGN0eFszXSArIGUpPj4+MDtcbiAgY3R4WzNdID0gKGUgICAgICArIGN0eFswXSk+Pj4wO1xuICByZXR1cm4gY3R4WzNdO1xufTtcblxuQnVydGxlUFJORy5wcm90b3R5cGVbJ2Zsb2F0J10gPSBmdW5jdGlvbigpIHtcbiAgcmV0dXJuIHRoaXMubmV4dCgpIC8gNDI5NDk2NzI5Ni4wO1xufTtcblxuaWYgKHR5cGVvZiBtb2R1bGUgPT09ICdvYmplY3QnKSB7XG4gIG1vZHVsZS5leHBvcnRzID0gQnVydGxlUFJORztcbn1cbiJdfQ== |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment