Fifo.vala 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  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. fifo.unblock();
  73. // Iteration should return items in FIFO order
  74. var tracker = fifo.get_tracker();
  75. var items = new string[3];
  76. var index = 0;
  77. while (tracker.has_next()) {
  78. items[index++] = tracker.get_next();
  79. }
  80. assert_cmpstr("first", CompareOperator.EQ, items[0]);
  81. assert_cmpstr("second", CompareOperator.EQ, items[1]);
  82. assert_cmpstr("third", CompareOperator.EQ, items[2]);
  83. });
  84. Test.add_func("/invercargill/fifo/blocking_behavior", () => {
  85. var fifo = new Fifo<string>();
  86. bool thread_started = false;
  87. bool thread_finished = false;
  88. // Start a thread that will wait for an item
  89. Thread<void*> thread = new Thread<void*>("test-thread", () => {
  90. thread_started = true;
  91. var item = fifo.pop();
  92. assert_cmpstr("test_item", CompareOperator.EQ, item);
  93. thread_finished = true;
  94. return null;
  95. });
  96. // Wait for thread to start and block
  97. while (!thread_started) {
  98. Thread.usleep(1000); // 1ms
  99. }
  100. // Give additional time for thread to block on pop()
  101. Thread.usleep(50000); // 50ms
  102. // Push an item to unblock the thread
  103. fifo.push("test_item");
  104. // Wait for thread to finish
  105. thread.join();
  106. assert_true(thread_finished);
  107. });
  108. Test.add_func("/invercargill/fifo/unblock_behavior", () => {
  109. var fifo = new Fifo<int>();
  110. bool thread_started = false;
  111. bool exception_thrown = false;
  112. // Start a thread that will wait for an item
  113. Thread<void*> thread = new Thread<void*>("test-thread", () => {
  114. thread_started = true;
  115. try {
  116. var item = fifo.pop(); // This should throw after unblock
  117. assert_not_reached();
  118. }
  119. catch (SequenceError e) {
  120. assert_cmpstr("No elements in unblocked queue to pop", CompareOperator.EQ, e.message);
  121. exception_thrown = true;
  122. }
  123. return null;
  124. });
  125. // Wait for thread to start and block
  126. while (!thread_started) {
  127. Thread.usleep(1000); // 1ms
  128. }
  129. // Give additional time for thread to block on pop()
  130. Thread.usleep(50000); // 50ms
  131. // Unblock the fifo
  132. fifo.unblock();
  133. // Wait for thread to finish
  134. thread.join();
  135. assert_true(exception_thrown);
  136. });
  137. Test.add_func("/invercargill/fifo/try_peek_and_try_pop", () => {
  138. var fifo = new Fifo<string>();
  139. // Try operations on empty fifo
  140. string item;
  141. assert_false(fifo.try_peek(out item));
  142. assert_null(item);
  143. string popped;
  144. fifo.unblock();
  145. assert_false(fifo.try_pop(out popped));
  146. assert_null(popped);
  147. // Add an item
  148. fifo.push("test");
  149. // Try operations should now succeed
  150. assert_true(fifo.try_peek(out item));
  151. assert_cmpstr("test", CompareOperator.EQ, item);
  152. assert_true(fifo.try_pop(out popped));
  153. assert_cmpstr("test", CompareOperator.EQ, popped);
  154. // Should be empty again
  155. assert_false(fifo.try_pop(out popped));
  156. assert_null(popped);
  157. });
  158. Test.add_func("/invercargill/fifo/push_start", () => {
  159. var fifo = new Fifo<string>();
  160. // Add items normally
  161. fifo.push("first");
  162. fifo.push("second");
  163. // Add item to start
  164. fifo.push_start("zero");
  165. // Should pop: zero, first, second
  166. assert_cmpstr("zero", CompareOperator.EQ, fifo.pop());
  167. assert_cmpstr("first", CompareOperator.EQ, fifo.pop());
  168. assert_cmpstr("second", CompareOperator.EQ, fifo.pop());
  169. });
  170. }