CompareExpression.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. var assert = require("assert"),
  2. CompareExpression = require("../../../../lib/pipeline/expressions/CompareExpression"),
  3. Expression = require("../../../../lib/pipeline/expressions/Expression"),
  4. FieldRangeExpression = require("../../../../lib/pipeline/expressions/FieldRangeExpression");
  5. module.exports = {
  6. "CompareExpression": {
  7. "constructor()": {
  8. "should throw Error if no args": function testConstructor(){
  9. assert.throws(function(){
  10. new CompareExpression();
  11. });
  12. }
  13. },
  14. "#getOpName()": {
  15. "should return the correct op name; $eq, $ne, $gt, $gte, $lt, $lte, $cmp": function testOpName(){
  16. assert.equal((new CompareExpression(Expression.CmpOp.EQ)).getOpName(), "$eq");
  17. assert.equal((new CompareExpression(Expression.CmpOp.NE)).getOpName(), "$ne");
  18. assert.equal((new CompareExpression(Expression.CmpOp.GT)).getOpName(), "$gt");
  19. assert.equal((new CompareExpression(Expression.CmpOp.GTE)).getOpName(), "$gte");
  20. assert.equal((new CompareExpression(Expression.CmpOp.LT)).getOpName(), "$lt");
  21. assert.equal((new CompareExpression(Expression.CmpOp.LTE)).getOpName(), "$lte");
  22. assert.equal((new CompareExpression(Expression.CmpOp.CMP)).getOpName(), "$cmp");
  23. }
  24. },
  25. "#evaluate()": {
  26. "$eq": {
  27. "should return false if first < second; {$eq:[1,2]}": function testEqLt(){
  28. assert.equal(Expression.parseOperand({$eq:[1,2]}).evaluate({}), false);
  29. },
  30. "should return true if first == second; {$eq:[1,1]}": function testEqEq(){
  31. assert.equal(Expression.parseOperand({$eq:[1,1]}).evaluate({}), true);
  32. },
  33. "should return false if first > second {$eq:[1,0]}": function testEqGt(){
  34. assert.equal(Expression.parseOperand({$eq:[1,0]}).evaluate({}), false);
  35. },
  36. "should return false if first and second are different types {$eq:[null,0]}": function testEqGt(){
  37. assert.equal(Expression.parseOperand({$eq:[null,0]}).evaluate({}), false);
  38. },
  39. "should return false if first and second are different types {$eq:[undefined,0]}": function testEqGt(){
  40. assert.equal(Expression.parseOperand({$eq:[undefined,0]}).evaluate({}), false);
  41. },
  42. "should return false if first and second are different arrays {$eq:[[1],[null]]}": function testEqGt(){
  43. assert.equal(Expression.parseOperand({$eq:[[1],[null]]}).evaluate({}), false);
  44. },
  45. "should return false if first and second are different arrays {$eq:[[1],[]]}": function testEqGt(){
  46. assert.equal(Expression.parseOperand({$eq:[[1],[]]}).evaluate({}), false);
  47. },
  48. "should return true if first and second are the same arrays {$eq:[[1],[1]]}": function testEqGt(){
  49. assert.equal(Expression.parseOperand({$eq:[[1],[1]]}).evaluate({}), true);
  50. }
  51. },
  52. "$ne": {
  53. "should return true if first < second; {$ne:[1,2]}": function testNeLt(){
  54. assert.equal(Expression.parseOperand({$ne:[1,2]}).evaluate({}), true);
  55. },
  56. "should return false if first == second; {$ne:[1,1]}": function testNeLt(){
  57. assert.equal(Expression.parseOperand({$ne:[1,1]}).evaluate({}), false);
  58. },
  59. "should return true if first > second; {$ne:[1,0]}": function testNeGt(){
  60. assert.equal(Expression.parseOperand({$ne:[1,0]}).evaluate({}), true);
  61. }
  62. },
  63. "$gt": {
  64. "should return false if first < second; {$gt:[1,2]}": function testGtLt(){
  65. assert.equal(Expression.parseOperand({$gt:[1,2]}).evaluate({}), false);
  66. },
  67. "should return false if first == second; {$gt:[1,1]}": function testGtLt(){
  68. assert.equal(Expression.parseOperand({$gt:[1,1]}).evaluate({}), false);
  69. },
  70. "should return true if first > second; {$gt:[1,0]}": function testGtGt(){
  71. assert.equal(Expression.parseOperand({$gt:[1,0]}).evaluate({}), true);
  72. }
  73. },
  74. "$gte": {
  75. "should return false if first < second; {$gte:[1,2]}": function testGteLt(){
  76. assert.equal(Expression.parseOperand({$gte:[1,2]}).evaluate({}), false);
  77. },
  78. "should return true if first == second; {$gte:[1,1]}": function testGteLt(){
  79. assert.equal(Expression.parseOperand({$gte:[1,1]}).evaluate({}), true);
  80. },
  81. "should return true if first > second; {$gte:[1,0]}": function testGteGt(){
  82. assert.equal(Expression.parseOperand({$gte:[1,0]}).evaluate({}), true);
  83. }
  84. },
  85. "$lt": {
  86. "should return true if first < second; {$lt:[1,2]}": function testLtLt(){
  87. assert.equal(Expression.parseOperand({$lt:[1,2]}).evaluate({}), true);
  88. },
  89. "should return false if first == second; {$lt:[1,1]}": function testLtLt(){
  90. assert.equal(Expression.parseOperand({$lt:[1,1]}).evaluate({}), false);
  91. },
  92. "should return false if first > second; {$lt:[1,0]}": function testLtGt(){
  93. assert.equal(Expression.parseOperand({$lt:[1,0]}).evaluate({}), false);
  94. }
  95. },
  96. "$lte": {
  97. "should return true if first < second; {$lte:[1,2]}": function testLteLt(){
  98. assert.equal(Expression.parseOperand({$lte:[1,2]}).evaluate({}), true);
  99. },
  100. "should return true if first == second; {$lte:[1,1]}": function testLteLt(){
  101. assert.equal(Expression.parseOperand({$lte:[1,1]}).evaluate({}), true);
  102. },
  103. "should return false if first > second; {$lte:[1,0]}": function testLteGt(){
  104. assert.equal(Expression.parseOperand({$lte:[1,0]}).evaluate({}), false);
  105. }
  106. },
  107. "$cmp": {
  108. "should return -1 if first < second; {$cmp:[1,2]}": function testCmpLt(){
  109. assert.equal(Expression.parseOperand({$cmp:[1,2]}).evaluate({}), -1);
  110. },
  111. "should return 0 if first < second; {$cmp:[1,1]}": function testCmpLt(){
  112. assert.equal(Expression.parseOperand({$cmp:[1,1]}).evaluate({}), 0);
  113. },
  114. "should return 1 if first < second; {$cmp:[1,0]}": function testCmpLt(){
  115. assert.equal(Expression.parseOperand({$cmp:[1,0]}).evaluate({}), 1);
  116. },
  117. "should return 1 even if comparison is larger; {$cmp:['z','a']}": function testCmpBracketed(){
  118. assert.equal(Expression.parseOperand({$cmp:['z','a']}).evaluate({}), 1);
  119. }
  120. },
  121. "should throw Error": {
  122. "if zero operands are provided; {$ne:[]}": function testZeroOperands(){
  123. assert.throws(function(){
  124. Expression.parseOperand({$ne:[]}).evaluate({});
  125. });
  126. },
  127. "if one operand is provided; {$eq:[1]}": function testOneOperand(){
  128. assert.throws(function(){
  129. Expression.parseOperand({$eq:[1]}).evaluate({});
  130. });
  131. },
  132. "if three operands are provided; {$gt:[2,3,4]}": function testThreeOperands(){
  133. assert.throws(function(){
  134. Expression.parseOperand({$gt:[2,3,4]}).evaluate({});
  135. });
  136. }
  137. }
  138. },
  139. "#optimize()": {
  140. "should optimize constants; {$eq:[1,1]}": function testOptimizeConstants(){
  141. assert.deepEqual(Expression.parseOperand({$eq:[1,1]}).optimize().toJson(true), {$const:true});
  142. },
  143. "should not optimize if $cmp op; {$cmp:[1,'$a']}": function testNoOptimizeCmp(){
  144. assert.deepEqual(Expression.parseOperand({$cmp:[1,'$a']}).optimize().toJson(), {$cmp:[1,'$a']});
  145. },
  146. "should not optimize if $ne op; {$ne:[1,'$a']}": function testNoOptimizeNe(){
  147. assert.deepEqual(Expression.parseOperand({$ne:[1,'$a']}).optimize().toJson(), {$ne:[1,'$a']});
  148. },
  149. "should not optimize if no constants; {$ne:['$a','$b']}": function testNoOptimizeNoConstant(){
  150. assert.deepEqual(Expression.parseOperand({$ne:['$a','$b']}).optimize().toJson(), {$ne:['$a','$b']});
  151. },
  152. "should not optimize without an immediate field path;": {
  153. "{$eq:[{$and:['$a']},1]}": function testNoOptimizeWithoutFieldPath(){
  154. assert.deepEqual(Expression.parseOperand({$eq:[{$and:['$a']},1]}).optimize().toJson(), {$eq:[{$and:['$a']},1]});
  155. },
  156. "(reversed); {$eq:[1,{$and:['$a']}]}": function testNoOptimizeWithoutFieldPathReverse(){
  157. assert.deepEqual(Expression.parseOperand({$eq:[1,{$and:['$a']}]}).optimize().toJson(), {$eq:[1,{$and:['$a']}]});
  158. }
  159. },
  160. "should optimize $eq expressions;": {
  161. "{$eq:['$a',1]}": function testOptimizeEq(){
  162. var expr = Expression.parseOperand({$eq:['$a',1]}).optimize();
  163. assert(expr instanceof FieldRangeExpression, "not optimized");
  164. assert.deepEqual(expr.toJson(), {$eq:['$a',1]});
  165. },
  166. "{$eq:[1,'$a']} (reversed)": function testOptimizeEqReverse(){
  167. var expr = Expression.parseOperand({$eq:[1,'$a']}).optimize();
  168. assert(expr instanceof FieldRangeExpression, "not optimized");
  169. assert.deepEqual(expr.toJson(), {$eq:['$a',1]});
  170. }
  171. },
  172. "should optimize $lt expressions;": {
  173. "{$lt:['$a',1]}": function testOptimizeLt(){
  174. var expr = Expression.parseOperand({$lt:['$a',1]}).optimize();
  175. assert(expr instanceof FieldRangeExpression, "not optimized");
  176. assert.deepEqual(expr.toJson(), {$lt:['$a',1]});
  177. },
  178. "{$lt:[1,'$a']} (reversed)": function testOptimizeLtReverse(){
  179. var expr = Expression.parseOperand({$lt:[1,'$a']}).optimize();
  180. assert(expr instanceof FieldRangeExpression, "not optimized");
  181. assert.deepEqual(expr.toJson(), {$gt:['$a',1]});
  182. }
  183. },
  184. "should optimize $lte expressions;": {
  185. "{$lte:['$b',2]}": function testOptimizeLte(){
  186. var expr = Expression.parseOperand({$lte:['$b',2]}).optimize();
  187. assert(expr instanceof FieldRangeExpression, "not optimized");
  188. assert.deepEqual(expr.toJson(), {$lte:['$b',2]});
  189. },
  190. "{$lte:[2,'$b']} (reversed)": function testOptimizeLteReverse(){
  191. var expr = Expression.parseOperand({$lte:[2,'$b']}).optimize();
  192. assert(expr instanceof FieldRangeExpression, "not optimized");
  193. assert.deepEqual(expr.toJson(), {$gte:['$b',2]});
  194. }
  195. },
  196. "should optimize $gt expressions;": {
  197. "{$gt:['$b',2]}": function testOptimizeGt(){
  198. var expr = Expression.parseOperand({$gt:['$b',2]}).optimize();
  199. assert(expr instanceof FieldRangeExpression, "not optimized");
  200. assert.deepEqual(expr.toJson(), {$gt:['$b',2]});
  201. },
  202. "{$gt:[2,'$b']} (reversed)": function testOptimizeGtReverse(){
  203. var expr = Expression.parseOperand({$gt:[2,'$b']}).optimize();
  204. assert(expr instanceof FieldRangeExpression, "not optimized");
  205. assert.deepEqual(expr.toJson(), {$lt:['$b',2]});
  206. }
  207. },
  208. "should optimize $gte expressions;": {
  209. "{$gte:['$b',2]}": function testOptimizeGte(){
  210. var expr = Expression.parseOperand({$gte:['$b',2]}).optimize();
  211. assert(expr instanceof FieldRangeExpression, "not optimized");
  212. assert.deepEqual(expr.toJson(), {$gte:['$b',2]});
  213. },
  214. "{$gte:[2,'$b']} (reversed)": function testOptimizeGteReverse(){
  215. var expr = Expression.parseOperand({$gte:[2,'$b']}).optimize();
  216. assert(expr instanceof FieldRangeExpression, "not optimized");
  217. assert.deepEqual(expr.toJson(), {$lte:['$b',2]});
  218. }
  219. },
  220. }
  221. }
  222. };
  223. if (!module.parent)(new(require("mocha"))()).ui("exports").reporter("spec").addFile(__filename).run(process.exit);