Browse Source

Merge branch 'feature/mongo_2.6.5_expressions' into feature/mongo_2.6.5_expressions_ifNull_Cond_Not

Tony Ennis 11 years ago
parent
commit
92f6f0a998

+ 30 - 34
lib/pipeline/expressions/ConstantExpression.js

@@ -1,64 +1,60 @@
 "use strict";
 
+var Value = require("../Value"),
+    Expression = require("./Expression");
+
 /**
  * Internal expression for constant values
  * @class ConstantExpression
  * @namespace mungedb-aggregate.pipeline.expressions
  * @module mungedb-aggregate
  * @constructor
- **/
+ */
 var ConstantExpression = module.exports = function ConstantExpression(value){
-    if (arguments.length !== 1) throw new Error("args expected: value");
-    this.value = value; //TODO: actually make read-only in terms of JS?
+    if (arguments.length !== 1) throw new Error(klass.name + ": args expected: value");
+    this.value = value;
     base.call(this);
-}, klass = ConstantExpression, base = require("./Expression"), proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}});
-
-
-// DEPENDENCIES
-var Value = require("../Value"),
-    Expression = require("./Expression");
+}, klass = ConstantExpression, base = require("./FixedArityExpressionT")(klass,1), proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}});
 
-// PROTOTYPE MEMBERS
-proto.getOpName = function getOpName(){
-	return "$const";
+klass.parse = function parse(exprElement, vps) {
+	return new ConstantExpression(exprElement);
 };
 
-/**
- * Get the constant value represented by this Expression.
- * @method getValue
- * @returns the value
- **/
-proto.getValue = function getValue(){   //TODO: convert this to an instance field rather than a property
-    return this.value;
+klass.create = function create(value) {
+	var constExpr = new ConstantExpression(value);
+	return constExpr;
 };
 
-proto.addDependencies = function addDependencies(deps, path) {
+proto.optimize = function optimize() {
 	// nothing to do
+	return this;
 };
 
-klass.parse = function parse(expr, vps){
-    return new ConstantExpression(expr);
+proto.addDependencies = function addDependencies(deps, path) {
+	// nothing to do
 };
 
 /**
  * Get the constant value represented by this Expression.
  * @method evaluate
- **/
-proto.evaluateInternal = function evaluateInternal(vars){
+ */
+proto.evaluateInternal = function evaluateInternal(vars) {
 	return this.value;
 };
 
-proto.optimize = function optimize() {
-	return this; // nothing to do
-};
+/// Helper function to easily wrap constants with $const.
+function serializeConstant(val) {
+    return {$const: val};
+}
 
-proto.serialize = function(rawValue){
-	return rawValue ? {$const: this.value} : this.value;
+proto.serialize = function serialize(explain) {
+	return serializeConstant(this.value);
 };
 
-//TODO: proto.addToBsonObj   --- may be required for $project to work -- my hope is that we can implement toJSON methods all around and use that instead
-//TODO: proto.addToBsonArray
+Expression.registerExpression("$const", klass.parse);
+
+Expression.registerExpression("$literal", klass.parse); // alias
 
-/** Register Expression */
-Expression.registerExpression("$const",klass.parse(ConstantExpression));
-Expression.registerExpression("$literal", klass.parse(ConstantExpression)); // alias
+proto.getOpName = function getOpName() {
+	return "$const";
+};

+ 0 - 55
test/lib/pipeline/expressions/ConstantExpression.js

@@ -1,55 +0,0 @@
-"use strict";
-var assert = require("assert"),
-	ConstantExpression = require("../../../../lib/pipeline/expressions/ConstantExpression");
-
-
-module.exports = {
-
-	"ConstantExpression": {
-
-		"constructor() / #evaluate": {
-
-			"should be able to construct from a value type": function testCreate(){
-				assert.strictEqual(new ConstantExpression(5).evaluateInternal({}), 5);
-			}
-
-			//TODO: CreateFromBsonElement ? ?? ???
-
-		},
-
-// TODO: the constructor() tests this so not really needed here
-//		"#evaluate()": {
-//		},
-
-		"#optimize()": {
-
-			"should not optimize anything": function testOptimize(){
-				var expr = new ConstantExpression(5);
-				assert.strictEqual(expr, expr.optimize());
-			}
-
-		},
-
-		"#addDependencies()": {
-
-			"should return nothing": function testDependencies(){
-				assert.strictEqual(new ConstantExpression(5).addDependencies(), undefined);
-			}
-
-		},
-
-		"#toJSON()": {
-
-			"should output proper JSON": function testJson(){
-				var expr = new ConstantExpression(5);
-				assert.strictEqual(expr.serialize(), 5);
-				assert.deepEqual(expr.serialize(true), {$const:5});
-			}
-
-		}
-
-	}
-
-};
-
-if (!module.parent)(new(require("mocha"))()).ui("exports").reporter("spec").addFile(__filename).run(process.exit);

+ 107 - 0
test/lib/pipeline/expressions/ConstantExpression_test.js

@@ -0,0 +1,107 @@
+"use strict";
+var assert = require("assert"),
+	ConstantExpression = require("../../../../lib/pipeline/expressions/ConstantExpression"),
+	VariablesIdGenerator = require("../../../../lib/pipeline/expressions/VariablesIdGenerator"),
+	VariablesParseState = require("../../../../lib/pipeline/expressions/VariablesParseState");
+
+// 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));
+
+exports.ConstantExpression = {
+
+	".constructor()": {
+
+		"should accept one argument": function() {
+			new ConstantExpression(5);
+		},
+
+		"should not accept 0 arguments": function() {
+			assert.throws(function() {
+				 new ConstantExpression();
+			});
+		},
+
+		"should not accept 2 arguments": function() {
+			assert.throws(function() {
+				new ConstantExpression(1, 2);
+			});
+		},
+
+	},
+
+	".parse()": {
+
+		"should create an expression from a json element": function testCreateFromBsonElement() {
+			var idGenerator = new VariablesIdGenerator(),
+				vps = new VariablesParseState(idGenerator),
+				expression = ConstantExpression.parse("foo", vps);
+			assert.deepEqual("foo", expression.evaluate({}));
+		},
+
+	},
+
+	".create()": {
+
+		"should create an expression": function testCreate() {
+			assert(ConstantExpression.create() instanceof ConstantExpression);
+		},
+
+		//SKIPPED: testCreateFronBsonElement
+
+	},
+
+	"#optimize()": {
+
+		"should not optimize anything": function testOptimize() {
+			var expr = new ConstantExpression(5);
+			assert.strictEqual(expr, expr.optimize());
+		},
+
+	},
+
+	"#addDependencies()": {
+
+		"should return nothing": function testDependencies() {
+			var expr = ConstantExpression.create(5),
+				deps = {}; //TODO: new DepsTracker
+			expr.addDependencies(deps);
+			assert.strictEqual(deps.fields.length, 0);
+			assert.strictEqual(deps.needWholeDocument, false);
+			assert.strictEqual(deps.needTextScore, false);
+		},
+
+	},
+
+	//TODO: AddToBsonObj
+
+	//TODO: AddToBsonArray
+
+	"#evaluate()": {
+
+		"should do what comes natural with an int": function() {
+			var c = 567;
+			var expr = new ConstantExpression(c);
+			assert.deepEqual(expr.evaluate(), c);
+		},
+
+		"should do what comes natural with a float": function() {
+			var c = 567.123;
+			var expr = new ConstantExpression(c);
+			assert.deepEqual(expr.evaluate(), c);
+		},
+
+		"should do what comes natural with a String": function() {
+			var c = "Quoth the raven";
+			var expr = new ConstantExpression(c);
+			assert.deepEqual(expr.evaluate(), c);
+		},
+
+		"should do what comes natural with a date": function() {
+			var c = new Date();
+			var expr = new ConstantExpression(c);
+			assert.deepEqual(expr.evaluate(), c);
+		},
+
+	},
+
+};