NaryExpression.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. "use strict";
  2. var assert = require("assert"),
  3. NaryExpression = require("../../../../lib/pipeline/expressions/NaryExpression"),
  4. ConstantExpression = require("../../../../lib/pipeline/expressions/ConstantExpression"),
  5. FieldPathExpression = require("../../../../lib/pipeline/expressions/FieldPathExpression"),
  6. Expression = require("../../../../lib/pipeline/expressions/Expression");
  7. // A dummy child of NaryExpression used for testing
  8. var TestableExpression = (function(){
  9. // CONSTRUCTOR
  10. var klass = module.exports = function TestableExpression(operands, haveFactory){
  11. base.call(this);
  12. if (operands) {
  13. var self = this;
  14. operands.forEach(function(operand) {
  15. self.addOperand(operand);
  16. });
  17. }
  18. this.haveFactory = !!haveFactory;
  19. }, base = NaryExpression, proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}});
  20. // PROTOTYPE MEMBERS
  21. proto.evaluate = function evaluate(doc) {
  22. // Just put all the values in a list. This is not associative/commutative so
  23. // the results will change if a factory is provided and operations are reordered.
  24. return this.operands.map(function(operand) {
  25. return operand.evaluate(doc);
  26. });
  27. };
  28. proto.getFactory = function getFactory(){
  29. return this.haveFactory ? this.factory : klass;
  30. };
  31. proto.getOpName = function getOpName() {
  32. return "$testable";
  33. };
  34. return klass;
  35. })();
  36. module.exports = {
  37. "NaryExpression": {
  38. "constructor()": {
  39. },
  40. "#optimize()": {
  41. },
  42. "#addOperand() should be able to add operands to expressions": function testAddOperand(){
  43. assert.deepEqual(new TestableExpression([new ConstantExpression(9)]).toJSON(), {$testable:[9]});
  44. assert.deepEqual(new TestableExpression([new FieldPathExpression("ab.c")]).toJSON(), {$testable:["$ab.c"]});
  45. },
  46. "#checkArgLimit() should throw Error iff number of operands is over given limit": function testCheckArgLimit(){
  47. var testableExpr = new TestableExpression();
  48. // no arguments
  49. assert.doesNotThrow(function(){
  50. testableExpr.checkArgLimit(1);
  51. });
  52. // one argument
  53. testableExpr.addOperand(new ConstantExpression(1));
  54. assert.throws(function(){
  55. testableExpr.checkArgLimit(1);
  56. });
  57. assert.doesNotThrow(function(){
  58. testableExpr.checkArgLimit(2);
  59. });
  60. // two arguments
  61. testableExpr.addOperand(new ConstantExpression(2));
  62. assert.throws(function(){
  63. testableExpr.checkArgLimit(1);
  64. });
  65. assert.throws(function(){
  66. testableExpr.checkArgLimit(2);
  67. });
  68. assert.doesNotThrow(function(){
  69. testableExpr.checkArgLimit(3);
  70. });
  71. },
  72. "#checkArgCount() should throw Error iff number of operands is not equal to given count": function testCheckArgCount(){
  73. var testableExpr = new TestableExpression();
  74. // no arguments
  75. assert.doesNotThrow(function(){
  76. testableExpr.checkArgCount(0);
  77. });
  78. assert.throws(function(){
  79. testableExpr.checkArgCount(1);
  80. });
  81. // one argument
  82. testableExpr.addOperand(new ConstantExpression(1));
  83. assert.throws(function(){
  84. testableExpr.checkArgCount(0);
  85. });
  86. assert.doesNotThrow(function(){
  87. testableExpr.checkArgCount(1);
  88. });
  89. assert.throws(function(){
  90. testableExpr.checkArgCount(2);
  91. });
  92. // two arguments
  93. testableExpr.addOperand(new ConstantExpression(2));
  94. assert.throws(function(){
  95. testableExpr.checkArgCount(1);
  96. });
  97. assert.doesNotThrow(function(){
  98. testableExpr.checkArgCount(2);
  99. });
  100. assert.throws(function(){
  101. testableExpr.checkArgCount(3);
  102. });
  103. },
  104. //the following test case is eagerly awaiting ObjectExpression
  105. "#addDependencies()": function testDependencies(){
  106. var testableExpr = new TestableExpression();
  107. // no arguments
  108. assert.deepEqual(testableExpr.addDependencies({}), {});
  109. // add a constant argument
  110. testableExpr.addOperand(new ConstantExpression(1));
  111. assert.deepEqual(testableExpr.addDependencies({}), {});
  112. // add a field path argument
  113. testableExpr.addOperand(new FieldPathExpression("ab.c"));
  114. assert.deepEqual(testableExpr.addDependencies({}), {"ab.c":1});
  115. // add an object expression
  116. testableExpr.addOperand(Expression.parseObject({a:"$x",q:"$r"}, new Expression.ObjectCtx({isDocumentOk:1})));
  117. assert.deepEqual(testableExpr.addDependencies({}), {"ab.c":1, "x":1, "r":1});
  118. }
  119. }
  120. };
  121. if (!module.parent)(new(require("mocha"))()).ui("exports").reporter("spec").addFile(__filename).run(process.exit);