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
3 // found in the LICENSE file.
4
5 #include "base/debug/activity_analyzer.h"
6
7 #include <atomic>
8 #include <memory>
9
10 #include "base/auto_reset.h"
11 #include "base/bind.h"
12 #include "base/debug/activity_tracker.h"
13 #include "base/files/file.h"
14 #include "base/files/file_util.h"
15 #include "base/files/memory_mapped_file.h"
16 #include "base/files/scoped_temp_dir.h"
17 #include "base/memory/ptr_util.h"
18 #include "base/pending_task.h"
19 #include "base/process/process.h"
20 #include "base/stl_util.h"
21 #include "base/synchronization/condition_variable.h"
22 #include "base/synchronization/lock.h"
23 #include "base/synchronization/spin_wait.h"
24 #include "base/threading/platform_thread.h"
25 #include "base/threading/simple_thread.h"
26 #include "base/time/time.h"
27 #include "testing/gtest/include/gtest/gtest.h"
28
29 namespace base {
30 namespace debug {
31
32 namespace {
33
34 class TestActivityTracker : public ThreadActivityTracker {
35 public:
TestActivityTracker(std::unique_ptr<char[]> memory,size_t mem_size)36 TestActivityTracker(std::unique_ptr<char[]> memory, size_t mem_size)
37 : ThreadActivityTracker(memset(memory.get(), 0, mem_size), mem_size),
38 mem_segment_(std::move(memory)) {}
39
40 ~TestActivityTracker() override = default;
41
42 private:
43 std::unique_ptr<char[]> mem_segment_;
44 };
45
46 } // namespace
47
48
49 class ActivityAnalyzerTest : public testing::Test {
50 public:
51 const int kMemorySize = 1 << 20; // 1MiB
52 const int kStackSize = 1 << 10; // 1KiB
53
54 ActivityAnalyzerTest() = default;
55
~ActivityAnalyzerTest()56 ~ActivityAnalyzerTest() override {
57 GlobalActivityTracker* global_tracker = GlobalActivityTracker::Get();
58 if (global_tracker) {
59 global_tracker->ReleaseTrackerForCurrentThreadForTesting();
60 delete global_tracker;
61 }
62 }
63
CreateActivityTracker()64 std::unique_ptr<ThreadActivityTracker> CreateActivityTracker() {
65 std::unique_ptr<char[]> memory(new char[kStackSize]);
66 return std::make_unique<TestActivityTracker>(std::move(memory), kStackSize);
67 }
68
69 template <typename Function>
AsOtherProcess(int64_t pid,Function function)70 void AsOtherProcess(int64_t pid, Function function) {
71 std::unique_ptr<GlobalActivityTracker> old_global =
72 GlobalActivityTracker::ReleaseForTesting();
73 ASSERT_TRUE(old_global);
74
75 PersistentMemoryAllocator* old_allocator = old_global->allocator();
76 std::unique_ptr<PersistentMemoryAllocator> new_allocator(
77 std::make_unique<PersistentMemoryAllocator>(
78 const_cast<void*>(old_allocator->data()), old_allocator->size(), 0,
79 0, "", false));
80 GlobalActivityTracker::CreateWithAllocator(std::move(new_allocator), 3,
81 pid);
82
83 function();
84
85 GlobalActivityTracker::ReleaseForTesting();
86 GlobalActivityTracker::SetForTesting(std::move(old_global));
87 }
88
DoNothing()89 static void DoNothing() {}
90 };
91
TEST_F(ActivityAnalyzerTest,ThreadAnalyzerConstruction)92 TEST_F(ActivityAnalyzerTest, ThreadAnalyzerConstruction) {
93 std::unique_ptr<ThreadActivityTracker> tracker = CreateActivityTracker();
94 {
95 ThreadActivityAnalyzer analyzer(*tracker);
96 EXPECT_TRUE(analyzer.IsValid());
97 EXPECT_EQ(PlatformThread::GetName(), analyzer.GetThreadName());
98 }
99
100 // TODO(bcwhite): More tests once Analyzer does more.
101 }
102
103
104 // GlobalActivityAnalyzer tests below.
105
106 namespace {
107
108 class SimpleActivityThread : public SimpleThread {
109 public:
SimpleActivityThread(const std::string & name,const void * source,Activity::Type activity,const ActivityData & data)110 SimpleActivityThread(const std::string& name,
111 const void* source,
112 Activity::Type activity,
113 const ActivityData& data)
114 : SimpleThread(name, Options()),
115 source_(source),
116 activity_(activity),
117 data_(data),
118 ready_(false),
119 exit_(false),
120 exit_condition_(&lock_) {}
121
122 ~SimpleActivityThread() override = default;
123
Run()124 void Run() override {
125 ThreadActivityTracker::ActivityId id =
126 GlobalActivityTracker::Get()
127 ->GetOrCreateTrackerForCurrentThread()
128 ->PushActivity(source_, activity_, data_);
129
130 {
131 AutoLock auto_lock(lock_);
132 ready_.store(true, std::memory_order_release);
133 while (!exit_.load(std::memory_order_relaxed))
134 exit_condition_.Wait();
135 }
136
137 GlobalActivityTracker::Get()->GetTrackerForCurrentThread()->PopActivity(id);
138 }
139
Exit()140 void Exit() {
141 AutoLock auto_lock(lock_);
142 exit_.store(true, std::memory_order_relaxed);
143 exit_condition_.Signal();
144 }
145
WaitReady()146 void WaitReady() {
147 SPIN_FOR_1_SECOND_OR_UNTIL_TRUE(ready_.load(std::memory_order_acquire));
148 }
149
150 private:
151 const void* source_;
152 Activity::Type activity_;
153 ActivityData data_;
154
155 std::atomic<bool> ready_;
156 std::atomic<bool> exit_;
157 Lock lock_;
158 ConditionVariable exit_condition_;
159
160 DISALLOW_COPY_AND_ASSIGN(SimpleActivityThread);
161 };
162
163 } // namespace
164
TEST_F(ActivityAnalyzerTest,GlobalAnalyzerConstruction)165 TEST_F(ActivityAnalyzerTest, GlobalAnalyzerConstruction) {
166 GlobalActivityTracker::CreateWithLocalMemory(kMemorySize, 0, "", 3, 0);
167 GlobalActivityTracker::Get()->process_data().SetString("foo", "bar");
168
169 PersistentMemoryAllocator* allocator =
170 GlobalActivityTracker::Get()->allocator();
171 GlobalActivityAnalyzer analyzer(std::make_unique<PersistentMemoryAllocator>(
172 const_cast<void*>(allocator->data()), allocator->size(), 0, 0, "", true));
173
174 // The only thread at this point is the test thread of this process.
175 const int64_t pid = analyzer.GetFirstProcess();
176 ASSERT_NE(0, pid);
177 ThreadActivityAnalyzer* ta1 = analyzer.GetFirstAnalyzer(pid);
178 ASSERT_TRUE(ta1);
179 EXPECT_FALSE(analyzer.GetNextAnalyzer());
180 ThreadActivityAnalyzer::ThreadKey tk1 = ta1->GetThreadKey();
181 EXPECT_EQ(ta1, analyzer.GetAnalyzerForThread(tk1));
182 EXPECT_EQ(0, analyzer.GetNextProcess());
183
184 // Create a second thread that will do something.
185 SimpleActivityThread t2("t2", nullptr, Activity::ACT_TASK,
186 ActivityData::ForTask(11));
187 t2.Start();
188 t2.WaitReady();
189
190 // Now there should be two. Calling GetFirstProcess invalidates any
191 // previously returned analyzer pointers.
192 ASSERT_EQ(pid, analyzer.GetFirstProcess());
193 EXPECT_TRUE(analyzer.GetFirstAnalyzer(pid));
194 EXPECT_TRUE(analyzer.GetNextAnalyzer());
195 EXPECT_FALSE(analyzer.GetNextAnalyzer());
196 EXPECT_EQ(0, analyzer.GetNextProcess());
197
198 // Let thread exit.
199 t2.Exit();
200 t2.Join();
201
202 // Now there should be only one again.
203 ASSERT_EQ(pid, analyzer.GetFirstProcess());
204 ThreadActivityAnalyzer* ta2 = analyzer.GetFirstAnalyzer(pid);
205 ASSERT_TRUE(ta2);
206 EXPECT_FALSE(analyzer.GetNextAnalyzer());
207 ThreadActivityAnalyzer::ThreadKey tk2 = ta2->GetThreadKey();
208 EXPECT_EQ(ta2, analyzer.GetAnalyzerForThread(tk2));
209 EXPECT_EQ(tk1, tk2);
210 EXPECT_EQ(0, analyzer.GetNextProcess());
211
212 // Verify that there is process data.
213 const ActivityUserData::Snapshot& data_snapshot =
214 analyzer.GetProcessDataSnapshot(pid);
215 ASSERT_LE(1U, data_snapshot.size());
216 EXPECT_EQ("bar", data_snapshot.at("foo").GetString());
217 }
218
TEST_F(ActivityAnalyzerTest,GlobalAnalyzerFromSharedMemory)219 TEST_F(ActivityAnalyzerTest, GlobalAnalyzerFromSharedMemory) {
220 SharedMemoryHandle handle1;
221 SharedMemoryHandle handle2;
222
223 {
224 std::unique_ptr<SharedMemory> shmem(new SharedMemory());
225 ASSERT_TRUE(shmem->CreateAndMapAnonymous(kMemorySize));
226 handle1 = shmem->handle().Duplicate();
227 ASSERT_TRUE(handle1.IsValid());
228 handle2 = shmem->handle().Duplicate();
229 ASSERT_TRUE(handle2.IsValid());
230 }
231
232 GlobalActivityTracker::CreateWithSharedMemoryHandle(handle1, kMemorySize, 0,
233 "", 3);
234 GlobalActivityTracker::Get()->process_data().SetString("foo", "bar");
235
236 std::unique_ptr<GlobalActivityAnalyzer> analyzer =
237 GlobalActivityAnalyzer::CreateWithSharedMemoryHandle(handle2,
238 kMemorySize);
239
240 const int64_t pid = analyzer->GetFirstProcess();
241 ASSERT_NE(0, pid);
242 const ActivityUserData::Snapshot& data_snapshot =
243 analyzer->GetProcessDataSnapshot(pid);
244 ASSERT_LE(1U, data_snapshot.size());
245 EXPECT_EQ("bar", data_snapshot.at("foo").GetString());
246 }
247
TEST_F(ActivityAnalyzerTest,UserDataSnapshotTest)248 TEST_F(ActivityAnalyzerTest, UserDataSnapshotTest) {
249 GlobalActivityTracker::CreateWithLocalMemory(kMemorySize, 0, "", 3, 0);
250 ThreadActivityAnalyzer::Snapshot tracker_snapshot;
251
252 const char string1a[] = "string1a";
253 const char string1b[] = "string1b";
254 const char string2a[] = "string2a";
255 const char string2b[] = "string2b";
256
257 PersistentMemoryAllocator* allocator =
258 GlobalActivityTracker::Get()->allocator();
259 GlobalActivityAnalyzer global_analyzer(
260 std::make_unique<PersistentMemoryAllocator>(
261 const_cast<void*>(allocator->data()), allocator->size(), 0, 0, "",
262 true));
263
264 ThreadActivityTracker* tracker =
265 GlobalActivityTracker::Get()->GetOrCreateTrackerForCurrentThread();
266
267 {
268 ScopedActivity activity1(1, 11, 111);
269 ActivityUserData& user_data1 = activity1.user_data();
270 user_data1.Set("raw1", "foo1", 4);
271 user_data1.SetString("string1", "bar1");
272 user_data1.SetChar("char1", '1');
273 user_data1.SetInt("int1", -1111);
274 user_data1.SetUint("uint1", 1111);
275 user_data1.SetBool("bool1", true);
276 user_data1.SetReference("ref1", string1a, sizeof(string1a));
277 user_data1.SetStringReference("sref1", string1b);
278
279 {
280 ScopedActivity activity2(2, 22, 222);
281 ActivityUserData& user_data2 = activity2.user_data();
282 user_data2.Set("raw2", "foo2", 4);
283 user_data2.SetString("string2", "bar2");
284 user_data2.SetChar("char2", '2');
285 user_data2.SetInt("int2", -2222);
286 user_data2.SetUint("uint2", 2222);
287 user_data2.SetBool("bool2", false);
288 user_data2.SetReference("ref2", string2a, sizeof(string2a));
289 user_data2.SetStringReference("sref2", string2b);
290
291 ASSERT_TRUE(tracker->CreateSnapshot(&tracker_snapshot));
292 ASSERT_EQ(2U, tracker_snapshot.activity_stack.size());
293
294 ThreadActivityAnalyzer analyzer(*tracker);
295 analyzer.AddGlobalInformation(&global_analyzer);
296 const ThreadActivityAnalyzer::Snapshot& analyzer_snapshot =
297 analyzer.activity_snapshot();
298 ASSERT_EQ(2U, analyzer_snapshot.user_data_stack.size());
299 const ActivityUserData::Snapshot& user_data =
300 analyzer_snapshot.user_data_stack.at(1);
301 EXPECT_EQ(8U, user_data.size());
302 ASSERT_TRUE(ContainsKey(user_data, "raw2"));
303 EXPECT_EQ("foo2", user_data.at("raw2").Get().as_string());
304 ASSERT_TRUE(ContainsKey(user_data, "string2"));
305 EXPECT_EQ("bar2", user_data.at("string2").GetString().as_string());
306 ASSERT_TRUE(ContainsKey(user_data, "char2"));
307 EXPECT_EQ('2', user_data.at("char2").GetChar());
308 ASSERT_TRUE(ContainsKey(user_data, "int2"));
309 EXPECT_EQ(-2222, user_data.at("int2").GetInt());
310 ASSERT_TRUE(ContainsKey(user_data, "uint2"));
311 EXPECT_EQ(2222U, user_data.at("uint2").GetUint());
312 ASSERT_TRUE(ContainsKey(user_data, "bool2"));
313 EXPECT_FALSE(user_data.at("bool2").GetBool());
314 ASSERT_TRUE(ContainsKey(user_data, "ref2"));
315 EXPECT_EQ(string2a, user_data.at("ref2").GetReference().data());
316 EXPECT_EQ(sizeof(string2a), user_data.at("ref2").GetReference().size());
317 ASSERT_TRUE(ContainsKey(user_data, "sref2"));
318 EXPECT_EQ(string2b, user_data.at("sref2").GetStringReference().data());
319 EXPECT_EQ(strlen(string2b),
320 user_data.at("sref2").GetStringReference().size());
321 }
322
323 ASSERT_TRUE(tracker->CreateSnapshot(&tracker_snapshot));
324 ASSERT_EQ(1U, tracker_snapshot.activity_stack.size());
325
326 ThreadActivityAnalyzer analyzer(*tracker);
327 analyzer.AddGlobalInformation(&global_analyzer);
328 const ThreadActivityAnalyzer::Snapshot& analyzer_snapshot =
329 analyzer.activity_snapshot();
330 ASSERT_EQ(1U, analyzer_snapshot.user_data_stack.size());
331 const ActivityUserData::Snapshot& user_data =
332 analyzer_snapshot.user_data_stack.at(0);
333 EXPECT_EQ(8U, user_data.size());
334 EXPECT_EQ("foo1", user_data.at("raw1").Get().as_string());
335 EXPECT_EQ("bar1", user_data.at("string1").GetString().as_string());
336 EXPECT_EQ('1', user_data.at("char1").GetChar());
337 EXPECT_EQ(-1111, user_data.at("int1").GetInt());
338 EXPECT_EQ(1111U, user_data.at("uint1").GetUint());
339 EXPECT_TRUE(user_data.at("bool1").GetBool());
340 EXPECT_EQ(string1a, user_data.at("ref1").GetReference().data());
341 EXPECT_EQ(sizeof(string1a), user_data.at("ref1").GetReference().size());
342 EXPECT_EQ(string1b, user_data.at("sref1").GetStringReference().data());
343 EXPECT_EQ(strlen(string1b),
344 user_data.at("sref1").GetStringReference().size());
345 }
346
347 ASSERT_TRUE(tracker->CreateSnapshot(&tracker_snapshot));
348 ASSERT_EQ(0U, tracker_snapshot.activity_stack.size());
349 }
350
TEST_F(ActivityAnalyzerTest,GlobalUserDataTest)351 TEST_F(ActivityAnalyzerTest, GlobalUserDataTest) {
352 const int64_t pid = GetCurrentProcId();
353 GlobalActivityTracker::CreateWithLocalMemory(kMemorySize, 0, "", 3, 0);
354
355 const char string1[] = "foo";
356 const char string2[] = "bar";
357
358 PersistentMemoryAllocator* allocator =
359 GlobalActivityTracker::Get()->allocator();
360 GlobalActivityAnalyzer global_analyzer(
361 std::make_unique<PersistentMemoryAllocator>(
362 const_cast<void*>(allocator->data()), allocator->size(), 0, 0, "",
363 true));
364
365 ActivityUserData& process_data = GlobalActivityTracker::Get()->process_data();
366 ASSERT_NE(0U, process_data.id());
367 process_data.Set("raw", "foo", 3);
368 process_data.SetString("string", "bar");
369 process_data.SetChar("char", '9');
370 process_data.SetInt("int", -9999);
371 process_data.SetUint("uint", 9999);
372 process_data.SetBool("bool", true);
373 process_data.SetReference("ref", string1, sizeof(string1));
374 process_data.SetStringReference("sref", string2);
375
376 int64_t first_pid = global_analyzer.GetFirstProcess();
377 DCHECK_EQ(pid, first_pid);
378 const ActivityUserData::Snapshot& snapshot =
379 global_analyzer.GetProcessDataSnapshot(pid);
380 ASSERT_TRUE(ContainsKey(snapshot, "raw"));
381 EXPECT_EQ("foo", snapshot.at("raw").Get().as_string());
382 ASSERT_TRUE(ContainsKey(snapshot, "string"));
383 EXPECT_EQ("bar", snapshot.at("string").GetString().as_string());
384 ASSERT_TRUE(ContainsKey(snapshot, "char"));
385 EXPECT_EQ('9', snapshot.at("char").GetChar());
386 ASSERT_TRUE(ContainsKey(snapshot, "int"));
387 EXPECT_EQ(-9999, snapshot.at("int").GetInt());
388 ASSERT_TRUE(ContainsKey(snapshot, "uint"));
389 EXPECT_EQ(9999U, snapshot.at("uint").GetUint());
390 ASSERT_TRUE(ContainsKey(snapshot, "bool"));
391 EXPECT_TRUE(snapshot.at("bool").GetBool());
392 ASSERT_TRUE(ContainsKey(snapshot, "ref"));
393 EXPECT_EQ(string1, snapshot.at("ref").GetReference().data());
394 EXPECT_EQ(sizeof(string1), snapshot.at("ref").GetReference().size());
395 ASSERT_TRUE(ContainsKey(snapshot, "sref"));
396 EXPECT_EQ(string2, snapshot.at("sref").GetStringReference().data());
397 EXPECT_EQ(strlen(string2), snapshot.at("sref").GetStringReference().size());
398 }
399
TEST_F(ActivityAnalyzerTest,GlobalModulesTest)400 TEST_F(ActivityAnalyzerTest, GlobalModulesTest) {
401 GlobalActivityTracker::CreateWithLocalMemory(kMemorySize, 0, "", 3, 0);
402 GlobalActivityTracker* global = GlobalActivityTracker::Get();
403
404 PersistentMemoryAllocator* allocator = global->allocator();
405 GlobalActivityAnalyzer global_analyzer(
406 std::make_unique<PersistentMemoryAllocator>(
407 const_cast<void*>(allocator->data()), allocator->size(), 0, 0, "",
408 true));
409
410 GlobalActivityTracker::ModuleInfo info1;
411 info1.is_loaded = true;
412 info1.address = 0x12345678;
413 info1.load_time = 1111;
414 info1.size = 0xABCDEF;
415 info1.timestamp = 111;
416 info1.age = 11;
417 info1.identifier[0] = 1;
418 info1.file = "anything";
419 info1.debug_file = "elsewhere";
420
421 global->RecordModuleInfo(info1);
422 std::vector<GlobalActivityTracker::ModuleInfo> modules1;
423 modules1 = global_analyzer.GetModules(global_analyzer.GetFirstProcess());
424 ASSERT_EQ(1U, modules1.size());
425 GlobalActivityTracker::ModuleInfo& stored1a = modules1[0];
426 EXPECT_EQ(info1.is_loaded, stored1a.is_loaded);
427 EXPECT_EQ(info1.address, stored1a.address);
428 EXPECT_NE(info1.load_time, stored1a.load_time);
429 EXPECT_EQ(info1.size, stored1a.size);
430 EXPECT_EQ(info1.timestamp, stored1a.timestamp);
431 EXPECT_EQ(info1.age, stored1a.age);
432 EXPECT_EQ(info1.identifier[0], stored1a.identifier[0]);
433 EXPECT_EQ(info1.file, stored1a.file);
434 EXPECT_EQ(info1.debug_file, stored1a.debug_file);
435
436 info1.is_loaded = false;
437 global->RecordModuleInfo(info1);
438 modules1 = global_analyzer.GetModules(global_analyzer.GetFirstProcess());
439 ASSERT_EQ(1U, modules1.size());
440 GlobalActivityTracker::ModuleInfo& stored1b = modules1[0];
441 EXPECT_EQ(info1.is_loaded, stored1b.is_loaded);
442 EXPECT_EQ(info1.address, stored1b.address);
443 EXPECT_NE(info1.load_time, stored1b.load_time);
444 EXPECT_EQ(info1.size, stored1b.size);
445 EXPECT_EQ(info1.timestamp, stored1b.timestamp);
446 EXPECT_EQ(info1.age, stored1b.age);
447 EXPECT_EQ(info1.identifier[0], stored1b.identifier[0]);
448 EXPECT_EQ(info1.file, stored1b.file);
449 EXPECT_EQ(info1.debug_file, stored1b.debug_file);
450
451 GlobalActivityTracker::ModuleInfo info2;
452 info2.is_loaded = true;
453 info2.address = 0x87654321;
454 info2.load_time = 2222;
455 info2.size = 0xFEDCBA;
456 info2.timestamp = 222;
457 info2.age = 22;
458 info2.identifier[0] = 2;
459 info2.file = "nothing";
460 info2.debug_file = "farewell";
461
462 global->RecordModuleInfo(info2);
463 std::vector<GlobalActivityTracker::ModuleInfo> modules2;
464 modules2 = global_analyzer.GetModules(global_analyzer.GetFirstProcess());
465 ASSERT_EQ(2U, modules2.size());
466 GlobalActivityTracker::ModuleInfo& stored2 = modules2[1];
467 EXPECT_EQ(info2.is_loaded, stored2.is_loaded);
468 EXPECT_EQ(info2.address, stored2.address);
469 EXPECT_NE(info2.load_time, stored2.load_time);
470 EXPECT_EQ(info2.size, stored2.size);
471 EXPECT_EQ(info2.timestamp, stored2.timestamp);
472 EXPECT_EQ(info2.age, stored2.age);
473 EXPECT_EQ(info2.identifier[0], stored2.identifier[0]);
474 EXPECT_EQ(info2.file, stored2.file);
475 EXPECT_EQ(info2.debug_file, stored2.debug_file);
476 }
477
TEST_F(ActivityAnalyzerTest,GlobalLogMessages)478 TEST_F(ActivityAnalyzerTest, GlobalLogMessages) {
479 GlobalActivityTracker::CreateWithLocalMemory(kMemorySize, 0, "", 3, 0);
480
481 PersistentMemoryAllocator* allocator =
482 GlobalActivityTracker::Get()->allocator();
483 GlobalActivityAnalyzer analyzer(std::make_unique<PersistentMemoryAllocator>(
484 const_cast<void*>(allocator->data()), allocator->size(), 0, 0, "", true));
485
486 GlobalActivityTracker::Get()->RecordLogMessage("hello world");
487 GlobalActivityTracker::Get()->RecordLogMessage("foo bar");
488
489 std::vector<std::string> messages = analyzer.GetLogMessages();
490 ASSERT_EQ(2U, messages.size());
491 EXPECT_EQ("hello world", messages[0]);
492 EXPECT_EQ("foo bar", messages[1]);
493 }
494
TEST_F(ActivityAnalyzerTest,GlobalMultiProcess)495 TEST_F(ActivityAnalyzerTest, GlobalMultiProcess) {
496 GlobalActivityTracker::CreateWithLocalMemory(kMemorySize, 0, "", 3, 1001);
497 GlobalActivityTracker* global = GlobalActivityTracker::Get();
498 PersistentMemoryAllocator* allocator = global->allocator();
499 EXPECT_EQ(1001, global->process_id());
500
501 int64_t process_id;
502 int64_t create_stamp;
503 ActivityUserData::GetOwningProcessId(
504 GlobalActivityTracker::Get()->process_data().GetBaseAddress(),
505 &process_id, &create_stamp);
506 ASSERT_EQ(1001, process_id);
507
508 GlobalActivityTracker::Get()->process_data().SetInt("pid",
509 global->process_id());
510
511 GlobalActivityAnalyzer analyzer(std::make_unique<PersistentMemoryAllocator>(
512 const_cast<void*>(allocator->data()), allocator->size(), 0, 0, "", true));
513
514 AsOtherProcess(2002, [&global]() {
515 ASSERT_NE(global, GlobalActivityTracker::Get());
516 EXPECT_EQ(2002, GlobalActivityTracker::Get()->process_id());
517
518 int64_t process_id;
519 int64_t create_stamp;
520 ActivityUserData::GetOwningProcessId(
521 GlobalActivityTracker::Get()->process_data().GetBaseAddress(),
522 &process_id, &create_stamp);
523 ASSERT_EQ(2002, process_id);
524
525 GlobalActivityTracker::Get()->process_data().SetInt(
526 "pid", GlobalActivityTracker::Get()->process_id());
527 });
528 ASSERT_EQ(global, GlobalActivityTracker::Get());
529 EXPECT_EQ(1001, GlobalActivityTracker::Get()->process_id());
530
531 const int64_t pid1 = analyzer.GetFirstProcess();
532 ASSERT_EQ(1001, pid1);
533 const int64_t pid2 = analyzer.GetNextProcess();
534 ASSERT_EQ(2002, pid2);
535 EXPECT_EQ(0, analyzer.GetNextProcess());
536
537 const ActivityUserData::Snapshot& pdata1 =
538 analyzer.GetProcessDataSnapshot(pid1);
539 const ActivityUserData::Snapshot& pdata2 =
540 analyzer.GetProcessDataSnapshot(pid2);
541 EXPECT_EQ(1001, pdata1.at("pid").GetInt());
542 EXPECT_EQ(2002, pdata2.at("pid").GetInt());
543 }
544
545 } // namespace debug
546 } // namespace base
547