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

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

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

Powered by Google App Engine
This is Rietveld 408576698