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

Side by Side Diff: base/tracked_objects_unittest.cc

Issue 8313013: Support JSON encoding of data for about:tracking information (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« base/tracked_objects.h ('K') | « base/tracked_objects.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/message_loop.h" 9 #include "base/json/json_writer.h"
10 #include "base/memory/scoped_ptr.h"
10 #include "base/time.h" 11 #include "base/time.h"
11 #include "testing/gtest/include/gtest/gtest.h" 12 #include "testing/gtest/include/gtest/gtest.h"
12 13
13 namespace tracked_objects { 14 namespace tracked_objects {
14 15
15 class TrackedObjectsTest : public testing::Test { 16 class TrackedObjectsTest : public testing::Test {
16 public: 17 public:
17 MessageLoop message_loop_; 18 ~TrackedObjectsTest() {
eroman 2011/10/24 22:23:04 nit: indentation
jar (doing other things) 2011/10/27 06:23:35 Done.
19 ThreadData::ShutdownSingleThreadedCleanup();
20 }
21
18 }; 22 };
19 23
20 TEST_F(TrackedObjectsTest, MinimalStartupShutdown) { 24 TEST_F(TrackedObjectsTest, MinimalStartupShutdown) {
21 // Minimal test doesn't even create any tasks. 25 // Minimal test doesn't even create any tasks.
22 if (!ThreadData::StartTracking(true)) 26 if (!ThreadData::StartTracking(true))
23 return; 27 return;
24 28
25 EXPECT_FALSE(ThreadData::first()); // No activity even on this thread. 29 EXPECT_FALSE(ThreadData::first()); // No activity even on this thread.
26 ThreadData* data = ThreadData::Get(); 30 ThreadData* data = ThreadData::Get();
27 EXPECT_TRUE(ThreadData::first()); // Now class was constructed. 31 EXPECT_TRUE(ThreadData::first()); // Now class was constructed.
(...skipping 15 matching lines...) Expand all
43 EXPECT_TRUE(ThreadData::first()); // Now class was constructed. 47 EXPECT_TRUE(ThreadData::first()); // Now class was constructed.
44 EXPECT_TRUE(data); 48 EXPECT_TRUE(data);
45 EXPECT_TRUE(!data->next()); 49 EXPECT_TRUE(!data->next());
46 EXPECT_EQ(data, ThreadData::Get()); 50 EXPECT_EQ(data, ThreadData::Get());
47 birth_map.clear(); 51 birth_map.clear();
48 data->SnapshotBirthMap(&birth_map); 52 data->SnapshotBirthMap(&birth_map);
49 EXPECT_EQ(0u, birth_map.size()); 53 EXPECT_EQ(0u, birth_map.size());
50 death_map.clear(); 54 death_map.clear();
51 data->SnapshotDeathMap(&death_map); 55 data->SnapshotDeathMap(&death_map);
52 EXPECT_EQ(0u, death_map.size()); 56 EXPECT_EQ(0u, death_map.size());
53 ThreadData::ShutdownSingleThreadedCleanup();
54 } 57 }
55 58
56 TEST_F(TrackedObjectsTest, TinyStartupShutdown) { 59 TEST_F(TrackedObjectsTest, TinyStartupShutdown) {
57 if (!ThreadData::StartTracking(true)) 60 if (!ThreadData::StartTracking(true))
58 return; 61 return;
59 62
60 // Instigate tracking on a single tracked object, or our thread. 63 // Instigate tracking on a single tracked object, on our thread.
61 const Location& location = FROM_HERE; 64 const Location& location = FROM_HERE;
62 ThreadData::TallyABirthIfActive(location); 65 ThreadData::TallyABirthIfActive(location);
63 66
64 const ThreadData* data = ThreadData::first(); 67 const ThreadData* data = ThreadData::first();
65 ASSERT_TRUE(data); 68 ASSERT_TRUE(data);
66 EXPECT_TRUE(!data->next()); 69 EXPECT_TRUE(!data->next());
67 EXPECT_EQ(data, ThreadData::Get()); 70 EXPECT_EQ(data, ThreadData::Get());
68 ThreadData::BirthMap birth_map; 71 ThreadData::BirthMap birth_map;
69 data->SnapshotBirthMap(&birth_map); 72 data->SnapshotBirthMap(&birth_map);
70 EXPECT_EQ(1u, birth_map.size()); // 1 birth location. 73 EXPECT_EQ(1u, birth_map.size()); // 1 birth location.
71 EXPECT_EQ(1, birth_map.begin()->second->birth_count()); // 1 birth. 74 EXPECT_EQ(1, birth_map.begin()->second->birth_count()); // 1 birth.
72 ThreadData::DeathMap death_map; 75 ThreadData::DeathMap death_map;
73 data->SnapshotDeathMap(&death_map); 76 data->SnapshotDeathMap(&death_map);
74 EXPECT_EQ(0u, death_map.size()); // No deaths. 77 EXPECT_EQ(0u, death_map.size()); // No deaths.
75 78
76 79
77 // Now instigate a birth, and a death. 80 // Now instigate a birth, and a death.
78 const Births* second_birth = ThreadData::TallyABirthIfActive(location); 81 const Births* second_birth = ThreadData::TallyABirthIfActive(location);
79 ThreadData::TallyADeathIfActive( 82 ThreadData::TallyADeathIfActive(
80 second_birth, 83 second_birth,
81 base::TimeTicks(), /* Bogus post_time. */ 84 base::TimeTicks(), /* Bogus post_time. */
82 base::TimeTicks(), /* Bogus delayed_start_time. */ 85 base::TimeTicks(), /* Bogus delayed_start_time. */
83 base::TimeTicks() /* Bogus start_run_time. */); 86 base::TimeTicks(), /* Bogus start_run_time. */
87 base::TimeTicks() /* Bogus end_run_time */ );
84 88
85 birth_map.clear(); 89 birth_map.clear();
86 data->SnapshotBirthMap(&birth_map); 90 data->SnapshotBirthMap(&birth_map);
87 EXPECT_EQ(1u, birth_map.size()); // 1 birth location. 91 EXPECT_EQ(1u, birth_map.size()); // 1 birth location.
88 EXPECT_EQ(2, birth_map.begin()->second->birth_count()); // 2 births. 92 EXPECT_EQ(2, birth_map.begin()->second->birth_count()); // 2 births.
89 death_map.clear(); 93 death_map.clear();
90 data->SnapshotDeathMap(&death_map); 94 data->SnapshotDeathMap(&death_map);
91 EXPECT_EQ(1u, death_map.size()); // 1 location. 95 EXPECT_EQ(1u, death_map.size()); // 1 location.
92 EXPECT_EQ(1, death_map.begin()->second.count()); // 1 death. 96 EXPECT_EQ(1, death_map.begin()->second.count()); // 1 death.
93 97
94 // The births were at the same location as the one known death. 98 // The births were at the same location as the one known death.
95 EXPECT_EQ(birth_map.begin()->second, death_map.begin()->first); 99 EXPECT_EQ(birth_map.begin()->second, death_map.begin()->first);
96 100 }
97 ThreadData::ShutdownSingleThreadedCleanup(); 101
102 TEST_F(TrackedObjectsTest, DeathDataTest) {
103 if (!ThreadData::StartTracking(true))
104 return;
105
106 scoped_ptr<DeathData> data(new DeathData());
107 ASSERT_NE(data, reinterpret_cast<DeathData*>(NULL));
108 EXPECT_EQ(data->run_duration(), base::TimeDelta());
109 EXPECT_EQ(data->queue_duration(), base::TimeDelta());
110 EXPECT_EQ(data->AverageMsRunDuration(), 0);
111 EXPECT_EQ(data->AverageMsQueueDuration(), 0);
112 EXPECT_EQ(data->count(), 0);
113
114 int run_ms = 42;
115 int queue_ms = 8;
116
117 base::TimeDelta run_duration = base::TimeDelta().FromMilliseconds(run_ms);
118 base::TimeDelta queue_duration = base::TimeDelta().FromMilliseconds(queue_ms);
119 data->RecordDeath(queue_duration, run_duration);
120 EXPECT_EQ(data->run_duration(), run_duration);
121 EXPECT_EQ(data->queue_duration(), queue_duration);
122 EXPECT_EQ(data->AverageMsRunDuration(), run_ms);
123 EXPECT_EQ(data->AverageMsQueueDuration(), queue_ms);
124 EXPECT_EQ(data->count(), 1);
125
126 data->RecordDeath(queue_duration, run_duration);
127 EXPECT_EQ(data->run_duration(), run_duration + run_duration);
128 EXPECT_EQ(data->queue_duration(), queue_duration + queue_duration);
129 EXPECT_EQ(data->AverageMsRunDuration(), run_ms);
130 EXPECT_EQ(data->AverageMsQueueDuration(), queue_ms);
131 EXPECT_EQ(data->count(), 2);
132
133 scoped_ptr<base::DictionaryValue> dictionary(data->ToValue());
134 int integer;
135 EXPECT_TRUE(dictionary->GetInteger("run_ms", &integer));
136 EXPECT_EQ(integer, 2 * run_ms);
137 EXPECT_TRUE(dictionary->GetInteger("queue_ms", &integer));
138 EXPECT_EQ(integer, 2* queue_ms);
139 EXPECT_TRUE(dictionary->GetInteger("count", &integer));
140 EXPECT_EQ(integer, 2);
141
142 std::string output;
143 data->WriteHTML(&output);
144 std::string results = "Lives:2, Run:84ms(42ms/life) Queue:16ms(8ms/life) ";
145 EXPECT_EQ(output, results);
146
147 scoped_ptr<base::Value> value(data->ToValue());
148 std::string json;
149 base::JSONWriter::Write(value.get(), false, &json);
150 std::string birth_only_result = "{\"count\":2,\"queue_ms\":16,\"run_ms\":84}";
151 EXPECT_EQ(json, birth_only_result);
152 }
153
154 TEST_F(TrackedObjectsTest, BirthOnlyToValueWorkerThread) {
155 if (!ThreadData::StartTracking(true))
156 return;
157 // We don't initialize system with a thread name, so we're viewed as a worker
158 // thread.
159 int fake_line_number = 173;
160 const char* kFile = "FixedFileName";
161 const char* kFunction = "BirthOnlyToValueWorkerThread";
162 Location location(kFunction, kFile, fake_line_number, NULL);
163 Births* birth = ThreadData::TallyABirthIfActive(location);
164 EXPECT_NE(birth, reinterpret_cast<Births*>(NULL));
165
166 int process_type = 3;
167 scoped_ptr<base::Value> value(ThreadData::ToValue(process_type));
168 std::string json;
169 base::JSONWriter::Write(value.get(), false, &json);
170 std::string birth_only_result = "{"
171 "\"list\":["
172 "{"
173 "\"birth_thread\":\"WorkerThread-1\","
eroman 2011/10/24 22:23:04 Are thread names guaranteed to be unique? I wander
jar (doing other things) 2011/10/27 06:23:35 It is possible (within a single process) to have t
174 "\"death_data\":{"
175 "\"count\":1,"
176 "\"queue_ms\":0,"
177 "\"run_ms\":0"
178 "},"
179 "\"death_thread\":\"Still_Alive\","
180 "\"location\":{"
181 "\"file_name\":\"FixedFileName\","
182 "\"function_name\":\"BirthOnlyToValueWorkerThread\","
183 "\"line_number\":173"
184 "}"
185 "}"
186 "],"
187 "\"process\":3"
188 "}";
189 EXPECT_EQ(json, birth_only_result);
190 }
191
192 TEST_F(TrackedObjectsTest, BirthOnlyToValueMainThread) {
193 if (!ThreadData::StartTracking(true))
194 return;
195
196 // Use a well named thread.
197 ThreadData::InitializeThreadContext("SomeMainThreadName");
198 int fake_line_number = 173;
199 const char* kFile = "FixedFileName";
200 const char* kFunction = "BirthOnlyToValueMainThread";
201 Location location(kFunction, kFile, fake_line_number, NULL);
202 // Do not delete birth. We don't own it.
203 Births* birth = ThreadData::TallyABirthIfActive(location);
204 EXPECT_NE(birth, reinterpret_cast<Births*>(NULL));
205
206 int process_type = 34;
207 scoped_ptr<base::Value> value(ThreadData::ToValue(process_type));
208 std::string json;
209 base::JSONWriter::Write(value.get(), false, &json);
210 std::string birth_only_result = "{"
211 "\"list\":["
212 "{"
213 "\"birth_thread\":\"SomeMainThreadName\","
214 "\"death_data\":{"
215 "\"count\":1,"
216 "\"queue_ms\":0,"
217 "\"run_ms\":0"
218 "},"
219 "\"death_thread\":\"Still_Alive\","
220 "\"location\":{"
221 "\"file_name\":\"FixedFileName\","
222 "\"function_name\":\"BirthOnlyToValueMainThread\","
223 "\"line_number\":173"
224 "}"
225 "}"
226 "],"
227 "\"process\":34"
228 "}";
229 EXPECT_EQ(json, birth_only_result);
230 }
231
232 TEST_F(TrackedObjectsTest, LifeCycleToValueMainThread) {
233 if (!ThreadData::StartTracking(true))
234 return;
235
236 // Use a well named thread.
237 ThreadData::InitializeThreadContext("SomeMainThreadName");
238 int fake_line_number = 236;
239 const char* kFile = "FixedFileName";
240 const char* kFunction = "LifeCycleToValueMainThread";
241 Location location(kFunction, kFile, fake_line_number, NULL);
242 // Do not delete birth. We don't own it.
243 Births* birth = ThreadData::TallyABirthIfActive(location);
244 EXPECT_NE(birth, reinterpret_cast<Births*>(NULL));
245
246 // TimeTicks initializers ar ein microseconds. Durations are calculated in
247 // milliseconds, so we need to use 1000x.
248 const base::TimeTicks time_posted = base::TimeTicks() +
249 base::TimeDelta::FromMilliseconds(1);
250 const base::TimeTicks delayed_start_time = base::TimeTicks();
251 const base::TimeTicks start_of_run = base::TimeTicks() +
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
258 int process_type = 7;
259 scoped_ptr<base::Value> value(ThreadData::ToValue(process_type));
260 std::string json;
261 base::JSONWriter::Write(value.get(), false, &json);
262 std::string one_line_result = "{"
263 "\"list\":["
264 "{"
265 "\"birth_thread\":\"SomeMainThreadName\","
266 "\"death_data\":{"
267 "\"count\":1,"
268 "\"queue_ms\":4,"
269 "\"run_ms\":2"
270 "},"
271 "\"death_thread\":\"SomeMainThreadName\","
272 "\"location\":{"
273 "\"file_name\":\"FixedFileName\","
274 "\"function_name\":\"LifeCycleToValueMainThread\","
275 "\"line_number\":236"
276 "}"
277 "}"
278 "],"
279 "\"process\":7"
280 "}";
281 EXPECT_EQ(json, one_line_result);
282 }
283
284 TEST_F(TrackedObjectsTest, TwoLives) {
285 if (!ThreadData::StartTracking(true))
286 return;
287
288 // Use a well named thread.
289 ThreadData::InitializeThreadContext("SomeFileThreadName");
290 int fake_line_number = 222;
291 const char* kFile = "AnotherFileName";
292 const char* kFunction = "TwoLives";
293 Location location(kFunction, kFile, fake_line_number, NULL);
294 // Do not delete birth. We don't own it.
295 Births* birth = ThreadData::TallyABirthIfActive(location);
296 EXPECT_NE(birth, reinterpret_cast<Births*>(NULL));
297
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
310 birth = ThreadData::TallyABirthIfActive(location);
311 ThreadData::TallyADeathIfActive(birth, time_posted, delayed_start_time,
312 start_of_run, end_of_run);
313
314 int process_type = 7;
315 scoped_ptr<base::Value> value(ThreadData::ToValue(process_type));
316 std::string json;
317 base::JSONWriter::Write(value.get(), false, &json);
318 std::string one_line_result = "{"
319 "\"list\":["
320 "{"
321 "\"birth_thread\":\"SomeFileThreadName\","
322 "\"death_data\":{"
323 "\"count\":2,"
324 "\"queue_ms\":8,"
325 "\"run_ms\":4"
326 "},"
327 "\"death_thread\":\"SomeFileThreadName\","
328 "\"location\":{"
329 "\"file_name\":\"AnotherFileName\","
330 "\"function_name\":\"TwoLives\","
331 "\"line_number\":222"
332 "}"
333 "}"
334 "],"
335 "\"process\":7"
336 "}";
337 EXPECT_EQ(json, one_line_result);
338 }
339
340 TEST_F(TrackedObjectsTest, DifferentLives) {
341 if (!ThreadData::StartTracking(true))
342 return;
343
344 // Use a well named thread.
345 ThreadData::InitializeThreadContext("SomeFileThreadName");
346 int fake_line_number = 567;
347 const char* kFile = "AnotherFileName";
348 const char* kFunction = "DifferentLives";
349 Location location(kFunction, kFile, fake_line_number, 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
354 // TimeTicks initializers ar ein microseconds. Durations are calculated in
355 // milliseconds, so we need to use 1000x.
356 const base::TimeTicks time_posted = base::TimeTicks() +
357 base::TimeDelta::FromMilliseconds(1);
358 const base::TimeTicks delayed_start_time = base::TimeTicks();
359 const base::TimeTicks start_of_run = base::TimeTicks() +
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
366 int second_fake_line_number = 999;
367 Location second_location(kFunction, kFile, second_fake_line_number, NULL);
368 birth = ThreadData::TallyABirthIfActive(second_location);
369
370 int process_type = 2;
371 scoped_ptr<base::Value> value(ThreadData::ToValue(process_type));
372 std::string json;
373 base::JSONWriter::Write(value.get(), false, &json);
374 std::string one_line_result = "{"
375 "\"list\":["
376 "{"
377 "\"birth_thread\":\"SomeFileThreadName\","
378 "\"death_data\":{"
379 "\"count\":1,"
380 "\"queue_ms\":4,"
381 "\"run_ms\":2"
382 "},"
383 "\"death_thread\":\"SomeFileThreadName\","
384 "\"location\":{"
385 "\"file_name\":\"AnotherFileName\","
386 "\"function_name\":\"DifferentLives\","
387 "\"line_number\":567"
388 "}"
389 "},"
390 "{"
391 "\"birth_thread\":\"SomeFileThreadName\","
392 "\"death_data\":{"
393 "\"count\":1,"
394 "\"queue_ms\":0,"
395 "\"run_ms\":0"
396 "},"
397 "\"death_thread\":\"Still_Alive\","
398 "\"location\":{"
399 "\"file_name\":\"AnotherFileName\","
400 "\"function_name\":\"DifferentLives\","
401 "\"line_number\":999"
402 "}"
403 "}"
404 "],"
405 "\"process\":2"
406 "}";
407 EXPECT_EQ(json, one_line_result);
98 } 408 }
99 409
100 } // namespace tracked_objects 410 } // namespace tracked_objects
OLDNEW
« base/tracked_objects.h ('K') | « base/tracked_objects.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698