test_tb_linklist.cpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. // ================================================================================
  2. // == This file is a part of Turbo Badger. (C) 2011-2014, Emil Segerås ==
  3. // == See tb_core.h for more information. ==
  4. // ================================================================================
  5. #include "tb_test.h"
  6. #include "tb_linklist.h"
  7. #ifdef TB_UNIT_TESTING
  8. using namespace tb;
  9. TB_TEST_GROUP(tb_linklist)
  10. {
  11. class Apple : public TBLinkOf<Apple>
  12. {
  13. public:
  14. Apple() : id(0) { total_apple_count++; }
  15. Apple(int id) : id(id) { total_apple_count++; }
  16. ~Apple() { total_apple_count--; }
  17. void eat() {}
  18. int id;
  19. static int total_apple_count;
  20. };
  21. int Apple::total_apple_count = 0;
  22. TBLinkListOf<Apple> list;
  23. bool AddAppless(int num_apples)
  24. {
  25. for (int i = 0; i < num_apples; i++)
  26. list.AddLast(new Apple(i + 1));
  27. return list.CountLinks() == num_apples;
  28. }
  29. TB_TEST(Setup)
  30. {
  31. // Add 3 apples to list for each test.
  32. list.DeleteAll();
  33. TB_VERIFY(AddAppless(3));
  34. }
  35. TB_TEST(Shutdown)
  36. {
  37. list.DeleteAll();
  38. }
  39. TB_TEST(iteration_while_delete_all)
  40. {
  41. TBLinkListOf<Apple>::Iterator iterator = list.IterateForward();
  42. while (Apple *apple = iterator.GetAndStep())
  43. {
  44. apple->eat();
  45. // Lets pretend we do something with apple
  46. // that trig deletion of all apples.
  47. list.DeleteAll();
  48. }
  49. // success already, if we didn't crash
  50. TB_VERIFY(list.CountLinks() == 0);
  51. }
  52. TB_TEST(iteration_while_delete)
  53. {
  54. TBLinkListOf<Apple>::Iterator iterator = list.IterateForward();
  55. while (Apple *apple = iterator.GetAndStep())
  56. {
  57. // Lets pretend we do something with apple
  58. // that trig deletion of both apple and next apple!
  59. if (apple->GetNext())
  60. list.Delete(apple->GetNext());
  61. list.Delete(apple);
  62. }
  63. // success already, if we didn't crash
  64. TB_VERIFY(list.CountLinks() == 0);
  65. }
  66. TB_TEST(iteration_while_list_delete)
  67. {
  68. // Allocate a list that does not own its apples.
  69. // We need the apples to survive their list to test this fully.
  70. TBLinkListOf<Apple> *apple_refs = new TBLinkListOf<Apple>;
  71. Apple apples[3];
  72. for (int i = 0; i < 3; i++)
  73. apple_refs->AddLast(&apples[i]);
  74. TB_VERIFY(apples[0].IsInList());
  75. TB_VERIFY(apples[1].IsInList());
  76. TB_VERIFY(apples[2].IsInList());
  77. // Lets pretend we do some iteration in a list...
  78. TBLinkListOf<Apple>::Iterator iterator = apple_refs->IterateForward();
  79. TB_VERIFY(iterator.Get());
  80. // Now the list itself gets deallocated.
  81. delete apple_refs;
  82. // Since the list is gone, the links should not be added anymore.
  83. TB_VERIFY(!apples[0].IsInList());
  84. TB_VERIFY(!apples[1].IsInList());
  85. TB_VERIFY(!apples[2].IsInList());
  86. // Now the iterator should not point to anything,
  87. // and we should not crash.
  88. TB_VERIFY(!iterator.Get());
  89. }
  90. TB_TEST(forward_iterator)
  91. {
  92. TBLinkListOf<Apple>::Iterator i = list.IterateForward();
  93. TB_VERIFY(i.Get()->id == 1);
  94. TB_VERIFY(i.GetAndStep()->id == 1);
  95. TB_VERIFY(i.GetAndStep()->id == 2);
  96. TB_VERIFY(i.GetAndStep()->id == 3);
  97. TB_VERIFY(i.Get() == nullptr);
  98. i.Reset();
  99. TB_VERIFY(i.Get()->id == 1);
  100. }
  101. TB_TEST(backward_iterator)
  102. {
  103. TBLinkListOf<Apple>::Iterator i = list.IterateBackward();
  104. TB_VERIFY(i.Get()->id == 3);
  105. TB_VERIFY(i.GetAndStep()->id == 3);
  106. TB_VERIFY(i.GetAndStep()->id == 2);
  107. TB_VERIFY(i.GetAndStep()->id == 1);
  108. TB_VERIFY(i.Get() == nullptr);
  109. i.Reset();
  110. TB_VERIFY(i.Get()->id == 3);
  111. }
  112. TB_TEST(multiple_iterators_assign)
  113. {
  114. TBLinkListOf<Apple>::Iterator iA = list.IterateForward();
  115. TBLinkListOf<Apple>::Iterator iB = list.IterateBackward();
  116. TB_VERIFY(iA.Get()->id == 1);
  117. TB_VERIFY(iB.Get()->id == 3);
  118. iA = iB;
  119. TB_VERIFY(iA.GetAndStep()->id == 3);
  120. TB_VERIFY(iA.GetAndStep()->id == 2);
  121. TB_VERIFY(iA.GetAndStep()->id == 1);
  122. }
  123. TB_TEST(multiple_iterators_assign_swap_list)
  124. {
  125. TBLinkListAutoDeleteOf<Apple> other_list;
  126. other_list.AddLast(new Apple(42));
  127. TBLinkListOf<Apple>::Iterator iA = list.IterateForward();
  128. TBLinkListOf<Apple>::Iterator iB = other_list.IterateForward();
  129. TB_VERIFY(iA.Get()->id == 1);
  130. TB_VERIFY(iB.Get()->id == 42);
  131. iA = iB;
  132. TB_VERIFY(iA.GetAndStep()->id == 42);
  133. TB_VERIFY(iA.Get() == nullptr);
  134. }
  135. TB_TEST(autodelete)
  136. {
  137. // Check that the apples really are destroyed.
  138. int old_total_apple_count = Apple::total_apple_count;
  139. // Scope for TBLinkListAutoDeleteOf
  140. {
  141. TBLinkListAutoDeleteOf<Apple> autodelete_list;
  142. autodelete_list.AddLast(new Apple(1));
  143. autodelete_list.AddLast(new Apple(2));
  144. TB_VERIFY(Apple::total_apple_count == old_total_apple_count + 2);
  145. }
  146. TB_VERIFY(Apple::total_apple_count == old_total_apple_count);
  147. }
  148. }
  149. #endif // TB_UNIT_TESTING