Browse Source

EAGLESIX-2715: test cases work

Jake Delaney 11 years ago
parent
commit
321738ca12

+ 25 - 0
lib/pipeline/expressions/Helpers.js

@@ -0,0 +1,25 @@
+module.exports = {
+	//Returns an object containing unique values. All keys are the same as the corresponding value.
+	arrayToSet : function arrayToSet(array){
+
+		var set = {};
+
+		// This ensures no duplicates.
+		array.forEach(function (element) {
+			var elementString = JSON.stringify(element);
+			set[elementString] = element;
+		});
+
+		return set;
+	},
+
+	setToArray: function setToArray(set){
+		var array = [];
+
+		Object.keys(set).forEach(function (key) {
+			array.push(set[key]);
+		});
+
+		return array;
+	}
+}

+ 20 - 17
lib/pipeline/expressions/SetUnionExpression.js

@@ -10,12 +10,14 @@
  **/
  **/
 
 
 var SetUnionExpression = module.exports = function SetUnionExpression() {
 var SetUnionExpression = module.exports = function SetUnionExpression() {
+	if(arguments.length != 0) throw new Error("SetUnionExpression constructor takes no args");
 	base.call(this);
 	base.call(this);
 }, klass = SetUnionExpression, base = require("./NaryBaseExpressionT")(SetUnionExpression), proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}});
 }, klass = SetUnionExpression, base = require("./NaryBaseExpressionT")(SetUnionExpression), proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}});
 
 
 // DEPENDENCIES
 // DEPENDENCIES
 var Value = require("../Value"),
 var Value = require("../Value"),
-	Expression = require("./Expression");
+	Expression = require("./Expression"),
+	Helpers = require("./Helpers");
 
 
 // PROTOTYPE MEMBERS
 // PROTOTYPE MEMBERS
 proto.getOpName = function getOpName() {
 proto.getOpName = function getOpName() {
@@ -23,28 +25,29 @@ proto.getOpName = function getOpName() {
 };
 };
 
 
 /**
 /**
- * Takes 2 objects. Returns the union of the two objects.
+ * Takes arrays. Returns the union of the arrays (arrays treated as sets, so duplicates are ignored).
  * @method evaluateInternal
  * @method evaluateInternal
  **/
  **/
 proto.evaluateInternal = function evaluateInternal(vars) {
 proto.evaluateInternal = function evaluateInternal(vars) {
 
 
-	var unionSet = {};
-
-	var object1 = this.operands[0].evaluateInternal(vars),
-		object2 = this.operands[1].evaluateInternal(vars);
-
-	//Deviation from Mongo. We are using objects for this, while they use arrays. 
-	if (typeof object1 != object) throw new Error("All operands of " + this.getOpName() + "must be objects. First argument is of type: " + typeof object1);
-	if (typeof object2 != object) throw new Error("All operands of " + this.getOpName() + "must be objects. Second argument is of type: " + typeof object2);
-
-	for (var attrname1 in object1) {
-		unionSet[attrname1] = object1[attrname1];
-	}
-	for (var attrname2 in object2) {
-		unionSet[attrname2] = object2[attrname2];
+	var unionSet = {}, 
+		n = this.operands.length;
+
+	for (var i = 0; i < n; i++){
+		var newEntries = this.operands[i].evaluateInternal(vars);
+		if (newEntries === null || newEntries === undefined){
+			return null;
+		}
+		if (!(newEntries instanceof Array)) throw new Error("Uassert 17043: All operands of " + this.getOpName() + "must be arrays. One argument is of type: " + typeof newEntries)
+		
+		var len = newEntries.length;
+		for (var j = 0; j < len; j++){
+			unionSet[newEntries[j]] = newEntries[j];
+		}
 	}
 	}
+	var result = Helpers.setToArray(unionSet);
+	return Value.consume(result);
 
 
-	return unionSet;
 };
 };
 
 
 /** Register Expression */
 /** Register Expression */

+ 120 - 108
test/lib/pipeline/expressions/SetUnionExpression.js

@@ -1,119 +1,131 @@
 "use strict";
 "use strict";
 var assert = require("assert"),
 var assert = require("assert"),
-		SetUnionExpression = require("../../../../lib/pipeline/expressions/SetUnionExpression"),
-		Expression = require("../../../../lib/pipeline/expressions/Expression");
-
+	VariablesIdGenerator = require("../../../../lib/pipeline/expressions/VariablesIdGenerator"),
+	VariablesParseState = require("../../../../lib/pipeline/expressions/VariablesParseState"),
+	SetUnionExpression = require("../../../../lib/pipeline/expressions/SetUnionExpression"),
+	Expression = require("../../../../lib/pipeline/expressions/Expression");
+
+function errMsg(expr, args, tree, expected, result) {
+	return "for expression " + expr +
+		" with argument " + args +
+		" full tree: " + JSON.stringify(tree) +
+		" expected: " + expected +
+		" result: " + result;
+}
 
 
 module.exports = {
 module.exports = {
 
 
-		"SetUnionExpression": {
-
-				"constructor()": {
-
-						"should throw Error when constructing without args": function testConstructor() {
-								assert.throws(function() {
-										new SetUnionExpression();
-								});
-						}
-
-				},
-
-				"#getOpName()": {
-
-						"should return the correct op name; $setUnion": function testOpName() {
-								assert.equal(new SetUnionExpression([1, 2, 3], [4, 5, 6]).getOpName(), "$setUnion");
-						}
-
-				},
-
-				"#evaluateInternal()": {
-
-						"Should fail if array1 is not an array": function testArg1() {
-								var array1 = "not an array",
-										array2 = [6, 7, 8, 9];
-								assert.throws(function() {
-										Expression.parseOperand({
-												$setUnion: ["$array1", "$array2"]
-										}).evaluateInternal({
-												array1: array1,
-												array2: array2
-										});
-								});
-						},
-
-						"Should fail if array2 is not an array": function testArg2() {
-								var array1 = [1, 2, 3, 4],
-										array2 = "not an array";
-								assert.throws(function() {
-										Expression.parseOperand({
-												$setUnion: ["$array1", "$array2"]
-										}).evaluateInternal({
-												array1: array1,
-												array2: array2
-										});
-								});
-						},
-
-						"Should fail if both are not an array": function testArg1andArg2() {
-								var array1 = "not an array",
-										array2 = "not an array";
-								assert.throws(function() {
-										Expression.parseOperand({
-												$setUnion: ["$array1", "$array2"]
-										}).evaluateInternal({
-												array1: array1,
-												array2: array2
-										});
-								});
-						},
-
-						"Should pass and return a unioned set1": function testBasicAssignment() {
-								var array1 = {
-										"a": "3",
-										"c": "4"
-								},
-										array2 = {
-												"a": "3",
-												"b": "3"
-										};
-								assert.strictEqual(Expression.parseOperand({
-										$setUnion: ["$array1", "$array2"]
-								}).evaluateInternal({
-										array1: array1,
-										array2: array2
-								}), {
-										"a": "3",
-										"c": "4",
-										"b": "3"
-								});
-						},
-
-						"Should pass and return a unioned set": function testBasicAssignment() {
-								var array1 = [1, 2, 3, 4, 5],
-										array2 = [2, 3, 6, 7, 8];
-								assert.strictEqual(Expression.parseOperand({
-										$setUnion: ["$array1", "$array2"]
-								}).evaluateInternal({
-										array1: array1,
-										array2: array2
-								}), [1, 2, 3, 4, 5, 6, 7, 8]);
-						},
-
-						"Should pass and return unioned set": function testBasicAssignment() {
-								var array1 = [1, 2, 3, 4, 5],
-										array2 = [7, 8, 9];
-								assert.strictEqual(Expression.parseOperand({
-										$setUnion: ["$array1", "$array2"]
-								}).evaluateInternal({
-										array1: array1,
-										array2: array2
-								}), [1, 2, 3, 4, 5, 7, 8, 9]);
-						},
-
-				}
+	"SetUnionExpression": {
+
+		"constructor()": {
+
+			"should not throw Error when constructing without args": function testConstructor() {
+				assert.doesNotThrow(function() {
+						new SetUnionExpression();
+				});
+			},
+
+			"should throw Error when constructing with args": function testConstructor() {
+				assert.throws(function() {
+						new SetUnionExpression("someArg");
+				});
+			}
+
+		},
+
+		"#getOpName()": {
+
+			"should return the correct op name; $setUnion": function testOpName() {
+				assert.equal(new SetUnionExpression().getOpName(), "$setUnion");
+			}
+
+		},
+
+		"#evaluateInternal()": {
+
+			"Should fail if array1 is not an array": function testArg1() {
+				var array1 = "not an array",
+					array2 = [6, 7, 8, 9],
+					input = [array1,array2],
+					idGenerator = new VariablesIdGenerator(),
+					vps = new VariablesParseState(idGenerator),
+					expr = Expression.parseExpression("$setUnion", input, vps);
+				assert.throws(function () {
+					expr.evaluate({});
+				});
+			},
+
+			"Should fail if array2 is not an array": function testArg2() {
+				var array1 = [1, 2, 3, 4],
+					array2 = "not an array",
+					input = [array1,array2],
+					idGenerator = new VariablesIdGenerator(),
+					vps = new VariablesParseState(idGenerator),
+					expr = Expression.parseExpression("$setUnion", input, vps);
+				assert.throws(function () {
+					expr.evaluate({});
+				});
+			},
+
+			"Should fail if both are not an array": function testArg1andArg2() {
+				var array1 = "not an array",
+					array2 = "not an array",
+					input = [array1,array2],
+					idGenerator = new VariablesIdGenerator(),
+					vps = new VariablesParseState(idGenerator),
+					expr = Expression.parseExpression("$setUnion", input, vps);
+				assert.throws(function () {
+					expr.evaluate({});
+				});
+			},
+
+			"Should pass and return [1, 2, 3, 4, 5, 8, 9]": function testBasicAssignment(){
+				var array1 = [1, 2, 3, 9, 8],
+					array2 = [1, 2, 3, 4, 5],
+					input = [array1,array2],
+					idGenerator = new VariablesIdGenerator(),
+					vps = new VariablesParseState(idGenerator),
+					expr = Expression.parseExpression("$setUnion", input, vps),
+					result = expr.evaluate({}),
+					expected = [1, 2, 3, 4, 5, 8, 9],
+					msg = errMsg("$setUnion", input, expr.serialize(false), expected, result);
+				assert.deepEqual(result, expected, msg);
+			},
+
+			"Should pass and return [1, 2, 3, 4, 5, 7]": function testBasicAssignment() {
+				var array1 = [2, 4],
+					array2 = [1, 2, 3, 4, 5],
+					array3 = [7, 2, 1],
+					array4 = [],
+					input = [array1,array2,array3, array4],
+					idGenerator = new VariablesIdGenerator(),
+					vps = new VariablesParseState(idGenerator),
+					expr = Expression.parseExpression("$setUnion", input, vps),
+					result = expr.evaluate({}),
+					expected = [1, 2, 3, 4, 5, 7],
+					msg = errMsg("$setUnion", input, expr.serialize(false), expected, result);
+				assert.deepEqual(result, expected, msg);
+			},
+
+			"Should pass and return [1, 2, 7]": function testBasicAssignment() {
+				var array1 = [],
+					array2 = [],
+					array3 = [7, 2, 1],
+					array4 = [],
+					input = [array1,array2,array3, array4],
+					idGenerator = new VariablesIdGenerator(),
+					vps = new VariablesParseState(idGenerator),
+					expr = Expression.parseExpression("$setUnion", input, vps),
+					result = expr.evaluate({}),
+					expected = [1, 2, 7],
+					msg = errMsg("$setUnion", input, expr.serialize(false), expected, result);
+				assert.deepEqual(result, expected, msg);
+			}
 
 
 		}
 		}
 
 
+	}
+
 };
 };
 
 
 if (!module.parent)(new(require("mocha"))()).ui("exports").reporter("spec").addFile(__filename).run(process.exit);
 if (!module.parent)(new(require("mocha"))()).ui("exports").reporter("spec").addFile(__filename).run(process.exit);