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

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: More wording fixes. 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() = 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
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