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

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

Issue 2680123003: Multi-Process Tracking Support (Closed)
Patch Set: addressed review comments by manzagop Created 3 years, 9 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 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
77 if (!global_tracker) 77 if (!global_tracker)
78 return 0; 78 return 0;
79 base::AutoLock autolock(global_tracker->thread_tracker_allocator_lock_); 79 base::AutoLock autolock(global_tracker->thread_tracker_allocator_lock_);
80 return global_tracker->thread_tracker_allocator_.cache_used(); 80 return global_tracker->thread_tracker_allocator_.cache_used();
81 } 81 }
82 82
83 size_t GetGlobalUserDataMemoryCacheUsed() { 83 size_t GetGlobalUserDataMemoryCacheUsed() {
84 return GlobalActivityTracker::Get()->user_data_allocator_.cache_used(); 84 return GlobalActivityTracker::Get()->user_data_allocator_.cache_used();
85 } 85 }
86 86
87 void HandleProcessExit(int64_t id,
88 int64_t stamp,
89 int code,
90 GlobalActivityTracker::ProcessPhase phase,
91 std::string&& command,
92 ActivityUserData::Snapshot&& data) {
93 exit_id = id;
94 exit_stamp = stamp;
95 exit_code = code;
96 exit_phase = phase;
97 exit_command = std::move(command);
98 exit_data = std::move(data);
99 }
100
87 static void DoNothing() {} 101 static void DoNothing() {}
102
103 int64_t exit_id = 0;
104 int64_t exit_stamp;
105 int exit_code;
106 GlobalActivityTracker::ProcessPhase exit_phase;
107 std::string exit_command;
108 ActivityUserData::Snapshot exit_data;
88 }; 109 };
89 110
90 TEST_F(ActivityTrackerTest, UserDataTest) { 111 TEST_F(ActivityTrackerTest, UserDataTest) {
91 char buffer[256]; 112 char buffer[256];
92 memset(buffer, 0, sizeof(buffer)); 113 memset(buffer, 0, sizeof(buffer));
93 ActivityUserData data(buffer, sizeof(buffer)); 114 ActivityUserData data(buffer, sizeof(buffer));
94 ASSERT_EQ(sizeof(buffer) - 8, data.available_); 115 size_t space = sizeof(buffer) - sizeof(ActivityUserData::MemoryHeader);
116 ASSERT_EQ(space, data.available_);
95 117
96 data.SetInt("foo", 1); 118 data.SetInt("foo", 1);
97 ASSERT_EQ(sizeof(buffer) - 8 - 24, data.available_); 119 space -= 24;
120 ASSERT_EQ(space, data.available_);
98 121
99 data.SetUint("b", 1U); // Small names fit beside header in a word. 122 data.SetUint("b", 1U); // Small names fit beside header in a word.
100 ASSERT_EQ(sizeof(buffer) - 8 - 24 - 16, data.available_); 123 space -= 16;
124 ASSERT_EQ(space, data.available_);
101 125
102 data.Set("c", buffer, 10); 126 data.Set("c", buffer, 10);
103 ASSERT_EQ(sizeof(buffer) - 8 - 24 - 16 - 24, data.available_); 127 space -= 24;
128 ASSERT_EQ(space, data.available_);
104 129
105 data.SetString("dear john", "it's been fun"); 130 data.SetString("dear john", "it's been fun");
106 ASSERT_EQ(sizeof(buffer) - 8 - 24 - 16 - 24 - 32, data.available_); 131 space -= 32;
132 ASSERT_EQ(space, data.available_);
107 133
108 data.Set("c", buffer, 20); 134 data.Set("c", buffer, 20);
109 ASSERT_EQ(sizeof(buffer) - 8 - 24 - 16 - 24 - 32, data.available_); 135 ASSERT_EQ(space, data.available_);
110 136
111 data.SetString("dear john", "but we're done together"); 137 data.SetString("dear john", "but we're done together");
112 ASSERT_EQ(sizeof(buffer) - 8 - 24 - 16 - 24 - 32, data.available_); 138 ASSERT_EQ(space, data.available_);
113 139
114 data.SetString("dear john", "bye"); 140 data.SetString("dear john", "bye");
115 ASSERT_EQ(sizeof(buffer) - 8 - 24 - 16 - 24 - 32, data.available_); 141 ASSERT_EQ(space, data.available_);
116 142
117 data.SetChar("d", 'x'); 143 data.SetChar("d", 'x');
118 ASSERT_EQ(sizeof(buffer) - 8 - 24 - 16 - 24 - 32 - 8, data.available_); 144 space -= 8;
145 ASSERT_EQ(space, data.available_);
119 146
120 data.SetBool("ee", true); 147 data.SetBool("ee", true);
121 ASSERT_EQ(sizeof(buffer) - 8 - 24 - 16 - 24 - 32 - 8 - 16, data.available_); 148 space -= 16;
149 ASSERT_EQ(space, data.available_);
122 } 150 }
123 151
124 TEST_F(ActivityTrackerTest, PushPopTest) { 152 TEST_F(ActivityTrackerTest, PushPopTest) {
125 std::unique_ptr<ThreadActivityTracker> tracker = CreateActivityTracker(); 153 std::unique_ptr<ThreadActivityTracker> tracker = CreateActivityTracker();
126 ThreadActivityTracker::Snapshot snapshot; 154 ThreadActivityTracker::Snapshot snapshot;
127 155
128 ASSERT_TRUE(tracker->CreateSnapshot(&snapshot)); 156 ASSERT_TRUE(tracker->CreateSnapshot(&snapshot));
129 ASSERT_EQ(0U, snapshot.activity_stack_depth); 157 ASSERT_EQ(0U, snapshot.activity_stack_depth);
130 ASSERT_EQ(0U, snapshot.activity_stack.size()); 158 ASSERT_EQ(0U, snapshot.activity_stack.size());
131 159
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
239 GlobalActivityTracker::CreateWithFile(temp_file, temp_size, 0, "bar", 3); 267 GlobalActivityTracker::CreateWithFile(temp_file, temp_size, 0, "bar", 3);
240 global = GlobalActivityTracker::Get(); 268 global = GlobalActivityTracker::Get();
241 EXPECT_EQ(std::string("bar"), global->allocator()->Name()); 269 EXPECT_EQ(std::string("bar"), global->allocator()->Name());
242 global->ReleaseTrackerForCurrentThreadForTesting(); 270 global->ReleaseTrackerForCurrentThreadForTesting();
243 delete global; 271 delete global;
244 } 272 }
245 273
246 274
247 // GlobalActivityTracker tests below. 275 // GlobalActivityTracker tests below.
248 276
277 TEST_F(ActivityTrackerTest, BasicTest) {
278 GlobalActivityTracker::CreateWithLocalMemory(kMemorySize, 0, "", 3);
279 GlobalActivityTracker* global = GlobalActivityTracker::Get();
280
281 // Ensure the data repositories have backing store, indicated by non-zero ID.
282 EXPECT_NE(0U, global->process_data().id());
283 EXPECT_NE(0U, global->global_data().id());
284 EXPECT_NE(global->process_data().id(), global->global_data().id());
285 }
286
249 class SimpleActivityThread : public SimpleThread { 287 class SimpleActivityThread : public SimpleThread {
250 public: 288 public:
251 SimpleActivityThread(const std::string& name, 289 SimpleActivityThread(const std::string& name,
252 const void* origin, 290 const void* origin,
253 Activity::Type activity, 291 Activity::Type activity,
254 const ActivityData& data) 292 const ActivityData& data)
255 : SimpleThread(name, Options()), 293 : SimpleThread(name, Options()),
256 origin_(origin), 294 origin_(origin),
257 activity_(activity), 295 activity_(activity),
258 data_(data), 296 data_(data),
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
325 t2.WaitReady(); 363 t2.WaitReady();
326 EXPECT_EQ(starting_active + 1, GetGlobalActiveTrackerCount()); 364 EXPECT_EQ(starting_active + 1, GetGlobalActiveTrackerCount());
327 EXPECT_EQ(starting_inactive, GetGlobalInactiveTrackerCount()); 365 EXPECT_EQ(starting_inactive, GetGlobalInactiveTrackerCount());
328 366
329 t2.Exit(); 367 t2.Exit();
330 t2.Join(); 368 t2.Join();
331 EXPECT_EQ(starting_active, GetGlobalActiveTrackerCount()); 369 EXPECT_EQ(starting_active, GetGlobalActiveTrackerCount());
332 EXPECT_EQ(starting_inactive + 1, GetGlobalInactiveTrackerCount()); 370 EXPECT_EQ(starting_inactive + 1, GetGlobalInactiveTrackerCount());
333 } 371 }
334 372
373 TEST_F(ActivityTrackerTest, ProcessDeathTest) {
374 // This doesn't actually create and destroy a process. Instead, it uses for-
375 // testing interfaces to simulate data created by other processes.
376 const ProcessId other_process_id = GetCurrentProcId() + 1;
377
378 GlobalActivityTracker::CreateWithLocalMemory(kMemorySize, 0, "", 3);
379 GlobalActivityTracker* global = GlobalActivityTracker::Get();
380 ThreadActivityTracker* thread = global->GetOrCreateTrackerForCurrentThread();
381
382 // Get callbacks for process exit.
383 global->SetProcessExitCallback(
384 Bind(&ActivityTrackerTest::HandleProcessExit, Unretained(this)));
385
386 // Pretend than another process has started.
387 global->RecordProcessLaunch(other_process_id, FILE_PATH_LITERAL("foo --bar"));
388
389 // Do some activities.
390 PendingTask task(FROM_HERE, base::Bind(&DoNothing));
391 ScopedTaskRunActivity activity(task);
392 ActivityUserData& user_data = activity.user_data();
393 ASSERT_NE(0U, user_data.id());
394
395 // Get the memory-allocator references to that data.
396 PersistentMemoryAllocator::Reference proc_data_ref =
397 global->allocator()->GetAsReference(
398 global->process_data().GetBaseAddress(),
399 GlobalActivityTracker::kTypeIdProcessDataRecord);
400 ASSERT_TRUE(proc_data_ref);
401 PersistentMemoryAllocator::Reference tracker_ref =
402 global->allocator()->GetAsReference(
403 thread->GetBaseAddress(),
404 GlobalActivityTracker::kTypeIdActivityTracker);
405 ASSERT_TRUE(tracker_ref);
406 PersistentMemoryAllocator::Reference user_data_ref =
407 global->allocator()->GetAsReference(
408 user_data.GetBaseAddress(),
409 GlobalActivityTracker::kTypeIdUserDataRecord);
410 ASSERT_TRUE(user_data_ref);
411
412 // Make a copy of the thread-tracker state so it can be restored later.
413 const size_t tracker_size = global->allocator()->GetAllocSize(tracker_ref);
414 std::unique_ptr<char[]> tracker_copy(new char[tracker_size]);
415 memcpy(tracker_copy.get(), thread->GetBaseAddress(), tracker_size);
416
417 // Change the objects to appear to be owned by another process.
418 ProcessId owning_id;
419 int64_t stamp;
420 ASSERT_TRUE(ActivityUserData::GetOwningProcessId(
421 global->process_data().GetBaseAddress(), &owning_id, &stamp));
422 EXPECT_NE(other_process_id, owning_id);
423 ASSERT_TRUE(ThreadActivityTracker::GetOwningProcessId(
424 thread->GetBaseAddress(), &owning_id, &stamp));
425 EXPECT_NE(other_process_id, owning_id);
426 ASSERT_TRUE(ActivityUserData::GetOwningProcessId(user_data.GetBaseAddress(),
427 &owning_id, &stamp));
428 EXPECT_NE(other_process_id, owning_id);
429 global->process_data().SetOwningProcessIdForTesting(other_process_id, stamp);
430 thread->SetOwningProcessIdForTesting(other_process_id, stamp);
431 user_data.SetOwningProcessIdForTesting(other_process_id, stamp);
432 ASSERT_TRUE(ActivityUserData::GetOwningProcessId(
433 global->process_data().GetBaseAddress(), &owning_id, &stamp));
434 EXPECT_EQ(other_process_id, owning_id);
435 ASSERT_TRUE(ThreadActivityTracker::GetOwningProcessId(
436 thread->GetBaseAddress(), &owning_id, &stamp));
437 EXPECT_EQ(other_process_id, owning_id);
438 ASSERT_TRUE(ActivityUserData::GetOwningProcessId(user_data.GetBaseAddress(),
439 &owning_id, &stamp));
440 EXPECT_EQ(other_process_id, owning_id);
441
442 // Check that process exit will perform callback and free the allocations.
443 ASSERT_EQ(0, exit_id);
444 ASSERT_EQ(GlobalActivityTracker::kTypeIdProcessDataRecord,
445 global->allocator()->GetType(proc_data_ref));
446 ASSERT_EQ(GlobalActivityTracker::kTypeIdActivityTracker,
447 global->allocator()->GetType(tracker_ref));
448 ASSERT_EQ(GlobalActivityTracker::kTypeIdUserDataRecord,
449 global->allocator()->GetType(user_data_ref));
450 global->RecordProcessExit(other_process_id, 0);
451 EXPECT_EQ(other_process_id, exit_id);
452 EXPECT_EQ("foo --bar", exit_command);
453 EXPECT_EQ(GlobalActivityTracker::kTypeIdProcessDataRecordFree,
454 global->allocator()->GetType(proc_data_ref));
455 EXPECT_EQ(GlobalActivityTracker::kTypeIdActivityTrackerFree,
456 global->allocator()->GetType(tracker_ref));
457 EXPECT_EQ(GlobalActivityTracker::kTypeIdUserDataRecordFree,
458 global->allocator()->GetType(user_data_ref));
459
460 // Restore memory contents and types so things don't crash when doing real
461 // process clean-up.
462 memcpy(const_cast<void*>(thread->GetBaseAddress()), tracker_copy.get(),
463 tracker_size);
464 global->allocator()->ChangeType(
465 proc_data_ref, GlobalActivityTracker::kTypeIdProcessDataRecord,
466 GlobalActivityTracker::kTypeIdUserDataRecordFree, false);
467 global->allocator()->ChangeType(
468 tracker_ref, GlobalActivityTracker::kTypeIdActivityTracker,
469 GlobalActivityTracker::kTypeIdActivityTrackerFree, false);
470 global->allocator()->ChangeType(
471 user_data_ref, GlobalActivityTracker::kTypeIdUserDataRecord,
472 GlobalActivityTracker::kTypeIdUserDataRecordFree, false);
473 }
474
335 } // namespace debug 475 } // namespace debug
336 } // namespace base 476 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698