blob: 372f6f4a77fb921d1801fd0fb8e171346b727dc1 [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"
kwiberg4485ffb2016-04-26 08:14:39 -070017#include "webrtc/base/constructormagic.h"
henrik.lundin@webrtc.org1e3c5c22014-06-16 11:34:44 +000018#include "webrtc/base/thread.h"
19#include "webrtc/base/thread_checker.h"
henrik.lundin@webrtc.org1e3c5c22014-06-16 11:34:44 +000020
21// Duplicated from base/threading/thread_checker.h so that we can be
22// good citizens there and undef the macro.
23#if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
24#define ENABLE_THREAD_CHECKER 1
25#else
26#define ENABLE_THREAD_CHECKER 0
27#endif
28
29namespace rtc {
30
31namespace {
32
33// Simple class to exercise the basics of ThreadChecker.
34// Both the destructor and DoStuff should verify that they were
35// called on the same thread as the constructor.
36class ThreadCheckerClass : public ThreadChecker {
37 public:
38 ThreadCheckerClass() {}
39
40 // Verifies that it was called on the same thread as the constructor.
henrikg91d6ede2015-09-17 00:24:34 -070041 void DoStuff() { RTC_DCHECK(CalledOnValidThread()); }
henrik.lundin@webrtc.org1e3c5c22014-06-16 11:34:44 +000042
43 void DetachFromThread() {
44 ThreadChecker::DetachFromThread();
45 }
46
47 static void MethodOnDifferentThreadImpl();
48 static void DetachThenCallFromDifferentThreadImpl();
49
50 private:
henrikg3c089d72015-09-16 05:37:44 -070051 RTC_DISALLOW_COPY_AND_ASSIGN(ThreadCheckerClass);
henrik.lundin@webrtc.org1e3c5c22014-06-16 11:34:44 +000052};
53
54// Calls ThreadCheckerClass::DoStuff on another thread.
55class CallDoStuffOnThread : public Thread {
56 public:
57 explicit CallDoStuffOnThread(ThreadCheckerClass* thread_checker_class)
58 : Thread(),
59 thread_checker_class_(thread_checker_class) {
60 SetName("call_do_stuff_on_thread", NULL);
61 }
62
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +000063 void Run() override { thread_checker_class_->DoStuff(); }
henrik.lundin@webrtc.org1e3c5c22014-06-16 11:34:44 +000064
65 // New method. Needed since Thread::Join is protected, and it is called by
66 // the TEST.
67 void Join() {
68 Thread::Join();
69 }
70
71 private:
72 ThreadCheckerClass* thread_checker_class_;
73
henrikg3c089d72015-09-16 05:37:44 -070074 RTC_DISALLOW_COPY_AND_ASSIGN(CallDoStuffOnThread);
henrik.lundin@webrtc.org1e3c5c22014-06-16 11:34:44 +000075};
76
77// Deletes ThreadCheckerClass on a different thread.
78class DeleteThreadCheckerClassOnThread : public Thread {
79 public:
80 explicit DeleteThreadCheckerClassOnThread(
81 ThreadCheckerClass* thread_checker_class)
82 : Thread(),
83 thread_checker_class_(thread_checker_class) {
84 SetName("delete_thread_checker_class_on_thread", NULL);
85 }
86
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +000087 void Run() override { thread_checker_class_.reset(); }
henrik.lundin@webrtc.org1e3c5c22014-06-16 11:34:44 +000088
89 // New method. Needed since Thread::Join is protected, and it is called by
90 // the TEST.
91 void Join() {
92 Thread::Join();
93 }
94
95 private:
jbauch555604a2016-04-26 03:13:22 -070096 std::unique_ptr<ThreadCheckerClass> thread_checker_class_;
henrik.lundin@webrtc.org1e3c5c22014-06-16 11:34:44 +000097
henrikg3c089d72015-09-16 05:37:44 -070098 RTC_DISALLOW_COPY_AND_ASSIGN(DeleteThreadCheckerClassOnThread);
henrik.lundin@webrtc.org1e3c5c22014-06-16 11:34:44 +000099};
100
101} // namespace
102
henrike@webrtc.orgc732a3e2014-10-09 22:08:15 +0000103TEST(ThreadCheckerTest, CallsAllowedOnSameThread) {
jbauch555604a2016-04-26 03:13:22 -0700104 std::unique_ptr<ThreadCheckerClass> thread_checker_class(
henrik.lundin@webrtc.org1e3c5c22014-06-16 11:34:44 +0000105 new ThreadCheckerClass);
106
107 // Verify that DoStuff doesn't assert.
108 thread_checker_class->DoStuff();
109
110 // Verify that the destructor doesn't assert.
111 thread_checker_class.reset();
112}
113
henrike@webrtc.orgc732a3e2014-10-09 22:08:15 +0000114TEST(ThreadCheckerTest, DestructorAllowedOnDifferentThread) {
jbauch555604a2016-04-26 03:13:22 -0700115 std::unique_ptr<ThreadCheckerClass> thread_checker_class(
henrik.lundin@webrtc.org1e3c5c22014-06-16 11:34:44 +0000116 new ThreadCheckerClass);
117
118 // Verify that the destructor doesn't assert
119 // when called on a different thread.
120 DeleteThreadCheckerClassOnThread delete_on_thread(
121 thread_checker_class.release());
122
123 delete_on_thread.Start();
124 delete_on_thread.Join();
125}
126
henrike@webrtc.orgc732a3e2014-10-09 22:08:15 +0000127TEST(ThreadCheckerTest, DetachFromThread) {
jbauch555604a2016-04-26 03:13:22 -0700128 std::unique_ptr<ThreadCheckerClass> thread_checker_class(
henrik.lundin@webrtc.org1e3c5c22014-06-16 11:34:44 +0000129 new ThreadCheckerClass);
130
131 // Verify that DoStuff doesn't assert when called on a different thread after
132 // a call to DetachFromThread.
133 thread_checker_class->DetachFromThread();
134 CallDoStuffOnThread call_on_thread(thread_checker_class.get());
135
136 call_on_thread.Start();
137 call_on_thread.Join();
138}
139
140#if GTEST_HAS_DEATH_TEST || !ENABLE_THREAD_CHECKER
141
142void ThreadCheckerClass::MethodOnDifferentThreadImpl() {
jbauch555604a2016-04-26 03:13:22 -0700143 std::unique_ptr<ThreadCheckerClass> thread_checker_class(
henrik.lundin@webrtc.org1e3c5c22014-06-16 11:34:44 +0000144 new ThreadCheckerClass);
145
146 // DoStuff should assert in debug builds only when called on a
147 // different thread.
148 CallDoStuffOnThread call_on_thread(thread_checker_class.get());
149
150 call_on_thread.Start();
151 call_on_thread.Join();
152}
153
154#if ENABLE_THREAD_CHECKER
tommi@webrtc.org2eb16602015-02-07 19:17:47 +0000155TEST(ThreadCheckerDeathTest, MethodNotAllowedOnDifferentThreadInDebug) {
henrik.lundin@webrtc.org1e3c5c22014-06-16 11:34:44 +0000156 ASSERT_DEATH({
157 ThreadCheckerClass::MethodOnDifferentThreadImpl();
158 }, "");
159}
160#else
161TEST(ThreadCheckerTest, MethodAllowedOnDifferentThreadInRelease) {
162 ThreadCheckerClass::MethodOnDifferentThreadImpl();
163}
164#endif // ENABLE_THREAD_CHECKER
165
166void ThreadCheckerClass::DetachThenCallFromDifferentThreadImpl() {
jbauch555604a2016-04-26 03:13:22 -0700167 std::unique_ptr<ThreadCheckerClass> thread_checker_class(
henrik.lundin@webrtc.org1e3c5c22014-06-16 11:34:44 +0000168 new ThreadCheckerClass);
169
170 // DoStuff doesn't assert when called on a different thread
171 // after a call to DetachFromThread.
172 thread_checker_class->DetachFromThread();
173 CallDoStuffOnThread call_on_thread(thread_checker_class.get());
174
175 call_on_thread.Start();
176 call_on_thread.Join();
177
178 // DoStuff should assert in debug builds only after moving to
179 // another thread.
180 thread_checker_class->DoStuff();
181}
182
183#if ENABLE_THREAD_CHECKER
tommi@webrtc.org2eb16602015-02-07 19:17:47 +0000184TEST(ThreadCheckerDeathTest, DetachFromThreadInDebug) {
henrik.lundin@webrtc.org1e3c5c22014-06-16 11:34:44 +0000185 ASSERT_DEATH({
186 ThreadCheckerClass::DetachThenCallFromDifferentThreadImpl();
187 }, "");
188}
189#else
190TEST(ThreadCheckerTest, DetachFromThreadInRelease) {
191 ThreadCheckerClass::DetachThenCallFromDifferentThreadImpl();
192}
193#endif // ENABLE_THREAD_CHECKER
194
195#endif // GTEST_HAS_DEATH_TEST || !ENABLE_THREAD_CHECKER
196
197// Just in case we ever get lumped together with other compilation units.
198#undef ENABLE_THREAD_CHECKER
199
200} // namespace rtc