hang_watcher_unittest.cc 45 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289
  1. // Copyright 2020 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/threading/hang_watcher.h"
  5. #include <atomic>
  6. #include <memory>
  7. #include "base/barrier_closure.h"
  8. #include "base/bind.h"
  9. #include "base/callback.h"
  10. #include "base/callback_helpers.h"
  11. #include "base/memory/raw_ptr.h"
  12. #include "base/run_loop.h"
  13. #include "base/strings/string_number_conversions.h"
  14. #include "base/synchronization/lock.h"
  15. #include "base/synchronization/waitable_event.h"
  16. #include "base/test/bind.h"
  17. #include "base/test/metrics/histogram_tester.h"
  18. #include "base/test/power_monitor_test.h"
  19. #include "base/test/scoped_feature_list.h"
  20. #include "base/test/simple_test_tick_clock.h"
  21. #include "base/test/task_environment.h"
  22. #include "base/test/test_timeouts.h"
  23. #include "base/threading/platform_thread.h"
  24. #include "base/threading/thread_checker.h"
  25. #include "base/threading/threading_features.h"
  26. #include "base/time/tick_clock.h"
  27. #include "base/time/time.h"
  28. #include "build/build_config.h"
  29. #include "testing/gmock/include/gmock/gmock.h"
  30. #include "testing/gtest/include/gtest/gtest.h"
  31. #include "third_party/abseil-cpp/absl/types/optional.h"
  32. using testing::ElementsAre;
  33. using testing::IsEmpty;
  34. namespace base {
  35. namespace {
  36. // Use with a FeatureList to activate crash dumping for threads marked as
  37. // threadpool threads.
  38. const std::vector<base::test::ScopedFeatureList::FeatureAndParams>
  39. kFeatureAndParams{
  40. {base::kEnableHangWatcher, {{"ui_thread_log_level", "2"}}}};
  41. // Use this value to mark things very far off in the future. Adding this
  42. // to TimeTicks::Now() gives a point that will never be reached during the
  43. // normal execution of a test.
  44. constexpr TimeDelta kVeryLongDelta{base::Days(365)};
  45. // A relatively small time delta to ensure ordering of hung threads list.
  46. constexpr TimeDelta kSmallCPUQuantum{base::Milliseconds(1)};
  47. constexpr uint64_t kArbitraryDeadline = 0x0000C0FFEEC0FFEEu;
  48. constexpr uint64_t kAllOnes = 0xFFFFFFFFFFFFFFFFu;
  49. constexpr uint64_t kAllZeros = 0x0000000000000000u;
  50. constexpr uint64_t kOnesThenZeroes = 0xAAAAAAAAAAAAAAAAu;
  51. constexpr uint64_t kZeroesThenOnes = 0x5555555555555555u;
  52. // Waits on provided WaitableEvent before executing and signals when done.
  53. class BlockingThread : public DelegateSimpleThread::Delegate {
  54. public:
  55. explicit BlockingThread(base::WaitableEvent* unblock_thread,
  56. base::TimeDelta timeout)
  57. : thread_(this, "BlockingThread"),
  58. unblock_thread_(unblock_thread),
  59. timeout_(timeout) {}
  60. ~BlockingThread() override = default;
  61. void Run() override {
  62. // (Un)Register the thread here instead of in ctor/dtor so that the action
  63. // happens on the right thread.
  64. base::ScopedClosureRunner unregister_closure =
  65. base::HangWatcher::RegisterThread(
  66. base::HangWatcher::ThreadType::kMainThread);
  67. WatchHangsInScope scope(timeout_);
  68. wait_until_entered_scope_.Signal();
  69. unblock_thread_->Wait();
  70. run_event_.Signal();
  71. }
  72. bool IsDone() { return run_event_.IsSignaled(); }
  73. void StartAndWaitForScopeEntered() {
  74. thread_.Start();
  75. // Block until this thread registered itself for hang watching and has
  76. // entered a WatchHangsInScope.
  77. wait_until_entered_scope_.Wait();
  78. }
  79. void Join() { thread_.Join(); }
  80. PlatformThreadId GetId() { return thread_.tid(); }
  81. private:
  82. base::DelegateSimpleThread thread_;
  83. // Will be signaled once the thread is properly registered for watching and
  84. // the WatchHangsInScope has been entered.
  85. WaitableEvent wait_until_entered_scope_;
  86. // Will be signaled once ThreadMain has run.
  87. WaitableEvent run_event_;
  88. const raw_ptr<base::WaitableEvent> unblock_thread_;
  89. base::TimeDelta timeout_;
  90. };
  91. class HangWatcherTest : public testing::Test {
  92. public:
  93. const base::TimeDelta kTimeout = base::Seconds(10);
  94. const base::TimeDelta kHangTime = kTimeout + base::Seconds(1);
  95. HangWatcherTest() {
  96. feature_list_.InitWithFeaturesAndParameters(kFeatureAndParams, {});
  97. hang_watcher_.InitializeOnMainThread(
  98. HangWatcher::ProcessType::kBrowserProcess);
  99. hang_watcher_.SetAfterMonitorClosureForTesting(base::BindRepeating(
  100. &WaitableEvent::Signal, base::Unretained(&monitor_event_)));
  101. hang_watcher_.SetOnHangClosureForTesting(base::BindRepeating(
  102. &WaitableEvent::Signal, base::Unretained(&hang_event_)));
  103. // We're not testing the monitoring loop behavior in this test so we want to
  104. // trigger monitoring manually.
  105. hang_watcher_.SetMonitoringPeriodForTesting(kVeryLongDelta);
  106. // Start the monitoring loop.
  107. hang_watcher_.Start();
  108. }
  109. void TearDown() override { hang_watcher_.UnitializeOnMainThreadForTesting(); }
  110. HangWatcherTest(const HangWatcherTest& other) = delete;
  111. HangWatcherTest& operator=(const HangWatcherTest& other) = delete;
  112. protected:
  113. // Used to wait for monitoring. Will be signaled by the HangWatcher thread and
  114. // so needs to outlive it.
  115. WaitableEvent monitor_event_;
  116. // Signaled from the HangWatcher thread when a hang is detected. Needs to
  117. // outlive the HangWatcher thread.
  118. WaitableEvent hang_event_;
  119. base::test::ScopedFeatureList feature_list_;
  120. // Used exclusively for MOCK_TIME. No tasks will be run on the environment.
  121. // Single threaded to avoid ThreadPool WorkerThreads registering.
  122. test::SingleThreadTaskEnvironment task_environment_{
  123. test::TaskEnvironment::TimeSource::MOCK_TIME};
  124. // This must be declared last (after task_environment_, for example) so that
  125. // the watcher thread is joined before objects like the mock timer are
  126. // destroyed, causing racy crashes.
  127. HangWatcher hang_watcher_;
  128. };
  129. class HangWatcherBlockingThreadTest : public HangWatcherTest {
  130. public:
  131. HangWatcherBlockingThreadTest() : thread_(&unblock_thread_, kTimeout) {}
  132. HangWatcherBlockingThreadTest(const HangWatcherBlockingThreadTest& other) =
  133. delete;
  134. HangWatcherBlockingThreadTest& operator=(
  135. const HangWatcherBlockingThreadTest& other) = delete;
  136. protected:
  137. void JoinThread() {
  138. unblock_thread_.Signal();
  139. // Thread is joinable since we signaled |unblock_thread_|.
  140. thread_.Join();
  141. // If thread is done then it signaled.
  142. ASSERT_TRUE(thread_.IsDone());
  143. }
  144. void StartBlockedThread() {
  145. // Thread has not run yet.
  146. ASSERT_FALSE(thread_.IsDone());
  147. // Start the thread. It will block since |unblock_thread_| was not
  148. // signaled yet.
  149. thread_.StartAndWaitForScopeEntered();
  150. // Thread registration triggered a call to HangWatcher::Monitor() which
  151. // signaled |monitor_event_|. Reset it so it's ready for waiting later on.
  152. monitor_event_.Reset();
  153. }
  154. void MonitorHangs() {
  155. // HangWatcher::Monitor() should not be set which would mean a call to
  156. // HangWatcher::Monitor() happened and was unacounted for.
  157. // ASSERT_FALSE(monitor_event_.IsSignaled());
  158. // Trigger a monitoring on HangWatcher thread and verify results.
  159. hang_watcher_.SignalMonitorEventForTesting();
  160. monitor_event_.Wait();
  161. }
  162. // Used to unblock the monitored thread. Signaled from the test main thread.
  163. WaitableEvent unblock_thread_;
  164. BlockingThread thread_;
  165. };
  166. } // namespace
  167. TEST_F(HangWatcherTest, InvalidatingExpectationsPreventsCapture) {
  168. // Register the main test thread for hang watching.
  169. auto unregister_thread_closure =
  170. HangWatcher::RegisterThread(base::HangWatcher::ThreadType::kMainThread);
  171. // Create a hang.
  172. WatchHangsInScope expires_instantly(base::TimeDelta{});
  173. task_environment_.FastForwardBy(kHangTime);
  174. // de-activate hang watching,
  175. base::HangWatcher::InvalidateActiveExpectations();
  176. // Trigger a monitoring on HangWatcher thread and verify results.
  177. // Hang is not detected.
  178. hang_watcher_.SignalMonitorEventForTesting();
  179. monitor_event_.Wait();
  180. ASSERT_FALSE(hang_event_.IsSignaled());
  181. }
  182. TEST_F(HangWatcherTest, MultipleInvalidateExpectationsDoNotCancelOut) {
  183. // Register the main test thread for hang watching.
  184. auto unregister_thread_closure =
  185. HangWatcher::RegisterThread(base::HangWatcher::ThreadType::kMainThread);
  186. // Create a hang.
  187. WatchHangsInScope expires_instantly(base::TimeDelta{});
  188. task_environment_.FastForwardBy(kHangTime);
  189. // de-activate hang watching,
  190. base::HangWatcher::InvalidateActiveExpectations();
  191. // Redundently de-activate hang watching.
  192. base::HangWatcher::InvalidateActiveExpectations();
  193. // Trigger a monitoring on HangWatcher thread and verify results.
  194. // Hang is not detected.
  195. hang_watcher_.SignalMonitorEventForTesting();
  196. monitor_event_.Wait();
  197. ASSERT_FALSE(hang_event_.IsSignaled());
  198. }
  199. TEST_F(HangWatcherTest, NewInnerWatchHangsInScopeAfterInvalidationDetectsHang) {
  200. // Register the main test thread for hang watching.
  201. auto unregister_thread_closure =
  202. HangWatcher::RegisterThread(base::HangWatcher::ThreadType::kMainThread);
  203. WatchHangsInScope expires_instantly(base::TimeDelta{});
  204. task_environment_.FastForwardBy(kHangTime);
  205. // De-activate hang watching.
  206. base::HangWatcher::InvalidateActiveExpectations();
  207. {
  208. WatchHangsInScope also_expires_instantly(base::TimeDelta{});
  209. task_environment_.FastForwardBy(kHangTime);
  210. // Trigger a monitoring on HangWatcher thread and verify results.
  211. hang_watcher_.SignalMonitorEventForTesting();
  212. monitor_event_.Wait();
  213. // Hang is detected since the new WatchHangsInScope temporarily
  214. // re-activated hang_watching.
  215. monitor_event_.Wait();
  216. ASSERT_TRUE(hang_event_.IsSignaled());
  217. }
  218. // Reset to attempt capture again.
  219. monitor_event_.Reset();
  220. hang_event_.Reset();
  221. // Trigger a monitoring on HangWatcher thread and verify results.
  222. hang_watcher_.SignalMonitorEventForTesting();
  223. monitor_event_.Wait();
  224. // Hang is not detected since execution is back to being covered by
  225. // |expires_instantly| for which expectations were invalidated.
  226. monitor_event_.Wait();
  227. ASSERT_FALSE(hang_event_.IsSignaled());
  228. }
  229. TEST_F(HangWatcherTest,
  230. NewSeparateWatchHangsInScopeAfterInvalidationDetectsHang) {
  231. // Register the main test thread for hang watching.
  232. auto unregister_thread_closure =
  233. HangWatcher::RegisterThread(base::HangWatcher::ThreadType::kMainThread);
  234. {
  235. WatchHangsInScope expires_instantly(base::TimeDelta{});
  236. task_environment_.FastForwardBy(kHangTime);
  237. // De-activate hang watching.
  238. base::HangWatcher::InvalidateActiveExpectations();
  239. }
  240. WatchHangsInScope also_expires_instantly(base::TimeDelta{});
  241. task_environment_.FastForwardBy(kHangTime);
  242. // Trigger a monitoring on HangWatcher thread and verify results.
  243. hang_watcher_.SignalMonitorEventForTesting();
  244. monitor_event_.Wait();
  245. // Hang is detected since the new WatchHangsInScope did not have its
  246. // expectations invalidated.
  247. monitor_event_.Wait();
  248. ASSERT_TRUE(hang_event_.IsSignaled());
  249. }
  250. // Test that invalidating expectations from inner WatchHangsInScope will also
  251. // prevent hang detection in outer scopes.
  252. TEST_F(HangWatcherTest, ScopeDisabledObjectInnerScope) {
  253. // Register the main test thread for hang watching.
  254. auto unregister_thread_closure =
  255. HangWatcher::RegisterThread(base::HangWatcher::ThreadType::kMainThread);
  256. // Start a WatchHangsInScope that expires right away. Then advance
  257. // time to make sure no hang is detected.
  258. WatchHangsInScope expires_instantly(base::TimeDelta{});
  259. task_environment_.FastForwardBy(kHangTime);
  260. {
  261. WatchHangsInScope also_expires_instantly(base::TimeDelta{});
  262. // De-activate hang watching.
  263. base::HangWatcher::InvalidateActiveExpectations();
  264. task_environment_.FastForwardBy(kHangTime);
  265. }
  266. // Trigger a monitoring on HangWatcher thread and verify results.
  267. hang_watcher_.SignalMonitorEventForTesting();
  268. monitor_event_.Wait();
  269. // Hang is ignored since it concerns a scope for which one of the inner scope
  270. // was ignored.
  271. ASSERT_FALSE(hang_event_.IsSignaled());
  272. }
  273. TEST_F(HangWatcherTest, NewScopeAfterDisabling) {
  274. // Register the main test thread for hang watching.
  275. auto unregister_thread_closure =
  276. HangWatcher::RegisterThread(base::HangWatcher::ThreadType::kMainThread);
  277. // Start a WatchHangsInScope that expires right away. Then advance
  278. // time to make sure no hang is detected.
  279. WatchHangsInScope expires_instantly(base::TimeDelta{});
  280. task_environment_.FastForwardBy(kHangTime);
  281. {
  282. WatchHangsInScope also_expires_instantly(base::TimeDelta{});
  283. // De-activate hang watching.
  284. base::HangWatcher::InvalidateActiveExpectations();
  285. task_environment_.FastForwardBy(kHangTime);
  286. }
  287. // New scope for which expecations are never invalidated.
  288. WatchHangsInScope also_expires_instantly(base::TimeDelta{});
  289. task_environment_.FastForwardBy(kHangTime);
  290. // Trigger a monitoring on HangWatcher thread and verify results.
  291. hang_watcher_.SignalMonitorEventForTesting();
  292. monitor_event_.Wait();
  293. // Hang is detected because it's unrelated to the hangs that were disabled.
  294. ASSERT_TRUE(hang_event_.IsSignaled());
  295. }
  296. TEST_F(HangWatcherTest, NestedScopes) {
  297. // Create a state object for the test thread since this test is single
  298. // threaded.
  299. auto current_hang_watch_state =
  300. base::internal::HangWatchState::CreateHangWatchStateForCurrentThread(
  301. HangWatcher::ThreadType::kMainThread);
  302. ASSERT_FALSE(current_hang_watch_state->IsOverDeadline());
  303. base::TimeTicks original_deadline = current_hang_watch_state->GetDeadline();
  304. constexpr base::TimeDelta kFirstTimeout(base::Milliseconds(500));
  305. base::TimeTicks first_deadline = base::TimeTicks::Now() + kFirstTimeout;
  306. constexpr base::TimeDelta kSecondTimeout(base::Milliseconds(250));
  307. base::TimeTicks second_deadline = base::TimeTicks::Now() + kSecondTimeout;
  308. // At this point we have not set any timeouts.
  309. {
  310. // Create a first timeout which is more restrictive than the default.
  311. WatchHangsInScope first_scope(kFirstTimeout);
  312. // We are on mock time. There is no time advancement and as such no hangs.
  313. ASSERT_FALSE(current_hang_watch_state->IsOverDeadline());
  314. ASSERT_EQ(current_hang_watch_state->GetDeadline(), first_deadline);
  315. {
  316. // Set a yet more restrictive deadline. Still no hang.
  317. WatchHangsInScope second_scope(kSecondTimeout);
  318. ASSERT_FALSE(current_hang_watch_state->IsOverDeadline());
  319. ASSERT_EQ(current_hang_watch_state->GetDeadline(), second_deadline);
  320. }
  321. // First deadline we set should be restored.
  322. ASSERT_FALSE(current_hang_watch_state->IsOverDeadline());
  323. ASSERT_EQ(current_hang_watch_state->GetDeadline(), first_deadline);
  324. }
  325. // Original deadline should now be restored.
  326. ASSERT_FALSE(current_hang_watch_state->IsOverDeadline());
  327. ASSERT_EQ(current_hang_watch_state->GetDeadline(), original_deadline);
  328. }
  329. TEST_F(HangWatcherBlockingThreadTest, HistogramsLoggedOnHang) {
  330. base::HistogramTester histogram_tester;
  331. StartBlockedThread();
  332. // Simulate hang.
  333. task_environment_.FastForwardBy(kHangTime);
  334. // First monitoring catches the hang and emits the histogram.
  335. MonitorHangs();
  336. EXPECT_THAT(histogram_tester.GetAllSamples("HangWatcher.IsThreadHung."
  337. "BrowserProcess.UIThread"),
  338. ElementsAre(base::Bucket(true, /*count=*/1)));
  339. // Reset to attempt capture again.
  340. hang_event_.Reset();
  341. monitor_event_.Reset();
  342. // Hang is logged again even if it would not trigger a crash dump.
  343. MonitorHangs();
  344. EXPECT_THAT(histogram_tester.GetAllSamples("HangWatcher.IsThreadHung."
  345. "BrowserProcess.UIThread"),
  346. ElementsAre(base::Bucket(true, /*count=*/2)));
  347. // Thread types that are not monitored should not get any samples.
  348. EXPECT_THAT(histogram_tester.GetAllSamples("HangWatcher.IsThreadHung."
  349. "BrowserProcess.IOThread"),
  350. IsEmpty());
  351. JoinThread();
  352. }
  353. TEST_F(HangWatcherBlockingThreadTest, HistogramsLoggedWithoutHangs) {
  354. base::HistogramTester histogram_tester;
  355. StartBlockedThread();
  356. // No hang to catch so nothing is recorded.
  357. MonitorHangs();
  358. ASSERT_FALSE(hang_event_.IsSignaled());
  359. // A thread of type ThreadForTesting was monitored but didn't hang. This is
  360. // logged.
  361. EXPECT_THAT(histogram_tester.GetAllSamples("HangWatcher.IsThreadHung."
  362. "BrowserProcess.UIThread"),
  363. ElementsAre(base::Bucket(false, /*count=*/1)));
  364. // Thread types that are not monitored should not get any samples.
  365. EXPECT_THAT(histogram_tester.GetAllSamples("HangWatcher.IsThreadHung."
  366. "BrowserProcess.IOThread"),
  367. IsEmpty());
  368. JoinThread();
  369. }
  370. TEST_F(HangWatcherBlockingThreadTest, Hang) {
  371. StartBlockedThread();
  372. // Simulate hang.
  373. task_environment_.FastForwardBy(kHangTime);
  374. // First monitoring catches and records the hang.
  375. MonitorHangs();
  376. ASSERT_TRUE(hang_event_.IsSignaled());
  377. JoinThread();
  378. }
  379. TEST_F(HangWatcherBlockingThreadTest, HangAlreadyRecorded) {
  380. StartBlockedThread();
  381. // Simulate hang.
  382. task_environment_.FastForwardBy(kHangTime);
  383. // First monitoring catches and records the hang.
  384. MonitorHangs();
  385. ASSERT_TRUE(hang_event_.IsSignaled());
  386. // Reset to attempt capture again.
  387. hang_event_.Reset();
  388. monitor_event_.Reset();
  389. // Second monitoring does not record because a hang that was already recorded
  390. // is still live.
  391. MonitorHangs();
  392. ASSERT_FALSE(hang_event_.IsSignaled());
  393. JoinThread();
  394. }
  395. TEST_F(HangWatcherBlockingThreadTest, NoHang) {
  396. StartBlockedThread();
  397. // No hang to catch so nothing is recorded.
  398. MonitorHangs();
  399. ASSERT_FALSE(hang_event_.IsSignaled());
  400. JoinThread();
  401. }
  402. namespace {
  403. class HangWatcherSnapshotTest : public testing::Test {
  404. public:
  405. void SetUp() override {
  406. feature_list_.InitWithFeaturesAndParameters(kFeatureAndParams, {});
  407. hang_watcher_.InitializeOnMainThread(
  408. HangWatcher::ProcessType::kBrowserProcess);
  409. // The monitoring loop behavior is not verified in this test so we want to
  410. // trigger monitoring manually.
  411. hang_watcher_.SetMonitoringPeriodForTesting(kVeryLongDelta);
  412. }
  413. void TearDown() override { hang_watcher_.UnitializeOnMainThreadForTesting(); }
  414. HangWatcherSnapshotTest() = default;
  415. HangWatcherSnapshotTest(const HangWatcherSnapshotTest& other) = delete;
  416. HangWatcherSnapshotTest& operator=(const HangWatcherSnapshotTest& other) =
  417. delete;
  418. protected:
  419. void TriggerMonitorAndWaitForCompletion() {
  420. monitor_event_.Reset();
  421. hang_watcher_.SignalMonitorEventForTesting();
  422. monitor_event_.Wait();
  423. }
  424. // Verify that a capture takes place and that at the time of the capture the
  425. // list of hung thread ids is correct.
  426. void TestIDList(const std::string& id_list) {
  427. list_of_hung_thread_ids_during_capture_ = id_list;
  428. task_environment_.AdvanceClock(kSmallCPUQuantum);
  429. TriggerMonitorAndWaitForCompletion();
  430. ASSERT_EQ(++reference_capture_count_, hang_capture_count_);
  431. }
  432. // Verify that even if hang monitoring takes place no hangs are detected.
  433. void ExpectNoCapture() {
  434. int old_capture_count = hang_capture_count_;
  435. task_environment_.AdvanceClock(kSmallCPUQuantum);
  436. TriggerMonitorAndWaitForCompletion();
  437. ASSERT_EQ(old_capture_count, hang_capture_count_);
  438. }
  439. std::string ConcatenateThreadIds(
  440. const std::vector<base::PlatformThreadId>& ids) const {
  441. std::string result;
  442. constexpr char kSeparator{'|'};
  443. for (PlatformThreadId id : ids) {
  444. result += base::NumberToString(id) + kSeparator;
  445. }
  446. return result;
  447. }
  448. // Will be signaled once monitoring took place. Marks the end of the test.
  449. WaitableEvent monitor_event_;
  450. const PlatformThreadId test_thread_id_ = PlatformThread::CurrentId();
  451. // This is written to by the test main thread and read from the hang watching
  452. // thread. It does not need to be protected because access to it is
  453. // synchronized by always setting before triggering the execution of the
  454. // reading code through HangWatcher::SignalMonitorEventForTesting().
  455. std::string list_of_hung_thread_ids_during_capture_;
  456. // This is written to by from the hang watching thread and read the test main
  457. // thread. It does not need to be protected because access to it is
  458. // synchronized by always reading after monitor_event_ has been signaled.
  459. int hang_capture_count_ = 0;
  460. // Increases at the same time as |hang_capture_count_| to test that capture
  461. // actually took place.
  462. int reference_capture_count_ = 0;
  463. std::string seconds_since_last_power_resume_crash_key_;
  464. base::test::ScopedFeatureList feature_list_;
  465. // Used exclusively for MOCK_TIME.
  466. test::SingleThreadTaskEnvironment task_environment_{
  467. test::TaskEnvironment::TimeSource::MOCK_TIME};
  468. HangWatcher hang_watcher_;
  469. };
  470. } // namespace
  471. // Verify that the hang capture fails when marking a thread for blocking fails.
  472. // This simulates a WatchHangsInScope completing between the time the hang
  473. // was dected and the time it is recorded which would create a non-actionable
  474. // report.
  475. TEST_F(HangWatcherSnapshotTest, NonActionableReport) {
  476. hang_watcher_.SetOnHangClosureForTesting(
  477. base::BindLambdaForTesting([this]() { ++hang_capture_count_; }));
  478. hang_watcher_.SetAfterMonitorClosureForTesting(
  479. base::BindLambdaForTesting([this]() { monitor_event_.Signal(); }));
  480. hang_watcher_.Start();
  481. // Register the main test thread for hang watching.
  482. auto unregister_thread_closure =
  483. HangWatcher::RegisterThread(base::HangWatcher::ThreadType::kMainThread);
  484. {
  485. // Start a WatchHangsInScope that expires right away. Ensures that
  486. // the first monitor will detect a hang.
  487. WatchHangsInScope expires_instantly(base::TimeDelta{});
  488. internal::HangWatchState* current_hang_watch_state =
  489. internal::HangWatchState::GetHangWatchStateForCurrentThread()->Get();
  490. // Simulate the deadline changing concurrently during the capture. This
  491. // makes the capture fail since marking of the deadline fails.
  492. ASSERT_NE(current_hang_watch_state->GetDeadline(),
  493. base::TimeTicks::FromInternalValue(kArbitraryDeadline));
  494. current_hang_watch_state->GetHangWatchDeadlineForTesting()
  495. ->SetSwitchBitsClosureForTesting(
  496. base::BindLambdaForTesting([]() { return kArbitraryDeadline; }));
  497. ExpectNoCapture();
  498. // Marking failed.
  499. ASSERT_FALSE(current_hang_watch_state->IsFlagSet(
  500. internal::HangWatchDeadline::Flag::kShouldBlockOnHang));
  501. current_hang_watch_state->GetHangWatchDeadlineForTesting()
  502. ->ResetSwitchBitsClosureForTesting();
  503. }
  504. }
  505. // TODO(crbug.com/1223033): On MAC, the base::PlatformThread::CurrentId(...)
  506. // should return the system wide IDs. The HungThreadIDs test fails because the
  507. // reported process ids do not match.
  508. #if BUILDFLAG(IS_MAC)
  509. #define MAYBE_HungThreadIDs DISABLED_HungThreadIDs
  510. #else
  511. #define MAYBE_HungThreadIDs HungThreadIDs
  512. #endif
  513. TEST_F(HangWatcherSnapshotTest, MAYBE_HungThreadIDs) {
  514. // During hang capture the list of hung threads should be populated.
  515. hang_watcher_.SetOnHangClosureForTesting(base::BindLambdaForTesting([this]() {
  516. EXPECT_EQ(hang_watcher_.GrabWatchStateSnapshotForTesting()
  517. .PrepareHungThreadListCrashKey(),
  518. list_of_hung_thread_ids_during_capture_);
  519. ++hang_capture_count_;
  520. }));
  521. // When hang capture is over the list should be empty.
  522. hang_watcher_.SetAfterMonitorClosureForTesting(
  523. base::BindLambdaForTesting([this]() {
  524. monitor_event_.Signal();
  525. }));
  526. hang_watcher_.Start();
  527. // Register the main test thread for hang watching.
  528. auto unregister_thread_closure =
  529. HangWatcher::RegisterThread(base::HangWatcher::ThreadType::kMainThread);
  530. BlockingThread blocking_thread(&monitor_event_, base::TimeDelta{});
  531. blocking_thread.StartAndWaitForScopeEntered();
  532. {
  533. // Ensure the blocking thread entered the scope before the main thread. This
  534. // will guarantee an ordering while reporting the list of hung threads.
  535. task_environment_.AdvanceClock(kSmallCPUQuantum);
  536. // Start a WatchHangsInScope that expires right away. Ensures that
  537. // the first monitor will detect a hang. This scope will naturally have a
  538. // later deadline than the one in |blocking_thread_| since it was created
  539. // after.
  540. WatchHangsInScope expires_instantly(base::TimeDelta{});
  541. // Hung thread list should contain the id the blocking thread and then the
  542. // id of the test main thread since that is the order of increasing
  543. // deadline.
  544. TestIDList(
  545. ConcatenateThreadIds({blocking_thread.GetId(), test_thread_id_}));
  546. // |expires_instantly| and the scope from |blocking_thread| are still live
  547. // but already recorded so should be ignored.
  548. ExpectNoCapture();
  549. // Thread is joinable since we signaled |monitor_event_|. This closes the
  550. // scope in |blocking_thread|.
  551. blocking_thread.Join();
  552. // |expires_instantly| is still live but already recorded so should be
  553. // ignored.
  554. ExpectNoCapture();
  555. }
  556. // All HangWatchScopeEnables are over. There should be no capture.
  557. ExpectNoCapture();
  558. // Once all recorded scopes are over creating a new one and monitoring will
  559. // trigger a hang detection.
  560. WatchHangsInScope expires_instantly(base::TimeDelta{});
  561. TestIDList(ConcatenateThreadIds({test_thread_id_}));
  562. }
  563. TEST_F(HangWatcherSnapshotTest, TimeSinceLastSystemPowerResumeCrashKey) {
  564. // Override the capture of hangs. Simulate a crash key capture.
  565. hang_watcher_.SetOnHangClosureForTesting(base::BindLambdaForTesting([this]() {
  566. ++hang_capture_count_;
  567. seconds_since_last_power_resume_crash_key_ =
  568. hang_watcher_.GetTimeSinceLastSystemPowerResumeCrashKeyValue();
  569. }));
  570. // When hang capture is over, unblock the main thread.
  571. hang_watcher_.SetAfterMonitorClosureForTesting(
  572. base::BindLambdaForTesting([this]() { monitor_event_.Signal(); }));
  573. hang_watcher_.Start();
  574. // Register the main test thread for hang watching.
  575. auto unregister_thread_closure =
  576. HangWatcher::RegisterThread(base::HangWatcher::ThreadType::kMainThread);
  577. {
  578. WatchHangsInScope expires_instantly(base::TimeDelta{});
  579. task_environment_.AdvanceClock(kSmallCPUQuantum);
  580. TriggerMonitorAndWaitForCompletion();
  581. EXPECT_EQ(1, hang_capture_count_);
  582. EXPECT_EQ("Never suspended", seconds_since_last_power_resume_crash_key_);
  583. }
  584. {
  585. test::ScopedPowerMonitorTestSource power_monitor_source;
  586. power_monitor_source.Suspend();
  587. task_environment_.AdvanceClock(kSmallCPUQuantum);
  588. {
  589. WatchHangsInScope expires_instantly(base::TimeDelta{});
  590. task_environment_.AdvanceClock(kSmallCPUQuantum);
  591. TriggerMonitorAndWaitForCompletion();
  592. EXPECT_EQ(2, hang_capture_count_);
  593. EXPECT_EQ("Power suspended", seconds_since_last_power_resume_crash_key_);
  594. }
  595. power_monitor_source.Resume();
  596. constexpr TimeDelta kAfterResumeTime{base::Seconds(5)};
  597. task_environment_.AdvanceClock(kAfterResumeTime);
  598. {
  599. WatchHangsInScope expires_instantly(base::TimeDelta{});
  600. TriggerMonitorAndWaitForCompletion();
  601. EXPECT_EQ(3, hang_capture_count_);
  602. EXPECT_EQ(base::NumberToString(kAfterResumeTime.InSeconds()),
  603. seconds_since_last_power_resume_crash_key_);
  604. }
  605. }
  606. }
  607. namespace {
  608. // Determines how long the HangWatcher will wait between calls to
  609. // Monitor(). Choose a low value so that that successive invocations happens
  610. // fast. This makes tests that wait for monitoring run fast and makes tests that
  611. // expect no monitoring fail fast.
  612. const base::TimeDelta kMonitoringPeriod = base::Milliseconds(1);
  613. // Test if and how often the HangWatcher periodically monitors for hangs.
  614. class HangWatcherPeriodicMonitoringTest : public testing::Test {
  615. public:
  616. HangWatcherPeriodicMonitoringTest() {
  617. hang_watcher_.SetMonitoringPeriodForTesting(kMonitoringPeriod);
  618. hang_watcher_.SetOnHangClosureForTesting(base::BindRepeating(
  619. &WaitableEvent::Signal, base::Unretained(&hang_event_)));
  620. // HangWatcher uses a TickClock to detect how long it slept in between calls
  621. // to Monitor(). Override that clock to control its subjective passage of
  622. // time.
  623. hang_watcher_.SetTickClockForTesting(&test_clock_);
  624. }
  625. HangWatcherPeriodicMonitoringTest(
  626. const HangWatcherPeriodicMonitoringTest& other) = delete;
  627. HangWatcherPeriodicMonitoringTest& operator=(
  628. const HangWatcherPeriodicMonitoringTest& other) = delete;
  629. protected:
  630. // Setup the callback invoked after waiting in HangWatcher to advance the
  631. // tick clock by the desired time delta.
  632. void InstallAfterWaitCallback(base::TimeDelta time_delta) {
  633. hang_watcher_.SetAfterWaitCallbackForTesting(base::BindLambdaForTesting(
  634. [this, time_delta](base::TimeTicks time_before_wait) {
  635. test_clock_.Advance(time_delta);
  636. }));
  637. }
  638. base::SimpleTestTickClock test_clock_;
  639. // Single threaded to avoid ThreadPool WorkerThreads registering. Will run
  640. // delayed tasks created by the tests.
  641. test::SingleThreadTaskEnvironment task_environment_;
  642. std::unique_ptr<base::TickClock> fake_tick_clock_;
  643. HangWatcher hang_watcher_;
  644. // Signaled when a hang is detected.
  645. WaitableEvent hang_event_;
  646. base::ScopedClosureRunner unregister_thread_closure_;
  647. };
  648. } // namespace
  649. // Don't register any threads for hang watching. HangWatcher should not monitor.
  650. TEST_F(HangWatcherPeriodicMonitoringTest,
  651. NoPeriodicMonitoringWithoutRegisteredThreads) {
  652. RunLoop run_loop;
  653. // If a call to HangWatcher::Monitor() takes place the test will instantly
  654. // fail.
  655. hang_watcher_.SetAfterMonitorClosureForTesting(
  656. base::BindLambdaForTesting([&run_loop]() {
  657. ADD_FAILURE() << "Monitoring took place!";
  658. run_loop.Quit();
  659. }));
  660. // Make the HangWatcher tick clock advance by exactly the monitoring period
  661. // after waiting so it will never detect oversleeping between attempts to call
  662. // Monitor(). This would inhibit monitoring and make the test pass for the
  663. // wrong reasons.
  664. InstallAfterWaitCallback(kMonitoringPeriod);
  665. hang_watcher_.Start();
  666. // Unblock the test thread. No thread ever registered after the HangWatcher
  667. // was created in the test's constructor. No monitoring should have taken
  668. // place.
  669. task_environment_.GetMainThreadTaskRunner()->PostDelayedTask(
  670. FROM_HERE, run_loop.QuitClosure(), TestTimeouts::tiny_timeout());
  671. run_loop.Run();
  672. // NOTE:
  673. // A lack of calls could technically also be caused by the HangWatcher thread
  674. // executing too slowly / being descheduled. This is a known limitation.
  675. // It's expected for |TestTimeouts::tiny_timeout()| to be large enough that
  676. // this is rare.
  677. }
  678. // During normal execution periodic monitorings should take place.
  679. TEST_F(HangWatcherPeriodicMonitoringTest, PeriodicCallsTakePlace) {
  680. // HangWatcher::Monitor() will run once right away on thread registration.
  681. // We want to make sure it runs at a couple more times from being scheduled.
  682. constexpr int kMinimumMonitorCount = 3;
  683. RunLoop run_loop;
  684. // Setup the HangWatcher to unblock run_loop when the Monitor() has been
  685. // invoked enough times.
  686. hang_watcher_.SetAfterMonitorClosureForTesting(BarrierClosure(
  687. kMinimumMonitorCount, base::BindLambdaForTesting([&run_loop]() {
  688. // Test condition are confirmed, stop monitoring.
  689. HangWatcher::StopMonitoringForTesting();
  690. // Unblock the test main thread.
  691. run_loop.Quit();
  692. })));
  693. // Make the HangWatcher tick clock advance by exactly the monitoring period
  694. // after waiting so it will never detect oversleeping between attempts to call
  695. // Monitor(). This would inhibit monitoring.
  696. InstallAfterWaitCallback(kMonitoringPeriod);
  697. hang_watcher_.Start();
  698. // Register a thread,
  699. unregister_thread_closure_ =
  700. HangWatcher::RegisterThread(base::HangWatcher::ThreadType::kMainThread);
  701. run_loop.Run();
  702. // No monitored scope means no possible hangs.
  703. ASSERT_FALSE(hang_event_.IsSignaled());
  704. }
  705. // If the HangWatcher detects it slept for longer than expected it will not
  706. // monitor.
  707. TEST_F(HangWatcherPeriodicMonitoringTest, NoMonitorOnOverSleep) {
  708. RunLoop run_loop;
  709. // If a call to HangWatcher::Monitor() takes place the test will instantly
  710. // fail.
  711. hang_watcher_.SetAfterMonitorClosureForTesting(
  712. base::BindLambdaForTesting([&run_loop]() {
  713. ADD_FAILURE() << "Monitoring took place!";
  714. run_loop.Quit();
  715. }));
  716. // Make the HangWatcher tick clock advance so much after waiting that it will
  717. // detect oversleeping every time. This will keep it from monitoring.
  718. InstallAfterWaitCallback(base::Minutes(1));
  719. hang_watcher_.Start();
  720. // Register a thread.
  721. unregister_thread_closure_ =
  722. HangWatcher::RegisterThread(base::HangWatcher::ThreadType::kMainThread);
  723. // Unblock the test thread. All waits were perceived as oversleeping so all
  724. // monitoring was inhibited.
  725. task_environment_.GetMainThreadTaskRunner()->PostDelayedTask(
  726. FROM_HERE, run_loop.QuitClosure(), TestTimeouts::tiny_timeout());
  727. run_loop.Run();
  728. // NOTE: A lack of calls could technically also be caused by the HangWatcher
  729. // thread executing too slowly / being descheduled. This is a known
  730. // limitation. It's expected for |TestTimeouts::tiny_timeout()| to be large
  731. // enough that this happens rarely.
  732. }
  733. namespace {
  734. class WatchHangsInScopeBlockingTest : public testing::Test {
  735. public:
  736. WatchHangsInScopeBlockingTest() {
  737. feature_list_.InitWithFeaturesAndParameters(kFeatureAndParams, {});
  738. hang_watcher_.InitializeOnMainThread(
  739. HangWatcher::ProcessType::kBrowserProcess);
  740. hang_watcher_.SetOnHangClosureForTesting(base::BindLambdaForTesting([&] {
  741. capture_started_.Signal();
  742. // Simulate capturing that takes a long time.
  743. PlatformThread::Sleep(base::Milliseconds(500));
  744. continue_capture_.Wait();
  745. completed_capture_ = true;
  746. }));
  747. hang_watcher_.SetAfterMonitorClosureForTesting(
  748. base::BindLambdaForTesting([&] {
  749. // Simulate monitoring that takes a long time.
  750. PlatformThread::Sleep(base::Milliseconds(500));
  751. completed_monitoring_.Signal();
  752. }));
  753. // Make sure no periodic monitoring takes place.
  754. hang_watcher_.SetMonitoringPeriodForTesting(kVeryLongDelta);
  755. hang_watcher_.Start();
  756. // Register the test main thread for hang watching.
  757. unregister_thread_closure_ =
  758. HangWatcher::RegisterThread(base::HangWatcher::ThreadType::kMainThread);
  759. }
  760. void TearDown() override { hang_watcher_.UnitializeOnMainThreadForTesting(); }
  761. WatchHangsInScopeBlockingTest(const WatchHangsInScopeBlockingTest& other) =
  762. delete;
  763. WatchHangsInScopeBlockingTest& operator=(
  764. const WatchHangsInScopeBlockingTest& other) = delete;
  765. void VerifyScopesDontBlock() {
  766. // Start a WatchHangsInScope that cannot possibly cause a hang to be
  767. // detected.
  768. {
  769. WatchHangsInScope long_scope(kVeryLongDelta);
  770. // Manually trigger a monitoring.
  771. hang_watcher_.SignalMonitorEventForTesting();
  772. // Execution has to continue freely here as no capture is in progress.
  773. }
  774. // Monitoring should not be over yet because the test code should execute
  775. // faster when not blocked.
  776. EXPECT_FALSE(completed_monitoring_.IsSignaled());
  777. // Wait for the full monitoring process to be complete. This is to prove
  778. // that monitoring truly executed and that we raced the signaling.
  779. completed_monitoring_.Wait();
  780. // No hang means no capture.
  781. EXPECT_FALSE(completed_capture_);
  782. }
  783. protected:
  784. base::WaitableEvent capture_started_;
  785. base::WaitableEvent completed_monitoring_;
  786. // The HangWatcher waits on this event via the "on hang" closure when a hang
  787. // is detected.
  788. base::WaitableEvent continue_capture_;
  789. bool completed_capture_{false};
  790. base::test::ScopedFeatureList feature_list_;
  791. HangWatcher hang_watcher_;
  792. base::ScopedClosureRunner unregister_thread_closure_;
  793. };
  794. } // namespace
  795. // Tests that execution is unimpeded by ~WatchHangsInScope() when no capture
  796. // ever takes place.
  797. TEST_F(WatchHangsInScopeBlockingTest, ScopeDoesNotBlocksWithoutCapture) {
  798. // No capture should take place so |continue_capture_| is not signaled to
  799. // create a test hang if one ever does.
  800. VerifyScopesDontBlock();
  801. }
  802. // Test that execution blocks in ~WatchHangsInScope() for a thread under
  803. // watch during the capturing of a hang.
  804. TEST_F(WatchHangsInScopeBlockingTest, ScopeBlocksDuringCapture) {
  805. // The capture completing is not dependent on any test event. Signal to make
  806. // sure the test is not blocked.
  807. continue_capture_.Signal();
  808. // Start a WatchHangsInScope that expires in the past already. Ensures
  809. // that the first monitor will detect a hang.
  810. {
  811. // Start a WatchHangsInScope that expires right away. Ensures that the
  812. // first monitor will detect a hang.
  813. WatchHangsInScope expires_right_away(base::TimeDelta{});
  814. // Manually trigger a monitoring.
  815. hang_watcher_.SignalMonitorEventForTesting();
  816. // Ensure that the hang capturing started.
  817. capture_started_.Wait();
  818. // Execution will get stuck in the outer scope because it can't escape
  819. // ~WatchHangsInScope() if a hang capture is under way.
  820. }
  821. // A hang was in progress so execution should have been blocked in
  822. // BlockWhileCaptureInProgress() until capture finishes.
  823. EXPECT_TRUE(completed_capture_);
  824. completed_monitoring_.Wait();
  825. // Reset expectations
  826. completed_monitoring_.Reset();
  827. capture_started_.Reset();
  828. completed_capture_ = false;
  829. // Verify that scopes don't block just because a capture happened in the past.
  830. VerifyScopesDontBlock();
  831. }
  832. #if BUILDFLAG(IS_MAC) && defined(ARCH_CPU_ARM64)
  833. // Flaky hangs on arm64 Macs: https://crbug.com/1140207
  834. #define MAYBE_NewScopeDoesNotBlockDuringCapture \
  835. DISABLED_NewScopeDoesNotBlockDuringCapture
  836. #else
  837. #define MAYBE_NewScopeDoesNotBlockDuringCapture \
  838. NewScopeDoesNotBlockDuringCapture
  839. #endif
  840. // Test that execution does not block in ~WatchHangsInScope() when the scope
  841. // was created after the start of a capture.
  842. TEST_F(WatchHangsInScopeBlockingTest, MAYBE_NewScopeDoesNotBlockDuringCapture) {
  843. // Start a WatchHangsInScope that expires right away. Ensures that the
  844. // first monitor will detect a hang.
  845. WatchHangsInScope expires_right_away(base::TimeDelta{});
  846. // Manually trigger a monitoring.
  847. hang_watcher_.SignalMonitorEventForTesting();
  848. // Ensure that the hang capturing started.
  849. capture_started_.Wait();
  850. // A scope started once a capture is already under way should not block
  851. // execution.
  852. { WatchHangsInScope also_expires_right_away(base::TimeDelta{}); }
  853. // Wait for the new WatchHangsInScope to be destroyed to let the capture
  854. // finish. If the new scope block waiting for the capture to finish this would
  855. // create a deadlock and the test would hang.
  856. continue_capture_.Signal();
  857. }
  858. namespace internal {
  859. namespace {
  860. constexpr std::array<HangWatchDeadline::Flag, 3> kAllFlags{
  861. {HangWatchDeadline::Flag::kMinValue,
  862. HangWatchDeadline::Flag::kIgnoreCurrentWatchHangsInScope,
  863. HangWatchDeadline::Flag::kShouldBlockOnHang}};
  864. } // namespace
  865. class HangWatchDeadlineTest : public testing::Test {
  866. protected:
  867. void AssertNoFlagsSet() const {
  868. for (HangWatchDeadline::Flag flag : kAllFlags) {
  869. ASSERT_FALSE(deadline_.IsFlagSet(flag));
  870. }
  871. }
  872. // Return a flag mask without one of the flags for test purposes. Use to
  873. // ignore that effect of setting a flag that was just set.
  874. uint64_t FlagsMinus(uint64_t flags, HangWatchDeadline::Flag flag) {
  875. return flags & ~(static_cast<uint64_t>(flag));
  876. }
  877. HangWatchDeadline deadline_;
  878. };
  879. // Verify that the extract functions don't mangle any bits.
  880. TEST_F(HangWatchDeadlineTest, BitsPreservedThroughExtract) {
  881. for (auto bits : {kAllOnes, kAllZeros, kOnesThenZeroes, kZeroesThenOnes}) {
  882. ASSERT_TRUE((HangWatchDeadline::ExtractFlags(bits) |
  883. HangWatchDeadline::ExtractDeadline(bits)) == bits);
  884. }
  885. }
  886. // Verify that setting and clearing a persistent flag works and has no unwanted
  887. // side-effects. Neither the flags nor the deadline change concurrently in this
  888. // test.
  889. TEST_F(HangWatchDeadlineTest, SetAndClearPersistentFlag) {
  890. AssertNoFlagsSet();
  891. // Grab the original values for flags and deadline.
  892. auto [old_flags, old_deadline] = deadline_.GetFlagsAndDeadline();
  893. // Set the flag. Operation cannot fail.
  894. deadline_.SetIgnoreCurrentWatchHangsInScope();
  895. // Get new flags and deadline.
  896. auto [new_flags, new_deadline] = deadline_.GetFlagsAndDeadline();
  897. // Flag was set properly.
  898. ASSERT_TRUE(HangWatchDeadline::IsFlagSet(
  899. HangWatchDeadline::Flag::kIgnoreCurrentWatchHangsInScope, new_flags));
  900. // No side-effect on deadline.
  901. ASSERT_EQ(new_deadline, old_deadline);
  902. // No side-effect on other flags.
  903. ASSERT_EQ(
  904. FlagsMinus(new_flags,
  905. HangWatchDeadline::Flag::kIgnoreCurrentWatchHangsInScope),
  906. old_flags);
  907. // Clear the flag, operation cannot fail.
  908. deadline_.UnsetIgnoreCurrentWatchHangsInScope();
  909. // Update new values.
  910. std::tie(new_flags, new_deadline) = deadline_.GetFlagsAndDeadline();
  911. // All flags back to original state.
  912. ASSERT_EQ(new_flags, old_flags);
  913. // Deadline still unnafected.
  914. ASSERT_EQ(new_deadline, old_deadline);
  915. }
  916. // Verify setting the TimeTicks value works and has no unwanted side-effects.
  917. TEST_F(HangWatchDeadlineTest, SetDeadline) {
  918. TimeTicks ticks;
  919. AssertNoFlagsSet();
  920. ASSERT_NE(deadline_.GetDeadline(), ticks);
  921. // Set the deadline and verify it stuck.
  922. deadline_.SetDeadline(ticks);
  923. ASSERT_EQ(deadline_.GetDeadline(), ticks);
  924. // Only the value was modified, no flags should be set.
  925. AssertNoFlagsSet();
  926. }
  927. // Verify that setting a non-persistent flag (kShouldBlockOnHang)
  928. // when the TimeTicks value changed since calling the flag setting
  929. // function fails and has no side-effects.
  930. TEST_F(HangWatchDeadlineTest, SetShouldBlockOnHangDeadlineChanged) {
  931. AssertNoFlagsSet();
  932. auto [flags, deadline] = deadline_.GetFlagsAndDeadline();
  933. // Simulate value change. Flags are constant.
  934. const base::TimeTicks new_deadline =
  935. base::TimeTicks::FromInternalValue(kArbitraryDeadline);
  936. ASSERT_NE(deadline, new_deadline);
  937. deadline_.SetSwitchBitsClosureForTesting(
  938. base::BindLambdaForTesting([]() { return kArbitraryDeadline; }));
  939. // kShouldBlockOnHangs does not persist through value change.
  940. ASSERT_FALSE(deadline_.SetShouldBlockOnHang(flags, deadline));
  941. // Flag was not applied.
  942. ASSERT_FALSE(
  943. deadline_.IsFlagSet(HangWatchDeadline::Flag::kShouldBlockOnHang));
  944. // New value that was changed concurrently is preserved.
  945. ASSERT_EQ(deadline_.GetDeadline(), new_deadline);
  946. }
  947. // Verify that clearing a persistent (kIgnoreCurrentWatchHangsInScope) when
  948. // the value changed succeeds and has non side-effects.
  949. TEST_F(HangWatchDeadlineTest, ClearIgnoreHangsDeadlineChanged) {
  950. AssertNoFlagsSet();
  951. auto [flags, deadline] = deadline_.GetFlagsAndDeadline();
  952. deadline_.SetIgnoreCurrentWatchHangsInScope();
  953. std::tie(flags, deadline) = deadline_.GetFlagsAndDeadline();
  954. ASSERT_TRUE(HangWatchDeadline::IsFlagSet(
  955. HangWatchDeadline::Flag::kIgnoreCurrentWatchHangsInScope, flags));
  956. // Simulate deadline change. Flags are constant.
  957. const base::TimeTicks new_deadline =
  958. base::TimeTicks::FromInternalValue(kArbitraryDeadline);
  959. ASSERT_NE(deadline, new_deadline);
  960. deadline_.SetSwitchBitsClosureForTesting(base::BindLambdaForTesting([]() {
  961. return static_cast<uint64_t>(HangWatchDeadline::Flag::kShouldBlockOnHang) |
  962. kArbitraryDeadline;
  963. }));
  964. // Clearing kIgnoreHang is unaffected by deadline or flags change.
  965. deadline_.UnsetIgnoreCurrentWatchHangsInScope();
  966. ASSERT_FALSE(deadline_.IsFlagSet(
  967. HangWatchDeadline::Flag::kIgnoreCurrentWatchHangsInScope));
  968. // New deadline that was changed concurrently is preserved.
  969. ASSERT_TRUE(deadline_.IsFlagSet(HangWatchDeadline::Flag::kShouldBlockOnHang));
  970. ASSERT_EQ(deadline_.GetDeadline(), new_deadline);
  971. }
  972. // Verify that setting a persistent (kIgnoreCurrentWatchHangsInScope) when
  973. // the deadline or flags changed succeeds and has non side-effects.
  974. TEST_F(HangWatchDeadlineTest,
  975. SetIgnoreCurrentHangWatchScopeEnableDeadlineChangedd) {
  976. AssertNoFlagsSet();
  977. auto [flags, deadline] = deadline_.GetFlagsAndDeadline();
  978. // Simulate deadline change. Flags are constant.
  979. const base::TimeTicks new_deadline =
  980. base::TimeTicks::FromInternalValue(kArbitraryDeadline);
  981. ASSERT_NE(deadline, new_deadline);
  982. deadline_.SetSwitchBitsClosureForTesting(base::BindLambdaForTesting([]() {
  983. return static_cast<uint64_t>(HangWatchDeadline::Flag::kShouldBlockOnHang) |
  984. kArbitraryDeadline;
  985. }));
  986. // kIgnoreHang persists through value change.
  987. deadline_.SetIgnoreCurrentWatchHangsInScope();
  988. ASSERT_TRUE(deadline_.IsFlagSet(
  989. HangWatchDeadline::Flag::kIgnoreCurrentWatchHangsInScope));
  990. // New deadline and flags that changed concurrently are preserved.
  991. ASSERT_TRUE(deadline_.IsFlagSet(HangWatchDeadline::Flag::kShouldBlockOnHang));
  992. ASSERT_EQ(deadline_.GetDeadline(), new_deadline);
  993. }
  994. // Setting a new deadline should wipe flags that a not persistent.
  995. // Persistent flags should not be disturbed.
  996. TEST_F(HangWatchDeadlineTest, SetDeadlineWipesFlags) {
  997. auto [flags, deadline] = deadline_.GetFlagsAndDeadline();
  998. ASSERT_TRUE(deadline_.SetShouldBlockOnHang(flags, deadline));
  999. ASSERT_TRUE(deadline_.IsFlagSet(HangWatchDeadline::Flag::kShouldBlockOnHang));
  1000. std::tie(flags, deadline) = deadline_.GetFlagsAndDeadline();
  1001. deadline_.SetIgnoreCurrentWatchHangsInScope();
  1002. ASSERT_TRUE(deadline_.IsFlagSet(
  1003. HangWatchDeadline::Flag::kIgnoreCurrentWatchHangsInScope));
  1004. // Change the deadline.
  1005. deadline_.SetDeadline(TimeTicks{});
  1006. ASSERT_EQ(deadline_.GetDeadline(), TimeTicks{});
  1007. // Verify the persistent flag stuck and the non-persistent one was unset.
  1008. ASSERT_FALSE(
  1009. deadline_.IsFlagSet(HangWatchDeadline::Flag::kShouldBlockOnHang));
  1010. ASSERT_TRUE(deadline_.IsFlagSet(
  1011. HangWatchDeadline::Flag::kIgnoreCurrentWatchHangsInScope));
  1012. }
  1013. } // namespace internal
  1014. } // namespace base