Simple email application for Android. Original source code: https://framagit.org/dystopia-project/simple-email
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

620 lines
21 KiB

  1. var makeTest = require('./context')
  2. var Bottleneck = require('./bottleneck')
  3. var assert = require('assert')
  4. var child_process = require('child_process')
  5. describe('General', function () {
  6. var c
  7. afterEach(function () {
  8. return c.limiter.disconnect(false)
  9. })
  10. it('Should prompt to upgrade', function () {
  11. c = makeTest()
  12. try {
  13. var limiter = new Bottleneck(1, 250)
  14. } catch (err) {
  15. c.mustEqual(err.message, 'Bottleneck v2 takes a single object argument. Refer to https://github.com/SGrondin/bottleneck#upgrading-to-v2 if you\'re upgrading from Bottleneck v1.')
  16. }
  17. })
  18. describe('Counts and statuses', function () {
  19. it('Should check() and return the queued count with and without a priority value', function () {
  20. c = makeTest({maxConcurrent: 1, minTime: 100})
  21. return c.limiter.check()
  22. .then(function (willRunNow) {
  23. c.mustEqual(willRunNow, true)
  24. c.mustEqual(c.limiter.queued(), 0)
  25. return c.limiter.submit({id: 1}, c.slowJob, 50, null, 1, c.noErrVal(1))
  26. })
  27. .then(function () {
  28. c.mustEqual(c.limiter.queued(), 0) // It's already running
  29. return c.limiter.check()
  30. })
  31. .then(function (willRunNow) {
  32. c.mustEqual(willRunNow, false)
  33. return c.limiter.submit({id: 2}, c.slowJob, 50, null, 2, c.noErrVal(2))
  34. })
  35. .then(function () {
  36. c.mustEqual(c.limiter.queued(), 1)
  37. c.mustEqual(c.limiter.queued(1), 0)
  38. c.mustEqual(c.limiter.queued(5), 1)
  39. return c.limiter.submit({id: 3}, c.slowJob, 50, null, 3, c.noErrVal(3))
  40. })
  41. .then(function () {
  42. c.mustEqual(c.limiter.queued(), 2)
  43. c.mustEqual(c.limiter.queued(1), 0)
  44. c.mustEqual(c.limiter.queued(5), 2)
  45. return c.limiter.submit({id: 4}, c.slowJob, 50, null, 4, c.noErrVal(4))
  46. })
  47. .then(function () {
  48. c.mustEqual(c.limiter.queued(), 3)
  49. c.mustEqual(c.limiter.queued(1), 0)
  50. c.mustEqual(c.limiter.queued(5), 3)
  51. return c.limiter.submit({priority: 1, id: 5}, c.job, null, 5, c.noErrVal(5))
  52. })
  53. .then(function () {
  54. c.mustEqual(c.limiter.queued(), 4)
  55. c.mustEqual(c.limiter.queued(1), 1)
  56. c.mustEqual(c.limiter.queued(5), 3)
  57. return c.last()
  58. })
  59. .then(function (results) {
  60. c.mustEqual(c.limiter.queued(), 0)
  61. c.checkResultsOrder([[1], [5], [2], [3], [4]])
  62. c.checkDuration(450)
  63. })
  64. })
  65. it('Should return the running and done counts', function () {
  66. c = makeTest({maxConcurrent: 5, minTime: 0})
  67. return Promise.all([c.limiter.running(), c.limiter.done()])
  68. .then(function ([running, done]) {
  69. c.mustEqual(running, 0)
  70. c.mustEqual(done, 0)
  71. c.pNoErrVal(c.limiter.schedule({ weight: 1, id: 1 }, c.slowPromise, 100, null, 1), 1)
  72. c.pNoErrVal(c.limiter.schedule({ weight: 3, id: 2 }, c.slowPromise, 200, null, 2), 2)
  73. c.pNoErrVal(c.limiter.schedule({ weight: 1, id: 3 }, c.slowPromise, 100, null, 3), 3)
  74. return c.limiter.schedule({ weight: 0, id: 4 }, c.promise, null)
  75. })
  76. .then(function () {
  77. return Promise.all([c.limiter.running(), c.limiter.done()])
  78. })
  79. .then(function ([running, done]) {
  80. c.mustEqual(running, 5)
  81. c.mustEqual(done, 0)
  82. return c.wait(125)
  83. })
  84. .then(function () {
  85. return Promise.all([c.limiter.running(), c.limiter.done()])
  86. })
  87. .then(function ([running, done]) {
  88. c.mustEqual(running, 3)
  89. c.mustEqual(done, 2)
  90. return c.wait(100)
  91. })
  92. .then(function () {
  93. return Promise.all([c.limiter.running(), c.limiter.done()])
  94. })
  95. .then(function ([running, done]) {
  96. c.mustEqual(running, 0)
  97. c.mustEqual(done, 5)
  98. return c.last()
  99. })
  100. .then(function (results) {
  101. c.checkDuration(200)
  102. c.checkResultsOrder([[], [1], [3], [2]])
  103. })
  104. })
  105. it('Should reject duplicate Job IDs', function (done) {
  106. c = makeTest({maxConcurrent: 2, minTime: 100, trackDoneStatus: true})
  107. c.limiter.schedule({ id: 'a' }, c.promise, null, 1)
  108. .then(function () {
  109. return c.limiter.schedule({ id: 'b' }, c.promise, null, 2)
  110. })
  111. .then(function () {
  112. return c.limiter.schedule({ id: 'a' }, c.promise, null, 3)
  113. })
  114. .catch(function (e) {
  115. c.mustEqual(e.message, 'A job with the same id already exists (id=a)')
  116. done()
  117. })
  118. })
  119. it('Should return job statuses', function () {
  120. c = makeTest({maxConcurrent: 2, minTime: 100})
  121. c.mustEqual(c.limiter.counts(), { RECEIVED: 0, QUEUED: 0, RUNNING: 0, EXECUTING: 0 })
  122. c.pNoErrVal(c.limiter.schedule({ weight: 1, id: 1 }, c.slowPromise, 100, null, 1), 1)
  123. c.pNoErrVal(c.limiter.schedule({ weight: 1, id: 2 }, c.slowPromise, 200, null, 2), 2)
  124. c.pNoErrVal(c.limiter.schedule({ weight: 2, id: 3 }, c.slowPromise, 100, null, 3), 3)
  125. c.mustEqual(c.limiter.counts(), { RECEIVED: 3, QUEUED: 0, RUNNING: 0, EXECUTING: 0 })
  126. return c.wait(50)
  127. .then(function () {
  128. c.mustEqual(c.limiter.counts(), { RECEIVED: 0, QUEUED: 1, RUNNING: 1, EXECUTING: 1 })
  129. c.mustEqual(c.limiter.jobStatus(1), 'EXECUTING')
  130. c.mustEqual(c.limiter.jobStatus(2), 'RUNNING')
  131. c.mustEqual(c.limiter.jobStatus(3), 'QUEUED')
  132. return c.last()
  133. })
  134. .then(function (results) {
  135. c.checkDuration(400)
  136. c.checkResultsOrder([[1], [2], [3]])
  137. })
  138. })
  139. it('Should return job statuses, including DONE', function () {
  140. c = makeTest({maxConcurrent: 2, minTime: 100, trackDoneStatus: true})
  141. c.mustEqual(c.limiter.counts(), { RECEIVED: 0, QUEUED: 0, RUNNING: 0, EXECUTING: 0, DONE: 0 })
  142. c.pNoErrVal(c.limiter.schedule({ weight: 1, id: 1 }, c.slowPromise, 100, null, 1), 1)
  143. c.pNoErrVal(c.limiter.schedule({ weight: 1, id: 2 }, c.slowPromise, 200, null, 2), 2)
  144. c.pNoErrVal(c.limiter.schedule({ weight: 2, id: 3 }, c.slowPromise, 100, null, 3), 3)
  145. c.mustEqual(c.limiter.counts(), { RECEIVED: 3, QUEUED: 0, RUNNING: 0, EXECUTING: 0, DONE: 0 })
  146. return c.wait(50)
  147. .then(function () {
  148. c.mustEqual(c.limiter.counts(), { RECEIVED: 0, QUEUED: 1, RUNNING: 1, EXECUTING: 1, DONE: 0 })
  149. c.mustEqual(c.limiter.jobStatus(1), 'EXECUTING')
  150. c.mustEqual(c.limiter.jobStatus(2), 'RUNNING')
  151. c.mustEqual(c.limiter.jobStatus(3), 'QUEUED')
  152. return c.wait(100)
  153. })
  154. .then(function () {
  155. c.mustEqual(c.limiter.counts(), { RECEIVED: 0, QUEUED: 1, RUNNING: 0, EXECUTING: 1, DONE: 1 })
  156. c.mustEqual(c.limiter.jobStatus(1), 'DONE')
  157. c.mustEqual(c.limiter.jobStatus(2), 'EXECUTING')
  158. c.mustEqual(c.limiter.jobStatus(3), 'QUEUED')
  159. return c.last()
  160. })
  161. .then(function (results) {
  162. c.mustEqual(c.limiter.counts(), { RECEIVED: 0, QUEUED: 0, RUNNING: 0, EXECUTING: 0, DONE: 4 })
  163. c.checkDuration(400)
  164. c.checkResultsOrder([[1], [2], [3]])
  165. })
  166. })
  167. it('Should return jobs for a status', function () {
  168. c = makeTest({maxConcurrent: 2, minTime: 100, trackDoneStatus: true})
  169. c.mustEqual(c.limiter.counts(), { RECEIVED: 0, QUEUED: 0, RUNNING: 0, EXECUTING: 0, DONE: 0 })
  170. c.pNoErrVal(c.limiter.schedule({ weight: 1, id: 1 }, c.slowPromise, 100, null, 1), 1)
  171. c.pNoErrVal(c.limiter.schedule({ weight: 1, id: 2 }, c.slowPromise, 200, null, 2), 2)
  172. c.pNoErrVal(c.limiter.schedule({ weight: 2, id: 3 }, c.slowPromise, 100, null, 3), 3)
  173. c.mustEqual(c.limiter.counts(), { RECEIVED: 3, QUEUED: 0, RUNNING: 0, EXECUTING: 0, DONE: 0 })
  174. c.mustEqual(c.limiter.jobs(), ['1', '2', '3'])
  175. c.mustEqual(c.limiter.jobs('RECEIVED'), ['1', '2', '3'])
  176. return c.wait(50)
  177. .then(function () {
  178. c.mustEqual(c.limiter.counts(), { RECEIVED: 0, QUEUED: 1, RUNNING: 1, EXECUTING: 1, DONE: 0 })
  179. c.mustEqual(c.limiter.jobs('EXECUTING'), ['1'])
  180. c.mustEqual(c.limiter.jobs('RUNNING'), ['2'])
  181. c.mustEqual(c.limiter.jobs('QUEUED'), ['3'])
  182. return c.wait(100)
  183. })
  184. .then(function () {
  185. c.mustEqual(c.limiter.counts(), { RECEIVED: 0, QUEUED: 1, RUNNING: 0, EXECUTING: 1, DONE: 1 })
  186. c.mustEqual(c.limiter.jobs('DONE'), ['1'])
  187. c.mustEqual(c.limiter.jobs('EXECUTING'), ['2'])
  188. c.mustEqual(c.limiter.jobs('QUEUED'), ['3'])
  189. return c.last()
  190. })
  191. .then(function (results) {
  192. c.mustEqual(c.limiter.counts(), { RECEIVED: 0, QUEUED: 0, RUNNING: 0, EXECUTING: 0, DONE: 4 })
  193. c.checkDuration(400)
  194. c.checkResultsOrder([[1], [2], [3]])
  195. })
  196. })
  197. })
  198. describe('Events', function () {
  199. it('Should return itself', function () {
  200. c = makeTest({ id: 'test-limiter' })
  201. var returned = c.limiter.on('ready', function () { })
  202. c.mustEqual(returned.id, 'test-limiter')
  203. })
  204. it('Should fire events on empty queue', function () {
  205. c = makeTest({maxConcurrent: 1, minTime: 100})
  206. var calledEmpty = 0
  207. var calledIdle = 0
  208. var calledDepleted = 0
  209. c.limiter.on('empty', function () { calledEmpty++ })
  210. c.limiter.on('idle', function () { calledIdle++ })
  211. c.limiter.on('depleted', function () { calledDepleted++ })
  212. return c.pNoErrVal(c.limiter.schedule({id: 1}, c.slowPromise, 50, null, 1), 1)
  213. .then(function () {
  214. c.mustEqual(calledEmpty, 1)
  215. c.mustEqual(calledIdle, 1)
  216. return Promise.all([
  217. c.pNoErrVal(c.limiter.schedule({id: 2}, c.slowPromise, 50, null, 2), 2),
  218. c.pNoErrVal(c.limiter.schedule({id: 3}, c.slowPromise, 50, null, 3), 3)
  219. ])
  220. })
  221. .then(function () {
  222. return c.limiter.submit({id: 4}, c.slowJob, 50, null, 4, null)
  223. })
  224. .then(function () {
  225. c.checkDuration(250)
  226. c.checkResultsOrder([[1], [2], [3]])
  227. c.mustEqual(calledEmpty, 3)
  228. c.mustEqual(calledIdle, 2)
  229. c.mustEqual(calledDepleted, 0)
  230. return c.last()
  231. })
  232. })
  233. it('Should fire events once', function () {
  234. c = makeTest({maxConcurrent: 1, minTime: 100})
  235. var calledEmptyOnce = 0
  236. var calledIdleOnce = 0
  237. var calledEmpty = 0
  238. var calledIdle = 0
  239. var calledDepleted = 0
  240. c.limiter.once('empty', function () { calledEmptyOnce++ })
  241. c.limiter.once('idle', function () { calledIdleOnce++ })
  242. c.limiter.on('empty', function () { calledEmpty++ })
  243. c.limiter.on('idle', function () { calledIdle++ })
  244. c.limiter.on('depleted', function () { calledDepleted++ })
  245. c.pNoErrVal(c.limiter.schedule(c.slowPromise, 50, null, 1), 1)
  246. return c.pNoErrVal(c.limiter.schedule(c.promise, null, 2), 2)
  247. .then(function () {
  248. c.mustEqual(calledEmptyOnce, 1)
  249. c.mustEqual(calledIdleOnce, 1)
  250. c.mustEqual(calledEmpty, 1)
  251. c.mustEqual(calledIdle, 1)
  252. return c.pNoErrVal(c.limiter.schedule(c.promise, null, 3), 3)
  253. })
  254. .then(function () {
  255. c.checkDuration(200)
  256. c.checkResultsOrder([[1], [2], [3]])
  257. c.mustEqual(calledEmptyOnce, 1)
  258. c.mustEqual(calledIdleOnce, 1)
  259. c.mustEqual(calledEmpty, 2)
  260. c.mustEqual(calledIdle, 2)
  261. c.mustEqual(calledDepleted, 0)
  262. })
  263. })
  264. it('Should support faulty event listeners', function (done) {
  265. c = makeTest({maxConcurrent: 1, minTime: 100, errorEventsExpected: true})
  266. var calledError = 0
  267. c.limiter.on('error', function (err) {
  268. calledError++
  269. if (err.message === 'Oh noes!' && calledError === 1) {
  270. done()
  271. }
  272. })
  273. c.limiter.on('empty', function () {
  274. throw new Error('Oh noes!')
  275. })
  276. c.pNoErrVal(c.limiter.schedule(c.promise, null, 1), 1)
  277. })
  278. it('Should wait for async event listeners', function (done) {
  279. c = makeTest({maxConcurrent: 1, minTime: 100, errorEventsExpected: true})
  280. var calledError = 0
  281. c.limiter.on('error', function (err) {
  282. calledError++
  283. if (err.message === 'It broke!' && calledError === 1) {
  284. done()
  285. }
  286. })
  287. c.limiter.on('empty', function () {
  288. return c.slowPromise(100, null, 1, 2)
  289. .then(function (x) {
  290. c.mustEqual(x, [1, 2])
  291. return Promise.reject(new Error('It broke!'))
  292. })
  293. })
  294. c.pNoErrVal(c.limiter.schedule(c.promise, null, 1), 1)
  295. })
  296. })
  297. describe('High water limit', function () {
  298. it('Should support highWater set to 0', function () {
  299. c = makeTest({maxConcurrent: 1, minTime: 0, highWater: 0, rejectOnDrop: false})
  300. var first = c.pNoErrVal(c.limiter.schedule(c.slowPromise, 50, null, 1), 1)
  301. c.pNoErrVal(c.limiter.schedule(c.slowPromise, 50, null, 2), 2)
  302. c.pNoErrVal(c.limiter.schedule(c.slowPromise, 50, null, 3), 3)
  303. c.pNoErrVal(c.limiter.schedule(c.slowPromise, 50, null, 4), 4)
  304. return first
  305. .then(function () {
  306. return c.last({ weight: 0 })
  307. })
  308. .then(function (results) {
  309. c.checkDuration(50)
  310. c.checkResultsOrder([[1]])
  311. })
  312. })
  313. it('Should support highWater set to 1', function () {
  314. c = makeTest({maxConcurrent: 1, minTime: 0, highWater: 1, rejectOnDrop: false})
  315. var first = c.pNoErrVal(c.limiter.schedule(c.slowPromise, 50, null, 1), 1)
  316. c.pNoErrVal(c.limiter.schedule(c.slowPromise, 50, null, 2), 2)
  317. c.pNoErrVal(c.limiter.schedule(c.slowPromise, 50, null, 3), 3)
  318. var last = c.pNoErrVal(c.limiter.schedule(c.slowPromise, 50, null, 4), 4)
  319. return Promise.all([first, last])
  320. .then(function () {
  321. return c.last({ weight: 0 })
  322. })
  323. .then(function (results) {
  324. c.checkDuration(100)
  325. c.checkResultsOrder([[1], [4]])
  326. })
  327. })
  328. })
  329. describe('Weight', function () {
  330. it('Should not add jobs with a weight above the maxConcurrent', function () {
  331. c = makeTest({maxConcurrent: 2})
  332. c.pNoErrVal(c.limiter.schedule({ weight: 1 }, c.promise, null, 1), 1)
  333. c.pNoErrVal(c.limiter.schedule({ weight: 2 }, c.promise, null, 2), 2)
  334. return c.limiter.schedule({ weight: 3 }, c.promise, null, 3)
  335. .catch(function (err) {
  336. c.mustEqual(err.message, 'Impossible to add a job having a weight of 3 to a limiter having a maxConcurrent setting of 2')
  337. return c.last()
  338. })
  339. .then(function (results) {
  340. c.checkDuration(0)
  341. c.checkResultsOrder([[1], [2]])
  342. })
  343. })
  344. it('Should support custom job weights', function () {
  345. c = makeTest({maxConcurrent: 2})
  346. c.pNoErrVal(c.limiter.schedule({ weight: 1 }, c.slowPromise, 100, null, 1), 1)
  347. c.pNoErrVal(c.limiter.schedule({ weight: 2 }, c.slowPromise, 200, null, 2), 2)
  348. c.pNoErrVal(c.limiter.schedule({ weight: 1 }, c.slowPromise, 100, null, 3), 3)
  349. c.pNoErrVal(c.limiter.schedule({ weight: 1 }, c.slowPromise, 100, null, 4), 4)
  350. c.pNoErrVal(c.limiter.schedule({ weight: 0 }, c.slowPromise, 100, null, 5), 5)
  351. return c.last()
  352. .then(function (results) {
  353. c.checkDuration(400)
  354. c.checkResultsOrder([[1], [2], [3], [4], [5]])
  355. })
  356. })
  357. it('Should overflow at the correct rate', function () {
  358. c = makeTest({
  359. maxConcurrent: 2,
  360. reservoir: 3
  361. })
  362. var calledDepleted = 0
  363. var emptyArguments = []
  364. c.limiter.on('depleted', function (empty) {
  365. emptyArguments.push(empty)
  366. calledDepleted++
  367. })
  368. var p1 = c.pNoErrVal(c.limiter.schedule({ weight: 1, id: 1 }, c.slowPromise, 100, null, 1), 1)
  369. var p2 = c.pNoErrVal(c.limiter.schedule({ weight: 2, id: 2 }, c.slowPromise, 150, null, 2), 2)
  370. var p3 = c.pNoErrVal(c.limiter.schedule({ weight: 1, id: 3 }, c.slowPromise, 100, null, 3), 3)
  371. var p4 = c.pNoErrVal(c.limiter.schedule({ weight: 1, id: 4 }, c.slowPromise, 100, null, 4), 4)
  372. return Promise.all([p1, p2])
  373. .then(function () {
  374. c.mustEqual(c.limiter.queued(), 2)
  375. return c.limiter.currentReservoir()
  376. })
  377. .then(function (reservoir) {
  378. c.mustEqual(reservoir, 0)
  379. c.mustEqual(calledDepleted, 1)
  380. return c.limiter.incrementReservoir(1)
  381. })
  382. .then(function (reservoir) {
  383. c.mustEqual(reservoir, 1)
  384. return c.last({ priority: 1, weight: 0 })
  385. })
  386. .then(function (results) {
  387. c.mustEqual(calledDepleted, 3)
  388. c.mustEqual(c.limiter.queued(), 1)
  389. c.checkDuration(250)
  390. c.checkResultsOrder([[1], [2]])
  391. return c.limiter.currentReservoir()
  392. })
  393. .then(function (reservoir) {
  394. c.mustEqual(reservoir, 0)
  395. return c.limiter.updateSettings({ reservoir: 1 })
  396. })
  397. .then(function () {
  398. return Promise.all([p3, p4])
  399. })
  400. .then(function () {
  401. return c.limiter.currentReservoir()
  402. })
  403. .then(function (reservoir) {
  404. c.mustEqual(reservoir, 0)
  405. c.mustEqual(calledDepleted, 4)
  406. c.mustEqual(emptyArguments, [false, false, false, true])
  407. })
  408. })
  409. })
  410. describe('Expiration', function () {
  411. it('Should cancel jobs', function () {
  412. c = makeTest({ maxConcurrent: 2 })
  413. var t0 = Date.now()
  414. return Promise.all([
  415. c.pNoErrVal(c.limiter.schedule(c.slowPromise, 150, null, 1), 1),
  416. c.limiter.schedule({ expiration: 50 }, c.slowPromise, 75, null, 2)
  417. .then(function () {
  418. return Promise.reject(new Error("Should have timed out."))
  419. })
  420. .catch(function (err) {
  421. c.mustEqual(err.message, 'This job timed out after 50 ms.')
  422. var duration = Date.now() - t0
  423. assert(duration > 45 && duration < 80)
  424. return Promise.all([c.limiter.running(), c.limiter.done()])
  425. })
  426. .then(function ([running, done]) {
  427. c.mustEqual(running, 1)
  428. c.mustEqual(done, 1)
  429. })
  430. ])
  431. .then(function () {
  432. var duration = Date.now() - t0
  433. assert(duration > 145 && duration < 180)
  434. return Promise.all([c.limiter.running(), c.limiter.done()])
  435. })
  436. .then(function ([running, done]) {
  437. c.mustEqual(running, 0)
  438. c.mustEqual(done, 2)
  439. })
  440. })
  441. })
  442. describe('Pubsub', function () {
  443. it('Should pass strings', function (done) {
  444. c = makeTest({ maxConcurrent: 2 })
  445. c.limiter.on('message', function (msg) {
  446. c.mustEqual(msg, 'hello')
  447. done()
  448. })
  449. c.limiter.publish('hello')
  450. })
  451. it('Should pass objects', function (done) {
  452. c = makeTest({ maxConcurrent: 2 })
  453. var obj = {
  454. array: ['abc', true],
  455. num: 235.59
  456. }
  457. c.limiter.on('message', function (msg) {
  458. c.mustEqual(JSON.parse(msg), obj)
  459. done()
  460. })
  461. c.limiter.publish(JSON.stringify(obj))
  462. })
  463. })
  464. describe('Refresh', function () {
  465. it('Should auto-refresh the reservoir', function () {
  466. c = makeTest({
  467. reservoir: 8,
  468. reservoirRefreshInterval: 150,
  469. reservoirRefreshAmount: 5,
  470. heartbeatInterval: 75 // not for production use
  471. })
  472. var calledDepleted = 0
  473. c.limiter.on('depleted', function () {
  474. calledDepleted++
  475. })
  476. return Promise.all([
  477. c.pNoErrVal(c.limiter.schedule({ weight: 1 }, c.promise, null, 1), 1),
  478. c.pNoErrVal(c.limiter.schedule({ weight: 2 }, c.promise, null, 2), 2),
  479. c.pNoErrVal(c.limiter.schedule({ weight: 3 }, c.promise, null, 3), 3),
  480. c.pNoErrVal(c.limiter.schedule({ weight: 4 }, c.promise, null, 4), 4),
  481. c.pNoErrVal(c.limiter.schedule({ weight: 5 }, c.promise, null, 5), 5)
  482. ])
  483. .then(function () {
  484. return c.limiter.currentReservoir()
  485. })
  486. .then(function (reservoir) {
  487. c.mustEqual(reservoir, 0)
  488. return c.last({ weight: 0, priority: 9 })
  489. })
  490. .then(function (results) {
  491. c.checkResultsOrder([[1], [2], [3], [4], [5]])
  492. c.mustEqual(calledDepleted, 2)
  493. c.checkDuration(300)
  494. })
  495. })
  496. it('Should allow staggered X by Y type usage', function () {
  497. c = makeTest({
  498. reservoir: 2,
  499. reservoirRefreshInterval: 150,
  500. reservoirRefreshAmount: 2,
  501. heartbeatInterval: 75 // not for production use
  502. })
  503. return Promise.all([
  504. c.pNoErrVal(c.limiter.schedule(c.promise, null, 1), 1),
  505. c.pNoErrVal(c.limiter.schedule(c.promise, null, 2), 2),
  506. c.pNoErrVal(c.limiter.schedule(c.promise, null, 3), 3),
  507. c.pNoErrVal(c.limiter.schedule(c.promise, null, 4), 4)
  508. ])
  509. .then(function () {
  510. return c.limiter.currentReservoir()
  511. })
  512. .then(function (reservoir) {
  513. c.mustEqual(reservoir, 0)
  514. return c.last({ weight: 0, priority: 9 })
  515. })
  516. .then(function (results) {
  517. c.checkResultsOrder([[1], [2], [3], [4]])
  518. c.checkDuration(150)
  519. })
  520. })
  521. it('Should keep process alive until queue is empty', function (done) {
  522. c = makeTest()
  523. var options = {
  524. cwd: process.cwd() + '/test/spawn',
  525. timeout: 1000
  526. }
  527. child_process.exec('node ref.js', options, function (err, stdout, stderr) {
  528. c.mustEqual(stdout, '[0][0][2][2]')
  529. c.mustEqual(stderr, '')
  530. done(err)
  531. })
  532. })
  533. })
  534. })