| Index: base/debug/activity_tracker_unittest.cc
|
| diff --git a/base/debug/activity_tracker_unittest.cc b/base/debug/activity_tracker_unittest.cc
|
| index c46b81686b9147abc18266e0ac7dbc3166075688..f368127e3ddbb6733caca8373e213785138ca203 100644
|
| --- a/base/debug/activity_tracker_unittest.cc
|
| +++ b/base/debug/activity_tracker_unittest.cc
|
| @@ -91,34 +91,34 @@ TEST_F(ActivityTrackerTest, UserDataTest) {
|
| char buffer[256];
|
| memset(buffer, 0, sizeof(buffer));
|
| ActivityUserData data(buffer, sizeof(buffer));
|
| - ASSERT_EQ(sizeof(buffer) - 8, data.available_);
|
| + ASSERT_EQ(sizeof(buffer) - 24, data.available_);
|
|
|
| data.SetInt("foo", 1);
|
| - ASSERT_EQ(sizeof(buffer) - 8 - 24, data.available_);
|
| + ASSERT_EQ(sizeof(buffer) - 24 - 24, data.available_);
|
|
|
| data.SetUint("b", 1U); // Small names fit beside header in a word.
|
| - ASSERT_EQ(sizeof(buffer) - 8 - 24 - 16, data.available_);
|
| + ASSERT_EQ(sizeof(buffer) - 24 - 24 - 16, data.available_);
|
|
|
| data.Set("c", buffer, 10);
|
| - ASSERT_EQ(sizeof(buffer) - 8 - 24 - 16 - 24, data.available_);
|
| + ASSERT_EQ(sizeof(buffer) - 24 - 24 - 16 - 24, data.available_);
|
|
|
| data.SetString("dear john", "it's been fun");
|
| - ASSERT_EQ(sizeof(buffer) - 8 - 24 - 16 - 24 - 32, data.available_);
|
| + ASSERT_EQ(sizeof(buffer) - 24 - 24 - 16 - 24 - 32, data.available_);
|
|
|
| data.Set("c", buffer, 20);
|
| - ASSERT_EQ(sizeof(buffer) - 8 - 24 - 16 - 24 - 32, data.available_);
|
| + ASSERT_EQ(sizeof(buffer) - 24 - 24 - 16 - 24 - 32, data.available_);
|
|
|
| data.SetString("dear john", "but we're done together");
|
| - ASSERT_EQ(sizeof(buffer) - 8 - 24 - 16 - 24 - 32, data.available_);
|
| + ASSERT_EQ(sizeof(buffer) - 24 - 24 - 16 - 24 - 32, data.available_);
|
|
|
| data.SetString("dear john", "bye");
|
| - ASSERT_EQ(sizeof(buffer) - 8 - 24 - 16 - 24 - 32, data.available_);
|
| + ASSERT_EQ(sizeof(buffer) - 24 - 24 - 16 - 24 - 32, data.available_);
|
|
|
| data.SetChar("d", 'x');
|
| - ASSERT_EQ(sizeof(buffer) - 8 - 24 - 16 - 24 - 32 - 8, data.available_);
|
| + ASSERT_EQ(sizeof(buffer) - 24 - 24 - 16 - 24 - 32 - 8, data.available_);
|
|
|
| data.SetBool("ee", true);
|
| - ASSERT_EQ(sizeof(buffer) - 8 - 24 - 16 - 24 - 32 - 8 - 16, data.available_);
|
| + ASSERT_EQ(sizeof(buffer) - 24 - 24 - 16 - 24 - 32 - 8 - 16, data.available_);
|
| }
|
|
|
| TEST_F(ActivityTrackerTest, PushPopTest) {
|
| @@ -246,6 +246,16 @@ TEST_F(ActivityTrackerTest, CreateWithFileTest) {
|
|
|
| // GlobalActivityTracker tests below.
|
|
|
| +TEST_F(ActivityTrackerTest, BasicTest) {
|
| + GlobalActivityTracker::CreateWithLocalMemory(kMemorySize, 0, "", 3);
|
| + GlobalActivityTracker* global = GlobalActivityTracker::Get();
|
| +
|
| + // Ensure the data repositories have backing store, indicated by non-zero ID.
|
| + EXPECT_NE(0U, global->process_data().id());
|
| + EXPECT_NE(0U, global->global_data().id());
|
| + EXPECT_NE(global->process_data().id(), global->global_data().id());
|
| +}
|
| +
|
| class SimpleActivityThread : public SimpleThread {
|
| public:
|
| SimpleActivityThread(const std::string& name,
|
| @@ -332,5 +342,100 @@ TEST_F(ActivityTrackerTest, ThreadDeathTest) {
|
| EXPECT_EQ(starting_inactive + 1, GetGlobalInactiveTrackerCount());
|
| }
|
|
|
| +TEST_F(ActivityTrackerTest, ProcessDeathTest) {
|
| + // This doesn't actually create and destroy a process. Instead, it uses for-
|
| + // testing interfaces to simulate data created by other processes.
|
| + const ProcessId other_process_id = GetCurrentProcId() + 1;
|
| +
|
| + GlobalActivityTracker::CreateWithLocalMemory(kMemorySize, 0, "", 3);
|
| + GlobalActivityTracker* global = GlobalActivityTracker::Get();
|
| + ThreadActivityTracker* thread = global->GetOrCreateTrackerForCurrentThread();
|
| +
|
| + // Pretend than another process has started.
|
| + global->RecordProcessLaunch(other_process_id);
|
| +
|
| + // Do some activities.
|
| + PendingTask task(FROM_HERE, base::Bind(&DoNothing));
|
| + ScopedTaskRunActivity activity(task);
|
| + ActivityUserData& user_data = activity.user_data();
|
| + ASSERT_NE(0U, user_data.id());
|
| +
|
| + // Get the memory-allocator references to that data.
|
| + PersistentMemoryAllocator::Reference proc_data_ref =
|
| + global->allocator()->GetAsReference(
|
| + global->process_data().GetBaseAddress(),
|
| + GlobalActivityTracker::kTypeIdProcessDataRecord);
|
| + ASSERT_TRUE(proc_data_ref);
|
| + PersistentMemoryAllocator::Reference tracker_ref =
|
| + global->allocator()->GetAsReference(
|
| + thread->GetBaseAddress(),
|
| + GlobalActivityTracker::kTypeIdActivityTracker);
|
| + ASSERT_TRUE(tracker_ref);
|
| + PersistentMemoryAllocator::Reference user_data_ref =
|
| + global->allocator()->GetAsReference(
|
| + user_data.GetBaseAddress(),
|
| + GlobalActivityTracker::kTypeIdUserDataRecord);
|
| + ASSERT_TRUE(user_data_ref);
|
| +
|
| + // Make a copy of the thread-tracker state so it can be restored later.
|
| + const size_t tracker_size = global->allocator()->GetAllocSize(tracker_ref);
|
| + std::unique_ptr<char[]> tracker_copy(new char[tracker_size]);
|
| + memcpy(tracker_copy.get(), thread->GetBaseAddress(), tracker_size);
|
| +
|
| + // Change the objects to appear to be owned by another process.
|
| + ProcessId owning_id;
|
| + int64_t stamp;
|
| + ASSERT_TRUE(ActivityUserData::OwningProcessId(
|
| + global->process_data().GetBaseAddress(), &owning_id, &stamp));
|
| + EXPECT_NE(other_process_id, owning_id);
|
| + ASSERT_TRUE(ThreadActivityTracker::OwningProcessId(thread->GetBaseAddress(),
|
| + &owning_id, &stamp));
|
| + EXPECT_NE(other_process_id, owning_id);
|
| + ASSERT_TRUE(ActivityUserData::OwningProcessId(user_data.GetBaseAddress(),
|
| + &owning_id, &stamp));
|
| + EXPECT_NE(other_process_id, owning_id);
|
| + global->process_data().SetOwningProcessIdForTesting(other_process_id, stamp);
|
| + thread->SetOwningProcessIdForTesting(other_process_id, stamp);
|
| + user_data.SetOwningProcessIdForTesting(other_process_id, stamp);
|
| + ASSERT_TRUE(ActivityUserData::OwningProcessId(
|
| + global->process_data().GetBaseAddress(), &owning_id, &stamp));
|
| + EXPECT_EQ(other_process_id, owning_id);
|
| + ASSERT_TRUE(ThreadActivityTracker::OwningProcessId(thread->GetBaseAddress(),
|
| + &owning_id, &stamp));
|
| + EXPECT_EQ(other_process_id, owning_id);
|
| + ASSERT_TRUE(ActivityUserData::OwningProcessId(user_data.GetBaseAddress(),
|
| + &owning_id, &stamp));
|
| + EXPECT_EQ(other_process_id, owning_id);
|
| +
|
| + // Check that process exit will free the allocations.
|
| + ASSERT_EQ(GlobalActivityTracker::kTypeIdProcessDataRecord,
|
| + global->allocator()->GetType(proc_data_ref));
|
| + ASSERT_EQ(GlobalActivityTracker::kTypeIdActivityTracker,
|
| + global->allocator()->GetType(tracker_ref));
|
| + ASSERT_EQ(GlobalActivityTracker::kTypeIdUserDataRecord,
|
| + global->allocator()->GetType(user_data_ref));
|
| + global->RecordProcessExit(other_process_id, 0);
|
| + EXPECT_EQ(GlobalActivityTracker::kTypeIdProcessDataRecordFree,
|
| + global->allocator()->GetType(proc_data_ref));
|
| + EXPECT_EQ(GlobalActivityTracker::kTypeIdActivityTrackerFree,
|
| + global->allocator()->GetType(tracker_ref));
|
| + EXPECT_EQ(GlobalActivityTracker::kTypeIdUserDataRecordFree,
|
| + global->allocator()->GetType(user_data_ref));
|
| +
|
| + // Restore memory contents and types so things don't crash when doing real
|
| + // process clean-up.
|
| + memcpy(const_cast<void*>(thread->GetBaseAddress()), tracker_copy.get(),
|
| + tracker_size);
|
| + global->allocator()->ChangeType(
|
| + proc_data_ref, GlobalActivityTracker::kTypeIdProcessDataRecord,
|
| + GlobalActivityTracker::kTypeIdUserDataRecordFree, false);
|
| + global->allocator()->ChangeType(
|
| + tracker_ref, GlobalActivityTracker::kTypeIdActivityTracker,
|
| + GlobalActivityTracker::kTypeIdActivityTrackerFree, false);
|
| + global->allocator()->ChangeType(
|
| + user_data_ref, GlobalActivityTracker::kTypeIdUserDataRecord,
|
| + GlobalActivityTracker::kTypeIdUserDataRecordFree, false);
|
| +}
|
| +
|
| } // namespace debug
|
| } // namespace base
|
|
|