lazy_instance_unittest.cc revision c7f5f8508d98d5952d42ed7648c2a8f30a4da156
1// Copyright (c) 2008 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "base/at_exit.h"
6#include "base/atomic_sequence_num.h"
7#include "base/lazy_instance.h"
8#include "base/simple_thread.h"
9#include "testing/gtest/include/gtest/gtest.h"
10
11namespace {
12
13base::AtomicSequenceNumber constructed_seq_(base::LINKER_INITIALIZED);
14base::AtomicSequenceNumber destructed_seq_(base::LINKER_INITIALIZED);
15
16class ConstructAndDestructLogger {
17 public:
18  ConstructAndDestructLogger() {
19    constructed_seq_.GetNext();
20  }
21  ~ConstructAndDestructLogger() {
22    destructed_seq_.GetNext();
23  }
24};
25
26class SlowConstructor {
27 public:
28  SlowConstructor() : some_int_(0) {
29    PlatformThread::Sleep(1000);  // Sleep for 1 second to try to cause a race.
30    ++constructed;
31    some_int_ = 12;
32  }
33  int some_int() const { return some_int_; }
34
35  static int constructed;
36 private:
37  int some_int_;
38};
39
40int SlowConstructor::constructed = 0;
41
42class SlowDelegate : public base::DelegateSimpleThread::Delegate {
43 public:
44  explicit SlowDelegate(base::LazyInstance<SlowConstructor>* lazy)
45      : lazy_(lazy) {}
46
47  virtual void Run() {
48    EXPECT_EQ(12, lazy_->Get().some_int());
49    EXPECT_EQ(12, lazy_->Pointer()->some_int());
50  }
51
52 private:
53  base::LazyInstance<SlowConstructor>* lazy_;
54};
55
56}  // namespace
57
58static base::LazyInstance<ConstructAndDestructLogger> lazy_logger(
59    base::LINKER_INITIALIZED);
60
61TEST(LazyInstanceTest, Basic) {
62  {
63    base::ShadowingAtExitManager shadow;
64
65    EXPECT_EQ(0, constructed_seq_.GetNext());
66    EXPECT_EQ(0, destructed_seq_.GetNext());
67
68    lazy_logger.Get();
69    EXPECT_EQ(2, constructed_seq_.GetNext());
70    EXPECT_EQ(1, destructed_seq_.GetNext());
71
72    lazy_logger.Pointer();
73    EXPECT_EQ(3, constructed_seq_.GetNext());
74    EXPECT_EQ(2, destructed_seq_.GetNext());
75  }
76  EXPECT_EQ(4, constructed_seq_.GetNext());
77  EXPECT_EQ(4, destructed_seq_.GetNext());
78}
79
80static base::LazyInstance<SlowConstructor> lazy_slow(base::LINKER_INITIALIZED);
81
82TEST(LazyInstanceTest, ConstructorThreadSafety) {
83  {
84    base::ShadowingAtExitManager shadow;
85
86    SlowDelegate delegate(&lazy_slow);
87    EXPECT_EQ(0, SlowConstructor::constructed);
88
89    base::DelegateSimpleThreadPool pool("lazy_instance_cons", 5);
90    pool.AddWork(&delegate, 20);
91    EXPECT_EQ(0, SlowConstructor::constructed);
92
93    pool.Start();
94    pool.JoinAll();
95    EXPECT_EQ(1, SlowConstructor::constructed);
96  }
97}
98