Fifo.vala 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. using Invercargill;
  2. using Invercargill.DataStructures;
  3. void fifo_tests() {
  4. Test.add_func("/invercargill/fifo/basic_push_pop", () => {
  5. var fifo = new Fifo<string>();
  6. // Push items
  7. fifo.push("first");
  8. fifo.push("second");
  9. fifo.push("third");
  10. // Pop in insertion order (FIFO)
  11. var first = fifo.pop();
  12. var second = fifo.pop();
  13. var third = fifo.pop();
  14. assert_cmpstr("first", CompareOperator.EQ, first);
  15. assert_cmpstr("second", CompareOperator.EQ, second);
  16. assert_cmpstr("third", CompareOperator.EQ, third);
  17. });
  18. Test.add_func("/invercargill/fifo/peek functionality", () => {
  19. var fifo = new Fifo<int>();
  20. fifo.push(1);
  21. fifo.push(2);
  22. fifo.push(3);
  23. // Peek should return front item without removing
  24. var front = fifo.peek();
  25. assert_cmpint(1, CompareOperator.EQ, front);
  26. // Pop should still return 1
  27. var popped = fifo.pop();
  28. assert_cmpint(1, CompareOperator.EQ, popped);
  29. // Peek now should return 2
  30. var new_front = fifo.peek();
  31. assert_cmpint(2, CompareOperator.EQ, new_front);
  32. });
  33. Test.add_func("/invercargill/fifo/empty_fifo_behavior", () => {
  34. // Test peek on empty fifo
  35. var fifo1 = new Fifo<string>();
  36. try {
  37. fifo1.peek();
  38. assert_not_reached();
  39. }
  40. catch (SequenceError e) {
  41. assert_cmpstr("No elements in queue", CompareOperator.EQ, e.message);
  42. }
  43. // Test pop on empty fifo - need to unblock first
  44. var fifo2 = new Fifo<string>();
  45. fifo2.unblock();
  46. try {
  47. fifo2.pop();
  48. assert_not_reached();
  49. }
  50. catch (SequenceError e) {
  51. assert_cmpstr("No elements in unblocked queue to pop", CompareOperator.EQ, e.message);
  52. }
  53. });
  54. Test.add_func("/invercargill/fifo/push_all", () => {
  55. var fifo = new Fifo<int>();
  56. var items = new Series<int>();
  57. items.add(1);
  58. items.add(2);
  59. items.add(3);
  60. // Push all items
  61. fifo.push_all(items);
  62. // Should pop in insertion order
  63. assert_cmpint(1, CompareOperator.EQ, fifo.pop());
  64. assert_cmpint(2, CompareOperator.EQ, fifo.pop());
  65. assert_cmpint(3, CompareOperator.EQ, fifo.pop());
  66. });
  67. Test.add_func("/invercargill/fifo/enumerable_behavior", () => {
  68. var fifo = new Fifo<string>();
  69. fifo.push("first");
  70. fifo.push("second");
  71. fifo.push("third");
  72. // Iteration should return items in FIFO order
  73. var tracker = fifo.get_tracker();
  74. var items = new string[3];
  75. var index = 0;
  76. while (tracker.has_next()) {
  77. items[index++] = tracker.get_next();
  78. }
  79. assert_cmpstr("first", CompareOperator.EQ, items[0]);
  80. assert_cmpstr("second", CompareOperator.EQ, items[1]);
  81. assert_cmpstr("third", CompareOperator.EQ, items[2]);
  82. });
  83. Test.add_func("/invercargill/fifo/count_and_iteration", () => {
  84. var fifo = new Fifo<int>();
  85. // Empty fifo
  86. assert_cmpint(0, CompareOperator.EQ, fifo.count());
  87. // Add items
  88. fifo.push(1);
  89. fifo.push(2);
  90. fifo.push(3);
  91. assert_cmpint(3, CompareOperator.EQ, fifo.count());
  92. // Pop items
  93. fifo.pop();
  94. assert_cmpint(2, CompareOperator.EQ, fifo.count());
  95. fifo.pop();
  96. assert_cmpint(1, CompareOperator.EQ, fifo.count());
  97. fifo.pop();
  98. assert_cmpint(0, CompareOperator.EQ, fifo.count());
  99. // Unblock to prevent blocking on any future operations
  100. fifo.unblock();
  101. });
  102. Test.add_func("/invercargill/fifo/blocking_behavior", () => {
  103. var fifo = new Fifo<string>();
  104. bool thread_started = false;
  105. bool thread_finished = false;
  106. // Start a thread that will wait for an item
  107. Thread<void*> thread = new Thread<void*>("test-thread", () => {
  108. thread_started = true;
  109. var item = fifo.pop();
  110. assert_cmpstr("test_item", CompareOperator.EQ, item);
  111. thread_finished = true;
  112. return null;
  113. });
  114. // Wait for thread to start and block
  115. while (!thread_started) {
  116. Thread.usleep(1000); // 1ms
  117. }
  118. // Give additional time for thread to block on pop()
  119. Thread.usleep(50000); // 50ms
  120. // Push an item to unblock the thread
  121. fifo.push("test_item");
  122. // Wait for thread to finish
  123. thread.join();
  124. assert_true(thread_finished);
  125. });
  126. Test.add_func("/invercargill/fifo/unblock_behavior", () => {
  127. var fifo = new Fifo<int>();
  128. bool thread_started = false;
  129. bool exception_thrown = false;
  130. // Start a thread that will wait for an item
  131. Thread<void*> thread = new Thread<void*>("test-thread", () => {
  132. thread_started = true;
  133. try {
  134. var item = fifo.pop(); // This should throw after unblock
  135. assert_not_reached();
  136. }
  137. catch (SequenceError e) {
  138. assert_cmpstr("No elements in unblocked queue to pop", CompareOperator.EQ, e.message);
  139. exception_thrown = true;
  140. }
  141. return null;
  142. });
  143. // Wait for thread to start and block
  144. while (!thread_started) {
  145. Thread.usleep(1000); // 1ms
  146. }
  147. // Give additional time for thread to block on pop()
  148. Thread.usleep(50000); // 50ms
  149. // Unblock the fifo
  150. fifo.unblock();
  151. // Wait for thread to finish
  152. thread.join();
  153. assert_true(exception_thrown);
  154. });
  155. Test.add_func("/invercargill/fifo/try_peek_and_try_pop", () => {
  156. var fifo = new Fifo<string>();
  157. // Try operations on empty fifo
  158. string item;
  159. assert_false(fifo.try_peek(out item));
  160. assert_null(item);
  161. string popped;
  162. assert_false(fifo.try_pop(out popped));
  163. assert_null(popped);
  164. // Add an item
  165. fifo.push("test");
  166. // Try operations should now succeed
  167. assert_true(fifo.try_peek(out item));
  168. assert_cmpstr("test", CompareOperator.EQ, item);
  169. assert_true(fifo.try_pop(out popped));
  170. assert_cmpstr("test", CompareOperator.EQ, popped);
  171. // Should be empty again
  172. assert_false(fifo.try_pop(out popped));
  173. assert_null(popped);
  174. });
  175. Test.add_func("/invercargill/fifo/push_start", () => {
  176. var fifo = new Fifo<string>();
  177. // Add items normally
  178. fifo.push("first");
  179. fifo.push("second");
  180. // Add item to start
  181. fifo.push_start("zero");
  182. // Should pop: zero, first, second
  183. assert_cmpstr("zero", CompareOperator.EQ, fifo.pop());
  184. assert_cmpstr("first", CompareOperator.EQ, fifo.pop());
  185. assert_cmpstr("second", CompareOperator.EQ, fifo.pop());
  186. });
  187. }