Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(184)

Side by Side Diff: base/debug/activity_tracker_unittest.cc

Issue 2680123003: Multi-Process Tracking Support (Closed)
Patch Set: wire actual process launch/exit to global tracker Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/debug/activity_tracker.h" 5 #include "base/debug/activity_tracker.h"
6 6
7 #include <memory> 7 #include <memory>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/files/file.h" 10 #include "base/files/file.h"
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
84 return GlobalActivityTracker::Get()->user_data_allocator_.cache_used(); 84 return GlobalActivityTracker::Get()->user_data_allocator_.cache_used();
85 } 85 }
86 86
87 static void DoNothing() {} 87 static void DoNothing() {}
88 }; 88 };
89 89
90 TEST_F(ActivityTrackerTest, UserDataTest) { 90 TEST_F(ActivityTrackerTest, UserDataTest) {
91 char buffer[256]; 91 char buffer[256];
92 memset(buffer, 0, sizeof(buffer)); 92 memset(buffer, 0, sizeof(buffer));
93 ActivityUserData data(buffer, sizeof(buffer)); 93 ActivityUserData data(buffer, sizeof(buffer));
94 ASSERT_EQ(sizeof(buffer) - 8, data.available_); 94 ASSERT_EQ(sizeof(buffer) - 24, data.available_);
95 95
96 data.SetInt("foo", 1); 96 data.SetInt("foo", 1);
97 ASSERT_EQ(sizeof(buffer) - 8 - 24, data.available_); 97 ASSERT_EQ(sizeof(buffer) - 24 - 24, data.available_);
98 98
99 data.SetUint("b", 1U); // Small names fit beside header in a word. 99 data.SetUint("b", 1U); // Small names fit beside header in a word.
100 ASSERT_EQ(sizeof(buffer) - 8 - 24 - 16, data.available_); 100 ASSERT_EQ(sizeof(buffer) - 24 - 24 - 16, data.available_);
101 101
102 data.Set("c", buffer, 10); 102 data.Set("c", buffer, 10);
103 ASSERT_EQ(sizeof(buffer) - 8 - 24 - 16 - 24, data.available_); 103 ASSERT_EQ(sizeof(buffer) - 24 - 24 - 16 - 24, data.available_);
104 104
105 data.SetString("dear john", "it's been fun"); 105 data.SetString("dear john", "it's been fun");
106 ASSERT_EQ(sizeof(buffer) - 8 - 24 - 16 - 24 - 32, data.available_); 106 ASSERT_EQ(sizeof(buffer) - 24 - 24 - 16 - 24 - 32, data.available_);
107 107
108 data.Set("c", buffer, 20); 108 data.Set("c", buffer, 20);
109 ASSERT_EQ(sizeof(buffer) - 8 - 24 - 16 - 24 - 32, data.available_); 109 ASSERT_EQ(sizeof(buffer) - 24 - 24 - 16 - 24 - 32, data.available_);
110 110
111 data.SetString("dear john", "but we're done together"); 111 data.SetString("dear john", "but we're done together");
112 ASSERT_EQ(sizeof(buffer) - 8 - 24 - 16 - 24 - 32, data.available_); 112 ASSERT_EQ(sizeof(buffer) - 24 - 24 - 16 - 24 - 32, data.available_);
113 113
114 data.SetString("dear john", "bye"); 114 data.SetString("dear john", "bye");
115 ASSERT_EQ(sizeof(buffer) - 8 - 24 - 16 - 24 - 32, data.available_); 115 ASSERT_EQ(sizeof(buffer) - 24 - 24 - 16 - 24 - 32, data.available_);
116 116
117 data.SetChar("d", 'x'); 117 data.SetChar("d", 'x');
118 ASSERT_EQ(sizeof(buffer) - 8 - 24 - 16 - 24 - 32 - 8, data.available_); 118 ASSERT_EQ(sizeof(buffer) - 24 - 24 - 16 - 24 - 32 - 8, data.available_);
119 119
120 data.SetBool("ee", true); 120 data.SetBool("ee", true);
121 ASSERT_EQ(sizeof(buffer) - 8 - 24 - 16 - 24 - 32 - 8 - 16, data.available_); 121 ASSERT_EQ(sizeof(buffer) - 24 - 24 - 16 - 24 - 32 - 8 - 16, data.available_);
122 } 122 }
123 123
124 TEST_F(ActivityTrackerTest, PushPopTest) { 124 TEST_F(ActivityTrackerTest, PushPopTest) {
125 std::unique_ptr<ThreadActivityTracker> tracker = CreateActivityTracker(); 125 std::unique_ptr<ThreadActivityTracker> tracker = CreateActivityTracker();
126 ThreadActivityTracker::Snapshot snapshot; 126 ThreadActivityTracker::Snapshot snapshot;
127 127
128 ASSERT_TRUE(tracker->CreateSnapshot(&snapshot)); 128 ASSERT_TRUE(tracker->CreateSnapshot(&snapshot));
129 ASSERT_EQ(0U, snapshot.activity_stack_depth); 129 ASSERT_EQ(0U, snapshot.activity_stack_depth);
130 ASSERT_EQ(0U, snapshot.activity_stack.size()); 130 ASSERT_EQ(0U, snapshot.activity_stack.size());
131 131
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
239 GlobalActivityTracker::CreateWithFile(temp_file, temp_size, 0, "bar", 3); 239 GlobalActivityTracker::CreateWithFile(temp_file, temp_size, 0, "bar", 3);
240 global = GlobalActivityTracker::Get(); 240 global = GlobalActivityTracker::Get();
241 EXPECT_EQ(std::string("bar"), global->allocator()->Name()); 241 EXPECT_EQ(std::string("bar"), global->allocator()->Name());
242 global->ReleaseTrackerForCurrentThreadForTesting(); 242 global->ReleaseTrackerForCurrentThreadForTesting();
243 delete global; 243 delete global;
244 } 244 }
245 245
246 246
247 // GlobalActivityTracker tests below. 247 // GlobalActivityTracker tests below.
248 248
249 TEST_F(ActivityTrackerTest, BasicTest) {
250 GlobalActivityTracker::CreateWithLocalMemory(kMemorySize, 0, "", 3);
251 GlobalActivityTracker* global = GlobalActivityTracker::Get();
252
253 // Ensure the data repositories have backing store, indicated by non-zero ID.
254 EXPECT_NE(0U, global->process_data().id());
255 EXPECT_NE(0U, global->global_data().id());
256 EXPECT_NE(global->process_data().id(), global->global_data().id());
257 }
258
249 class SimpleActivityThread : public SimpleThread { 259 class SimpleActivityThread : public SimpleThread {
250 public: 260 public:
251 SimpleActivityThread(const std::string& name, 261 SimpleActivityThread(const std::string& name,
252 const void* origin, 262 const void* origin,
253 Activity::Type activity, 263 Activity::Type activity,
254 const ActivityData& data) 264 const ActivityData& data)
255 : SimpleThread(name, Options()), 265 : SimpleThread(name, Options()),
256 origin_(origin), 266 origin_(origin),
257 activity_(activity), 267 activity_(activity),
258 data_(data), 268 data_(data),
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
325 t2.WaitReady(); 335 t2.WaitReady();
326 EXPECT_EQ(starting_active + 1, GetGlobalActiveTrackerCount()); 336 EXPECT_EQ(starting_active + 1, GetGlobalActiveTrackerCount());
327 EXPECT_EQ(starting_inactive, GetGlobalInactiveTrackerCount()); 337 EXPECT_EQ(starting_inactive, GetGlobalInactiveTrackerCount());
328 338
329 t2.Exit(); 339 t2.Exit();
330 t2.Join(); 340 t2.Join();
331 EXPECT_EQ(starting_active, GetGlobalActiveTrackerCount()); 341 EXPECT_EQ(starting_active, GetGlobalActiveTrackerCount());
332 EXPECT_EQ(starting_inactive + 1, GetGlobalInactiveTrackerCount()); 342 EXPECT_EQ(starting_inactive + 1, GetGlobalInactiveTrackerCount());
333 } 343 }
334 344
345 TEST_F(ActivityTrackerTest, ProcessDeathTest) {
346 // This doesn't actually create and destroy a process. Instead, it uses for-
347 // testing interfaces to simulate data created by other processes.
348 const ProcessId other_process_id = GetCurrentProcId() + 1;
349
350 GlobalActivityTracker::CreateWithLocalMemory(kMemorySize, 0, "", 3);
351 GlobalActivityTracker* global = GlobalActivityTracker::Get();
352 ThreadActivityTracker* thread = global->GetOrCreateTrackerForCurrentThread();
353
354 // Pretend than another process has started.
355 global->RecordProcessLaunch(other_process_id);
356
357 // Do some activities.
358 PendingTask task(FROM_HERE, base::Bind(&DoNothing));
359 ScopedTaskRunActivity activity(task);
360 ActivityUserData& user_data = activity.user_data();
361 ASSERT_NE(0U, user_data.id());
362
363 // Get the memory-allocator references to that data.
364 PersistentMemoryAllocator::Reference proc_data_ref =
365 global->allocator()->GetAsReference(
366 global->process_data().GetBaseAddress(),
367 GlobalActivityTracker::kTypeIdProcessDataRecord);
368 ASSERT_TRUE(proc_data_ref);
369 PersistentMemoryAllocator::Reference tracker_ref =
370 global->allocator()->GetAsReference(
371 thread->GetBaseAddress(),
372 GlobalActivityTracker::kTypeIdActivityTracker);
373 ASSERT_TRUE(tracker_ref);
374 PersistentMemoryAllocator::Reference user_data_ref =
375 global->allocator()->GetAsReference(
376 user_data.GetBaseAddress(),
377 GlobalActivityTracker::kTypeIdUserDataRecord);
378 ASSERT_TRUE(user_data_ref);
379
380 // Make a copy of the thread-tracker state so it can be restored later.
381 const size_t tracker_size = global->allocator()->GetAllocSize(tracker_ref);
382 std::unique_ptr<char[]> tracker_copy(new char[tracker_size]);
383 memcpy(tracker_copy.get(), thread->GetBaseAddress(), tracker_size);
384
385 // Change the objects to appear to be owned by another process.
386 ProcessId owning_id;
387 int64_t stamp;
388 ASSERT_TRUE(ActivityUserData::OwningProcessId(
389 global->process_data().GetBaseAddress(), &owning_id, &stamp));
390 EXPECT_NE(other_process_id, owning_id);
391 ASSERT_TRUE(ThreadActivityTracker::OwningProcessId(thread->GetBaseAddress(),
392 &owning_id, &stamp));
393 EXPECT_NE(other_process_id, owning_id);
394 ASSERT_TRUE(ActivityUserData::OwningProcessId(user_data.GetBaseAddress(),
395 &owning_id, &stamp));
396 EXPECT_NE(other_process_id, owning_id);
397 global->process_data().SetOwningProcessIdForTesting(other_process_id, stamp);
398 thread->SetOwningProcessIdForTesting(other_process_id, stamp);
399 user_data.SetOwningProcessIdForTesting(other_process_id, stamp);
400 ASSERT_TRUE(ActivityUserData::OwningProcessId(
401 global->process_data().GetBaseAddress(), &owning_id, &stamp));
402 EXPECT_EQ(other_process_id, owning_id);
403 ASSERT_TRUE(ThreadActivityTracker::OwningProcessId(thread->GetBaseAddress(),
404 &owning_id, &stamp));
405 EXPECT_EQ(other_process_id, owning_id);
406 ASSERT_TRUE(ActivityUserData::OwningProcessId(user_data.GetBaseAddress(),
407 &owning_id, &stamp));
408 EXPECT_EQ(other_process_id, owning_id);
409
410 // Check that process exit will free the allocations.
411 ASSERT_EQ(GlobalActivityTracker::kTypeIdProcessDataRecord,
412 global->allocator()->GetType(proc_data_ref));
413 ASSERT_EQ(GlobalActivityTracker::kTypeIdActivityTracker,
414 global->allocator()->GetType(tracker_ref));
415 ASSERT_EQ(GlobalActivityTracker::kTypeIdUserDataRecord,
416 global->allocator()->GetType(user_data_ref));
417 global->RecordProcessExit(other_process_id, 0);
418 EXPECT_EQ(GlobalActivityTracker::kTypeIdProcessDataRecordFree,
419 global->allocator()->GetType(proc_data_ref));
420 EXPECT_EQ(GlobalActivityTracker::kTypeIdActivityTrackerFree,
421 global->allocator()->GetType(tracker_ref));
422 EXPECT_EQ(GlobalActivityTracker::kTypeIdUserDataRecordFree,
423 global->allocator()->GetType(user_data_ref));
424
425 // Restore memory contents and types so things don't crash when doing real
426 // process clean-up.
427 memcpy(const_cast<void*>(thread->GetBaseAddress()), tracker_copy.get(),
428 tracker_size);
429 global->allocator()->ChangeType(
430 proc_data_ref, GlobalActivityTracker::kTypeIdProcessDataRecord,
431 GlobalActivityTracker::kTypeIdUserDataRecordFree, false);
432 global->allocator()->ChangeType(
433 tracker_ref, GlobalActivityTracker::kTypeIdActivityTracker,
434 GlobalActivityTracker::kTypeIdActivityTrackerFree, false);
435 global->allocator()->ChangeType(
436 user_data_ref, GlobalActivityTracker::kTypeIdUserDataRecord,
437 GlobalActivityTracker::kTypeIdUserDataRecordFree, false);
438 }
439
335 } // namespace debug 440 } // namespace debug
336 } // namespace base 441 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698