PriorityQueue.test.js 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  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. for ( let i = 0; i < 7; i ++ ) {
  38. await nextFrame();
  39. }
  40. expect( result ).toEqual( [ 8, 6, 4, 3, 2, 1, 0 ] );
  41. expect( queue.items.length ).toEqual( queue.callbacks.size );
  42. } );
  43. it( 'should remove an item from the queue correctly.', () => {
  44. const A = { priority: 0 };
  45. const B = { priority: 1 };
  46. const C = { priority: 2 };
  47. const D = { priority: 3 };
  48. const queue = new PriorityQueue();
  49. queue.priorityCallback = item => item.priority;
  50. queue.add( A, () => new Promise( () => {} ) );
  51. queue.add( B, () => new Promise( () => {} ) );
  52. queue.add( C, () => new Promise( () => {} ) );
  53. queue.add( D, () => new Promise( () => {} ) );
  54. queue.sort();
  55. expect( queue.items ).toEqual( [ A, B, C, D ] );
  56. queue.remove( C );
  57. expect( queue.items ).toEqual( [ A, B, D ] );
  58. queue.remove( A );
  59. expect( queue.items ).toEqual( [ B, D ] );
  60. queue.remove( B );
  61. expect( queue.items ).toEqual( [ D ] );
  62. queue.remove( D );
  63. expect( queue.items ).toEqual( [] );
  64. expect( queue.items.length ).toEqual( queue.callbacks.size );
  65. } );
  66. it( 'should automatically run new jobs when one is finished.', async () => {
  67. let called = 0;
  68. let resolveFunc = null;
  69. const queue = new PriorityQueue();
  70. queue.maxJobs = 1;
  71. queue.priorityCallback = item => item.priority;
  72. queue.add( { priority: 1 }, () => new Promise( resolve => {
  73. resolveFunc = resolve;
  74. called ++;
  75. } ) );
  76. queue.add( { priority: 0 }, () => new Promise( () => {
  77. called ++;
  78. } ) );
  79. expect( queue.currJobs ).toEqual( 0 );
  80. await nextFrame();
  81. expect( queue.currJobs ).toEqual( 1 );
  82. expect( resolveFunc ).not.toEqual( null );
  83. expect( called ).toEqual( 1 );
  84. resolveFunc();
  85. await nextFrame();
  86. await nextFrame();
  87. expect( queue.currJobs ).toEqual( 1 );
  88. expect( called ).toEqual( 2 );
  89. } );
  90. it( 'should fire the callback with the item and priority.', async () => {
  91. const A = { priority: 100 };
  92. const queue = new PriorityQueue();
  93. queue.priorityCallback = item => item.priority;
  94. queue.add( A, item => new Promise( () => {
  95. expect( item ).toEqual( A );
  96. } ) );
  97. await nextFrame();
  98. } );
  99. it( 'should return a promise that resolves from the add function.', async () => {
  100. const queue = new PriorityQueue();
  101. queue.priorityCallback = item => item.priority;
  102. let result = null;
  103. queue.add( { priority: 0 }, item => Promise.resolve( 1000 ) ).then( res => result = res );
  104. expect( result ).toEqual( null );
  105. await nextFrame();
  106. expect( result ).toEqual( 1000 );
  107. } );
  108. it( 'should not automatically run if autoUpdate is false.', async () => {
  109. const queue = new PriorityQueue();
  110. queue.priorityCallback = () => 0;
  111. queue.autoUpdate = false;
  112. queue.maxJobs = 1;
  113. queue.add( {}, async () => {} );
  114. queue.add( {}, async () => {} );
  115. expect( queue.items ).toHaveLength( 2 );
  116. await nextFrame();
  117. expect( queue.items ).toHaveLength( 2 );
  118. queue.scheduleJobRun();
  119. await nextFrame();
  120. expect( queue.items ).toHaveLength( 1 );
  121. await nextFrame();
  122. expect( queue.items ).toHaveLength( 1 );
  123. queue.scheduleJobRun();
  124. await nextFrame();
  125. expect( queue.items ).toHaveLength( 0 );
  126. } );
  127. } );