| OLD | NEW | 
|---|
| (Empty) |  | 
|  | 1 // Copyright (c) 2017 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 | 
|  | 5 #include "base/pending_task.h" | 
|  | 6 | 
|  | 7 #include <vector> | 
|  | 8 | 
|  | 9 #include "base/bind.h" | 
|  | 10 #include "base/message_loop/message_loop.h" | 
|  | 11 #include "base/run_loop.h" | 
|  | 12 #include "base/strings/stringprintf.h" | 
|  | 13 #include "base/threading/thread.h" | 
|  | 14 #include "testing/gtest/include/gtest/gtest.h" | 
|  | 15 | 
|  | 16 namespace base { | 
|  | 17 | 
|  | 18 class PendingTaskTest : public ::testing::Test { | 
|  | 19  public: | 
|  | 20   PendingTaskTest() = default; | 
|  | 21 | 
|  | 22   ~PendingTaskTest() override = default; | 
|  | 23 | 
|  | 24  protected: | 
|  | 25   using ExpectedTrace = std::vector<const void*>; | 
|  | 26 | 
|  | 27   static void VerifyTraceAndPost( | 
|  | 28       const scoped_refptr<TaskRunner>& task_runner, | 
|  | 29       const tracked_objects::Location& posted_from, | 
|  | 30       const tracked_objects::Location& next_from_here, | 
|  | 31       const std::vector<const void*>& expected_trace, | 
|  | 32       Closure task) { | 
|  | 33     SCOPED_TRACE(StringPrintf("Callback Depth: %zu", expected_trace.size())); | 
|  | 34 | 
|  | 35     // Beyond depth + 1, the trace is nonsensical because there haven't been | 
|  | 36     // enough nested tasks called. | 
|  | 37     const PendingTask* current_pending_task = | 
|  | 38         MessageLoop::current()->current_pending_task_; | 
|  | 39     size_t window = std::min(current_pending_task->task_backtrace.size(), | 
|  | 40                              expected_trace.size()); | 
|  | 41 | 
|  | 42     EXPECT_EQ(posted_from, | 
|  | 43               MessageLoop::current()->current_pending_task_->posted_from); | 
|  | 44     for (size_t i = 0; i < window; i++) { | 
|  | 45       SCOPED_TRACE(StringPrintf("Trace frame: %zu", i)); | 
|  | 46       EXPECT_EQ(expected_trace[i], current_pending_task->task_backtrace[i]); | 
|  | 47     } | 
|  | 48     task_runner->PostTask(next_from_here, std::move(task)); | 
|  | 49   } | 
|  | 50 | 
|  | 51   static void RunTwo(Closure c1, Closure c2) { | 
|  | 52     c1.Run(); | 
|  | 53     c2.Run(); | 
|  | 54   } | 
|  | 55 }; | 
|  | 56 | 
|  | 57 // Ensure the task backtrace populates correctly. | 
|  | 58 TEST_F(PendingTaskTest, SingleThreadedSimple) { | 
|  | 59   MessageLoop loop; | 
|  | 60   const tracked_objects::Location& location0 = FROM_HERE; | 
|  | 61   const tracked_objects::Location& location1 = FROM_HERE; | 
|  | 62   const tracked_objects::Location& location2 = FROM_HERE; | 
|  | 63   const tracked_objects::Location& location3 = FROM_HERE; | 
|  | 64   const tracked_objects::Location& location4 = FROM_HERE; | 
|  | 65   const tracked_objects::Location& location5 = FROM_HERE; | 
|  | 66 | 
|  | 67   Closure task5 = Bind( | 
|  | 68       &PendingTaskTest::VerifyTraceAndPost, loop.task_runner(), location4, | 
|  | 69       location5, | 
|  | 70       ExpectedTrace({location3.program_counter(), location2.program_counter(), | 
|  | 71                      location1.program_counter(), location0.program_counter()}), | 
|  | 72       Bind(&DoNothing)); | 
|  | 73   Closure task4 = Bind( | 
|  | 74       &PendingTaskTest::VerifyTraceAndPost, loop.task_runner(), location3, | 
|  | 75       location4, | 
|  | 76       ExpectedTrace({location2.program_counter(), location1.program_counter(), | 
|  | 77                      location0.program_counter(), nullptr}), | 
|  | 78       task5); | 
|  | 79   Closure task3 = Bind( | 
|  | 80       &PendingTaskTest::VerifyTraceAndPost, loop.task_runner(), location2, | 
|  | 81       location3, ExpectedTrace({location1.program_counter(), | 
|  | 82                                 location0.program_counter(), nullptr, nullptr}), | 
|  | 83       task4); | 
|  | 84   Closure task2 = | 
|  | 85       Bind(&PendingTaskTest::VerifyTraceAndPost, loop.task_runner(), location1, | 
|  | 86            location2, ExpectedTrace({location0.program_counter()}), task3); | 
|  | 87   Closure task1 = Bind(&PendingTaskTest::VerifyTraceAndPost, loop.task_runner(), | 
|  | 88                        location0, location1, ExpectedTrace({}), task2); | 
|  | 89 | 
|  | 90   loop.task_runner()->PostTask(location0, task1); | 
|  | 91 | 
|  | 92   RunLoop().RunUntilIdle(); | 
|  | 93 } | 
|  | 94 | 
|  | 95 // Post a task onto another thread. Ensure on the other thread, it has the | 
|  | 96 // right stack trace. | 
|  | 97 TEST_F(PendingTaskTest, MultipleThreads) { | 
|  | 98   MessageLoop loop;  // Implicitly "thread a." | 
|  | 99   Thread thread_b("pt_test_b"); | 
|  | 100   Thread thread_c("pt_test_c"); | 
|  | 101   thread_b.StartAndWaitForTesting(); | 
|  | 102   thread_c.StartAndWaitForTesting(); | 
|  | 103 | 
|  | 104   const tracked_objects::Location& location_a0 = FROM_HERE; | 
|  | 105   const tracked_objects::Location& location_a1 = FROM_HERE; | 
|  | 106   const tracked_objects::Location& location_a2 = FROM_HERE; | 
|  | 107   const tracked_objects::Location& location_a3 = FROM_HERE; | 
|  | 108 | 
|  | 109   const tracked_objects::Location& location_b0 = FROM_HERE; | 
|  | 110   const tracked_objects::Location& location_b1 = FROM_HERE; | 
|  | 111 | 
|  | 112   const tracked_objects::Location& location_c0 = FROM_HERE; | 
|  | 113 | 
|  | 114   // On thread c, post a task back to thread a that verifies its trace | 
|  | 115   // and terminates after one more self-post. | 
|  | 116   Closure task_a2 = | 
|  | 117       Bind(&PendingTaskTest::VerifyTraceAndPost, loop.task_runner(), | 
|  | 118            location_a2, location_a3, | 
|  | 119            ExpectedTrace( | 
|  | 120                {location_c0.program_counter(), location_b0.program_counter(), | 
|  | 121                 location_a1.program_counter(), location_a0.program_counter()}), | 
|  | 122            Bind(&DoNothing)); | 
|  | 123   Closure task_c0 = Bind(&PendingTaskTest::VerifyTraceAndPost, | 
|  | 124                          loop.task_runner(), location_c0, location_a2, | 
|  | 125                          ExpectedTrace({location_b0.program_counter(), | 
|  | 126                                         location_a1.program_counter(), | 
|  | 127                                         location_a0.program_counter()}), | 
|  | 128                          task_a2); | 
|  | 129 | 
|  | 130   // On thread b run two tasks that conceptually come from the same location | 
|  | 131   // (managed via RunTwo().) One will post back to thread b and another will | 
|  | 132   // post to thread c to test spawning multiple tasks on different message | 
|  | 133   // loops. The task posted to thread c will not get location b1 whereas the | 
|  | 134   // one posted back to thread b will. | 
|  | 135   Closure task_b0_fork = | 
|  | 136       Bind(&PendingTaskTest::VerifyTraceAndPost, | 
|  | 137            thread_c.message_loop()->task_runner(), location_b0, location_c0, | 
|  | 138            ExpectedTrace({location_a1.program_counter(), | 
|  | 139                           location_a0.program_counter(), nullptr}), | 
|  | 140            task_c0); | 
|  | 141   Closure task_b0_local = | 
|  | 142       Bind(&PendingTaskTest::VerifyTraceAndPost, | 
|  | 143            thread_b.message_loop()->task_runner(), location_b0, location_b1, | 
|  | 144            ExpectedTrace({location_a1.program_counter(), | 
|  | 145                           location_a0.program_counter(), nullptr}), | 
|  | 146            Bind(&DoNothing)); | 
|  | 147 | 
|  | 148   // Push one frame onto the stack in thread a then pass to thread b. | 
|  | 149   Closure task_a1 = | 
|  | 150       Bind(&PendingTaskTest::VerifyTraceAndPost, | 
|  | 151            thread_b.message_loop()->task_runner(), location_a1, location_b0, | 
|  | 152            ExpectedTrace({location_a0.program_counter(), nullptr}), | 
|  | 153            Bind(&PendingTaskTest::RunTwo, task_b0_local, task_b0_fork)); | 
|  | 154   Closure task_a0 = | 
|  | 155       Bind(&PendingTaskTest::VerifyTraceAndPost, loop.task_runner(), | 
|  | 156            location_a0, location_a1, ExpectedTrace({nullptr}), task_a1); | 
|  | 157 | 
|  | 158   loop.task_runner()->PostTask(location_a0, task_a0); | 
|  | 159 | 
|  | 160   RunLoop().RunUntilIdle(); | 
|  | 161 | 
|  | 162   thread_b.FlushForTesting(); | 
|  | 163   thread_b.Stop(); | 
|  | 164 | 
|  | 165   thread_c.FlushForTesting(); | 
|  | 166   thread_c.Stop(); | 
|  | 167 } | 
|  | 168 | 
|  | 169 }  // namespace base | 
| OLD | NEW | 
|---|