<commit_before>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Test of classes in the tracked_objects.h classes.

#include "base/tracked_objects.h"

#include "base/json/json_writer.h"
#include "base/memory/scoped_ptr.h"
#include "base/time.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace tracked_objects {

class TrackedObjectsTest : public testing::Test {
 protected:
  TrackedObjectsTest() {
    // On entry, leak any database structures in case they are still in use by
    // prior threads.
    ThreadData::ShutdownSingleThreadedCleanup(true);
  }

  ~TrackedObjectsTest() {
    // We should not need to leak any structures we create, since we are
    // single threaded, and carefully accounting for items.
    ThreadData::ShutdownSingleThreadedCleanup(false);
  }

  // Provide access, since this class is a friend of ThreadData.
  void ShutdownSingleThreadedCleanup(bool leak) {
    ThreadData::ShutdownSingleThreadedCleanup(leak);
  }
};

TEST_F(TrackedObjectsTest, MinimalStartupShutdown) {
  // Minimal test doesn't even create any tasks.
  if (!ThreadData::InitializeAndSetTrackingStatus(true))
    return;

  EXPECT_FALSE(ThreadData::first());  // No activity even on this thread.
  ThreadData* data = ThreadData::Get();
  EXPECT_TRUE(ThreadData::first());  // Now class was constructed.
  EXPECT_TRUE(data);
  EXPECT_TRUE(!data->next());
  EXPECT_EQ(data, ThreadData::Get());
  ThreadData::BirthMap birth_map;
  ThreadData::DeathMap death_map;
  ThreadData::ParentChildSet parent_child_set;
  data->SnapshotMaps(false, &birth_map, &death_map, &parent_child_set);
  EXPECT_EQ(0u, birth_map.size());
  EXPECT_EQ(0u, death_map.size());
  EXPECT_EQ(0u, parent_child_set.size());
  // Cleanup with no leaking.
  ShutdownSingleThreadedCleanup(false);

  // Do it again, just to be sure we reset state completely.
  ThreadData::InitializeAndSetTrackingStatus(true);
  EXPECT_FALSE(ThreadData::first());  // No activity even on this thread.
  data = ThreadData::Get();
  EXPECT_TRUE(ThreadData::first());  // Now class was constructed.
  EXPECT_TRUE(data);
  EXPECT_TRUE(!data->next());
  EXPECT_EQ(data, ThreadData::Get());
  birth_map.clear();
  death_map.clear();
  data->SnapshotMaps(false, &birth_map, &death_map, &parent_child_set);
  EXPECT_EQ(0u, birth_map.size());
  EXPECT_EQ(0u, death_map.size());
  EXPECT_EQ(0u, parent_child_set.size());
}

TEST_F(TrackedObjectsTest, TinyStartupShutdown) {
  if (!ThreadData::InitializeAndSetTrackingStatus(true))
    return;

  // Instigate tracking on a single tracked object, on our thread.
  const Location& location = FROM_HERE;
  Births* first_birth = ThreadData::TallyABirthIfActive(location);

  ThreadData* data = ThreadData::first();
  ASSERT_TRUE(data);
  EXPECT_TRUE(!data->next());
  EXPECT_EQ(data, ThreadData::Get());
  ThreadData::BirthMap birth_map;
  ThreadData::DeathMap death_map;
  ThreadData::ParentChildSet parent_child_set;
  data->SnapshotMaps(false, &birth_map, &death_map, &parent_child_set);
  EXPECT_EQ(1u, birth_map.size());                         // 1 birth location.
  EXPECT_EQ(1, birth_map.begin()->second->birth_count());  // 1 birth.
  EXPECT_EQ(0u, death_map.size());                         // No deaths.
  EXPECT_EQ(0u, parent_child_set.size());                  // No children.


  // Now instigate another birth, while we are timing the run of the first
  // execution.
  TrackedTime start_time =
      ThreadData::NowForStartOfRun(first_birth);
  // Create a child (using the same birth location).
  // TrackingInfo will call TallyABirth() during construction.
  base::TimeTicks kBogusBirthTime;
  base::TrackingInfo pending_task(location, kBogusBirthTime);
  // Finally conclude the outer run.
  TrackedTime end_time = ThreadData::NowForEndOfRun();
  ThreadData::TallyRunOnNamedThreadIfTracking(pending_task, start_time,
                                              end_time);

  birth_map.clear();
  death_map.clear();
  parent_child_set.clear();
  data->SnapshotMaps(false, &birth_map, &death_map, &parent_child_set);
  EXPECT_EQ(1u, birth_map.size());                         // 1 birth location.
  EXPECT_EQ(2, birth_map.begin()->second->birth_count());  // 2 births.
  EXPECT_EQ(1u, death_map.size());                         // 1 location.
  EXPECT_EQ(1, death_map.begin()->second.count());         // 1 death.
  if (ThreadData::tracking_parent_child_status()) {
    EXPECT_EQ(1u, parent_child_set.size());                  // 1 child.
    EXPECT_EQ(parent_child_set.begin()->first,
              parent_child_set.begin()->second);
  } else {
    EXPECT_EQ(0u, parent_child_set.size());                  // no stats.
  }

  // The births were at the same location as the one known death.
  EXPECT_EQ(birth_map.begin()->second, death_map.begin()->first);
}

TEST_F(TrackedObjectsTest, ParentChildTest) {
  if (!ThreadData::InitializeAndSetTrackingStatus(true))
    return;
  if (!ThreadData::tracking_parent_child_status())
    return;   // Feature not compiled in.

  // Instigate tracking on a single tracked object, on our thread.
  const int kFakeLineNumber = 1776;
  const char* kFile = "FixedUnitTestFileName";
  const char* kFunction = "ParentChildTest";
  Location location(kFunction, kFile, kFakeLineNumber, NULL);
  Births* first_birth = ThreadData::TallyABirthIfActive(location);

  // Now instigate another birth, while we are timing the run of the first
  // execution.
  TrackedTime start_time =
      ThreadData::NowForStartOfRun(first_birth);
  // Create a child (using the same birth location).
  // TrackingInfo will call TallyABirth() during construction.
  base::TimeTicks kBogusBirthTime;
  base::TrackingInfo pending_task(location, kBogusBirthTime);

  // Don't conclude the run, so that we don't use the actual timer that we
  // started for the outer profile.  This way the JSON will not include some
  // random time.
  ThreadData* data = ThreadData::first();
  ASSERT_TRUE(data);
  EXPECT_TRUE(!data->next());
  EXPECT_EQ(data, ThreadData::Get());

  ThreadData::BirthMap birth_map;
  ThreadData::DeathMap death_map;
  ThreadData::ParentChildSet parent_child_set;

  data->SnapshotMaps(false, &birth_map, &death_map, &parent_child_set);<commit_msg>Compile fix for gcc 4.6, unused variables.<commit_after>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Test of classes in the tracked_objects.h classes.

#include "base/tracked_objects.h"

#include "base/json/json_writer.h"
#include "base/memory/scoped_ptr.h"
#include "base/time.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace tracked_objects {

class TrackedObjectsTest : public testing::Test {
 protected:
  TrackedObjectsTest() {
    // On entry, leak any database structures in case they are still in use by
    // prior threads.
    ThreadData::ShutdownSingleThreadedCleanup(true);
  }

  ~TrackedObjectsTest() {
    // We should not need to leak any structures we create, since we are
    // single threaded, and carefully accounting for items.
    ThreadData::ShutdownSingleThreadedCleanup(false);
  }

  // Provide access, since this class is a friend of ThreadData.
  void ShutdownSingleThreadedCleanup(bool leak) {
    ThreadData::ShutdownSingleThreadedCleanup(leak);
  }
};

TEST_F(TrackedObjectsTest, MinimalStartupShutdown) {
  // Minimal test doesn't even create any tasks.
  if (!ThreadData::InitializeAndSetTrackingStatus(true))
    return;

  EXPECT_FALSE(ThreadData::first());  // No activity even on this thread.
  ThreadData* data = ThreadData::Get();
  EXPECT_TRUE(ThreadData::first());  // Now class was constructed.
  EXPECT_TRUE(data);
  EXPECT_TRUE(!data->next());
  EXPECT_EQ(data, ThreadData::Get());
  ThreadData::BirthMap birth_map;
  ThreadData::DeathMap death_map;
  ThreadData::ParentChildSet parent_child_set;
  data->SnapshotMaps(false, &birth_map, &death_map, &parent_child_set);
  EXPECT_EQ(0u, birth_map.size());
  EXPECT_EQ(0u, death_map.size());
  EXPECT_EQ(0u, parent_child_set.size());
  // Cleanup with no leaking.
  ShutdownSingleThreadedCleanup(false);

  // Do it again, just to be sure we reset state completely.
  ThreadData::InitializeAndSetTrackingStatus(true);
  EXPECT_FALSE(ThreadData::first());  // No activity even on this thread.
  data = ThreadData::Get();
  EXPECT_TRUE(ThreadData::first());  // Now class was constructed.
  EXPECT_TRUE(data);
  EXPECT_TRUE(!data->next());
  EXPECT_EQ(data, ThreadData::Get());
  birth_map.clear();
  death_map.clear();
  data->SnapshotMaps(false, &birth_map, &death_map, &parent_child_set);
  EXPECT_EQ(0u, birth_map.size());
  EXPECT_EQ(0u, death_map.size());
  EXPECT_EQ(0u, parent_child_set.size());
}

TEST_F(TrackedObjectsTest, TinyStartupShutdown) {
  if (!ThreadData::InitializeAndSetTrackingStatus(true))
    return;

  // Instigate tracking on a single tracked object, on our thread.
  const Location& location = FROM_HERE;
  Births* first_birth = ThreadData::TallyABirthIfActive(location);

  ThreadData* data = ThreadData::first();
  ASSERT_TRUE(data);
  EXPECT_TRUE(!data->next());
  EXPECT_EQ(data, ThreadData::Get());
  ThreadData::BirthMap birth_map;
  ThreadData::DeathMap death_map;
  ThreadData::ParentChildSet parent_child_set;
  data->SnapshotMaps(false, &birth_map, &death_map, &parent_child_set);
  EXPECT_EQ(1u, birth_map.size());                         // 1 birth location.
  EXPECT_EQ(1, birth_map.begin()->second->birth_count());  // 1 birth.
  EXPECT_EQ(0u, death_map.size());                         // No deaths.
  EXPECT_EQ(0u, parent_child_set.size());                  // No children.


  // Now instigate another birth, while we are timing the run of the first
  // execution.
  TrackedTime start_time =
      ThreadData::NowForStartOfRun(first_birth);
  // Create a child (using the same birth location).
  // TrackingInfo will call TallyABirth() during construction.
  base::TimeTicks kBogusBirthTime;
  base::TrackingInfo pending_task(location, kBogusBirthTime);
  // Finally conclude the outer run.
  TrackedTime end_time = ThreadData::NowForEndOfRun();
  ThreadData::TallyRunOnNamedThreadIfTracking(pending_task, start_time,
                                              end_time);

  birth_map.clear();
  death_map.clear();
  parent_child_set.clear();
  data->SnapshotMaps(false, &birth_map, &death_map, &parent_child_set);
  EXPECT_EQ(1u, birth_map.size());                         // 1 birth location.
  EXPECT_EQ(2, birth_map.begin()->second->birth_count());  // 2 births.
  EXPECT_EQ(1u, death_map.size());                         // 1 location.
  EXPECT_EQ(1, death_map.begin()->second.count());         // 1 death.
  if (ThreadData::tracking_parent_child_status()) {
    EXPECT_EQ(1u, parent_child_set.size());                  // 1 child.
    EXPECT_EQ(parent_child_set.begin()->first,
              parent_child_set.begin()->second);
  } else {
    EXPECT_EQ(0u, parent_child_set.size());                  // no stats.
  }

  // The births were at the same location as the one known death.
  EXPECT_EQ(birth_map.begin()->second, death_map.begin()->first);
}

TEST_F(TrackedObjectsTest, ParentChildTest) {
  if (!ThreadData::InitializeAndSetTrackingStatus(true))
    return;
  if (!ThreadData::tracking_parent_child_status())
    return;   // Feature not compiled in.

  // Instigate tracking on a single tracked object, on our thread.
  const int kFakeLineNumber = 1776;
  const char* kFile = "FixedUnitTestFileName";
  const char* kFunction = "ParentChildTest";
  Location location(kFunction, kFile, kFakeLineNumber, NULL);

  // Now instigate another birth, while we are timing the run of the first
  // execution.

  // Create a child (using the same birth location).
  // TrackingInfo will call TallyABirth() during construction.
  base::TimeTicks kBogusBirthTime;
  base::TrackingInfo pending_task(location, kBogusBirthTime);

  // Don't conclude the run, so that we don't use the actual timer that we
  // started for the outer profile.  This way the JSON will not include some
  // random time.
  ThreadData* data = ThreadData::first();
  ASSERT_TRUE(data);
  EXPECT_TRUE(!data->next());
  EXPECT_EQ(data, ThreadData::Get());

  ThreadData::BirthMap birth_map;
  ThreadData::DeathMap death_map;
  ThreadData::ParentChildSet parent_child_set;

  data->SnapshotMaps(false, &birth_map, &death_map, &parent_child_set);
{'fraction_non_alphanumeric': 0.11857770675189773, 'fraction_numerical': 0.005113863363963244, 'mean_word_length': 4.002398081534772, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 39, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3606164', 'n_tokens_mistral': 3967, 'n_tokens_neox': 3899, 'n_words': 957}