/*
 * 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) {
  // 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
