OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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" | 9 #include "base/json/json_writer.h" |
10 #include "base/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.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 namespace tracked_objects { | 14 namespace tracked_objects { |
15 | 15 |
16 class TrackedObjectsTest : public testing::Test { | 16 class TrackedObjectsTest : public testing::Test { |
17 public: | 17 public: |
18 ~TrackedObjectsTest() { | 18 TrackedObjectsTest() { |
19 ThreadData::ShutdownSingleThreadedCleanup(); | 19 ThreadData::ShutdownSingleThreadedCleanup(); |
20 } | 20 } |
21 | 21 |
| 22 ~TrackedObjectsTest() { |
| 23 ThreadData::ShutdownSingleThreadedCleanup(); |
| 24 } |
22 }; | 25 }; |
23 | 26 |
24 TEST_F(TrackedObjectsTest, MinimalStartupShutdown) { | 27 TEST_F(TrackedObjectsTest, MinimalStartupShutdown) { |
25 // Minimal test doesn't even create any tasks. | 28 // Minimal test doesn't even create any tasks. |
26 if (!ThreadData::StartTracking(true)) | 29 if (!ThreadData::InitializeAndSetTrackingStatus(true)) |
27 return; | 30 return; |
28 | 31 |
29 EXPECT_FALSE(ThreadData::first()); // No activity even on this thread. | 32 EXPECT_FALSE(ThreadData::first()); // No activity even on this thread. |
30 ThreadData* data = ThreadData::Get(); | 33 ThreadData* data = ThreadData::Get(); |
31 EXPECT_TRUE(ThreadData::first()); // Now class was constructed. | 34 EXPECT_TRUE(ThreadData::first()); // Now class was constructed. |
32 EXPECT_TRUE(data); | 35 EXPECT_TRUE(data); |
33 EXPECT_TRUE(!data->next()); | 36 EXPECT_TRUE(!data->next()); |
34 EXPECT_EQ(data, ThreadData::Get()); | 37 EXPECT_EQ(data, ThreadData::Get()); |
35 ThreadData::BirthMap birth_map; | 38 ThreadData::BirthMap birth_map; |
36 data->SnapshotBirthMap(&birth_map); | 39 data->SnapshotBirthMap(&birth_map); |
37 EXPECT_EQ(0u, birth_map.size()); | 40 EXPECT_EQ(0u, birth_map.size()); |
38 ThreadData::DeathMap death_map; | 41 ThreadData::DeathMap death_map; |
39 data->SnapshotDeathMap(&death_map); | 42 data->SnapshotDeathMap(&death_map); |
40 EXPECT_EQ(0u, death_map.size()); | 43 EXPECT_EQ(0u, death_map.size()); |
41 ThreadData::ShutdownSingleThreadedCleanup(); | 44 ThreadData::ShutdownSingleThreadedCleanup(); |
42 | 45 |
43 // Do it again, just to be sure we reset state completely. | 46 // Do it again, just to be sure we reset state completely. |
44 ThreadData::StartTracking(true); | 47 ThreadData::InitializeAndSetTrackingStatus(true); |
45 EXPECT_FALSE(ThreadData::first()); // No activity even on this thread. | 48 EXPECT_FALSE(ThreadData::first()); // No activity even on this thread. |
46 data = ThreadData::Get(); | 49 data = ThreadData::Get(); |
47 EXPECT_TRUE(ThreadData::first()); // Now class was constructed. | 50 EXPECT_TRUE(ThreadData::first()); // Now class was constructed. |
48 EXPECT_TRUE(data); | 51 EXPECT_TRUE(data); |
49 EXPECT_TRUE(!data->next()); | 52 EXPECT_TRUE(!data->next()); |
50 EXPECT_EQ(data, ThreadData::Get()); | 53 EXPECT_EQ(data, ThreadData::Get()); |
51 birth_map.clear(); | 54 birth_map.clear(); |
52 data->SnapshotBirthMap(&birth_map); | 55 data->SnapshotBirthMap(&birth_map); |
53 EXPECT_EQ(0u, birth_map.size()); | 56 EXPECT_EQ(0u, birth_map.size()); |
54 death_map.clear(); | 57 death_map.clear(); |
55 data->SnapshotDeathMap(&death_map); | 58 data->SnapshotDeathMap(&death_map); |
56 EXPECT_EQ(0u, death_map.size()); | 59 EXPECT_EQ(0u, death_map.size()); |
57 } | 60 } |
58 | 61 |
59 TEST_F(TrackedObjectsTest, TinyStartupShutdown) { | 62 TEST_F(TrackedObjectsTest, TinyStartupShutdown) { |
60 if (!ThreadData::StartTracking(true)) | 63 if (!ThreadData::InitializeAndSetTrackingStatus(true)) |
61 return; | 64 return; |
62 | 65 |
63 // Instigate tracking on a single tracked object, on our thread. | 66 // Instigate tracking on a single tracked object, on our thread. |
64 const Location& location = FROM_HERE; | 67 const Location& location = FROM_HERE; |
65 ThreadData::TallyABirthIfActive(location); | 68 ThreadData::TallyABirthIfActive(location); |
66 | 69 |
67 const ThreadData* data = ThreadData::first(); | 70 const ThreadData* data = ThreadData::first(); |
68 ASSERT_TRUE(data); | 71 ASSERT_TRUE(data); |
69 EXPECT_TRUE(!data->next()); | 72 EXPECT_TRUE(!data->next()); |
70 EXPECT_EQ(data, ThreadData::Get()); | 73 EXPECT_EQ(data, ThreadData::Get()); |
71 ThreadData::BirthMap birth_map; | 74 ThreadData::BirthMap birth_map; |
72 data->SnapshotBirthMap(&birth_map); | 75 data->SnapshotBirthMap(&birth_map); |
73 EXPECT_EQ(1u, birth_map.size()); // 1 birth location. | 76 EXPECT_EQ(1u, birth_map.size()); // 1 birth location. |
74 EXPECT_EQ(1, birth_map.begin()->second->birth_count()); // 1 birth. | 77 EXPECT_EQ(1, birth_map.begin()->second->birth_count()); // 1 birth. |
75 ThreadData::DeathMap death_map; | 78 ThreadData::DeathMap death_map; |
76 data->SnapshotDeathMap(&death_map); | 79 data->SnapshotDeathMap(&death_map); |
77 EXPECT_EQ(0u, death_map.size()); // No deaths. | 80 EXPECT_EQ(0u, death_map.size()); // No deaths. |
78 | 81 |
79 | 82 |
80 // Now instigate a birth, and a death. | 83 // Now instigate another birth, and a first death at the same location. |
81 const Births* second_birth = ThreadData::TallyABirthIfActive(location); | 84 // TrackingInfo will call TallyABirth() during construction. |
82 ThreadData::TallyADeathIfActive( | 85 base::TimeTicks kBogusStartTime; |
83 second_birth, | 86 base::TrackingInfo pending_task(location, kBogusStartTime); |
84 base::TimeTicks(), /* Bogus post_time. */ | 87 TrackedTime kBogusStartRunTime; |
85 base::TimeTicks(), /* Bogus delayed_start_time. */ | 88 TrackedTime kBogusEndRunTime; |
86 base::TimeTicks(), /* Bogus start_run_time. */ | 89 ThreadData::TallyRunOnNamedThreadIfTracking(pending_task, kBogusStartRunTime, |
87 base::TimeTicks() /* Bogus end_run_time */ ); | 90 kBogusEndRunTime); |
88 | 91 |
89 birth_map.clear(); | 92 birth_map.clear(); |
90 data->SnapshotBirthMap(&birth_map); | 93 data->SnapshotBirthMap(&birth_map); |
91 EXPECT_EQ(1u, birth_map.size()); // 1 birth location. | 94 EXPECT_EQ(1u, birth_map.size()); // 1 birth location. |
92 EXPECT_EQ(2, birth_map.begin()->second->birth_count()); // 2 births. | 95 EXPECT_EQ(2, birth_map.begin()->second->birth_count()); // 2 births. |
93 death_map.clear(); | 96 death_map.clear(); |
94 data->SnapshotDeathMap(&death_map); | 97 data->SnapshotDeathMap(&death_map); |
95 EXPECT_EQ(1u, death_map.size()); // 1 location. | 98 EXPECT_EQ(1u, death_map.size()); // 1 location. |
96 EXPECT_EQ(1, death_map.begin()->second.count()); // 1 death. | 99 EXPECT_EQ(1, death_map.begin()->second.count()); // 1 death. |
97 | 100 |
98 // The births were at the same location as the one known death. | 101 // The births were at the same location as the one known death. |
99 EXPECT_EQ(birth_map.begin()->second, death_map.begin()->first); | 102 EXPECT_EQ(birth_map.begin()->second, death_map.begin()->first); |
100 } | 103 } |
101 | 104 |
102 TEST_F(TrackedObjectsTest, DeathDataTest) { | 105 TEST_F(TrackedObjectsTest, DeathDataTest) { |
103 if (!ThreadData::StartTracking(true)) | 106 if (!ThreadData::InitializeAndSetTrackingStatus(true)) |
104 return; | 107 return; |
105 | 108 |
106 scoped_ptr<DeathData> data(new DeathData()); | 109 scoped_ptr<DeathData> data(new DeathData()); |
107 ASSERT_NE(data, reinterpret_cast<DeathData*>(NULL)); | 110 ASSERT_NE(data, reinterpret_cast<DeathData*>(NULL)); |
108 EXPECT_EQ(data->run_duration(), base::TimeDelta()); | 111 EXPECT_EQ(data->run_duration(), Duration()); |
109 EXPECT_EQ(data->queue_duration(), base::TimeDelta()); | 112 EXPECT_EQ(data->queue_duration(), Duration()); |
110 EXPECT_EQ(data->AverageMsRunDuration(), 0); | 113 EXPECT_EQ(data->AverageMsRunDuration(), 0); |
111 EXPECT_EQ(data->AverageMsQueueDuration(), 0); | 114 EXPECT_EQ(data->AverageMsQueueDuration(), 0); |
112 EXPECT_EQ(data->count(), 0); | 115 EXPECT_EQ(data->count(), 0); |
113 | 116 |
114 int run_ms = 42; | 117 int run_ms = 42; |
115 int queue_ms = 8; | 118 int queue_ms = 8; |
116 | 119 |
117 base::TimeDelta run_duration = base::TimeDelta().FromMilliseconds(run_ms); | 120 Duration run_duration = Duration().FromMilliseconds(run_ms); |
118 base::TimeDelta queue_duration = base::TimeDelta().FromMilliseconds(queue_ms); | 121 Duration queue_duration = Duration().FromMilliseconds(queue_ms); |
119 data->RecordDeath(queue_duration, run_duration); | 122 data->RecordDeath(queue_duration, run_duration); |
120 EXPECT_EQ(data->run_duration(), run_duration); | 123 EXPECT_EQ(data->run_duration(), run_duration); |
121 EXPECT_EQ(data->queue_duration(), queue_duration); | 124 EXPECT_EQ(data->queue_duration(), queue_duration); |
122 EXPECT_EQ(data->AverageMsRunDuration(), run_ms); | 125 EXPECT_EQ(data->AverageMsRunDuration(), run_ms); |
123 EXPECT_EQ(data->AverageMsQueueDuration(), queue_ms); | 126 EXPECT_EQ(data->AverageMsQueueDuration(), queue_ms); |
124 EXPECT_EQ(data->count(), 1); | 127 EXPECT_EQ(data->count(), 1); |
125 | 128 |
126 data->RecordDeath(queue_duration, run_duration); | 129 data->RecordDeath(queue_duration, run_duration); |
127 EXPECT_EQ(data->run_duration(), run_duration + run_duration); | 130 EXPECT_EQ(data->run_duration(), run_duration + run_duration); |
128 EXPECT_EQ(data->queue_duration(), queue_duration + queue_duration); | 131 EXPECT_EQ(data->queue_duration(), queue_duration + queue_duration); |
(...skipping 15 matching lines...) Expand all Loading... |
144 std::string results = "Lives:2, Run:84ms(42ms/life) Queue:16ms(8ms/life) "; | 147 std::string results = "Lives:2, Run:84ms(42ms/life) Queue:16ms(8ms/life) "; |
145 EXPECT_EQ(output, results); | 148 EXPECT_EQ(output, results); |
146 | 149 |
147 scoped_ptr<base::Value> value(data->ToValue()); | 150 scoped_ptr<base::Value> value(data->ToValue()); |
148 std::string json; | 151 std::string json; |
149 base::JSONWriter::Write(value.get(), false, &json); | 152 base::JSONWriter::Write(value.get(), false, &json); |
150 std::string birth_only_result = "{\"count\":2,\"queue_ms\":16,\"run_ms\":84}"; | 153 std::string birth_only_result = "{\"count\":2,\"queue_ms\":16,\"run_ms\":84}"; |
151 EXPECT_EQ(json, birth_only_result); | 154 EXPECT_EQ(json, birth_only_result); |
152 } | 155 } |
153 | 156 |
| 157 TEST_F(TrackedObjectsTest, DeactivatedBirthOnlyToValueWorkerThread) { |
| 158 // Transition to Deactivated state before doing anything. |
| 159 if (!ThreadData::InitializeAndSetTrackingStatus(false)) |
| 160 return; |
| 161 // We don't initialize system with a thread name, so we're viewed as a worker |
| 162 // thread. |
| 163 const int kFakeLineNumber = 173; |
| 164 const char* kFile = "FixedFileName"; |
| 165 const char* kFunction = "BirthOnlyToValueWorkerThread"; |
| 166 Location location(kFunction, kFile, kFakeLineNumber, NULL); |
| 167 Births* birth = ThreadData::TallyABirthIfActive(location); |
| 168 // We should now see a NULL birth record. |
| 169 EXPECT_EQ(birth, reinterpret_cast<Births*>(NULL)); |
| 170 |
| 171 scoped_ptr<base::Value> value(ThreadData::ToValue()); |
| 172 std::string json; |
| 173 base::JSONWriter::Write(value.get(), false, &json); |
| 174 std::string birth_only_result = "{" |
| 175 "\"list\":[" |
| 176 "]" |
| 177 "}"; |
| 178 EXPECT_EQ(json, birth_only_result); |
| 179 } |
| 180 |
| 181 TEST_F(TrackedObjectsTest, DeactivatedBirthOnlyToValueMainThread) { |
| 182 // Start in the deactivated state. |
| 183 if (!ThreadData::InitializeAndSetTrackingStatus(false)) |
| 184 return; |
| 185 |
| 186 // Use a well named thread. |
| 187 ThreadData::InitializeThreadContext("SomeMainThreadName"); |
| 188 const int kFakeLineNumber = 173; |
| 189 const char* kFile = "FixedFileName"; |
| 190 const char* kFunction = "BirthOnlyToValueMainThread"; |
| 191 Location location(kFunction, kFile, kFakeLineNumber, NULL); |
| 192 // Do not delete birth. We don't own it. |
| 193 Births* birth = ThreadData::TallyABirthIfActive(location); |
| 194 // We expect to not get a birth record. |
| 195 EXPECT_EQ(birth, reinterpret_cast<Births*>(NULL)); |
| 196 |
| 197 scoped_ptr<base::Value> value(ThreadData::ToValue()); |
| 198 std::string json; |
| 199 base::JSONWriter::Write(value.get(), false, &json); |
| 200 std::string birth_only_result = "{" |
| 201 "\"list\":[" |
| 202 "]" |
| 203 "}"; |
| 204 EXPECT_EQ(json, birth_only_result); |
| 205 } |
| 206 |
154 TEST_F(TrackedObjectsTest, BirthOnlyToValueWorkerThread) { | 207 TEST_F(TrackedObjectsTest, BirthOnlyToValueWorkerThread) { |
155 if (!ThreadData::StartTracking(true)) | 208 if (!ThreadData::InitializeAndSetTrackingStatus(true)) |
156 return; | 209 return; |
157 // We don't initialize system with a thread name, so we're viewed as a worker | 210 // We don't initialize system with a thread name, so we're viewed as a worker |
158 // thread. | 211 // thread. |
159 int fake_line_number = 173; | 212 const int kFakeLineNumber = 173; |
160 const char* kFile = "FixedFileName"; | 213 const char* kFile = "FixedFileName"; |
161 const char* kFunction = "BirthOnlyToValueWorkerThread"; | 214 const char* kFunction = "BirthOnlyToValueWorkerThread"; |
162 Location location(kFunction, kFile, fake_line_number, NULL); | 215 Location location(kFunction, kFile, kFakeLineNumber, NULL); |
163 Births* birth = ThreadData::TallyABirthIfActive(location); | 216 Births* birth = ThreadData::TallyABirthIfActive(location); |
164 EXPECT_NE(birth, reinterpret_cast<Births*>(NULL)); | 217 EXPECT_NE(birth, reinterpret_cast<Births*>(NULL)); |
165 | 218 |
166 int process_type = 3; | 219 scoped_ptr<base::Value> value(ThreadData::ToValue()); |
167 scoped_ptr<base::Value> value(ThreadData::ToValue(process_type)); | |
168 std::string json; | 220 std::string json; |
169 base::JSONWriter::Write(value.get(), false, &json); | 221 base::JSONWriter::Write(value.get(), false, &json); |
170 std::string birth_only_result = "{" | 222 std::string birth_only_result = "{" |
171 "\"list\":[" | 223 "\"list\":[" |
172 "{" | 224 "{" |
173 "\"birth_thread\":\"WorkerThread-1\"," | 225 "\"birth_thread\":\"WorkerThread-1\"," |
174 "\"death_data\":{" | 226 "\"death_data\":{" |
175 "\"count\":1," | 227 "\"count\":1," |
176 "\"queue_ms\":0," | 228 "\"queue_ms\":0," |
177 "\"run_ms\":0" | 229 "\"run_ms\":0" |
178 "}," | 230 "}," |
179 "\"death_thread\":\"Still_Alive\"," | 231 "\"death_thread\":\"Still_Alive\"," |
180 "\"location\":{" | 232 "\"location\":{" |
181 "\"file_name\":\"FixedFileName\"," | 233 "\"file_name\":\"FixedFileName\"," |
182 "\"function_name\":\"BirthOnlyToValueWorkerThread\"," | 234 "\"function_name\":\"BirthOnlyToValueWorkerThread\"," |
183 "\"line_number\":173" | 235 "\"line_number\":173" |
184 "}" | 236 "}" |
185 "}" | 237 "}" |
186 "]," | 238 "]" |
187 "\"process\":3" | |
188 "}"; | 239 "}"; |
189 EXPECT_EQ(json, birth_only_result); | 240 EXPECT_EQ(json, birth_only_result); |
190 } | 241 } |
191 | 242 |
192 TEST_F(TrackedObjectsTest, BirthOnlyToValueMainThread) { | 243 TEST_F(TrackedObjectsTest, BirthOnlyToValueMainThread) { |
193 if (!ThreadData::StartTracking(true)) | 244 if (!ThreadData::InitializeAndSetTrackingStatus(true)) |
194 return; | 245 return; |
195 | 246 |
196 // Use a well named thread. | 247 // Use a well named thread. |
197 ThreadData::InitializeThreadContext("SomeMainThreadName"); | 248 ThreadData::InitializeThreadContext("SomeMainThreadName"); |
198 int fake_line_number = 173; | 249 const int kFakeLineNumber = 173; |
199 const char* kFile = "FixedFileName"; | 250 const char* kFile = "FixedFileName"; |
200 const char* kFunction = "BirthOnlyToValueMainThread"; | 251 const char* kFunction = "BirthOnlyToValueMainThread"; |
201 Location location(kFunction, kFile, fake_line_number, NULL); | 252 Location location(kFunction, kFile, kFakeLineNumber, NULL); |
202 // Do not delete birth. We don't own it. | 253 // Do not delete birth. We don't own it. |
203 Births* birth = ThreadData::TallyABirthIfActive(location); | 254 Births* birth = ThreadData::TallyABirthIfActive(location); |
204 EXPECT_NE(birth, reinterpret_cast<Births*>(NULL)); | 255 EXPECT_NE(birth, reinterpret_cast<Births*>(NULL)); |
205 | 256 |
206 int process_type = 34; | 257 scoped_ptr<base::Value> value(ThreadData::ToValue()); |
207 scoped_ptr<base::Value> value(ThreadData::ToValue(process_type)); | |
208 std::string json; | 258 std::string json; |
209 base::JSONWriter::Write(value.get(), false, &json); | 259 base::JSONWriter::Write(value.get(), false, &json); |
210 std::string birth_only_result = "{" | 260 std::string birth_only_result = "{" |
211 "\"list\":[" | 261 "\"list\":[" |
212 "{" | 262 "{" |
213 "\"birth_thread\":\"SomeMainThreadName\"," | 263 "\"birth_thread\":\"SomeMainThreadName\"," |
214 "\"death_data\":{" | 264 "\"death_data\":{" |
215 "\"count\":1," | 265 "\"count\":1," |
216 "\"queue_ms\":0," | 266 "\"queue_ms\":0," |
217 "\"run_ms\":0" | 267 "\"run_ms\":0" |
218 "}," | 268 "}," |
219 "\"death_thread\":\"Still_Alive\"," | 269 "\"death_thread\":\"Still_Alive\"," |
220 "\"location\":{" | 270 "\"location\":{" |
221 "\"file_name\":\"FixedFileName\"," | 271 "\"file_name\":\"FixedFileName\"," |
222 "\"function_name\":\"BirthOnlyToValueMainThread\"," | 272 "\"function_name\":\"BirthOnlyToValueMainThread\"," |
223 "\"line_number\":173" | 273 "\"line_number\":173" |
224 "}" | 274 "}" |
225 "}" | 275 "}" |
226 "]," | 276 "]" |
227 "\"process\":34" | |
228 "}"; | 277 "}"; |
229 EXPECT_EQ(json, birth_only_result); | 278 EXPECT_EQ(json, birth_only_result); |
230 } | 279 } |
231 | 280 |
232 TEST_F(TrackedObjectsTest, LifeCycleToValueMainThread) { | 281 TEST_F(TrackedObjectsTest, LifeCycleToValueMainThread) { |
233 if (!ThreadData::StartTracking(true)) | 282 if (!ThreadData::InitializeAndSetTrackingStatus(true)) |
234 return; | 283 return; |
235 | 284 |
236 // Use a well named thread. | 285 // Use a well named thread. |
237 ThreadData::InitializeThreadContext("SomeMainThreadName"); | 286 ThreadData::InitializeThreadContext("SomeMainThreadName"); |
238 int fake_line_number = 236; | 287 const int kFakeLineNumber = 236; |
239 const char* kFile = "FixedFileName"; | 288 const char* kFile = "FixedFileName"; |
240 const char* kFunction = "LifeCycleToValueMainThread"; | 289 const char* kFunction = "LifeCycleToValueMainThread"; |
241 Location location(kFunction, kFile, fake_line_number, NULL); | 290 Location location(kFunction, kFile, kFakeLineNumber, NULL); |
242 // Do not delete birth. We don't own it. | 291 // Do not delete birth. We don't own it. |
243 Births* birth = ThreadData::TallyABirthIfActive(location); | 292 Births* birth = ThreadData::TallyABirthIfActive(location); |
244 EXPECT_NE(birth, reinterpret_cast<Births*>(NULL)); | 293 EXPECT_NE(birth, reinterpret_cast<Births*>(NULL)); |
245 | 294 |
246 // TimeTicks initializers ar ein microseconds. Durations are calculated in | 295 const base::TimeTicks kTimePosted = base::TimeTicks() |
247 // milliseconds, so we need to use 1000x. | 296 + base::TimeDelta::FromMilliseconds(1); |
248 const base::TimeTicks time_posted = base::TimeTicks() + | 297 const base::TimeTicks kDelayedStartTime = base::TimeTicks(); |
249 base::TimeDelta::FromMilliseconds(1); | 298 // TrackingInfo will call TallyABirth() during construction. |
250 const base::TimeTicks delayed_start_time = base::TimeTicks(); | 299 base::TrackingInfo pending_task(location, kDelayedStartTime); |
251 const base::TimeTicks start_of_run = base::TimeTicks() + | 300 pending_task.time_posted = kTimePosted; // Overwrite implied Now(). |
252 base::TimeDelta::FromMilliseconds(5); | |
253 const base::TimeTicks end_of_run = base::TimeTicks() + | |
254 base::TimeDelta::FromMilliseconds(7); | |
255 ThreadData::TallyADeathIfActive(birth, time_posted, delayed_start_time, | |
256 start_of_run, end_of_run); | |
257 | 301 |
258 int process_type = 7; | 302 const TrackedTime kStartOfRun = TrackedTime() + |
259 scoped_ptr<base::Value> value(ThreadData::ToValue(process_type)); | 303 Duration::FromMilliseconds(5); |
| 304 const TrackedTime kEndOfRun = TrackedTime() + Duration::FromMilliseconds(7); |
| 305 ThreadData::TallyRunOnNamedThreadIfTracking(pending_task, |
| 306 kStartOfRun, kEndOfRun); |
| 307 |
| 308 scoped_ptr<base::Value> value(ThreadData::ToValue()); |
260 std::string json; | 309 std::string json; |
261 base::JSONWriter::Write(value.get(), false, &json); | 310 base::JSONWriter::Write(value.get(), false, &json); |
262 std::string one_line_result = "{" | 311 std::string one_line_result = "{" |
263 "\"list\":[" | 312 "\"list\":[" |
264 "{" | 313 "{" |
265 "\"birth_thread\":\"SomeMainThreadName\"," | 314 "\"birth_thread\":\"SomeMainThreadName\"," |
266 "\"death_data\":{" | 315 "\"death_data\":{" |
267 "\"count\":1," | 316 "\"count\":1," |
268 "\"queue_ms\":4," | 317 "\"queue_ms\":4," |
269 "\"run_ms\":2" | 318 "\"run_ms\":2" |
270 "}," | 319 "}," |
271 "\"death_thread\":\"SomeMainThreadName\"," | 320 "\"death_thread\":\"SomeMainThreadName\"," |
272 "\"location\":{" | 321 "\"location\":{" |
273 "\"file_name\":\"FixedFileName\"," | 322 "\"file_name\":\"FixedFileName\"," |
274 "\"function_name\":\"LifeCycleToValueMainThread\"," | 323 "\"function_name\":\"LifeCycleToValueMainThread\"," |
275 "\"line_number\":236" | 324 "\"line_number\":236" |
276 "}" | 325 "}" |
277 "}" | 326 "}" |
278 "]," | 327 "]" |
279 "\"process\":7" | |
280 "}"; | 328 "}"; |
281 EXPECT_EQ(json, one_line_result); | 329 EXPECT_EQ(one_line_result, json); |
| 330 } |
| 331 |
| 332 // We will deactivate tracking after the birth, and before the death, and |
| 333 // demonstrate that the lifecycle is completely tallied. This ensures that |
| 334 // our tallied births are matched by tallied deaths (except for when the |
| 335 // task is still running, or is queued). |
| 336 TEST_F(TrackedObjectsTest, LifeCycleMidDeactivatedToValueMainThread) { |
| 337 if (!ThreadData::InitializeAndSetTrackingStatus(true)) |
| 338 return; |
| 339 |
| 340 // Use a well named thread. |
| 341 ThreadData::InitializeThreadContext("SomeMainThreadName"); |
| 342 const int kFakeLineNumber = 236; |
| 343 const char* kFile = "FixedFileName"; |
| 344 const char* kFunction = "LifeCycleToValueMainThread"; |
| 345 Location location(kFunction, kFile, kFakeLineNumber, NULL); |
| 346 // Do not delete birth. We don't own it. |
| 347 Births* birth = ThreadData::TallyABirthIfActive(location); |
| 348 EXPECT_NE(birth, reinterpret_cast<Births*>(NULL)); |
| 349 |
| 350 const base::TimeTicks kTimePosted = base::TimeTicks() |
| 351 + base::TimeDelta::FromMilliseconds(1); |
| 352 const base::TimeTicks kDelayedStartTime = base::TimeTicks(); |
| 353 // TrackingInfo will call TallyABirth() during construction. |
| 354 base::TrackingInfo pending_task(location, kDelayedStartTime); |
| 355 pending_task.time_posted = kTimePosted; // Overwrite implied Now(). |
| 356 |
| 357 // Turn off tracking now that we have births. |
| 358 EXPECT_TRUE(ThreadData::InitializeAndSetTrackingStatus(false)); |
| 359 |
| 360 const TrackedTime kStartOfRun = TrackedTime() + |
| 361 Duration::FromMilliseconds(5); |
| 362 const TrackedTime kEndOfRun = TrackedTime() + Duration::FromMilliseconds(7); |
| 363 ThreadData::TallyRunOnNamedThreadIfTracking(pending_task, |
| 364 kStartOfRun, kEndOfRun); |
| 365 |
| 366 scoped_ptr<base::Value> value(ThreadData::ToValue()); |
| 367 std::string json; |
| 368 base::JSONWriter::Write(value.get(), false, &json); |
| 369 std::string one_line_result = "{" |
| 370 "\"list\":[" |
| 371 "{" |
| 372 "\"birth_thread\":\"SomeMainThreadName\"," |
| 373 "\"death_data\":{" |
| 374 "\"count\":1," |
| 375 "\"queue_ms\":4," |
| 376 "\"run_ms\":2" |
| 377 "}," |
| 378 "\"death_thread\":\"SomeMainThreadName\"," |
| 379 "\"location\":{" |
| 380 "\"file_name\":\"FixedFileName\"," |
| 381 "\"function_name\":\"LifeCycleToValueMainThread\"," |
| 382 "\"line_number\":236" |
| 383 "}" |
| 384 "}" |
| 385 "]" |
| 386 "}"; |
| 387 EXPECT_EQ(one_line_result, json); |
| 388 } |
| 389 |
| 390 // We will deactivate tracking before starting a life cycle, and neither |
| 391 // the birth nor the death will be recorded. |
| 392 TEST_F(TrackedObjectsTest, LifeCyclePreDeactivatedToValueMainThread) { |
| 393 if (!ThreadData::InitializeAndSetTrackingStatus(false)) |
| 394 return; |
| 395 |
| 396 // Use a well named thread. |
| 397 ThreadData::InitializeThreadContext("SomeMainThreadName"); |
| 398 const int kFakeLineNumber = 236; |
| 399 const char* kFile = "FixedFileName"; |
| 400 const char* kFunction = "LifeCycleToValueMainThread"; |
| 401 Location location(kFunction, kFile, kFakeLineNumber, NULL); |
| 402 // Do not delete birth. We don't own it. |
| 403 Births* birth = ThreadData::TallyABirthIfActive(location); |
| 404 EXPECT_EQ(birth, reinterpret_cast<Births*>(NULL)); |
| 405 |
| 406 const base::TimeTicks kTimePosted = base::TimeTicks() |
| 407 + base::TimeDelta::FromMilliseconds(1); |
| 408 const base::TimeTicks kDelayedStartTime = base::TimeTicks(); |
| 409 // TrackingInfo will call TallyABirth() during construction. |
| 410 base::TrackingInfo pending_task(location, kDelayedStartTime); |
| 411 pending_task.time_posted = kTimePosted; // Overwrite implied Now(). |
| 412 |
| 413 const TrackedTime kStartOfRun = TrackedTime() + |
| 414 Duration::FromMilliseconds(5); |
| 415 const TrackedTime kEndOfRun = TrackedTime() + Duration::FromMilliseconds(7); |
| 416 ThreadData::TallyRunOnNamedThreadIfTracking(pending_task, |
| 417 kStartOfRun, kEndOfRun); |
| 418 |
| 419 scoped_ptr<base::Value> value(ThreadData::ToValue()); |
| 420 std::string json; |
| 421 base::JSONWriter::Write(value.get(), false, &json); |
| 422 std::string one_line_result = "{" |
| 423 "\"list\":[" |
| 424 "]" |
| 425 "}"; |
| 426 EXPECT_EQ(one_line_result, json); |
| 427 } |
| 428 |
| 429 TEST_F(TrackedObjectsTest, LifeCycleToValueWorkerThread) { |
| 430 if (!ThreadData::InitializeAndSetTrackingStatus(true)) |
| 431 return; |
| 432 |
| 433 // Don't initialize thread, so that we appear as a worker thread. |
| 434 // ThreadData::InitializeThreadContext("SomeMainThreadName"); |
| 435 |
| 436 const int kFakeLineNumber = 236; |
| 437 const char* kFile = "FixedFileName"; |
| 438 const char* kFunction = "LifeCycleToValueWorkerThread"; |
| 439 Location location(kFunction, kFile, kFakeLineNumber, NULL); |
| 440 // Do not delete birth. We don't own it. |
| 441 Births* birth = ThreadData::TallyABirthIfActive(location); |
| 442 EXPECT_NE(birth, reinterpret_cast<Births*>(NULL)); |
| 443 |
| 444 const TrackedTime kTimePosted = TrackedTime() + Duration::FromMilliseconds(1); |
| 445 const TrackedTime kStartOfRun = TrackedTime() + |
| 446 Duration::FromMilliseconds(5); |
| 447 const TrackedTime kEndOfRun = TrackedTime() + Duration::FromMilliseconds(7); |
| 448 ThreadData::TallyRunOnWorkerThreadIfTracking(birth, kTimePosted, |
| 449 kStartOfRun, kEndOfRun); |
| 450 |
| 451 scoped_ptr<base::Value> value(ThreadData::ToValue()); |
| 452 std::string json; |
| 453 base::JSONWriter::Write(value.get(), false, &json); |
| 454 std::string one_line_result = "{" |
| 455 "\"list\":[" |
| 456 "{" |
| 457 "\"birth_thread\":\"WorkerThread-1\"," |
| 458 "\"death_data\":{" |
| 459 "\"count\":1," |
| 460 "\"queue_ms\":4," |
| 461 "\"run_ms\":2" |
| 462 "}," |
| 463 "\"death_thread\":\"WorkerThread-1\"," |
| 464 "\"location\":{" |
| 465 "\"file_name\":\"FixedFileName\"," |
| 466 "\"function_name\":\"LifeCycleToValueWorkerThread\"," |
| 467 "\"line_number\":236" |
| 468 "}" |
| 469 "}" |
| 470 "]" |
| 471 "}"; |
| 472 EXPECT_EQ(one_line_result, json); |
282 } | 473 } |
283 | 474 |
284 TEST_F(TrackedObjectsTest, TwoLives) { | 475 TEST_F(TrackedObjectsTest, TwoLives) { |
285 if (!ThreadData::StartTracking(true)) | 476 if (!ThreadData::InitializeAndSetTrackingStatus(true)) |
286 return; | 477 return; |
287 | 478 |
288 // Use a well named thread. | 479 // Use a well named thread. |
289 ThreadData::InitializeThreadContext("SomeFileThreadName"); | 480 ThreadData::InitializeThreadContext("SomeFileThreadName"); |
290 int fake_line_number = 222; | 481 const int kFakeLineNumber = 222; |
291 const char* kFile = "AnotherFileName"; | 482 const char* kFile = "AnotherFileName"; |
292 const char* kFunction = "TwoLives"; | 483 const char* kFunction = "TwoLives"; |
293 Location location(kFunction, kFile, fake_line_number, NULL); | 484 Location location(kFunction, kFile, kFakeLineNumber, NULL); |
294 // Do not delete birth. We don't own it. | 485 // Do not delete birth. We don't own it. |
295 Births* birth = ThreadData::TallyABirthIfActive(location); | 486 Births* birth = ThreadData::TallyABirthIfActive(location); |
296 EXPECT_NE(birth, reinterpret_cast<Births*>(NULL)); | 487 EXPECT_NE(birth, reinterpret_cast<Births*>(NULL)); |
297 | 488 |
298 // TimeTicks initializers ar ein microseconds. Durations are calculated in | |
299 // milliseconds, so we need to use 1000x. | |
300 const base::TimeTicks time_posted = base::TimeTicks() + | |
301 base::TimeDelta::FromMilliseconds(1); | |
302 const base::TimeTicks delayed_start_time = base::TimeTicks(); | |
303 const base::TimeTicks start_of_run = base::TimeTicks() + | |
304 base::TimeDelta::FromMilliseconds(5); | |
305 const base::TimeTicks end_of_run = base::TimeTicks() + | |
306 base::TimeDelta::FromMilliseconds(7); | |
307 ThreadData::TallyADeathIfActive(birth, time_posted, delayed_start_time, | |
308 start_of_run, end_of_run); | |
309 | 489 |
310 birth = ThreadData::TallyABirthIfActive(location); | 490 const base::TimeTicks kTimePosted = base::TimeTicks() |
311 ThreadData::TallyADeathIfActive(birth, time_posted, delayed_start_time, | 491 + base::TimeDelta::FromMilliseconds(1); |
312 start_of_run, end_of_run); | 492 const base::TimeTicks kDelayedStartTime = base::TimeTicks(); |
| 493 // TrackingInfo will call TallyABirth() during construction. |
| 494 base::TrackingInfo pending_task(location, kDelayedStartTime); |
| 495 pending_task.time_posted = kTimePosted; // Overwrite implied Now(). |
313 | 496 |
314 int process_type = 7; | 497 const TrackedTime kStartOfRun = TrackedTime() + |
315 scoped_ptr<base::Value> value(ThreadData::ToValue(process_type)); | 498 Duration::FromMilliseconds(5); |
| 499 const TrackedTime kEndOfRun = TrackedTime() + Duration::FromMilliseconds(7); |
| 500 ThreadData::TallyRunOnNamedThreadIfTracking(pending_task, |
| 501 kStartOfRun, kEndOfRun); |
| 502 |
| 503 // TrackingInfo will call TallyABirth() during construction. |
| 504 base::TrackingInfo pending_task2(location, kDelayedStartTime); |
| 505 pending_task2.time_posted = kTimePosted; // Overwrite implied Now(). |
| 506 |
| 507 ThreadData::TallyRunOnNamedThreadIfTracking(pending_task2, |
| 508 kStartOfRun, kEndOfRun); |
| 509 |
| 510 scoped_ptr<base::Value> value(ThreadData::ToValue()); |
316 std::string json; | 511 std::string json; |
317 base::JSONWriter::Write(value.get(), false, &json); | 512 base::JSONWriter::Write(value.get(), false, &json); |
318 std::string one_line_result = "{" | 513 std::string one_line_result = "{" |
319 "\"list\":[" | 514 "\"list\":[" |
320 "{" | 515 "{" |
321 "\"birth_thread\":\"SomeFileThreadName\"," | 516 "\"birth_thread\":\"SomeFileThreadName\"," |
322 "\"death_data\":{" | 517 "\"death_data\":{" |
323 "\"count\":2," | 518 "\"count\":2," |
324 "\"queue_ms\":8," | 519 "\"queue_ms\":8," |
325 "\"run_ms\":4" | 520 "\"run_ms\":4" |
326 "}," | 521 "}," |
327 "\"death_thread\":\"SomeFileThreadName\"," | 522 "\"death_thread\":\"SomeFileThreadName\"," |
328 "\"location\":{" | 523 "\"location\":{" |
329 "\"file_name\":\"AnotherFileName\"," | 524 "\"file_name\":\"AnotherFileName\"," |
330 "\"function_name\":\"TwoLives\"," | 525 "\"function_name\":\"TwoLives\"," |
331 "\"line_number\":222" | 526 "\"line_number\":222" |
332 "}" | 527 "}" |
333 "}" | 528 "}" |
334 "]," | 529 "]" |
335 "\"process\":7" | |
336 "}"; | 530 "}"; |
337 EXPECT_EQ(json, one_line_result); | 531 EXPECT_EQ(one_line_result, json); |
338 } | 532 } |
339 | 533 |
340 TEST_F(TrackedObjectsTest, DifferentLives) { | 534 TEST_F(TrackedObjectsTest, DifferentLives) { |
341 if (!ThreadData::StartTracking(true)) | 535 if (!ThreadData::InitializeAndSetTrackingStatus(true)) |
342 return; | 536 return; |
343 | 537 |
344 // Use a well named thread. | 538 // Use a well named thread. |
345 ThreadData::InitializeThreadContext("SomeFileThreadName"); | 539 ThreadData::InitializeThreadContext("SomeFileThreadName"); |
346 int fake_line_number = 567; | 540 const int kFakeLineNumber = 567; |
347 const char* kFile = "AnotherFileName"; | 541 const char* kFile = "AnotherFileName"; |
348 const char* kFunction = "DifferentLives"; | 542 const char* kFunction = "DifferentLives"; |
349 Location location(kFunction, kFile, fake_line_number, NULL); | 543 Location location(kFunction, kFile, kFakeLineNumber, NULL); |
350 // Do not delete birth. We don't own it. | |
351 Births* birth = ThreadData::TallyABirthIfActive(location); | |
352 EXPECT_NE(birth, reinterpret_cast<Births*>(NULL)); | |
353 | 544 |
354 // TimeTicks initializers ar ein microseconds. Durations are calculated in | 545 const base::TimeTicks kTimePosted = base::TimeTicks() |
355 // milliseconds, so we need to use 1000x. | 546 + base::TimeDelta::FromMilliseconds(1); |
356 const base::TimeTicks time_posted = base::TimeTicks() + | 547 const base::TimeTicks kDelayedStartTime = base::TimeTicks(); |
357 base::TimeDelta::FromMilliseconds(1); | 548 // TrackingInfo will call TallyABirth() during construction. |
358 const base::TimeTicks delayed_start_time = base::TimeTicks(); | 549 base::TrackingInfo pending_task(location, kDelayedStartTime); |
359 const base::TimeTicks start_of_run = base::TimeTicks() + | 550 pending_task.time_posted = kTimePosted; // Overwrite implied Now(). |
360 base::TimeDelta::FromMilliseconds(5); | |
361 const base::TimeTicks end_of_run = base::TimeTicks() + | |
362 base::TimeDelta::FromMilliseconds(7); | |
363 ThreadData::TallyADeathIfActive(birth, time_posted, delayed_start_time, | |
364 start_of_run, end_of_run); | |
365 | 551 |
366 int second_fake_line_number = 999; | 552 const TrackedTime kStartOfRun = TrackedTime() + |
367 Location second_location(kFunction, kFile, second_fake_line_number, NULL); | 553 Duration::FromMilliseconds(5); |
368 birth = ThreadData::TallyABirthIfActive(second_location); | 554 const TrackedTime kEndOfRun = TrackedTime() + Duration::FromMilliseconds(7); |
| 555 ThreadData::TallyRunOnNamedThreadIfTracking(pending_task, |
| 556 kStartOfRun, kEndOfRun); |
369 | 557 |
370 int process_type = 2; | 558 const int kSecondFakeLineNumber = 999; |
371 scoped_ptr<base::Value> value(ThreadData::ToValue(process_type)); | 559 Location second_location(kFunction, kFile, kSecondFakeLineNumber, NULL); |
| 560 |
| 561 // TrackingInfo will call TallyABirth() during construction. |
| 562 base::TrackingInfo pending_task2(second_location, kDelayedStartTime); |
| 563 pending_task2.time_posted = kTimePosted; // Overwrite implied Now(). |
| 564 |
| 565 scoped_ptr<base::Value> value(ThreadData::ToValue()); |
372 std::string json; | 566 std::string json; |
373 base::JSONWriter::Write(value.get(), false, &json); | 567 base::JSONWriter::Write(value.get(), false, &json); |
374 std::string one_line_result = "{" | 568 std::string one_line_result = "{" |
375 "\"list\":[" | 569 "\"list\":[" |
376 "{" | 570 "{" |
377 "\"birth_thread\":\"SomeFileThreadName\"," | 571 "\"birth_thread\":\"SomeFileThreadName\"," |
378 "\"death_data\":{" | 572 "\"death_data\":{" |
379 "\"count\":1," | 573 "\"count\":1," |
380 "\"queue_ms\":4," | 574 "\"queue_ms\":4," |
381 "\"run_ms\":2" | 575 "\"run_ms\":2" |
(...skipping 12 matching lines...) Expand all Loading... |
394 "\"queue_ms\":0," | 588 "\"queue_ms\":0," |
395 "\"run_ms\":0" | 589 "\"run_ms\":0" |
396 "}," | 590 "}," |
397 "\"death_thread\":\"Still_Alive\"," | 591 "\"death_thread\":\"Still_Alive\"," |
398 "\"location\":{" | 592 "\"location\":{" |
399 "\"file_name\":\"AnotherFileName\"," | 593 "\"file_name\":\"AnotherFileName\"," |
400 "\"function_name\":\"DifferentLives\"," | 594 "\"function_name\":\"DifferentLives\"," |
401 "\"line_number\":999" | 595 "\"line_number\":999" |
402 "}" | 596 "}" |
403 "}" | 597 "}" |
404 "]," | 598 "]" |
405 "\"process\":2" | |
406 "}"; | 599 "}"; |
407 EXPECT_EQ(json, one_line_result); | 600 EXPECT_EQ(one_line_result, json); |
408 } | 601 } |
409 | 602 |
410 } // namespace tracked_objects | 603 } // namespace tracked_objects |
OLD | NEW |