/*
 * Copyright 2016 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "nb/analytics/memory_tracker_impl.h"
#include "nb/memory_scope.h"
#include "nb/scoped_ptr.h"
#include "nb/test_thread.h"
#include "starboard/configuration.h"
#include "starboard/system.h"
#include "testing/gtest/include/gtest/gtest.h"

#define STRESS_TEST_DURATION_SECONDS 1
#define NUM_STRESS_TEST_THREADS 3

// The following is necessary to prevent operator new from being optimized
// out using some compilers. This is required because we rely on operator new
// to report memory usage. Overly aggressive optimizing compilers will
// eliminate the call to operator new, even though it causes a lost of side
// effects. This will therefore break the memory reporting mechanism. This is
// a bug in the compiler.
//
// The solution here is to use macro-replacement to substitute calls to global
// new to instead be delegated to our custom new, which prevents elimination
// by using a temporay volatile.
namespace {
struct CustomObject {
  static CustomObject Make() {
    CustomObject o;
    return o;
  }
};
}

void* operator new(std::size_t size, CustomObject ignored) {
  SB_UNREFERENCED_PARAMETER(ignored);
  // Volatile prevents optimization and elimination of operator new by the
  // optimizing compiler.
  volatile void* ptr = ::operator new(size);
  return const_cast<void*>(ptr);
}

#define NEW_NO_OPTIMIZER_ELIMINATION new (CustomObject::Make())
#define new NEW_NO_OPTIMIZER_ELIMINATION

namespace nb {
namespace analytics {
namespace {

class NoReportAllocator {
 public:
  NoReportAllocator() {}
  NoReportAllocator(const NoReportAllocator&) {}
  static void* Allocate(size_t n) {
    return SbMemoryAllocateNoReport(n);
  }
  // Second argument can be used for accounting, but is otherwise optional.
  static void Deallocate(void* ptr, size_t /* not used*/) {
    SbMemoryDeallocateNoReport(ptr);
  }
};

// Some platforms will allocate memory for empty vectors. Therefore
// use MyVector to prevent empty vectors from reporting memory.
template <typename T>
using MyVector = std::vector<T, StdAllocator<T, NoReportAllocator>>;

MemoryTrackerImpl* s_memory_tracker_ = NULL;

struct NoMemTracking {
  bool prev_val;
  NoMemTracking() : prev_val(false) {
    if (s_memory_tracker_) {
      prev_val = s_memory_tracker_->IsMemoryTrackingEnabled();
      s_memory_tracker_->SetMemoryTrackingEnabled(false);
    }
  }
  ~NoMemTracking() {
    if (s_memory_tracker_) {
      s_memory_tracker_->SetMemoryTrackingEnabled(prev_val);
    }
  }
};

// EXPECT_XXX and ASSERT_XXX allocate memory, a big no-no when
// for unit testing allocations. These overrides disable memory
// tracking for the duration of the EXPECT and ASSERT operations.
#define EXPECT_EQ_NO_TRACKING(A, B)                 \
  {                                                 \
    NoMemTracking no_memory_tracking_in_this_scope; \
    EXPECT_EQ(A, B);                                \
  }

#define EXPECT_TRUE_NO_TRACKING(A)                  \
  {                                                 \
    NoMemTracking no_memory_tracking_in_this_scope; \
    EXPECT_TRUE(A);                                 \
  }

#define EXPECT_FALSE_NO_TRACKING(A)                 \
  {                                                 \
    NoMemTracking no_memory_tracking_in_this_scope; \
    EXPECT_FALSE(A);                                \
  }

#define ASSERT_EQ_NO_TRACKING(A, B)                 \
  {                                                 \
    NoMemTracking no_memory_tracking_in_this_scope; \
    ASSERT_EQ(A, B);                                \
  }

#define ASSERT_TRUE_NO_TRACKING(A)                  \
  {                                                 \
    NoMemTracking no_memory_tracking_in_this_scope; \
    ASSERT_TRUE(A);                                 \
  }

// !! converts int -> bool.
bool FlipCoin() {
  return !!(SbSystemGetRandomUInt64() & 0x1);
}

///////////////////////////////////////////////////////////////////////////////
// Stress testing the Allocation Tracker.
class MemoryScopeThread : public nb::TestThread {
 public:
  typedef nb::TestThread Super;

  explicit MemoryScopeThread(MemoryTrackerImpl* memory_tracker)
      : memory_tracker_(memory_tracker) {
    static int s_counter = 0;

    std::stringstream ss;
    ss << "MemoryScopeThread_" << s_counter++;
    unique_name_ = ss.str();
  }
  virtual ~MemoryScopeThread() {}

  // Overridden so that the thread can exit gracefully.
  virtual void Join() {
    finished_ = true;
    Super::Join();
  }
  virtual void Run() {
    while (!finished_) {
      TRACK_MEMORY_SCOPE_DYNAMIC(unique_name_.c_str());
      AllocationGroup* group = memory_tracker_->PeekAllocationGroup();

      const int cmp_result = group->name().compare(unique_name_);
      if (cmp_result != 0) {
        GTEST_FAIL() << "unique name mismatch";
        return;
      }
    }
  }

 private:
  MemoryTrackerImpl* memory_tracker_;
  bool finished_;
  std::string unique_name_;
  int do_delete_counter_;
  int do_malloc_counter_;
};

///////////////////////////////////////////////////////////////////////////////
// Stress testing the Allocation Tracker.
class AllocationStressThread : public nb::TestThread {
 public:
  explicit AllocationStressThread(MemoryTrackerImpl* memory_tracker);
  virtual ~AllocationStressThread();

  // Overridden so that the thread can exit gracefully.
  virtual void Join();
  virtual void Run();

 private:
  typedef std::map<const void*, AllocationRecord> AllocMap;

  void CheckPointers();
  bool RemoveRandomAllocation(std::pair<const void*, AllocationRecord>* output);
  bool DoDelete();
  void DoMalloc();

  MemoryTrackerImpl* memory_tracker_;
  bool finished_;
  std::map<const void*, AllocationRecord> allocated_pts_;
  std::string unique_name_;
  int do_delete_counter_;
  int do_malloc_counter_;
};

class AddAllocationStressThread : public nb::TestThread {
 public:
  typedef std::map<const void*, AllocationRecord> AllocMap;

  AddAllocationStressThread(MemoryTracker* memory_tracker,
                            int num_elements_add,
                            AllocMap* destination_map,
                            starboard::Mutex* destination_map_mutex)
      : memory_tracker_(memory_tracker),
        num_elements_to_add_(num_elements_add),
        destination_map_(destination_map),
        destination_map_mutex_(destination_map_mutex) {}

  virtual void Run() {
    for (int i = 0; i < num_elements_to_add_; ++i) {
      const int alloc_size = std::rand() % 100 + 8;
      void* ptr = SbMemoryAllocate(alloc_size);

      AllocationRecord record;
      if (memory_tracker_->GetMemoryTracking(ptr, &record)) {
        NoMemTracking no_mem_tracking;  // simplifies test.

        starboard::ScopedLock lock(*destination_map_mutex_);
        destination_map_->insert(std::make_pair(ptr, record));
      } else {
        ADD_FAILURE_AT(__FILE__, __LINE__) << "Could not add pointer.";
      }
      if (FlipCoin()) {
        SbThreadYield();  // Give other threads a chance to run.
      }
    }
  }

 private:
  MemoryTracker* memory_tracker_;
  AllocMap* destination_map_;
  starboard::Mutex* destination_map_mutex_;
  int num_elements_to_add_;
};

///////////////////////////////////////////////////////////////////////////////
// Framework which initializes the MemoryTracker once and installs it
// for the first test and the removes the MemoryTracker after the
// the last test finishes.
class MemoryTrackerImplTest : public ::testing::Test {
 public:
  typedef MemoryTrackerImpl::AllocationMapType AllocationMapType;
  MemoryTrackerImplTest() {}

  MemoryTrackerImpl* memory_tracker() { return s_memory_tracker_; }

  bool GetAllocRecord(void* alloc_memory, AllocationRecord* output) {
    return memory_tracker()->GetMemoryTracking(alloc_memory, output);
  }

  AllocationMapType* pointer_map() { return memory_tracker()->pointer_map(); }

  size_t NumberOfAllocations() {
    AllocationMapType* map = pointer_map();
    return map->Size();
  }

  int64_t TotalAllocationBytes() {
    return memory_tracker()->GetTotalAllocationBytes();
  }

  bool MemoryTrackerEnabled() const { return s_memory_tracker_enabled_; }

 protected:
  static void SetUpTestCase() {
    if (!s_memory_tracker_) {
      s_memory_tracker_ = new MemoryTrackerImpl;
    }
    // There are obligatory background threads for nb_test suite. This filter
    // makes sure that they don't intercept this test.
    s_memory_tracker_->SetThreadFilter(SbThreadGetId());
    s_memory_tracker_enabled_ =
        s_memory_tracker_->InstallGlobalTrackingHooks();
  }
  static void TearDownTestCase() {
    s_memory_tracker_->RemoveGlobalTrackingHooks();
    // Give time for threads to sync. We don't use locks on the reporter
    // for performance reasons.
    SbThreadSleep(250 * kSbTimeMillisecond);
  }

  virtual void SetUp() {
    memory_tracker()->Clear();
  }

  virtual void TearDown() {
    memory_tracker()->Clear();
  }
  static bool s_memory_tracker_enabled_;
};
bool MemoryTrackerImplTest::s_memory_tracker_enabled_ = false;

///////////////////////////////////////////////////////////////////////////////
// MemoryTrackerImplTest
TEST_F(MemoryTrackerImplTest, NoMemTracking) {
  // Memory tracker is not enabled for this build.
  if (!MemoryTrackerEnabled()) {
    return;
  }
  ASSERT_EQ_NO_TRACKING(0, NumberOfAllocations());
  scoped_ptr<int> dummy(new int());
  EXPECT_EQ_NO_TRACKING(1, NumberOfAllocations());
  {
    // Now that memory allocation is disabled, no more allocations should
    // be recorded.
    NoMemTracking no_memory_tracking_in_this_scope;
    int* dummy2 = new int();
    EXPECT_EQ_NO_TRACKING(1, NumberOfAllocations());
    delete dummy2;
    EXPECT_EQ_NO_TRACKING(1, NumberOfAllocations());
  }
  scoped_ptr<int> dummy2(new int());
  EXPECT_EQ_NO_TRACKING(2, NumberOfAllocations());
  dummy.reset(NULL);
  EXPECT_EQ_NO_TRACKING(1, NumberOfAllocations());
  dummy2.reset(NULL);
  EXPECT_EQ_NO_TRACKING(0, NumberOfAllocations());
}

TEST_F(MemoryTrackerImplTest, RemovePointerOnNoMemoryTracking) {
  // Memory tracker is not enabled for this build.
  if (!MemoryTrackerEnabled()) {
    return;
  }

  int* int_ptr = new int();
  {
    NoMemTracking no_memory_tracking_in_this_scope;
    delete int_ptr;
  }
  EXPECT_FALSE_NO_TRACKING(pointer_map()->Get(int_ptr, NULL));
}

TEST_F(MemoryTrackerImplTest, NewDeleteOverridenTest) {
  // Memory tracker is not enabled for this build.
  if (!MemoryTrackerEnabled()) {
    return;
  }
  EXPECT_EQ_NO_TRACKING(0, NumberOfAllocations());
  int* int_a = new int(0);
  EXPECT_EQ_NO_TRACKING(1, NumberOfAllocations());
  delete int_a;
  EXPECT_EQ_NO_TRACKING(0, NumberOfAllocations());
}

TEST_F(MemoryTrackerImplTest, TotalAllocationBytes) {
  // Memory tracker is not enabled for this build.
  if (!MemoryTrackerEnabled()) {
    return;
  }
  int32_t* int_a = new int32_t(0);
  EXPECT_EQ_NO_TRACKING(1, NumberOfAllocations());
  EXPECT_EQ_NO_TRACKING(4, TotalAllocationBytes());
  delete int_a;
  EXPECT_EQ_NO_TRACKING(0, NumberOfAllocations());
}

// Tests the expectation that a lot of allocations can be executed and that
// internal data structures won't overflow.
TEST_F(MemoryTrackerImplTest, NoStackOverflow) {
  // Memory tracker is not enabled for this build.
  if (!MemoryTrackerEnabled()) {
    return;
  }
  static const int kNumAllocations = 1000;
  MyVector<int*> allocations;

  // Also it turns out that this test is great for catching
  // background threads pushing allocations through the allocator.
  // This is supposed to be filtered, but if it's not then this test will
  // fail.
  // SbThreadYield() is used to give other threads a chance to enter into our
  // allocator and catch a test failure.
  SbThreadSleep(1);
  size_t previously_existing_allocs = NumberOfAllocations();
  ASSERT_EQ_NO_TRACKING(0, previously_existing_allocs);

  for (int i = 0; i < kNumAllocations; ++i) {
    SbThreadYield();
    EXPECT_EQ_NO_TRACKING(i, NumberOfAllocations());
    int* val = new int(0);
    NoMemTracking no_tracking_in_scope;
    allocations.push_back(val);
  }

  EXPECT_EQ_NO_TRACKING(kNumAllocations, NumberOfAllocations());

  for (int i = 0; i < kNumAllocations; ++i) {
    SbThreadYield();
    EXPECT_EQ_NO_TRACKING(kNumAllocations - i, NumberOfAllocations());
    delete allocations[i];
  }

  EXPECT_EQ_NO_TRACKING(0, NumberOfAllocations());
}

// Tests the expectation that the macros will push/pop the memory scope.
TEST_F(MemoryTrackerImplTest, MacrosPushPop) {
  // Memory tracker is not enabled for this build.
  if (!MemoryTrackerEnabled()) {
    return;
  }
  scoped_ptr<int> dummy;
  {
    TRACK_MEMORY_SCOPE("TestAllocations");
    dummy.reset(new int());
  }

  scoped_ptr<int> dummy2(new int());

  AllocationRecord alloc_rec;
  pointer_map()->Get(dummy.get(), &alloc_rec);

  ASSERT_TRUE_NO_TRACKING(alloc_rec.allocation_group);
  EXPECT_EQ_NO_TRACKING(std::string("TestAllocations"),
                        alloc_rec.allocation_group->name());

  pointer_map()->Get(dummy2.get(), &alloc_rec);

  ASSERT_TRUE_NO_TRACKING(alloc_rec.allocation_group);
  EXPECT_EQ_NO_TRACKING(std::string("Unaccounted"),
                        alloc_rec.allocation_group->name());
}

// Tests the expectation that if the cached flag on the NbMemoryScopeInfo is
// set to false that the caching of the handle is not performed.
TEST_F(MemoryTrackerImplTest, RespectsNonCachedHandle) {
  // Memory tracker is not enabled for this build.
  if (!MemoryTrackerEnabled()) {
    return;
  }
  const bool kCaching = false;
  NbMemoryScopeInfo memory_scope = {
      NULL, "MyName", __FILE__,
      __LINE__, __FUNCTION__, false};  // false to disallow caching.

  // Pushing the memory scope should trigger the caching operation to be
  // attempted. However, because caching was explicitly disabled this handle
  // should retain the value of 0.
  NbPushMemoryScope(&memory_scope);
  EXPECT_TRUE_NO_TRACKING(memory_scope.cached_handle_ == NULL);

  // ... and still assert that the group was created with the expected name.
  AllocationGroup* group = memory_tracker()->GetAllocationGroup("MyName");
  // Equality check.
  EXPECT_EQ_NO_TRACKING(0, group->name().compare("MyName"));
  NbPopMemoryScope();
}

// Tests the expectation that if the cached flag on the NbMemoryScopeInfo is
// set to true that the caching will be applied for the cached_handle of the
// memory scope.
TEST_F(MemoryTrackerImplTest, PushAllocGroupCachedHandle) {
  // Memory tracker is not enabled for this build.
  if (!MemoryTrackerEnabled()) {
    return;
  }
  NbMemoryScopeInfo memory_scope = {
      NULL,      // Cached handle.
      "MyName",  // Memory scope name.
      __FILE__, __LINE__, __FUNCTION__,
      true  // Allows caching.
  };

  NbPushMemoryScope(&memory_scope);
  EXPECT_TRUE_NO_TRACKING(memory_scope.cached_handle_ != NULL);
  AllocationGroup* group = memory_tracker()->GetAllocationGroup("MyName");

  EXPECT_EQ_NO_TRACKING(memory_scope.cached_handle_,
                        static_cast<void*>(group));
  NbPopMemoryScope();
}

// Tests the expectation that the macro TRACK_MEMORY_SCOPE will capture the
// allocation in the MemoryTrackerImpl.
TEST_F(MemoryTrackerImplTest, MacrosGroupAccounting) {
  // Memory tracker is not enabled for this build.
  if (!MemoryTrackerEnabled()) {
    return;
  }
  MemoryTrackerImpl* track_alloc = memory_tracker();  // Debugging.
  track_alloc->Clear();

  memory_tracker()->Clear();
  const AllocationGroup* group_a =
      memory_tracker()->GetAllocationGroup("MemoryTrackerTest-ScopeA");

  const AllocationGroup* group_b =
      memory_tracker()->GetAllocationGroup("MemoryTrackerTest-ScopeB");

  ASSERT_TRUE_NO_TRACKING(group_a);
  ASSERT_TRUE_NO_TRACKING(group_b);

  int32_t num_allocations = -1;
  int64_t allocation_bytes = -1;

  // Expect that both groups have no allocations in them.
  group_a->GetAggregateStats(&num_allocations, &allocation_bytes);
  EXPECT_EQ_NO_TRACKING(0, num_allocations);
  EXPECT_EQ_NO_TRACKING(0, allocation_bytes);

  group_b->GetAggregateStats(&num_allocations, &allocation_bytes);
  EXPECT_EQ_NO_TRACKING(0, num_allocations);
  EXPECT_EQ_NO_TRACKING(0, allocation_bytes);

  scoped_ptr<int> alloc_a, alloc_b, alloc_b2;
  {
    TRACK_MEMORY_SCOPE("MemoryTrackerTest-ScopeA");
    alloc_a.reset(new int());
    {
      TRACK_MEMORY_SCOPE("MemoryTrackerTest-ScopeB");
      alloc_b.reset(new int());
      alloc_b2.reset(new int());

      group_a->GetAggregateStats(&num_allocations, &allocation_bytes);
      EXPECT_EQ_NO_TRACKING(1, num_allocations);
      EXPECT_EQ_NO_TRACKING(4, allocation_bytes);
      alloc_a.reset(NULL);
      group_a->GetAggregateStats(&num_allocations, &allocation_bytes);
      EXPECT_EQ_NO_TRACKING(0, num_allocations);
      EXPECT_EQ_NO_TRACKING(0, allocation_bytes);

      allocation_bytes = num_allocations = -1;
      group_b->GetAggregateStats(&num_allocations, &allocation_bytes);
      EXPECT_EQ_NO_TRACKING(2, num_allocations);
      EXPECT_EQ_NO_TRACKING(8, allocation_bytes);

      alloc_b2.reset(NULL);
      group_b->GetAggregateStats(&num_allocations, &allocation_bytes);
      EXPECT_EQ_NO_TRACKING(1, num_allocations);
      EXPECT_EQ_NO_TRACKING(4, allocation_bytes);

      alloc_b.reset(NULL);
      group_b->GetAggregateStats(&num_allocations, &allocation_bytes);
      EXPECT_EQ_NO_TRACKING(0, num_allocations);
      EXPECT_EQ_NO_TRACKING(0, allocation_bytes);
    }
  }
}

// Tests the expectation that the MemoryTrackerDebugCallback works as expected
// to notify of incoming allocations.
TEST_F(MemoryTrackerImplTest, MemoryTrackerDebugCallback) {
  // Memory tracker is not enabled for this build.
  if (!MemoryTrackerEnabled()) {
    return;
  }

  // Impl of the callback. Copies the allocation information so that we can
  // ensure it produces expected values.
  class MemoryTrackerDebugCallbackTest : public MemoryTrackerDebugCallback {
   public:
    MemoryTrackerDebugCallbackTest() { Reset(); }
    void OnMemoryAllocation(const void* memory_block,
                            const AllocationRecord& record,
                            const CallStack& callstack) override {
      last_memory_block_allocated_ = memory_block;
      last_allocation_record_allocated_ = record;
    }
    void OnMemoryDeallocation(const void* memory_block,
                              const AllocationRecord& record,
                              const CallStack& callstack) override {
      last_memory_block_deallocated_ = memory_block;
      last_allocation_record_deallocated_ = record;
    }
    void Reset() {
      last_memory_block_allocated_ = NULL;
      last_memory_block_deallocated_ = NULL;
      last_allocation_record_allocated_ = AllocationRecord::Empty();
      last_allocation_record_deallocated_ = AllocationRecord::Empty();
    }
    const void* last_memory_block_allocated_;
    const void* last_memory_block_deallocated_;
    AllocationRecord last_allocation_record_allocated_;
    AllocationRecord last_allocation_record_deallocated_;
  };

  // Needs to be static due to concurrent and lockless nature of object.
  static MemoryTrackerDebugCallbackTest s_debug_callback;
  s_debug_callback.Reset();

  memory_tracker()->SetMemoryTrackerDebugCallback(&s_debug_callback);
  void* memory_block = SbMemoryAllocate(8);
  EXPECT_EQ_NO_TRACKING(
      memory_block,
      s_debug_callback.last_memory_block_allocated_);
  EXPECT_EQ_NO_TRACKING(
      8,
      s_debug_callback.last_allocation_record_allocated_.size);
  // ... and no memory should have been deallocated.
  EXPECT_TRUE_NO_TRACKING(s_debug_callback.last_memory_block_deallocated_
                          == NULL);

  // After this call we check that the callback for deallocation was used.
  SbMemoryDeallocate(memory_block);
  EXPECT_EQ_NO_TRACKING(
      memory_block,
      s_debug_callback.last_memory_block_deallocated_);

  EXPECT_EQ_NO_TRACKING(
      s_debug_callback.last_allocation_record_deallocated_.size,
      8);
}

// Tests the expectation that the visitor can access the allocations.
TEST_F(MemoryTrackerImplTest, VisitorAccess) {
  // Memory tracker is not enabled for this build.
  if (!MemoryTrackerEnabled()) {
    return;
  }
  class SimpleVisitor : public AllocationVisitor {
   public:
    SimpleVisitor() : num_memory_allocs_(0) {}
    virtual bool Visit(const void* memory,
                       const AllocationRecord& alloc_record) {
      num_memory_allocs_++;
      return true;  // Keep traversing.
    }

    size_t num_memory_allocs_;
  };

  SimpleVisitor visitor;
  scoped_ptr<int> int_ptr(new int);

  // Should see the int_ptr allocation.
  memory_tracker()->Accept(&visitor);
  EXPECT_EQ_NO_TRACKING(1, visitor.num_memory_allocs_);
  visitor.num_memory_allocs_ = 0;

  int_ptr.reset(NULL);
  // Now no allocations should be available.
  memory_tracker()->Accept(&visitor);
  EXPECT_EQ_NO_TRACKING(0, visitor.num_memory_allocs_);
}

// A stress test that rapidly adds allocations, but saves all deletions
// for the main thread. This test will catch concurrency errors related
// to reporting new allocations.
TEST_F(MemoryTrackerImplTest, MultiThreadedStressAddTest) {
  // Memory tracker is not enabled for this build.
  if (!MemoryTrackerEnabled()) {
    return;
  }
  // Disable allocation filtering.
  memory_tracker()->SetThreadFilter(kSbThreadInvalidId);

  MyVector<nb::TestThread*> threads;

  const int kNumObjectsToAdd = 10000 / NUM_STRESS_TEST_THREADS;
  AddAllocationStressThread::AllocMap map;
  starboard::Mutex map_mutex;

  for (int i = 0; i < NUM_STRESS_TEST_THREADS; ++i) {
    nb::TestThread* thread = new AddAllocationStressThread(
        memory_tracker(), kNumObjectsToAdd, &map, &map_mutex);

    threads.push_back(thread);
  }

  for (int i = 0; i < NUM_STRESS_TEST_THREADS; ++i) {
    threads[i]->Start();
  }

  for (int i = 0; i < NUM_STRESS_TEST_THREADS; ++i) {
    threads[i]->Join();
  }
  for (int i = 0; i < NUM_STRESS_TEST_THREADS; ++i) {
    delete threads[i];
  }

  while (!map.empty()) {
    const void* ptr = map.begin()->first;
    map.erase(map.begin());

    if (!memory_tracker()->GetMemoryTracking(ptr, NULL)) {
      ADD_FAILURE_AT(__FILE__, __LINE__) << "No tracking?!";
    }

    SbMemoryDeallocate(const_cast<void*>(ptr));
    if (memory_tracker()->GetMemoryTracking(ptr, NULL)) {
      ADD_FAILURE_AT(__FILE__, __LINE__) << "Tracking?!";
    }
  }
}

// Tests the expectation that memory scopes are multi-threaded safe.
TEST_F(MemoryTrackerImplTest, MultiThreadedMemoryScope) {
  // Memory tracker is not enabled for this build.
  if (!MemoryTrackerEnabled()) {
    return;
  }
  memory_tracker()->SetThreadFilter(kSbThreadInvalidId);
  TRACK_MEMORY_SCOPE("MultiThreadedStressUseTest");

  MyVector<MemoryScopeThread*> threads;

  for (int i = 0; i < NUM_STRESS_TEST_THREADS; ++i) {
    threads.push_back(new MemoryScopeThread(memory_tracker()));
  }

  for (int i = 0; i < threads.size(); ++i) {
    threads[i]->Start();
  }

  SbThreadSleep(STRESS_TEST_DURATION_SECONDS * 1000 * 1000);

  for (int i = 0; i < threads.size(); ++i) {
    threads[i]->Join();
  }

  for (int i = 0; i < threads.size(); ++i) {
    delete threads[i];
  }

  threads.clear();
}

// Tests the expectation that new/delete can be done by different threads.
TEST_F(MemoryTrackerImplTest, MultiThreadedStressUseTest) {
  // Memory tracker is not enabled for this build.
  if (!MemoryTrackerEnabled()) {
    return;
  }
  // Disable allocation filtering.
  memory_tracker()->SetThreadFilter(kSbThreadInvalidId);
  TRACK_MEMORY_SCOPE("MultiThreadedStressUseTest");

  MyVector<AllocationStressThread*> threads;

  for (int i = 0; i < NUM_STRESS_TEST_THREADS; ++i) {
    threads.push_back(new AllocationStressThread(memory_tracker()));
  }

  for (int i = 0; i < threads.size(); ++i) {
    threads[i]->Start();
  }

  SbThreadSleep(STRESS_TEST_DURATION_SECONDS * 1000 * 1000);

  for (int i = 0; i < threads.size(); ++i) {
    threads[i]->Join();
  }

  for (int i = 0; i < threads.size(); ++i) {
    delete threads[i];
  }

  threads.clear();
}

//////////////////////////// Implementation ///////////////////////////////////
/// Impl of AllocationStressThread
AllocationStressThread::AllocationStressThread(MemoryTrackerImpl* tracker)
    : memory_tracker_(tracker), finished_(false) {
  static int counter = 0;
  std::stringstream ss;
  ss << "AllocStressThread-" << counter++;
  unique_name_ = ss.str();
}

AllocationStressThread::~AllocationStressThread() {
  if (!allocated_pts_.empty()) {
    ADD_FAILURE_AT(__FILE__, __LINE__) << "allocated pointers still exist";
  }
}

void AllocationStressThread::Join() {
  finished_ = true;
  nb::TestThread::Join();
}

void AllocationStressThread::CheckPointers() {
  typedef AllocMap::iterator Iter;

  for (Iter it = allocated_pts_.begin(); it != allocated_pts_.end(); ++it) {
    const void* ptr = it->first;
    const bool found = memory_tracker_->GetMemoryTracking(ptr, NULL);
    if (!found) {
      NoMemTracking no_tracking_in_scope;
      ADD_FAILURE_AT(__FILE__, __LINE__) << "Not found";
    }
  }
}

void AllocationStressThread::Run() {
  while (!finished_) {
    const bool do_delete = FlipCoin();
    if (FlipCoin()) {
      DoDelete();
    } else {
      DoMalloc();
    }
    CheckPointers();

    // Randomly give other threads the opportunity run.
    if (FlipCoin()) {
      SbThreadYield();
    }
  }

  // Clear out all memory.
  while (DoDelete()) {
    ;
  }
}

bool AllocationStressThread::RemoveRandomAllocation(
    std::pair<const void*, AllocationRecord>* output) {
  if (allocated_pts_.empty()) {
    return false;
  }

  // Select a random pointer to delete.
  int idx = std::rand() % allocated_pts_.size();
  AllocMap::iterator iter = allocated_pts_.begin();
  while (idx > 0) {
    idx--;
    iter++;
  }
  output->first = iter->first;
  output->second = iter->second;
  allocated_pts_.erase(iter);
  return true;
}

bool AllocationStressThread::DoDelete() {
  NoMemTracking no_memory_tracking_in_this_scope;
  ++do_delete_counter_;

  std::pair<const void*, AllocationRecord> alloc;
  if (!RemoveRandomAllocation(&alloc)) {
    return false;
  }

  const void* ptr = alloc.first;
  const AllocationRecord expected_alloc_record = alloc.second;

  TRACK_MEMORY_SCOPE_DYNAMIC(unique_name_.c_str());
  AllocationGroup* current_group = memory_tracker_->PeekAllocationGroup();

  // Expect that the name of the current allocation group name is the same as
  // what we expect.
  if (current_group->name() != unique_name_) {
    NoMemTracking no_memory_tracking_in_this_scope;
    ADD_FAILURE_AT(__FILE__, __LINE__) << " " << current_group->name()
                                       << " != " << unique_name_;
  }

  MemoryTrackerImpl::AllocationMapType* internal_alloc_map =
      memory_tracker_->pointer_map();

  AllocationRecord existing_alloc_record;

  const bool found_existing_record =
      memory_tracker_->GetMemoryTracking(ptr, &existing_alloc_record);

  if (!found_existing_record) {
    ADD_FAILURE_AT(__FILE__, __LINE__)
        << "expected to find existing record, but did not";
  } else if (current_group != existing_alloc_record.allocation_group) {
    ADD_FAILURE_AT(__FILE__, __LINE__)
        << "group allocation mismatch: " << current_group->name()
        << " != " << existing_alloc_record.allocation_group->name() << "\n";
  }
  SbMemoryDeallocate(const_cast<void*>(ptr));
  return true;
}

void AllocationStressThread::DoMalloc() {
  ++do_malloc_counter_;
  if (allocated_pts_.size() > 10000) {
    return;
  }

  TRACK_MEMORY_SCOPE_DYNAMIC(unique_name_.c_str());
  AllocationGroup* current_group = memory_tracker_->PeekAllocationGroup();

  // Sanity check, make sure that the current_group name is the same as
  // our unique name.
  if (current_group->name() != unique_name_) {
    NoMemTracking no_tracking_in_scope;
    ADD_FAILURE_AT(__FILE__, __LINE__) << " " << current_group->name()
                                       << " != " << unique_name_;
  }

  if (!memory_tracker_->IsMemoryTrackingEnabled()) {
    NoMemTracking no_tracking_in_scope;
    ADD_FAILURE_AT(__FILE__, __LINE__)
        << " memory tracking state was disabled.";
  }

  const int alloc_size = std::rand() % 100 + 8;

  void* memory = SbMemoryAllocate(alloc_size);

  AllocationRecord record;
  bool found = memory_tracker_->GetMemoryTracking(memory, &record);
  if (!found) {
    NoMemTracking no_tracking_in_scope;
    ADD_FAILURE_AT(__FILE__, __LINE__)
        << "Violated expectation, malloc counter: " << do_malloc_counter_;
  }
  AllocMap::iterator found_it = allocated_pts_.find(memory);

  if (found_it != allocated_pts_.end()) {
    NoMemTracking no_tracking_in_scope;
    ADD_FAILURE_AT(__FILE__, __LINE__)
        << "This pointer should not be in the map.";
  }

  NoMemTracking no_tracking_in_scope;
  allocated_pts_[memory] = AllocationRecord(alloc_size, current_group);
}

}  // namespace
}  // namespace analytics
}  // namespace nb
