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

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

Powered by Google App Engine
This is Rietveld 408576698