<commit_before>/*
 * Paper.js - The Swiss Army Knife of Vector Graphics Scripting.
 * http://paperjs.org/
 *
 * Copyright (c) 2011 - 2013, Juerg Lehni & Jonathan Puckey
 * http://lehni.org/ & http://jonathanpuckey.com/
 *
 * Distributed under the MIT license. See LICENSE file for details.
 *
 * All rights reserved.
 */

// Register a jsDump parser for Base.
QUnit.jsDump.setParser('Base', function (obj, stack) {
	return obj.toString();
});

// Override the default object parser to handle Base objects.
// We need to keep a reference to the previous implementation.
var objectParser = QUnit.jsDump.parsers.object;

QUnit.jsDump.setParser('object', function (obj, stack) {
	return (obj instanceof Base
			? QUnit.jsDump.parsers.Base
			: objectParser).call(this, obj, stack);
});

// Override equals to convert functions to message and execute them as tests()
function equals(actual, expected, message, tolerance) {
	if (typeof actual === 'function') {
		if (!message) {
			message = actual.toString().match(
				/^\s*function[^\{]*\{([\s\S]*)\}\s*$/)[1]
					.replace(/    /g, '')
					.replace(/^\s+|\s+$/g, '');
			if (/^return /.test(message)) {
				message = message
					.replace(/^return /, '')
					.replace(/;$/, '');
			}
		}
		actual = actual();
	}
	// See if we need to compare with a tolerance, and if so, assume a number.
	if (tolerance !== undefined) {
		var ok = Math.abs(actual - expected) <= tolerance;
		return QUnit.push(ok, ok ? expected : actual, expected, message);
	} else if (expected && expected.equals) {
		// Support calling of #equals() on the expected value, and automatically
		// convert displayed values to strings.
		return QUnit.push(expected.equals(actual), actual + '', expected + '',
				message);
	} else {
		// Let's be strict
		return strictEqual(actual, expected, message);
	}
}

function test(testName, expected) {
	return QUnit.test(testName, function() {
		var project = new Project();
		expected();
		project.remove();
	});
}

function asyncTest(testName, expected) {
	return QUnit.asyncTest(testName, function() {
		var project = new Project();
		expected(function() {
			project.remove();
			start();
		});
	});
}

function compareNumbers(number1, number2, message, precision) {
	var formatter = new Formatter(precision);
	equals(formatter.number(number1, precision),
			formatter.number(number2, precision), message);
}

function compareArrays(array1, array2, message, precision) {
	var formatter = new Formatter(precision);
	function format(array) {
		return Base.each(array, function(value, index) {
			this[index] = formatter.number(value, precision);
		}, []).toString();
	}
	equals(format(array1), format(array2), message);
}

function comparePoints(point1, point2, message) {
	compareNumbers(point1.x, point2.x, (message || '') + ' x');
	compareNumbers(point1.y, point2.y, (message || '') + ' y');
}

function compareRectangles(rect1, rect2, message) {
	compareNumbers(rect1.x, rect2.x, (message || '') + ' x');
	compareNumbers(rect1.y, rect2.y, (message || '') + ' y');
	compareNumbers(rect1.width, rect2.width, (message || '') + ' width');
	compareNumbers(rect1.height, rect2.height, (message || '') + ' height');
}

function compareColors(color1, color2, message, precision) {
	color1 = color1 && new Color(color1);
	color2 = color2 && new Color(color2);
	if (color1 && color2) {
		equals(color1.type, color2.type, (message || '') + ' type');
		compareArrays(color1.components, color2.components,
				(message || '') + ' components', precision);
	} else {
		equals(color1, color2, message);
	}
}

function compareStyles(style, style2, checkIdentity) {
	if (checkIdentity) {
		equals(function() {
			return style !== style2;
		}, true);
	}
	Base.each(['fillColor', 'strokeColor'], function(key) {
		if (style[key]) {
			// The color should not point to the same color object:
			if (checkIdentity) {
				equals(function() {
					return style[key] !== style2[key];
				}, true, 'The ' + key + ' should not point to the same color object:');
			}
			if (style[key] instanceof Color) {
				if (style[key].type === 'gradient' && checkIdentity) {
					equals(function() {
						return style[key].gradient === style2[key].gradient;
					}, true, 'The ' + key + '.gradient should point to the same object:');
				}
				compareColors(style[key], style2[key],
						'Compare Style#' + key);
			} else {
				equals(style[key] && style[key].toString(),
						style2[key] && style2[key].toString(),
						'Compare Style#' + key);
			}
		}
	});

	compareObjects('Style', ['strokeCap', 'strokeJoin', 'dashArray',
			'dashOffset', 'miterLimit', 'strokeOverprint', 'fillOverprint',
			'fontSize', 'font', 'leading', 'justification'],
			style, style2, checkIdentity);
}

function compareObjects(name, keys, obj, obj2, checkIdentity) {
	if (checkIdentity) {
		equals(function() {
			return obj !== obj2;
		}, true);
	}
	Base.each(keys, function(key) {
		var val = obj[key], val2 = obj2[key],
			message = 'Compare ' + name + '#' + key;
		if (typeof val === 'number') {
			compareNumbers(val, val2, message);
		} else if (Array.isArray(val)) {
			compareArrays(val, val2, message);
		} else {
			equals(val, val2, message);
		}
	});
}

function compareSegmentPoints(segmentPoint, segmentPoint2, checkIdentity) {
	compareObjects('SegmentPoint', ['x', 'y', 'selected'],
			segmentPoint, segmentPoint2, checkIdentity);
}

function compareSegments(segment, segment2, checkIdentity) {
	if (checkIdentity) {
		equals(function() {
			return segment !== segment2;
		}, true);
	}
	equals(function() {
		return segment.selected == segment2.selected;
	}, true);
	Base.each(['handleIn', 'handleOut', 'point'], function(key) {
		compareSegmentPoints(segment[key], segment2[key]);
	});
}

function compareSegmentLists(segmentList, segmentList2, checkIdentity) {
	if (checkIdentity) {
		equals(function() {
			return segmentList !== segmentList2;
		}, true);
	}
	equals(segmentList.toString(), segmentList2.toString(),
			'Compare Item#segments');
	if (checkIdentity) {
		for (var i = 0, l = segmentList.length; i < l; i++) {
			var segment = segmentList[i],
				segment2 = segmentList2[i];
			compareSegments(segment, segment2, checkIdentity);
		}
	}
}

function compareItems(item, item2, cloned, checkIdentity, dontShareProject) {
	if (checkIdentity) {
		equals(function() {
			return item !== item2;
		}, true);

		equals(function() {
			return item.id !== item2.id;
		}, true);
	}

	equals(function() {
		return item.constructor == item2.constructor;
	}, true);

	var itemProperties = ['opacity', 'locked', 'visible', 'blendMode', 'name',
			'selected', 'clipMask'];
	Base.each(itemProperties, function(key) {
		var value = item[key];
		// When item was cloned and had a name, the name will be versioned
		equals(
			key == 'name' && cloned && value
				? value + ' 1'
				: value,
			item2[key],
			'compare Item#' + key);
	});

	if (checkIdentity) {
		equals(function() {
			return item.bounds !== item2.bounds;
		}, true);
	}

	equals(item.bounds.toString(), item2.bounds.toString(),
			'Compare Item#bounds');

	if (checkIdentity) {
		equals(function() {
			return item.position !== item2.position;
		}, true);
	}

	equals(item.position.toString(), item2.position.toString(),
			'Compare Item#position');

	equals(function() {
		return Base.equals(item.data, item2.data);
	}, true);

	if (item.matrix) {
		if (checkIdentity) {
			equals(function() {
				return item.matrix !== item2.matrix;
			}, true);
		}
		equals(item.matrix.toString(), item2.matrix.toString(),
				'Compare Item#matrix');
	}

	// Path specific
	if (item2 instanceof Path) {
		var keys = ['closed', 'fullySelected', 'clockwise'];
		for (var i = 0, l = keys.length; i < l; i++) {
			var key = keys[i];
			equals(item[key], item2[key], 'Compare Path#' + key);
		}
		compareNumbers(item.length, item2.length, 'Compare Path#length');
		compareSegmentLists(item.segments, item2.segments, checkIdentity);
	}

	// Group specific
	if (item instanceof Group) {
		equals(function() {
			return item.clipped == item2.clipped;
		}, true);
	}

	// Layer specific
	if (item instanceof Layer) {
		equals(function() {
			return dontShareProject
					? item.project != item2.project
					: item.project == item2.project;
		}, true);
	}

	// PlacedSymbol specific
	if (item instanceof PlacedSymbol) {
		if (dontShareProject) {
			compareItems(item.symbol.definition, item2.symbol.definition,
					cloned, checkIdentity, dontShareProject,
					'Compare Symbol#definition');
		} else {
			equals(function() {
				return item.symbol == item2.symbol;
			}, true);
		}
	}

	// Raster specific
	if (item instanceof Raster) {
		equals(item.size.toString(), item2.size.toString(),
				'Compare Raster#size');
		compareNumbers(item.width, item2.width, 'Compare Raster#width');
		compareNumbers(item.height, item2.height, 'Compare Raster#height');

		equals(item.ppi.toString(), item2.ppi.toString(),
				'Compare Raster#ppi');

		equals(item.source, item2.source, 'Compare Raster#source');
		if (checkIdentity) {
			equals(item.image, item2.image, 'Compare Raster#image');
		}
		equals(item.size.toString(), item2.size.toString(),
				'Compare Raster#size');
		equals(item.toDataURL() == item2.toDataURL(), true,
				'Compare Raster#toDataUrl()');
	}

	// TextItem specific:
	if (item instanceof TextItem) {
		equals(item.content, item2.content, 'Compare Item#content');
	}

	// PointText specific:
	if (item instanceof PointText) {
		if (checkIdentity) {
			equals(function() {
				return item.point !== item2.point;
			}, true);
		}
		equals(item.point.toString(), item2.point.toString(),
				'Compare Item#point');
	}

	if (item.style) {
		// Style
		compareStyles(item.style, item2.style, checkIdentity);
	}

	// Check length of children and recursively compare them:
	if (item.children) {
		equals(function() {
			return item.children.length == item2.children.length;
		}, true);
		for (var i = 0, l = item.children.length; i < l; i++) {
			compareItems(item.children[i], item2.children[i], cloned,
					checkIdentity, dontShareProject);
		}
	}
}

function compareProjects(project, project2) {
	// Compare Project#symbols:
	equals(function() {
		return project.symbols.length == project2.symbols.length;
	}, true);
	for (var i = 0, l = project.symbols.length; i < l; i++) {
		var definition1 = project.symbols[i].definition;
		var definition2 = project2.symbols[i].definition;
		compareItems(definition1, definition2, false, false, true,
				'Compare Symbol#definition');
	}

	// Compare Project#layers:
	equals(function() {
		return project.layers.length == project2.layers.length;
	}, true);
	for (var i = 0, l = project.layers.length; i < l; i++) {
		compareItems(project.layers[i], project2.layers[i], false, false, true);
	}
}

// SVG

function createSVG(xml) {
	return new DOMParser().parseFromString('<svg xmlns="http://www.w3.org/2000/svg">' + xml + '</svg>', 'application/xml');
}<commit_msg>Improve equals() test helper.<commit_after>/*
 * Paper.js - The Swiss Army Knife of Vector Graphics Scripting.
 * http://paperjs.org/
 *
 * Copyright (c) 2011 - 2013, Juerg Lehni & Jonathan Puckey
 * http://lehni.org/ & http://jonathanpuckey.com/
 *
 * Distributed under the MIT license. See LICENSE file for details.
 *
 * All rights reserved.
 */

// Register a jsDump parser for Base.
QUnit.jsDump.setParser('Base', function (obj, stack) {
	return obj.toString();
});

// Override the default object parser to handle Base objects.
// We need to keep a reference to the previous implementation.
var objectParser = QUnit.jsDump.parsers.object;

QUnit.jsDump.setParser('object', function (obj, stack) {
	return (obj instanceof Base
			? QUnit.jsDump.parsers.Base
			: objectParser).call(this, obj, stack);
});

// Override equals to convert functions to message and execute them as tests()
function equals(actual, expected, message, tolerance) {
	if (typeof actual === 'function') {
		if (!message) {
			message = actual.toString().match(
				/^\s*function[^\{]*\{([\s\S]*)\}\s*$/)[1]
					.replace(/    /g, '')
					.replace(/^\s+|\s+$/g, '');
			if (/^return /.test(message)) {
				message = message
					.replace(/^return /, '')
					.replace(/;$/, '');
			}
		}
		actual = actual();
	}
	// See if we need to compare with a tolerance, and if so, assume a number.
	if (tolerance !== undefined) {
		var ok = Math.abs(actual - expected) <= tolerance;
		return QUnit.push(ok, ok ? expected : actual, expected, message);
	} else if (actual && actual.equals) {
		// Support calling of #equals() on the actual or expected value, and
		// automatically convert displayed values to strings.
		return QUnit.push(actual.equals(expected), actual, expected, message);
	} else if (expected && expected.equals) {
		return QUnit.push(expected.equals(actual), actual, expected, message);
	}
	// Let's be strict
	return strictEqual(actual, expected, message);
}

function test(testName, expected) {
	return QUnit.test(testName, function() {
		var project = new Project();
		expected();
		project.remove();
	});
}

function asyncTest(testName, expected) {
	return QUnit.asyncTest(testName, function() {
		var project = new Project();
		expected(function() {
			project.remove();
			start();
		});
	});
}

function compareNumbers(number1, number2, message, precision) {
	var formatter = new Formatter(precision);
	equals(formatter.number(number1, precision),
			formatter.number(number2, precision), message);
}

function compareArrays(array1, array2, message, precision) {
	var formatter = new Formatter(precision);
	function format(array) {
		return Base.each(array, function(value, index) {
			this[index] = formatter.number(value, precision);
		}, []).toString();
	}
	equals(format(array1), format(array2), message);
}

function comparePoints(point1, point2, message) {
	compareNumbers(point1.x, point2.x, (message || '') + ' x');
	compareNumbers(point1.y, point2.y, (message || '') + ' y');
}

function compareRectangles(rect1, rect2, message) {
	compareNumbers(rect1.x, rect2.x, (message || '') + ' x');
	compareNumbers(rect1.y, rect2.y, (message || '') + ' y');
	compareNumbers(rect1.width, rect2.width, (message || '') + ' width');
	compareNumbers(rect1.height, rect2.height, (message || '') + ' height');
}

function compareColors(color1, color2, message, precision) {
	color1 = color1 && new Color(color1);
	color2 = color2 && new Color(color2);
	if (color1 && color2) {
		equals(color1.type, color2.type, (message || '') + ' type');
		compareArrays(color1.components, color2.components,
				(message || '') + ' components', precision);
	} else {
		equals(color1, color2, message);
	}
}

function compareStyles(style, style2, checkIdentity) {
	if (checkIdentity) {
		equals(function() {
			return style !== style2;
		}, true);
	}
	Base.each(['fillColor', 'strokeColor'], function(key) {
		if (style[key]) {
			// The color should not point to the same color object:
			if (checkIdentity) {
				equals(function() {
					return style[key] !== style2[key];
				}, true, 'The ' + key + ' should not point to the same color object:');
			}
			if (style[key] instanceof Color) {
				if (style[key].type === 'gradient' && checkIdentity) {
					equals(function() {
						return style[key].gradient === style2[key].gradient;
					}, true, 'The ' + key + '.gradient should point to the same object:');
				}
				compareColors(style[key], style2[key],
						'Compare Style#' + key);
			} else {
				equals(style[key] && style[key].toString(),
						style2[key] && style2[key].toString(),
						'Compare Style#' + key);
			}
		}
	});

	compareObjects('Style', ['strokeCap', 'strokeJoin', 'dashArray',
			'dashOffset', 'miterLimit', 'strokeOverprint', 'fillOverprint',
			'fontSize', 'font', 'leading', 'justification'],
			style, style2, checkIdentity);
}

function compareObjects(name, keys, obj, obj2, checkIdentity) {
	if (checkIdentity) {
		equals(function() {
			return obj !== obj2;
		}, true);
	}
	Base.each(keys, function(key) {
		var val = obj[key], val2 = obj2[key],
			message = 'Compare ' + name + '#' + key;
		if (typeof val === 'number') {
			compareNumbers(val, val2, message);
		} else if (Array.isArray(val)) {
			compareArrays(val, val2, message);
		} else {
			equals(val, val2, message);
		}
	});
}

function compareSegmentPoints(segmentPoint, segmentPoint2, checkIdentity) {
	compareObjects('SegmentPoint', ['x', 'y', 'selected'],
			segmentPoint, segmentPoint2, checkIdentity);
}

function compareSegments(segment, segment2, checkIdentity) {
	if (checkIdentity) {
		equals(function() {
			return segment !== segment2;
		}, true);
	}
	equals(function() {
		return segment.selected == segment2.selected;
	}, true);
	Base.each(['handleIn', 'handleOut', 'point'], function(key) {
		compareSegmentPoints(segment[key], segment2[key]);
	});
}

function compareSegmentLists(segmentList, segmentList2, checkIdentity) {
	if (checkIdentity) {
		equals(function() {
			return segmentList !== segmentList2;
		}, true);
	}
	equals(segmentList.toString(), segmentList2.toString(),
			'Compare Item#segments');
	if (checkIdentity) {
		for (var i = 0, l = segmentList.length; i < l; i++) {
			var segment = segmentList[i],
				segment2 = segmentList2[i];
			compareSegments(segment, segment2, checkIdentity);
		}
	}
}

function compareItems(item, item2, cloned, checkIdentity, dontShareProject) {
	if (checkIdentity) {
		equals(function() {
			return item !== item2;
		}, true);

		equals(function() {
			return item.id !== item2.id;
		}, true);
	}

	equals(function() {
		return item.constructor == item2.constructor;
	}, true);

	var itemProperties = ['opacity', 'locked', 'visible', 'blendMode', 'name',
			'selected', 'clipMask'];
	Base.each(itemProperties, function(key) {
		var value = item[key];
		// When item was cloned and had a name, the name will be versioned
		equals(
			key == 'name' && cloned && value
				? value + ' 1'
				: value,
			item2[key],
			'compare Item#' + key);
	});

	if (checkIdentity) {
		equals(function() {
			return item.bounds !== item2.bounds;
		}, true);
	}

	equals(item.bounds.toString(), item2.bounds.toString(),
			'Compare Item#bounds');

	if (checkIdentity) {
		equals(function() {
			return item.position !== item2.position;
		}, true);
	}

	equals(item.position.toString(), item2.position.toString(),
			'Compare Item#position');

	equals(function() {
		return Base.equals(item.data, item2.data);
	}, true);

	if (item.matrix) {
		if (checkIdentity) {
			equals(function() {
				return item.matrix !== item2.matrix;
			}, true);
		}
		equals(item.matrix.toString(), item2.matrix.toString(),
				'Compare Item#matrix');
	}

	// Path specific
	if (item2 instanceof Path) {
		var keys = ['closed', 'fullySelected', 'clockwise'];
		for (var i = 0, l = keys.length; i < l; i++) {
			var key = keys[i];
			equals(item[key], item2[key], 'Compare Path#' + key);
		}
		compareNumbers(item.length, item2.length, 'Compare Path#length');
		compareSegmentLists(item.segments, item2.segments, checkIdentity);
	}

	// Group specific
	if (item instanceof Group) {
		equals(function() {
			return item.clipped == item2.clipped;
		}, true);
	}

	// Layer specific
	if (item instanceof Layer) {
		equals(function() {
			return dontShareProject
					? item.project != item2.project
					: item.project == item2.project;
		}, true);
	}

	// PlacedSymbol specific
	if (item instanceof PlacedSymbol) {
		if (dontShareProject) {
			compareItems(item.symbol.definition, item2.symbol.definition,
					cloned, checkIdentity, dontShareProject,
					'Compare Symbol#definition');
		} else {
			equals(function() {
				return item.symbol == item2.symbol;
			}, true);
		}
	}

	// Raster specific
	if (item instanceof Raster) {
		equals(item.size.toString(), item2.size.toString(),
				'Compare Raster#size');
		compareNumbers(item.width, item2.width, 'Compare Raster#width');
		compareNumbers(item.height, item2.height, 'Compare Raster#height');

		equals(item.ppi.toString(), item2.ppi.toString(),
				'Compare Raster#ppi');

		equals(item.source, item2.source, 'Compare Raster#source');
		if (checkIdentity) {
			equals(item.image, item2.image, 'Compare Raster#image');
		}
		equals(item.size.toString(), item2.size.toString(),
				'Compare Raster#size');
		equals(item.toDataURL() == item2.toDataURL(), true,
				'Compare Raster#toDataUrl()');
	}

	// TextItem specific:
	if (item instanceof TextItem) {
		equals(item.content, item2.content, 'Compare Item#content');
	}

	// PointText specific:
	if (item instanceof PointText) {
		if (checkIdentity) {
			equals(function() {
				return item.point !== item2.point;
			}, true);
		}
		equals(item.point.toString(), item2.point.toString(),
				'Compare Item#point');
	}

	if (item.style) {
		// Style
		compareStyles(item.style, item2.style, checkIdentity);
	}

	// Check length of children and recursively compare them:
	if (item.children) {
		equals(function() {
			return item.children.length == item2.children.length;
		}, true);
		for (var i = 0, l = item.children.length; i < l; i++) {
			compareItems(item.children[i], item2.children[i], cloned,
					checkIdentity, dontShareProject);
		}
	}
}

function compareProjects(project, project2) {
	// Compare Project#symbols:
	equals(function() {
		return project.symbols.length == project2.symbols.length;
	}, true);
	for (var i = 0, l = project.symbols.length; i < l; i++) {
		var definition1 = project.symbols[i].definition;
		var definition2 = project2.symbols[i].definition;
		compareItems(definition1, definition2, false, false, true,
				'Compare Symbol#definition');
	}

	// Compare Project#layers:
	equals(function() {
		return project.layers.length == project2.layers.length;
	}, true);
	for (var i = 0, l = project.layers.length; i < l; i++) {
		compareItems(project.layers[i], project2.layers[i], false, false, true);
	}
}

// SVG

function createSVG(xml) {
	return new DOMParser().parseFromString('<svg xmlns="http://www.w3.org/2000/svg">' + xml + '</svg>', 'application/xml');
}<|endoftext|>


<commit_before>/*jshint expr: true*/
var expect    = require('chai').expect;
var clone     = require('clone');
var validator = require('validator');
var equal     = require('deep-equal');
var txLib     = require('../../lib/tx');

describe('lib/tx', function(){

  describe('.getTx()', function(){

    var tx = require('./examples/tx_8DFC1A7FBB60472CBEE9211D4DA44A5A42542729C9472D6B582302C77F31D95B.json');
    var remote = {
        constructor: {
          name: 'Remote'
        },
        _getServer: function(){
          return {
            _lastLedgerClose: Date.now()
          };
        },
        requestTx: function(tx_hash, callback) {
          if (tx_hash === '8DFC1A7FBB60472CBEE9211D4DA44A5A42542729C9472D6B582302C77F31D95B') {
            callback(null, tx);
          } else {
            callback(new Error('ripple-lib error'));
          }
        }
      };

    it('should respond with an error if given no hash', function(done){
      txLib.getTx({}, function(err, res){
        expect(err).to.exist;
        expect(err.message).to.equal('Invalid parameter: tx_hash. Must provide a transaction hash to look for');
        expect(res).not.to.exist;
        done();
      });
    });

    it('should respond with an error if given an invalid hash', function(done){
      txLib.getTx({
        remote: remote,
        tx_hash: 'badhash'
      }, function(err, res){
        expect(err).to.exist;
        expect(err.message).to.equal('Invalid parameter: tx_hash. Must provide a transaction hash to look for');
        expect(res).not.to.exist;
        done();
      });
    });

    it('should respond with an error if it cannot locate a transaction for a given hash', function(done){
      txLib.getTx({
        remote: remote,
        tx_hash: '00001A7FBB60472CBEE9211D4DA44A5A42542729C9472D6B582302C77F31D95B'
      }, function(err, res){
        expect(err).to.exist;
        expect(err.message).to.equal('Cannot locate transaction. This may be the result of an incomplete rippled historical database or that transaction may not exist. Error: ripple-lib error');
        expect(res).not.to.exist;
        done();
      });
    });

    it('should get a full ripple tx if given a valid hash', function(done){

      txLib.getTx({
        remote: remote,
        hash: '8DFC1A7FBB60472CBEE9211D4DA44A5A42542729C9472D6B582302C77F31D95B'
      }, function(err, res){
        expect(err).not.to.exist;
        expect(res).to.deep.equal(tx);
        done();
      });
    });

  });

});

<commit_msg>[TEST] Added another test<commit_after>/*jshint expr: true*/
var expect    = require('chai').expect;
var clone     = require('clone');
var validator = require('validator');
var equal     = require('deep-equal');
var txLib     = require('../../lib/tx');

describe('lib/tx', function(){

  describe('.getTx()', function(){

    var tx = require('./examples/tx_8DFC1A7FBB60472CBEE9211D4DA44A5A42542729C9472D6B582302C77F31D95B.json');
    var remote = {
        constructor: {
          name: 'Remote'
        },
        _getServer: function(){
          return {
            _lastLedgerClose: Date.now()
          };
        },
        requestTx: function(tx_hash, callback) {
          if (tx_hash === '8DFC1A7FBB60472CBEE9211D4DA44A5A42542729C9472D6B582302C77F31D95B') {
            callback(null, tx);
          } else {
            callback(new Error('ripple-lib error'));
          }
        }
      };

    it('should respond with an error if given no hash', function(done){
      txLib.getTx({}, function(err, res){
        expect(err).to.exist;
        expect(err.message).to.equal('Invalid parameter: tx_hash. Must provide a transaction hash to look for');
        expect(res).not.to.exist;
        done();
      });
    });

    it('should respond with an error if given an invalid hash', function(done){
      txLib.getTx({
        remote: remote,
        tx_hash: 'badhash'
      }, function(err, res){
        expect(err).to.exist;
        expect(err.message).to.equal('Invalid parameter: tx_hash. Must provide a transaction hash to look for');
        expect(res).not.to.exist;
        done();
      });
    });

    it('should respond with an error if it cannot locate a transaction for a given hash', function(done){
      txLib.getTx({
        remote: remote,
        tx_hash: '00001A7FBB60472CBEE9211D4DA44A5A42542729C9472D6B582302C77F31D95B'
      }, function(err, res){
        expect(err).to.exist;
        expect(err.message).to.equal('Cannot locate transaction. This may be the result of an incomplete rippled historical database or that transaction may not exist. Error: ripple-lib error');
        expect(res).not.to.exist;
        done();
      });
    });

    it('should get a full ripple tx if given a valid hash', function(done){

      txLib.getTx({
        remote: remote,
        hash: '8DFC1A7FBB60472CBEE9211D4DA44A5A42542729C9472D6B582302C77F31D95B'
      }, function(err, res){
        expect(err).not.to.exist;
        expect(res).to.deep.equal(tx);
        done();
      });
    });

  });

});

<|endoftext|>


<commit_before>var fs = require('fs');
var path = require('path');
var assign = require('object-assign');
var expect = require('expect.js');
var webpack = require('webpack');

describe('svg-url-loader', function() {
    'use strict';

    var outputDir = path.resolve(__dirname, './output'),
        bundleFileName = 'bundle.js',
        getBundleFile = function() {
            return path.join(outputDir, bundleFileName);
        };
    var svgUrlLoader = path.resolve(__dirname, '../');
    var globalConfig = {
        context: path.resolve(__dirname, '../'),
        output: {
            path: outputDir,
            filename: bundleFileName
        },
        module: {
            loaders: [
                {
                    test: /\.svg/,
                    loader: svgUrlLoader,
                    query: {},
                    exclude: /node_modules/
                }
            ]
        }
    };

    // Clean generated cache files before each test so that we can call each test with an empty state.
    afterEach(function(done) {
        fs.unlink(getBundleFile(), done);
        globalConfig.module.loaders[0].query = {};
    });

    describe('"noquotes" option', function () {
        it('should convert SVG file to utf-8 encoded data-uri string, enclosed in quotes', function(done) {
            var config = assign({}, globalConfig, {
                entry: './test/input/icon.js'
            });
            config.module.loaders[0].query.noquotes = false;

            webpack(config, function(err) {
                expect(err).to.be(null);
                fs.readFile(getBundleFile(), function(err, data) {
                    expect(err).to.be(null);
                    var encoded = (0,eval)(data.toString());
                    expect(encoded.indexOf('"')).to.be(0);
                    expect(encoded.lastIndexOf('"')).to.be(encoded.length - 1);
                    expect(encoded.indexOf('data:image/svg+xml;charset=utf8,%3Csvg')).to.be(1);
                    return done();
                });
            });
        });

        it('should not enclose output in quotes if \'noquotes\' option is specified', function(done) {
            var config = assign({}, globalConfig, {
                entry: './test/input/icon.js'
            });
            config.module.loaders[0].query.noquotes = true;

            webpack(config, function(err) {
                expect(err).to.be(null);
                fs.readFile(getBundleFile(), function(err, data) {
                    expect(err).to.be(null);
                    var encoded = (0,eval)(data.toString());
                    expect(encoded.indexOf('data:image/svg+xml;charset=utf8,%3Csvg')).to.be(0);
                    expect(encoded.lastIndexOf('svg%3E')).to.be(encoded.length - 'svg%3E'.length);
                    return done();
                });
            });
        });
    });

    describe('"limit" option and "url.dataUrlLimit" configuration', function () {
        it('should fall back to file-loader if the content of SVG file is longer than "limit" query parameter', function(done) {
            var config = assign({}, globalConfig, {
                entry: './test/input/icon.js'
            });
            config.module.loaders[0].query.limit = 10;
            config.module.loaders[0].query.name = 'foo.svg';

            webpack(config, function(err) {
                expect(err).to.be(null);
                fs.readFile(getBundleFile(), function(err, data) {
                    expect(err).to.be(null);
                    var encoded = (0,eval)(data.toString());
                    expect(encoded).to.be('foo.svg');
                    return done();
                });
            });
        });

        it('should fall back to file-loader if the content of SVG file is longer than "url.dataUrlLimit" option', function(done) {
            var config = assign({}, globalConfig, {
                entry: './test/input/icon.js'
            });
            config.module.loaders[0].query.name = 'foo.svg';
            config.url = {
                dataUrlLimit: 10
            };

            webpack(config, function(err) {
                expect(err).to.be(null);
                fs.readFile(getBundleFile(), function(err, data) {
                    expect(err).to.be(null);
                    var encoded = (0,eval)(data.toString());
                    expect(encoded).to.be('foo.svg');
                    return done();
                });
            });
        });

        it('should fall back to file-loader and prefer limit specified by query parameter to the limit specified by "url.dataUrlLimit" configuration', function(done) {
            var config = assign({}, globalConfig, {
                entry: './test/input/icon.js'
            });
            config.module.loaders[0].query.limit = 100000000;
            config.url = {
                dataUrlLimit: 10
            };

            webpack(config, function(err) {
                expect(err).to.be(null);
                fs.readFile(getBundleFile(), function(err, data) {
                    expect(err).to.be(null);
                    var encoded = (0,eval)(data.toString());
                    expect(encoded.indexOf('"')).to.be(0);
                    expect(encoded.lastIndexOf('"')).to.be(encoded.length - 1);
                    expect(encoded.indexOf('data:image/svg+xml;charset=utf8,%3Csvg')).to.be(1);
                    return done();
                });
            });
        });
    });

    describe('combining with other loaders', function () {
        it('should convert SVG file to utf-8 encoded data-uri string, when embedded in LESS file', function(done) {
            var config = assign({}, globalConfig, {
                entry: './test/input/less.js'
            });
            config.module.loaders[0].query.noquotes = false;
            config.module.loaders.push({
                test: /\.less$/,
                loaders: [
                    'css-loader',
                    'less-loader'
                ]
            });

            webpack(config, function(err) {
                expect(err).to.be(null);
                fs.readFile(getBundleFile(), function(err, data) {
                    expect(err).to.be(null);
                    var encoded = (0,eval)(data.toString()),
                        found = false;
                    for(var i=0; i<encoded[0].length; ++i) {
                        var v = encoded[0][i];
                        if (typeof v === 'string' && v.indexOf('background-image: url("data:image/svg+xml;charset=utf8,%3Csvg') !== -1) {
                            found = true;
                        }
                    }
                    expect(found).to.be(true);
                    return done();
                });
            });
        });

        it('should convert SVG file to utf-8 encoded data-uri string, when embedded in SCSS file', function(done) {
            var config = assign({}, globalConfig, {
                entry: './test/input/scss.js'
            });
            config.module.loaders[0].query.noquotes = false;
            config.module.loaders.push({
                test: /\.scss$/,
                loaders: [
                    'css-loader',
                    'sass-loader'
                ]
            });

            webpack(config, function(err) {
                expect(err).to.be(null);
                fs.readFile(getBundleFile(), function(err, data) {
                    expect(err).to.be(null);
                    var encoded = (0,eval)(data.toString()),
                        found = false;
                    for(var i=0; i<encoded[0].length; ++i) {
                        var v = encoded[0][i];
                        if (typeof v === 'string' && v.indexOf('background-image: url("data:image/svg+xml;charset=utf8,%3Csvg') !== -1) {
                            found = true;
                        }
                    }
                    expect(found).to.be(true);
                    return done();
                });
            });
        });

        it('should convert SVG file to utf-8 encoded data-uri string, when embedded in CSS file', function(done) {
            var config = assign({}, globalConfig, {
                entry: './test/input/css.js'
            });
            config.module.loaders[0].query.noquotes = false;
            config.module.loaders.push({
                test: /\.css$/,
                loaders: [
                    'css-loader'
                ]
            });

            webpack(config, function(err) {
                expect(err).to.be(null);
                fs.readFile(getBundleFile(), function(err, data) {
                    expect(err).to.be(null);
                    var encoded = (0,eval)(data.toString()),
                        found = false;
                    for(var i=0; i<encoded[0].length; ++i) {
                        var v = encoded[0][i];
                        if (typeof v === 'string' && v.indexOf('background-image: url("data:image/svg+xml;charset=utf8,%3Csvg') !== -1) {
                            found = true;
                        }
                    }
                    expect(found).to.be(true);
                    return done();
                });
            });
        });
    });
});
<commit_msg>chore: increasing timeout to avoid flaky Travis CI failures<commit_after>var fs = require('fs');
var path = require('path');
var assign = require('object-assign');
var expect = require('expect.js');
var webpack = require('webpack');

var ASYNC_TEST_TIMEOUT = 10000;

describe('svg-url-loader', function() {
    'use strict';

    var outputDir = path.resolve(__dirname, './output'),
        bundleFileName = 'bundle.js',
        getBundleFile = function() {
            return path.join(outputDir, bundleFileName);
        };
    var svgUrlLoader = path.resolve(__dirname, '../');
    var globalConfig = {
        context: path.resolve(__dirname, '../'),
        output: {
            path: outputDir,
            filename: bundleFileName
        },
        module: {
            loaders: [
                {
                    test: /\.svg/,
                    loader: svgUrlLoader,
                    query: {},
                    exclude: /node_modules/
                }
            ]
        }
    };

    // Clean generated cache files before each test so that we can call each test with an empty state.
    afterEach(function(done) {
        fs.unlink(getBundleFile(), done);
        globalConfig.module.loaders[0].query = {};
    });

    describe('"noquotes" option', function () {
        it('should convert SVG file to utf-8 encoded data-uri string, enclosed in quotes', function(done) {
            var config = assign({}, globalConfig, {
                entry: './test/input/icon.js'
            });
            config.module.loaders[0].query.noquotes = false;

            webpack(config, function(err) {
                expect(err).to.be(null);
                fs.readFile(getBundleFile(), function(err, data) {
                    expect(err).to.be(null);
                    var encoded = (0,eval)(data.toString());
                    expect(encoded.indexOf('"')).to.be(0);
                    expect(encoded.lastIndexOf('"')).to.be(encoded.length - 1);
                    expect(encoded.indexOf('data:image/svg+xml;charset=utf8,%3Csvg')).to.be(1);
                    return done();
                });
            });
        }, ASYNC_TEST_TIMEOUT);

        it('should not enclose output in quotes if \'noquotes\' option is specified', function(done) {
            var config = assign({}, globalConfig, {
                entry: './test/input/icon.js'
            });
            config.module.loaders[0].query.noquotes = true;

            webpack(config, function(err) {
                expect(err).to.be(null);
                fs.readFile(getBundleFile(), function(err, data) {
                    expect(err).to.be(null);
                    var encoded = (0,eval)(data.toString());
                    expect(encoded.indexOf('data:image/svg+xml;charset=utf8,%3Csvg')).to.be(0);
                    expect(encoded.lastIndexOf('svg%3E')).to.be(encoded.length - 'svg%3E'.length);
                    return done();
                });
            });
        }, ASYNC_TEST_TIMEOUT);
    });

    describe('"limit" option and "url.dataUrlLimit" configuration', function () {
        it('should fall back to file-loader if the content of SVG file is longer than "limit" query parameter', function(done) {
            var config = assign({}, globalConfig, {
                entry: './test/input/icon.js'
            });
            config.module.loaders[0].query.limit = 10;
            config.module.loaders[0].query.name = 'foo.svg';

            webpack(config, function(err) {
                expect(err).to.be(null);
                fs.readFile(getBundleFile(), function(err, data) {
                    expect(err).to.be(null);
                    var encoded = (0,eval)(data.toString());
                    expect(encoded).to.be('foo.svg');
                    return done();
                });
            });
        }, ASYNC_TEST_TIMEOUT);

        it('should fall back to file-loader if the content of SVG file is longer than "url.dataUrlLimit" option', function(done) {
            var config = assign({}, globalConfig, {
                entry: './test/input/icon.js'
            });
            config.module.loaders[0].query.name = 'foo.svg';
            config.url = {
                dataUrlLimit: 10
            };

            webpack(config, function(err) {
                expect(err).to.be(null);
                fs.readFile(getBundleFile(), function(err, data) {
                    expect(err).to.be(null);
                    var encoded = (0,eval)(data.toString());
                    expect(encoded).to.be('foo.svg');
                    return done();
                });
            });
        }, ASYNC_TEST_TIMEOUT);

        it('should fall back to file-loader and prefer limit specified by query parameter to the limit specified by "url.dataUrlLimit" configuration', function(done) {
            var config = assign({}, globalConfig, {
                entry: './test/input/icon.js'
            });
            config.module.loaders[0].query.limit = 100000000;
            config.url = {
                dataUrlLimit: 10
            };

            webpack(config, function(err) {
                expect(err).to.be(null);
                fs.readFile(getBundleFile(), function(err, data) {
                    expect(err).to.be(null);
                    var encoded = (0,eval)(data.toString());
                    expect(encoded.indexOf('"')).to.be(0);
                    expect(encoded.lastIndexOf('"')).to.be(encoded.length - 1);
                    expect(encoded.indexOf('data:image/svg+xml;charset=utf8,%3Csvg')).to.be(1);
                    return done();
                });
            });
        }, ASYNC_TEST_TIMEOUT);
    });

    describe('combining with other loaders', function () {
        it('should convert SVG file to utf-8 encoded data-uri string, when embedded in LESS file', function(done) {
            var config = assign({}, globalConfig, {
                entry: './test/input/less.js'
            });
            config.module.loaders[0].query.noquotes = false;
            config.module.loaders.push({
                test: /\.less$/,
                loaders: [
                    'css-loader',
                    'less-loader'
                ]
            });

            webpack(config, function(err) {
                expect(err).to.be(null);
                fs.readFile(getBundleFile(), function(err, data) {
                    expect(err).to.be(null);
                    var encoded = (0,eval)(data.toString()),
                        found = false;
                    for(var i=0; i<encoded[0].length; ++i) {
                        var v = encoded[0][i];
                        if (typeof v === 'string' && v.indexOf('background-image: url("data:image/svg+xml;charset=utf8,%3Csvg') !== -1) {
                            found = true;
                        }
                    }
                    expect(found).to.be(true);
                    return done();
                });
            });
        }, ASYNC_TEST_TIMEOUT);

        it('should convert SVG file to utf-8 encoded data-uri string, when embedded in SCSS file', function(done) {
            var config = assign({}, globalConfig, {
                entry: './test/input/scss.js'
            });
            config.module.loaders[0].query.noquotes = false;
            config.module.loaders.push({
                test: /\.scss$/,
                loaders: [
                    'css-loader',
                    'sass-loader'
                ]
            });

            webpack(config, function(err) {
                expect(err).to.be(null);
                fs.readFile(getBundleFile(), function(err, data) {
                    expect(err).to.be(null);
                    var encoded = (0,eval)(data.toString()),
                        found = false;
                    for(var i=0; i<encoded[0].length; ++i) {
                        var v = encoded[0][i];
                        if (typeof v === 'string' && v.indexOf('background-image: url("data:image/svg+xml;charset=utf8,%3Csvg') !== -1) {
                            found = true;
                        }
                    }
                    expect(found).to.be(true);
                    return done();
                });
            });
        }, ASYNC_TEST_TIMEOUT);

        it('should convert SVG file to utf-8 encoded data-uri string, when embedded in CSS file', function(done) {
            var config = assign({}, globalConfig, {
                entry: './test/input/css.js'
            });
            config.module.loaders[0].query.noquotes = false;
            config.module.loaders.push({
                test: /\.css$/,
                loaders: [
                    'css-loader'
                ]
            });

            webpack(config, function(err) {
                expect(err).to.be(null);
                fs.readFile(getBundleFile(), function(err, data) {
                    expect(err).to.be(null);
                    var encoded = (0,eval)(data.toString()),
                        found = false;
                    for(var i=0; i<encoded[0].length; ++i) {
                        var v = encoded[0][i];
                        if (typeof v === 'string' && v.indexOf('background-image: url("data:image/svg+xml;charset=utf8,%3Csvg') !== -1) {
                            found = true;
                        }
                    }
                    expect(found).to.be(true);
                    return done();
                });
            });
        }, ASYNC_TEST_TIMEOUT);
    });
});
<|endoftext|>


<commit_before>var pg = require('pg');

function add() {}

function dump() {
	pg.connect(process.env.DATABASE_URL, function (err, client, done) {
		client.query('SELECT * FROM results', function (err, result) {
			done();
			if (err) {
				console.error(err);
				return "Error " + err;
			} else {
				return result.rows;
			}
		});
	});
}

module.exports = {
	add : add,
	dump : dump
};
<commit_msg>Fix dump query<commit_after>var pg = require('pg');

function add() {

}

function dump() {
	pg.connect(process.env.DATABASE_URL, function (err, client, done) {
		client.query('TABLE results;', function (err, result) {
			done();
			if (err) {
				console.error(err);
				return "Error " + err;
			} else {
				return result.rows;
			}
		});
	});
}

module.exports = {
	add : add,
	dump : dump
};
<|endoftext|>


<commit_before>/*
* ProtectedInfowindow
* v0.21
*/

function ProtectedInfowindow(map, opts) {

  this.content = {};

  this.latlng_ = null;
  this.offsetHorizontal_ = 0;
  this.offsetVertical_   = -10;
  this.width_ = 295;
  this.div_ = null;
  this.map_ = map;
  this.setMap(map);

  if (opts) {
    this.className         = opts.className;
    this.offsetHorizontal_ = ("offsetHorizontal" in opts) ? opts.offsetHorizontal : 0;
    this.offsetVertical_   = ("offsetVertical" in opts) ? opts.offsetVertical : 0;
    this.width_            = opts.width;
    this.template          = opts.template;
  }
}

ProtectedInfowindow.prototype = new google.maps.OverlayView();

ProtectedInfowindow.prototype.draw = function() {
  var me = this;

  var div = this.div_;
  if (!div) {
    div = this.div_ = document.createElement('DIV');

    div.className = this.className || "cartodb_infowindow with_image";

    div.innerHTML = ''+
      '
'+
      '
' +
      '

'+
      '
' +
      '
'+
      '

' +
      '
'+
      '
'+
      '

'+
      '

';

    var close = this.getElementsByClassName("close", div)[0];
    var analyse = this.getElementsByClassName("analyse", div)[0];

    google.maps.event.addDomListener(analyse, 'click', function (ev) {
      ev.preventDefault ? ev.preventDefault() : ev.returnValue = false;
      analysis._loadProtectedArea(me.content.id, me.content.name)
      me._hide();
    });

    google.maps.event.addDomListener(close, 'click', function (ev) {
      //ev.preventDefault ? ev.preventDefault() : ev.returnValue = false;
      //me._hide();
    });

    google.maps.event.addDomListener(div, 'click', function (ev) {
      //ev.preventDefault ? ev.preventDefault() : ev.returnValue = false;
      //ev.stopPropagation ? ev.stopPropagation() : window.event.cancelBubble = true;
    });

    google.maps.event.addDomListener(close, 'touchend', function (ev) {
      ev.preventDefault ? ev.preventDefault() : ev.returnValue = false;
      //me._hide();
    });

    google.maps.event.addDomListener(div, 'touchstart', function (ev) {
      ev.preventDefault ? ev.preventDefault() : ev.returnValue = false;
    });

    google.maps.event.addDomListener(div, 'touchend', function (ev) {
      ev.preventDefault ? ev.preventDefault() : ev.returnValue = false;
    });

    google.maps.event.addDomListener(div, 'dblclick', function (ev) {
      ev.preventDefault ? ev.preventDefault() : ev.returnValue = false;
    });
    google.maps.event.addDomListener(div, 'mousedown', function (ev) {
      ev.preventDefault ? ev.preventDefault() : ev.returnValue = false;
      ev.stopPropagation ? ev.stopPropagation() : window.event.cancelBubble = true;
    });
    google.maps.event.addDomListener(div, 'mouseup', function (ev) {
      ev.preventDefault ? ev.preventDefault() : ev.returnValue = false;
    });
    google.maps.event.addDomListener(div, 'mousewheel', function (ev) {
      ev.stopPropagation ? ev.stopPropagation() : window.event.cancelBubble = true;
    });
    google.maps.event.addDomListener(div, 'DOMMouseScroll', function (ev) {
      ev.stopPropagation ? ev.stopPropagation() : window.event.cancelBubble = true;
    });

    var panes = this.getPanes();
    panes.floatPane.appendChild(div);

    div.style.opacity = 0;
  }

  this.setPosition();

};

ProtectedInfowindow.prototype.setTemplate = function(template){
  this.template_ = template;
};

ProtectedInfowindow.prototype.setOffset = function(offsetVertical, offsetHorizontal){
  this.offsetHorizontal_ = offsetHorizontal;
  this.offsetVertical_   = offsetVertical;
};

ProtectedInfowindow.prototype.setContent = function(content){

  if (this.div_) {

    var div = this.div_
    , top = this.getElementsByClassName("infowindow_content", div)[0];

    if (!content) { return; }

      top.innerHTML = '';
      var html = '';

      this.content = content;
      var sorted = [];

      for (var column in content) {
        if (column === "id") {
          sorted[column] = content[column];
        }
      }

      for (var column in content) {
        if (column === "name") {
          sorted[column] = content[column];
        }
      }

      for (var column in content) {
        if (column === "desig_eng") {
          sorted[column] = content[column];
        }
      }

      for (var column in content) {
        if (column === "local_name") {
          sorted[column] = content[column];
        }
      }

      for (var column in sorted) {
        if (sorted[column] != null && sorted[column] != ''){
          html += '' + column + '';
          html += '
'+(sorted[column] || 'empty')+'
';
        }

      }

      top.innerHTML = html;
      $(div).find("h1").html(content.name);
      $(div).find("img").attr("src", content.image.replace("square", "medium"));
      $(div).find("img").css("width", "295px");

  }

};

ProtectedInfowindow.prototype.setPosition = function(latlng) {
  if (latlng) {
    this.latlng_ = latlng;
    // Adjust pan
    this._adjustPan();
  }

  if (this.div_) {
    var div = this.div_
    , pixPosition = this.getProjection().fromLatLngToDivPixel(this.latlng_);
    if (pixPosition) {
      div.style.width = this.width_ + 'px';
      div.style.left = (pixPosition.x - this.width_ / 2 + this.offsetHorizontal_) + 'px';
      var actual_height = - div.clientHeight;
      div.style.top = (pixPosition.y + actual_height + this.offsetVertical_) + 'px';
    }
  }
};

ProtectedInfowindow.prototype.open = function(){
  this._show();
};

ProtectedInfowindow.prototype.close2 = function(){
  this._hide();
};
ProtectedInfowindow.prototype.close = function(){
  this._hide();
};

ProtectedInfowindow.prototype.destroy = function() {
  // Check if the overlay was on the map and needs to be removed.
  if (this.div_) {
    this.div_.parentNode.removeChild(this.div_);
    this.div_ = null;
  }
  this.setMap(null);
};

ProtectedInfowindow.prototype._hide = function() {

  if (this.div_) {

    var div = this.div_;

    $(div).find(".header img").attr("src", "/assets/backgrounds/cover.png");

    emile(div,{
      opacity: 0,
      duration: 1,
      after: function(){
        div.style.visibility = "hidden";
      }
    });
  }
};

ProtectedInfowindow.prototype._show = function() {
  if (this.div_) {

    var div = this.div_;
    div.style.opacity = 0;
    div.style.top = (parseInt(div.style.top, 10) - 10) + 'px';

    div.style.visibility = "visible";
     $(".imgLiquidFill").imgLiquid();

    if (this.api_) {
      this.api_.destroy();
    }

    var pane = $(".cartodb_infowindow.with_image .infowindow_content").jScrollPane( { showArrows: true });
    var api = this.api_ = pane.data('jsp');
    api.scrollToY(0); // scroll to top

    emile(div,{
      opacity: 1,
      duration: 250
    });
  }
};

ProtectedInfowindow.prototype._adjustPan = function() {
  var left = 0
  , top = 0
  , pixPosition = this.getProjection().fromLatLngToContainerPixel(this.latlng_)
  , container = this.map_.getDiv()
  , div_height = this.div_.clientHeight;

  if ((pixPosition.x - 165) < 0) {
    left = (pixPosition.x - 165);
  }

  if ((pixPosition.x + 180) >= container.clientWidth) {
    left = (pixPosition.x + 180 - container.clientWidth);
  }

  if ((pixPosition.y - div_height) < 0) {
    top = (pixPosition.y - div_height - 20);
  }

  this.map_.panBy(left,top);
};

ProtectedInfowindow.prototype.getElementsByClassName = function(classname, node)  {
  if(!node) node = document.getElementsByTagName("body")[0];
  var a = [];
  var re = new RegExp('\\b' + classname + '\\b');
  var els = node.getElementsByTagName("*");
  for(var i=0,j=els.length; i<j; i++)
    if(re.test(els[i].className))a.push(els[i]);
  return a;
}

/*!
* emile.js (c) 2009 - 2011 Thomas Fuchs
* Licensed under the terms of the MIT license.
*/
!function(a){function A(a,b){a=typeof a=="string"?document.getElementById(a):a,b=z(b);var c={duration:b.duration,easing:b.easing,after:b.after};delete b.duration,delete b.easing,delete b.after;if(e&&typeof c.easing!="function")return y(a,b,c);var d=q(b,function(a,b){a=r(a);return p(a)in h&&g.test(b)?[a,b+"px"]:[a,b]});x(a,d,c)}function z(a){var b={};for(var c in a)b[c]=a[c],c=="after"&&delete a[c];return b}function y(a,b,c){var d=[],f=[],i=c.duration||1e3,j=c.easing||"ease-out",k="";i=i+"ms",a.addEventListener(l,function m(){a.setAttribute("style",k),c.after&&c.after(),a.removeEventListener(l,m,!0)},!0),setTimeout(function(){var c;for(c in b)b.hasOwnProperty(c)&&d.push(r(c)+" "+i+" "+j);for(c in b){var f=p(c)in h&&g.test(b[c])?b[c]+"px":b[c];b.hasOwnProperty(c)&&(a.style[p(c)]=f)}k=a.getAttribute("style"),d=d.join(","),a.style[e+"Transition"]=d},10)}function x(a,b,c,d){c=c||{};var e=w(b),f=a.currentStyle?a.currentStyle:getComputedStyle(a,null),g={},h=+(new Date),i,j=c.duration||200,k=h+j,l,m=c.easing||function(a){return-Math.cos(a*Math.PI)/2+.5};for(i in e)g[i]=v(f[i]);l=setInterval(function(){var b=+(new Date),f,i=b>k?1:(b-h)/j;for(f in e)a.style[f]=e[f].f(g[f].v,e[f].v,m(i))+e[f].u;b>k&&(clearInterval(l),c.after&&c.after(),d&&setTimeout(d,1))},10)}function w(a){var c,d={},e=k.length,f;b.innerHTML='

',c=b.childNodes[0].style;while(e--)(f=c[k[e]])&&(d[k[e]]=v(f));return d}function v(a){var b=parseFloat(a),c=a?a.replace(/^[\-\d\.]+/,""):a;return isNaN(b)?{v:c,f:u,u:""}:{v:b,f:s,u:c}}function u(a,b,c){var d=2,e,f,g,h=[],i=[];while((e=3)&&(f=arguments[d-1])&&d--)if(t(f,0)=="r"){f=f.match(/\d+/g);while(e--)h.push(~~f[e])}else{f.length==4&&(f="#"+t(f,1)+t(f,1)+t(f,2)+t(f,2)+t(f,3)+t(f,3));while(e--)h.push(parseInt(t(f,1+e*2,2),16))}while(e--)g=~~(h[e+3]+(h[e]-h[e+3])*c),i.push(g<0?0:g>255?255:g);return"rgb("+i.join(",")+")"}function t(a,b,c){return a.substr(b,c||1)}function s(a,b,c){return(a+(b-a)*c).toFixed(3)}function r(a){if(a.toUpperCase()===a)return a;return a.replace(/([a-zA-Z0-9])([A-Z])/g,function(a,b,c){return b+"-"+c}).toLowerCase()}function q(a,b){return o(a,function(a,c){var d=b?b(c,a):[c,a];return d[0]+":"+d[1]+";"}).join("")}function p(a){return a.replace(/-(.)/g,function(a,b){return b.toUpperCase()})}function o(a,b,c){var d=[],e;for(e in a)d.push(b.call(c,a[e],e,a));return d}var b=document.createElement("div"),c=["webkit","Moz","O"],d=3,e,f,g=/\d+$/,h={},i="backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color fontWeight lineHeight opacity outlineColor zIndex",j="top bottom left right borderWidth borderBottomWidth borderLeftWidth borderRightWidth borderTopWidth borderSpacing borderRadius marginBottom marginLeft marginRight marginTop width height maxHeight maxWidth minHeight minWidth paddingBottom paddingLeft paddingRight paddingTop fontSize wordSpacing textIndent letterSpacing outlineWidth outlineOffset",k=(i+" "+j).split(" ");while(d--)f=c[d],b.style.cssText="-"+f.toLowerCase()+"-transition-property:opacity;",typeof b.style[f+"TransitionProperty"]!="undefined"&&(e=f);var l=/^w/.test(e)?"webkitTransitionEnd":"transitionend";for(var m=j.split(" "),n=m.length;n--;)h[m[n]]=1;var B=a.emile;A.noConflict=function(){a.emile=B;return this},a.emile=A}(this)
<commit_msg>rearrange protected infowindows columns<commit_after>/*
* ProtectedInfowindow
* v0.21
*/

function ProtectedInfowindow(map, opts) {

  this.content = {};

  this.latlng_ = null;
  this.offsetHorizontal_ = 0;
  this.offsetVertical_   = -10;
  this.width_ = 295;
  this.div_ = null;
  this.map_ = map;
  this.setMap(map);

  if (opts) {
    this.className         = opts.className;
    this.offsetHorizontal_ = ("offsetHorizontal" in opts) ? opts.offsetHorizontal : 0;
    this.offsetVertical_   = ("offsetVertical" in opts) ? opts.offsetVertical : 0;
    this.width_            = opts.width;
    this.template          = opts.template;
  }
}

ProtectedInfowindow.prototype = new google.maps.OverlayView();

ProtectedInfowindow.prototype.draw = function() {
  var me = this;

  var div = this.div_;
  if (!div) {
    div = this.div_ = document.createElement('DIV');

    div.className = this.className || "cartodb_infowindow with_image";

    div.innerHTML = ''+
      '
'+
      '
' +
      '

'+
      '
' +
      '
'+
      '

' +
      '
'+
      '
'+
      '

'+
      '

';

    var close = this.getElementsByClassName("close", div)[0];
    var analyse = this.getElementsByClassName("analyse", div)[0];

    google.maps.event.addDomListener(analyse, 'click', function (ev) {
      ev.preventDefault ? ev.preventDefault() : ev.returnValue = false;
      analysis._loadProtectedArea(me.content.id, me.content.name)
      me._hide();
    });

    google.maps.event.addDomListener(close, 'click', function (ev) {
      //ev.preventDefault ? ev.preventDefault() : ev.returnValue = false;
      //me._hide();
    });

    google.maps.event.addDomListener(div, 'click', function (ev) {
      //ev.preventDefault ? ev.preventDefault() : ev.returnValue = false;
      //ev.stopPropagation ? ev.stopPropagation() : window.event.cancelBubble = true;
    });

    google.maps.event.addDomListener(close, 'touchend', function (ev) {
      ev.preventDefault ? ev.preventDefault() : ev.returnValue = false;
      //me._hide();
    });

    google.maps.event.addDomListener(div, 'touchstart', function (ev) {
      ev.preventDefault ? ev.preventDefault() : ev.returnValue = false;
    });

    google.maps.event.addDomListener(div, 'touchend', function (ev) {
      ev.preventDefault ? ev.preventDefault() : ev.returnValue = false;
    });

    google.maps.event.addDomListener(div, 'dblclick', function (ev) {
      ev.preventDefault ? ev.preventDefault() : ev.returnValue = false;
    });
    google.maps.event.addDomListener(div, 'mousedown', function (ev) {
      ev.preventDefault ? ev.preventDefault() : ev.returnValue = false;
      ev.stopPropagation ? ev.stopPropagation() : window.event.cancelBubble = true;
    });
    google.maps.event.addDomListener(div, 'mouseup', function (ev) {
      ev.preventDefault ? ev.preventDefault() : ev.returnValue = false;
    });
    google.maps.event.addDomListener(div, 'mousewheel', function (ev) {
      ev.stopPropagation ? ev.stopPropagation() : window.event.cancelBubble = true;
    });
    google.maps.event.addDomListener(div, 'DOMMouseScroll', function (ev) {
      ev.stopPropagation ? ev.stopPropagation() : window.event.cancelBubble = true;
    });

    var panes = this.getPanes();
    panes.floatPane.appendChild(div);

    div.style.opacity = 0;
  }

  this.setPosition();

};

ProtectedInfowindow.prototype.setTemplate = function(template){
  this.template_ = template;
};

ProtectedInfowindow.prototype.setOffset = function(offsetVertical, offsetHorizontal){
  this.offsetHorizontal_ = offsetHorizontal;
  this.offsetVertical_   = offsetVertical;
};

ProtectedInfowindow.prototype.setContent = function(content){

  if (this.div_) {

    var div = this.div_
    , top = this.getElementsByClassName("infowindow_content", div)[0];

    if (!content) { return; }

      top.innerHTML = '';
      var html = '';

      this.content = content;
      var sorted = [];

      for (var column in content) {
        if (column === "name") {
          sorted[column] = content[column];
        }
      }

      for (var column in content) {
        if (column === "desig_eng") {
          sorted[column] = content[column];
        }
      }

      for (var column in content) {
        if (column === "id") {
          sorted[column] = content[column];
        }
      }

      for (var column in sorted) {
        if (sorted[column] != null && sorted[column] != ''){
          html += '' + column + '';
          html += '
'+(sorted[column] || 'empty')+'
';
        }

      }

      top.innerHTML = html;
      $(div).find("h1").html(content.name);
      $(div).find("img").attr("src", content.image.replace("square", "medium"));
      $(div).find("img").css("width", "295px");

  }

};

ProtectedInfowindow.prototype.setPosition = function(latlng) {
  if (latlng) {
    this.latlng_ = latlng;
    // Adjust pan
    this._adjustPan();
  }

  if (this.div_) {
    var div = this.div_
    , pixPosition = this.getProjection().fromLatLngToDivPixel(this.latlng_);
    if (pixPosition) {
      div.style.width = this.width_ + 'px';
      div.style.left = (pixPosition.x - this.width_ / 2 + this.offsetHorizontal_) + 'px';
      var actual_height = - div.clientHeight;
      div.style.top = (pixPosition.y + actual_height + this.offsetVertical_) + 'px';
    }
  }
};

ProtectedInfowindow.prototype.open = function(){
  this._show();
};

ProtectedInfowindow.prototype.close2 = function(){
  this._hide();
};
ProtectedInfowindow.prototype.close = function(){
  this._hide();
};

ProtectedInfowindow.prototype.destroy = function() {
  // Check if the overlay was on the map and needs to be removed.
  if (this.div_) {
    this.div_.parentNode.removeChild(this.div_);
    this.div_ = null;
  }
  this.setMap(null);
};

ProtectedInfowindow.prototype._hide = function() {

  if (this.div_) {

    var div = this.div_;

    $(div).find(".header img").attr("src", "/assets/backgrounds/cover.png");

    emile(div,{
      opacity: 0,
      duration: 1,
      after: function(){
        div.style.visibility = "hidden";
      }
    });
  }
};

ProtectedInfowindow.prototype._show = function() {
  if (this.div_) {

    var div = this.div_;
    div.style.opacity = 0;
    div.style.top = (parseInt(div.style.top, 10) - 10) + 'px';

    div.style.visibility = "visible";
     $(".imgLiquidFill").imgLiquid();

    if (this.api_) {
      this.api_.destroy();
    }

    var pane = $(".cartodb_infowindow.with_image .infowindow_content").jScrollPane( { showArrows: true });
    var api = this.api_ = pane.data('jsp');
    api.scrollToY(0); // scroll to top

    emile(div,{
      opacity: 1,
      duration: 250
    });
  }
};

ProtectedInfowindow.prototype._adjustPan = function() {
  var left = 0
  , top = 0
  , pixPosition = this.getProjection().fromLatLngToContainerPixel(this.latlng_)
  , container = this.map_.getDiv()
  , div_height = this.div_.clientHeight;

  if ((pixPosition.x - 165) < 0) {
    left = (pixPosition.x - 165);
  }

  if ((pixPosition.x + 180) >= container.clientWidth) {
    left = (pixPosition.x + 180 - container.clientWidth);
  }

  if ((pixPosition.y - div_height) < 0) {
    top = (pixPosition.y - div_height - 20);
  }

  this.map_.panBy(left,top);
};

ProtectedInfowindow.prototype.getElementsByClassName = function(classname, node)  {
  if(!node) node = document.getElementsByTagName("body")[0];
  var a = [];
  var re = new RegExp('\\b' + classname + '\\b');
  var els = node.getElementsByTagName("*");
  for(var i=0,j=els.length; i<j; i++)
    if(re.test(els[i].className))a.push(els[i]);
  return a;
}

/*!
* emile.js (c) 2009 - 2011 Thomas Fuchs
* Licensed under the terms of the MIT license.
*/
!function(a){function A(a,b){a=typeof a=="string"?document.getElementById(a):a,b=z(b);var c={duration:b.duration,easing:b.easing,after:b.after};delete b.duration,delete b.easing,delete b.after;if(e&&typeof c.easing!="function")return y(a,b,c);var d=q(b,function(a,b){a=r(a);return p(a)in h&&g.test(b)?[a,b+"px"]:[a,b]});x(a,d,c)}function z(a){var b={};for(var c in a)b[c]=a[c],c=="after"&&delete a[c];return b}function y(a,b,c){var d=[],f=[],i=c.duration||1e3,j=c.easing||"ease-out",k="";i=i+"ms",a.addEventListener(l,function m(){a.setAttribute("style",k),c.after&&c.after(),a.removeEventListener(l,m,!0)},!0),setTimeout(function(){var c;for(c in b)b.hasOwnProperty(c)&&d.push(r(c)+" "+i+" "+j);for(c in b){var f=p(c)in h&&g.test(b[c])?b[c]+"px":b[c];b.hasOwnProperty(c)&&(a.style[p(c)]=f)}k=a.getAttribute("style"),d=d.join(","),a.style[e+"Transition"]=d},10)}function x(a,b,c,d){c=c||{};var e=w(b),f=a.currentStyle?a.currentStyle:getComputedStyle(a,null),g={},h=+(new Date),i,j=c.duration||200,k=h+j,l,m=c.easing||function(a){return-Math.cos(a*Math.PI)/2+.5};for(i in e)g[i]=v(f[i]);l=setInterval(function(){var b=+(new Date),f,i=b>k?1:(b-h)/j;for(f in e)a.style[f]=e[f].f(g[f].v,e[f].v,m(i))+e[f].u;b>k&&(clearInterval(l),c.after&&c.after(),d&&setTimeout(d,1))},10)}function w(a){var c,d={},e=k.length,f;b.innerHTML='

',c=b.childNodes[0].style;while(e--)(f=c[k[e]])&&(d[k[e]]=v(f));return d}function v(a){var b=parseFloat(a),c=a?a.replace(/^[\-\d\.]+/,""):a;return isNaN(b)?{v:c,f:u,u:""}:{v:b,f:s,u:c}}function u(a,b,c){var d=2,e,f,g,h=[],i=[];while((e=3)&&(f=arguments[d-1])&&d--)if(t(f,0)=="r"){f=f.match(/\d+/g);while(e--)h.push(~~f[e])}else{f.length==4&&(f="#"+t(f,1)+t(f,1)+t(f,2)+t(f,2)+t(f,3)+t(f,3));while(e--)h.push(parseInt(t(f,1+e*2,2),16))}while(e--)g=~~(h[e+3]+(h[e]-h[e+3])*c),i.push(g<0?0:g>255?255:g);return"rgb("+i.join(",")+")"}function t(a,b,c){return a.substr(b,c||1)}function s(a,b,c){return(a+(b-a)*c).toFixed(3)}function r(a){if(a.toUpperCase()===a)return a;return a.replace(/([a-zA-Z0-9])([A-Z])/g,function(a,b,c){return b+"-"+c}).toLowerCase()}function q(a,b){return o(a,function(a,c){var d=b?b(c,a):[c,a];return d[0]+":"+d[1]+";"}).join("")}function p(a){return a.replace(/-(.)/g,function(a,b){return b.toUpperCase()})}function o(a,b,c){var d=[],e;for(e in a)d.push(b.call(c,a[e],e,a));return d}var b=document.createElement("div"),c=["webkit","Moz","O"],d=3,e,f,g=/\d+$/,h={},i="backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color fontWeight lineHeight opacity outlineColor zIndex",j="top bottom left right borderWidth borderBottomWidth borderLeftWidth borderRightWidth borderTopWidth borderSpacing borderRadius marginBottom marginLeft marginRight marginTop width height maxHeight maxWidth minHeight minWidth paddingBottom paddingLeft paddingRight paddingTop fontSize wordSpacing textIndent letterSpacing outlineWidth outlineOffset",k=(i+" "+j).split(" ");while(d--)f=c[d],b.style.cssText="-"+f.toLowerCase()+"-transition-property:opacity;",typeof b.style[f+"TransitionProperty"]!="undefined"&&(e=f);var l=/^w/.test(e)?"webkitTransitionEnd":"transitionend";for(var m=j.split(" "),n=m.length;n--;)h[m[n]]=1;var B=a.emile;A.noConflict=function(){a.emile=B;return this},a.emile=A}(this)
<|endoftext|>


<commit_before>// Some functions for inserting quickly (unack'ed writes) (Create)
// Preheating data to get it into memory (Read)
// Changing the data, with/without growth (Update)
// Removing data (Delete)

// First function is used to create a random set of data, the C in CRUD
// Defaults/Assumptions: _id index only, collection always called "data"
// Takes 3 arguments:
// numGB is the approximate data size to create in GiB (integer usually, but any number should work)
// dbName is the database to use (defaults to a collection called data)
// usePowerOf2 is a boolean to allow you to select the storage strategy

createData = function(numGB, dbName, usePowerOf2) {
    var db1 = db.getSiblingDB(dbName);
    // set powerOf2 per the boolean, but need to handle it differently if it currently exists or not
    // NOTE that second option will turn it off for all new collections

    if(db1.data.findOne()){
        db1.runCommand({ collMod : "data", usePowerOf2Sizes : usePowerOf2 });
    } else {
        db1.adminCommand({ setParameter: 1, newCollectionsUsePowerOf2Sizes: usePowerOf2 });
    };

    // check the shell version, if 2.5+ set legacy mode for unacked writes (for speed)
    var shellVersion = version().split('.').map(Number);
    if ( shellVersion[0] > 2 ) {
	    db1.getMongo().forceWriteMode("legacy");
	} else if (shellVersion[0] == 2) {
		if (shellVersion[1] > 4) {
		db1.getMongo().forceWriteMode("legacy");
		}
	};

    // with the document we are using, 68 iterations of this loop will get you ~1033MiB of data (not uncluding indexes), so use that as a multiplier
    var startTime = new Date();

    for(var j = 0; j < (numGB * 68); j++){
        // going to create a big array of docs, then insert them
        var bigDoc = [];
        for(var i = 0; i < 66400; i++){  // 132800 gets pretty close to the max doc size but takes a bit too long to generate on my machine, leaving gaps, so divide by 2
            var randomNum = Math.random(); // generate a single random number per loop iteration
            var ranDate = new Date(Math.floor(1500000000000 * randomNum));
            // let's construct a random ObjectId based on the number, basically construct a string with the info we need and some randomness
            // first piece is 4 bytes (8 hex digits), need to pad with zeroes for low values (same with random end piece)
            // next pieces per the spec are 6 hex digits for the machine, 4 digits for the PID
            // instead we will insert 10 placeholder characters for expedience
            // then, round things out with 3 bytes of randomness per the spec, and use the increment on the loop to avoid collisions
            var ranString = (Math.floor(randomNum * 1500000000).toString(16)).pad(8, false, 0) + "adacefd123" + ((Math.floor(randomNum * 16710815) + i).toString(16)).pad(6, false, 0);
            // this one would be better, but too slow to generate:
            // var ranString = ((Math.floor(1500000000 * randomNum)).toString(16)).pad(8, false, "0") + db1.version().replace(/\./g, "") + "adacefd" + ((Math.floor(randomNum * 9920329) + i).toString(16)).pad(6, false, "0");
            var ranId = new ObjectId(ranString);
            // To explain the document:
            // _id and ranDate are both based on the same randomly generated date, but ranDate has millis and is a bit easier to parse
            // After that we add an integer, boolean and a small array with a string and a number (array is useful for growth later)
            bigDoc.push({_id : ranId, ranDate : ranDate, ranInt : NumberInt(randomNum * 1000000), ranBool : (randomNum < 0.5 ? true : false), smallArray : [randomNum, randomNum.toString()]});
        };
        db1.data.insert(bigDoc);

        if(j == (numGB * 34)){
            print("Approximately 50% done: " + (j * 66400) + " docs inserted in " + (new Date() - startTime)/1000 + " seconds");
        };

    };
    var timeTaken = ((new Date() - startTime)/1000);
    print("Run complete: " + (numGB * 68 * 66400) + " docs inserted in " + timeTaken + " seconds.  Average insertion rate: " + ((numGB * 136 * 33200)/timeTaken) + " docs per second");
    // clean up the write mode if altered at the top
    if(db1.getMongo().writeMode() == "legacy"){
	    db1.getMongo().forceWriteMode("commands");
    }
};

// Sample runs of the createData script on a standalone mongod, both run on same 8 core Linux host, not IO bound
// Single thread CPU for shell was close to max, as was database lock on mongod - results within margin of error for the versions:

// 2.6.3 - Run complete: 4515200 docs inserted in 148.452 seconds.  Average insertion rate: 30415.218387088084 docs per second
// 2.4.10 - Run complete: 4515200 docs inserted in 146.916 seconds.  Average insertion rate: 30733.20809169866 docs per second

// Next, the reads - we'll do this randomly across the set
// Takes 2 arguments:
// numGB is the approximate data size to create in GiB (integer usually, but any number should work)
// dbName is the database to use (defaults to a collection called data)

preHeatRandomData = function(numGB, dbName) {

// We will brute force this basically, the _id is indexed and we know how it was constructed
// The first 8 hex digits of the pseudo ObjectID we created have a maximum of 16^6 docs, but likely far less
// A bit of experimentation tells me that using all 8 digits is too slow (low hit rate)
// Even 6 digits is still only 256 second ranges and yielded an average of less than 2 docs per range in limited tests
// Hence, we will do a range query using the first 5 digits plus fixed strings to create the start/end of the range
// Thats 16^3 or 4096 secs, so not an unreasonable range to query in general (1GiB set tests yielded ~12 docs per range)
// Every time we do the range query, we will call explain, and then increment the results by the nscanned count
//
// Note: decent chance there will be collisions, so may need to "oversubscribe" the amount of data to be touched

var docHits = 0;
var noHits = 0;
var iterations = 0;   // not really needed other than for stats

var db1 = db.getSiblingDB(dbName);

var startTime = new Date(); // time the loop
while(docHits < (5000000 * numGB)) {
	// the creation of the string is identical to the creation code
    var randomNum = Math.random();
    var ranString = (Math.floor(randomNum * 1500000000).toString(16)).pad(8, false, 0);
    // we just strip the last 3 characters to allow us to create ranges - 3 characters is only 4096 seconds
    ranString = ranString.substring(0, ranString.length - 3)
    var beginId = new ObjectId(ranString + "000adacefd123000000");
    var endId = new ObjectId(ranString + "fffadacefd123ffffff");
    // simple ranged query on _id with an explicit hint and an explain so we exhaust the cursor and get useful stats back
    var result = db1.data.find({_id : {$gte : beginId, $lte : endId}}).hint({_id : 1}).explain();
    if(result.nscanned > 0) {
        docHits += result.nscanned; //increment by number of scanned if not empty
    } else {
        noHits++;  // record the lack of hits
    };
    iterations++; // total iterations
    // warn about low hit rates at each 250k no hit occurrences
	if((noHits % 250000) == 0  && noHits > 0){
        print("Warning: hit rate is poor - just passed " + noHits + " iterations with no hits (current hits doc hits are: " + docHits + " out of " + (5000000 * numGB) + " or " + docHits/(50000 * numGB) + "%).");
	};
};
var endTime = new Date();
// some info on the time taken, hit rate etc.
print(numGB + "GiB of data loaded (" + (numGB * 5000000) + " docs), took " + (endTime - startTime)/1000 + " seconds to complete (average: " + (numGB * 5000000)/((endTime - startTime)/1000) + " docs/sec)")
print(noHits + " queries hit 0 documents (" + (noHits*100)/iterations + "%) and there were " + iterations + " total iterations." );
print("Average number of docs scanned per iteration (hits only): " + (numGB * 5000000)/(iterations - noHits) );
};

// update docs, optionally making them grow (creates free list)

updateRandomData = function(numGB, dbName, growDocs){

// quick test shows that with powerOf2Sizes, need to add 9 ObjectIds to the smallArray to trigger a move
// so growing the docs will take a lot more updates in order to complete the run
// testing for a move is a little clunky until we get better write command stats, so pushing that to its own function for now
var db1 = db.getSiblingDB(dbName);
var updateHits = 0;
var growthOverhead = 0;
var startTime = new Date(); // time the loop
while(updateHits < (5000000 * numGB)){
    // we'll re-use the logic from the finds, create a range to look for a candidate document
    var randomNum = Math.random();
    var ranString = (Math.floor(randomNum * 1500000000).toString(16)).pad(8, false, 0);
    // we just strip the last 3 characters to allow us to create ranges - 3 characters is only 4096 seconds
    // this is looking pretty inefficient at finding data in a 2GB data set for testing, may need to increase the ranges
    ranString = ranString.substring(0, ranString.length - 3)
    var beginId = new ObjectId(ranString + "000adacefd123000000");
    var endId = new ObjectId(ranString + "fffadacefd123ffffff");
	var result = 0;
    // simple find on _id with a hint and next() to get the first doc off the cursor
	// loop until we have a valid result (in case of misses), and we will use the ranInt to not hit docs twice
	while(result == 0){
        result = db1.data.find({_id : {$gte : beginId, $lte : endId}, ranInt : {$lte : 1000000}}).hint({_id : 1}).next();
    }
    if(growDocs){
        growthOverhead += pushUntilMoved(dbName, result._id, false);
        db1.data.update({_id : result._id}, {$inc : {ranInt : 1000000}});
        updateHits++;
    } else {
	    db1.data.update({_id : result._id}, {$inc : {ranInt : 1000000}});
        updateHits++;
	}
}
var endTime = new Date();

if(growDocs){
    print("Updated " + updateHits + " docs in " + (endTime - startTime)/1000 + " seconds (avg: " + (5000000 * numGB)/((endTime - startTime)/1000) + " docs/sec. Growth required an average of " + (growthOverhead/updateHits) + " pushes to the array.");
} else {
    print("Updated " + updateHits + " docs in " + (endTime - startTime)/1000 + " seconds (avg: " + (5000000 * numGB)/((endTime - startTime)/1000) + " docs/sec.");
};

}

// this little function will take an ObjectID, then push new IDs to the smallArray until the document moves on disk
// verbose toggles information about old/new location and number of pushes required (will be more for powerOf2 docs)
// it's needed to provide the move functionality in the update function
pushUntilMoved = function(dbName, docID, verbose){
	var db1 = db.getSiblingDB(dbName);
	var currentLoc = db1.data.find({_id : docID}).showDiskLoc().next().$diskLoc;
	var newLoc = currentLoc;
	var pushes = 0;
	while((currentLoc.file == newLoc.file) && (currentLoc.offset == newLoc.offset)){
		db1.data.update({_id : docID}, {$push : {smallArray : new ObjectId()}});
		newLoc = db1.data.find({_id : docID}).showDiskLoc().next().$diskLoc;
		pushes++;
	}
	if(verbose){
		print("Old location: file: " + currentLoc.file + " offset: " + currentLoc.offset);
		print("New location: file: " + newLoc.file + " offset: " + newLoc.offset);
		print("Pushes required: " + pushes);
    }
	return pushes;
}

// delete docs, create holes and a free list

deleteRandomData = function(numGB, dbName){
	var db1 = db.getSiblingDB(dbName);
	var delHits = 0;

	// this one is actually far more simple in 2.6 with the write results, so writing that first, may not bother with 2.4
 	var startTime = new Date(); // time the loop
	while(delHits < (5000000 * numGB)){
	// we'll re-use the logic from the finds/updates, create a range to look for a candidate document
	    var randomNum = Math.random();
	    var ranString = (Math.floor(randomNum * 1500000000).toString(16)).pad(8, false, 0);
	    ranString = ranString.substring(0, ranString.length - 3)
	    var beginId = new ObjectId(ranString + "000adacefd123000000");
	    var endId = new ObjectId(ranString + "fffadacefd123ffffff");
		var result = db1.data.remove({_id : {$gte : beginId, $lte : endId}}, 1); // just remove one doc at a time
		delHits += result.nRemoved;
    }
    var endTime = new Date();
	print("Removed " + delHits + " docs in " + (endTime - startTime)/1000 + " seconds (avg: " + (5000000 * numGB)/((endTime - startTime)/1000) + " docs/sec.");

}<commit_msg>added optional delay to the create loop<commit_after>// Some functions for inserting quickly (unack'ed writes) (Create)
// Preheating data to get it into memory (Read)
// Changing the data, with/without growth (Update)
// Removing data (Delete)

// First function is used to create a random set of data, the C in CRUD
// Defaults/Assumptions: _id index only, collection always called "data"
// Takes 3 arguments:
// numGB is the approximate data size to create in GiB (integer usually, but any number should work)
// dbName is the database to use (defaults to a collection called data)
// usePowerOf2 is a boolean to allow you to select the storage strategy
// delay is optional - it will introduce a sleep into the loop to slow down the operations, defaults to 0

createData = function(numGB, dbName, usePowerOf2, delay) {
    var db1 = db.getSiblingDB(dbName);
    // set powerOf2 per the boolean, but need to handle it differently if it currently exists or not
    // NOTE that second option will turn it off for all new collections

    if(db1.data.findOne()){
        db1.runCommand({ collMod : "data", usePowerOf2Sizes : usePowerOf2 });
    } else {
        db1.adminCommand({ setParameter: 1, newCollectionsUsePowerOf2Sizes: usePowerOf2 });
    };
    // set the delay as passed in, with the default of 0 as a fallback
    delay = typeof delay !== 'undefined' ? delay : 0;
    // check the shell version, if 2.5+ set legacy mode for unacked writes (for speed)
    var shellVersion = version().split('.').map(Number);
    if ( shellVersion[0] > 2 ) {
	    db1.getMongo().forceWriteMode("legacy");
	} else if (shellVersion[0] == 2) {
		if (shellVersion[1] > 4) {
		db1.getMongo().forceWriteMode("legacy");
		}
	};

    // with the document we are using, 68 iterations of this loop will get you ~1033MiB of data (not uncluding indexes), so use that as a multiplier
    var startTime = new Date();

    for(var j = 0; j < (numGB * 68); j++){
        // going to create a big array of docs, then insert them
        var bigDoc = [];
        for(var i = 0; i < 66400; i++){  // 132800 gets pretty close to the max doc size but takes a bit too long to generate on my machine, leaving gaps, so divide by 2
            var randomNum = Math.random(); // generate a single random number per loop iteration
            var ranDate = new Date(Math.floor(1500000000000 * randomNum));
            // let's construct a random ObjectId based on the number, basically construct a string with the info we need and some randomness
            // first piece is 4 bytes (8 hex digits), need to pad with zeroes for low values (same with random end piece)
            // next pieces per the spec are 6 hex digits for the machine, 4 digits for the PID
            // instead we will insert 10 placeholder characters for expedience
            // then, round things out with 3 bytes of randomness per the spec, and use the increment on the loop to avoid collisions
            var ranString = (Math.floor(randomNum * 1500000000).toString(16)).pad(8, false, 0) + "adacefd123" + ((Math.floor(randomNum * 16710815) + i).toString(16)).pad(6, false, 0);
            // this one would be better, but too slow to generate:
            // var ranString = ((Math.floor(1500000000 * randomNum)).toString(16)).pad(8, false, "0") + db1.version().replace(/\./g, "") + "adacefd" + ((Math.floor(randomNum * 9920329) + i).toString(16)).pad(6, false, "0");
            var ranId = new ObjectId(ranString);
            // To explain the document:
            // _id and ranDate are both based on the same randomly generated date, but ranDate has millis and is a bit easier to parse
            // After that we add an integer, boolean and a small array with a string and a number (array is useful for growth later)
            bigDoc.push({_id : ranId, ranDate : ranDate, ranInt : NumberInt(randomNum * 1000000), ranBool : (randomNum < 0.5 ? true : false), smallArray : [randomNum, randomNum.toString()]});
            // if there is a non-default delay specified, use it
            if(delay > 0){
                sleep(delay);
            }
        };
        db1.data.insert(bigDoc);

        if(j == (numGB * 34)){
            print("Approximately 50% done: " + (j * 66400) + " docs inserted in " + (new Date() - startTime)/1000 + " seconds");
        };

    };
    var timeTaken = ((new Date() - startTime)/1000);
    print("Run complete: " + (numGB * 68 * 66400) + " docs inserted in " + timeTaken + " seconds.  Average insertion rate: " + ((numGB * 136 * 33200)/timeTaken) + " docs per second");
    // clean up the write mode if altered at the top
    if(db1.getMongo().writeMode() == "legacy"){
	    db1.getMongo().forceWriteMode("commands");
    }
};

// Sample runs of the createData script on a standalone mongod, both run on same 8 core Linux host, not IO bound
// Single thread CPU for shell was close to max, as was database lock on mongod - results within margin of error for the versions:

// 2.6.3 - Run complete: 4515200 docs inserted in 148.452 seconds.  Average insertion rate: 30415.218387088084 docs per second
// 2.4.10 - Run complete: 4515200 docs inserted in 146.916 seconds.  Average insertion rate: 30733.20809169866 docs per second

// Next, the reads - we'll do this randomly across the set
// Takes 2 arguments:
// numGB is the approximate data size to create in GiB (integer usually, but any number should work)
// dbName is the database to use (defaults to a collection called data)

preHeatRandomData = function(numGB, dbName) {

// We will brute force this basically, the _id is indexed and we know how it was constructed
// The first 8 hex digits of the pseudo ObjectID we created have a maximum of 16^6 docs, but likely far less
// A bit of experimentation tells me that using all 8 digits is too slow (low hit rate)
// Even 6 digits is still only 256 second ranges and yielded an average of less than 2 docs per range in limited tests
// Hence, we will do a range query using the first 5 digits plus fixed strings to create the start/end of the range
// Thats 16^3 or 4096 secs, so not an unreasonable range to query in general (1GiB set tests yielded ~12 docs per range)
// Every time we do the range query, we will call explain, and then increment the results by the nscanned count
//
// Note: decent chance there will be collisions, so may need to "oversubscribe" the amount of data to be touched

var docHits = 0;
var noHits = 0;
var iterations = 0;   // not really needed other than for stats

var db1 = db.getSiblingDB(dbName);

var startTime = new Date(); // time the loop
while(docHits < (5000000 * numGB)) {
	// the creation of the string is identical to the creation code
    var randomNum = Math.random();
    var ranString = (Math.floor(randomNum * 1500000000).toString(16)).pad(8, false, 0);
    // we just strip the last 3 characters to allow us to create ranges - 3 characters is only 4096 seconds
    ranString = ranString.substring(0, ranString.length - 3)
    var beginId = new ObjectId(ranString + "000adacefd123000000");
    var endId = new ObjectId(ranString + "fffadacefd123ffffff");
    // simple ranged query on _id with an explicit hint and an explain so we exhaust the cursor and get useful stats back
    var result = db1.data.find({_id : {$gte : beginId, $lte : endId}}).hint({_id : 1}).explain();
    if(result.nscanned > 0) {
        docHits += result.nscanned; //increment by number of scanned if not empty
    } else {
        noHits++;  // record the lack of hits
    };
    iterations++; // total iterations
    // warn about low hit rates at each 250k no hit occurrences
	if((noHits % 250000) == 0  && noHits > 0){
        print("Warning: hit rate is poor - just passed " + noHits + " iterations with no hits (current hits doc hits are: " + docHits + " out of " + (5000000 * numGB) + " or " + docHits/(50000 * numGB) + "%).");
	};
};
var endTime = new Date();
// some info on the time taken, hit rate etc.
print(numGB + "GiB of data loaded (" + (numGB * 5000000) + " docs), took " + (endTime - startTime)/1000 + " seconds to complete (average: " + (numGB * 5000000)/((endTime - startTime)/1000) + " docs/sec)")
print(noHits + " queries hit 0 documents (" + (noHits*100)/iterations + "%) and there were " + iterations + " total iterations." );
print("Average number of docs scanned per iteration (hits only): " + (numGB * 5000000)/(iterations - noHits) );
};

// update docs, optionally making them grow (creates free list)

updateRandomData = function(numGB, dbName, growDocs){

// quick test shows that with powerOf2Sizes, need to add 9 ObjectIds to the smallArray to trigger a move
// so growing the docs will take a lot more updates in order to complete the run
// testing for a move is a little clunky until we get better write command stats, so pushing that to its own function for now
var db1 = db.getSiblingDB(dbName);
var updateHits = 0;
var growthOverhead = 0;
var startTime = new Date(); // time the loop
while(updateHits < (5000000 * numGB)){
    // we'll re-use the logic from the finds, create a range to look for a candidate document
    var randomNum = Math.random();
    var ranString = (Math.floor(randomNum * 1500000000).toString(16)).pad(8, false, 0);
    // we just strip the last 3 characters to allow us to create ranges - 3 characters is only 4096 seconds
    // this is looking pretty inefficient at finding data in a 2GB data set for testing, may need to increase the ranges
    ranString = ranString.substring(0, ranString.length - 3)
    var beginId = new ObjectId(ranString + "000adacefd123000000");
    var endId = new ObjectId(ranString + "fffadacefd123ffffff");
	var result = 0;
    // simple find on _id with a hint and next() to get the first doc off the cursor
	// loop until we have a valid result (in case of misses), and we will use the ranInt to not hit docs twice
	while(result == 0){
        result = db1.data.find({_id : {$gte : beginId, $lte : endId}, ranInt : {$lte : 1000000}}).hint({_id : 1}).next();
    }
    if(growDocs){
        growthOverhead += pushUntilMoved(dbName, result._id, false);
        db1.data.update({_id : result._id}, {$inc : {ranInt : 1000000}});
        updateHits++;
    } else {
	    db1.data.update({_id : result._id}, {$inc : {ranInt : 1000000}});
        updateHits++;
	}
}
var endTime = new Date();

if(growDocs){
    print("Updated " + updateHits + " docs in " + (endTime - startTime)/1000 + " seconds (avg: " + (5000000 * numGB)/((endTime - startTime)/1000) + " docs/sec. Growth required an average of " + (growthOverhead/updateHits) + " pushes to the array.");
} else {
    print("Updated " + updateHits + " docs in " + (endTime - startTime)/1000 + " seconds (avg: " + (5000000 * numGB)/((endTime - startTime)/1000) + " docs/sec.");
};

}

// this little function will take an ObjectID, then push new IDs to the smallArray until the document moves on disk
// verbose toggles information about old/new location and number of pushes required (will be more for powerOf2 docs)
// it's needed to provide the move functionality in the update function
pushUntilMoved = function(dbName, docID, verbose){
	var db1 = db.getSiblingDB(dbName);
	var currentLoc = db1.data.find({_id : docID}).showDiskLoc().next().$diskLoc;
	var newLoc = currentLoc;
	var pushes = 0;
	while((currentLoc.file == newLoc.file) && (currentLoc.offset == newLoc.offset)){
		db1.data.update({_id : docID}, {$push : {smallArray : new ObjectId()}});
		newLoc = db1.data.find({_id : docID}).showDiskLoc().next().$diskLoc;
		pushes++;
	}
	if(verbose){
		print("Old location: file: " + currentLoc.file + " offset: " + currentLoc.offset);
		print("New location: file: " + newLoc.file + " offset: " + newLoc.offset);
		print("Pushes required: " + pushes);
    }
	return pushes;
}

// delete docs, create holes and a free list

deleteRandomData = function(numGB, dbName){
	var db1 = db.getSiblingDB(dbName);
	var delHits = 0;

	// this one is actually far more simple in 2.6 with the write results, so writing that first, may not bother with 2.4
 	var startTime = new Date(); // time the loop
	while(delHits < (5000000 * numGB)){
	// we'll re-use the logic from the finds/updates, create a range to look for a candidate document
	    var randomNum = Math.random();
	    var ranString = (Math.floor(randomNum * 1500000000).toString(16)).pad(8, false, 0);
	    ranString = ranString.substring(0, ranString.length - 3)
	    var beginId = new ObjectId(ranString + "000adacefd123000000");
	    var endId = new ObjectId(ranString + "fffadacefd123ffffff");
		var result = db1.data.remove({_id : {$gte : beginId, $lte : endId}}, 1); // just remove one doc at a time
		delHits += result.nRemoved;
    }
    var endTime = new Date();
	print("Removed " + delHits + " docs in " + (endTime - startTime)/1000 + " seconds (avg: " + (5000000 * numGB)/((endTime - startTime)/1000) + " docs/sec.");

}
<|endoftext|>