application.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585
  1. var app = require('../lib/application');
  2. var pomelo = require('../');
  3. var should = require('should');
  4. var WAIT_TIME = 1000;
  5. var mockBase = process.cwd() + '/test';
  6. describe('application test', function(){
  7. afterEach(function() {
  8. app.state = 0;
  9. app.settings = {};
  10. });
  11. describe('#init', function() {
  12. it('should init the app instance', function() {
  13. app.init({base: mockBase});
  14. app.state.should.equal(1); // magic number from application.js
  15. });
  16. });
  17. describe('#set and get', function() {
  18. it('should play the role of normal set and get', function() {
  19. should.not.exist(app.get('some undefined key'));
  20. var key = 'some defined key', value = 'some value';
  21. app.set(key, value);
  22. value.should.equal(app.get(key));
  23. });
  24. it('should return the value if pass just one parameter to the set method', function() {
  25. var key = 'some defined key', value = 'some value';
  26. should.not.exist(app.set(key));
  27. app.set(key, value);
  28. value.should.equal(app.set(key));
  29. });
  30. });
  31. describe("#enable and disable", function() {
  32. it('should play the role of enable and disable', function() {
  33. var key = 'some enable key';
  34. app.enabled(key).should.be.false;
  35. app.disabled(key).should.be.true;
  36. app.enable(key);
  37. app.enabled(key).should.be.true;
  38. app.disabled(key).should.be.false;
  39. app.disable(key);
  40. app.enabled(key).should.be.false;
  41. app.disabled(key).should.be.true;
  42. });
  43. });
  44. describe("#compoent", function() {
  45. it('should load the component and fire their lifecircle callback by app.start, app.afterStart, app.stop', function(done) {
  46. var startCount = 0, afterStartCount = 0, stopCount = 0;
  47. var mockComponent = {
  48. start: function(cb) {
  49. console.log('start invoked');
  50. startCount++;
  51. cb();
  52. },
  53. afterStart: function(cb) {
  54. console.log('afterStart invoked');
  55. afterStartCount++;
  56. cb();
  57. },
  58. stop: function(force, cb) {
  59. console.log('stop invoked');
  60. stopCount++;
  61. cb();
  62. }
  63. };
  64. app.init({base: mockBase});
  65. app.load(mockComponent);
  66. app.start(function(err) {
  67. should.not.exist(err);
  68. });
  69. setTimeout(function() {
  70. // wait for after start
  71. app.stop(false);
  72. setTimeout(function() {
  73. // wait for stop
  74. startCount.should.equal(1);
  75. afterStartCount.should.equal(1);
  76. stopCount.should.equal(1);
  77. done();
  78. }, WAIT_TIME);
  79. }, WAIT_TIME);
  80. });
  81. it('should access the component with a name by app.components.name after loaded', function() {
  82. var key1 = 'key1', comp1 = {content: 'some thing in comp1'};
  83. var comp2 = {name: 'key2', content: 'some thing in comp2'};
  84. var key3 = 'key3';
  85. var comp3 = function() {
  86. return {content: 'some thing in comp3', name: key3};
  87. };
  88. app.init({base: mockBase});
  89. app.load(key1, comp1);
  90. app.load(comp2);
  91. app.load(comp3);
  92. app.components.key1.should.eql(comp1);
  93. app.components.key2.should.eql(comp2);
  94. app.components.key3.should.eql(comp3());
  95. });
  96. it('should ignore duplicated components', function() {
  97. var key = 'key';
  98. var comp1 = {content: 'some thing in comp1'};
  99. var comp2 = {content: 'some thing in comp2'};
  100. app.init({base: mockBase});
  101. app.load(key, comp1);
  102. app.load(key, comp2);
  103. app.components[key].should.eql(comp1);
  104. app.components[key].should.not.eql(comp2);
  105. });
  106. });
  107. describe('#filter', function() {
  108. it('should add before filter and could fetch it later', function() {
  109. var filters = [
  110. function() {console.error('filter1');},
  111. function() {}
  112. ];
  113. app.init({base: mockBase});
  114. var i, l;
  115. for(i=0, l=filters.length; i<l; i++) {
  116. app.before(filters[i]);
  117. }
  118. var filters2 = app.get('__befores__');
  119. should.exist(filters2);
  120. filters2.length.should.equal(filters.length);
  121. for(i=0, l=filters2.length; i<l; i++) {
  122. filters2[i].should.equal(filters[i]);
  123. }
  124. });
  125. it('should add after filter and could fetch it later', function() {
  126. var filters = [
  127. function() {console.error('filter1');},
  128. function() {}
  129. ];
  130. app.init({base: mockBase});
  131. var i, l;
  132. for(i=0, l=filters.length; i<l; i++) {
  133. app.after(filters[i]);
  134. }
  135. var filters2 = app.get('__afters__');
  136. should.exist(filters2);
  137. filters2.length.should.equal(filters.length);
  138. for(i=0, l=filters2.length; i<l; i++) {
  139. filters2[i].should.equal(filters[i]);
  140. }
  141. });
  142. it('should add filter and could fetch it from before and after filter later', function() {
  143. var filters = [
  144. function() {console.error('filter1');},
  145. function() {}
  146. ];
  147. app.init({base: mockBase});
  148. var i, l;
  149. for(i=0, l=filters.length; i<l; i++) {
  150. app.filter(filters[i]);
  151. }
  152. var filters2 = app.get('__befores__');
  153. should.exist(filters2);
  154. filters2.length.should.equal(filters.length);
  155. for(i=0, l=filters2.length; i<l; i++) {
  156. filters2[i].should.equal(filters[i]);
  157. }
  158. var filters3 = app.get('__afters__');
  159. should.exist(filters3);
  160. filters3.length.should.equal(filters.length);
  161. for(i=0, l=filters3.length; i<l; i++) {
  162. filters2[i].should.equal(filters[i]);
  163. }
  164. });
  165. });
  166. describe('#globalFilter', function() {
  167. it('should add before global filter and could fetch it later', function() {
  168. var filters = [
  169. function() {console.error('global filter1');},
  170. function() {}
  171. ];
  172. app.init({base: mockBase});
  173. var i, l;
  174. for(i=0, l=filters.length; i<l; i++) {
  175. app.globalBefore(filters[i]);
  176. }
  177. var filters2 = app.get('__globalBefores__');
  178. should.exist(filters2);
  179. filters2.length.should.equal(filters.length);
  180. for(i=0, l=filters2.length; i<l; i++) {
  181. filters2[i].should.equal(filters[i]);
  182. }
  183. });
  184. it('should add after global filter and could fetch it later', function() {
  185. var filters = [
  186. function() {console.error('filter1');},
  187. function() {}
  188. ];
  189. app.init({base: mockBase});
  190. var i, l;
  191. for(i=0, l=filters.length; i<l; i++) {
  192. app.globalAfter(filters[i]);
  193. }
  194. var filters2 = app.get('__globalAfters__');
  195. should.exist(filters2);
  196. filters2.length.should.equal(filters.length);
  197. for(i=0, l=filters2.length; i<l; i++) {
  198. filters2[i].should.equal(filters[i]);
  199. }
  200. });
  201. it('should add filter and could fetch it from before and after filter later', function() {
  202. var filters = [
  203. function() {console.error('filter1');},
  204. function() {}
  205. ];
  206. app.init({base: mockBase});
  207. var i, l;
  208. for(i=0, l=filters.length; i<l; i++) {
  209. app.globalFilter(filters[i]);
  210. }
  211. var filters2 = app.get('__globalBefores__');
  212. should.exist(filters2);
  213. filters2.length.should.equal(filters.length);
  214. for(i=0, l=filters2.length; i<l; i++) {
  215. filters2[i].should.equal(filters[i]);
  216. }
  217. var filters3 = app.get('__globalAfters__');
  218. should.exist(filters3);
  219. filters3.length.should.equal(filters.length);
  220. for(i=0, l=filters3.length; i<l; i++) {
  221. filters2[i].should.equal(filters[i]);
  222. }
  223. });
  224. });
  225. describe('#configure', function() {
  226. it('should execute the code block wtih the right environment', function() {
  227. var proCount = 0, devCount = 0;
  228. var proEnv = 'production', devEnv = 'development', serverType = 'server';
  229. app.init({base: mockBase});
  230. app.set('serverType', serverType);
  231. app.set('env', proEnv);
  232. app.configure(proEnv, serverType, function() {
  233. proCount++;
  234. });
  235. app.configure(devEnv, serverType, function() {
  236. devCount++;
  237. });
  238. app.set('env', devEnv);
  239. app.configure(proEnv, serverType, function() {
  240. proCount++;
  241. });
  242. app.configure(devEnv, serverType, function() {
  243. devCount++;
  244. });
  245. proCount.should.equal(1);
  246. devCount.should.equal(1);
  247. });
  248. it('should execute the code block wtih the right server', function() {
  249. var server1Count = 0, server2Count = 0;
  250. var proEnv = 'production', serverType1 = 'server1', serverType2 = 'server2';
  251. app.init({base: mockBase});
  252. app.set('serverType', serverType1);
  253. app.set('env', proEnv);
  254. app.configure(proEnv, serverType1, function() {
  255. server1Count++;
  256. });
  257. app.configure(proEnv, serverType2, function() {
  258. server2Count++;
  259. });
  260. app.set('serverType', serverType2);
  261. app.configure(proEnv, serverType1, function() {
  262. server1Count++;
  263. });
  264. app.configure(proEnv, serverType2, function() {
  265. server2Count++;
  266. });
  267. server1Count.should.equal(1);
  268. server2Count.should.equal(1);
  269. });
  270. });
  271. describe('#route', function() {
  272. it('should add route record and could fetch it later', function() {
  273. var type1 = 'area', type2 = 'connector';
  274. var func1 = function() {console.log('func1');};
  275. var func2 = function() {console.log('func2');};
  276. app.init({base: mockBase});
  277. app.route(type1, func1);
  278. app.route(type2, func2);
  279. var routes = app.get('__routes__');
  280. should.exist(routes);
  281. func1.should.equal(routes[type1]);
  282. func2.should.equal(routes[type2]);
  283. });
  284. });
  285. describe('#transaction', function() {
  286. it('should execute all conditions and handlers', function() {
  287. var conditions = {
  288. test1: function(cb) {
  289. console.log('condition1');
  290. cb();
  291. },
  292. test2: function(cb) {
  293. console.log('condition2');
  294. cb();
  295. }
  296. };
  297. var flag = 1;
  298. var handlers = {
  299. do1: function(cb) {
  300. console.log('handler1');
  301. cb();
  302. },
  303. do2: function(cb) {
  304. console.log('handler2');
  305. if(flag < 3){
  306. flag ++;
  307. cb(new Error('error'));
  308. } else {
  309. cb();
  310. }
  311. }
  312. };
  313. app.transaction('test', conditions, handlers, 5);
  314. });
  315. it('shoud execute conditions with error and do not execute handlers', function() {
  316. var conditions = {
  317. test1: function(cb) {
  318. console.log('condition1');
  319. cb();
  320. },
  321. test2: function(cb) {
  322. console.log('condition2');
  323. cb(new Error('error'));
  324. },
  325. test3: function(cb) {
  326. console.log('condition3');
  327. cb();
  328. }
  329. };
  330. var handlers = {
  331. do1: function(cb) {
  332. console.log('handler1');
  333. cb();
  334. },
  335. do2: function(cb) {
  336. console.log('handler2');
  337. cb();
  338. }
  339. };
  340. app.transaction('test', conditions, handlers);
  341. });
  342. });
  343. describe('#add and remove servers', function() {
  344. it('should add servers and emit event and fetch the new server info by get methods', function(done) {
  345. var newServers = [
  346. {id: 'connector-server-1', serverType: 'connecctor', host: '127.0.0.1', port: 1234, clientPort: 3000, frontend: true},
  347. {id: 'area-server-1', serverType: 'area', host: '127.0.0.1', port: 2234}
  348. ];
  349. app.init({base: mockBase});
  350. app.event.on(pomelo.events.ADD_SERVERS, function(servers) {
  351. // check event args
  352. newServers.should.eql(servers);
  353. // check servers
  354. var curServers = app.getServers();
  355. should.exist(curServers);
  356. var item, i, l;
  357. for(i=0, l=newServers.length; i<l; i++) {
  358. item = newServers[i];
  359. item.should.eql(curServers[item.id]);
  360. }
  361. // check get server by id
  362. for(i=0, l=newServers.length; i<l; i++) {
  363. item = newServers[i];
  364. item.should.eql(app.getServerById(item.id));
  365. }
  366. // check server types
  367. var types = [];
  368. for(i=0, l=newServers.length; i<l; i++) {
  369. item = newServers[i];
  370. if(types.indexOf(item.serverType) < 0) {
  371. types.push(item.serverType);
  372. }
  373. }
  374. var types2 = app.getServerTypes();
  375. types.length.should.equal(types2.length);
  376. for(i=0, l=types.length; i<l; i++) {
  377. types2.should.include(types[i]);
  378. }
  379. // check server type list
  380. var slist;
  381. for(i=0, l=newServers.length; i<l; i++) {
  382. item = newServers[i];
  383. slist = app.getServersByType(item.serverType);
  384. should.exist(slist);
  385. contains(slist, item).should.be.true;
  386. }
  387. done();
  388. });
  389. app.addServers(newServers);
  390. });
  391. it('should remove server info and emit event', function(done) {
  392. var newServers = [
  393. {id: 'connector-server-1', serverType: 'connecctor', host: '127.0.0.1', port: 1234, clientPort: 3000, frontend: true},
  394. {id: 'area-server-1', serverType: 'area', host: '127.0.0.1', port: 2234},
  395. {id: 'path-server-1', serverType: 'path', host: '127.0.0.1', port: 2235}
  396. ];
  397. var destServers = [
  398. {id: 'connector-server-1', serverType: 'connecctor', host: '127.0.0.1', port: 1234, clientPort: 3000, frontend: true},
  399. {id: 'path-server-1', serverType: 'path', host: '127.0.0.1', port: 2235}
  400. ];
  401. var delIds = ['area-server-1'];
  402. var addCount = 0;
  403. var delCount = 0;
  404. app.init({base: mockBase});
  405. app.event.on(pomelo.events.ADD_SERVERS, function(servers) {
  406. // check event args
  407. newServers.should.eql(servers);
  408. addCount++;
  409. });
  410. app.event.on(pomelo.events.REMOVE_SERVERS, function(ids) {
  411. delIds.should.eql(ids);
  412. // check servers
  413. var curServers = app.getServers();
  414. should.exist(curServers);
  415. var item, i, l;
  416. for(i=0, l=destServers.length; i<l; i++) {
  417. item = destServers[i];
  418. item.should.eql(curServers[item.id]);
  419. }
  420. // check get server by id
  421. for(i=0, l=destServers.length; i<l; i++) {
  422. item = destServers[i];
  423. item.should.eql(app.getServerById(item.id));
  424. }
  425. // check server types
  426. // NOTICE: server types would not clear when remove server from app
  427. var types = [];
  428. for(i=0, l=newServers.length; i<l; i++) {
  429. item = newServers[i];
  430. if(types.indexOf(item.serverType) < 0) {
  431. types.push(item.serverType);
  432. }
  433. }
  434. var types2 = app.getServerTypes();
  435. types.length.should.equal(types2.length);
  436. for(i=0, l=types.length; i<l; i++) {
  437. types2.should.include(types[i]);
  438. }
  439. // check server type list
  440. var slist;
  441. for(i=0, l=destServers.length; i<l; i++) {
  442. item = destServers[i];
  443. slist = app.getServersByType(item.serverType);
  444. should.exist(slist);
  445. contains(slist, item).should.be.true;
  446. }
  447. done();
  448. });
  449. app.addServers(newServers);
  450. app.removeServers(delIds);
  451. });
  452. });
  453. describe('#beforeStopHook', function() {
  454. it('should be called before application stopped.', function(done) {
  455. var count = 0;
  456. app.init({base: mockBase});
  457. app.beforeStopHook(function() {
  458. count++;
  459. });
  460. app.start(function(err) {
  461. should.not.exist(err);
  462. });
  463. setTimeout(function() {
  464. // wait for after start
  465. app.stop(false);
  466. setTimeout(function() {
  467. // wait for stop
  468. count.should.equal(1);
  469. done();
  470. }, WAIT_TIME);
  471. }, WAIT_TIME);
  472. });
  473. });
  474. describe('#use', function() {
  475. it('should exist plugin component and event', function(done) {
  476. var plugin = {
  477. components: mockBase + '/mock-plugin/components/',
  478. events: mockBase + '/mock-plugin/events/'
  479. };
  480. var opts = {};
  481. app.use(plugin, opts);
  482. should.exist(app.event.listeners('bind_session'));
  483. should.exist(app.components.mockPlugin);
  484. done();
  485. });
  486. });
  487. });
  488. var contains = function(slist, sinfo) {
  489. for(var i=0, l=slist.length; i<l; i++) {
  490. if(slist[i].id === sinfo.id) {
  491. return true;
  492. }
  493. }
  494. return false;
  495. };