Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(430)

Side by Side Diff: base/pending_task_unittest.cc

Issue 1044413002: Record async "task backtraces" (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: c++11 is hard; let's go shopping. Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « base/pending_task.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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() {}
21
22 ~PendingTaskTest() override {}
23
24 protected:
25 typedef std::vector<const void*> ExpectedTrace;
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 size_t window = std::min(base::MessageLoop::current()
38 ->current_pending_task_->task_backtrace.size(),
danakj 2017/02/09 20:34:42 nit: this would probably wrap a lot nicer if u put
awong 2017/02/09 20:56:06 Done.
39 expected_trace.size());
40
41 EXPECT_EQ(posted_from,
42 base::MessageLoop::current()->current_pending_task_->posted_from);
43 for (size_t i = 0; i < window; i++) {
44 SCOPED_TRACE(StringPrintf("Trace frame: %zu", i));
45 EXPECT_EQ(expected_trace[i],
46 base::MessageLoop::current()
47 ->current_pending_task_->task_backtrace[i]);
48 }
49 task_runner->PostTask(next_from_here, std::move(task));
50 }
51
52 static void RunTwo(Closure c1, Closure c2) {
53 c1.Run();
54 c2.Run();
55 }
56 };
57
58 // Ensure the task backtrace populates correctly.
59 TEST_F(PendingTaskTest, SingleThreadedSimple) {
60 base::MessageLoop loop;
61 const tracked_objects::Location& location0 = FROM_HERE;
62 const tracked_objects::Location& location1 = FROM_HERE;
63 const tracked_objects::Location& location2 = FROM_HERE;
64 const tracked_objects::Location& location3 = FROM_HERE;
65 const tracked_objects::Location& location4 = FROM_HERE;
66 const tracked_objects::Location& location5 = FROM_HERE;
67
68 Closure task5 = base::Bind(
69 &PendingTaskTest::VerifyTraceAndPost, loop.task_runner(), location4,
70 location5,
71 ExpectedTrace({location3.program_counter(), location2.program_counter(),
72 location1.program_counter(), location0.program_counter()}),
73 base::Bind(&DoNothing));
74 Closure task4 = base::Bind(
75 &PendingTaskTest::VerifyTraceAndPost, loop.task_runner(), location3,
76 location4,
77 ExpectedTrace({location2.program_counter(), location1.program_counter(),
78 location0.program_counter(), nullptr}),
79 task5);
80 Closure task3 = base::Bind(
81 &PendingTaskTest::VerifyTraceAndPost, loop.task_runner(), location2,
82 location3, ExpectedTrace({location1.program_counter(),
83 location0.program_counter(), nullptr, nullptr}),
84 task4);
85 Closure task2 = base::Bind(
86 &PendingTaskTest::VerifyTraceAndPost, loop.task_runner(), location1,
87 location2, ExpectedTrace({location0.program_counter()}), task3);
88 Closure task1 =
89 base::Bind(&PendingTaskTest::VerifyTraceAndPost, loop.task_runner(),
90 location0, location1, ExpectedTrace({}), task2);
91
92 loop.task_runner()->PostTask(location0, task1);
93
94 base::RunLoop().RunUntilIdle();
95 }
96
97 // Post a task onto another thread. Ensure on the other thread, it has the
98 // right stack trace.
99 TEST_F(PendingTaskTest, MultipleThreads) {
100 base::MessageLoop loop; // Implicitly "thread a"
101 base::Thread thread_b("pt_test_b");
102 base::Thread thread_c("pt_test_c");
103 thread_b.StartAndWaitForTesting();
104 thread_c.StartAndWaitForTesting();
105
106 const tracked_objects::Location& location_a0 = FROM_HERE;
107 const tracked_objects::Location& location_a1 = FROM_HERE;
108 const tracked_objects::Location& location_a2 = FROM_HERE;
109
110 const tracked_objects::Location& location_b0 = FROM_HERE;
111 const tracked_objects::Location& location_b1 = FROM_HERE;
112
113 const tracked_objects::Location& location_c0 = FROM_HERE;
114
115 // Push one frame onto the stack in thread c and then pass back to thread a.
116 Closure task_a2 = base::Bind(
117 &PendingTaskTest::VerifyTraceAndPost, loop.task_runner(), location_c0,
118 location_a2,
119 ExpectedTrace(
120 {location_b1.program_counter(), location_b0.program_counter(),
121 location_a1.program_counter(), location_a0.program_counter()}),
122 base::Bind(&DoNothing));
123 Closure task_c0 = base::Bind(&PendingTaskTest::VerifyTraceAndPost,
124 loop.task_runner(), location_b1, location_c0,
125 ExpectedTrace({location_b0.program_counter(),
126 location_a1.program_counter(),
127 location_a0.program_counter()}),
128 task_a2);
129
130 // Push one frame onto the stack in thread b then spawn two tasks, one in
131 // thread b and one in thread c using location_b1.
132 Closure task_b0_fork = base::Bind(
133 &PendingTaskTest::VerifyTraceAndPost,
134 thread_c.message_loop()->task_runner(), location_b0, location_b1,
135 ExpectedTrace({location_a1.program_counter(),
136 location_a0.program_counter(), nullptr}),
137 task_c0);
138 Closure task_b0_local = base::Bind(
139 &PendingTaskTest::VerifyTraceAndPost,
140 thread_c.message_loop()->task_runner(), location_b0, location_b1,
141 ExpectedTrace({location_a1.program_counter(),
142 location_a0.program_counter(), nullptr}),
143 base::Bind(&DoNothing));
144
145 // Push one frame onto the stack in thread a then pass to thread b.
146 Closure task_a1 = base::Bind(
147 &PendingTaskTest::VerifyTraceAndPost,
148 thread_c.message_loop()->task_runner(), location_a1, location_b0,
149 ExpectedTrace({location_a0.program_counter(), nullptr}),
150 base::Bind(&PendingTaskTest::RunTwo, task_b0_local, task_b0_fork));
151 Closure task_a0 =
152 base::Bind(&PendingTaskTest::VerifyTraceAndPost, loop.task_runner(),
153 location_a0, location_a1, ExpectedTrace({nullptr}), task_a1);
154
155 loop.task_runner()->PostTask(location_a0, task_a0);
156
157 base::RunLoop().RunUntilIdle();
158
159 thread_b.FlushForTesting();
160 thread_b.Stop();
161
162 thread_c.FlushForTesting();
163 thread_c.Stop();
164 }
165
166 } // namespace base
OLDNEW
« no previous file with comments | « base/pending_task.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698