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

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: Don't duplicate the posted_from in stacktrace. 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
« base/debug/task_annotator.cc ('K') | « 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 =
38 std::min(arraysize(PendingTask::task_backtrace), expected_trace.size());
39
40 EXPECT_EQ(posted_from,
41 base::MessageLoop::current()->current_pending_task_->posted_from);
42 for (size_t i = 0; i < window; i++) {
43 SCOPED_TRACE(StringPrintf("Trace frame: %zu", i));
44 EXPECT_EQ(expected_trace[i],
45 base::MessageLoop::current()
46 ->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 base::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 = base::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 base::Bind(&DoNothing));
73 Closure task4 = base::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 = base::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 = base::Bind(
85 &PendingTaskTest::VerifyTraceAndPost, loop.task_runner(), location1,
86 location2, ExpectedTrace({location0.program_counter()}), task3);
87 Closure task1 =
88 base::Bind(&PendingTaskTest::VerifyTraceAndPost, loop.task_runner(),
89 location0, location1, ExpectedTrace({}), task2);
90
91 loop.task_runner()->PostTask(location0, task1);
92
93 base::RunLoop().RunUntilIdle();
94 }
95
96 // Post a task onto another thread. Ensure on the other thread, it has the
97 // right stack trace.
98 TEST_F(PendingTaskTest, MultipleThreads) {
99 base::MessageLoop loop; // Implicitly "thread a"
100 base::Thread thread_b("pt_test_b");
101 base::Thread thread_c("pt_test_c");
102 thread_b.StartAndWaitForTesting();
103 thread_c.StartAndWaitForTesting();
104
105 const tracked_objects::Location& location_a0 = FROM_HERE;
106 const tracked_objects::Location& location_a1 = FROM_HERE;
107 const tracked_objects::Location& location_a2 = 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 // Push one frame onto the stack in thread c and then pass back to thread a.
115 Closure task_a2 = base::Bind(
116 &PendingTaskTest::VerifyTraceAndPost, loop.task_runner(), location_c0,
117 location_a2,
118 ExpectedTrace(
119 {location_b1.program_counter(), location_b0.program_counter(),
120 location_a1.program_counter(), location_a0.program_counter()}),
121 base::Bind(&DoNothing));
122 Closure task_c0 = base::Bind(&PendingTaskTest::VerifyTraceAndPost,
123 loop.task_runner(), location_b1, location_c0,
124 ExpectedTrace({location_b0.program_counter(),
125 location_a1.program_counter(),
126 location_a0.program_counter()}),
127 task_a2);
128
129 // Push one frame onto the stack in thread b then spawn two tasks, one in
130 // thread b and one in thread c using location_b1.
131 Closure task_b0_fork = base::Bind(
132 &PendingTaskTest::VerifyTraceAndPost,
133 thread_c.message_loop()->task_runner(), location_b0, location_b1,
134 ExpectedTrace({location_a1.program_counter(),
135 location_a0.program_counter(), nullptr}),
136 task_c0);
137 Closure task_b0_local = base::Bind(
138 &PendingTaskTest::VerifyTraceAndPost,
139 thread_c.message_loop()->task_runner(), location_b0, location_b1,
140 ExpectedTrace({location_a1.program_counter(),
141 location_a0.program_counter(), nullptr}),
142 base::Bind(&DoNothing));
143
144 // Push one frame onto the stack in thread a then pass to thread b.
145 Closure task_a1 = base::Bind(
146 &PendingTaskTest::VerifyTraceAndPost,
147 thread_c.message_loop()->task_runner(), location_a1, location_b0,
148 ExpectedTrace({location_a0.program_counter(), nullptr}),
149 base::Bind(&PendingTaskTest::RunTwo, task_b0_local, task_b0_fork));
150 Closure task_a0 =
151 base::Bind(&PendingTaskTest::VerifyTraceAndPost, loop.task_runner(),
152 location_a0, location_a1, ExpectedTrace({nullptr}), task_a1);
153
154 loop.task_runner()->PostTask(location_a0, task_a0);
155
156 base::RunLoop().RunUntilIdle();
157
158 thread_b.FlushForTesting();
159 thread_b.Stop();
160
161 thread_c.FlushForTesting();
162 thread_c.Stop();
163 }
164
165 } // namespace base
OLDNEW
« base/debug/task_annotator.cc ('K') | « base/pending_task.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698