serial_runner_unittest.cc 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. // Copyright 2013 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 <stddef.h>
  5. #include <memory>
  6. #include "base/bind.h"
  7. #include "base/debug/stack_trace.h"
  8. #include "base/run_loop.h"
  9. #include "base/task/single_thread_task_runner.h"
  10. #include "base/test/task_environment.h"
  11. #include "media/base/pipeline_status.h"
  12. #include "media/base/serial_runner.h"
  13. #include "testing/gtest/include/gtest/gtest.h"
  14. namespace media {
  15. class SerialRunnerTest : public ::testing::Test {
  16. public:
  17. SerialRunnerTest()
  18. : inside_start_(false), done_called_(false), done_status_(PIPELINE_OK) {}
  19. SerialRunnerTest(const SerialRunnerTest&) = delete;
  20. SerialRunnerTest& operator=(const SerialRunnerTest&) = delete;
  21. ~SerialRunnerTest() override = default;
  22. void RunSerialRunner() {
  23. task_environment_.GetMainThreadTaskRunner()->PostTask(
  24. FROM_HERE,
  25. base::BindOnce(&SerialRunnerTest::StartRunnerInternal,
  26. base::Unretained(this), std::move(bound_fns_)));
  27. base::RunLoop().RunUntilIdle();
  28. }
  29. // Pushes a bound function to the queue that will run its callback with
  30. // |status|. called(i) returns whether the i'th bound function pushed to the
  31. // queue was called while running the SerialRunner.
  32. void PushBoundFunction(PipelineStatus status) {
  33. bound_fns_.Push(base::BindOnce(&SerialRunnerTest::RunBoundFunction,
  34. base::Unretained(this), status,
  35. called_.size()));
  36. called_.push_back(false);
  37. }
  38. void PushBoundClosure() {
  39. bound_fns_.Push(base::BindOnce(&SerialRunnerTest::RunBoundClosure,
  40. base::Unretained(this), called_.size()));
  41. called_.push_back(false);
  42. }
  43. void PushClosure() {
  44. bound_fns_.Push(base::BindOnce(&SerialRunnerTest::RunClosure,
  45. base::Unretained(this), called_.size()));
  46. called_.push_back(false);
  47. }
  48. // Push a bound function to the queue that will delete the SerialRunner,
  49. // which should cancel all remaining queued work.
  50. void PushCancellation() {
  51. bound_fns_.Push(base::BindOnce(&SerialRunnerTest::CancelSerialRunner,
  52. base::Unretained(this)));
  53. }
  54. // Queries final status of pushed functions and done callback. Valid only
  55. // after calling RunSerialRunner().
  56. bool called(size_t index) { return called_[index]; }
  57. bool done_called() { return done_called_; }
  58. PipelineStatus done_status() { return done_status_; }
  59. private:
  60. void RunBoundFunction(PipelineStatus status,
  61. size_t index,
  62. PipelineStatusCallback status_cb) {
  63. EXPECT_EQ(index == 0u, inside_start_)
  64. << "First bound function should run on same stack as "
  65. << "SerialRunner::Run() while all others should not\n"
  66. << base::debug::StackTrace().ToString();
  67. called_[index] = true;
  68. std::move(status_cb).Run(status);
  69. }
  70. void RunBoundClosure(size_t index, base::OnceClosure done_cb) {
  71. EXPECT_EQ(index == 0u, inside_start_)
  72. << "First bound function should run on same stack as "
  73. << "SerialRunner::Run() while all others should not\n"
  74. << base::debug::StackTrace().ToString();
  75. called_[index] = true;
  76. std::move(done_cb).Run();
  77. }
  78. void RunClosure(size_t index) {
  79. EXPECT_EQ(index == 0u, inside_start_)
  80. << "First bound function should run on same stack as "
  81. << "SerialRunner::Run() while all others should not\n"
  82. << base::debug::StackTrace().ToString();
  83. called_[index] = true;
  84. }
  85. void StartRunnerInternal(SerialRunner::Queue bound_fns) {
  86. inside_start_ = true;
  87. runner_ = SerialRunner::Run(std::move(bound_fns),
  88. base::BindOnce(&SerialRunnerTest::DoneCallback,
  89. base::Unretained(this)));
  90. inside_start_ = false;
  91. }
  92. void DoneCallback(PipelineStatus status) {
  93. EXPECT_FALSE(inside_start_)
  94. << "Done callback should not run on same stack as SerialRunner::Run()\n"
  95. << base::debug::StackTrace().ToString();
  96. done_called_ = true;
  97. done_status_ = status;
  98. }
  99. void CancelSerialRunner(PipelineStatusCallback status_cb) {
  100. // Tasks run by |runner_| shouldn't reset it, hence we post a task to do so.
  101. task_environment_.GetMainThreadTaskRunner()->PostTask(
  102. FROM_HERE, base::BindOnce(&SerialRunnerTest::ResetSerialRunner,
  103. base::Unretained(this)));
  104. std::move(status_cb).Run(PIPELINE_OK);
  105. }
  106. void ResetSerialRunner() {
  107. runner_.reset();
  108. }
  109. base::test::SingleThreadTaskEnvironment task_environment_;
  110. SerialRunner::Queue bound_fns_;
  111. std::unique_ptr<SerialRunner> runner_;
  112. // Used to enforce calling stack guarantees of the API.
  113. bool inside_start_;
  114. // Tracks whether the i'th bound function was called.
  115. std::vector<bool> called_;
  116. // Tracks whether the final done callback was called + resulting status.
  117. bool done_called_;
  118. PipelineStatus done_status_;
  119. };
  120. TEST_F(SerialRunnerTest, Empty) {
  121. RunSerialRunner();
  122. EXPECT_TRUE(done_called());
  123. EXPECT_EQ(PIPELINE_OK, done_status());
  124. }
  125. TEST_F(SerialRunnerTest, Single) {
  126. PushBoundFunction(PIPELINE_OK);
  127. RunSerialRunner();
  128. EXPECT_TRUE(called(0));
  129. EXPECT_TRUE(done_called());
  130. EXPECT_EQ(PIPELINE_OK, done_status());
  131. }
  132. TEST_F(SerialRunnerTest, Single_Error) {
  133. PushBoundFunction(PIPELINE_ERROR_ABORT);
  134. RunSerialRunner();
  135. EXPECT_TRUE(called(0));
  136. EXPECT_TRUE(done_called());
  137. EXPECT_EQ(PIPELINE_ERROR_ABORT, done_status());
  138. }
  139. TEST_F(SerialRunnerTest, Single_Cancel) {
  140. PushBoundFunction(PIPELINE_OK);
  141. PushCancellation();
  142. RunSerialRunner();
  143. EXPECT_TRUE(called(0));
  144. EXPECT_FALSE(done_called());
  145. }
  146. TEST_F(SerialRunnerTest, Multiple) {
  147. PushBoundFunction(PIPELINE_OK);
  148. PushBoundFunction(PIPELINE_OK);
  149. RunSerialRunner();
  150. EXPECT_TRUE(called(0));
  151. EXPECT_TRUE(called(1));
  152. EXPECT_TRUE(done_called());
  153. EXPECT_EQ(PIPELINE_OK, done_status());
  154. }
  155. TEST_F(SerialRunnerTest, Multiple_Error) {
  156. PushBoundFunction(PIPELINE_ERROR_ABORT);
  157. PushBoundFunction(PIPELINE_OK);
  158. RunSerialRunner();
  159. EXPECT_TRUE(called(0));
  160. EXPECT_FALSE(called(1)); // A bad status cancels remaining work.
  161. EXPECT_TRUE(done_called());
  162. EXPECT_EQ(PIPELINE_ERROR_ABORT, done_status());
  163. }
  164. TEST_F(SerialRunnerTest, Multiple_Cancel) {
  165. PushBoundFunction(PIPELINE_OK);
  166. PushCancellation();
  167. PushBoundFunction(PIPELINE_OK);
  168. RunSerialRunner();
  169. EXPECT_TRUE(called(0));
  170. EXPECT_FALSE(called(1));
  171. EXPECT_FALSE(done_called());
  172. }
  173. TEST_F(SerialRunnerTest, BoundClosure) {
  174. PushBoundClosure();
  175. RunSerialRunner();
  176. EXPECT_TRUE(called(0));
  177. EXPECT_TRUE(done_called());
  178. EXPECT_EQ(PIPELINE_OK, done_status());
  179. }
  180. TEST_F(SerialRunnerTest, Closure) {
  181. PushClosure();
  182. RunSerialRunner();
  183. EXPECT_TRUE(called(0));
  184. EXPECT_TRUE(done_called());
  185. EXPECT_EQ(PIPELINE_OK, done_status());
  186. }
  187. } // namespace media