Any file that uses the RTC_DISALLOW_* macros should #include "webrtc/base/constructormagic.h", but a shocking number of them don't. This causes trouble when we try to wean files off of #including scoped_ptr.h, since a bunch of files get their constructormagic macros only from there. Rather than fixing these errors one by one as they turn up, this CL simply ensures that every file in the WebRTC tree that uses the RTC_DISALLOW_* macros #includes "webrtc/base/constructormagic.h". BUG=webrtc:5520 Review URL: https://codereview.webrtc.org/1917043005 Cr-Commit-Position: refs/heads/master@{#12509}
201 lines
5.7 KiB
C++
201 lines
5.7 KiB
C++
/*
|
|
* Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license
|
|
* that can be found in the LICENSE file in the root of the source
|
|
* tree. An additional intellectual property rights grant can be found
|
|
* in the file PATENTS. All contributing project authors may
|
|
* be found in the AUTHORS file in the root of the source tree.
|
|
*/
|
|
|
|
// Borrowed from Chromium's src/base/threading/thread_checker_unittest.cc.
|
|
|
|
#include <memory>
|
|
|
|
#include "testing/gtest/include/gtest/gtest.h"
|
|
#include "webrtc/base/checks.h"
|
|
#include "webrtc/base/constructormagic.h"
|
|
#include "webrtc/base/thread.h"
|
|
#include "webrtc/base/thread_checker.h"
|
|
|
|
// Duplicated from base/threading/thread_checker.h so that we can be
|
|
// good citizens there and undef the macro.
|
|
#if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
|
|
#define ENABLE_THREAD_CHECKER 1
|
|
#else
|
|
#define ENABLE_THREAD_CHECKER 0
|
|
#endif
|
|
|
|
namespace rtc {
|
|
|
|
namespace {
|
|
|
|
// Simple class to exercise the basics of ThreadChecker.
|
|
// Both the destructor and DoStuff should verify that they were
|
|
// called on the same thread as the constructor.
|
|
class ThreadCheckerClass : public ThreadChecker {
|
|
public:
|
|
ThreadCheckerClass() {}
|
|
|
|
// Verifies that it was called on the same thread as the constructor.
|
|
void DoStuff() { RTC_DCHECK(CalledOnValidThread()); }
|
|
|
|
void DetachFromThread() {
|
|
ThreadChecker::DetachFromThread();
|
|
}
|
|
|
|
static void MethodOnDifferentThreadImpl();
|
|
static void DetachThenCallFromDifferentThreadImpl();
|
|
|
|
private:
|
|
RTC_DISALLOW_COPY_AND_ASSIGN(ThreadCheckerClass);
|
|
};
|
|
|
|
// Calls ThreadCheckerClass::DoStuff on another thread.
|
|
class CallDoStuffOnThread : public Thread {
|
|
public:
|
|
explicit CallDoStuffOnThread(ThreadCheckerClass* thread_checker_class)
|
|
: Thread(),
|
|
thread_checker_class_(thread_checker_class) {
|
|
SetName("call_do_stuff_on_thread", NULL);
|
|
}
|
|
|
|
void Run() override { thread_checker_class_->DoStuff(); }
|
|
|
|
// New method. Needed since Thread::Join is protected, and it is called by
|
|
// the TEST.
|
|
void Join() {
|
|
Thread::Join();
|
|
}
|
|
|
|
private:
|
|
ThreadCheckerClass* thread_checker_class_;
|
|
|
|
RTC_DISALLOW_COPY_AND_ASSIGN(CallDoStuffOnThread);
|
|
};
|
|
|
|
// Deletes ThreadCheckerClass on a different thread.
|
|
class DeleteThreadCheckerClassOnThread : public Thread {
|
|
public:
|
|
explicit DeleteThreadCheckerClassOnThread(
|
|
ThreadCheckerClass* thread_checker_class)
|
|
: Thread(),
|
|
thread_checker_class_(thread_checker_class) {
|
|
SetName("delete_thread_checker_class_on_thread", NULL);
|
|
}
|
|
|
|
void Run() override { thread_checker_class_.reset(); }
|
|
|
|
// New method. Needed since Thread::Join is protected, and it is called by
|
|
// the TEST.
|
|
void Join() {
|
|
Thread::Join();
|
|
}
|
|
|
|
private:
|
|
std::unique_ptr<ThreadCheckerClass> thread_checker_class_;
|
|
|
|
RTC_DISALLOW_COPY_AND_ASSIGN(DeleteThreadCheckerClassOnThread);
|
|
};
|
|
|
|
} // namespace
|
|
|
|
TEST(ThreadCheckerTest, CallsAllowedOnSameThread) {
|
|
std::unique_ptr<ThreadCheckerClass> thread_checker_class(
|
|
new ThreadCheckerClass);
|
|
|
|
// Verify that DoStuff doesn't assert.
|
|
thread_checker_class->DoStuff();
|
|
|
|
// Verify that the destructor doesn't assert.
|
|
thread_checker_class.reset();
|
|
}
|
|
|
|
TEST(ThreadCheckerTest, DestructorAllowedOnDifferentThread) {
|
|
std::unique_ptr<ThreadCheckerClass> thread_checker_class(
|
|
new ThreadCheckerClass);
|
|
|
|
// Verify that the destructor doesn't assert
|
|
// when called on a different thread.
|
|
DeleteThreadCheckerClassOnThread delete_on_thread(
|
|
thread_checker_class.release());
|
|
|
|
delete_on_thread.Start();
|
|
delete_on_thread.Join();
|
|
}
|
|
|
|
TEST(ThreadCheckerTest, DetachFromThread) {
|
|
std::unique_ptr<ThreadCheckerClass> thread_checker_class(
|
|
new ThreadCheckerClass);
|
|
|
|
// Verify that DoStuff doesn't assert when called on a different thread after
|
|
// a call to DetachFromThread.
|
|
thread_checker_class->DetachFromThread();
|
|
CallDoStuffOnThread call_on_thread(thread_checker_class.get());
|
|
|
|
call_on_thread.Start();
|
|
call_on_thread.Join();
|
|
}
|
|
|
|
#if GTEST_HAS_DEATH_TEST || !ENABLE_THREAD_CHECKER
|
|
|
|
void ThreadCheckerClass::MethodOnDifferentThreadImpl() {
|
|
std::unique_ptr<ThreadCheckerClass> thread_checker_class(
|
|
new ThreadCheckerClass);
|
|
|
|
// DoStuff should assert in debug builds only when called on a
|
|
// different thread.
|
|
CallDoStuffOnThread call_on_thread(thread_checker_class.get());
|
|
|
|
call_on_thread.Start();
|
|
call_on_thread.Join();
|
|
}
|
|
|
|
#if ENABLE_THREAD_CHECKER
|
|
TEST(ThreadCheckerDeathTest, MethodNotAllowedOnDifferentThreadInDebug) {
|
|
ASSERT_DEATH({
|
|
ThreadCheckerClass::MethodOnDifferentThreadImpl();
|
|
}, "");
|
|
}
|
|
#else
|
|
TEST(ThreadCheckerTest, MethodAllowedOnDifferentThreadInRelease) {
|
|
ThreadCheckerClass::MethodOnDifferentThreadImpl();
|
|
}
|
|
#endif // ENABLE_THREAD_CHECKER
|
|
|
|
void ThreadCheckerClass::DetachThenCallFromDifferentThreadImpl() {
|
|
std::unique_ptr<ThreadCheckerClass> thread_checker_class(
|
|
new ThreadCheckerClass);
|
|
|
|
// DoStuff doesn't assert when called on a different thread
|
|
// after a call to DetachFromThread.
|
|
thread_checker_class->DetachFromThread();
|
|
CallDoStuffOnThread call_on_thread(thread_checker_class.get());
|
|
|
|
call_on_thread.Start();
|
|
call_on_thread.Join();
|
|
|
|
// DoStuff should assert in debug builds only after moving to
|
|
// another thread.
|
|
thread_checker_class->DoStuff();
|
|
}
|
|
|
|
#if ENABLE_THREAD_CHECKER
|
|
TEST(ThreadCheckerDeathTest, DetachFromThreadInDebug) {
|
|
ASSERT_DEATH({
|
|
ThreadCheckerClass::DetachThenCallFromDifferentThreadImpl();
|
|
}, "");
|
|
}
|
|
#else
|
|
TEST(ThreadCheckerTest, DetachFromThreadInRelease) {
|
|
ThreadCheckerClass::DetachThenCallFromDifferentThreadImpl();
|
|
}
|
|
#endif // ENABLE_THREAD_CHECKER
|
|
|
|
#endif // GTEST_HAS_DEATH_TEST || !ENABLE_THREAD_CHECKER
|
|
|
|
// Just in case we ever get lumped together with other compilation units.
|
|
#undef ENABLE_THREAD_CHECKER
|
|
|
|
} // namespace rtc
|