浏览代码

EAGLESIX-2651: Divide: fix expr and tests

Kyle P Davis 11 年之前
父节点
当前提交
23a789be42
共有 2 个文件被更改,包括 67 次插入23 次删除
  1. 22 23
      lib/pipeline/expressions/DivideExpression.js
  2. 45 0
      test/lib/pipeline/expressions/DivideExpression_test.js

+ 22 - 23
lib/pipeline/expressions/DivideExpression.js

@@ -4,43 +4,42 @@
  * A $divide pipeline expression.
  * A $divide pipeline expression.
  * @see evaluateInternal
  * @see evaluateInternal
  * @class DivideExpression
  * @class DivideExpression
+ * @extends mungedb-aggregate.pipeline.expressions.FixedArityExpressionT
  * @namespace mungedb-aggregate.pipeline.expressions
  * @namespace mungedb-aggregate.pipeline.expressions
  * @module mungedb-aggregate
  * @module mungedb-aggregate
  * @constructor
  * @constructor
  **/
  **/
 var DivideExpression = module.exports = function DivideExpression(){
 var DivideExpression = module.exports = function DivideExpression(){
+    if (arguments.length !== 0) throw new Error(klass.name + ": no args expected");
     base.call(this);
     base.call(this);
-}, klass = DivideExpression,
-	FixedArityExpression = require("./FixedArityExpressionT")(klass, 2),
-	base = FixedArityExpression,
-	proto = klass.prototype = Object.create(base.prototype, {
-		constructor:{
-			value:klass
-		}
-	});
+}, klass = DivideExpression, base = require("./FixedArityExpressionT")(DivideExpression, 2), proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}});
 
 
-// DEPENDENCIES
 var Value = require("../Value"),
 var Value = require("../Value"),
 	Expression = require("./Expression");
 	Expression = require("./Expression");
 
 
-// PROTOTYPE MEMBERS
-proto.getOpName = function getOpName(){ //TODO: try to move this to a static and/or instance field instead of a getter function
-	return "$divide";
-};
-
 /**
 /**
  * Takes an array that contains a pair of numbers and returns the value of the first number divided by the second number.
  * Takes an array that contains a pair of numbers and returns the value of the first number divided by the second number.
  * @method evaluateInternal
  * @method evaluateInternal
  **/
  **/
 proto.evaluateInternal = function evaluateInternal(vars) {
 proto.evaluateInternal = function evaluateInternal(vars) {
-	var left = this.operands[0].evaluateInternal(vars),
-		right = this.operands[1].evaluateInternal(vars);
-	if (!(left instanceof Date) && (!right instanceof Date)) throw new Error("$divide does not support dates; code 16373");
-	right = Value.coerceToDouble(right);
-	if (right === 0) return undefined;
-	left = Value.coerceToDouble(left);
-	return left / right;
+	var lhs = this.operands[0].evaluateInternal(vars),
+		rhs = this.operands[1].evaluateInternal(vars);
+
+	if (typeof lhs !== "number" && typeof rhs !== "number") {
+        var numer = lhs,
+            denom = rhs;
+        if (denom === 0) throw new Error("can't $divide by zero; uassert code 16608");
+
+        return numer / denom;
+    } else if (lhs === undefined || lhs === null || rhs === undefined || rhs === null) {
+        return null;
+    } else{
+        throw new Error("User assertion: 16609: $divide only supports numeric types, not " + Value.getType(lhs) + " and " + Value.getType(rhs));
+    }
 };
 };
 
 
-/** Register Expression */
-Expression.registerExpression("$divide",base.parse);
+Expression.registerExpression("$divide", base.parse);
+
+proto.getOpName = function getOpName() {
+	return "$divide";
+};

+ 45 - 0
test/lib/pipeline/expressions/DivideExpression_test.js

@@ -0,0 +1,45 @@
+"use strict";
+var assert = require("assert"),
+	DivideExpression = require("../../../../lib/pipeline/expressions/DivideExpression"),
+	Expression = require("../../../../lib/pipeline/expressions/Expression");
+
+// 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.DivideExpression = {
+
+	"constructor()": {
+
+		"should construct instance": function() {
+			assert(new DivideExpression() instanceof DivideExpression);
+			assert(new DivideExpression() instanceof Expression);
+		},
+
+		"should error if given args": function() {
+			assert.throws(function() {
+				new DivideExpression("bad stuff");
+			});
+		},
+
+	},
+
+	"#getOpName()": {
+
+		"should return the correct op name; $size": function() {
+			assert.equal(new DivideExpression().getOpName(), "$divide");
+		},
+
+	},
+
+	"#evaluate()": {
+
+		"should return the size": function() {
+			var spec = {$divide: ["$a", "$b"]},
+				vars = {a: 6, b: 2},
+				expected = 3;
+			assert.strictEqual(Expression.parseOperand(spec).evaluate(vars), expected);
+		},
+
+	},
+
+};