activity_analyzer_unittest.cc 21 KB

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