Prechádzať zdrojové kódy

EAGLESIX-2653: Updated some tests for GTE/LT and started comparison port

Chris Sexton 11 rokov pred
rodič
commit
4fe67e1494

+ 11 - 29
lib/pipeline/matcher/ComparisonMatchExpression.js

@@ -3,14 +3,13 @@ var LeafMatchExpression = require('./LeafMatchExpression.js');
 var Value = require('../Value');
 
 
-// Autogenerated by cport.py on 2013-09-17 14:37
+// File: expression_leaf.h
 var ComparisonMatchExpression = module.exports = function ComparisonMatchExpression( type ){
 	base.call(this);
 	this._matchType = type;
 }, klass = ComparisonMatchExpression, base =  LeafMatchExpression, proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}});
 
 
-// File: expression_leaf.h lines: 88-88
 proto._rhs = undefined;
 
 /**
@@ -21,7 +20,6 @@ proto._rhs = undefined;
  *
  */
 proto.debugString = function debugString(level) {
-	// File: expression_leaf.cpp lines: 135-154
 	var retStr = this._debugAddSpace( level ) + this.path() + " ";
 	switch (this._matchType){
 		case 'LT':
@@ -59,7 +57,6 @@ proto.debugString = function debugString(level) {
  *
  */
 proto.equivalent = function equivalent(other) {
-	// File: expression_leaf.cpp lines: 53-61
 	if (other._matchType != this._matchType)  return false;
 	return this.path() === other.path() && Value.compare(this._rhs,other._rhs) === 0;
 };
@@ -71,7 +68,6 @@ proto.equivalent = function equivalent(other) {
  *
  */
 proto.getData = function getData(){
-	// File: expression_leaf.h lines: 85-84
 	return this._rhs;
 };
 
@@ -82,7 +78,6 @@ proto.getData = function getData(){
  *
  */
 proto.getRHS = function getRHS(){
-	// File: expression_leaf.h lines: 79-78
 	return this._rhs;
 };
 
@@ -95,7 +90,6 @@ proto.getRHS = function getRHS(){
  *
  */
 proto.init = function init(path,rhs) {
-	// File: expression_leaf.cpp lines: 65-87
 	this._rhs = rhs;
 	if ( (rhs instanceof Object && Object.keys(rhs).length === 0)) { return {'code':'BAD_VALUE', 'description':'Need a real operand'};}
 
@@ -114,43 +108,31 @@ proto.init = function init(path,rhs) {
  *
  */
 proto.matchesSingleElement = function matchesSingleElement(e){
-	// File: expression_leaf.cpp lines: 91-132
-	if( typeof(e) != typeof(this._rhs) ){
-		if( this._rhs === null) {
-			if(this._matchType in {'EQ':1, 'LTE':1, 'GTE':1}){
-				if(e === undefined || e === null || (e instanceof Object && Object.keys(e).length === 0)) {
-					return true;
-				}
-			}
-			return false;
-		}
-		if((e === null || e === undefined) && (this._rhs ===null || this._rhs === undefined)) {
-			return ["EQ","LTE","GTE"].indexOf(this._matchType) != -1;
+	if (Value.canonicalize(e) !== Value.canonicalize(this._rhs)) {
+		// some special cases
+		// // jsonNULL and undefined are treated the same
+		if (Value.canonicalize(e) + Value.canonicalize(this._rhs) === 5) {
+			return this._matchType === 'EQ' || this._matchType === 'LTE' || this._matchType === 'GTE';
 		}
 
-		if (this._rhs.constructor.name in {'MaxKey':1,'MinKey':1} ) {
-			return this._matchType != "EQ";
+		if (Value.canonicalize(e) === -1 || Value.canonicalize(e) === 127) {
+			return this._matchType !== 'EQ';
 		}
-		return false;
-	}
 
-	if( this._rhs instanceof Array) {
-		if( this._matchType != 'EQ') {
-			return false;
-		}
+		return false;
 	}
 
 	var x = Value.compare( e, this._rhs );
 
 	switch( this._matchType ) {
 		case "LT":
-			return x == -1;
+			return x < 0;
 		case "LTE":
 			return x <= 0;
 		case "EQ":
 			return x === 0;
 		case "GT":
-			return x === 1;
+			return x > 0;
 		case "GTE":
 			return x >= 0;
 		default:

+ 27 - 7
test/lib/pipeline/matcher/GTEMatchExpression.js

@@ -8,13 +8,13 @@ module.exports = {
 	"GTEMatchExpression": {
 		"should match scalars and strings properly": function (){
 			var e = new GTEMatchExpression();
-			var s = e.init('x',5);
+			var s = e.init('a',5);
 
 			assert.strictEqual(s.code, 'OK');
-			assert.ok( e.matches({'x':5}) );
-			assert.ok( ! e.matches({'x':4}) );
-			assert.ok( e.matches({'x':6}) );
-			assert.ok( ! e.matches({'x': 'eliot'}) );
+			assert.ok( e.matches({'a':5.5}) );
+			assert.ok( e.matches({'a':5}) );
+			assert.ok( ! e.matches({'a':4}) );
+			assert.ok( ! e.matches({'a': 'foo'}) );
 		},
 		"should handle invalid End of Object Operand": function testInvalidEooOperand(){
 			var e = new GTEMatchExpression();
@@ -43,16 +43,36 @@ module.exports = {
 			var s = e.init('a',[5]);
 
 			assert.strictEqual(s.code, 'OK');
-			assert.ok( ! e.matches({'a':[6]}) );
+			assert.ok( ! e.matches({'a':[4]}) );
+			assert.ok( e.matches({'a':[5]}) );
+			assert.ok( e.matches({'a':[6]}) );
 		},
 		"should not match null" : function() {
 			var e = new GTEMatchExpression();
 			var s = e.init('a',null);
-		
+
 			assert.strictEqual(s.code, 'OK');
 			assert.ok( e.matches({}) );
 			assert.ok( e.matches({'a':null}) );
 			assert.ok( ! e.matches({'a':4}) );
+			assert.ok( e.matches({'b':4}) );
+		},
+		"should match dot notation nulls": function() {
+			var e = new GTEMatchExpression();
+			var s = e.init('a.b',null);
+
+			assert.strictEqual(s.code, 'OK');
+			assert.ok(e.matchesJSON({}));
+			assert.ok(e.matchesJSON({a:null}));
+			assert.ok(e.matchesJSON({a:{}}));
+			assert.ok(e.matchesJSON({a:[{b: null}]}));
+			assert.ok(e.matchesJSON({a:[{a:4}, {b:4}]}));
+			assert.ok(!e.matchesJSON({a:[4]}));
+			assert.ok(!e.matchesJSON({a:[{b:4}]}));
+		},
+		"should match MinKey": function() {
+		},
+		"should match MaxKey": function() {
 		},
 		"should handle elemMatchKey":function() {
 			var e = new GTEMatchExpression();

+ 70 - 28
test/lib/pipeline/matcher/LTMatchExpression.js

@@ -1,20 +1,24 @@
 "use strict";
 var assert = require("assert"),
+	BSON = require("bson"),
 	MatchDetails = require('../../../../lib/pipeline/matcher/MatchDetails'),
 	LTMatchExpression = require("../../../../lib/pipeline/matcher/LTMatchExpression");
 
+// 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));
 
 module.exports = {
 	"LTMatchExpression": {
 		"should match scalars and strings properly": function (){
 			var e = new LTMatchExpression();
-			var s = e.init('x',5);
-			
+			var s = e.init('a',5);
+
 			assert.strictEqual(s.code, 'OK');
-			assert.ok( ! e.matches({'x':5}) );
-			assert.ok( e.matches({'x':4}) );
-			assert.ok( ! e.matches({'x':6}) );
-			assert.ok( ! e.matches({'x': 'eliot'}) );
+			assert.ok( ! e.matchesJSON({'a':5}) );
+			assert.ok( e.matchesJSON({'a':4.5}) );
+			assert.ok( ! e.matchesJSON({'a':6}) );
+			assert.ok( ! e.matchesJSON({'a':5}) );
+			assert.ok( ! e.matchesJSON({'a': 'foo'}) );
 		},
 		"should handle invalid End of Object Operand": function testInvalidEooOperand(){
 			var e = new LTMatchExpression();
@@ -22,45 +26,53 @@ module.exports = {
 
 			assert.strictEqual(s.code, 'BAD_VALUE');
 		},
-		"should match a pathed number":function() {
+		"should match a scalar":function() {
 			var e = new LTMatchExpression();
 			var s = e.init('a',5);
 
 			assert.strictEqual(s.code, 'OK');
-			assert.ok( e.matches({'a':4.5}) );
-			assert.ok( ! e.matches({'a':6}) );
+			assert.ok( e.matchesJSON({'a':4.5}) );
+			assert.ok( ! e.matchesJSON({'a':6}) );
 		},
-		"should match an empty pathed number":function() {
+		"should match an empty key":function() {
 			var e = new LTMatchExpression();
 			var s = e.init('',5);
 
 			assert.strictEqual(s.code, 'OK');
-			assert.ok( e.matches({'':4.5}) );
-			assert.ok( ! e.matches({'':6}) );
+			assert.ok( e.matchesJSON({'':4.5}) );
+			assert.ok( ! e.matchesJSON({'':6}) );
 		},
-		"should match stuff in an array": function() {
+		"should match array values": function() {
 			var e = new LTMatchExpression();
 			var s = e.init('a',5);
 
 			assert.strictEqual(s.code, 'OK');
-			assert.ok( e.matches({'a':[6,4.5]}) );
-			assert.ok( ! e.matches({'a':[6,7]}) );
+			assert.ok( e.matchesJSON({'a':[6,4.5]}) );
+			assert.ok( ! e.matchesJSON({'a':[6,7]}) );
 		},
-		"should not match full array" : function() {
+		"should match whole array" : function() {
 			var e = new LTMatchExpression();
 			var s = e.init('a',[5]);
 
 			assert.strictEqual(s.code, 'OK');
-			assert.ok( ! e.matches({'a':[4]}) );
+			assert.ok(e.matchesJSON({'a':[4]}));
+			assert.ok(!e.matchesJSON({'a':[5]}));
+			assert.ok(!e.matchesJSON({'a':[6]}));
+			// Nested arrays
+			assert.ok(!e.matchesJSON({'a':[[4]]}));
+			assert.ok(!e.matchesJSON({'a':[[5]]}));
+			assert.ok(!e.matchesJSON({'a':[[6]]}));
 		},
 		"should not match null" : function() {
 			var e = new LTMatchExpression();
 			var s = e.init('a',null);
-		
+
 			assert.strictEqual(s.code, 'OK');
-			assert.ok( ! e.matches({}) );
-			assert.ok( ! e.matches({'a':null}) );
-			assert.ok( ! e.matches({'a':4}) );
+			assert.ok( ! e.matchesJSON({}) );
+			assert.ok( ! e.matchesJSON({'a':null}) );
+			assert.ok( ! e.matchesJSON({'a':4}) );
+			// A non-existent field is treated same way as an empty bson object
+			assert.ok( ! e.matchesJSON({'b':4}) );
 		},
 		"should handle elemMatchKey":function() {
 			var e = new LTMatchExpression();
@@ -69,21 +81,51 @@ module.exports = {
 			m.requestElemMatchKey();
 			assert.strictEqual( s.code, 'OK' );
 
-			assert.ok( ! e.matches({'a':6}, m) );
+			assert.ok( ! e.matchesJSON({'a':6}, m) );
 			assert.ok( ! m.hasElemMatchKey() );
 
-			assert.ok( e.matches({'a':4}, m) );
+			assert.ok( e.matchesJSON({'a':4}, m) );
 			assert.ok( ! m.hasElemMatchKey() );
 
-			assert.ok( e.matches({'a':[6,2,5]}, m));
+			assert.ok( e.matchesJSON({'a':[6,2,5]}, m));
 			assert.ok( m.hasElemMatchKey());
 			assert.strictEqual('1', m.elemMatchKey());
-		}
+		},
+		"should match dot notation with nulls": function() {
+			var e = new LTMatchExpression();
+			var s = e.init('a.b',null);
+
+			assert.ok(!e.matchesJSON({}));
+			assert.ok(!e.matchesJSON({a:null}));
+			assert.ok(!e.matchesJSON({a:{}}));
+			assert.ok(!e.matchesJSON({a:[{b: null}]}));
+			assert.ok(!e.matchesJSON({a:[{a:4}, {b:4}]}));
+			assert.ok(!e.matchesJSON({a:[4]}));
+			assert.ok(!e.matchesJSON({a:[{b:4}]}));
+		},
+		"should match MinKey": function() {
+			var e = new LTMatchExpression();
+			var s = e.init('a', new BSON.MinKey());
 
+			assert.ok(!e.matchesJSON({a: new BSON.MinKey()}, null));
+			assert.ok(!e.matchesJSON({a: new BSON.MaxKey()}, null));
+			assert.ok(!e.matchesJSON({a: 4}, null));
+		},
+		"should match MaxKey": function() {
+			var e = new LTMatchExpression();
+			var s = e.init('a', new BSON.MaxKey());
 
+			assert.ok(!e.matchesJSON({a: new BSON.MaxKey()}));
+			assert.ok(e.matchesJSON({a: new BSON.MinKey()}));
+			assert.ok(e.matchesJSON({a: 4}));
+		},
+		"should match with ElemMatchKey": function() {
+			var e = new LTMatchExpression()
+			var s = e.init('a', 5);
 
+			assert.ok(!e.matchesJSON({a: 6}));
+			assert.ok(e.matchesJSON({a: 4}));
+			assert.ok(e.matchesJSON({a: [6,2,5]}));
+		},
 	}
 };
-
-if (!module.parent)(new(require("mocha"))()).ui("exports").reporter("spec").addFile(__filename).run(process.exit);
-