MatchExpressionParser.js 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595
  1. "use strict";
  2. var assert = require("assert"),
  3. MatchExpressionParser = require("../../../../lib/pipeline/matcher/MatchExpressionParser");
  4. module.exports = {
  5. "MatchExpressionParser": {
  6. "Should generate matchers that work with no operators": function (){
  7. var goodQ = {'x':2},badQ = {'x':3};
  8. var parser = new MatchExpressionParser();
  9. var res = parser.parse(goodQ);
  10. assert.strictEqual(res.code,'OK',res.description);
  11. assert.ok( res.result.matches(goodQ));
  12. assert.ok( ! res.result.matches(badQ));
  13. },
  14. "Should parse {x:5,y:{$gt:5, :$lt:8}}": function() {
  15. var q = {'x':5, 'y':{'$gt':5, '$lt':8}};
  16. var parser = new MatchExpressionParser();
  17. var res = parser.parse( q );
  18. assert.strictEqual(res.code,'OK',res.description);
  19. assert.ok( res.result.matches({'x':5, 'y':7}) );
  20. assert.ok( res.result.matches({'x':5, 'y':6}) );
  21. assert.ok( ! res.result.matches({'x':6, 'y':7}) );
  22. assert.ok( ! res.result.matches({'x':5, 'y':9}) );
  23. assert.ok( ! res.result.matches({'x':5, 'y':4}) );
  24. },
  25. "Should parse $isolated and $atomic appropriately": function() {
  26. var q1 = {'x':5, '$atomic': {'$gt':5, '$lt':8}},
  27. q2 = {'x':5, '$isolated':1},
  28. q3 = {'x':5, 'y':{'$isolated':1}};
  29. var parser = new MatchExpressionParser();
  30. var t = parser.parse(q1);
  31. assert.strictEqual(parser.parse(q1).code, 'OK');
  32. assert.strictEqual(parser.parse(q2).code, 'OK');
  33. assert.strictEqual(parser.parse(q3).code, 'BAD_VALUE');
  34. },
  35. "Should parse and match $size with an int": function() {
  36. var parser = new MatchExpressionParser();
  37. var q = {'x':{'$size':2}};
  38. var res = parser.parse(q);
  39. assert.strictEqual(res.code,'OK',res.description);
  40. assert.ok( ! res.result.matches({'x':1}) );
  41. assert.ok( res.result.matches({'x':[1,2]}) );
  42. assert.ok( ! res.result.matches({'x':[1]}) );
  43. assert.ok( ! res.result.matches({'x':[1,2,3]}) );
  44. },
  45. "Should parse and match $size with a string argument": function() {
  46. var parser = new MatchExpressionParser();
  47. var q = {'x':{'$size':'a'}};
  48. var res = parser.parse( q );
  49. assert.strictEqual(res.code,'OK',res.description);
  50. assert.ok( ! res.result.matches({'x':1}) );
  51. assert.ok( ! res.result.matches({'x':[1,2]}) );
  52. assert.ok( res.result.matches({'x':[]}) );
  53. assert.ok( ! res.result.matches({'x': [1]}) );
  54. },
  55. "Should parse and match $size with a float argument":function() {
  56. var parser = new MatchExpressionParser();
  57. var q = {'x': {'$size': 2.5}};
  58. var res = parser.parse( q );
  59. assert.strictEqual( res.code,'OK',res.description );
  60. assert.ok( ! res.result.matches({'x':1}) );
  61. assert.ok( ! res.result.matches({'x':[1,2]}) );
  62. assert.ok( ! res.result.matches({'x':[]}) );
  63. assert.ok( ! res.result.matches({'x':[1,2,3]}) );
  64. },
  65. "Should not accept null": function() {
  66. var parser = new MatchExpressionParser();
  67. var q = {'x':{'$size':null}};
  68. var res = parser.parse( q );
  69. assert.strictEqual( res.code, 'BAD_VALUE' );
  70. },
  71. "Should parse $elemMatch : {x:1,y:2}": function() {
  72. var parser = new MatchExpressionParser();
  73. var q = {'x':{'$elemMatch': {'x':1,'y':2}}};
  74. var res = parser.parse( q );
  75. assert.strictEqual( res.code,'OK',res.description );
  76. assert.ok( ! res.result.matches({'x':1}) );
  77. assert.ok( ! res.result.matches({'x':[1,2]}) );
  78. assert.ok( ! res.result.matches({'x':[{'x':1}]}) );
  79. assert.ok( res.result.matches({'x': [{'x':1,'y':2}]}) );
  80. },
  81. "Should parse and match $elemMatch: {$gt:5}": function() {
  82. var parser = new MatchExpressionParser();
  83. var q = {'x': {'$elemMatch': {'$gt':5}}};
  84. var res = parser.parse( q );
  85. assert.strictEqual( res.code,'OK',res.description );
  86. assert.ok( ! res.result.matches({'x':1}) );
  87. assert.ok( ! res.result.matches({'x':[4]}) );
  88. assert.ok( res.result.matches({'x':[6]}) );
  89. },
  90. "Should parse and match $all:[1,2]" : function() {
  91. var parser = new MatchExpressionParser();
  92. var q = {'x':{'$all':[1,2]}};
  93. var res = parser.parse( q );
  94. assert.strictEqual( res.code,'OK',res.description );
  95. assert.ok( ! res.result.matches({'x':1}) );
  96. assert.ok( ! res.result.matches({'x':[1]}) );
  97. assert.ok( ! res.result.matches({'x':[2]}) );
  98. assert.ok( res.result.matches({'x':[1,2]}) );
  99. assert.ok( res.result.matches({'x':[1,2,3]}) );
  100. assert.ok( ! res.result.matches({'x':[2,3]}) );
  101. },
  102. "Should not allow $all to have an element argument": function() {
  103. var parser = new MatchExpressionParser();
  104. var q = {'x': {'$all':1}};
  105. var res = parser.parse( q );
  106. assert.strictEqual( res.code, 'BAD_VALUE' );
  107. },
  108. "Should not allow large regex patterns": function () {
  109. var parser = new MatchExpressionParser();
  110. var q = {'x':{'$all':[new RegExp((new Array(50*1000+1)).join('z'))] }};
  111. var res = parser.parse( q );
  112. assert.strictEqual( res.code, 'BAD_VALUE' );
  113. },
  114. "Should parse and match some simple regex patterns": function() {
  115. var parser = new MatchExpressionParser();
  116. var a = /^a/;
  117. var b = /B/i;
  118. var q = {'a': {'$all': [ a , b ]}};
  119. var res = parser.parse( q );
  120. assert.strictEqual( res.code,'OK',res.description );
  121. assert.ok( ! res.result.matches({'a':'ax'}) );
  122. assert.ok( ! res.result.matches({'a':'qqb'}) );
  123. assert.ok( res.result.matches({'a':'ab'}) );
  124. },
  125. "Should parse and match some more simple regexes" : function(){
  126. var parser = new MatchExpressionParser();
  127. var a = /^a/;
  128. var b = /abc/;
  129. var q = {'a': {'$all': [a, b]}};
  130. var res = parser.parse( q );
  131. assert.strictEqual( res.code,'OK',res.description );
  132. assert.ok( ! res.result.matches({'a':'ax'}) );
  133. assert.ok( res.result.matches({'a':'abc'}) );
  134. },
  135. "Should properly handle x:{$all:[5]}": function() {
  136. var parser = new MatchExpressionParser();
  137. var q = {'x':{'$all':[5]}};
  138. var res = parser.parse( q );
  139. assert.strictEqual( res.code,'OK',res.description );
  140. assert.ok( res.result.matches({'x':5}) );
  141. assert.ok( res.result.matches({'x':[5]}) );
  142. assert.ok( ! res.result.matches({'x':4}) );
  143. assert.ok( ! res.result.matches({'x':[4]}) );
  144. },
  145. "Should handle a good $all $elemMatch query": function() {
  146. var parser = new MatchExpressionParser();
  147. var q = {'x':{'$all':[{'$elemMatch': {'x':1,'y':2}}]}};
  148. var res = parser.parse( q );
  149. assert.strictEqual( res.code,'OK',res.description );
  150. assert.ok( ! res.result.matches({'x':1}) );
  151. assert.ok( ! res.result.matches({'x':[1,2]}) );
  152. assert.ok( ! res.result.matches({'x':[{'x':1}]}) );
  153. assert.ok( res.result.matches({'x':[{'x':1,'y':2}]}) );
  154. },
  155. "Should properly not parse bad $all $elemMatch queries": function() {
  156. var parser = new MatchExpressionParser();
  157. var q = {'x':{'$all':[{'$elemMatch':{'x':1,'y':2}}, 5]}};
  158. var res = parser.parse( q );
  159. assert.strictEqual( res.code, 'BAD_VALUE' );
  160. q = {'x':{'$all':[5,{'$elemMatch':{'x':1,'y':2}}]}};
  161. res = parser.parse( q );
  162. assert.strictEqual( res.code, 'BAD_VALUE' );
  163. },
  164. "Should parse and match simple $eq": function () {
  165. var parser = new MatchExpressionParser();
  166. var q = {'x': {'$eq': 2}};
  167. var res = parser.parse( q );
  168. assert.strictEqual( res.code,'OK',res.description );
  169. assert.ok( ! res.result.matches({'x':1}) );
  170. assert.ok( res.result.matches({'x':2}) );
  171. assert.ok( ! res.result.matches({'x':3}) );
  172. },
  173. "Should parse and match simple $gt": function() {
  174. var parser = new MatchExpressionParser();
  175. var q = {'x': {'$gt':2}};
  176. var res = parser.parse( q );
  177. assert.strictEqual( res.code,'OK',res.description );
  178. assert.ok( ! res.result.matches({'x':2}) );
  179. assert.ok( res.result.matches({'x':3}) );
  180. },
  181. "Should parse and match a simple $lt": function () {
  182. var parser = new MatchExpressionParser();
  183. var q = {'x':{'$lt':2}};
  184. var res = parser.parse( q );
  185. assert.strictEqual( res.code,'OK',res.description );
  186. assert.ok( res.result.matches({'x':1}) );
  187. assert.ok( ! res.result.matches({'x':2}) );
  188. assert.ok( ! res.result.matches({'x':3}) );
  189. },
  190. "Should parse and match simple $gte": function() {
  191. var parser = new MatchExpressionParser();
  192. var q = {'x': {'$gte':2}};
  193. var res = parser.parse( q );
  194. assert.strictEqual( res.code,'OK',res.description );
  195. assert.ok( ! res.result.matches({'x':1}) );
  196. assert.ok( res.result.matches({'x':2}) );
  197. assert.ok( res.result.matches({'x':3}) );
  198. },
  199. "Should parse and matc simple $lte": function() {
  200. var parser = new MatchExpressionParser();
  201. var q = {'x': {'$lte':2}};
  202. var res = parser.parse( q );
  203. assert.strictEqual( res.code,'OK',res.description );
  204. assert.ok( res.result.matches({'x':1}) );
  205. assert.ok( res.result.matches({'x':2}) );
  206. assert.ok( ! res.result.matches({'x':3}) );
  207. },
  208. "Should parse and match simple $ne": function() {
  209. var parser = new MatchExpressionParser();
  210. var q = {'x': {'$ne':2}};
  211. var res = parser.parse( q );
  212. assert.strictEqual( res.code,'OK',res.description );
  213. assert.ok( res.result.matches({'x':1}) );
  214. assert.ok( ! res.result.matches({'x':2}) );
  215. assert.ok( res.result.matches({'x':3}) );
  216. },
  217. "Should parse simple $mod patterns":function(){
  218. var parser = new MatchExpressionParser();
  219. var q = {'x':{'$mod':[3,2]}};
  220. var res = parser.parse( q );
  221. assert.strictEqual( res.code,'OK',res.description );
  222. q = {'x':{'$mod':[3]}};
  223. res = parser.parse( q );
  224. assert.strictEqual( res.code, 'BAD_VALUE' );
  225. q = {'x':{'$mod':[3,2,4]}};
  226. res = parser.parse( q );
  227. assert.strictEqual( res.code, 'BAD_VALUE' );
  228. q = {'x':{'$mod':['q',2]}};
  229. res = parser.parse( q );
  230. assert.strictEqual( res.code, 'BAD_VALUE' );
  231. q = {'x':{'$mod':3}};
  232. res = parser.parse( q );
  233. assert.strictEqual( res.code, 'BAD_VALUE' );
  234. q = {'x':{'$mod':{'a':1,'b':2}}};
  235. res = parser.parse( q );
  236. assert.strictEqual( res.code, 'BAD_VALUE' );
  237. },
  238. "Should parse and match simple $mod": function() {
  239. var parser = new MatchExpressionParser();
  240. var q = {'x':{'$mod':[3,2]}};
  241. var res = parser.parse( q );
  242. assert.strictEqual( res.code,'OK',res.description );
  243. assert.ok( res.result.matches({'x':5}) );
  244. assert.ok( ! res.result.matches({'x':4}) );
  245. assert.ok( res.result.matches({'x':8}) );
  246. },
  247. "Should parse and match a simple $in": function() {
  248. var parser = new MatchExpressionParser();
  249. var q = {'x': {'$in':[2,3]}};
  250. var res = parser.parse( q );
  251. assert.strictEqual( res.code,'OK',res.description );
  252. assert.ok( ! res.result.matches({'x':1}) );
  253. assert.ok( res.result.matches({'x':2}) );
  254. assert.ok( res.result.matches({'x':3}) );
  255. },
  256. "Should not accept a scalar as an arg to $in" : function() {
  257. var parser = new MatchExpressionParser();
  258. var q = {'x':{'$in': 5}};
  259. var res = parser.parse( q );
  260. assert.strictEqual( res.code, 'BAD_VALUE' );
  261. },
  262. "Should not accept an $elemMatch as an arg to an $in": function () {
  263. var parser = new MatchExpressionParser();
  264. var q = {'x':{'$in':[{'$elemMatch': 1}]}};
  265. var res = parser.parse( q );
  266. assert.strictEqual( res.code, 'BAD_VALUE' );
  267. },
  268. "Should not parse regexes that are too long": function() {
  269. var parser = new MatchExpressionParser();
  270. var str = (new Array(50*1000+1).join('z'));
  271. var q = {'x': {'$in':[new RegExp(str)]}};
  272. var res = parser.parse( q );
  273. assert.strictEqual( res.code, 'BAD_VALUE' );
  274. q = {'x':{'$in': [{'$regex': str}]}};
  275. res = parser.parse( q );
  276. assert.strictEqual( res.code, 'BAD_VALUE' );
  277. },
  278. "Should parse and match $regex in an $in expression": function() {
  279. var parser = new MatchExpressionParser();
  280. var a = /^a/;
  281. var b = /B/i;
  282. var q = {'a': {'$in': [a,b,"2",4]}};
  283. var res = parser.parse( q );
  284. assert.strictEqual( res.code,'OK',res.description );
  285. assert.ok( res.result.matches({'a':'ax'}) );
  286. assert.ok( res.result.matches({'a':/^a/}) );
  287. assert.ok( res.result.matches({'a':'qqb'}) );
  288. assert.ok( res.result.matches({'a':/B/i}) );
  289. assert.ok( res.result.matches({'a':4}) );
  290. assert.ok( ! res.result.matches({'a':'l'}) );
  291. assert.ok( ! res.result.matches({'a':/B/}) );
  292. },
  293. "Should parse and match a simple $nin": function() {
  294. var parser = new MatchExpressionParser();
  295. var q = {'x': {'$nin': [2,3]}};
  296. var res = parser.parse( q );
  297. assert.strictEqual( res.code,'OK',res.description );
  298. assert.ok( res.result.matches({'x':1}) );
  299. assert.ok( ! res.result.matches({'x':2}) );
  300. assert.ok( ! res.result.matches({'x':3}) );
  301. },
  302. "Should not accept a scalar argument to $nin":function() {
  303. var parser = new MatchExpressionParser();
  304. var q = {'x':{$nin: 5}};
  305. var res = parser.parse( q );
  306. assert.strictEqual( res.code, 'BAD_VALUE' );
  307. },
  308. "Should properly handle /regex/i":function() {
  309. var parser = new MatchExpressionParser();
  310. var a = /abc/i;
  311. var q = {'x': a };
  312. var res = parser.parse( q );
  313. assert.strictEqual( res.code,'OK',res.description );
  314. assert.ok( res.result.matches({'x':'ABC'}) );
  315. assert.ok( res.result.matches({'x':'abc'}) );
  316. assert.ok( ! res.result.matches({'x':'AC'}) );
  317. },
  318. "Should properly handle $regex x $option i": function() {
  319. var parser = new MatchExpressionParser();
  320. var q = {'x': {'$regex': 'abc', '$options':'i'}};
  321. var res = parser.parse( q );
  322. assert.strictEqual( res.code,'OK',res.description );
  323. assert.ok( res.result.matches({'x':'abc'}) );
  324. assert.ok( res.result.matches({'x':'ABC'}) );
  325. assert.ok( ! res.result.matches({'x':'AC'}) );
  326. },
  327. "Should properly handle $option i $regex x": function () {
  328. var parser = new MatchExpressionParser();
  329. var q = {'x':{'$options': 'i', '$regex': 'abc'}};
  330. var res = parser.parse( q );
  331. assert.strictEqual( res.code,'OK',res.description );
  332. assert.ok( res.result.matches({'x':'abc'}) );
  333. assert.ok( res.result.matches({'x':'ABC'}) );
  334. assert.ok( ! res.result.matches({'x':'AC'}) );
  335. },
  336. "Should not accept $optionas":function() {
  337. var parser = new MatchExpressionParser();
  338. var q = {'x':{'$regex':'abc', '$optionas':'i'}};
  339. var res = parser.parse( q );
  340. assert.strictEqual( res.code, 'BAD_VALUE' );
  341. q = {'x':{'$optionas': 'i'}};
  342. res = parser.parse( q );
  343. assert.strictEqual( res.code, 'BAD_VALUE' );
  344. q = {'x':{'$options':'i'}};
  345. res = parser.parse( q );
  346. assert.strictEqual( res.code, 'BAD_VALUE' );
  347. },
  348. "Should parse and match $exist true": function () {
  349. var parser = new MatchExpressionParser();
  350. var q = {'x':{'$exists': true}};
  351. var res = parser.parse( q );
  352. assert.strictEqual( res.code,'OK',res.description );
  353. assert.ok( res.result.matches({'x':'abc'}) );
  354. assert.ok( ! res.result.matches({'y':'AC'}) );
  355. },
  356. "Should parse and match $exists false": function() {
  357. var parser = new MatchExpressionParser();
  358. var q = {'x':{'$exists':false}};
  359. var res = parser.parse( q );
  360. assert.strictEqual( res.code,'OK',res.description );
  361. assert.ok( ! res.result.matches({'x':'abc'}) );
  362. assert.ok( res.result.matches({'y':'AC'}) );
  363. },
  364. "Should parse and match String $type": function() {
  365. var parser = new MatchExpressionParser();
  366. var q = {'x':{'$type': 2 }};
  367. var res = parser.parse( q );
  368. assert.strictEqual( res.code,'OK',res.description );
  369. assert.ok( res.result.matches({'x': 'abc'}) );
  370. assert.ok( ! res.result.matches({'x': 2}) );
  371. },
  372. "Should parse and match Number $type":function() {
  373. var parser = new MatchExpressionParser();
  374. var q = {'x':{'$type':1}};
  375. var res = parser.parse( q );
  376. assert.strictEqual( res.code,'OK',res.description );
  377. assert.ok( res.result.matches({'x':2}) );
  378. assert.ok( ! res.result.matches({'x': 'f'}) );
  379. },
  380. "Should parse and match null $type" : function() {
  381. var parser = new MatchExpressionParser();
  382. var q = {'x':{'$type': 10}};
  383. var res = parser.parse( q );
  384. assert.strictEqual( res.code,'OK',res.description );
  385. assert.ok( ! res.result.matches({'x':{}}) );
  386. assert.ok( ! res.result.matches({'x':5}) );
  387. assert.ok( res.result.matches({'x':null}) );
  388. },
  389. "Should parse but not match a type beyond typemax in $type": function() {
  390. var parser = new MatchExpressionParser();
  391. var q = {'x':{'$type': 1000}};
  392. var res = parser.parse( q );
  393. assert.strictEqual( res.code,'OK',res.description );
  394. assert.ok( ! res.result.matches({'x':5}) );
  395. assert.ok( ! res.result.matches({'x':'abc'}) );
  396. },
  397. "Should not parse a $type: Object":function() {
  398. var parser = new MatchExpressionParser();
  399. var q = {'x':{'$type': {'x':1}}};
  400. var res = parser.parse( q );
  401. assert.strictEqual( res.code, 'BAD_VALUE' );
  402. },
  403. "Should parse and match a simple $or": function() {
  404. var parser = new MatchExpressionParser();
  405. var q = {'$or':[{'x':1},{'y':2}]};
  406. var res = parser.parse( q );
  407. assert.strictEqual( res.code,'OK',res.description );
  408. assert.ok( res.result.matches({'x':1}) );
  409. assert.ok( res.result.matches({'y':2}) );
  410. assert.ok( ! res.result.matches({'x':3}) );
  411. assert.ok( ! res.result.matches({'y':1}) );
  412. },
  413. "Should parse and match with nested $or s": function() {
  414. var parser = new MatchExpressionParser();
  415. var q = {'$or':[{'$or':[{'x':1},{'y':2}]}]};
  416. var res = parser.parse( q );
  417. assert.strictEqual( res.code,'OK',res.description );
  418. assert.ok( res.result.matches({'x':1}) );
  419. assert.ok( res.result.matches({'y':2}) );
  420. assert.ok( ! res.result.matches({'x':3}) );
  421. assert.ok( ! res.result.matches({'y':1}) );
  422. },
  423. "Should parse and match $and": function(){
  424. var parser = new MatchExpressionParser();
  425. var q = {'$and':[{'x':1},{'y':2}]};
  426. var res = parser.parse( q );
  427. assert.strictEqual( res.code,'OK',res.description );
  428. assert.ok( ! res.result.matches({'x':1}) );
  429. assert.ok( ! res.result.matches({'y':2}) );
  430. assert.ok( ! res.result.matches({'x':3}) );
  431. assert.ok( ! res.result.matches({'y':1}) );
  432. assert.ok( res.result.matches({'x':1, 'y':2}) );
  433. assert.ok( ! res.result.matches({'x':2, 'y':2}) );
  434. },
  435. "Should parse and match $nor": function() {
  436. var parser = new MatchExpressionParser();
  437. var q = {'$nor':[{'x':1},{'y':2}]};
  438. var res = parser.parse( q );
  439. assert.strictEqual( res.code,'OK',res.description );
  440. assert.ok( ! res.result.matches({'x':1}) );
  441. assert.ok( ! res.result.matches({'y':2}) );
  442. assert.ok( res.result.matches({'x':3}) );
  443. assert.ok( res.result.matches({'y':1}) );
  444. },
  445. "Should parse and match $not": function() {
  446. var parser = new MatchExpressionParser();
  447. var q = {'x':{'$not':{'$gt':5}}};
  448. var res = parser.parse( q );
  449. assert.strictEqual( res.code,'OK',res.description );
  450. assert.ok( res.result.matches({'x':2}) );
  451. assert.ok( ! res.result.matches({'x':8}) );
  452. },
  453. "should allow trees less than the maximum recursion depth": function() {
  454. var parser = new MatchExpressionParser(),
  455. depth = 60,
  456. q = "",
  457. i;
  458. for (i = 0; i < depth/2; i++) {
  459. q = q + '{"$and": [{"a":3}, {"$or": [{"b":2},';
  460. }
  461. q = q + '{"b": 4}';
  462. for (i = 0; i < depth/2; i++) {
  463. q = q + "]}]}";
  464. }
  465. var res = parser.parse(JSON.parse(q));
  466. assert.strictEqual(res.code, 'OK', res.description);
  467. },
  468. "should error when depth limit is exceeded": function() {
  469. var parser = new MatchExpressionParser(),
  470. depth = 105,
  471. q = "",
  472. i;
  473. for (i = 0; i < depth/2; i++) {
  474. q = q + '{"$and": [{"a":3}, {"$or": [{"b":2},';
  475. }
  476. q = q + '{"b": 4}';
  477. for (i = 0; i < depth/2; i++) {
  478. q = q + "]}]}";
  479. }
  480. var res = parser.parse(JSON.parse(q));
  481. assert.strictEqual(res.description.substr(0, 43), 'exceeded maximum query tree depth of 100 at');
  482. assert.strictEqual(res.code, 'BAD_VALUE');
  483. },
  484. "should error when depth limit is reached through a $not": function() {
  485. var parser = new MatchExpressionParser(),
  486. depth = 105,
  487. q = '{"a": ',
  488. i;
  489. for (i = 0; i < depth; i++) {
  490. q = q + '{"$not": ';
  491. }
  492. q = q + '{"$eq": 5}';
  493. for (i = 0; i < depth+1; i++) {
  494. q = q + "}";
  495. }
  496. var res = parser.parse(JSON.parse(q));
  497. assert.strictEqual(res.description.substr(0, 43), 'exceeded maximum query tree depth of 100 at');
  498. assert.strictEqual(res.code, 'BAD_VALUE');
  499. },
  500. "should error when depth limit is reached through an $elemMatch": function() {
  501. var parser = new MatchExpressionParser(),
  502. depth = 105,
  503. q = '',
  504. i;
  505. for (i = 0; i < depth; i++) {
  506. q = q + '{"a": {"$elemMatch": ';
  507. }
  508. q = q + '{"b": 5}';
  509. for (i = 0; i < depth; i++) {
  510. q = q + "}}";
  511. }
  512. var res = parser.parse(JSON.parse(q));
  513. assert.strictEqual(res.description.substr(0, 43), 'exceeded maximum query tree depth of 100 at');
  514. assert.strictEqual(res.code, 'BAD_VALUE');
  515. },
  516. "Should parse $not $regex and match properly": function() {
  517. var parser = new MatchExpressionParser();
  518. var a = /abc/i;
  519. var q = {'x':{'$not': a}};
  520. var res = parser.parse( q );
  521. assert.strictEqual( res.code,'OK',res.description );
  522. assert.ok( ! res.result.matches({'x':'abc'}) );
  523. assert.ok( ! res.result.matches({'x':'ABC'}) );
  524. assert.ok( res.result.matches({'x':'AC'}) );
  525. }
  526. }
  527. };
  528. if (!module.parent)(new(require("mocha"))()).ui("exports").reporter("spec").addFile(__filename).run(process.exit);