connection.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  1. // Copyright 2015 The MemDB Authors.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
  12. // implied. See the License for the specific language governing
  13. // permissions and limitations under the License. See the AUTHORS file
  14. // for names of contributors.
  15. 'use strict';
  16. var P = require('bluebird');
  17. var _ = require('lodash');
  18. var should = require('should');
  19. var env = require('../env');
  20. var memdb = require('../../lib');
  21. var logger = require('memdb-logger').getLogger('test', __filename);
  22. describe('connection test', function(){
  23. beforeEach(env.flushdb);
  24. it('find/update/insert/remove/commit/rollback', function(cb){
  25. var conn = null;
  26. var User = null, News = null;
  27. var user1 = {_id : '1', name : 'rain', age : 30};
  28. var user2 = {_id : '2', name : 'tina', age : 24};
  29. var news1 = {_id : '1', text : 'hello'};
  30. return P.try(function(){
  31. return env.startCluster('s1');
  32. })
  33. .then(function(){
  34. return memdb.connect(env.config.shards.s1)
  35. .then(function(ret){
  36. conn = ret;
  37. });
  38. })
  39. .then(function(){
  40. User = conn.collection('user');
  41. News = conn.collection('news');
  42. return User.insert([user1, user2]);
  43. })
  44. .then(function(ret){
  45. return conn.commit();
  46. })
  47. .then(function(){
  48. return User.update(user1._id, {$set : {age : 31}});
  49. })
  50. .then(function(){
  51. return User.find(user1._id, 'age')
  52. .then(function(ret){
  53. ret.age.should.eql(31);
  54. });
  55. })
  56. .then(function(){
  57. return User.find(user2._id)
  58. .then(function(ret){
  59. ret.should.eql(user2);
  60. });
  61. })
  62. .then(function(){
  63. return User.remove(user2._id);
  64. })
  65. .then(function(){
  66. return News.insert(news1);
  67. })
  68. .then(function(){
  69. return User.find(user2._id)
  70. .then(function(ret){
  71. (ret === null).should.eql(true);
  72. });
  73. })
  74. .then(function(){
  75. return conn.rollback();
  76. })
  77. .then(function(){
  78. return User.findOne({_id : user1._id})
  79. .then(function(ret){
  80. ret.should.eql(user1);
  81. });
  82. })
  83. .then(function(){
  84. return User.findOne({_id : user2._id})
  85. .then(function(ret){
  86. ret.should.eql(user2);
  87. });
  88. })
  89. .then(function(){
  90. return News.findOne({_id : news1._id})
  91. .then(function(ret){
  92. (ret === null).should.eql(true);
  93. });
  94. })
  95. .then(function(){
  96. return User.remove(user1._id);
  97. })
  98. .then(function(){
  99. return User.remove(user2._id);
  100. })
  101. .then(function(){
  102. return conn.commit();
  103. })
  104. .then(function(){
  105. return conn.close();
  106. })
  107. .finally(function(){
  108. return env.stopCluster();
  109. })
  110. .nodeify(cb);
  111. });
  112. it('index test', function(cb){
  113. var conn = null;
  114. var Player = null;
  115. var errCount = 0;
  116. return P.try(function(){
  117. return env.startCluster('s1');
  118. })
  119. .then(function(){
  120. return memdb.connect(env.config.shards.s1)
  121. .then(function(ret){
  122. conn = ret;
  123. });
  124. })
  125. .then(function(){
  126. Player = conn.collection('player');
  127. return Player.find({areaId : 1})
  128. .then(function(players){
  129. players.length.should.eql(0);
  130. });
  131. })
  132. .then(function(){
  133. return Player.insert([{_id : '1', areaId : 1}, {_id : '2', areaId : 1}]);
  134. })
  135. .then(function(){
  136. return Player.find({areaId : 1})
  137. .then(function(players){
  138. players.length.should.eql(2);
  139. players.forEach(function(player){
  140. player.areaId.should.eql(1);
  141. });
  142. });
  143. })
  144. .then(function(){
  145. return Player.update({areaId : 1}, {$set : {areaId : 2}});
  146. })
  147. .then(function(){
  148. return Player.find({areaId : 1})
  149. .then(function(players){
  150. players.length.should.eql(0);
  151. });
  152. })
  153. .then(function(){
  154. return Player.find({areaId : 2})
  155. .then(function(players){
  156. players.length.should.eql(2);
  157. });
  158. })
  159. .then(function(){
  160. return Player.remove({areaId : 2});
  161. })
  162. .then(function(){
  163. return Player.find({areaId : 2})
  164. .then(function(players){
  165. players.length.should.eql(0);
  166. });
  167. })
  168. .then(function(){
  169. // Should ignore the index
  170. return Player.insert({_id : '1', areaId : -1});
  171. })
  172. .then(function(){
  173. // Should ignore the index
  174. return Player.find({areaId : -1})
  175. .catch(function(err){
  176. errCount++;
  177. });
  178. })
  179. .then(function(){
  180. // invalid index value
  181. return Player.update('1', {$set : {areaId : ['invalid value']}}, {upsert : true})
  182. .catch(function(err){
  183. errCount++;
  184. });
  185. })
  186. .then(function(){
  187. errCount.should.eql(2);
  188. return conn.close();
  189. })
  190. .finally(function(){
  191. return env.stopCluster();
  192. })
  193. .nodeify(cb);
  194. });
  195. it('compound index test', function(cb){
  196. var conn = null;
  197. var Player = null;
  198. return P.try(function(){
  199. return env.startCluster('s1');
  200. })
  201. .then(function(){
  202. return memdb.connect(env.config.shards.s1)
  203. .then(function(ret){
  204. conn = ret;
  205. });
  206. })
  207. .then(function(){
  208. Player = conn.collection('player');
  209. return Player.insert({_id : '1', deviceType : 1, deviceId : 'id1'});
  210. })
  211. .then(function(){
  212. return Player.find({deviceType : 1, deviceId : 'id1'})
  213. .then(function(players){
  214. players.length.should.eql(1);
  215. });
  216. })
  217. .then(function(){
  218. return Player.update({_id : '1'}, {$set : {deviceType : 2}});
  219. })
  220. .then(function(){
  221. return Player.find({deviceType : 2, deviceId : 'id1'})
  222. .then(function(players){
  223. players.length.should.eql(1);
  224. });
  225. })
  226. .then(function(){
  227. return Player.insert({_id : '2', deviceType : 2, deviceId : 'id1'})
  228. .catch(function(err){
  229. // Should throw duplicate key error
  230. logger.debug(err);
  231. });
  232. })
  233. .then(function(){
  234. // rolledback on previous error
  235. return Player.find({deviceType : 2, deviceId : 'id1'})
  236. .then(function(players){
  237. players.length.should.eql(0);
  238. });
  239. })
  240. .then(function(){
  241. return conn.close();
  242. })
  243. .finally(function(){
  244. return env.stopCluster();
  245. })
  246. .nodeify(cb);
  247. });
  248. it('concurrent query on same connection', function(cb){
  249. var conn = null;
  250. var errCount = 0;
  251. return P.try(function(){
  252. return env.startCluster('s1');
  253. })
  254. .then(function(){
  255. return memdb.connect(env.config.shards.s1)
  256. .then(function(ret){
  257. conn = ret;
  258. });
  259. })
  260. .then(function(){
  261. var Player = conn.collection('player');
  262. Player.insert({_id : 1, name : 'rain'});
  263. Player.remove({_id : 1})
  264. .catch(function(e){
  265. errCount++;
  266. });
  267. })
  268. .delay(500)
  269. .then(function(){
  270. return conn.commit();
  271. })
  272. .then(function(){
  273. errCount.should.eql(1);
  274. return conn.close();
  275. })
  276. .finally(function(){
  277. return env.stopCluster();
  278. })
  279. .nodeify(cb);
  280. });
  281. it('eval', function(cb){
  282. var conn = null;
  283. return P.try(function(){
  284. return env.startCluster('s1');
  285. })
  286. .then(function(){
  287. return memdb.connect(env.config.shards.s1)
  288. .then(function(ret){
  289. conn = ret;
  290. });
  291. })
  292. .then(function(){
  293. var script = '\
  294. P.try(function(){\
  295. return db.insert("test", doc);\
  296. })\
  297. .then(function(){\
  298. return db.commit();\
  299. });';
  300. var context = {
  301. doc : {_id : '1', name :'rain'},
  302. };
  303. return conn.eval(script, context); //jshint ignore:line
  304. })
  305. .then(function(){
  306. return conn.collection('test').find('1')
  307. .then(function(ret){
  308. ret.name.should.eql('rain');
  309. });
  310. })
  311. .then(function(){
  312. return conn.collection('test').remove('1');
  313. })
  314. .then(function(){
  315. return conn.commit();
  316. })
  317. .then(function(){
  318. return conn.close();
  319. })
  320. .finally(function(){
  321. return env.stopCluster();
  322. })
  323. .nodeify(cb);
  324. });
  325. it('collection/field name restriction', function(cb){
  326. var conn = null;
  327. var Collection = null;
  328. var errCount = 0;
  329. return P.try(function(){
  330. return env.startCluster('s1');
  331. })
  332. .then(function(){
  333. return memdb.connect(env.config.shards.s1)
  334. .then(function(ret){
  335. conn = ret;
  336. });
  337. })
  338. .then(function(){
  339. Collection = conn.collection('invalid$name');
  340. return Collection.insert({_id : 1, name : 'rain'});
  341. })
  342. .catch(function(err){
  343. errCount++;
  344. })
  345. .then(function(){
  346. Collection = conn.collection('this is\\valid.coll:name');
  347. return Collection.insert({_id : 1, name : 'this.is:valid$value'});
  348. })
  349. .then(function(){
  350. return Collection.insert({_id : 2, 'invalid.field' : 'value'});
  351. })
  352. .catch(function(err){
  353. errCount++;
  354. })
  355. .then(function(){
  356. return Collection.insert({_id : 3, '$invalidfield' : 'value'});
  357. })
  358. .catch(function(err){
  359. errCount++;
  360. })
  361. .then(function(){
  362. errCount.should.eql(3);
  363. return conn.close();
  364. })
  365. .finally(function(){
  366. return env.stopCluster();
  367. })
  368. .nodeify(cb);
  369. });
  370. });