blob: 026cfd9e0e2e397116ecbbbbb5db44a6c90dd514 [file] [log] [blame]
[email protected]8c3881ab2012-01-04 19:02:381// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]d9ddc962010-08-24 04:29:562// 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/basictypes.h"
6#include "base/logging.h"
[email protected]3b63f8f42011-03-28 01:54:157#include "base/memory/scoped_ptr.h"
[email protected]ce072a72010-12-31 20:02:168#include "base/threading/thread_checker.h"
[email protected]ac9ba8fe2010-12-30 18:08:369#include "base/threading/simple_thread.h"
[email protected]d9ddc962010-08-24 04:29:5610#include "testing/gtest/include/gtest/gtest.h"
11
[email protected]8c3881ab2012-01-04 19:02:3812// Duplicated from base/threading/thread_checker.h so that we can be
13// good citizens there and undef the macro.
[email protected]85588412012-06-27 01:39:5214#if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
15#define ENABLE_THREAD_CHECKER 1
16#else
17#define ENABLE_THREAD_CHECKER 0
18#endif
[email protected]8c3881ab2012-01-04 19:02:3819
[email protected]ce072a72010-12-31 20:02:1620namespace base {
21
[email protected]85588412012-06-27 01:39:5222namespace {
23
[email protected]40064482011-03-03 23:38:5124// Simple class to exercise the basics of ThreadChecker.
[email protected]d9ddc962010-08-24 04:29:5625// Both the destructor and DoStuff should verify that they were
26// called on the same thread as the constructor.
27class ThreadCheckerClass : public ThreadChecker {
28 public:
29 ThreadCheckerClass() {}
30
31 // Verifies that it was called on the same thread as the constructor.
32 void DoStuff() {
[email protected]a42d4632011-10-26 21:48:0033 DCHECK(CalledOnValidThread());
[email protected]d9ddc962010-08-24 04:29:5634 }
35
[email protected]8ff672512010-10-07 20:17:3336 void DetachFromThread() {
37 ThreadChecker::DetachFromThread();
38 }
39
[email protected]40064482011-03-03 23:38:5140 static void MethodOnDifferentThreadImpl();
41 static void DetachThenCallFromDifferentThreadImpl();
42
[email protected]d9ddc962010-08-24 04:29:5643 private:
44 DISALLOW_COPY_AND_ASSIGN(ThreadCheckerClass);
45};
46
47// Calls ThreadCheckerClass::DoStuff on another thread.
48class CallDoStuffOnThread : public base::SimpleThread {
49 public:
50 CallDoStuffOnThread(ThreadCheckerClass* thread_checker_class)
51 : SimpleThread("call_do_stuff_on_thread"),
52 thread_checker_class_(thread_checker_class) {
53 }
54
[email protected]44106182012-04-06 03:53:0255 virtual void Run() OVERRIDE {
[email protected]d9ddc962010-08-24 04:29:5656 thread_checker_class_->DoStuff();
57 }
58
59 private:
60 ThreadCheckerClass* thread_checker_class_;
61
62 DISALLOW_COPY_AND_ASSIGN(CallDoStuffOnThread);
63};
64
65// Deletes ThreadCheckerClass on a different thread.
66class DeleteThreadCheckerClassOnThread : public base::SimpleThread {
67 public:
68 DeleteThreadCheckerClassOnThread(ThreadCheckerClass* thread_checker_class)
69 : SimpleThread("delete_thread_checker_class_on_thread"),
70 thread_checker_class_(thread_checker_class) {
71 }
72
[email protected]44106182012-04-06 03:53:0273 virtual void Run() OVERRIDE {
[email protected]d9ddc962010-08-24 04:29:5674 thread_checker_class_.reset();
75 }
76
77 private:
78 scoped_ptr<ThreadCheckerClass> thread_checker_class_;
79
80 DISALLOW_COPY_AND_ASSIGN(DeleteThreadCheckerClassOnThread);
81};
82
[email protected]85588412012-06-27 01:39:5283} // namespace
84
[email protected]d9ddc962010-08-24 04:29:5685TEST(ThreadCheckerTest, CallsAllowedOnSameThread) {
86 scoped_ptr<ThreadCheckerClass> thread_checker_class(
87 new ThreadCheckerClass);
88
89 // Verify that DoStuff doesn't assert.
90 thread_checker_class->DoStuff();
91
92 // Verify that the destructor doesn't assert.
93 thread_checker_class.reset();
94}
95
96TEST(ThreadCheckerTest, DestructorAllowedOnDifferentThread) {
97 scoped_ptr<ThreadCheckerClass> thread_checker_class(
98 new ThreadCheckerClass);
99
100 // Verify that the destructor doesn't assert
101 // when called on a different thread.
102 DeleteThreadCheckerClassOnThread delete_on_thread(
103 thread_checker_class.release());
104
105 delete_on_thread.Start();
106 delete_on_thread.Join();
107}
108
[email protected]8ff672512010-10-07 20:17:33109TEST(ThreadCheckerTest, DetachFromThread) {
110 scoped_ptr<ThreadCheckerClass> thread_checker_class(
111 new ThreadCheckerClass);
112
113 // Verify that DoStuff doesn't assert when called on a different thread after
114 // a call to DetachFromThread.
115 thread_checker_class->DetachFromThread();
116 CallDoStuffOnThread call_on_thread(thread_checker_class.get());
117
118 call_on_thread.Start();
119 call_on_thread.Join();
120}
121
[email protected]8c3881ab2012-01-04 19:02:38122#if GTEST_HAS_DEATH_TEST || !ENABLE_THREAD_CHECKER
[email protected]d9ddc962010-08-24 04:29:56123
[email protected]40064482011-03-03 23:38:51124void ThreadCheckerClass::MethodOnDifferentThreadImpl() {
125 scoped_ptr<ThreadCheckerClass> thread_checker_class(
126 new ThreadCheckerClass);
[email protected]d9ddc962010-08-24 04:29:56127
[email protected]40064482011-03-03 23:38:51128 // DoStuff should assert in debug builds only when called on a
129 // different thread.
130 CallDoStuffOnThread call_on_thread(thread_checker_class.get());
[email protected]d9ddc962010-08-24 04:29:56131
[email protected]40064482011-03-03 23:38:51132 call_on_thread.Start();
133 call_on_thread.Join();
[email protected]d9ddc962010-08-24 04:29:56134}
135
[email protected]8c3881ab2012-01-04 19:02:38136#if ENABLE_THREAD_CHECKER
[email protected]40064482011-03-03 23:38:51137TEST(ThreadCheckerDeathTest, MethodNotAllowedOnDifferentThreadInDebug) {
[email protected]85588412012-06-27 01:39:52138 ASSERT_DEATH({
[email protected]40064482011-03-03 23:38:51139 ThreadCheckerClass::MethodOnDifferentThreadImpl();
[email protected]8ff672512010-10-07 20:17:33140 }, "");
141}
[email protected]40064482011-03-03 23:38:51142#else
143TEST(ThreadCheckerTest, MethodAllowedOnDifferentThreadInRelease) {
144 ThreadCheckerClass::MethodOnDifferentThreadImpl();
145}
[email protected]8c3881ab2012-01-04 19:02:38146#endif // ENABLE_THREAD_CHECKER
[email protected]8ff672512010-10-07 20:17:33147
[email protected]40064482011-03-03 23:38:51148void ThreadCheckerClass::DetachThenCallFromDifferentThreadImpl() {
149 scoped_ptr<ThreadCheckerClass> thread_checker_class(
150 new ThreadCheckerClass);
151
152 // DoStuff doesn't assert when called on a different thread
153 // after a call to DetachFromThread.
154 thread_checker_class->DetachFromThread();
155 CallDoStuffOnThread call_on_thread(thread_checker_class.get());
156
157 call_on_thread.Start();
158 call_on_thread.Join();
159
160 // DoStuff should assert in debug builds only after moving to
161 // another thread.
162 thread_checker_class->DoStuff();
163}
164
[email protected]8c3881ab2012-01-04 19:02:38165#if ENABLE_THREAD_CHECKER
[email protected]40064482011-03-03 23:38:51166TEST(ThreadCheckerDeathTest, DetachFromThreadInDebug) {
[email protected]85588412012-06-27 01:39:52167 ASSERT_DEATH({
[email protected]40064482011-03-03 23:38:51168 ThreadCheckerClass::DetachThenCallFromDifferentThreadImpl();
169 }, "");
170}
171#else
172TEST(ThreadCheckerTest, DetachFromThreadInRelease) {
173 ThreadCheckerClass::DetachThenCallFromDifferentThreadImpl();
174}
[email protected]8c3881ab2012-01-04 19:02:38175#endif // ENABLE_THREAD_CHECKER
[email protected]40064482011-03-03 23:38:51176
[email protected]8c3881ab2012-01-04 19:02:38177#endif // GTEST_HAS_DEATH_TEST || !ENABLE_THREAD_CHECKER
178
179// Just in case we ever get lumped together with other compilation units.
180#undef ENABLE_THREAD_CHECKER
[email protected]d9ddc962010-08-24 04:29:56181
[email protected]ce072a72010-12-31 20:02:16182} // namespace base