- add sources.
[platform/framework/web/crosswalk.git] / src / base / threading / thread_local_unittest.cc
1 // Copyright (c) 2012 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/logging.h"
6 #include "base/threading/simple_thread.h"
7 #include "base/threading/thread_local.h"
8 #include "base/synchronization/waitable_event.h"
9 #include "testing/gtest/include/gtest/gtest.h"
10
11 namespace base {
12
13 namespace {
14
15 class ThreadLocalTesterBase : public base::DelegateSimpleThreadPool::Delegate {
16  public:
17   typedef base::ThreadLocalPointer<ThreadLocalTesterBase> TLPType;
18
19   ThreadLocalTesterBase(TLPType* tlp, base::WaitableEvent* done)
20       : tlp_(tlp),
21         done_(done) {
22   }
23   virtual ~ThreadLocalTesterBase() {}
24
25  protected:
26   TLPType* tlp_;
27   base::WaitableEvent* done_;
28 };
29
30 class SetThreadLocal : public ThreadLocalTesterBase {
31  public:
32   SetThreadLocal(TLPType* tlp, base::WaitableEvent* done)
33       : ThreadLocalTesterBase(tlp, done),
34         val_(NULL) {
35   }
36   virtual ~SetThreadLocal() {}
37
38   void set_value(ThreadLocalTesterBase* val) { val_ = val; }
39
40   virtual void Run() OVERRIDE {
41     DCHECK(!done_->IsSignaled());
42     tlp_->Set(val_);
43     done_->Signal();
44   }
45
46  private:
47   ThreadLocalTesterBase* val_;
48 };
49
50 class GetThreadLocal : public ThreadLocalTesterBase {
51  public:
52   GetThreadLocal(TLPType* tlp, base::WaitableEvent* done)
53       : ThreadLocalTesterBase(tlp, done),
54         ptr_(NULL) {
55   }
56   virtual ~GetThreadLocal() {}
57
58   void set_ptr(ThreadLocalTesterBase** ptr) { ptr_ = ptr; }
59
60   virtual void Run() OVERRIDE {
61     DCHECK(!done_->IsSignaled());
62     *ptr_ = tlp_->Get();
63     done_->Signal();
64   }
65
66  private:
67   ThreadLocalTesterBase** ptr_;
68 };
69
70 }  // namespace
71
72 // In this test, we start 2 threads which will access a ThreadLocalPointer.  We
73 // make sure the default is NULL, and the pointers are unique to the threads.
74 TEST(ThreadLocalTest, Pointer) {
75   base::DelegateSimpleThreadPool tp1("ThreadLocalTest tp1", 1);
76   base::DelegateSimpleThreadPool tp2("ThreadLocalTest tp1", 1);
77   tp1.Start();
78   tp2.Start();
79
80   base::ThreadLocalPointer<ThreadLocalTesterBase> tlp;
81
82   static ThreadLocalTesterBase* const kBogusPointer =
83       reinterpret_cast<ThreadLocalTesterBase*>(0x1234);
84
85   ThreadLocalTesterBase* tls_val;
86   base::WaitableEvent done(true, false);
87
88   GetThreadLocal getter(&tlp, &done);
89   getter.set_ptr(&tls_val);
90
91   // Check that both threads defaulted to NULL.
92   tls_val = kBogusPointer;
93   done.Reset();
94   tp1.AddWork(&getter);
95   done.Wait();
96   EXPECT_EQ(static_cast<ThreadLocalTesterBase*>(NULL), tls_val);
97
98   tls_val = kBogusPointer;
99   done.Reset();
100   tp2.AddWork(&getter);
101   done.Wait();
102   EXPECT_EQ(static_cast<ThreadLocalTesterBase*>(NULL), tls_val);
103
104
105   SetThreadLocal setter(&tlp, &done);
106   setter.set_value(kBogusPointer);
107
108   // Have thread 1 set their pointer value to kBogusPointer.
109   done.Reset();
110   tp1.AddWork(&setter);
111   done.Wait();
112
113   tls_val = NULL;
114   done.Reset();
115   tp1.AddWork(&getter);
116   done.Wait();
117   EXPECT_EQ(kBogusPointer, tls_val);
118
119   // Make sure thread 2 is still NULL
120   tls_val = kBogusPointer;
121   done.Reset();
122   tp2.AddWork(&getter);
123   done.Wait();
124   EXPECT_EQ(static_cast<ThreadLocalTesterBase*>(NULL), tls_val);
125
126   // Set thread 2 to kBogusPointer + 1.
127   setter.set_value(kBogusPointer + 1);
128
129   done.Reset();
130   tp2.AddWork(&setter);
131   done.Wait();
132
133   tls_val = NULL;
134   done.Reset();
135   tp2.AddWork(&getter);
136   done.Wait();
137   EXPECT_EQ(kBogusPointer + 1, tls_val);
138
139   // Make sure thread 1 is still kBogusPointer.
140   tls_val = NULL;
141   done.Reset();
142   tp1.AddWork(&getter);
143   done.Wait();
144   EXPECT_EQ(kBogusPointer, tls_val);
145
146   tp1.JoinAll();
147   tp2.JoinAll();
148 }
149
150 TEST(ThreadLocalTest, Boolean) {
151   {
152     base::ThreadLocalBoolean tlb;
153     EXPECT_FALSE(tlb.Get());
154
155     tlb.Set(false);
156     EXPECT_FALSE(tlb.Get());
157
158     tlb.Set(true);
159     EXPECT_TRUE(tlb.Get());
160   }
161
162   // Our slot should have been freed, we're all reset.
163   {
164     base::ThreadLocalBoolean tlb;
165     EXPECT_FALSE(tlb.Get());
166   }
167 }
168
169 }  // namespace base