blob: 8fcaa7a2720688783b972011812053958e09086f [file] [log] [blame]
henrik.lundin@webrtc.org1e3c5c22014-06-16 11:34:44 +00001/*
2 * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
3 *
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.
9 */
10
11// Borrowed from Chromium's src/base/threading/thread_checker_unittest.cc.
12
jbauch555604a2016-04-26 03:13:22 -070013#include <memory>
14
henrik.lundin@webrtc.org1e3c5c22014-06-16 11:34:44 +000015#include "testing/gtest/include/gtest/gtest.h"
henrik.lundin@webrtc.org18617cf2014-09-15 11:19:35 +000016#include "webrtc/base/checks.h"
henrik.lundin@webrtc.org1e3c5c22014-06-16 11:34:44 +000017#include "webrtc/base/thread.h"
18#include "webrtc/base/thread_checker.h"
henrik.lundin@webrtc.org1e3c5c22014-06-16 11:34:44 +000019
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
24#else
25#define ENABLE_THREAD_CHECKER 0
26#endif
27
28namespace rtc {
29
30namespace {
31
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.
35class ThreadCheckerClass : public ThreadChecker {
36 public:
37 ThreadCheckerClass() {}
38
39 // Verifies that it was called on the same thread as the constructor.
henrikg91d6ede2015-09-17 00:24:34 -070040 void DoStuff() { RTC_DCHECK(CalledOnValidThread()); }
henrik.lundin@webrtc.org1e3c5c22014-06-16 11:34:44 +000041
42 void DetachFromThread() {
43 ThreadChecker::DetachFromThread();
44 }
45
46 static void MethodOnDifferentThreadImpl();
47 static void DetachThenCallFromDifferentThreadImpl();
48
49 private:
henrikg3c089d72015-09-16 05:37:44 -070050 RTC_DISALLOW_COPY_AND_ASSIGN(ThreadCheckerClass);
henrik.lundin@webrtc.org1e3c5c22014-06-16 11:34:44 +000051};
52
53// Calls ThreadCheckerClass::DoStuff on another thread.
54class CallDoStuffOnThread : public Thread {
55 public:
56 explicit CallDoStuffOnThread(ThreadCheckerClass* thread_checker_class)
57 : Thread(),
58 thread_checker_class_(thread_checker_class) {
59 SetName("call_do_stuff_on_thread", NULL);
60 }
61
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +000062 void Run() override { thread_checker_class_->DoStuff(); }
henrik.lundin@webrtc.org1e3c5c22014-06-16 11:34:44 +000063
64 // New method. Needed since Thread::Join is protected, and it is called by
65 // the TEST.
66 void Join() {
67 Thread::Join();
68 }
69
70 private:
71 ThreadCheckerClass* thread_checker_class_;
72
henrikg3c089d72015-09-16 05:37:44 -070073 RTC_DISALLOW_COPY_AND_ASSIGN(CallDoStuffOnThread);
henrik.lundin@webrtc.org1e3c5c22014-06-16 11:34:44 +000074};
75
76// Deletes ThreadCheckerClass on a different thread.
77class DeleteThreadCheckerClassOnThread : public Thread {
78 public:
79 explicit DeleteThreadCheckerClassOnThread(
80 ThreadCheckerClass* thread_checker_class)
81 : Thread(),
82 thread_checker_class_(thread_checker_class) {
83 SetName("delete_thread_checker_class_on_thread", NULL);
84 }
85
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +000086 void Run() override { thread_checker_class_.reset(); }
henrik.lundin@webrtc.org1e3c5c22014-06-16 11:34:44 +000087
88 // New method. Needed since Thread::Join is protected, and it is called by
89 // the TEST.
90 void Join() {
91 Thread::Join();
92 }
93
94 private:
jbauch555604a2016-04-26 03:13:22 -070095 std::unique_ptr<ThreadCheckerClass> thread_checker_class_;
henrik.lundin@webrtc.org1e3c5c22014-06-16 11:34:44 +000096
henrikg3c089d72015-09-16 05:37:44 -070097 RTC_DISALLOW_COPY_AND_ASSIGN(DeleteThreadCheckerClassOnThread);
henrik.lundin@webrtc.org1e3c5c22014-06-16 11:34:44 +000098};
99
100} // namespace
101
henrike@webrtc.orgc732a3e2014-10-09 22:08:15 +0000102TEST(ThreadCheckerTest, CallsAllowedOnSameThread) {
jbauch555604a2016-04-26 03:13:22 -0700103 std::unique_ptr<ThreadCheckerClass> thread_checker_class(
henrik.lundin@webrtc.org1e3c5c22014-06-16 11:34:44 +0000104 new ThreadCheckerClass);
105
106 // Verify that DoStuff doesn't assert.
107 thread_checker_class->DoStuff();
108
109 // Verify that the destructor doesn't assert.
110 thread_checker_class.reset();
111}
112
henrike@webrtc.orgc732a3e2014-10-09 22:08:15 +0000113TEST(ThreadCheckerTest, DestructorAllowedOnDifferentThread) {
jbauch555604a2016-04-26 03:13:22 -0700114 std::unique_ptr<ThreadCheckerClass> thread_checker_class(
henrik.lundin@webrtc.org1e3c5c22014-06-16 11:34:44 +0000115 new ThreadCheckerClass);
116
117 // Verify that the destructor doesn't assert
118 // when called on a different thread.
119 DeleteThreadCheckerClassOnThread delete_on_thread(
120 thread_checker_class.release());
121
122 delete_on_thread.Start();
123 delete_on_thread.Join();
124}
125
henrike@webrtc.orgc732a3e2014-10-09 22:08:15 +0000126TEST(ThreadCheckerTest, DetachFromThread) {
jbauch555604a2016-04-26 03:13:22 -0700127 std::unique_ptr<ThreadCheckerClass> thread_checker_class(
henrik.lundin@webrtc.org1e3c5c22014-06-16 11:34:44 +0000128 new ThreadCheckerClass);
129
130 // Verify that DoStuff doesn't assert when called on a different thread after
131 // a call to DetachFromThread.
132 thread_checker_class->DetachFromThread();
133 CallDoStuffOnThread call_on_thread(thread_checker_class.get());
134
135 call_on_thread.Start();
136 call_on_thread.Join();
137}
138
139#if GTEST_HAS_DEATH_TEST || !ENABLE_THREAD_CHECKER
140
141void ThreadCheckerClass::MethodOnDifferentThreadImpl() {
jbauch555604a2016-04-26 03:13:22 -0700142 std::unique_ptr<ThreadCheckerClass> thread_checker_class(
henrik.lundin@webrtc.org1e3c5c22014-06-16 11:34:44 +0000143 new ThreadCheckerClass);
144
145 // DoStuff should assert in debug builds only when called on a
146 // different thread.
147 CallDoStuffOnThread call_on_thread(thread_checker_class.get());
148
149 call_on_thread.Start();
150 call_on_thread.Join();
151}
152
153#if ENABLE_THREAD_CHECKER
tommi@webrtc.org2eb16602015-02-07 19:17:47 +0000154TEST(ThreadCheckerDeathTest, MethodNotAllowedOnDifferentThreadInDebug) {
henrik.lundin@webrtc.org1e3c5c22014-06-16 11:34:44 +0000155 ASSERT_DEATH({
156 ThreadCheckerClass::MethodOnDifferentThreadImpl();
157 }, "");
158}
159#else
160TEST(ThreadCheckerTest, MethodAllowedOnDifferentThreadInRelease) {
161 ThreadCheckerClass::MethodOnDifferentThreadImpl();
162}
163#endif // ENABLE_THREAD_CHECKER
164
165void ThreadCheckerClass::DetachThenCallFromDifferentThreadImpl() {
jbauch555604a2016-04-26 03:13:22 -0700166 std::unique_ptr<ThreadCheckerClass> thread_checker_class(
henrik.lundin@webrtc.org1e3c5c22014-06-16 11:34:44 +0000167 new ThreadCheckerClass);
168
169 // DoStuff doesn't assert when called on a different thread
170 // after a call to DetachFromThread.
171 thread_checker_class->DetachFromThread();
172 CallDoStuffOnThread call_on_thread(thread_checker_class.get());
173
174 call_on_thread.Start();
175 call_on_thread.Join();
176
177 // DoStuff should assert in debug builds only after moving to
178 // another thread.
179 thread_checker_class->DoStuff();
180}
181
182#if ENABLE_THREAD_CHECKER
tommi@webrtc.org2eb16602015-02-07 19:17:47 +0000183TEST(ThreadCheckerDeathTest, DetachFromThreadInDebug) {
henrik.lundin@webrtc.org1e3c5c22014-06-16 11:34:44 +0000184 ASSERT_DEATH({
185 ThreadCheckerClass::DetachThenCallFromDifferentThreadImpl();
186 }, "");
187}
188#else
189TEST(ThreadCheckerTest, DetachFromThreadInRelease) {
190 ThreadCheckerClass::DetachThenCallFromDifferentThreadImpl();
191}
192#endif // ENABLE_THREAD_CHECKER
193
194#endif // GTEST_HAS_DEATH_TEST || !ENABLE_THREAD_CHECKER
195
196// Just in case we ever get lumped together with other compilation units.
197#undef ENABLE_THREAD_CHECKER
198
199} // namespace rtc