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

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

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