xref: /aosp_15_r20/external/libchrome/base/lazy_instance_unittest.cc (revision 635a864187cb8b6c713ff48b7e790a6b21769273)
1*635a8641SAndroid Build Coastguard Worker // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2*635a8641SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*635a8641SAndroid Build Coastguard Worker // found in the LICENSE file.
4*635a8641SAndroid Build Coastguard Worker 
5*635a8641SAndroid Build Coastguard Worker #include <stddef.h>
6*635a8641SAndroid Build Coastguard Worker 
7*635a8641SAndroid Build Coastguard Worker #include <memory>
8*635a8641SAndroid Build Coastguard Worker #include <vector>
9*635a8641SAndroid Build Coastguard Worker 
10*635a8641SAndroid Build Coastguard Worker #include "base/at_exit.h"
11*635a8641SAndroid Build Coastguard Worker #include "base/atomic_sequence_num.h"
12*635a8641SAndroid Build Coastguard Worker #include "base/atomicops.h"
13*635a8641SAndroid Build Coastguard Worker #include "base/barrier_closure.h"
14*635a8641SAndroid Build Coastguard Worker #include "base/bind.h"
15*635a8641SAndroid Build Coastguard Worker #include "base/lazy_instance.h"
16*635a8641SAndroid Build Coastguard Worker #include "base/sys_info.h"
17*635a8641SAndroid Build Coastguard Worker #include "base/threading/platform_thread.h"
18*635a8641SAndroid Build Coastguard Worker #include "base/threading/simple_thread.h"
19*635a8641SAndroid Build Coastguard Worker #include "base/time/time.h"
20*635a8641SAndroid Build Coastguard Worker #include "build/build_config.h"
21*635a8641SAndroid Build Coastguard Worker #include "testing/gtest/include/gtest/gtest.h"
22*635a8641SAndroid Build Coastguard Worker 
23*635a8641SAndroid Build Coastguard Worker namespace {
24*635a8641SAndroid Build Coastguard Worker 
25*635a8641SAndroid Build Coastguard Worker base::AtomicSequenceNumber constructed_seq_;
26*635a8641SAndroid Build Coastguard Worker base::AtomicSequenceNumber destructed_seq_;
27*635a8641SAndroid Build Coastguard Worker 
28*635a8641SAndroid Build Coastguard Worker class ConstructAndDestructLogger {
29*635a8641SAndroid Build Coastguard Worker  public:
ConstructAndDestructLogger()30*635a8641SAndroid Build Coastguard Worker   ConstructAndDestructLogger() {
31*635a8641SAndroid Build Coastguard Worker     constructed_seq_.GetNext();
32*635a8641SAndroid Build Coastguard Worker   }
~ConstructAndDestructLogger()33*635a8641SAndroid Build Coastguard Worker   ~ConstructAndDestructLogger() {
34*635a8641SAndroid Build Coastguard Worker     destructed_seq_.GetNext();
35*635a8641SAndroid Build Coastguard Worker   }
36*635a8641SAndroid Build Coastguard Worker 
37*635a8641SAndroid Build Coastguard Worker  private:
38*635a8641SAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(ConstructAndDestructLogger);
39*635a8641SAndroid Build Coastguard Worker };
40*635a8641SAndroid Build Coastguard Worker 
41*635a8641SAndroid Build Coastguard Worker class SlowConstructor {
42*635a8641SAndroid Build Coastguard Worker  public:
SlowConstructor()43*635a8641SAndroid Build Coastguard Worker   SlowConstructor() : some_int_(0) {
44*635a8641SAndroid Build Coastguard Worker     // Sleep for 1 second to try to cause a race.
45*635a8641SAndroid Build Coastguard Worker     base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(1));
46*635a8641SAndroid Build Coastguard Worker     ++constructed;
47*635a8641SAndroid Build Coastguard Worker     some_int_ = 12;
48*635a8641SAndroid Build Coastguard Worker   }
some_int() const49*635a8641SAndroid Build Coastguard Worker   int some_int() const { return some_int_; }
50*635a8641SAndroid Build Coastguard Worker 
51*635a8641SAndroid Build Coastguard Worker   static int constructed;
52*635a8641SAndroid Build Coastguard Worker  private:
53*635a8641SAndroid Build Coastguard Worker   int some_int_;
54*635a8641SAndroid Build Coastguard Worker 
55*635a8641SAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(SlowConstructor);
56*635a8641SAndroid Build Coastguard Worker };
57*635a8641SAndroid Build Coastguard Worker 
58*635a8641SAndroid Build Coastguard Worker // static
59*635a8641SAndroid Build Coastguard Worker int SlowConstructor::constructed = 0;
60*635a8641SAndroid Build Coastguard Worker 
61*635a8641SAndroid Build Coastguard Worker class SlowDelegate : public base::DelegateSimpleThread::Delegate {
62*635a8641SAndroid Build Coastguard Worker  public:
SlowDelegate(base::LazyInstance<SlowConstructor>::DestructorAtExit * lazy)63*635a8641SAndroid Build Coastguard Worker   explicit SlowDelegate(
64*635a8641SAndroid Build Coastguard Worker       base::LazyInstance<SlowConstructor>::DestructorAtExit* lazy)
65*635a8641SAndroid Build Coastguard Worker       : lazy_(lazy) {}
66*635a8641SAndroid Build Coastguard Worker 
Run()67*635a8641SAndroid Build Coastguard Worker   void Run() override {
68*635a8641SAndroid Build Coastguard Worker     EXPECT_EQ(12, lazy_->Get().some_int());
69*635a8641SAndroid Build Coastguard Worker     EXPECT_EQ(12, lazy_->Pointer()->some_int());
70*635a8641SAndroid Build Coastguard Worker   }
71*635a8641SAndroid Build Coastguard Worker 
72*635a8641SAndroid Build Coastguard Worker  private:
73*635a8641SAndroid Build Coastguard Worker   base::LazyInstance<SlowConstructor>::DestructorAtExit* lazy_;
74*635a8641SAndroid Build Coastguard Worker 
75*635a8641SAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(SlowDelegate);
76*635a8641SAndroid Build Coastguard Worker };
77*635a8641SAndroid Build Coastguard Worker 
78*635a8641SAndroid Build Coastguard Worker }  // namespace
79*635a8641SAndroid Build Coastguard Worker 
80*635a8641SAndroid Build Coastguard Worker base::LazyInstance<ConstructAndDestructLogger>::DestructorAtExit lazy_logger =
81*635a8641SAndroid Build Coastguard Worker     LAZY_INSTANCE_INITIALIZER;
82*635a8641SAndroid Build Coastguard Worker 
TEST(LazyInstanceTest,Basic)83*635a8641SAndroid Build Coastguard Worker TEST(LazyInstanceTest, Basic) {
84*635a8641SAndroid Build Coastguard Worker   {
85*635a8641SAndroid Build Coastguard Worker     base::ShadowingAtExitManager shadow;
86*635a8641SAndroid Build Coastguard Worker 
87*635a8641SAndroid Build Coastguard Worker     EXPECT_FALSE(lazy_logger.IsCreated());
88*635a8641SAndroid Build Coastguard Worker     EXPECT_EQ(0, constructed_seq_.GetNext());
89*635a8641SAndroid Build Coastguard Worker     EXPECT_EQ(0, destructed_seq_.GetNext());
90*635a8641SAndroid Build Coastguard Worker 
91*635a8641SAndroid Build Coastguard Worker     lazy_logger.Get();
92*635a8641SAndroid Build Coastguard Worker     EXPECT_TRUE(lazy_logger.IsCreated());
93*635a8641SAndroid Build Coastguard Worker     EXPECT_EQ(2, constructed_seq_.GetNext());
94*635a8641SAndroid Build Coastguard Worker     EXPECT_EQ(1, destructed_seq_.GetNext());
95*635a8641SAndroid Build Coastguard Worker 
96*635a8641SAndroid Build Coastguard Worker     lazy_logger.Pointer();
97*635a8641SAndroid Build Coastguard Worker     EXPECT_TRUE(lazy_logger.IsCreated());
98*635a8641SAndroid Build Coastguard Worker     EXPECT_EQ(3, constructed_seq_.GetNext());
99*635a8641SAndroid Build Coastguard Worker     EXPECT_EQ(2, destructed_seq_.GetNext());
100*635a8641SAndroid Build Coastguard Worker   }
101*635a8641SAndroid Build Coastguard Worker   EXPECT_FALSE(lazy_logger.IsCreated());
102*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(4, constructed_seq_.GetNext());
103*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(4, destructed_seq_.GetNext());
104*635a8641SAndroid Build Coastguard Worker }
105*635a8641SAndroid Build Coastguard Worker 
106*635a8641SAndroid Build Coastguard Worker base::LazyInstance<SlowConstructor>::DestructorAtExit lazy_slow =
107*635a8641SAndroid Build Coastguard Worker     LAZY_INSTANCE_INITIALIZER;
108*635a8641SAndroid Build Coastguard Worker 
TEST(LazyInstanceTest,ConstructorThreadSafety)109*635a8641SAndroid Build Coastguard Worker TEST(LazyInstanceTest, ConstructorThreadSafety) {
110*635a8641SAndroid Build Coastguard Worker   {
111*635a8641SAndroid Build Coastguard Worker     base::ShadowingAtExitManager shadow;
112*635a8641SAndroid Build Coastguard Worker 
113*635a8641SAndroid Build Coastguard Worker     SlowDelegate delegate(&lazy_slow);
114*635a8641SAndroid Build Coastguard Worker     EXPECT_EQ(0, SlowConstructor::constructed);
115*635a8641SAndroid Build Coastguard Worker 
116*635a8641SAndroid Build Coastguard Worker     base::DelegateSimpleThreadPool pool("lazy_instance_cons", 5);
117*635a8641SAndroid Build Coastguard Worker     pool.AddWork(&delegate, 20);
118*635a8641SAndroid Build Coastguard Worker     EXPECT_EQ(0, SlowConstructor::constructed);
119*635a8641SAndroid Build Coastguard Worker 
120*635a8641SAndroid Build Coastguard Worker     pool.Start();
121*635a8641SAndroid Build Coastguard Worker     pool.JoinAll();
122*635a8641SAndroid Build Coastguard Worker     EXPECT_EQ(1, SlowConstructor::constructed);
123*635a8641SAndroid Build Coastguard Worker   }
124*635a8641SAndroid Build Coastguard Worker }
125*635a8641SAndroid Build Coastguard Worker 
126*635a8641SAndroid Build Coastguard Worker namespace {
127*635a8641SAndroid Build Coastguard Worker 
128*635a8641SAndroid Build Coastguard Worker // DeleteLogger is an object which sets a flag when it's destroyed.
129*635a8641SAndroid Build Coastguard Worker // It accepts a bool* and sets the bool to true when the dtor runs.
130*635a8641SAndroid Build Coastguard Worker class DeleteLogger {
131*635a8641SAndroid Build Coastguard Worker  public:
DeleteLogger()132*635a8641SAndroid Build Coastguard Worker   DeleteLogger() : deleted_(nullptr) {}
~DeleteLogger()133*635a8641SAndroid Build Coastguard Worker   ~DeleteLogger() { *deleted_ = true; }
134*635a8641SAndroid Build Coastguard Worker 
SetDeletedPtr(bool * deleted)135*635a8641SAndroid Build Coastguard Worker   void SetDeletedPtr(bool* deleted) {
136*635a8641SAndroid Build Coastguard Worker     deleted_ = deleted;
137*635a8641SAndroid Build Coastguard Worker   }
138*635a8641SAndroid Build Coastguard Worker 
139*635a8641SAndroid Build Coastguard Worker  private:
140*635a8641SAndroid Build Coastguard Worker   bool* deleted_;
141*635a8641SAndroid Build Coastguard Worker };
142*635a8641SAndroid Build Coastguard Worker 
143*635a8641SAndroid Build Coastguard Worker }  // anonymous namespace
144*635a8641SAndroid Build Coastguard Worker 
TEST(LazyInstanceTest,LeakyLazyInstance)145*635a8641SAndroid Build Coastguard Worker TEST(LazyInstanceTest, LeakyLazyInstance) {
146*635a8641SAndroid Build Coastguard Worker   // Check that using a plain LazyInstance causes the dtor to run
147*635a8641SAndroid Build Coastguard Worker   // when the AtExitManager finishes.
148*635a8641SAndroid Build Coastguard Worker   bool deleted1 = false;
149*635a8641SAndroid Build Coastguard Worker   {
150*635a8641SAndroid Build Coastguard Worker     base::ShadowingAtExitManager shadow;
151*635a8641SAndroid Build Coastguard Worker     static base::LazyInstance<DeleteLogger>::DestructorAtExit test =
152*635a8641SAndroid Build Coastguard Worker         LAZY_INSTANCE_INITIALIZER;
153*635a8641SAndroid Build Coastguard Worker     test.Get().SetDeletedPtr(&deleted1);
154*635a8641SAndroid Build Coastguard Worker   }
155*635a8641SAndroid Build Coastguard Worker   EXPECT_TRUE(deleted1);
156*635a8641SAndroid Build Coastguard Worker 
157*635a8641SAndroid Build Coastguard Worker   // Check that using a *leaky* LazyInstance makes the dtor not run
158*635a8641SAndroid Build Coastguard Worker   // when the AtExitManager finishes.
159*635a8641SAndroid Build Coastguard Worker   bool deleted2 = false;
160*635a8641SAndroid Build Coastguard Worker   {
161*635a8641SAndroid Build Coastguard Worker     base::ShadowingAtExitManager shadow;
162*635a8641SAndroid Build Coastguard Worker     static base::LazyInstance<DeleteLogger>::Leaky
163*635a8641SAndroid Build Coastguard Worker         test = LAZY_INSTANCE_INITIALIZER;
164*635a8641SAndroid Build Coastguard Worker     test.Get().SetDeletedPtr(&deleted2);
165*635a8641SAndroid Build Coastguard Worker   }
166*635a8641SAndroid Build Coastguard Worker   EXPECT_FALSE(deleted2);
167*635a8641SAndroid Build Coastguard Worker }
168*635a8641SAndroid Build Coastguard Worker 
169*635a8641SAndroid Build Coastguard Worker namespace {
170*635a8641SAndroid Build Coastguard Worker 
171*635a8641SAndroid Build Coastguard Worker template <size_t alignment>
172*635a8641SAndroid Build Coastguard Worker class AlignedData {
173*635a8641SAndroid Build Coastguard Worker  public:
174*635a8641SAndroid Build Coastguard Worker   AlignedData() = default;
175*635a8641SAndroid Build Coastguard Worker   ~AlignedData() = default;
176*635a8641SAndroid Build Coastguard Worker   alignas(alignment) char data_[alignment];
177*635a8641SAndroid Build Coastguard Worker };
178*635a8641SAndroid Build Coastguard Worker 
179*635a8641SAndroid Build Coastguard Worker }  // namespace
180*635a8641SAndroid Build Coastguard Worker 
181*635a8641SAndroid Build Coastguard Worker #define EXPECT_ALIGNED(ptr, align) \
182*635a8641SAndroid Build Coastguard Worker     EXPECT_EQ(0u, reinterpret_cast<uintptr_t>(ptr) & (align - 1))
183*635a8641SAndroid Build Coastguard Worker 
TEST(LazyInstanceTest,Alignment)184*635a8641SAndroid Build Coastguard Worker TEST(LazyInstanceTest, Alignment) {
185*635a8641SAndroid Build Coastguard Worker   using base::LazyInstance;
186*635a8641SAndroid Build Coastguard Worker 
187*635a8641SAndroid Build Coastguard Worker   // Create some static instances with increasing sizes and alignment
188*635a8641SAndroid Build Coastguard Worker   // requirements. By ordering this way, the linker will need to do some work to
189*635a8641SAndroid Build Coastguard Worker   // ensure proper alignment of the static data.
190*635a8641SAndroid Build Coastguard Worker   static LazyInstance<AlignedData<4>>::DestructorAtExit align4 =
191*635a8641SAndroid Build Coastguard Worker       LAZY_INSTANCE_INITIALIZER;
192*635a8641SAndroid Build Coastguard Worker   static LazyInstance<AlignedData<32>>::DestructorAtExit align32 =
193*635a8641SAndroid Build Coastguard Worker       LAZY_INSTANCE_INITIALIZER;
194*635a8641SAndroid Build Coastguard Worker   static LazyInstance<AlignedData<4096>>::DestructorAtExit align4096 =
195*635a8641SAndroid Build Coastguard Worker       LAZY_INSTANCE_INITIALIZER;
196*635a8641SAndroid Build Coastguard Worker 
197*635a8641SAndroid Build Coastguard Worker   EXPECT_ALIGNED(align4.Pointer(), 4);
198*635a8641SAndroid Build Coastguard Worker   EXPECT_ALIGNED(align32.Pointer(), 32);
199*635a8641SAndroid Build Coastguard Worker   EXPECT_ALIGNED(align4096.Pointer(), 4096);
200*635a8641SAndroid Build Coastguard Worker }
201*635a8641SAndroid Build Coastguard Worker 
202*635a8641SAndroid Build Coastguard Worker namespace {
203*635a8641SAndroid Build Coastguard Worker 
204*635a8641SAndroid Build Coastguard Worker // A class whose constructor busy-loops until it is told to complete
205*635a8641SAndroid Build Coastguard Worker // construction.
206*635a8641SAndroid Build Coastguard Worker class BlockingConstructor {
207*635a8641SAndroid Build Coastguard Worker  public:
BlockingConstructor()208*635a8641SAndroid Build Coastguard Worker   BlockingConstructor() {
209*635a8641SAndroid Build Coastguard Worker     EXPECT_FALSE(WasConstructorCalled());
210*635a8641SAndroid Build Coastguard Worker     base::subtle::NoBarrier_Store(&constructor_called_, 1);
211*635a8641SAndroid Build Coastguard Worker     EXPECT_TRUE(WasConstructorCalled());
212*635a8641SAndroid Build Coastguard Worker     while (!base::subtle::NoBarrier_Load(&complete_construction_))
213*635a8641SAndroid Build Coastguard Worker       base::PlatformThread::YieldCurrentThread();
214*635a8641SAndroid Build Coastguard Worker     done_construction_ = true;
215*635a8641SAndroid Build Coastguard Worker   }
216*635a8641SAndroid Build Coastguard Worker 
~BlockingConstructor()217*635a8641SAndroid Build Coastguard Worker   ~BlockingConstructor() {
218*635a8641SAndroid Build Coastguard Worker     // Restore static state for the next test.
219*635a8641SAndroid Build Coastguard Worker     base::subtle::NoBarrier_Store(&constructor_called_, 0);
220*635a8641SAndroid Build Coastguard Worker     base::subtle::NoBarrier_Store(&complete_construction_, 0);
221*635a8641SAndroid Build Coastguard Worker   }
222*635a8641SAndroid Build Coastguard Worker 
223*635a8641SAndroid Build Coastguard Worker   // Returns true if BlockingConstructor() was entered.
WasConstructorCalled()224*635a8641SAndroid Build Coastguard Worker   static bool WasConstructorCalled() {
225*635a8641SAndroid Build Coastguard Worker     return base::subtle::NoBarrier_Load(&constructor_called_);
226*635a8641SAndroid Build Coastguard Worker   }
227*635a8641SAndroid Build Coastguard Worker 
228*635a8641SAndroid Build Coastguard Worker   // Instructs BlockingConstructor() that it may now unblock its construction.
CompleteConstructionNow()229*635a8641SAndroid Build Coastguard Worker   static void CompleteConstructionNow() {
230*635a8641SAndroid Build Coastguard Worker     base::subtle::NoBarrier_Store(&complete_construction_, 1);
231*635a8641SAndroid Build Coastguard Worker   }
232*635a8641SAndroid Build Coastguard Worker 
done_construction()233*635a8641SAndroid Build Coastguard Worker   bool done_construction() { return done_construction_; }
234*635a8641SAndroid Build Coastguard Worker 
235*635a8641SAndroid Build Coastguard Worker  private:
236*635a8641SAndroid Build Coastguard Worker   // Use Atomic32 instead of AtomicFlag for them to be trivially initialized.
237*635a8641SAndroid Build Coastguard Worker   static base::subtle::Atomic32 constructor_called_;
238*635a8641SAndroid Build Coastguard Worker   static base::subtle::Atomic32 complete_construction_;
239*635a8641SAndroid Build Coastguard Worker 
240*635a8641SAndroid Build Coastguard Worker   bool done_construction_ = false;
241*635a8641SAndroid Build Coastguard Worker 
242*635a8641SAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(BlockingConstructor);
243*635a8641SAndroid Build Coastguard Worker };
244*635a8641SAndroid Build Coastguard Worker 
245*635a8641SAndroid Build Coastguard Worker // A SimpleThread running at |thread_priority| which invokes |before_get|
246*635a8641SAndroid Build Coastguard Worker // (optional) and then invokes Get() on the LazyInstance it's assigned.
247*635a8641SAndroid Build Coastguard Worker class BlockingConstructorThread : public base::SimpleThread {
248*635a8641SAndroid Build Coastguard Worker  public:
BlockingConstructorThread(base::ThreadPriority thread_priority,base::LazyInstance<BlockingConstructor>::DestructorAtExit * lazy,base::OnceClosure before_get)249*635a8641SAndroid Build Coastguard Worker   BlockingConstructorThread(
250*635a8641SAndroid Build Coastguard Worker       base::ThreadPriority thread_priority,
251*635a8641SAndroid Build Coastguard Worker       base::LazyInstance<BlockingConstructor>::DestructorAtExit* lazy,
252*635a8641SAndroid Build Coastguard Worker       base::OnceClosure before_get)
253*635a8641SAndroid Build Coastguard Worker       : SimpleThread("BlockingConstructorThread", Options(thread_priority)),
254*635a8641SAndroid Build Coastguard Worker         lazy_(lazy),
255*635a8641SAndroid Build Coastguard Worker         before_get_(std::move(before_get)) {}
256*635a8641SAndroid Build Coastguard Worker 
Run()257*635a8641SAndroid Build Coastguard Worker   void Run() override {
258*635a8641SAndroid Build Coastguard Worker     if (before_get_)
259*635a8641SAndroid Build Coastguard Worker       std::move(before_get_).Run();
260*635a8641SAndroid Build Coastguard Worker     EXPECT_TRUE(lazy_->Get().done_construction());
261*635a8641SAndroid Build Coastguard Worker   }
262*635a8641SAndroid Build Coastguard Worker 
263*635a8641SAndroid Build Coastguard Worker  private:
264*635a8641SAndroid Build Coastguard Worker   base::LazyInstance<BlockingConstructor>::DestructorAtExit* lazy_;
265*635a8641SAndroid Build Coastguard Worker   base::OnceClosure before_get_;
266*635a8641SAndroid Build Coastguard Worker 
267*635a8641SAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(BlockingConstructorThread);
268*635a8641SAndroid Build Coastguard Worker };
269*635a8641SAndroid Build Coastguard Worker 
270*635a8641SAndroid Build Coastguard Worker // static
271*635a8641SAndroid Build Coastguard Worker base::subtle::Atomic32 BlockingConstructor::constructor_called_ = 0;
272*635a8641SAndroid Build Coastguard Worker // static
273*635a8641SAndroid Build Coastguard Worker base::subtle::Atomic32 BlockingConstructor::complete_construction_ = 0;
274*635a8641SAndroid Build Coastguard Worker 
275*635a8641SAndroid Build Coastguard Worker base::LazyInstance<BlockingConstructor>::DestructorAtExit lazy_blocking =
276*635a8641SAndroid Build Coastguard Worker     LAZY_INSTANCE_INITIALIZER;
277*635a8641SAndroid Build Coastguard Worker 
278*635a8641SAndroid Build Coastguard Worker }  // namespace
279*635a8641SAndroid Build Coastguard Worker 
280*635a8641SAndroid Build Coastguard Worker // Tests that if the thread assigned to construct the LazyInstance runs at
281*635a8641SAndroid Build Coastguard Worker // background priority : the foreground threads will yield to it enough for it
282*635a8641SAndroid Build Coastguard Worker // to eventually complete construction.
283*635a8641SAndroid Build Coastguard Worker // This is a regression test for https://crbug.com/797129.
TEST(LazyInstanceTest,PriorityInversionAtInitializationResolves)284*635a8641SAndroid Build Coastguard Worker TEST(LazyInstanceTest, PriorityInversionAtInitializationResolves) {
285*635a8641SAndroid Build Coastguard Worker   base::TimeTicks test_begin = base::TimeTicks::Now();
286*635a8641SAndroid Build Coastguard Worker 
287*635a8641SAndroid Build Coastguard Worker   // Construct BlockingConstructor from a background thread.
288*635a8641SAndroid Build Coastguard Worker   BlockingConstructorThread background_getter(
289*635a8641SAndroid Build Coastguard Worker       base::ThreadPriority::BACKGROUND, &lazy_blocking, base::OnceClosure());
290*635a8641SAndroid Build Coastguard Worker   background_getter.Start();
291*635a8641SAndroid Build Coastguard Worker 
292*635a8641SAndroid Build Coastguard Worker   while (!BlockingConstructor::WasConstructorCalled())
293*635a8641SAndroid Build Coastguard Worker     base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(1));
294*635a8641SAndroid Build Coastguard Worker 
295*635a8641SAndroid Build Coastguard Worker   // Spin 4 foreground thread per core contending to get the already under
296*635a8641SAndroid Build Coastguard Worker   // construction LazyInstance. When they are all running and poking at it :
297*635a8641SAndroid Build Coastguard Worker   // allow the background thread to complete its work.
298*635a8641SAndroid Build Coastguard Worker   const int kNumForegroundThreads = 4 * base::SysInfo::NumberOfProcessors();
299*635a8641SAndroid Build Coastguard Worker   std::vector<std::unique_ptr<base::SimpleThread>> foreground_threads;
300*635a8641SAndroid Build Coastguard Worker   base::RepeatingClosure foreground_thread_ready_callback =
301*635a8641SAndroid Build Coastguard Worker       base::BarrierClosure(
302*635a8641SAndroid Build Coastguard Worker           kNumForegroundThreads,
303*635a8641SAndroid Build Coastguard Worker           base::BindOnce(&BlockingConstructor::CompleteConstructionNow));
304*635a8641SAndroid Build Coastguard Worker   for (int i = 0; i < kNumForegroundThreads; ++i) {
305*635a8641SAndroid Build Coastguard Worker     foreground_threads.push_back(std::make_unique<BlockingConstructorThread>(
306*635a8641SAndroid Build Coastguard Worker         base::ThreadPriority::NORMAL, &lazy_blocking,
307*635a8641SAndroid Build Coastguard Worker         foreground_thread_ready_callback));
308*635a8641SAndroid Build Coastguard Worker     foreground_threads.back()->Start();
309*635a8641SAndroid Build Coastguard Worker   }
310*635a8641SAndroid Build Coastguard Worker 
311*635a8641SAndroid Build Coastguard Worker   // This test will hang if the foreground threads become stuck in
312*635a8641SAndroid Build Coastguard Worker   // LazyInstance::Get() per the background thread never being scheduled to
313*635a8641SAndroid Build Coastguard Worker   // complete construction.
314*635a8641SAndroid Build Coastguard Worker   for (auto& foreground_thread : foreground_threads)
315*635a8641SAndroid Build Coastguard Worker     foreground_thread->Join();
316*635a8641SAndroid Build Coastguard Worker   background_getter.Join();
317*635a8641SAndroid Build Coastguard Worker 
318*635a8641SAndroid Build Coastguard Worker   // Fail if this test takes more than 5 seconds (it takes 5-10 seconds on a
319*635a8641SAndroid Build Coastguard Worker   // Z840 without r527445 but is expected to be fast (~30ms) with the fix).
320*635a8641SAndroid Build Coastguard Worker   EXPECT_LT(base::TimeTicks::Now() - test_begin,
321*635a8641SAndroid Build Coastguard Worker             base::TimeDelta::FromSeconds(5));
322*635a8641SAndroid Build Coastguard Worker }
323