• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 The Chromium Authors
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/test/scoped_run_loop_timeout.h"
6 
7 #include "base/functional/bind.h"
8 #include "base/functional/callback_helpers.h"
9 #include "base/location.h"
10 #include "base/logging.h"
11 #include "base/strings/strcat.h"
12 #include "base/time/time.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14 
15 namespace base {
16 namespace test {
17 
18 namespace {
19 
20 bool g_add_gtest_failure_on_timeout = false;
21 
TimeoutMessage(const RepeatingCallback<std::string ()> & get_log,const Location & timeout_enabled_from_here)22 std::string TimeoutMessage(const RepeatingCallback<std::string()>& get_log,
23                            const Location& timeout_enabled_from_here) {
24   std::string message = "RunLoop::Run() timed out. Timeout set at ";
25   message += timeout_enabled_from_here.ToString() + ".";
26   if (get_log)
27     StrAppend(&message, {"\n", get_log.Run()});
28   return message;
29 }
30 
31 }  // namespace
32 
ScopedRunLoopTimeout(const Location & from_here,TimeDelta timeout)33 ScopedRunLoopTimeout::ScopedRunLoopTimeout(const Location& from_here,
34                                            TimeDelta timeout)
35     : ScopedRunLoopTimeout(from_here, timeout, NullCallback()) {}
36 
~ScopedRunLoopTimeout()37 ScopedRunLoopTimeout::~ScopedRunLoopTimeout() {
38   RunLoop::SetTimeoutForCurrentThread(nested_timeout_);
39 }
40 
ScopedRunLoopTimeout(const Location & timeout_enabled_from_here,TimeDelta timeout,RepeatingCallback<std::string ()> on_timeout_log)41 ScopedRunLoopTimeout::ScopedRunLoopTimeout(
42     const Location& timeout_enabled_from_here,
43     TimeDelta timeout,
44     RepeatingCallback<std::string()> on_timeout_log)
45     : nested_timeout_(RunLoop::GetTimeoutForCurrentThread()) {
46   DCHECK_GT(timeout, TimeDelta());
47   run_timeout_.timeout = timeout;
48 
49   if (g_add_gtest_failure_on_timeout) {
50     run_timeout_.on_timeout = BindRepeating(
51         [](const Location& timeout_enabled_from_here,
52            RepeatingCallback<std::string()> on_timeout_log,
53            const Location& run_from_here) {
54           GTEST_FAIL_AT(run_from_here.file_name(), run_from_here.line_number())
55               << TimeoutMessage(on_timeout_log, timeout_enabled_from_here);
56         },
57         timeout_enabled_from_here, std::move(on_timeout_log));
58   } else {
59     run_timeout_.on_timeout = BindRepeating(
60         [](const Location& timeout_enabled_from_here,
61            RepeatingCallback<std::string()> on_timeout_log,
62            const Location& run_from_here) {
63           std::string message =
64               TimeoutMessage(on_timeout_log, timeout_enabled_from_here);
65           logging::LogMessage(run_from_here.file_name(),
66                               run_from_here.line_number(), message.data());
67         },
68         timeout_enabled_from_here, std::move(on_timeout_log));
69   }
70 
71   RunLoop::SetTimeoutForCurrentThread(&run_timeout_);
72 }
73 
74 // static
ExistsForCurrentThread()75 bool ScopedRunLoopTimeout::ExistsForCurrentThread() {
76   return RunLoop::GetTimeoutForCurrentThread() != nullptr;
77 }
78 
79 // static
SetAddGTestFailureOnTimeout()80 void ScopedRunLoopTimeout::SetAddGTestFailureOnTimeout() {
81   g_add_gtest_failure_on_timeout = true;
82 }
83 
84 // static
85 const RunLoop::RunLoopTimeout*
GetTimeoutForCurrentThread()86 ScopedRunLoopTimeout::GetTimeoutForCurrentThread() {
87   return RunLoop::GetTimeoutForCurrentThread();
88 }
89 
ScopedDisableRunLoopTimeout()90 ScopedDisableRunLoopTimeout::ScopedDisableRunLoopTimeout()
91     : nested_timeout_(RunLoop::GetTimeoutForCurrentThread()) {
92   RunLoop::SetTimeoutForCurrentThread(nullptr);
93 }
94 
~ScopedDisableRunLoopTimeout()95 ScopedDisableRunLoopTimeout::~ScopedDisableRunLoopTimeout() {
96   RunLoop::SetTimeoutForCurrentThread(nested_timeout_);
97 }
98 
99 }  // namespace test
100 }  // namespace base
101