xref: /aosp_15_r20/external/libchrome/base/debug/activity_analyzer_unittest.cc (revision 635a864187cb8b6c713ff48b7e790a6b21769273)
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