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