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
3 // found in the LICENSE file.
5 // Test of classes in the tracked_objects.h classes.
7 #include "base/tracked_objects.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/process/process_handle.h"
13 #include "base/time/time.h"
14 #include "base/tracking_info.h"
15 #include "testing/gtest/include/gtest/gtest.h"
17 const int kLineNumber
= 1776;
18 const char kFile
[] = "FixedUnitTestFileName";
19 const char kWorkerThreadName
[] = "WorkerThread-1";
20 const char kMainThreadName
[] = "SomeMainThreadName";
21 const char kStillAlive
[] = "Still_Alive";
23 namespace tracked_objects
{
25 class TrackedObjectsTest
: public testing::Test
{
27 TrackedObjectsTest() {
28 // On entry, leak any database structures in case they are still in use by
30 ThreadData::ShutdownSingleThreadedCleanup(true);
33 ThreadData::SetAlternateTimeSource(&TrackedObjectsTest::GetTestTime
);
34 ThreadData::now_function_is_time_
= true;
37 ~TrackedObjectsTest() override
{
38 // We should not need to leak any structures we create, since we are
39 // single threaded, and carefully accounting for items.
40 ThreadData::ShutdownSingleThreadedCleanup(false);
43 // Reset the profiler state.
45 ThreadData::ShutdownSingleThreadedCleanup(false);
49 // Simulate a birth on the thread named |thread_name|, at the given
51 void TallyABirth(const Location
& location
, const std::string
& thread_name
) {
52 // If the |thread_name| is empty, we don't initialize system with a thread
53 // name, so we're viewed as a worker thread.
54 if (!thread_name
.empty())
55 ThreadData::InitializeThreadContext(kMainThreadName
);
57 // Do not delete |birth|. We don't own it.
58 Births
* birth
= ThreadData::TallyABirthIfActive(location
);
60 if (ThreadData::status() == ThreadData::DEACTIVATED
)
61 EXPECT_EQ(reinterpret_cast<Births
*>(NULL
), birth
);
63 EXPECT_NE(reinterpret_cast<Births
*>(NULL
), birth
);
66 // Helper function to verify the most common test expectations.
67 void ExpectSimpleProcessData(const ProcessDataSnapshot
& process_data
,
68 const std::string
& function_name
,
69 const std::string
& birth_thread
,
70 const std::string
& death_thread
,
74 ASSERT_EQ(1u, process_data
.phased_process_data_snapshots
.size());
75 auto it
= process_data
.phased_process_data_snapshots
.find(0);
76 ASSERT_TRUE(it
!= process_data
.phased_process_data_snapshots
.end());
77 const ProcessDataPhaseSnapshot
& process_data_phase
= it
->second
;
79 ASSERT_EQ(1u, process_data_phase
.tasks
.size());
81 EXPECT_EQ(kFile
, process_data_phase
.tasks
[0].birth
.location
.file_name
);
82 EXPECT_EQ(function_name
,
83 process_data_phase
.tasks
[0].birth
.location
.function_name
);
84 EXPECT_EQ(kLineNumber
,
85 process_data_phase
.tasks
[0].birth
.location
.line_number
);
87 EXPECT_EQ(birth_thread
, process_data_phase
.tasks
[0].birth
.thread_name
);
89 EXPECT_EQ(count
, process_data_phase
.tasks
[0].death_data
.count
);
90 EXPECT_EQ(count
* run_ms
,
91 process_data_phase
.tasks
[0].death_data
.run_duration_sum
);
92 EXPECT_EQ(run_ms
, process_data_phase
.tasks
[0].death_data
.run_duration_max
);
94 process_data_phase
.tasks
[0].death_data
.run_duration_sample
);
95 EXPECT_EQ(count
* queue_ms
,
96 process_data_phase
.tasks
[0].death_data
.queue_duration_sum
);
98 process_data_phase
.tasks
[0].death_data
.queue_duration_max
);
100 process_data_phase
.tasks
[0].death_data
.queue_duration_sample
);
102 EXPECT_EQ(death_thread
, process_data_phase
.tasks
[0].death_thread_name
);
104 EXPECT_EQ(0u, process_data_phase
.descendants
.size());
106 EXPECT_EQ(base::GetCurrentProcId(), process_data
.process_id
);
109 // Sets time that will be returned by ThreadData::Now().
110 static void SetTestTime(unsigned int test_time
) { test_time_
= test_time
; }
113 // Returns test time in milliseconds.
114 static unsigned int GetTestTime() { return test_time_
; }
116 // Test time in milliseconds.
117 static unsigned int test_time_
;
121 unsigned int TrackedObjectsTest::test_time_
;
123 TEST_F(TrackedObjectsTest
, TaskStopwatchNoStartStop
) {
124 if (!ThreadData::InitializeAndSetTrackingStatus(
125 ThreadData::PROFILING_CHILDREN_ACTIVE
)) {
129 // Check that creating and destroying a stopwatch without starting it doesn't
131 TaskStopwatch stopwatch
;
134 TEST_F(TrackedObjectsTest
, MinimalStartupShutdown
) {
135 // Minimal test doesn't even create any tasks.
136 if (!ThreadData::InitializeAndSetTrackingStatus(
137 ThreadData::PROFILING_CHILDREN_ACTIVE
)) {
141 EXPECT_FALSE(ThreadData::first()); // No activity even on this thread.
142 ThreadData
* data
= ThreadData::Get();
143 EXPECT_TRUE(ThreadData::first()); // Now class was constructed.
145 EXPECT_FALSE(data
->next());
146 EXPECT_EQ(data
, ThreadData::Get());
147 ThreadData::BirthMap birth_map
;
148 ThreadData::DeathMap death_map
;
149 ThreadData::ParentChildSet parent_child_set
;
150 data
->SnapshotMaps(&birth_map
, &death_map
, &parent_child_set
);
151 EXPECT_EQ(0u, birth_map
.size());
152 EXPECT_EQ(0u, death_map
.size());
153 EXPECT_EQ(0u, parent_child_set
.size());
155 // Clean up with no leaking.
158 // Do it again, just to be sure we reset state completely.
159 EXPECT_TRUE(ThreadData::InitializeAndSetTrackingStatus(
160 ThreadData::PROFILING_CHILDREN_ACTIVE
));
161 EXPECT_FALSE(ThreadData::first()); // No activity even on this thread.
162 data
= ThreadData::Get();
163 EXPECT_TRUE(ThreadData::first()); // Now class was constructed.
165 EXPECT_FALSE(data
->next());
166 EXPECT_EQ(data
, ThreadData::Get());
169 parent_child_set
.clear();
170 data
->SnapshotMaps(&birth_map
, &death_map
, &parent_child_set
);
171 EXPECT_EQ(0u, birth_map
.size());
172 EXPECT_EQ(0u, death_map
.size());
173 EXPECT_EQ(0u, parent_child_set
.size());
176 TEST_F(TrackedObjectsTest
, TinyStartupShutdown
) {
177 if (!ThreadData::InitializeAndSetTrackingStatus(
178 ThreadData::PROFILING_CHILDREN_ACTIVE
)) {
182 // Instigate tracking on a single tracked object, on our thread.
183 const char kFunction
[] = "TinyStartupShutdown";
184 Location
location(kFunction
, kFile
, kLineNumber
, NULL
);
185 Births
* first_birth
= ThreadData::TallyABirthIfActive(location
);
187 ThreadData
* data
= ThreadData::first();
189 EXPECT_FALSE(data
->next());
190 EXPECT_EQ(data
, ThreadData::Get());
191 ThreadData::BirthMap birth_map
;
192 ThreadData::DeathMap death_map
;
193 ThreadData::ParentChildSet parent_child_set
;
194 data
->SnapshotMaps(&birth_map
, &death_map
, &parent_child_set
);
195 EXPECT_EQ(1u, birth_map
.size()); // 1 birth location.
196 EXPECT_EQ(1, birth_map
.begin()->second
->birth_count()); // 1 birth.
197 EXPECT_EQ(0u, death_map
.size()); // No deaths.
198 EXPECT_EQ(0u, parent_child_set
.size()); // No children.
201 // Now instigate another birth, while we are timing the run of the first
203 ThreadData::PrepareForStartOfRun(first_birth
);
204 // Create a child (using the same birth location).
205 // TrackingInfo will call TallyABirth() during construction.
206 const int32 start_time
= 1;
207 base::TimeTicks kBogusBirthTime
= base::TimeTicks() +
208 base::TimeDelta::FromMilliseconds(start_time
);
209 base::TrackingInfo
pending_task(location
, kBogusBirthTime
);
211 TaskStopwatch stopwatch
;
213 // Finally conclude the outer run.
214 const int32 time_elapsed
= 1000;
215 SetTestTime(start_time
+ time_elapsed
);
218 ThreadData::TallyRunOnNamedThreadIfTracking(pending_task
, stopwatch
);
222 parent_child_set
.clear();
223 data
->SnapshotMaps(&birth_map
, &death_map
, &parent_child_set
);
224 EXPECT_EQ(1u, birth_map
.size()); // 1 birth location.
225 EXPECT_EQ(2, birth_map
.begin()->second
->birth_count()); // 2 births.
226 EXPECT_EQ(1u, death_map
.size()); // 1 location.
227 EXPECT_EQ(1, death_map
.begin()->second
.count()); // 1 death.
228 if (ThreadData::TrackingParentChildStatus()) {
229 EXPECT_EQ(1u, parent_child_set
.size()); // 1 child.
230 EXPECT_EQ(parent_child_set
.begin()->first
,
231 parent_child_set
.begin()->second
);
233 EXPECT_EQ(0u, parent_child_set
.size()); // no stats.
236 // The births were at the same location as the one known death.
237 EXPECT_EQ(birth_map
.begin()->second
, death_map
.begin()->first
);
239 ProcessDataSnapshot process_data
;
240 ThreadData::Snapshot(&process_data
);
242 ASSERT_EQ(1u, process_data
.phased_process_data_snapshots
.size());
243 auto it
= process_data
.phased_process_data_snapshots
.find(0);
244 ASSERT_TRUE(it
!= process_data
.phased_process_data_snapshots
.end());
245 const ProcessDataPhaseSnapshot
& process_data_phase
= it
->second
;
246 ASSERT_EQ(1u, process_data_phase
.tasks
.size());
247 EXPECT_EQ(kFile
, process_data_phase
.tasks
[0].birth
.location
.file_name
);
249 process_data_phase
.tasks
[0].birth
.location
.function_name
);
250 EXPECT_EQ(kLineNumber
,
251 process_data_phase
.tasks
[0].birth
.location
.line_number
);
252 EXPECT_EQ(kWorkerThreadName
, process_data_phase
.tasks
[0].birth
.thread_name
);
253 EXPECT_EQ(1, process_data_phase
.tasks
[0].death_data
.count
);
254 EXPECT_EQ(time_elapsed
,
255 process_data_phase
.tasks
[0].death_data
.run_duration_sum
);
256 EXPECT_EQ(time_elapsed
,
257 process_data_phase
.tasks
[0].death_data
.run_duration_max
);
258 EXPECT_EQ(time_elapsed
,
259 process_data_phase
.tasks
[0].death_data
.run_duration_sample
);
260 EXPECT_EQ(0, process_data_phase
.tasks
[0].death_data
.queue_duration_sum
);
261 EXPECT_EQ(0, process_data_phase
.tasks
[0].death_data
.queue_duration_max
);
262 EXPECT_EQ(0, process_data_phase
.tasks
[0].death_data
.queue_duration_sample
);
263 EXPECT_EQ(kWorkerThreadName
, process_data_phase
.tasks
[0].death_thread_name
);
265 if (ThreadData::TrackingParentChildStatus()) {
266 ASSERT_EQ(1u, process_data_phase
.descendants
.size());
268 process_data_phase
.descendants
[0].parent
.location
.file_name
);
270 process_data_phase
.descendants
[0].parent
.location
.function_name
);
271 EXPECT_EQ(kLineNumber
,
272 process_data_phase
.descendants
[0].parent
.location
.line_number
);
273 EXPECT_EQ(kWorkerThreadName
,
274 process_data_phase
.descendants
[0].parent
.thread_name
);
276 process_data_phase
.descendants
[0].child
.location
.file_name
);
278 process_data_phase
.descendants
[0].child
.location
.function_name
);
279 EXPECT_EQ(kLineNumber
,
280 process_data_phase
.descendants
[0].child
.location
.line_number
);
281 EXPECT_EQ(kWorkerThreadName
,
282 process_data_phase
.descendants
[0].child
.thread_name
);
284 EXPECT_EQ(0u, process_data_phase
.descendants
.size());
288 TEST_F(TrackedObjectsTest
, DeathDataTest
) {
289 if (!ThreadData::InitializeAndSetTrackingStatus(
290 ThreadData::PROFILING_CHILDREN_ACTIVE
)) {
294 scoped_ptr
<DeathData
> data(new DeathData());
295 ASSERT_NE(data
, reinterpret_cast<DeathData
*>(NULL
));
296 EXPECT_EQ(data
->run_duration_sum(), 0);
297 EXPECT_EQ(data
->run_duration_sample(), 0);
298 EXPECT_EQ(data
->queue_duration_sum(), 0);
299 EXPECT_EQ(data
->queue_duration_sample(), 0);
300 EXPECT_EQ(data
->count(), 0);
305 const int kUnrandomInt
= 0; // Fake random int that ensure we sample data.
306 data
->RecordDeath(queue_ms
, run_ms
, kUnrandomInt
);
307 EXPECT_EQ(data
->run_duration_sum(), run_ms
);
308 EXPECT_EQ(data
->run_duration_sample(), run_ms
);
309 EXPECT_EQ(data
->queue_duration_sum(), queue_ms
);
310 EXPECT_EQ(data
->queue_duration_sample(), queue_ms
);
311 EXPECT_EQ(data
->count(), 1);
313 data
->RecordDeath(queue_ms
, run_ms
, kUnrandomInt
);
314 EXPECT_EQ(data
->run_duration_sum(), run_ms
+ run_ms
);
315 EXPECT_EQ(data
->run_duration_sample(), run_ms
);
316 EXPECT_EQ(data
->queue_duration_sum(), queue_ms
+ queue_ms
);
317 EXPECT_EQ(data
->queue_duration_sample(), queue_ms
);
318 EXPECT_EQ(data
->count(), 2);
320 DeathDataSnapshot
snapshot(*data
);
321 EXPECT_EQ(2, snapshot
.count
);
322 EXPECT_EQ(2 * run_ms
, snapshot
.run_duration_sum
);
323 EXPECT_EQ(run_ms
, snapshot
.run_duration_max
);
324 EXPECT_EQ(run_ms
, snapshot
.run_duration_sample
);
325 EXPECT_EQ(2 * queue_ms
, snapshot
.queue_duration_sum
);
326 EXPECT_EQ(queue_ms
, snapshot
.queue_duration_max
);
327 EXPECT_EQ(queue_ms
, snapshot
.queue_duration_sample
);
330 TEST_F(TrackedObjectsTest
, DeactivatedBirthOnlyToSnapshotWorkerThread
) {
331 // Start in the deactivated state.
332 if (!ThreadData::InitializeAndSetTrackingStatus(ThreadData::DEACTIVATED
)) {
336 const char kFunction
[] = "DeactivatedBirthOnlyToSnapshotWorkerThread";
337 Location
location(kFunction
, kFile
, kLineNumber
, NULL
);
338 TallyABirth(location
, std::string());
340 ProcessDataSnapshot process_data
;
341 ThreadData::Snapshot(&process_data
);
343 ASSERT_EQ(1u, process_data
.phased_process_data_snapshots
.size());
344 auto it
= process_data
.phased_process_data_snapshots
.find(0);
345 ASSERT_TRUE(it
!= process_data
.phased_process_data_snapshots
.end());
346 const ProcessDataPhaseSnapshot
& process_data_phase
= it
->second
;
348 EXPECT_EQ(0u, process_data_phase
.tasks
.size());
349 EXPECT_EQ(0u, process_data_phase
.descendants
.size());
350 EXPECT_EQ(base::GetCurrentProcId(), process_data
.process_id
);
353 TEST_F(TrackedObjectsTest
, DeactivatedBirthOnlyToSnapshotMainThread
) {
354 // Start in the deactivated state.
355 if (!ThreadData::InitializeAndSetTrackingStatus(ThreadData::DEACTIVATED
)) {
359 const char kFunction
[] = "DeactivatedBirthOnlyToSnapshotMainThread";
360 Location
location(kFunction
, kFile
, kLineNumber
, NULL
);
361 TallyABirth(location
, kMainThreadName
);
363 ProcessDataSnapshot process_data
;
364 ThreadData::Snapshot(&process_data
);
366 ASSERT_EQ(1u, process_data
.phased_process_data_snapshots
.size());
367 auto it
= process_data
.phased_process_data_snapshots
.find(0);
368 ASSERT_TRUE(it
!= process_data
.phased_process_data_snapshots
.end());
369 const ProcessDataPhaseSnapshot
& process_data_phase
= it
->second
;
371 EXPECT_EQ(0u, process_data_phase
.tasks
.size());
372 EXPECT_EQ(0u, process_data_phase
.descendants
.size());
373 EXPECT_EQ(base::GetCurrentProcId(), process_data
.process_id
);
376 TEST_F(TrackedObjectsTest
, BirthOnlyToSnapshotWorkerThread
) {
377 if (!ThreadData::InitializeAndSetTrackingStatus(
378 ThreadData::PROFILING_CHILDREN_ACTIVE
)) {
382 const char kFunction
[] = "BirthOnlyToSnapshotWorkerThread";
383 Location
location(kFunction
, kFile
, kLineNumber
, NULL
);
384 TallyABirth(location
, std::string());
386 ProcessDataSnapshot process_data
;
387 ThreadData::Snapshot(&process_data
);
388 ExpectSimpleProcessData(process_data
, kFunction
, kWorkerThreadName
,
389 kStillAlive
, 1, 0, 0);
392 TEST_F(TrackedObjectsTest
, BirthOnlyToSnapshotMainThread
) {
393 if (!ThreadData::InitializeAndSetTrackingStatus(
394 ThreadData::PROFILING_CHILDREN_ACTIVE
)) {
398 const char kFunction
[] = "BirthOnlyToSnapshotMainThread";
399 Location
location(kFunction
, kFile
, kLineNumber
, NULL
);
400 TallyABirth(location
, kMainThreadName
);
402 ProcessDataSnapshot process_data
;
403 ThreadData::Snapshot(&process_data
);
404 ExpectSimpleProcessData(process_data
, kFunction
, kMainThreadName
, kStillAlive
,
408 TEST_F(TrackedObjectsTest
, LifeCycleToSnapshotMainThread
) {
409 if (!ThreadData::InitializeAndSetTrackingStatus(
410 ThreadData::PROFILING_CHILDREN_ACTIVE
)) {
414 const char kFunction
[] = "LifeCycleToSnapshotMainThread";
415 Location
location(kFunction
, kFile
, kLineNumber
, NULL
);
416 TallyABirth(location
, kMainThreadName
);
418 const TrackedTime kTimePosted
= TrackedTime::FromMilliseconds(1);
419 const base::TimeTicks kDelayedStartTime
= base::TimeTicks();
420 // TrackingInfo will call TallyABirth() during construction.
421 base::TrackingInfo
pending_task(location
, kDelayedStartTime
);
422 pending_task
.time_posted
= kTimePosted
; // Overwrite implied Now().
424 const unsigned int kStartOfRun
= 5;
425 const unsigned int kEndOfRun
= 7;
426 SetTestTime(kStartOfRun
);
427 TaskStopwatch stopwatch
;
429 SetTestTime(kEndOfRun
);
432 ThreadData::TallyRunOnNamedThreadIfTracking(pending_task
, stopwatch
);
434 ProcessDataSnapshot process_data
;
435 ThreadData::Snapshot(&process_data
);
436 ExpectSimpleProcessData(process_data
, kFunction
, kMainThreadName
,
437 kMainThreadName
, 1, 2, 4);
440 // We will deactivate tracking after the birth, and before the death, and
441 // demonstrate that the lifecycle is completely tallied. This ensures that
442 // our tallied births are matched by tallied deaths (except for when the
443 // task is still running, or is queued).
444 TEST_F(TrackedObjectsTest
, LifeCycleMidDeactivatedToSnapshotMainThread
) {
445 if (!ThreadData::InitializeAndSetTrackingStatus(
446 ThreadData::PROFILING_CHILDREN_ACTIVE
)) {
450 const char kFunction
[] = "LifeCycleMidDeactivatedToSnapshotMainThread";
451 Location
location(kFunction
, kFile
, kLineNumber
, NULL
);
452 TallyABirth(location
, kMainThreadName
);
454 const TrackedTime kTimePosted
= TrackedTime::FromMilliseconds(1);
455 const base::TimeTicks kDelayedStartTime
= base::TimeTicks();
456 // TrackingInfo will call TallyABirth() during construction.
457 base::TrackingInfo
pending_task(location
, kDelayedStartTime
);
458 pending_task
.time_posted
= kTimePosted
; // Overwrite implied Now().
460 // Turn off tracking now that we have births.
462 ThreadData::InitializeAndSetTrackingStatus(ThreadData::DEACTIVATED
));
464 const unsigned int kStartOfRun
= 5;
465 const unsigned int kEndOfRun
= 7;
466 SetTestTime(kStartOfRun
);
467 TaskStopwatch stopwatch
;
469 SetTestTime(kEndOfRun
);
472 ThreadData::TallyRunOnNamedThreadIfTracking(pending_task
, stopwatch
);
474 ProcessDataSnapshot process_data
;
475 ThreadData::Snapshot(&process_data
);
476 ExpectSimpleProcessData(process_data
, kFunction
, kMainThreadName
,
477 kMainThreadName
, 1, 2, 4);
480 // We will deactivate tracking before starting a life cycle, and neither
481 // the birth nor the death will be recorded.
482 TEST_F(TrackedObjectsTest
, LifeCyclePreDeactivatedToSnapshotMainThread
) {
483 // Start in the deactivated state.
484 if (!ThreadData::InitializeAndSetTrackingStatus(ThreadData::DEACTIVATED
)) {
488 const char kFunction
[] = "LifeCyclePreDeactivatedToSnapshotMainThread";
489 Location
location(kFunction
, kFile
, kLineNumber
, NULL
);
490 TallyABirth(location
, kMainThreadName
);
492 const TrackedTime kTimePosted
= TrackedTime::FromMilliseconds(1);
493 const base::TimeTicks kDelayedStartTime
= base::TimeTicks();
494 // TrackingInfo will call TallyABirth() during construction.
495 base::TrackingInfo
pending_task(location
, kDelayedStartTime
);
496 pending_task
.time_posted
= kTimePosted
; // Overwrite implied Now().
498 const unsigned int kStartOfRun
= 5;
499 const unsigned int kEndOfRun
= 7;
500 SetTestTime(kStartOfRun
);
501 TaskStopwatch stopwatch
;
503 SetTestTime(kEndOfRun
);
506 ThreadData::TallyRunOnNamedThreadIfTracking(pending_task
, stopwatch
);
508 ProcessDataSnapshot process_data
;
509 ThreadData::Snapshot(&process_data
);
511 ASSERT_EQ(1u, process_data
.phased_process_data_snapshots
.size());
512 auto it
= process_data
.phased_process_data_snapshots
.find(0);
513 ASSERT_TRUE(it
!= process_data
.phased_process_data_snapshots
.end());
514 const ProcessDataPhaseSnapshot
& process_data_phase
= it
->second
;
516 EXPECT_EQ(0u, process_data_phase
.tasks
.size());
517 EXPECT_EQ(0u, process_data_phase
.descendants
.size());
518 EXPECT_EQ(base::GetCurrentProcId(), process_data
.process_id
);
521 TEST_F(TrackedObjectsTest
, TwoLives
) {
522 if (!ThreadData::InitializeAndSetTrackingStatus(
523 ThreadData::PROFILING_CHILDREN_ACTIVE
)) {
527 const char kFunction
[] = "TwoLives";
528 Location
location(kFunction
, kFile
, kLineNumber
, NULL
);
529 TallyABirth(location
, kMainThreadName
);
531 const TrackedTime kTimePosted
= TrackedTime::FromMilliseconds(1);
532 const base::TimeTicks kDelayedStartTime
= base::TimeTicks();
533 // TrackingInfo will call TallyABirth() during construction.
534 base::TrackingInfo
pending_task(location
, kDelayedStartTime
);
535 pending_task
.time_posted
= kTimePosted
; // Overwrite implied Now().
537 const unsigned int kStartOfRun
= 5;
538 const unsigned int kEndOfRun
= 7;
539 SetTestTime(kStartOfRun
);
540 TaskStopwatch stopwatch
;
542 SetTestTime(kEndOfRun
);
545 ThreadData::TallyRunOnNamedThreadIfTracking(pending_task
, stopwatch
);
547 // TrackingInfo will call TallyABirth() during construction.
548 base::TrackingInfo
pending_task2(location
, kDelayedStartTime
);
549 pending_task2
.time_posted
= kTimePosted
; // Overwrite implied Now().
550 SetTestTime(kStartOfRun
);
551 TaskStopwatch stopwatch2
;
553 SetTestTime(kEndOfRun
);
556 ThreadData::TallyRunOnNamedThreadIfTracking(pending_task2
, stopwatch2
);
558 ProcessDataSnapshot process_data
;
559 ThreadData::Snapshot(&process_data
);
560 ExpectSimpleProcessData(process_data
, kFunction
, kMainThreadName
,
561 kMainThreadName
, 2, 2, 4);
564 TEST_F(TrackedObjectsTest
, DifferentLives
) {
565 if (!ThreadData::InitializeAndSetTrackingStatus(
566 ThreadData::PROFILING_CHILDREN_ACTIVE
)) {
570 // Use a well named thread.
571 ThreadData::InitializeThreadContext(kMainThreadName
);
572 const char kFunction
[] = "DifferentLives";
573 Location
location(kFunction
, kFile
, kLineNumber
, NULL
);
575 const TrackedTime kTimePosted
= TrackedTime::FromMilliseconds(1);
576 const base::TimeTicks kDelayedStartTime
= base::TimeTicks();
577 // TrackingInfo will call TallyABirth() during construction.
578 base::TrackingInfo
pending_task(location
, kDelayedStartTime
);
579 pending_task
.time_posted
= kTimePosted
; // Overwrite implied Now().
581 const unsigned int kStartOfRun
= 5;
582 const unsigned int kEndOfRun
= 7;
583 SetTestTime(kStartOfRun
);
584 TaskStopwatch stopwatch
;
586 SetTestTime(kEndOfRun
);
589 ThreadData::TallyRunOnNamedThreadIfTracking(pending_task
, stopwatch
);
591 const int kSecondFakeLineNumber
= 999;
592 Location
second_location(kFunction
, kFile
, kSecondFakeLineNumber
, NULL
);
594 // TrackingInfo will call TallyABirth() during construction.
595 base::TrackingInfo
pending_task2(second_location
, kDelayedStartTime
);
596 pending_task2
.time_posted
= kTimePosted
; // Overwrite implied Now().
598 ProcessDataSnapshot process_data
;
599 ThreadData::Snapshot(&process_data
);
601 ASSERT_EQ(1u, process_data
.phased_process_data_snapshots
.size());
602 auto it
= process_data
.phased_process_data_snapshots
.find(0);
603 ASSERT_TRUE(it
!= process_data
.phased_process_data_snapshots
.end());
604 const ProcessDataPhaseSnapshot
& process_data_phase
= it
->second
;
606 ASSERT_EQ(2u, process_data_phase
.tasks
.size());
608 EXPECT_EQ(kFile
, process_data_phase
.tasks
[0].birth
.location
.file_name
);
610 process_data_phase
.tasks
[0].birth
.location
.function_name
);
611 EXPECT_EQ(kLineNumber
,
612 process_data_phase
.tasks
[0].birth
.location
.line_number
);
613 EXPECT_EQ(kMainThreadName
, process_data_phase
.tasks
[0].birth
.thread_name
);
614 EXPECT_EQ(1, process_data_phase
.tasks
[0].death_data
.count
);
615 EXPECT_EQ(2, process_data_phase
.tasks
[0].death_data
.run_duration_sum
);
616 EXPECT_EQ(2, process_data_phase
.tasks
[0].death_data
.run_duration_max
);
617 EXPECT_EQ(2, process_data_phase
.tasks
[0].death_data
.run_duration_sample
);
618 EXPECT_EQ(4, process_data_phase
.tasks
[0].death_data
.queue_duration_sum
);
619 EXPECT_EQ(4, process_data_phase
.tasks
[0].death_data
.queue_duration_max
);
620 EXPECT_EQ(4, process_data_phase
.tasks
[0].death_data
.queue_duration_sample
);
621 EXPECT_EQ(kMainThreadName
, process_data_phase
.tasks
[0].death_thread_name
);
622 EXPECT_EQ(kFile
, process_data_phase
.tasks
[1].birth
.location
.file_name
);
624 process_data_phase
.tasks
[1].birth
.location
.function_name
);
625 EXPECT_EQ(kSecondFakeLineNumber
,
626 process_data_phase
.tasks
[1].birth
.location
.line_number
);
627 EXPECT_EQ(kMainThreadName
, process_data_phase
.tasks
[1].birth
.thread_name
);
628 EXPECT_EQ(1, process_data_phase
.tasks
[1].death_data
.count
);
629 EXPECT_EQ(0, process_data_phase
.tasks
[1].death_data
.run_duration_sum
);
630 EXPECT_EQ(0, process_data_phase
.tasks
[1].death_data
.run_duration_max
);
631 EXPECT_EQ(0, process_data_phase
.tasks
[1].death_data
.run_duration_sample
);
632 EXPECT_EQ(0, process_data_phase
.tasks
[1].death_data
.queue_duration_sum
);
633 EXPECT_EQ(0, process_data_phase
.tasks
[1].death_data
.queue_duration_max
);
634 EXPECT_EQ(0, process_data_phase
.tasks
[1].death_data
.queue_duration_sample
);
635 EXPECT_EQ(kStillAlive
, process_data_phase
.tasks
[1].death_thread_name
);
636 EXPECT_EQ(0u, process_data_phase
.descendants
.size());
637 EXPECT_EQ(base::GetCurrentProcId(), process_data
.process_id
);
640 TEST_F(TrackedObjectsTest
, TaskWithNestedExclusion
) {
641 if (!ThreadData::InitializeAndSetTrackingStatus(
642 ThreadData::PROFILING_CHILDREN_ACTIVE
)) {
646 const char kFunction
[] = "TaskWithNestedExclusion";
647 Location
location(kFunction
, kFile
, kLineNumber
, NULL
);
648 TallyABirth(location
, kMainThreadName
);
650 const TrackedTime kTimePosted
= TrackedTime::FromMilliseconds(1);
651 const base::TimeTicks kDelayedStartTime
= base::TimeTicks();
652 // TrackingInfo will call TallyABirth() during construction.
653 base::TrackingInfo
pending_task(location
, kDelayedStartTime
);
654 pending_task
.time_posted
= kTimePosted
; // Overwrite implied Now().
657 TaskStopwatch task_stopwatch
;
658 task_stopwatch
.Start();
661 TaskStopwatch exclusion_stopwatch
;
662 exclusion_stopwatch
.Start();
664 exclusion_stopwatch
.Stop();
667 task_stopwatch
.Stop();
669 ThreadData::TallyRunOnNamedThreadIfTracking(pending_task
, task_stopwatch
);
671 ProcessDataSnapshot process_data
;
672 ThreadData::Snapshot(&process_data
);
673 ExpectSimpleProcessData(process_data
, kFunction
, kMainThreadName
,
674 kMainThreadName
, 1, 6, 4);
677 TEST_F(TrackedObjectsTest
, TaskWith2NestedExclusions
) {
678 if (!ThreadData::InitializeAndSetTrackingStatus(
679 ThreadData::PROFILING_CHILDREN_ACTIVE
)) {
683 const char kFunction
[] = "TaskWith2NestedExclusions";
684 Location
location(kFunction
, kFile
, kLineNumber
, NULL
);
685 TallyABirth(location
, kMainThreadName
);
687 const TrackedTime kTimePosted
= TrackedTime::FromMilliseconds(1);
688 const base::TimeTicks kDelayedStartTime
= base::TimeTicks();
689 // TrackingInfo will call TallyABirth() during construction.
690 base::TrackingInfo
pending_task(location
, kDelayedStartTime
);
691 pending_task
.time_posted
= kTimePosted
; // Overwrite implied Now().
694 TaskStopwatch task_stopwatch
;
695 task_stopwatch
.Start();
698 TaskStopwatch exclusion_stopwatch
;
699 exclusion_stopwatch
.Start();
701 exclusion_stopwatch
.Stop();
704 TaskStopwatch exclusion_stopwatch2
;
705 exclusion_stopwatch2
.Start();
707 exclusion_stopwatch2
.Stop();
710 task_stopwatch
.Stop();
712 ThreadData::TallyRunOnNamedThreadIfTracking(pending_task
, task_stopwatch
);
714 ProcessDataSnapshot process_data
;
715 ThreadData::Snapshot(&process_data
);
716 ExpectSimpleProcessData(process_data
, kFunction
, kMainThreadName
,
717 kMainThreadName
, 1, 13, 4);
720 TEST_F(TrackedObjectsTest
, TaskWithNestedExclusionWithNestedTask
) {
721 if (!ThreadData::InitializeAndSetTrackingStatus(
722 ThreadData::PROFILING_CHILDREN_ACTIVE
)) {
726 const char kFunction
[] = "TaskWithNestedExclusionWithNestedTask";
727 Location
location(kFunction
, kFile
, kLineNumber
, NULL
);
729 const int kSecondFakeLineNumber
= 999;
731 TallyABirth(location
, kMainThreadName
);
733 const TrackedTime kTimePosted
= TrackedTime::FromMilliseconds(1);
734 const base::TimeTicks kDelayedStartTime
= base::TimeTicks();
735 // TrackingInfo will call TallyABirth() during construction.
736 base::TrackingInfo
pending_task(location
, kDelayedStartTime
);
737 pending_task
.time_posted
= kTimePosted
; // Overwrite implied Now().
740 TaskStopwatch task_stopwatch
;
741 task_stopwatch
.Start();
744 TaskStopwatch exclusion_stopwatch
;
745 exclusion_stopwatch
.Start();
747 Location
second_location(kFunction
, kFile
, kSecondFakeLineNumber
, NULL
);
748 base::TrackingInfo
nested_task(second_location
, kDelayedStartTime
);
749 // Overwrite implied Now().
750 nested_task
.time_posted
= TrackedTime::FromMilliseconds(8);
752 TaskStopwatch nested_task_stopwatch
;
753 nested_task_stopwatch
.Start();
755 nested_task_stopwatch
.Stop();
756 ThreadData::TallyRunOnNamedThreadIfTracking(
757 nested_task
, nested_task_stopwatch
);
760 exclusion_stopwatch
.Stop();
763 task_stopwatch
.Stop();
765 ThreadData::TallyRunOnNamedThreadIfTracking(pending_task
, task_stopwatch
);
767 ProcessDataSnapshot process_data
;
768 ThreadData::Snapshot(&process_data
);
770 ASSERT_EQ(1u, process_data
.phased_process_data_snapshots
.size());
771 auto it
= process_data
.phased_process_data_snapshots
.find(0);
772 ASSERT_TRUE(it
!= process_data
.phased_process_data_snapshots
.end());
773 const ProcessDataPhaseSnapshot
& process_data_phase
= it
->second
;
775 // The order in which the two task follow is platform-dependent.
777 (process_data_phase
.tasks
[0].birth
.location
.line_number
== kLineNumber
)
782 ASSERT_EQ(2u, process_data_phase
.tasks
.size());
783 EXPECT_EQ(kFile
, process_data_phase
.tasks
[t0
].birth
.location
.file_name
);
785 process_data_phase
.tasks
[t0
].birth
.location
.function_name
);
786 EXPECT_EQ(kLineNumber
,
787 process_data_phase
.tasks
[t0
].birth
.location
.line_number
);
788 EXPECT_EQ(kMainThreadName
, process_data_phase
.tasks
[t0
].birth
.thread_name
);
789 EXPECT_EQ(1, process_data_phase
.tasks
[t0
].death_data
.count
);
790 EXPECT_EQ(6, process_data_phase
.tasks
[t0
].death_data
.run_duration_sum
);
791 EXPECT_EQ(6, process_data_phase
.tasks
[t0
].death_data
.run_duration_max
);
792 EXPECT_EQ(6, process_data_phase
.tasks
[t0
].death_data
.run_duration_sample
);
793 EXPECT_EQ(4, process_data_phase
.tasks
[t0
].death_data
.queue_duration_sum
);
794 EXPECT_EQ(4, process_data_phase
.tasks
[t0
].death_data
.queue_duration_max
);
795 EXPECT_EQ(4, process_data_phase
.tasks
[t0
].death_data
.queue_duration_sample
);
796 EXPECT_EQ(kMainThreadName
, process_data_phase
.tasks
[t0
].death_thread_name
);
797 EXPECT_EQ(kFile
, process_data_phase
.tasks
[t1
].birth
.location
.file_name
);
799 process_data_phase
.tasks
[t1
].birth
.location
.function_name
);
800 EXPECT_EQ(kSecondFakeLineNumber
,
801 process_data_phase
.tasks
[t1
].birth
.location
.line_number
);
802 EXPECT_EQ(kMainThreadName
, process_data_phase
.tasks
[t1
].birth
.thread_name
);
803 EXPECT_EQ(1, process_data_phase
.tasks
[t1
].death_data
.count
);
804 EXPECT_EQ(2, process_data_phase
.tasks
[t1
].death_data
.run_duration_sum
);
805 EXPECT_EQ(2, process_data_phase
.tasks
[t1
].death_data
.run_duration_max
);
806 EXPECT_EQ(2, process_data_phase
.tasks
[t1
].death_data
.run_duration_sample
);
807 EXPECT_EQ(1, process_data_phase
.tasks
[t1
].death_data
.queue_duration_sum
);
808 EXPECT_EQ(1, process_data_phase
.tasks
[t1
].death_data
.queue_duration_max
);
809 EXPECT_EQ(1, process_data_phase
.tasks
[t1
].death_data
.queue_duration_sample
);
810 EXPECT_EQ(kMainThreadName
, process_data_phase
.tasks
[t1
].death_thread_name
);
811 EXPECT_EQ(0u, process_data_phase
.descendants
.size());
812 EXPECT_EQ(base::GetCurrentProcId(), process_data
.process_id
);
815 } // namespace tracked_objects