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

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: Actually use thread_b when I said I would. 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
108 const tracked_objects::Location& location_b0 = FROM_HERE;
109 const tracked_objects::Location& location_b1 = FROM_HERE;
110
111 const tracked_objects::Location& location_c0 = FROM_HERE;
112
113 // Push one frame onto the stack in thread c and then pass back to thread a.
114 Closure task_a2 =
115 Bind(&PendingTaskTest::VerifyTraceAndPost, loop.task_runner(),
116 location_c0, location_a2,
117 ExpectedTrace(
118 {location_b1.program_counter(), location_b0.program_counter(),
119 location_a1.program_counter(), location_a0.program_counter()}),
120 Bind(&DoNothing));
121 Closure task_c0 = Bind(&PendingTaskTest::VerifyTraceAndPost,
122 loop.task_runner(), location_b1, location_c0,
123 ExpectedTrace({location_b0.program_counter(),
124 location_a1.program_counter(),
125 location_a0.program_counter()}),
126 task_a2);
127
128 // Push one frame onto the stack in thread b then spawn two tasks, one in
129 // thread b and one in thread c using location_b1.
130 Closure task_b0_fork =
131 Bind(&PendingTaskTest::VerifyTraceAndPost,
132 thread_c.message_loop()->task_runner(), location_b0, location_b1,
danakj 2017/02/09 21:16:27 The names of the locations are a bit inconsistent.
awong 2017/02/09 21:25:36 That's actually me doing the backtrace wrong. :-/
133 ExpectedTrace({location_a1.program_counter(),
134 location_a0.program_counter(), nullptr}),
135 task_c0);
136 Closure task_b0_local =
137 Bind(&PendingTaskTest::VerifyTraceAndPost,
138 thread_b.message_loop()->task_runner(), location_b0, location_b1,
139 ExpectedTrace({location_a1.program_counter(),
140 location_a0.program_counter(), nullptr}),
141 Bind(&DoNothing));
142
143 // Push one frame onto the stack in thread a then pass to thread b.
danakj 2017/02/09 21:16:27 The comment explanations are helpful but also a bi
awong 2017/02/09 21:25:37 I think the comments were actually right and the c
144 Closure task_a1 =
145 Bind(&PendingTaskTest::VerifyTraceAndPost,
146 thread_b.message_loop()->task_runner(), location_a1, location_b0,
147 ExpectedTrace({location_a0.program_counter(), nullptr}),
148 Bind(&PendingTaskTest::RunTwo, task_b0_local, task_b0_fork));
149 Closure task_a0 =
150 Bind(&PendingTaskTest::VerifyTraceAndPost, loop.task_runner(),
151 location_a0, location_a1, ExpectedTrace({nullptr}), task_a1);
152
153 loop.task_runner()->PostTask(location_a0, task_a0);
154
155 RunLoop().RunUntilIdle();
156
157 thread_b.FlushForTesting();
158 thread_b.Stop();
159
160 thread_c.FlushForTesting();
161 thread_c.Stop();
162 }
163
164 } // 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