PriorityQueue.test.js 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. import { PriorityQueue } from '../src/utilities/PriorityQueue.js';
  2. const nextFrame = () => new Promise( resolve => requestAnimationFrame( resolve ) );
  3. const nextTick = () => new Promise( resolve => process.nextTick( resolve ) );
  4. describe( 'PriorityQueue', () => {
  5. it( 'should run jobs automatically in the correct order.', async () => {
  6. const queue = new PriorityQueue();
  7. queue.maxJobs = 6;
  8. queue.priorityCallback = item => item.priority;
  9. queue.add( { priority: 6 }, () => new Promise( () => {} ) );
  10. queue.add( { priority: 3 }, () => new Promise( () => {} ) );
  11. queue.add( { priority: 4 }, () => new Promise( () => {} ) );
  12. queue.add( { priority: 0 }, () => new Promise( () => {} ) );
  13. queue.add( { priority: 8 }, () => new Promise( () => {} ) );
  14. queue.add( { priority: 2 }, () => new Promise( () => {} ) );
  15. queue.add( { priority: 1 }, () => new Promise( () => {} ) );
  16. await nextFrame();
  17. expect( queue.items.map( item => item.priority ) ).toEqual( [ 0 ] );
  18. expect( queue.currJobs ).toEqual( 6 );
  19. } );
  20. it( 'should run jobs in the correct order.', async () => {
  21. const result = [];
  22. const cb = item => new Promise( resolve => {
  23. result.push( item.priority );
  24. resolve();
  25. } );
  26. const queue = new PriorityQueue();
  27. queue.maxJobs = 1;
  28. queue.priorityCallback = item => item.priority;
  29. queue.add( { priority: 6 }, cb );
  30. queue.add( { priority: 3 }, cb );
  31. queue.add( { priority: 4 }, cb );
  32. queue.add( { priority: 0 }, cb );
  33. queue.add( { priority: 8 }, cb );
  34. queue.add( { priority: 2 }, cb );
  35. queue.add( { priority: 1 }, cb );
  36. expect( queue.items.length ).toEqual( queue.callbacks.size );
  37. await nextFrame();
  38. await nextFrame();
  39. expect( result ).toEqual( [ 8, 6, 4, 3, 2, 1, 0 ] );
  40. expect( queue.items.length ).toEqual( queue.callbacks.size );
  41. } );
  42. it( 'should remove an item from the queue correctly.', () => {
  43. const A = { priority: 0 };
  44. const B = { priority: 1 };
  45. const C = { priority: 2 };
  46. const D = { priority: 3 };
  47. const queue = new PriorityQueue();
  48. queue.priorityCallback = item => item.priority;
  49. queue.add( A, () => new Promise( () => {} ) );
  50. queue.add( B, () => new Promise( () => {} ) );
  51. queue.add( C, () => new Promise( () => {} ) );
  52. queue.add( D, () => new Promise( () => {} ) );
  53. queue.sort();
  54. expect( queue.items ).toEqual( [ A, B, C, D ] );
  55. queue.remove( C );
  56. expect( queue.items ).toEqual( [ A, B, D ] );
  57. queue.remove( A );
  58. expect( queue.items ).toEqual( [ B, D ] );
  59. queue.remove( B );
  60. expect( queue.items ).toEqual( [ D ] );
  61. queue.remove( D );
  62. expect( queue.items ).toEqual( [] );
  63. expect( queue.items.length ).toEqual( queue.callbacks.size );
  64. } );
  65. it( 'should automatically run new jobs when one is finished.', async () => {
  66. let called = 0;
  67. let resolveFunc = null;
  68. const queue = new PriorityQueue();
  69. queue.maxJobs = 1;
  70. queue.priorityCallback = item => item.priority;
  71. queue.add( { priority: 1 }, () => new Promise( resolve => {
  72. resolveFunc = resolve;
  73. called ++;
  74. } ) );
  75. queue.add( { priority: 0 }, () => new Promise( () => {
  76. called ++;
  77. } ) );
  78. expect( queue.currJobs ).toEqual( 0 );
  79. await nextFrame();
  80. expect( queue.currJobs ).toEqual( 1 );
  81. expect( resolveFunc ).not.toEqual( null );
  82. expect( called ).toEqual( 1 );
  83. resolveFunc();
  84. await nextFrame();
  85. await nextFrame();
  86. expect( queue.currJobs ).toEqual( 1 );
  87. expect( called ).toEqual( 2 );
  88. } );
  89. it( 'should fire the callback with the item and priority.', async () => {
  90. const A = { priority: 100 };
  91. const queue = new PriorityQueue();
  92. queue.priorityCallback = item => item.priority;
  93. queue.add( A, item => new Promise( () => {
  94. expect( item ).toEqual( A );
  95. } ) );
  96. await nextFrame();
  97. } );
  98. it( 'should return a promise that resolves from the add function.', async () => {
  99. const queue = new PriorityQueue();
  100. queue.priorityCallback = item => item.priority;
  101. let result = null;
  102. queue.add( { priority: 0 }, item => Promise.resolve( 1000 ) ).then( res => result = res );
  103. expect( result ).toEqual( null );
  104. await nextFrame();
  105. expect( result ).toEqual( 1000 );
  106. } );
  107. it( 'should not automatically run if autoUpdate is false.', async () => {
  108. const queue = new PriorityQueue();
  109. queue.priorityCallback = () => 0;
  110. queue.autoUpdate = false;
  111. queue.maxJobs = 1;
  112. queue.add( {}, async () => {} );
  113. queue.add( {}, async () => {} );
  114. expect( queue.items ).toHaveLength( 2 );
  115. await nextFrame();
  116. expect( queue.items ).toHaveLength( 2 );
  117. queue.scheduleJobRun();
  118. await nextFrame();
  119. expect( queue.items ).toHaveLength( 1 );
  120. await nextFrame();
  121. expect( queue.items ).toHaveLength( 1 );
  122. queue.scheduleJobRun();
  123. await nextFrame();
  124. expect( queue.items ).toHaveLength( 0 );
  125. } );
  126. } );