sequenced_task_runner_test_template.cc 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "base/test/sequenced_task_runner_test_template.h"
  5. #include <ostream>
  6. #include "base/location.h"
  7. namespace base {
  8. namespace internal {
  9. TaskEvent::TaskEvent(int i, Type type)
  10. : i(i), type(type) {
  11. }
  12. SequencedTaskTracker::SequencedTaskTracker()
  13. : next_post_i_(0),
  14. task_end_count_(0),
  15. task_end_cv_(&lock_) {
  16. }
  17. void SequencedTaskTracker::PostWrappedNonNestableTask(
  18. SequencedTaskRunner* task_runner,
  19. OnceClosure task) {
  20. AutoLock event_lock(lock_);
  21. const int post_i = next_post_i_++;
  22. auto wrapped_task =
  23. BindOnce(&SequencedTaskTracker::RunTask, this, std::move(task), post_i);
  24. task_runner->PostNonNestableTask(FROM_HERE, std::move(wrapped_task));
  25. TaskPosted(post_i);
  26. }
  27. void SequencedTaskTracker::PostWrappedNestableTask(
  28. SequencedTaskRunner* task_runner,
  29. OnceClosure task) {
  30. AutoLock event_lock(lock_);
  31. const int post_i = next_post_i_++;
  32. auto wrapped_task =
  33. BindOnce(&SequencedTaskTracker::RunTask, this, std::move(task), post_i);
  34. task_runner->PostTask(FROM_HERE, std::move(wrapped_task));
  35. TaskPosted(post_i);
  36. }
  37. void SequencedTaskTracker::PostWrappedDelayedNonNestableTask(
  38. SequencedTaskRunner* task_runner,
  39. OnceClosure task,
  40. TimeDelta delay) {
  41. AutoLock event_lock(lock_);
  42. const int post_i = next_post_i_++;
  43. auto wrapped_task =
  44. BindOnce(&SequencedTaskTracker::RunTask, this, std::move(task), post_i);
  45. task_runner->PostNonNestableDelayedTask(FROM_HERE, std::move(wrapped_task),
  46. delay);
  47. TaskPosted(post_i);
  48. }
  49. void SequencedTaskTracker::PostNonNestableTasks(
  50. SequencedTaskRunner* task_runner,
  51. int task_count) {
  52. for (int i = 0; i < task_count; ++i) {
  53. PostWrappedNonNestableTask(task_runner, OnceClosure());
  54. }
  55. }
  56. void SequencedTaskTracker::RunTask(OnceClosure task, int task_i) {
  57. TaskStarted(task_i);
  58. if (!task.is_null())
  59. std::move(task).Run();
  60. TaskEnded(task_i);
  61. }
  62. void SequencedTaskTracker::TaskPosted(int i) {
  63. // Caller must own |lock_|.
  64. events_.push_back(TaskEvent(i, TaskEvent::POST));
  65. }
  66. void SequencedTaskTracker::TaskStarted(int i) {
  67. AutoLock lock(lock_);
  68. events_.push_back(TaskEvent(i, TaskEvent::START));
  69. }
  70. void SequencedTaskTracker::TaskEnded(int i) {
  71. AutoLock lock(lock_);
  72. events_.push_back(TaskEvent(i, TaskEvent::END));
  73. ++task_end_count_;
  74. task_end_cv_.Signal();
  75. }
  76. const std::vector<TaskEvent>&
  77. SequencedTaskTracker::GetTaskEvents() const {
  78. return events_;
  79. }
  80. void SequencedTaskTracker::WaitForCompletedTasks(int count) {
  81. AutoLock lock(lock_);
  82. while (task_end_count_ < count)
  83. task_end_cv_.Wait();
  84. }
  85. SequencedTaskTracker::~SequencedTaskTracker() = default;
  86. void PrintTo(const TaskEvent& event, std::ostream* os) {
  87. *os << "(i=" << event.i << ", type=";
  88. switch (event.type) {
  89. case TaskEvent::POST: *os << "POST"; break;
  90. case TaskEvent::START: *os << "START"; break;
  91. case TaskEvent::END: *os << "END"; break;
  92. }
  93. *os << ")";
  94. }
  95. namespace {
  96. // Returns the task ordinals for the task event type |type| in the order that
  97. // they were recorded.
  98. std::vector<int> GetEventTypeOrder(const std::vector<TaskEvent>& events,
  99. TaskEvent::Type type) {
  100. std::vector<int> tasks;
  101. std::vector<TaskEvent>::const_iterator event;
  102. for (event = events.begin(); event != events.end(); ++event) {
  103. if (event->type == type)
  104. tasks.push_back(event->i);
  105. }
  106. return tasks;
  107. }
  108. // Returns all task events for task |task_i|.
  109. std::vector<TaskEvent::Type> GetEventsForTask(
  110. const std::vector<TaskEvent>& events,
  111. int task_i) {
  112. std::vector<TaskEvent::Type> task_event_orders;
  113. std::vector<TaskEvent>::const_iterator event;
  114. for (event = events.begin(); event != events.end(); ++event) {
  115. if (event->i == task_i)
  116. task_event_orders.push_back(event->type);
  117. }
  118. return task_event_orders;
  119. }
  120. // Checks that the task events for each task in |events| occur in the order
  121. // {POST, START, END}, and that there is only one instance of each event type
  122. // per task.
  123. ::testing::AssertionResult CheckEventOrdersForEachTask(
  124. const std::vector<TaskEvent>& events,
  125. int task_count) {
  126. std::vector<TaskEvent::Type> expected_order;
  127. expected_order.push_back(TaskEvent::POST);
  128. expected_order.push_back(TaskEvent::START);
  129. expected_order.push_back(TaskEvent::END);
  130. // This is O(n^2), but it runs fast enough currently so is not worth
  131. // optimizing.
  132. for (int i = 0; i < task_count; ++i) {
  133. const std::vector<TaskEvent::Type> task_events =
  134. GetEventsForTask(events, i);
  135. if (task_events != expected_order) {
  136. return ::testing::AssertionFailure()
  137. << "Events for task " << i << " are out of order; expected: "
  138. << ::testing::PrintToString(expected_order) << "; actual: "
  139. << ::testing::PrintToString(task_events);
  140. }
  141. }
  142. return ::testing::AssertionSuccess();
  143. }
  144. // Checks that no two tasks were running at the same time. I.e. the only
  145. // events allowed between the START and END of a task are the POSTs of other
  146. // tasks.
  147. ::testing::AssertionResult CheckNoTaskRunsOverlap(
  148. const std::vector<TaskEvent>& events) {
  149. // If > -1, we're currently inside a START, END pair.
  150. int current_task_i = -1;
  151. std::vector<TaskEvent>::const_iterator event;
  152. for (event = events.begin(); event != events.end(); ++event) {
  153. bool spurious_event_found = false;
  154. if (current_task_i == -1) { // Not inside a START, END pair.
  155. switch (event->type) {
  156. case TaskEvent::POST:
  157. break;
  158. case TaskEvent::START:
  159. current_task_i = event->i;
  160. break;
  161. case TaskEvent::END:
  162. spurious_event_found = true;
  163. break;
  164. }
  165. } else { // Inside a START, END pair.
  166. bool interleaved_task_detected = false;
  167. switch (event->type) {
  168. case TaskEvent::POST:
  169. if (event->i == current_task_i)
  170. spurious_event_found = true;
  171. break;
  172. case TaskEvent::START:
  173. interleaved_task_detected = true;
  174. break;
  175. case TaskEvent::END:
  176. if (event->i != current_task_i)
  177. interleaved_task_detected = true;
  178. else
  179. current_task_i = -1;
  180. break;
  181. }
  182. if (interleaved_task_detected) {
  183. return ::testing::AssertionFailure()
  184. << "Found event " << ::testing::PrintToString(*event)
  185. << " between START and END events for task " << current_task_i
  186. << "; event dump: " << ::testing::PrintToString(events);
  187. }
  188. }
  189. if (spurious_event_found) {
  190. const int event_i = event - events.begin();
  191. return ::testing::AssertionFailure()
  192. << "Spurious event " << ::testing::PrintToString(*event)
  193. << " at position " << event_i << "; event dump: "
  194. << ::testing::PrintToString(events);
  195. }
  196. }
  197. return ::testing::AssertionSuccess();
  198. }
  199. } // namespace
  200. ::testing::AssertionResult CheckNonNestableInvariants(
  201. const std::vector<TaskEvent>& events,
  202. int task_count) {
  203. const std::vector<int> post_order =
  204. GetEventTypeOrder(events, TaskEvent::POST);
  205. const std::vector<int> start_order =
  206. GetEventTypeOrder(events, TaskEvent::START);
  207. const std::vector<int> end_order =
  208. GetEventTypeOrder(events, TaskEvent::END);
  209. if (start_order != post_order) {
  210. return ::testing::AssertionFailure()
  211. << "Expected START order (which equals actual POST order): \n"
  212. << ::testing::PrintToString(post_order)
  213. << "\n Actual START order:\n"
  214. << ::testing::PrintToString(start_order);
  215. }
  216. if (end_order != post_order) {
  217. return ::testing::AssertionFailure()
  218. << "Expected END order (which equals actual POST order): \n"
  219. << ::testing::PrintToString(post_order)
  220. << "\n Actual END order:\n"
  221. << ::testing::PrintToString(end_order);
  222. }
  223. const ::testing::AssertionResult result =
  224. CheckEventOrdersForEachTask(events, task_count);
  225. if (!result)
  226. return result;
  227. return CheckNoTaskRunsOverlap(events);
  228. }
  229. } // namespace internal
  230. // This suite is instantiated in binaries that use //base:test_support.
  231. GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SequencedTaskRunnerTest);
  232. } // namespace base