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

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

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

Powered by Google App Engine
This is Rietveld 408576698