Browse Source

Merge pull request #19 from RiveraGroup/feature/mongo_2.6.5_accumulators_Push

Feature/mongo 2.6.5 accumulators Push
Kyle P Davis 11 years ago
parent
commit
754e71f83d

+ 20 - 25
lib/pipeline/accumulators/PushAccumulator.js

@@ -8,44 +8,39 @@
  * @constructor
  **/
 var PushAccumulator = module.exports = function PushAccumulator(){
+	if (arguments.length !== 0) throw new Error("zero args expected");
 	this.values = [];
 	base.call(this);
 }, klass = PushAccumulator, Accumulator = require("./Accumulator"), base = Accumulator, proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}});
 
-// NOTE: Skipping the create function, using the constructor instead
-
-// MEMBER FUNCTIONS
-proto.getValue = function getValue(toBeMerged){
-	return this.values;
-};
-
-proto.getOpName = function getOpName(){
-	return "$push";
-};
-
-proto.getFactory = function getFactory(){
-	return klass;	// using the ctor rather than a separate .create() method
-};
-
-
 proto.processInternal = function processInternal(input, merging) {
 	if (!merging) {
 		if (input !== undefined) {
 			this.values.push(input);
-			//_memUsageBytes += input.getApproximateSize();
 		}
-	}
-	else {
+	} else {
 		// If we're merging, we need to take apart the arrays we
 		// receive and put their elements into the array we are collecting.
 		// If we didn't, then we'd get an array of arrays, with one array
 		// from each merge source.
-		if (!(input instanceof Array)) throw new Error("input is not an Array during merge in PushAccumulator:35");
-
-		this.values = this.values.concat(input);
+		if (!Array.isArray(input)) throw new Error("Assertion failure");
 
-		//for (size_t i=0; i < vec.size(); i++) {
-			//_memUsageBytes += vec[i].getApproximateSize();
-		//}
+		Array.prototype.push.apply(this.values, input);
 	}
 };
+
+proto.getValue = function getValue(toBeMerged) {
+	return this.values;
+};
+
+proto.reset = function reset() {
+	this.values = [];
+};
+
+klass.create = function create() {
+	return new PushAccumulator();
+};
+
+proto.getOpName = function getOpName() {
+	return "$push";
+};

+ 97 - 77
test/lib/pipeline/accumulators/PushAccumulator.js

@@ -2,99 +2,119 @@
 var assert = require("assert"),
 	PushAccumulator = require("../../../../lib/pipeline/accumulators/PushAccumulator");
 
+// Mocha one-liner to make these tests self-hosted
+if(!module.parent)return(require.cache[__filename]=null,(new(require("mocha"))({ui:"exports",reporter:"spec",grep:process.env.TEST_GREP})).addFile(__filename).run(process.exit));
 
-function createAccumulator(){
-	return new PushAccumulator();
-}
 
-module.exports = {
+exports.PushAccumulator = {
 
-	"PushAccumulator": {
+	".constructor()": {
 
-		"constructor()": {
+		"should create instance of accumulator": function() {
+			assert(new PushAccumulator() instanceof PushAccumulator);
+		},
+
+		"should throw error if called with args": function() {
+			assert.throws(function() {
+				new PushAccumulator(123);
+			});
+		},
+
+	},
+
+	".create()": {
+
+		"should return an instance of the accumulator": function() {
+			assert(PushAccumulator.create() instanceof PushAccumulator);
+		},
+
+	},
+
+	"#process()": {
+
+		"should return empty array if no inputs evaluated": function() {
+			var acc = PushAccumulator.create();
+			assert.deepEqual(acc.getValue(), []);
+		},
+
+		"should return array of one value for one input": function() {
+			var acc = PushAccumulator.create();
+			acc.process(1);
+			assert.deepEqual(acc.getValue(), [1]);
+		},
+
+		"should return array of two values for two inputs": function() {
+			var acc = PushAccumulator.create();
+			acc.process(1);
+			acc.process(2);
+			assert.deepEqual(acc.getValue(), [1,2]);
+		},
+
+		"should return array of two values for two inputs (including null)": function() {
+			var acc = PushAccumulator.create();
+			acc.process(1);
+			acc.process(null);
+			assert.deepEqual(acc.getValue(), [1, null]);
+		},
+
+		"should return array of one value for two inputs if one is undefined": function() {
+			var acc = PushAccumulator.create();
+			acc.process(1);
+			acc.process(undefined);
+			assert.deepEqual(acc.getValue(), [1]);
+		},
+
+		"should return array of two values from two separate mergeable inputs": function() {
+			var acc = PushAccumulator.create();
+			acc.process([1], true);
+			acc.process([0], true);
+			assert.deepEqual(acc.getValue(), [1, 0]);
+		},
+
+		"should throw error if merging non-array": function() {
+			var acc = PushAccumulator.create();
+			assert.throws(function() {
+				acc.process(0, true);
+			});
+			assert.throws(function() {
+				acc.process("foo", true);
+			});
+		},
+
+	},
 
-			"should not throw Error when constructing without args": function testConstructor(){
-				assert.doesNotThrow(function(){
-					new PushAccumulator();
-				});
-			}
+	"#getValue()": {
 
+		"should get value the same for shard and router": function() {
+			var acc = PushAccumulator.create();
+			assert.strictEqual(acc.getValue(false), acc.getValue(true));
+			acc.process(123);
+			assert.strictEqual(acc.getValue(false), acc.getValue(true));
 		},
 
-		"#getOpName()": {
+	},
 
-			"should return the correct op name; $push": function testOpName(){
-				assert.strictEqual(new PushAccumulator().getOpName(), "$push");
-			}
+	"#reset()": {
 
+		"should reset to empty array": function() {
+			var acc = PushAccumulator.create();
+			assert.deepEqual(acc.getValue(), []);
+			acc.process(123);
+			assert.notDeepEqual(acc.getValue(), []);
+			acc.reset();
+			assert.deepEqual(acc.getValue(), []);
+			assert.deepEqual(acc.getValue(true), []);
 		},
 
-		"#getFactory()": {
+	},
 
-			"should return the constructor for this class": function factoryIsConstructor(){
-				assert.strictEqual(new PushAccumulator().getFactory(), PushAccumulator);
-			}
+	"#getOpName()": {
 
+		"should return the correct op name; $push": function(){
+			assert.strictEqual(new PushAccumulator().getOpName(), "$push");
 		},
 
-		"#processInternal()": {
-
-			"should processInternal no documents and return []": function testprocessInternal_None(){
-				var accumulator = createAccumulator();
-				assert.deepEqual(accumulator.getValue(), []);
-			},
-
-			"should processInternal a 1 and return [1]": function testprocessInternal_One(){
-				var accumulator = createAccumulator();
-				accumulator.processInternal(1);
-				assert.deepEqual(accumulator.getValue(), [1]);
-			},
-
-			"should processInternal a 1 and a 2 and return [1,2]": function testprocessInternal_OneTwo(){
-				var accumulator = createAccumulator();
-				accumulator.processInternal(1);
-				accumulator.processInternal(2);
-				assert.deepEqual(accumulator.getValue(), [1,2]);
-			},
-
-			"should processInternal a 1 and a null and return [1,null]": function testprocessInternal_OneNull(){
-				var accumulator = createAccumulator();
-				accumulator.processInternal(1);
-				accumulator.processInternal(null);
-				assert.deepEqual(accumulator.getValue(), [1, null]);
-			},
-
-			"should processInternal a 1 and an undefined and return [1]": function testprocessInternal_OneUndefined(){
-				var accumulator = createAccumulator();
-				accumulator.processInternal(1);
-				accumulator.processInternal(undefined);
-				assert.deepEqual(accumulator.getValue(), [1]);
-			},
-
-			"should processInternal a 1 and a 0 and return [1,0]": function testprocessInternal_OneZero(){
-				var accumulator = createAccumulator();
-				accumulator.processInternal(1);
-				accumulator.processInternal(0);
-				assert.deepEqual(accumulator.getValue(), [1, 0]);
-			},
-
-			"should processInternal a 1 and a [0] and return [1,0]": function testprocessInternal_OneArrayZeroMerging(){
-				var accumulator = createAccumulator();
-				accumulator.processInternal(1);
-				accumulator.processInternal([0], true);
-				assert.deepEqual(accumulator.getValue(), [1, 0]);
-			},
-
-			"should processInternal a 1 and a 0 and throw an error if merging": function testprocessInternal_OneZeroMerging(){
-				var accumulator = createAccumulator();
-				accumulator.processInternal(1);
-				assert.throws(function() {
-					accumulator.processInternal(0, true);
-				});
-			}
-		}
-
-	}
+	},
 
 };