OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // Test of classes in the tracked_objects.h classes. | 5 // Test of classes in the tracked_objects.h classes. |
6 | 6 |
7 #include "base/tracked_objects.h" | 7 #include "base/tracked_objects.h" |
8 | 8 |
9 #include "base/json/json_writer.h" | |
10 #include "base/memory/scoped_ptr.h" | 9 #include "base/memory/scoped_ptr.h" |
| 10 #include "base/process_util.h" |
11 #include "base/time.h" | 11 #include "base/time.h" |
12 #include "testing/gtest/include/gtest/gtest.h" | 12 #include "testing/gtest/include/gtest/gtest.h" |
13 | 13 |
| 14 const int kLineNumber = 1776; |
| 15 const char kFile[] = "FixedUnitTestFileName"; |
| 16 const char kWorkerThreadName[] = "WorkerThread-1"; |
| 17 const char kMainThreadName[] = "SomeMainThreadName"; |
| 18 const char kStillAlive[] = "Still_Alive"; |
| 19 |
14 namespace tracked_objects { | 20 namespace tracked_objects { |
15 | 21 |
16 class TrackedObjectsTest : public testing::Test { | 22 class TrackedObjectsTest : public testing::Test { |
17 protected: | 23 protected: |
18 TrackedObjectsTest() { | 24 TrackedObjectsTest() { |
19 // On entry, leak any database structures in case they are still in use by | 25 // On entry, leak any database structures in case they are still in use by |
20 // prior threads. | 26 // prior threads. |
21 ThreadData::ShutdownSingleThreadedCleanup(true); | 27 ThreadData::ShutdownSingleThreadedCleanup(true); |
22 } | 28 } |
23 | 29 |
24 virtual ~TrackedObjectsTest() { | 30 virtual ~TrackedObjectsTest() { |
25 // We should not need to leak any structures we create, since we are | 31 // We should not need to leak any structures we create, since we are |
26 // single threaded, and carefully accounting for items. | 32 // single threaded, and carefully accounting for items. |
27 ThreadData::ShutdownSingleThreadedCleanup(false); | 33 ThreadData::ShutdownSingleThreadedCleanup(false); |
28 } | 34 } |
29 | 35 |
30 // Provide access, since this class is a friend of ThreadData. | 36 // Reset the profiler state. |
31 void ShutdownSingleThreadedCleanup(bool leak) { | 37 void Reset() { |
32 ThreadData::ShutdownSingleThreadedCleanup(leak); | 38 ThreadData::ShutdownSingleThreadedCleanup(false); |
| 39 } |
| 40 |
| 41 // Simulate a birth on the thread named |thread_name|, at the given |
| 42 // |location|. |
| 43 void TallyABirth(const Location& location, const std::string& thread_name) { |
| 44 // If the |thread_name| is empty, we don't initialize system with a thread |
| 45 // name, so we're viewed as a worker thread. |
| 46 if (!thread_name.empty()) |
| 47 ThreadData::InitializeThreadContext(kMainThreadName); |
| 48 |
| 49 // Do not delete |birth|. We don't own it. |
| 50 Births* birth = ThreadData::TallyABirthIfActive(location); |
| 51 |
| 52 if (ThreadData::status() == ThreadData::DEACTIVATED) |
| 53 EXPECT_EQ(reinterpret_cast<Births*>(NULL), birth); |
| 54 else |
| 55 EXPECT_NE(reinterpret_cast<Births*>(NULL), birth); |
| 56 } |
| 57 |
| 58 // Helper function to verify the most common test expectations. |
| 59 void ExpectSimpleProcessData(const ProcessDataSnapshot& process_data, |
| 60 const std::string& function_name, |
| 61 const std::string& birth_thread, |
| 62 const std::string& death_thread, |
| 63 int count, |
| 64 int run_ms, |
| 65 int queue_ms) { |
| 66 ASSERT_EQ(1u, process_data.tasks.size()); |
| 67 |
| 68 EXPECT_EQ(kFile, process_data.tasks[0].birth.location.file_name); |
| 69 EXPECT_EQ(function_name, |
| 70 process_data.tasks[0].birth.location.function_name); |
| 71 EXPECT_EQ(kLineNumber, process_data.tasks[0].birth.location.line_number); |
| 72 |
| 73 EXPECT_EQ(birth_thread, process_data.tasks[0].birth.thread_name); |
| 74 |
| 75 EXPECT_EQ(count, process_data.tasks[0].death_data.count); |
| 76 EXPECT_EQ(count * run_ms, |
| 77 process_data.tasks[0].death_data.run_duration_sum); |
| 78 EXPECT_EQ(run_ms, process_data.tasks[0].death_data.run_duration_max); |
| 79 EXPECT_EQ(run_ms, process_data.tasks[0].death_data.run_duration_sample); |
| 80 EXPECT_EQ(count * queue_ms, |
| 81 process_data.tasks[0].death_data.queue_duration_sum); |
| 82 EXPECT_EQ(queue_ms, process_data.tasks[0].death_data.queue_duration_max); |
| 83 EXPECT_EQ(queue_ms, process_data.tasks[0].death_data.queue_duration_sample); |
| 84 |
| 85 EXPECT_EQ(death_thread, process_data.tasks[0].death_thread_name); |
| 86 |
| 87 EXPECT_EQ(0u, process_data.descendants.size()); |
| 88 |
| 89 EXPECT_EQ(base::GetCurrentProcId(), process_data.process_id); |
33 } | 90 } |
34 }; | 91 }; |
35 | 92 |
36 TEST_F(TrackedObjectsTest, MinimalStartupShutdown) { | 93 TEST_F(TrackedObjectsTest, MinimalStartupShutdown) { |
37 // Minimal test doesn't even create any tasks. | 94 // Minimal test doesn't even create any tasks. |
38 if (!ThreadData::InitializeAndSetTrackingStatus( | 95 if (!ThreadData::InitializeAndSetTrackingStatus( |
39 ThreadData::PROFILING_CHILDREN_ACTIVE)) | 96 ThreadData::PROFILING_CHILDREN_ACTIVE)) |
40 return; | 97 return; |
41 | 98 |
42 EXPECT_FALSE(ThreadData::first()); // No activity even on this thread. | 99 EXPECT_FALSE(ThreadData::first()); // No activity even on this thread. |
43 ThreadData* data = ThreadData::Get(); | 100 ThreadData* data = ThreadData::Get(); |
44 EXPECT_TRUE(ThreadData::first()); // Now class was constructed. | 101 EXPECT_TRUE(ThreadData::first()); // Now class was constructed. |
45 EXPECT_TRUE(data); | 102 ASSERT_TRUE(data); |
46 EXPECT_TRUE(!data->next()); | 103 EXPECT_FALSE(data->next()); |
47 EXPECT_EQ(data, ThreadData::Get()); | 104 EXPECT_EQ(data, ThreadData::Get()); |
48 ThreadData::BirthMap birth_map; | 105 ThreadData::BirthMap birth_map; |
49 ThreadData::DeathMap death_map; | 106 ThreadData::DeathMap death_map; |
50 ThreadData::ParentChildSet parent_child_set; | 107 ThreadData::ParentChildSet parent_child_set; |
51 data->SnapshotMaps(false, &birth_map, &death_map, &parent_child_set); | 108 data->SnapshotMaps(false, &birth_map, &death_map, &parent_child_set); |
52 EXPECT_EQ(0u, birth_map.size()); | 109 EXPECT_EQ(0u, birth_map.size()); |
53 EXPECT_EQ(0u, death_map.size()); | 110 EXPECT_EQ(0u, death_map.size()); |
54 EXPECT_EQ(0u, parent_child_set.size()); | 111 EXPECT_EQ(0u, parent_child_set.size()); |
55 // Cleanup with no leaking. | 112 |
56 ShutdownSingleThreadedCleanup(false); | 113 // Clean up with no leaking. |
| 114 Reset(); |
57 | 115 |
58 // Do it again, just to be sure we reset state completely. | 116 // Do it again, just to be sure we reset state completely. |
59 ThreadData::InitializeAndSetTrackingStatus( | 117 EXPECT_TRUE(ThreadData::InitializeAndSetTrackingStatus( |
60 ThreadData::PROFILING_CHILDREN_ACTIVE); | 118 ThreadData::PROFILING_CHILDREN_ACTIVE)); |
61 EXPECT_FALSE(ThreadData::first()); // No activity even on this thread. | 119 EXPECT_FALSE(ThreadData::first()); // No activity even on this thread. |
62 data = ThreadData::Get(); | 120 data = ThreadData::Get(); |
63 EXPECT_TRUE(ThreadData::first()); // Now class was constructed. | 121 EXPECT_TRUE(ThreadData::first()); // Now class was constructed. |
64 EXPECT_TRUE(data); | 122 ASSERT_TRUE(data); |
65 EXPECT_TRUE(!data->next()); | 123 EXPECT_FALSE(data->next()); |
66 EXPECT_EQ(data, ThreadData::Get()); | 124 EXPECT_EQ(data, ThreadData::Get()); |
67 birth_map.clear(); | 125 birth_map.clear(); |
68 death_map.clear(); | 126 death_map.clear(); |
| 127 parent_child_set.clear(); |
69 data->SnapshotMaps(false, &birth_map, &death_map, &parent_child_set); | 128 data->SnapshotMaps(false, &birth_map, &death_map, &parent_child_set); |
70 EXPECT_EQ(0u, birth_map.size()); | 129 EXPECT_EQ(0u, birth_map.size()); |
71 EXPECT_EQ(0u, death_map.size()); | 130 EXPECT_EQ(0u, death_map.size()); |
72 EXPECT_EQ(0u, parent_child_set.size()); | 131 EXPECT_EQ(0u, parent_child_set.size()); |
73 } | 132 } |
74 | 133 |
75 TEST_F(TrackedObjectsTest, TinyStartupShutdown) { | 134 TEST_F(TrackedObjectsTest, TinyStartupShutdown) { |
76 if (!ThreadData::InitializeAndSetTrackingStatus( | 135 if (!ThreadData::InitializeAndSetTrackingStatus( |
77 ThreadData::PROFILING_CHILDREN_ACTIVE)) | 136 ThreadData::PROFILING_CHILDREN_ACTIVE)) |
78 return; | 137 return; |
79 | 138 |
80 // Instigate tracking on a single tracked object, on our thread. | 139 // Instigate tracking on a single tracked object, on our thread. |
81 const Location& location = FROM_HERE; | 140 const char kFunction[] = "TinyStartupShutdown"; |
| 141 Location location(kFunction, kFile, kLineNumber, NULL); |
82 Births* first_birth = ThreadData::TallyABirthIfActive(location); | 142 Births* first_birth = ThreadData::TallyABirthIfActive(location); |
83 | 143 |
84 ThreadData* data = ThreadData::first(); | 144 ThreadData* data = ThreadData::first(); |
85 ASSERT_TRUE(data); | 145 ASSERT_TRUE(data); |
86 EXPECT_TRUE(!data->next()); | 146 EXPECT_FALSE(data->next()); |
87 EXPECT_EQ(data, ThreadData::Get()); | 147 EXPECT_EQ(data, ThreadData::Get()); |
88 ThreadData::BirthMap birth_map; | 148 ThreadData::BirthMap birth_map; |
89 ThreadData::DeathMap death_map; | 149 ThreadData::DeathMap death_map; |
90 ThreadData::ParentChildSet parent_child_set; | 150 ThreadData::ParentChildSet parent_child_set; |
91 data->SnapshotMaps(false, &birth_map, &death_map, &parent_child_set); | 151 data->SnapshotMaps(false, &birth_map, &death_map, &parent_child_set); |
92 EXPECT_EQ(1u, birth_map.size()); // 1 birth location. | 152 EXPECT_EQ(1u, birth_map.size()); // 1 birth location. |
93 EXPECT_EQ(1, birth_map.begin()->second->birth_count()); // 1 birth. | 153 EXPECT_EQ(1, birth_map.begin()->second->birth_count()); // 1 birth. |
94 EXPECT_EQ(0u, death_map.size()); // No deaths. | 154 EXPECT_EQ(0u, death_map.size()); // No deaths. |
95 EXPECT_EQ(0u, parent_child_set.size()); // No children. | 155 EXPECT_EQ(0u, parent_child_set.size()); // No children. |
96 | 156 |
97 | 157 |
98 // Now instigate another birth, while we are timing the run of the first | 158 // Now instigate another birth, while we are timing the run of the first |
99 // execution. | 159 // execution. |
100 TrackedTime start_time = | 160 TrackedTime start_time = ThreadData::NowForStartOfRun(first_birth); |
101 ThreadData::NowForStartOfRun(first_birth); | |
102 // Create a child (using the same birth location). | 161 // Create a child (using the same birth location). |
103 // TrackingInfo will call TallyABirth() during construction. | 162 // TrackingInfo will call TallyABirth() during construction. |
104 base::TimeTicks kBogusBirthTime; | 163 base::TimeTicks kBogusBirthTime; |
105 base::TrackingInfo pending_task(location, kBogusBirthTime); | 164 base::TrackingInfo pending_task(location, kBogusBirthTime); |
106 // Finally conclude the outer run. | 165 // Finally conclude the outer run. |
107 TrackedTime end_time = ThreadData::NowForEndOfRun(); | 166 TrackedTime end_time = ThreadData::NowForEndOfRun(); |
108 ThreadData::TallyRunOnNamedThreadIfTracking(pending_task, start_time, | 167 ThreadData::TallyRunOnNamedThreadIfTracking(pending_task, start_time, |
109 end_time); | 168 end_time); |
110 | 169 |
111 birth_map.clear(); | 170 birth_map.clear(); |
112 death_map.clear(); | 171 death_map.clear(); |
113 parent_child_set.clear(); | 172 parent_child_set.clear(); |
114 data->SnapshotMaps(false, &birth_map, &death_map, &parent_child_set); | 173 data->SnapshotMaps(false, &birth_map, &death_map, &parent_child_set); |
115 EXPECT_EQ(1u, birth_map.size()); // 1 birth location. | 174 EXPECT_EQ(1u, birth_map.size()); // 1 birth location. |
116 EXPECT_EQ(2, birth_map.begin()->second->birth_count()); // 2 births. | 175 EXPECT_EQ(2, birth_map.begin()->second->birth_count()); // 2 births. |
117 EXPECT_EQ(1u, death_map.size()); // 1 location. | 176 EXPECT_EQ(1u, death_map.size()); // 1 location. |
118 EXPECT_EQ(1, death_map.begin()->second.count()); // 1 death. | 177 EXPECT_EQ(1, death_map.begin()->second.count()); // 1 death. |
119 if (ThreadData::TrackingParentChildStatus()) { | 178 if (ThreadData::TrackingParentChildStatus()) { |
120 EXPECT_EQ(1u, parent_child_set.size()); // 1 child. | 179 EXPECT_EQ(1u, parent_child_set.size()); // 1 child. |
121 EXPECT_EQ(parent_child_set.begin()->first, | 180 EXPECT_EQ(parent_child_set.begin()->first, |
122 parent_child_set.begin()->second); | 181 parent_child_set.begin()->second); |
123 } else { | 182 } else { |
124 EXPECT_EQ(0u, parent_child_set.size()); // no stats. | 183 EXPECT_EQ(0u, parent_child_set.size()); // no stats. |
125 } | 184 } |
126 | 185 |
127 // The births were at the same location as the one known death. | 186 // The births were at the same location as the one known death. |
128 EXPECT_EQ(birth_map.begin()->second, death_map.begin()->first); | 187 EXPECT_EQ(birth_map.begin()->second, death_map.begin()->first); |
129 } | |
130 | 188 |
131 TEST_F(TrackedObjectsTest, ParentChildTest) { | 189 ProcessDataSnapshot process_data; |
132 if (!ThreadData::InitializeAndSetTrackingStatus( | 190 ThreadData::Snapshot(false, &process_data); |
133 ThreadData::PROFILING_CHILDREN_ACTIVE)) | |
134 return; | |
135 if (!ThreadData::TrackingParentChildStatus()) | |
136 return; // Feature not compiled in. | |
137 | 191 |
138 // Instigate tracking on a single tracked object, on our thread. | 192 const int32 time_elapsed = (end_time - start_time).InMilliseconds(); |
139 const int kFakeLineNumber = 1776; | 193 ASSERT_EQ(1u, process_data.tasks.size()); |
140 const char* kFile = "FixedUnitTestFileName"; | 194 EXPECT_EQ(kFile, process_data.tasks[0].birth.location.file_name); |
141 const char* kFunction = "ParentChildTest"; | 195 EXPECT_EQ(kFunction, process_data.tasks[0].birth.location.function_name); |
142 Location location(kFunction, kFile, kFakeLineNumber, NULL); | 196 EXPECT_EQ(kLineNumber, process_data.tasks[0].birth.location.line_number); |
| 197 EXPECT_EQ(kWorkerThreadName, process_data.tasks[0].birth.thread_name); |
| 198 EXPECT_EQ(1, process_data.tasks[0].death_data.count); |
| 199 EXPECT_EQ(time_elapsed, process_data.tasks[0].death_data.run_duration_sum); |
| 200 EXPECT_EQ(time_elapsed, process_data.tasks[0].death_data.run_duration_max); |
| 201 EXPECT_EQ(time_elapsed, process_data.tasks[0].death_data.run_duration_sample); |
| 202 EXPECT_EQ(0, process_data.tasks[0].death_data.queue_duration_sum); |
| 203 EXPECT_EQ(0, process_data.tasks[0].death_data.queue_duration_max); |
| 204 EXPECT_EQ(0, process_data.tasks[0].death_data.queue_duration_sample); |
| 205 EXPECT_EQ(kWorkerThreadName, process_data.tasks[0].death_thread_name); |
143 | 206 |
144 // Now instigate another birth, while we are timing the run of the first | 207 if (ThreadData::TrackingParentChildStatus()) { |
145 // execution. | 208 ASSERT_EQ(1u, process_data.descendants.size()); |
146 | 209 EXPECT_EQ(kFile, process_data.descendants[0].parent.location.file_name); |
147 // Create a child (using the same birth location). | 210 EXPECT_EQ(kFunction, |
148 // TrackingInfo will call TallyABirth() during construction. | 211 process_data.descendants[0].parent.location.function_name); |
149 base::TimeTicks kBogusBirthTime; | 212 EXPECT_EQ(kLineNumber, |
150 base::TrackingInfo pending_task(location, kBogusBirthTime); | 213 process_data.descendants[0].parent.location.line_number); |
151 | 214 EXPECT_EQ(kWorkerThreadName, |
152 // Don't conclude the run, so that we don't use the actual timer that we | 215 process_data.descendants[0].parent.thread_name); |
153 // started for the outer profile. This way the JSON will not include some | 216 EXPECT_EQ(kFile, process_data.descendants[0].child.location.file_name); |
154 // random time. | 217 EXPECT_EQ(kFunction, |
155 ThreadData* data = ThreadData::first(); | 218 process_data.descendants[0].child.location.function_name); |
156 ASSERT_TRUE(data); | 219 EXPECT_EQ(kLineNumber, |
157 EXPECT_TRUE(!data->next()); | 220 process_data.descendants[0].child.location.line_number); |
158 EXPECT_EQ(data, ThreadData::Get()); | 221 EXPECT_EQ(kWorkerThreadName, process_data.descendants[0].child.thread_name); |
159 | 222 } else { |
160 ThreadData::BirthMap birth_map; | 223 EXPECT_EQ(0u, process_data.descendants.size()); |
161 ThreadData::DeathMap death_map; | 224 } |
162 ThreadData::ParentChildSet parent_child_set; | |
163 | |
164 data->SnapshotMaps(false, &birth_map, &death_map, &parent_child_set); | |
165 EXPECT_EQ(1u, birth_map.size()); // 1 birth location. | |
166 EXPECT_EQ(2, birth_map.begin()->second->birth_count()); // 2 births. | |
167 EXPECT_EQ(0u, death_map.size()); // No status yet. | |
168 // Just like TinyStartupShutdown test. | |
169 EXPECT_EQ(1u, parent_child_set.size()); // 1 child. | |
170 EXPECT_EQ(parent_child_set.begin()->first, | |
171 parent_child_set.begin()->second); | |
172 | |
173 scoped_ptr<base::Value> value(ThreadData::ToValue(false)); | |
174 std::string json; | |
175 base::JSONWriter::Write(value.get(), &json); | |
176 std::string birth_only_result = "{" | |
177 "\"descendants\":[" | |
178 "{" | |
179 "\"child_location\":{" | |
180 "\"file_name\":\"FixedUnitTestFileName\"," | |
181 "\"function_name\":\"ParentChildTest\"," | |
182 "\"line_number\":1776" | |
183 "}," | |
184 "\"child_thread\":\"WorkerThread-1\"," | |
185 "\"parent_location\":{" | |
186 "\"file_name\":\"FixedUnitTestFileName\"," | |
187 "\"function_name\":\"ParentChildTest\"," | |
188 "\"line_number\":1776" | |
189 "}," | |
190 "\"parent_thread\":\"WorkerThread-1\"" | |
191 "}" | |
192 "]," | |
193 "\"list\":[" | |
194 "{" | |
195 "\"birth_thread\":\"WorkerThread-1\"," | |
196 "\"death_data\":{" | |
197 "\"count\":2," | |
198 "\"queue_ms\":0," | |
199 "\"queue_ms_max\":0," | |
200 "\"queue_ms_sample\":0," | |
201 "\"run_ms\":0," | |
202 "\"run_ms_max\":0," | |
203 "\"run_ms_sample\":0" | |
204 "}," | |
205 "\"death_thread\":\"Still_Alive\"," | |
206 "\"location\":{" | |
207 "\"file_name\":\"FixedUnitTestFileName\"," | |
208 "\"function_name\":\"ParentChildTest\"," | |
209 "\"line_number\":1776" | |
210 "}" | |
211 "}" | |
212 "]" | |
213 "}"; | |
214 EXPECT_EQ(json, birth_only_result); | |
215 } | 225 } |
216 | 226 |
217 TEST_F(TrackedObjectsTest, DeathDataTest) { | 227 TEST_F(TrackedObjectsTest, DeathDataTest) { |
218 if (!ThreadData::InitializeAndSetTrackingStatus( | 228 if (!ThreadData::InitializeAndSetTrackingStatus( |
219 ThreadData::PROFILING_CHILDREN_ACTIVE)) | 229 ThreadData::PROFILING_CHILDREN_ACTIVE)) |
220 return; | 230 return; |
221 | 231 |
222 scoped_ptr<DeathData> data(new DeathData()); | 232 scoped_ptr<DeathData> data(new DeathData()); |
223 ASSERT_NE(data, reinterpret_cast<DeathData*>(NULL)); | 233 ASSERT_NE(data, reinterpret_cast<DeathData*>(NULL)); |
224 EXPECT_EQ(data->run_duration_sum(), 0); | 234 EXPECT_EQ(data->run_duration_sum(), 0); |
225 EXPECT_EQ(data->run_duration_sample(), 0); | 235 EXPECT_EQ(data->run_duration_sample(), 0); |
226 EXPECT_EQ(data->queue_duration_sum(), 0); | 236 EXPECT_EQ(data->queue_duration_sum(), 0); |
227 EXPECT_EQ(data->queue_duration_sample(), 0); | 237 EXPECT_EQ(data->queue_duration_sample(), 0); |
228 EXPECT_EQ(data->count(), 0); | 238 EXPECT_EQ(data->count(), 0); |
229 | 239 |
230 int32 run_ms = 42; | 240 int32 run_ms = 42; |
231 int32 queue_ms = 8; | 241 int32 queue_ms = 8; |
232 | 242 |
233 const int kUnrandomInt = 0; // Fake random int that ensure we sample data. | 243 const int kUnrandomInt = 0; // Fake random int that ensure we sample data. |
234 data->RecordDeath(queue_ms, run_ms, kUnrandomInt); | 244 data->RecordDeath(queue_ms, run_ms, kUnrandomInt); |
235 EXPECT_EQ(data->run_duration_sum(), run_ms); | 245 EXPECT_EQ(data->run_duration_sum(), run_ms); |
236 EXPECT_EQ(data->run_duration_sample(), run_ms); | 246 EXPECT_EQ(data->run_duration_sample(), run_ms); |
237 EXPECT_EQ(data->queue_duration_sum(), queue_ms); | 247 EXPECT_EQ(data->queue_duration_sum(), queue_ms); |
238 EXPECT_EQ(data->queue_duration_sample(), queue_ms); | 248 EXPECT_EQ(data->queue_duration_sample(), queue_ms); |
239 EXPECT_EQ(data->count(), 1); | 249 EXPECT_EQ(data->count(), 1); |
240 | 250 |
241 data->RecordDeath(queue_ms, run_ms, kUnrandomInt); | 251 data->RecordDeath(queue_ms, run_ms, kUnrandomInt); |
242 EXPECT_EQ(data->run_duration_sum(), run_ms + run_ms); | 252 EXPECT_EQ(data->run_duration_sum(), run_ms + run_ms); |
243 EXPECT_EQ(data->run_duration_sample(), run_ms); | 253 EXPECT_EQ(data->run_duration_sample(), run_ms); |
244 EXPECT_EQ(data->queue_duration_sum(), queue_ms + queue_ms); | 254 EXPECT_EQ(data->queue_duration_sum(), queue_ms + queue_ms); |
245 EXPECT_EQ(data->queue_duration_sample(), queue_ms); | 255 EXPECT_EQ(data->queue_duration_sample(), queue_ms); |
246 EXPECT_EQ(data->count(), 2); | 256 EXPECT_EQ(data->count(), 2); |
247 | 257 |
248 scoped_ptr<base::DictionaryValue> dictionary(data->ToValue()); | 258 DeathDataSnapshot snapshot(*data); |
249 int integer; | 259 EXPECT_EQ(2, snapshot.count); |
250 EXPECT_TRUE(dictionary->GetInteger("run_ms", &integer)); | 260 EXPECT_EQ(2 * run_ms, snapshot.run_duration_sum); |
251 EXPECT_EQ(integer, 2 * run_ms); | 261 EXPECT_EQ(run_ms, snapshot.run_duration_max); |
252 EXPECT_TRUE(dictionary->GetInteger("run_ms_sample", &integer)); | 262 EXPECT_EQ(run_ms, snapshot.run_duration_sample); |
253 EXPECT_EQ(integer, run_ms); | 263 EXPECT_EQ(2 * queue_ms, snapshot.queue_duration_sum); |
254 EXPECT_TRUE(dictionary->GetInteger("queue_ms", &integer)); | 264 EXPECT_EQ(queue_ms, snapshot.queue_duration_max); |
255 EXPECT_EQ(integer, 2 * queue_ms); | 265 EXPECT_EQ(queue_ms, snapshot.queue_duration_sample); |
256 EXPECT_TRUE(dictionary->GetInteger("queue_ms_sample", &integer)); | |
257 EXPECT_EQ(integer, queue_ms); | |
258 EXPECT_TRUE(dictionary->GetInteger("count", &integer)); | |
259 EXPECT_EQ(integer, 2); | |
260 | |
261 scoped_ptr<base::Value> value(data->ToValue()); | |
262 std::string json; | |
263 base::JSONWriter::Write(value.get(), &json); | |
264 std::string birth_only_result = "{" | |
265 "\"count\":2," | |
266 "\"queue_ms\":16," | |
267 "\"queue_ms_max\":8," | |
268 "\"queue_ms_sample\":8," | |
269 "\"run_ms\":84," | |
270 "\"run_ms_max\":42," | |
271 "\"run_ms_sample\":42" | |
272 "}"; | |
273 EXPECT_EQ(birth_only_result, json); | |
274 } | 266 } |
275 | 267 |
276 TEST_F(TrackedObjectsTest, DeactivatedBirthOnlyToValueWorkerThread) { | 268 TEST_F(TrackedObjectsTest, DeactivatedBirthOnlyToSnapshotWorkerThread) { |
277 // Transition to Deactivated state before doing anything. | |
278 if (!ThreadData::InitializeAndSetTrackingStatus(ThreadData::DEACTIVATED)) | |
279 return; | |
280 // We don't initialize system with a thread name, so we're viewed as a worker | |
281 // thread. | |
282 const int kFakeLineNumber = 173; | |
283 const char* kFile = "FixedFileName"; | |
284 const char* kFunction = "BirthOnlyToValueWorkerThread"; | |
285 Location location(kFunction, kFile, kFakeLineNumber, NULL); | |
286 Births* birth = ThreadData::TallyABirthIfActive(location); | |
287 // We should now see a NULL birth record. | |
288 EXPECT_EQ(birth, reinterpret_cast<Births*>(NULL)); | |
289 | |
290 scoped_ptr<base::Value> value(ThreadData::ToValue(false)); | |
291 std::string json; | |
292 base::JSONWriter::Write(value.get(), &json); | |
293 std::string birth_only_result = "{" | |
294 "\"descendants\":[" | |
295 "]," | |
296 "\"list\":[" | |
297 "]" | |
298 "}"; | |
299 EXPECT_EQ(json, birth_only_result); | |
300 } | |
301 | |
302 TEST_F(TrackedObjectsTest, DeactivatedBirthOnlyToValueMainThread) { | |
303 // Start in the deactivated state. | 269 // Start in the deactivated state. |
304 if (!ThreadData::InitializeAndSetTrackingStatus(ThreadData::DEACTIVATED)) | 270 if (!ThreadData::InitializeAndSetTrackingStatus(ThreadData::DEACTIVATED)) |
305 return; | 271 return; |
306 | 272 |
307 // Use a well named thread. | 273 const char kFunction[] = "DeactivatedBirthOnlyToSnapshotWorkerThread"; |
308 ThreadData::InitializeThreadContext("SomeMainThreadName"); | 274 Location location(kFunction, kFile, kLineNumber, NULL); |
309 const int kFakeLineNumber = 173; | 275 TallyABirth(location, std::string()); |
310 const char* kFile = "FixedFileName"; | |
311 const char* kFunction = "BirthOnlyToValueMainThread"; | |
312 Location location(kFunction, kFile, kFakeLineNumber, NULL); | |
313 // Do not delete birth. We don't own it. | |
314 Births* birth = ThreadData::TallyABirthIfActive(location); | |
315 // We expect to not get a birth record. | |
316 EXPECT_EQ(birth, reinterpret_cast<Births*>(NULL)); | |
317 | 276 |
318 scoped_ptr<base::Value> value(ThreadData::ToValue(false)); | 277 ProcessDataSnapshot process_data; |
319 std::string json; | 278 ThreadData::Snapshot(false, &process_data); |
320 base::JSONWriter::Write(value.get(), &json); | 279 EXPECT_EQ(0u, process_data.tasks.size()); |
321 std::string birth_only_result = "{" | 280 EXPECT_EQ(0u, process_data.descendants.size()); |
322 "\"descendants\":[" | 281 EXPECT_EQ(base::GetCurrentProcId(), process_data.process_id); |
323 "]," | |
324 "\"list\":[" | |
325 "]" | |
326 "}"; | |
327 EXPECT_EQ(json, birth_only_result); | |
328 } | 282 } |
329 | 283 |
330 TEST_F(TrackedObjectsTest, BirthOnlyToValueWorkerThread) { | 284 TEST_F(TrackedObjectsTest, DeactivatedBirthOnlyToSnapshotMainThread) { |
331 if (!ThreadData::InitializeAndSetTrackingStatus( | 285 // Start in the deactivated state. |
332 ThreadData::PROFILING_CHILDREN_ACTIVE)) | 286 if (!ThreadData::InitializeAndSetTrackingStatus(ThreadData::DEACTIVATED)) |
333 return; | 287 return; |
334 // We don't initialize system with a thread name, so we're viewed as a worker | |
335 // thread. | |
336 const int kFakeLineNumber = 173; | |
337 const char* kFile = "FixedFileName"; | |
338 const char* kFunction = "BirthOnlyToValueWorkerThread"; | |
339 Location location(kFunction, kFile, kFakeLineNumber, NULL); | |
340 Births* birth = ThreadData::TallyABirthIfActive(location); | |
341 EXPECT_NE(birth, reinterpret_cast<Births*>(NULL)); | |
342 | 288 |
343 scoped_ptr<base::Value> value(ThreadData::ToValue(false)); | 289 const char kFunction[] = "DeactivatedBirthOnlyToSnapshotMainThread"; |
344 std::string json; | 290 Location location(kFunction, kFile, kLineNumber, NULL); |
345 base::JSONWriter::Write(value.get(), &json); | 291 TallyABirth(location, kMainThreadName); |
346 std::string birth_only_result = "{" | 292 |
347 "\"descendants\":[" | 293 ProcessDataSnapshot process_data; |
348 "]," | 294 ThreadData::Snapshot(false, &process_data); |
349 "\"list\":[" | 295 EXPECT_EQ(0u, process_data.tasks.size()); |
350 "{" | 296 EXPECT_EQ(0u, process_data.descendants.size()); |
351 "\"birth_thread\":\"WorkerThread-1\"," | 297 EXPECT_EQ(base::GetCurrentProcId(), process_data.process_id); |
352 "\"death_data\":{" | |
353 "\"count\":1," | |
354 "\"queue_ms\":0," | |
355 "\"queue_ms_max\":0," | |
356 "\"queue_ms_sample\":0," | |
357 "\"run_ms\":0," | |
358 "\"run_ms_max\":0," | |
359 "\"run_ms_sample\":0" | |
360 "}," | |
361 "\"death_thread\":\"Still_Alive\"," | |
362 "\"location\":{" | |
363 "\"file_name\":\"FixedFileName\"," | |
364 "\"function_name\":\"BirthOnlyToValueWorkerThread\"," | |
365 "\"line_number\":173" | |
366 "}" | |
367 "}" | |
368 "]" | |
369 "}"; | |
370 EXPECT_EQ(json, birth_only_result); | |
371 } | 298 } |
372 | 299 |
373 TEST_F(TrackedObjectsTest, BirthOnlyToValueMainThread) { | 300 TEST_F(TrackedObjectsTest, BirthOnlyToSnapshotWorkerThread) { |
374 if (!ThreadData::InitializeAndSetTrackingStatus( | 301 if (!ThreadData::InitializeAndSetTrackingStatus( |
375 ThreadData::PROFILING_CHILDREN_ACTIVE)) | 302 ThreadData::PROFILING_CHILDREN_ACTIVE)) |
376 return; | 303 return; |
377 | 304 |
378 // Use a well named thread. | 305 const char kFunction[] = "BirthOnlyToSnapshotWorkerThread"; |
379 ThreadData::InitializeThreadContext("SomeMainThreadName"); | 306 Location location(kFunction, kFile, kLineNumber, NULL); |
380 const int kFakeLineNumber = 173; | 307 TallyABirth(location, std::string()); |
381 const char* kFile = "FixedFileName"; | |
382 const char* kFunction = "BirthOnlyToValueMainThread"; | |
383 Location location(kFunction, kFile, kFakeLineNumber, NULL); | |
384 // Do not delete birth. We don't own it. | |
385 Births* birth = ThreadData::TallyABirthIfActive(location); | |
386 EXPECT_NE(birth, reinterpret_cast<Births*>(NULL)); | |
387 | 308 |
388 scoped_ptr<base::Value> value(ThreadData::ToValue(false)); | 309 ProcessDataSnapshot process_data; |
389 std::string json; | 310 ThreadData::Snapshot(false, &process_data); |
390 base::JSONWriter::Write(value.get(), &json); | 311 ExpectSimpleProcessData(process_data, kFunction, kWorkerThreadName, |
391 std::string birth_only_result = "{" | 312 kStillAlive, 1, 0, 0); |
392 "\"descendants\":[" | |
393 "]," | |
394 "\"list\":[" | |
395 "{" | |
396 "\"birth_thread\":\"SomeMainThreadName\"," | |
397 "\"death_data\":{" | |
398 "\"count\":1," | |
399 "\"queue_ms\":0," | |
400 "\"queue_ms_max\":0," | |
401 "\"queue_ms_sample\":0," | |
402 "\"run_ms\":0," | |
403 "\"run_ms_max\":0," | |
404 "\"run_ms_sample\":0" | |
405 "}," | |
406 "\"death_thread\":\"Still_Alive\"," | |
407 "\"location\":{" | |
408 "\"file_name\":\"FixedFileName\"," | |
409 "\"function_name\":\"BirthOnlyToValueMainThread\"," | |
410 "\"line_number\":173" | |
411 "}" | |
412 "}" | |
413 "]" | |
414 "}"; | |
415 EXPECT_EQ(json, birth_only_result); | |
416 } | 313 } |
417 | 314 |
418 TEST_F(TrackedObjectsTest, LifeCycleToValueMainThread) { | 315 TEST_F(TrackedObjectsTest, BirthOnlyToSnapshotMainThread) { |
419 if (!ThreadData::InitializeAndSetTrackingStatus( | 316 if (!ThreadData::InitializeAndSetTrackingStatus( |
420 ThreadData::PROFILING_CHILDREN_ACTIVE)) | 317 ThreadData::PROFILING_CHILDREN_ACTIVE)) |
421 return; | 318 return; |
422 | 319 |
423 // Use a well named thread. | 320 const char kFunction[] = "BirthOnlyToSnapshotMainThread"; |
424 ThreadData::InitializeThreadContext("SomeMainThreadName"); | 321 Location location(kFunction, kFile, kLineNumber, NULL); |
425 const int kFakeLineNumber = 236; | 322 TallyABirth(location, kMainThreadName); |
426 const char* kFile = "FixedFileName"; | |
427 const char* kFunction = "LifeCycleToValueMainThread"; | |
428 Location location(kFunction, kFile, kFakeLineNumber, NULL); | |
429 // Do not delete birth. We don't own it. | |
430 Births* birth = ThreadData::TallyABirthIfActive(location); | |
431 EXPECT_NE(birth, reinterpret_cast<Births*>(NULL)); | |
432 | 323 |
433 const base::TimeTicks kTimePosted = base::TimeTicks() | 324 ProcessDataSnapshot process_data; |
434 + base::TimeDelta::FromMilliseconds(1); | 325 ThreadData::Snapshot(false, &process_data); |
| 326 ExpectSimpleProcessData(process_data, kFunction, kMainThreadName, kStillAlive, |
| 327 1, 0, 0); |
| 328 } |
| 329 |
| 330 TEST_F(TrackedObjectsTest, LifeCycleToSnapshotMainThread) { |
| 331 if (!ThreadData::InitializeAndSetTrackingStatus( |
| 332 ThreadData::PROFILING_CHILDREN_ACTIVE)) |
| 333 return; |
| 334 |
| 335 const char kFunction[] = "LifeCycleToSnapshotMainThread"; |
| 336 Location location(kFunction, kFile, kLineNumber, NULL); |
| 337 TallyABirth(location, kMainThreadName); |
| 338 |
| 339 const base::TimeTicks kTimePosted = base::TimeTicks() + |
| 340 base::TimeDelta::FromMilliseconds(1); |
435 const base::TimeTicks kDelayedStartTime = base::TimeTicks(); | 341 const base::TimeTicks kDelayedStartTime = base::TimeTicks(); |
436 // TrackingInfo will call TallyABirth() during construction. | 342 // TrackingInfo will call TallyABirth() during construction. |
437 base::TrackingInfo pending_task(location, kDelayedStartTime); | 343 base::TrackingInfo pending_task(location, kDelayedStartTime); |
438 pending_task.time_posted = kTimePosted; // Overwrite implied Now(). | 344 pending_task.time_posted = kTimePosted; // Overwrite implied Now(). |
439 | 345 |
440 const TrackedTime kStartOfRun = TrackedTime() + | 346 const TrackedTime kStartOfRun = TrackedTime() + |
441 Duration::FromMilliseconds(5); | 347 Duration::FromMilliseconds(5); |
442 const TrackedTime kEndOfRun = TrackedTime() + Duration::FromMilliseconds(7); | 348 const TrackedTime kEndOfRun = TrackedTime() + Duration::FromMilliseconds(7); |
443 ThreadData::TallyRunOnNamedThreadIfTracking(pending_task, | 349 ThreadData::TallyRunOnNamedThreadIfTracking(pending_task, |
444 kStartOfRun, kEndOfRun); | 350 kStartOfRun, kEndOfRun); |
445 | 351 |
446 scoped_ptr<base::Value> value(ThreadData::ToValue(false)); | 352 ProcessDataSnapshot process_data; |
447 std::string json; | 353 ThreadData::Snapshot(false, &process_data); |
448 base::JSONWriter::Write(value.get(), &json); | 354 ExpectSimpleProcessData(process_data, kFunction, kMainThreadName, |
449 std::string one_line_result = "{" | 355 kMainThreadName, 1, 2, 4); |
450 "\"descendants\":[" | |
451 "]," | |
452 "\"list\":[" | |
453 "{" | |
454 "\"birth_thread\":\"SomeMainThreadName\"," | |
455 "\"death_data\":{" | |
456 "\"count\":1," | |
457 "\"queue_ms\":4," | |
458 "\"queue_ms_max\":4," | |
459 "\"queue_ms_sample\":4," | |
460 "\"run_ms\":2," | |
461 "\"run_ms_max\":2," | |
462 "\"run_ms_sample\":2" | |
463 "}," | |
464 "\"death_thread\":\"SomeMainThreadName\"," | |
465 "\"location\":{" | |
466 "\"file_name\":\"FixedFileName\"," | |
467 "\"function_name\":\"LifeCycleToValueMainThread\"," | |
468 "\"line_number\":236" | |
469 "}" | |
470 "}" | |
471 "]" | |
472 "}"; | |
473 EXPECT_EQ(one_line_result, json); | |
474 } | 356 } |
475 | 357 |
476 // We will deactivate tracking after the birth, and before the death, and | 358 // We will deactivate tracking after the birth, and before the death, and |
477 // demonstrate that the lifecycle is completely tallied. This ensures that | 359 // demonstrate that the lifecycle is completely tallied. This ensures that |
478 // our tallied births are matched by tallied deaths (except for when the | 360 // our tallied births are matched by tallied deaths (except for when the |
479 // task is still running, or is queued). | 361 // task is still running, or is queued). |
480 TEST_F(TrackedObjectsTest, LifeCycleMidDeactivatedToValueMainThread) { | 362 TEST_F(TrackedObjectsTest, LifeCycleMidDeactivatedToSnapshotMainThread) { |
481 if (!ThreadData::InitializeAndSetTrackingStatus( | 363 if (!ThreadData::InitializeAndSetTrackingStatus( |
482 ThreadData::PROFILING_CHILDREN_ACTIVE)) | 364 ThreadData::PROFILING_CHILDREN_ACTIVE)) |
483 return; | 365 return; |
484 | 366 |
485 // Use a well named thread. | 367 const char kFunction[] = "LifeCycleMidDeactivatedToSnapshotMainThread"; |
486 ThreadData::InitializeThreadContext("SomeMainThreadName"); | 368 Location location(kFunction, kFile, kLineNumber, NULL); |
487 const int kFakeLineNumber = 236; | 369 TallyABirth(location, kMainThreadName); |
488 const char* kFile = "FixedFileName"; | |
489 const char* kFunction = "LifeCycleToValueMainThread"; | |
490 Location location(kFunction, kFile, kFakeLineNumber, NULL); | |
491 // Do not delete birth. We don't own it. | |
492 Births* birth = ThreadData::TallyABirthIfActive(location); | |
493 EXPECT_NE(birth, reinterpret_cast<Births*>(NULL)); | |
494 | 370 |
495 const base::TimeTicks kTimePosted = base::TimeTicks() | 371 const base::TimeTicks kTimePosted = base::TimeTicks() + |
496 + base::TimeDelta::FromMilliseconds(1); | 372 base::TimeDelta::FromMilliseconds(1); |
497 const base::TimeTicks kDelayedStartTime = base::TimeTicks(); | 373 const base::TimeTicks kDelayedStartTime = base::TimeTicks(); |
498 // TrackingInfo will call TallyABirth() during construction. | 374 // TrackingInfo will call TallyABirth() during construction. |
499 base::TrackingInfo pending_task(location, kDelayedStartTime); | 375 base::TrackingInfo pending_task(location, kDelayedStartTime); |
500 pending_task.time_posted = kTimePosted; // Overwrite implied Now(). | 376 pending_task.time_posted = kTimePosted; // Overwrite implied Now(). |
501 | 377 |
502 // Turn off tracking now that we have births. | 378 // Turn off tracking now that we have births. |
503 EXPECT_TRUE(ThreadData::InitializeAndSetTrackingStatus( | 379 EXPECT_TRUE(ThreadData::InitializeAndSetTrackingStatus( |
504 ThreadData::DEACTIVATED)); | 380 ThreadData::DEACTIVATED)); |
505 | 381 |
506 const TrackedTime kStartOfRun = TrackedTime() + | 382 const TrackedTime kStartOfRun = TrackedTime() + |
507 Duration::FromMilliseconds(5); | 383 Duration::FromMilliseconds(5); |
508 const TrackedTime kEndOfRun = TrackedTime() + Duration::FromMilliseconds(7); | 384 const TrackedTime kEndOfRun = TrackedTime() + Duration::FromMilliseconds(7); |
509 ThreadData::TallyRunOnNamedThreadIfTracking(pending_task, | 385 ThreadData::TallyRunOnNamedThreadIfTracking(pending_task, |
510 kStartOfRun, kEndOfRun); | 386 kStartOfRun, kEndOfRun); |
511 | 387 |
512 scoped_ptr<base::Value> value(ThreadData::ToValue(false)); | 388 ProcessDataSnapshot process_data; |
513 std::string json; | 389 ThreadData::Snapshot(false, &process_data); |
514 base::JSONWriter::Write(value.get(), &json); | 390 ExpectSimpleProcessData(process_data, kFunction, kMainThreadName, |
515 std::string one_line_result = "{" | 391 kMainThreadName, 1, 2, 4); |
516 "\"descendants\":[" | |
517 "]," | |
518 "\"list\":[" | |
519 "{" | |
520 "\"birth_thread\":\"SomeMainThreadName\"," | |
521 "\"death_data\":{" | |
522 "\"count\":1," | |
523 "\"queue_ms\":4," | |
524 "\"queue_ms_max\":4," | |
525 "\"queue_ms_sample\":4," | |
526 "\"run_ms\":2," | |
527 "\"run_ms_max\":2," | |
528 "\"run_ms_sample\":2" | |
529 "}," | |
530 "\"death_thread\":\"SomeMainThreadName\"," | |
531 "\"location\":{" | |
532 "\"file_name\":\"FixedFileName\"," | |
533 "\"function_name\":\"LifeCycleToValueMainThread\"," | |
534 "\"line_number\":236" | |
535 "}" | |
536 "}" | |
537 "]" | |
538 "}"; | |
539 EXPECT_EQ(one_line_result, json); | |
540 } | 392 } |
541 | 393 |
542 // We will deactivate tracking before starting a life cycle, and neither | 394 // We will deactivate tracking before starting a life cycle, and neither |
543 // the birth nor the death will be recorded. | 395 // the birth nor the death will be recorded. |
544 TEST_F(TrackedObjectsTest, LifeCyclePreDeactivatedToValueMainThread) { | 396 TEST_F(TrackedObjectsTest, LifeCyclePreDeactivatedToSnapshotMainThread) { |
| 397 // Start in the deactivated state. |
545 if (!ThreadData::InitializeAndSetTrackingStatus(ThreadData::DEACTIVATED)) | 398 if (!ThreadData::InitializeAndSetTrackingStatus(ThreadData::DEACTIVATED)) |
546 return; | 399 return; |
547 | 400 |
548 // Use a well named thread. | 401 const char kFunction[] = "LifeCyclePreDeactivatedToSnapshotMainThread"; |
549 ThreadData::InitializeThreadContext("SomeMainThreadName"); | 402 Location location(kFunction, kFile, kLineNumber, NULL); |
550 const int kFakeLineNumber = 236; | 403 TallyABirth(location, kMainThreadName); |
551 const char* kFile = "FixedFileName"; | |
552 const char* kFunction = "LifeCycleToValueMainThread"; | |
553 Location location(kFunction, kFile, kFakeLineNumber, NULL); | |
554 // Do not delete birth. We don't own it. | |
555 Births* birth = ThreadData::TallyABirthIfActive(location); | |
556 EXPECT_EQ(birth, reinterpret_cast<Births*>(NULL)); | |
557 | 404 |
558 const base::TimeTicks kTimePosted = base::TimeTicks() | 405 const base::TimeTicks kTimePosted = base::TimeTicks() + |
559 + base::TimeDelta::FromMilliseconds(1); | 406 base::TimeDelta::FromMilliseconds(1); |
560 const base::TimeTicks kDelayedStartTime = base::TimeTicks(); | 407 const base::TimeTicks kDelayedStartTime = base::TimeTicks(); |
561 // TrackingInfo will call TallyABirth() during construction. | 408 // TrackingInfo will call TallyABirth() during construction. |
562 base::TrackingInfo pending_task(location, kDelayedStartTime); | 409 base::TrackingInfo pending_task(location, kDelayedStartTime); |
563 pending_task.time_posted = kTimePosted; // Overwrite implied Now(). | 410 pending_task.time_posted = kTimePosted; // Overwrite implied Now(). |
564 | 411 |
565 const TrackedTime kStartOfRun = TrackedTime() + | 412 const TrackedTime kStartOfRun = TrackedTime() + |
566 Duration::FromMilliseconds(5); | 413 Duration::FromMilliseconds(5); |
567 const TrackedTime kEndOfRun = TrackedTime() + Duration::FromMilliseconds(7); | 414 const TrackedTime kEndOfRun = TrackedTime() + Duration::FromMilliseconds(7); |
568 ThreadData::TallyRunOnNamedThreadIfTracking(pending_task, | 415 ThreadData::TallyRunOnNamedThreadIfTracking(pending_task, |
569 kStartOfRun, kEndOfRun); | 416 kStartOfRun, kEndOfRun); |
570 | 417 |
571 scoped_ptr<base::Value> value(ThreadData::ToValue(false)); | 418 ProcessDataSnapshot process_data; |
572 std::string json; | 419 ThreadData::Snapshot(false, &process_data); |
573 base::JSONWriter::Write(value.get(), &json); | 420 EXPECT_EQ(0u, process_data.tasks.size()); |
574 std::string one_line_result = "{" | 421 EXPECT_EQ(0u, process_data.descendants.size()); |
575 "\"descendants\":[" | 422 EXPECT_EQ(base::GetCurrentProcId(), process_data.process_id); |
576 "]," | |
577 "\"list\":[" | |
578 "]" | |
579 "}"; | |
580 EXPECT_EQ(one_line_result, json); | |
581 } | 423 } |
582 | 424 |
583 TEST_F(TrackedObjectsTest, LifeCycleToValueWorkerThread) { | 425 TEST_F(TrackedObjectsTest, LifeCycleToSnapshotWorkerThread) { |
584 if (!ThreadData::InitializeAndSetTrackingStatus( | 426 if (!ThreadData::InitializeAndSetTrackingStatus( |
585 ThreadData::PROFILING_CHILDREN_ACTIVE)) | 427 ThreadData::PROFILING_CHILDREN_ACTIVE)) |
586 return; | 428 return; |
587 | 429 |
588 // Don't initialize thread, so that we appear as a worker thread. | 430 const char kFunction[] = "LifeCycleToSnapshotWorkerThread"; |
589 // ThreadData::InitializeThreadContext("SomeMainThreadName"); | 431 Location location(kFunction, kFile, kLineNumber, NULL); |
590 | 432 // Do not delete |birth|. We don't own it. |
591 const int kFakeLineNumber = 236; | |
592 const char* kFile = "FixedFileName"; | |
593 const char* kFunction = "LifeCycleToValueWorkerThread"; | |
594 Location location(kFunction, kFile, kFakeLineNumber, NULL); | |
595 // Do not delete birth. We don't own it. | |
596 Births* birth = ThreadData::TallyABirthIfActive(location); | 433 Births* birth = ThreadData::TallyABirthIfActive(location); |
597 EXPECT_NE(birth, reinterpret_cast<Births*>(NULL)); | 434 EXPECT_NE(reinterpret_cast<Births*>(NULL), birth); |
598 | 435 |
599 const TrackedTime kTimePosted = TrackedTime() + Duration::FromMilliseconds(1); | 436 const TrackedTime kTimePosted = TrackedTime() + Duration::FromMilliseconds(1); |
600 const TrackedTime kStartOfRun = TrackedTime() + | 437 const TrackedTime kStartOfRun = TrackedTime() + |
601 Duration::FromMilliseconds(5); | 438 Duration::FromMilliseconds(5); |
602 const TrackedTime kEndOfRun = TrackedTime() + Duration::FromMilliseconds(7); | 439 const TrackedTime kEndOfRun = TrackedTime() + Duration::FromMilliseconds(7); |
603 ThreadData::TallyRunOnWorkerThreadIfTracking(birth, kTimePosted, | 440 ThreadData::TallyRunOnWorkerThreadIfTracking(birth, kTimePosted, |
604 kStartOfRun, kEndOfRun); | 441 kStartOfRun, kEndOfRun); |
605 | 442 |
606 // Call for the ToValue, but tell it to not the maxes after scanning. | 443 // Call for the ToSnapshot, but tell it to not reset the maxes after scanning. |
607 scoped_ptr<base::Value> value(ThreadData::ToValue(false)); | 444 ProcessDataSnapshot process_data; |
608 std::string json; | 445 ThreadData::Snapshot(false, &process_data); |
609 base::JSONWriter::Write(value.get(), &json); | 446 ExpectSimpleProcessData(process_data, kFunction, kWorkerThreadName, |
610 std::string one_line_result = "{" | 447 kWorkerThreadName, 1, 2, 4); |
611 "\"descendants\":[" | |
612 "]," | |
613 "\"list\":[" | |
614 "{" | |
615 "\"birth_thread\":\"WorkerThread-1\"," | |
616 "\"death_data\":{" | |
617 "\"count\":1," | |
618 "\"queue_ms\":4," | |
619 "\"queue_ms_max\":4," | |
620 "\"queue_ms_sample\":4," | |
621 "\"run_ms\":2," | |
622 "\"run_ms_max\":2," | |
623 "\"run_ms_sample\":2" | |
624 "}," | |
625 "\"death_thread\":\"WorkerThread-1\"," | |
626 "\"location\":{" | |
627 "\"file_name\":\"FixedFileName\"," | |
628 "\"function_name\":\"LifeCycleToValueWorkerThread\"," | |
629 "\"line_number\":236" | |
630 "}" | |
631 "}" | |
632 "]" | |
633 "}"; | |
634 EXPECT_EQ(one_line_result, json); | |
635 | 448 |
636 // Call for the ToValue, but tell it to reset the maxes after scanning. | 449 // Call for the ToSnapshot, but tell it to reset the maxes after scanning. |
637 // We'll still get the same values, but the data will be reset (which we'll | 450 // We'll still get the same values, but the data will be reset (which we'll |
638 // see in a moment). | 451 // see in a moment). |
639 value.reset(ThreadData::ToValue(true)); | 452 ProcessDataSnapshot process_data_pre_reset; |
640 base::JSONWriter::Write(value.get(), &json); | 453 ThreadData::Snapshot(true, &process_data_pre_reset); |
641 // Result should be unchanged. | 454 ExpectSimpleProcessData(process_data, kFunction, kWorkerThreadName, |
642 EXPECT_EQ(one_line_result, json); | 455 kWorkerThreadName, 1, 2, 4); |
643 | 456 |
644 // Call for the ToValue, and now we'll see the result of the last translation, | 457 // Call for the ToSnapshot, and now we'll see the result of the last |
645 // as the max will have been pushed back to zero. | 458 // translation, as the max will have been pushed back to zero. |
646 value.reset(ThreadData::ToValue(false)); | 459 ProcessDataSnapshot process_data_post_reset; |
647 base::JSONWriter::Write(value.get(), &json); | 460 ThreadData::Snapshot(true, &process_data_post_reset); |
648 std::string one_line_result_with_zeros = "{" | 461 ASSERT_EQ(1u, process_data_post_reset.tasks.size()); |
649 "\"descendants\":[" | 462 EXPECT_EQ(kFile, process_data_post_reset.tasks[0].birth.location.file_name); |
650 "]," | 463 EXPECT_EQ(kFunction, |
651 "\"list\":[" | 464 process_data_post_reset.tasks[0].birth.location.function_name); |
652 "{" | 465 EXPECT_EQ(kLineNumber, |
653 "\"birth_thread\":\"WorkerThread-1\"," | 466 process_data_post_reset.tasks[0].birth.location.line_number); |
654 "\"death_data\":{" | 467 EXPECT_EQ(kWorkerThreadName, |
655 "\"count\":1," | 468 process_data_post_reset.tasks[0].birth.thread_name); |
656 "\"queue_ms\":4," | 469 EXPECT_EQ(1, process_data_post_reset.tasks[0].death_data.count); |
657 "\"queue_ms_max\":0," // Note zero here. | 470 EXPECT_EQ(2, process_data_post_reset.tasks[0].death_data.run_duration_sum); |
658 "\"queue_ms_sample\":4," | 471 EXPECT_EQ(0, process_data_post_reset.tasks[0].death_data.run_duration_max); |
659 "\"run_ms\":2," | 472 EXPECT_EQ(2, process_data_post_reset.tasks[0].death_data.run_duration_sample); |
660 "\"run_ms_max\":0," // Note zero here. | 473 EXPECT_EQ(4, process_data_post_reset.tasks[0].death_data.queue_duration_sum); |
661 "\"run_ms_sample\":2" | 474 EXPECT_EQ(0, process_data_post_reset.tasks[0].death_data.queue_duration_max); |
662 "}," | 475 EXPECT_EQ(4, |
663 "\"death_thread\":\"WorkerThread-1\"," | 476 process_data_post_reset.tasks[0].death_data.queue_duration_sample); |
664 "\"location\":{" | 477 EXPECT_EQ(kWorkerThreadName, |
665 "\"file_name\":\"FixedFileName\"," | 478 process_data_post_reset.tasks[0].death_thread_name); |
666 "\"function_name\":\"LifeCycleToValueWorkerThread\"," | 479 EXPECT_EQ(0u, process_data_post_reset.descendants.size()); |
667 "\"line_number\":236" | 480 EXPECT_EQ(base::GetCurrentProcId(), process_data_post_reset.process_id); |
668 "}" | |
669 "}" | |
670 "]" | |
671 "}"; | |
672 EXPECT_EQ(one_line_result_with_zeros, json); | |
673 } | 481 } |
674 | 482 |
675 TEST_F(TrackedObjectsTest, TwoLives) { | 483 TEST_F(TrackedObjectsTest, TwoLives) { |
676 if (!ThreadData::InitializeAndSetTrackingStatus( | 484 if (!ThreadData::InitializeAndSetTrackingStatus( |
677 ThreadData::PROFILING_CHILDREN_ACTIVE)) | 485 ThreadData::PROFILING_CHILDREN_ACTIVE)) |
678 return; | 486 return; |
679 | 487 |
680 // Use a well named thread. | 488 const char kFunction[] = "TwoLives"; |
681 ThreadData::InitializeThreadContext("SomeFileThreadName"); | 489 Location location(kFunction, kFile, kLineNumber, NULL); |
682 const int kFakeLineNumber = 222; | 490 TallyABirth(location, kMainThreadName); |
683 const char* kFile = "AnotherFileName"; | |
684 const char* kFunction = "TwoLives"; | |
685 Location location(kFunction, kFile, kFakeLineNumber, NULL); | |
686 // Do not delete birth. We don't own it. | |
687 Births* birth = ThreadData::TallyABirthIfActive(location); | |
688 EXPECT_NE(birth, reinterpret_cast<Births*>(NULL)); | |
689 | 491 |
690 | 492 const base::TimeTicks kTimePosted = base::TimeTicks() + |
691 const base::TimeTicks kTimePosted = base::TimeTicks() | 493 base::TimeDelta::FromMilliseconds(1); |
692 + base::TimeDelta::FromMilliseconds(1); | |
693 const base::TimeTicks kDelayedStartTime = base::TimeTicks(); | 494 const base::TimeTicks kDelayedStartTime = base::TimeTicks(); |
694 // TrackingInfo will call TallyABirth() during construction. | 495 // TrackingInfo will call TallyABirth() during construction. |
695 base::TrackingInfo pending_task(location, kDelayedStartTime); | 496 base::TrackingInfo pending_task(location, kDelayedStartTime); |
696 pending_task.time_posted = kTimePosted; // Overwrite implied Now(). | 497 pending_task.time_posted = kTimePosted; // Overwrite implied Now(). |
697 | 498 |
698 const TrackedTime kStartOfRun = TrackedTime() + | 499 const TrackedTime kStartOfRun = TrackedTime() + |
699 Duration::FromMilliseconds(5); | 500 Duration::FromMilliseconds(5); |
700 const TrackedTime kEndOfRun = TrackedTime() + Duration::FromMilliseconds(7); | 501 const TrackedTime kEndOfRun = TrackedTime() + Duration::FromMilliseconds(7); |
701 ThreadData::TallyRunOnNamedThreadIfTracking(pending_task, | 502 ThreadData::TallyRunOnNamedThreadIfTracking(pending_task, |
702 kStartOfRun, kEndOfRun); | 503 kStartOfRun, kEndOfRun); |
703 | 504 |
704 // TrackingInfo will call TallyABirth() during construction. | 505 // TrackingInfo will call TallyABirth() during construction. |
705 base::TrackingInfo pending_task2(location, kDelayedStartTime); | 506 base::TrackingInfo pending_task2(location, kDelayedStartTime); |
706 pending_task2.time_posted = kTimePosted; // Overwrite implied Now(). | 507 pending_task2.time_posted = kTimePosted; // Overwrite implied Now(). |
707 | 508 |
708 ThreadData::TallyRunOnNamedThreadIfTracking(pending_task2, | 509 ThreadData::TallyRunOnNamedThreadIfTracking(pending_task2, |
709 kStartOfRun, kEndOfRun); | 510 kStartOfRun, kEndOfRun); |
710 | 511 |
711 scoped_ptr<base::Value> value(ThreadData::ToValue(false)); | 512 ProcessDataSnapshot process_data; |
712 std::string json; | 513 ThreadData::Snapshot(false, &process_data); |
713 base::JSONWriter::Write(value.get(), &json); | 514 ExpectSimpleProcessData(process_data, kFunction, kMainThreadName, |
714 std::string one_line_result = "{" | 515 kMainThreadName, 2, 2, 4); |
715 "\"descendants\":[" | |
716 "]," | |
717 "\"list\":[" | |
718 "{" | |
719 "\"birth_thread\":\"SomeFileThreadName\"," | |
720 "\"death_data\":{" | |
721 "\"count\":2," | |
722 "\"queue_ms\":8," | |
723 "\"queue_ms_max\":4," | |
724 "\"queue_ms_sample\":4," | |
725 "\"run_ms\":4," | |
726 "\"run_ms_max\":2," | |
727 "\"run_ms_sample\":2" | |
728 "}," | |
729 "\"death_thread\":\"SomeFileThreadName\"," | |
730 "\"location\":{" | |
731 "\"file_name\":\"AnotherFileName\"," | |
732 "\"function_name\":\"TwoLives\"," | |
733 "\"line_number\":222" | |
734 "}" | |
735 "}" | |
736 "]" | |
737 "}"; | |
738 EXPECT_EQ(one_line_result, json); | |
739 } | 516 } |
740 | 517 |
741 TEST_F(TrackedObjectsTest, DifferentLives) { | 518 TEST_F(TrackedObjectsTest, DifferentLives) { |
742 if (!ThreadData::InitializeAndSetTrackingStatus( | 519 if (!ThreadData::InitializeAndSetTrackingStatus( |
743 ThreadData::PROFILING_CHILDREN_ACTIVE)) | 520 ThreadData::PROFILING_CHILDREN_ACTIVE)) |
744 return; | 521 return; |
745 | 522 |
746 // Use a well named thread. | 523 // Use a well named thread. |
747 ThreadData::InitializeThreadContext("SomeFileThreadName"); | 524 ThreadData::InitializeThreadContext(kMainThreadName); |
748 const int kFakeLineNumber = 567; | 525 const char kFunction[] = "DifferentLives"; |
749 const char* kFile = "AnotherFileName"; | 526 Location location(kFunction, kFile, kLineNumber, NULL); |
750 const char* kFunction = "DifferentLives"; | |
751 Location location(kFunction, kFile, kFakeLineNumber, NULL); | |
752 | 527 |
753 const base::TimeTicks kTimePosted = base::TimeTicks() | 528 const base::TimeTicks kTimePosted = base::TimeTicks() + |
754 + base::TimeDelta::FromMilliseconds(1); | 529 base::TimeDelta::FromMilliseconds(1); |
755 const base::TimeTicks kDelayedStartTime = base::TimeTicks(); | 530 const base::TimeTicks kDelayedStartTime = base::TimeTicks(); |
756 // TrackingInfo will call TallyABirth() during construction. | 531 // TrackingInfo will call TallyABirth() during construction. |
757 base::TrackingInfo pending_task(location, kDelayedStartTime); | 532 base::TrackingInfo pending_task(location, kDelayedStartTime); |
758 pending_task.time_posted = kTimePosted; // Overwrite implied Now(). | 533 pending_task.time_posted = kTimePosted; // Overwrite implied Now(). |
759 | 534 |
760 const TrackedTime kStartOfRun = TrackedTime() + | 535 const TrackedTime kStartOfRun = TrackedTime() + |
761 Duration::FromMilliseconds(5); | 536 Duration::FromMilliseconds(5); |
762 const TrackedTime kEndOfRun = TrackedTime() + Duration::FromMilliseconds(7); | 537 const TrackedTime kEndOfRun = TrackedTime() + Duration::FromMilliseconds(7); |
763 ThreadData::TallyRunOnNamedThreadIfTracking(pending_task, | 538 ThreadData::TallyRunOnNamedThreadIfTracking(pending_task, |
764 kStartOfRun, kEndOfRun); | 539 kStartOfRun, kEndOfRun); |
765 | 540 |
766 const int kSecondFakeLineNumber = 999; | 541 const int kSecondFakeLineNumber = 999; |
767 Location second_location(kFunction, kFile, kSecondFakeLineNumber, NULL); | 542 Location second_location(kFunction, kFile, kSecondFakeLineNumber, NULL); |
768 | 543 |
769 // TrackingInfo will call TallyABirth() during construction. | 544 // TrackingInfo will call TallyABirth() during construction. |
770 base::TrackingInfo pending_task2(second_location, kDelayedStartTime); | 545 base::TrackingInfo pending_task2(second_location, kDelayedStartTime); |
771 pending_task2.time_posted = kTimePosted; // Overwrite implied Now(). | 546 pending_task2.time_posted = kTimePosted; // Overwrite implied Now(). |
772 | 547 |
773 scoped_ptr<base::Value> value(ThreadData::ToValue(false)); | 548 ProcessDataSnapshot process_data; |
774 std::string json; | 549 ThreadData::Snapshot(false, &process_data); |
775 base::JSONWriter::Write(value.get(), &json); | 550 ASSERT_EQ(2u, process_data.tasks.size()); |
776 std::string one_line_result = "{" | 551 EXPECT_EQ(kFile, process_data.tasks[0].birth.location.file_name); |
777 "\"descendants\":[" | 552 EXPECT_EQ(kFunction, process_data.tasks[0].birth.location.function_name); |
778 "]," | 553 EXPECT_EQ(kLineNumber, process_data.tasks[0].birth.location.line_number); |
779 "\"list\":[" | 554 EXPECT_EQ(kMainThreadName, process_data.tasks[0].birth.thread_name); |
780 "{" | 555 EXPECT_EQ(1, process_data.tasks[0].death_data.count); |
781 "\"birth_thread\":\"SomeFileThreadName\"," | 556 EXPECT_EQ(2, process_data.tasks[0].death_data.run_duration_sum); |
782 "\"death_data\":{" | 557 EXPECT_EQ(2, process_data.tasks[0].death_data.run_duration_max); |
783 "\"count\":1," | 558 EXPECT_EQ(2, process_data.tasks[0].death_data.run_duration_sample); |
784 "\"queue_ms\":4," | 559 EXPECT_EQ(4, process_data.tasks[0].death_data.queue_duration_sum); |
785 "\"queue_ms_max\":4," | 560 EXPECT_EQ(4, process_data.tasks[0].death_data.queue_duration_max); |
786 "\"queue_ms_sample\":4," | 561 EXPECT_EQ(4, process_data.tasks[0].death_data.queue_duration_sample); |
787 "\"run_ms\":2," | 562 EXPECT_EQ(kMainThreadName, process_data.tasks[0].death_thread_name); |
788 "\"run_ms_max\":2," | 563 EXPECT_EQ(kFile, process_data.tasks[1].birth.location.file_name); |
789 "\"run_ms_sample\":2" | 564 EXPECT_EQ(kFunction, process_data.tasks[1].birth.location.function_name); |
790 "}," | 565 EXPECT_EQ(kSecondFakeLineNumber, |
791 "\"death_thread\":\"SomeFileThreadName\"," | 566 process_data.tasks[1].birth.location.line_number); |
792 "\"location\":{" | 567 EXPECT_EQ(kMainThreadName, process_data.tasks[1].birth.thread_name); |
793 "\"file_name\":\"AnotherFileName\"," | 568 EXPECT_EQ(1, process_data.tasks[1].death_data.count); |
794 "\"function_name\":\"DifferentLives\"," | 569 EXPECT_EQ(0, process_data.tasks[1].death_data.run_duration_sum); |
795 "\"line_number\":567" | 570 EXPECT_EQ(0, process_data.tasks[1].death_data.run_duration_max); |
796 "}" | 571 EXPECT_EQ(0, process_data.tasks[1].death_data.run_duration_sample); |
797 "}," | 572 EXPECT_EQ(0, process_data.tasks[1].death_data.queue_duration_sum); |
798 "{" | 573 EXPECT_EQ(0, process_data.tasks[1].death_data.queue_duration_max); |
799 "\"birth_thread\":\"SomeFileThreadName\"," | 574 EXPECT_EQ(0, process_data.tasks[1].death_data.queue_duration_sample); |
800 "\"death_data\":{" | 575 EXPECT_EQ(kStillAlive, process_data.tasks[1].death_thread_name); |
801 "\"count\":1," | 576 EXPECT_EQ(0u, process_data.descendants.size()); |
802 "\"queue_ms\":0," | 577 EXPECT_EQ(base::GetCurrentProcId(), process_data.process_id); |
803 "\"queue_ms_max\":0," | |
804 "\"queue_ms_sample\":0," | |
805 "\"run_ms\":0," | |
806 "\"run_ms_max\":0," | |
807 "\"run_ms_sample\":0" | |
808 "}," | |
809 "\"death_thread\":\"Still_Alive\"," | |
810 "\"location\":{" | |
811 "\"file_name\":\"AnotherFileName\"," | |
812 "\"function_name\":\"DifferentLives\"," | |
813 "\"line_number\":999" | |
814 "}" | |
815 "}" | |
816 "]" | |
817 "}"; | |
818 EXPECT_EQ(one_line_result, json); | |
819 } | 578 } |
820 | 579 |
821 | |
822 } // namespace tracked_objects | 580 } // namespace tracked_objects |
OLD | NEW |