2 * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
11 // Borrowed from Chromium's src/base/threading/thread_checker_unittest.cc.
13 #include "testing/gtest/include/gtest/gtest.h"
14 #include "webrtc/base/checks.h"
15 #include "webrtc/base/thread.h"
16 #include "webrtc/base/thread_checker.h"
17 #include "webrtc/base/scoped_ptr.h"
18 #include "webrtc/test/testsupport/gtest_disable.h"
20 // Duplicated from base/threading/thread_checker.h so that we can be
21 // good citizens there and undef the macro.
22 #if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
23 #define ENABLE_THREAD_CHECKER 1
25 #define ENABLE_THREAD_CHECKER 0
32 // Simple class to exercise the basics of ThreadChecker.
33 // Both the destructor and DoStuff should verify that they were
34 // called on the same thread as the constructor.
35 class ThreadCheckerClass : public ThreadChecker {
37 ThreadCheckerClass() {}
39 // Verifies that it was called on the same thread as the constructor.
41 DCHECK(CalledOnValidThread());
44 void DetachFromThread() {
45 ThreadChecker::DetachFromThread();
48 static void MethodOnDifferentThreadImpl();
49 static void DetachThenCallFromDifferentThreadImpl();
52 DISALLOW_COPY_AND_ASSIGN(ThreadCheckerClass);
55 // Calls ThreadCheckerClass::DoStuff on another thread.
56 class CallDoStuffOnThread : public Thread {
58 explicit CallDoStuffOnThread(ThreadCheckerClass* thread_checker_class)
60 thread_checker_class_(thread_checker_class) {
61 SetName("call_do_stuff_on_thread", NULL);
64 virtual void Run() OVERRIDE {
65 thread_checker_class_->DoStuff();
68 // New method. Needed since Thread::Join is protected, and it is called by
75 ThreadCheckerClass* thread_checker_class_;
77 DISALLOW_COPY_AND_ASSIGN(CallDoStuffOnThread);
80 // Deletes ThreadCheckerClass on a different thread.
81 class DeleteThreadCheckerClassOnThread : public Thread {
83 explicit DeleteThreadCheckerClassOnThread(
84 ThreadCheckerClass* thread_checker_class)
86 thread_checker_class_(thread_checker_class) {
87 SetName("delete_thread_checker_class_on_thread", NULL);
90 virtual void Run() OVERRIDE {
91 thread_checker_class_.reset();
94 // New method. Needed since Thread::Join is protected, and it is called by
101 scoped_ptr<ThreadCheckerClass> thread_checker_class_;
103 DISALLOW_COPY_AND_ASSIGN(DeleteThreadCheckerClassOnThread);
108 TEST(ThreadCheckerTest, CallsAllowedOnSameThread) {
109 scoped_ptr<ThreadCheckerClass> thread_checker_class(
110 new ThreadCheckerClass);
112 // Verify that DoStuff doesn't assert.
113 thread_checker_class->DoStuff();
115 // Verify that the destructor doesn't assert.
116 thread_checker_class.reset();
119 TEST(ThreadCheckerTest, DestructorAllowedOnDifferentThread) {
120 scoped_ptr<ThreadCheckerClass> thread_checker_class(
121 new ThreadCheckerClass);
123 // Verify that the destructor doesn't assert
124 // when called on a different thread.
125 DeleteThreadCheckerClassOnThread delete_on_thread(
126 thread_checker_class.release());
128 delete_on_thread.Start();
129 delete_on_thread.Join();
132 TEST(ThreadCheckerTest, DetachFromThread) {
133 scoped_ptr<ThreadCheckerClass> thread_checker_class(
134 new ThreadCheckerClass);
136 // Verify that DoStuff doesn't assert when called on a different thread after
137 // a call to DetachFromThread.
138 thread_checker_class->DetachFromThread();
139 CallDoStuffOnThread call_on_thread(thread_checker_class.get());
141 call_on_thread.Start();
142 call_on_thread.Join();
145 #if GTEST_HAS_DEATH_TEST || !ENABLE_THREAD_CHECKER
147 void ThreadCheckerClass::MethodOnDifferentThreadImpl() {
148 scoped_ptr<ThreadCheckerClass> thread_checker_class(
149 new ThreadCheckerClass);
151 // DoStuff should assert in debug builds only when called on a
153 CallDoStuffOnThread call_on_thread(thread_checker_class.get());
155 call_on_thread.Start();
156 call_on_thread.Join();
159 #if ENABLE_THREAD_CHECKER
160 TEST(ThreadCheckerDeathTest, MethodNotAllowedOnDifferentThreadInDebug) {
162 ThreadCheckerClass::MethodOnDifferentThreadImpl();
166 TEST(ThreadCheckerTest, MethodAllowedOnDifferentThreadInRelease) {
167 ThreadCheckerClass::MethodOnDifferentThreadImpl();
169 #endif // ENABLE_THREAD_CHECKER
171 void ThreadCheckerClass::DetachThenCallFromDifferentThreadImpl() {
172 scoped_ptr<ThreadCheckerClass> thread_checker_class(
173 new ThreadCheckerClass);
175 // DoStuff doesn't assert when called on a different thread
176 // after a call to DetachFromThread.
177 thread_checker_class->DetachFromThread();
178 CallDoStuffOnThread call_on_thread(thread_checker_class.get());
180 call_on_thread.Start();
181 call_on_thread.Join();
183 // DoStuff should assert in debug builds only after moving to
185 thread_checker_class->DoStuff();
188 #if ENABLE_THREAD_CHECKER
189 TEST(ThreadCheckerDeathTest, DetachFromThreadInDebug) {
191 ThreadCheckerClass::DetachThenCallFromDifferentThreadImpl();
195 TEST(ThreadCheckerTest, DetachFromThreadInRelease) {
196 ThreadCheckerClass::DetachThenCallFromDifferentThreadImpl();
198 #endif // ENABLE_THREAD_CHECKER
200 #endif // GTEST_HAS_DEATH_TEST || !ENABLE_THREAD_CHECKER
202 // Just in case we ever get lumped together with other compilation units.
203 #undef ENABLE_THREAD_CHECKER