Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(243)

Unified Diff: webrtc/base/thread_unittest.cc

Issue 2877023002: Move webrtc/{base => rtc_base} (Closed)
Patch Set: update presubmit.py and DEPS include rules Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « webrtc/base/thread_darwin.mm ('k') | webrtc/base/timedelta.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: webrtc/base/thread_unittest.cc
diff --git a/webrtc/base/thread_unittest.cc b/webrtc/base/thread_unittest.cc
deleted file mode 100644
index c143120fbcceec8d7611b42156761989102213ff..0000000000000000000000000000000000000000
--- a/webrtc/base/thread_unittest.cc
+++ /dev/null
@@ -1,613 +0,0 @@
-/*
- * Copyright 2004 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.
- */
-
-#include <memory>
-
-#include "webrtc/base/asyncinvoker.h"
-#include "webrtc/base/asyncudpsocket.h"
-#include "webrtc/base/event.h"
-#include "webrtc/base/gunit.h"
-#include "webrtc/base/physicalsocketserver.h"
-#include "webrtc/base/sigslot.h"
-#include "webrtc/base/socketaddress.h"
-#include "webrtc/base/thread.h"
-
-#if defined(WEBRTC_WIN)
-#include <comdef.h> // NOLINT
-#endif
-
-using namespace rtc;
-
-// Generates a sequence of numbers (collaboratively).
-class TestGenerator {
- public:
- TestGenerator() : last(0), count(0) {}
-
- int Next(int prev) {
- int result = prev + last;
- last = result;
- count += 1;
- return result;
- }
-
- int last;
- int count;
-};
-
-struct TestMessage : public MessageData {
- explicit TestMessage(int v) : value(v) {}
- virtual ~TestMessage() {}
-
- int value;
-};
-
-// Receives on a socket and sends by posting messages.
-class SocketClient : public TestGenerator, public sigslot::has_slots<> {
- public:
- SocketClient(AsyncSocket* socket, const SocketAddress& addr,
- Thread* post_thread, MessageHandler* phandler)
- : socket_(AsyncUDPSocket::Create(socket, addr)),
- post_thread_(post_thread),
- post_handler_(phandler) {
- socket_->SignalReadPacket.connect(this, &SocketClient::OnPacket);
- }
-
- ~SocketClient() {
- delete socket_;
- }
-
- SocketAddress address() const { return socket_->GetLocalAddress(); }
-
- void OnPacket(AsyncPacketSocket* socket, const char* buf, size_t size,
- const SocketAddress& remote_addr,
- const PacketTime& packet_time) {
- EXPECT_EQ(size, sizeof(uint32_t));
- uint32_t prev = reinterpret_cast<const uint32_t*>(buf)[0];
- uint32_t result = Next(prev);
-
- post_thread_->PostDelayed(RTC_FROM_HERE, 200, post_handler_, 0,
- new TestMessage(result));
- }
-
- private:
- AsyncUDPSocket* socket_;
- Thread* post_thread_;
- MessageHandler* post_handler_;
-};
-
-// Receives messages and sends on a socket.
-class MessageClient : public MessageHandler, public TestGenerator {
- public:
- MessageClient(Thread* pth, Socket* socket)
- : socket_(socket) {
- }
-
- virtual ~MessageClient() {
- delete socket_;
- }
-
- virtual void OnMessage(Message *pmsg) {
- TestMessage* msg = static_cast<TestMessage*>(pmsg->pdata);
- int result = Next(msg->value);
- EXPECT_GE(socket_->Send(&result, sizeof(result)), 0);
- delete msg;
- }
-
- private:
- Socket* socket_;
-};
-
-class CustomThread : public rtc::Thread {
- public:
- CustomThread() {}
- virtual ~CustomThread() { Stop(); }
- bool Start() { return false; }
-
- bool WrapCurrent() {
- return Thread::WrapCurrent();
- }
- void UnwrapCurrent() {
- Thread::UnwrapCurrent();
- }
-};
-
-
-// A thread that does nothing when it runs and signals an event
-// when it is destroyed.
-class SignalWhenDestroyedThread : public Thread {
- public:
- SignalWhenDestroyedThread(Event* event)
- : event_(event) {
- }
-
- virtual ~SignalWhenDestroyedThread() {
- Stop();
- event_->Set();
- }
-
- virtual void Run() {
- // Do nothing.
- }
-
- private:
- Event* event_;
-};
-
-// A bool wrapped in a mutex, to avoid data races. Using a volatile
-// bool should be sufficient for correct code ("eventual consistency"
-// between caches is sufficient), but we can't tell the compiler about
-// that, and then tsan complains about a data race.
-
-// See also discussion at
-// http://stackoverflow.com/questions/7223164/is-mutex-needed-to-synchronize-a-simple-flag-between-pthreads
-
-// Using std::atomic<bool> or std::atomic_flag in C++11 is probably
-// the right thing to do, but those features are not yet allowed. Or
-// rtc::AtomicInt, if/when that is added. Since the use isn't
-// performance critical, use a plain critical section for the time
-// being.
-
-class AtomicBool {
- public:
- explicit AtomicBool(bool value = false) : flag_(value) {}
- AtomicBool& operator=(bool value) {
- CritScope scoped_lock(&cs_);
- flag_ = value;
- return *this;
- }
- bool get() const {
- CritScope scoped_lock(&cs_);
- return flag_;
- }
-
- private:
- CriticalSection cs_;
- bool flag_;
-};
-
-// Function objects to test Thread::Invoke.
-struct FunctorA {
- int operator()() { return 42; }
-};
-class FunctorB {
- public:
- explicit FunctorB(AtomicBool* flag) : flag_(flag) {}
- void operator()() { if (flag_) *flag_ = true; }
- private:
- AtomicBool* flag_;
-};
-struct FunctorC {
- int operator()() {
- Thread::Current()->ProcessMessages(50);
- return 24;
- }
-};
-
-// See: https://code.google.com/p/webrtc/issues/detail?id=2409
-TEST(ThreadTest, DISABLED_Main) {
- const SocketAddress addr("127.0.0.1", 0);
-
- // Create the messaging client on its own thread.
- Thread th1;
- Socket* socket = th1.socketserver()->CreateAsyncSocket(addr.family(),
- SOCK_DGRAM);
- MessageClient msg_client(&th1, socket);
-
- // Create the socket client on its own thread.
- Thread th2;
- AsyncSocket* asocket =
- th2.socketserver()->CreateAsyncSocket(addr.family(), SOCK_DGRAM);
- SocketClient sock_client(asocket, addr, &th1, &msg_client);
-
- socket->Connect(sock_client.address());
-
- th1.Start();
- th2.Start();
-
- // Get the messages started.
- th1.PostDelayed(RTC_FROM_HERE, 100, &msg_client, 0, new TestMessage(1));
-
- // Give the clients a little while to run.
- // Messages will be processed at 100, 300, 500, 700, 900.
- Thread* th_main = Thread::Current();
- th_main->ProcessMessages(1000);
-
- // Stop the sending client. Give the receiver a bit longer to run, in case
- // it is running on a machine that is under load (e.g. the build machine).
- th1.Stop();
- th_main->ProcessMessages(200);
- th2.Stop();
-
- // Make sure the results were correct
- EXPECT_EQ(5, msg_client.count);
- EXPECT_EQ(34, msg_client.last);
- EXPECT_EQ(5, sock_client.count);
- EXPECT_EQ(55, sock_client.last);
-}
-
-// Test that setting thread names doesn't cause a malfunction.
-// There's no easy way to verify the name was set properly at this time.
-TEST(ThreadTest, Names) {
- // Default name
- Thread *thread;
- thread = new Thread();
- EXPECT_TRUE(thread->Start());
- thread->Stop();
- delete thread;
- thread = new Thread();
- // Name with no object parameter
- EXPECT_TRUE(thread->SetName("No object", nullptr));
- EXPECT_TRUE(thread->Start());
- thread->Stop();
- delete thread;
- // Really long name
- thread = new Thread();
- EXPECT_TRUE(thread->SetName("Abcdefghijklmnopqrstuvwxyz1234567890", this));
- EXPECT_TRUE(thread->Start());
- thread->Stop();
- delete thread;
-}
-
-TEST(ThreadTest, Wrap) {
- Thread* current_thread = Thread::Current();
- current_thread->UnwrapCurrent();
- CustomThread* cthread = new CustomThread();
- EXPECT_TRUE(cthread->WrapCurrent());
- EXPECT_TRUE(cthread->RunningForTest());
- EXPECT_FALSE(cthread->IsOwned());
- cthread->UnwrapCurrent();
- EXPECT_FALSE(cthread->RunningForTest());
- delete cthread;
- current_thread->WrapCurrent();
-}
-
-TEST(ThreadTest, Invoke) {
- // Create and start the thread.
- Thread thread;
- thread.Start();
- // Try calling functors.
- EXPECT_EQ(42, thread.Invoke<int>(RTC_FROM_HERE, FunctorA()));
- AtomicBool called;
- FunctorB f2(&called);
- thread.Invoke<void>(RTC_FROM_HERE, f2);
- EXPECT_TRUE(called.get());
- // Try calling bare functions.
- struct LocalFuncs {
- static int Func1() { return 999; }
- static void Func2() {}
- };
- EXPECT_EQ(999, thread.Invoke<int>(RTC_FROM_HERE, &LocalFuncs::Func1));
- thread.Invoke<void>(RTC_FROM_HERE, &LocalFuncs::Func2);
-}
-
-// Verifies that two threads calling Invoke on each other at the same time does
-// not deadlock.
-TEST(ThreadTest, TwoThreadsInvokeNoDeadlock) {
- AutoThread thread;
- Thread* current_thread = Thread::Current();
- ASSERT_TRUE(current_thread != nullptr);
-
- Thread other_thread;
- other_thread.Start();
-
- struct LocalFuncs {
- static void Set(bool* out) { *out = true; }
- static void InvokeSet(Thread* thread, bool* out) {
- thread->Invoke<void>(RTC_FROM_HERE, Bind(&Set, out));
- }
- };
-
- bool called = false;
- other_thread.Invoke<void>(
- RTC_FROM_HERE, Bind(&LocalFuncs::InvokeSet, current_thread, &called));
-
- EXPECT_TRUE(called);
-}
-
-// Verifies that if thread A invokes a call on thread B and thread C is trying
-// to invoke A at the same time, thread A does not handle C's invoke while
-// invoking B.
-TEST(ThreadTest, ThreeThreadsInvoke) {
- AutoThread thread;
- Thread* thread_a = Thread::Current();
- Thread thread_b, thread_c;
- thread_b.Start();
- thread_c.Start();
-
- class LockedBool {
- public:
- explicit LockedBool(bool value) : value_(value) {}
-
- void Set(bool value) {
- CritScope lock(&crit_);
- value_ = value;
- }
-
- bool Get() {
- CritScope lock(&crit_);
- return value_;
- }
-
- private:
- CriticalSection crit_;
- bool value_ GUARDED_BY(crit_);
- };
-
- struct LocalFuncs {
- static void Set(LockedBool* out) { out->Set(true); }
- static void InvokeSet(Thread* thread, LockedBool* out) {
- thread->Invoke<void>(RTC_FROM_HERE, Bind(&Set, out));
- }
-
- // Set |out| true and call InvokeSet on |thread|.
- static void SetAndInvokeSet(LockedBool* out,
- Thread* thread,
- LockedBool* out_inner) {
- out->Set(true);
- InvokeSet(thread, out_inner);
- }
-
- // Asynchronously invoke SetAndInvokeSet on |thread1| and wait until
- // |thread1| starts the call.
- static void AsyncInvokeSetAndWait(AsyncInvoker* invoker,
- Thread* thread1,
- Thread* thread2,
- LockedBool* out) {
- CriticalSection crit;
- LockedBool async_invoked(false);
-
- invoker->AsyncInvoke<void>(
- RTC_FROM_HERE, thread1,
- Bind(&SetAndInvokeSet, &async_invoked, thread2, out));
-
- EXPECT_TRUE_WAIT(async_invoked.Get(), 2000);
- }
- };
-
- AsyncInvoker invoker;
- LockedBool thread_a_called(false);
-
- // Start the sequence A --(invoke)--> B --(async invoke)--> C --(invoke)--> A.
- // Thread B returns when C receives the call and C should be blocked until A
- // starts to process messages.
- thread_b.Invoke<void>(RTC_FROM_HERE,
- Bind(&LocalFuncs::AsyncInvokeSetAndWait, &invoker,
- &thread_c, thread_a, &thread_a_called));
- EXPECT_FALSE(thread_a_called.Get());
-
- EXPECT_TRUE_WAIT(thread_a_called.Get(), 2000);
-}
-
-// Set the name on a thread when the underlying QueueDestroyed signal is
-// triggered. This causes an error if the object is already partially
-// destroyed.
-class SetNameOnSignalQueueDestroyedTester : public sigslot::has_slots<> {
- public:
- SetNameOnSignalQueueDestroyedTester(Thread* thread) : thread_(thread) {
- thread->SignalQueueDestroyed.connect(
- this, &SetNameOnSignalQueueDestroyedTester::OnQueueDestroyed);
- }
-
- void OnQueueDestroyed() {
- // Makes sure that if we access the Thread while it's being destroyed, that
- // it doesn't cause a problem because the vtable has been modified.
- thread_->SetName("foo", nullptr);
- }
-
- private:
- Thread* thread_;
-};
-
-TEST(ThreadTest, SetNameOnSignalQueueDestroyed) {
- Thread* thread1 = new Thread();
- SetNameOnSignalQueueDestroyedTester tester1(thread1);
- delete thread1;
-
- Thread* thread2 = new AutoThread();
- SetNameOnSignalQueueDestroyedTester tester2(thread2);
- delete thread2;
-}
-
-class AsyncInvokeTest : public testing::Test {
- public:
- void IntCallback(int value) {
- EXPECT_EQ(expected_thread_, Thread::Current());
- int_value_ = value;
- }
- void SetExpectedThreadForIntCallback(Thread* thread) {
- expected_thread_ = thread;
- }
-
- protected:
- enum { kWaitTimeout = 1000 };
- AsyncInvokeTest()
- : int_value_(0),
- expected_thread_(nullptr) {}
-
- int int_value_;
- Thread* expected_thread_;
-};
-
-TEST_F(AsyncInvokeTest, FireAndForget) {
- AsyncInvoker invoker;
- // Create and start the thread.
- Thread thread;
- thread.Start();
- // Try calling functor.
- AtomicBool called;
- invoker.AsyncInvoke<void>(RTC_FROM_HERE, &thread, FunctorB(&called));
- EXPECT_TRUE_WAIT(called.get(), kWaitTimeout);
-}
-
-TEST_F(AsyncInvokeTest, KillInvokerDuringExecute) {
- // Use these events to get in a state where the functor is in the middle of
- // executing, and then to wait for it to finish, ensuring the "EXPECT_FALSE"
- // is run.
- Event functor_started(false, false);
- Event functor_continue(false, false);
- Event functor_finished(false, false);
-
- Thread thread;
- thread.Start();
- volatile bool invoker_destroyed = false;
- {
- AsyncInvoker invoker;
- invoker.AsyncInvoke<void>(RTC_FROM_HERE, &thread,
- [&functor_started, &functor_continue,
- &functor_finished, &invoker_destroyed] {
- functor_started.Set();
- functor_continue.Wait(Event::kForever);
- rtc::Thread::Current()->SleepMs(kWaitTimeout);
- EXPECT_FALSE(invoker_destroyed);
- functor_finished.Set();
- });
- functor_started.Wait(Event::kForever);
-
- // Allow the functor to continue and immediately destroy the invoker.
- functor_continue.Set();
- }
-
- // If the destructor DIDN'T wait for the functor to finish executing, it will
- // hit the EXPECT_FALSE(invoker_destroyed) after it finishes sleeping for a
- // second.
- invoker_destroyed = true;
- functor_finished.Wait(Event::kForever);
-}
-
-TEST_F(AsyncInvokeTest, Flush) {
- AsyncInvoker invoker;
- AtomicBool flag1;
- AtomicBool flag2;
- // Queue two async calls to the current thread.
- invoker.AsyncInvoke<void>(RTC_FROM_HERE, Thread::Current(), FunctorB(&flag1));
- invoker.AsyncInvoke<void>(RTC_FROM_HERE, Thread::Current(), FunctorB(&flag2));
- // Because we haven't pumped messages, these should not have run yet.
- EXPECT_FALSE(flag1.get());
- EXPECT_FALSE(flag2.get());
- // Force them to run now.
- invoker.Flush(Thread::Current());
- EXPECT_TRUE(flag1.get());
- EXPECT_TRUE(flag2.get());
-}
-
-TEST_F(AsyncInvokeTest, FlushWithIds) {
- AsyncInvoker invoker;
- AtomicBool flag1;
- AtomicBool flag2;
- // Queue two async calls to the current thread, one with a message id.
- invoker.AsyncInvoke<void>(RTC_FROM_HERE, Thread::Current(), FunctorB(&flag1),
- 5);
- invoker.AsyncInvoke<void>(RTC_FROM_HERE, Thread::Current(), FunctorB(&flag2));
- // Because we haven't pumped messages, these should not have run yet.
- EXPECT_FALSE(flag1.get());
- EXPECT_FALSE(flag2.get());
- // Execute pending calls with id == 5.
- invoker.Flush(Thread::Current(), 5);
- EXPECT_TRUE(flag1.get());
- EXPECT_FALSE(flag2.get());
- flag1 = false;
- // Execute all pending calls. The id == 5 call should not execute again.
- invoker.Flush(Thread::Current());
- EXPECT_FALSE(flag1.get());
- EXPECT_TRUE(flag2.get());
-}
-
-class GuardedAsyncInvokeTest : public testing::Test {
- public:
- void IntCallback(int value) {
- EXPECT_EQ(expected_thread_, Thread::Current());
- int_value_ = value;
- }
- void SetExpectedThreadForIntCallback(Thread* thread) {
- expected_thread_ = thread;
- }
-
- protected:
- const static int kWaitTimeout = 1000;
- GuardedAsyncInvokeTest()
- : int_value_(0),
- expected_thread_(nullptr) {}
-
- int int_value_;
- Thread* expected_thread_;
-};
-
-// Functor for creating an invoker.
-struct CreateInvoker {
- CreateInvoker(std::unique_ptr<GuardedAsyncInvoker>* invoker)
- : invoker_(invoker) {}
- void operator()() { invoker_->reset(new GuardedAsyncInvoker()); }
- std::unique_ptr<GuardedAsyncInvoker>* invoker_;
-};
-
-// Test that we can call AsyncInvoke<void>() after the thread died.
-TEST_F(GuardedAsyncInvokeTest, KillThreadFireAndForget) {
- // Create and start the thread.
- std::unique_ptr<Thread> thread(new Thread());
- thread->Start();
- std::unique_ptr<GuardedAsyncInvoker> invoker;
- // Create the invoker on |thread|.
- thread->Invoke<void>(RTC_FROM_HERE, CreateInvoker(&invoker));
- // Kill |thread|.
- thread = nullptr;
- // Try calling functor.
- AtomicBool called;
- EXPECT_FALSE(invoker->AsyncInvoke<void>(RTC_FROM_HERE, FunctorB(&called)));
- // With thread gone, nothing should happen.
- WAIT(called.get(), kWaitTimeout);
- EXPECT_FALSE(called.get());
-}
-
-// The remaining tests check that GuardedAsyncInvoker behaves as AsyncInvoker
-// when Thread is still alive.
-TEST_F(GuardedAsyncInvokeTest, FireAndForget) {
- GuardedAsyncInvoker invoker;
- // Try calling functor.
- AtomicBool called;
- EXPECT_TRUE(invoker.AsyncInvoke<void>(RTC_FROM_HERE, FunctorB(&called)));
- EXPECT_TRUE_WAIT(called.get(), kWaitTimeout);
-}
-
-TEST_F(GuardedAsyncInvokeTest, Flush) {
- GuardedAsyncInvoker invoker;
- AtomicBool flag1;
- AtomicBool flag2;
- // Queue two async calls to the current thread.
- EXPECT_TRUE(invoker.AsyncInvoke<void>(RTC_FROM_HERE, FunctorB(&flag1)));
- EXPECT_TRUE(invoker.AsyncInvoke<void>(RTC_FROM_HERE, FunctorB(&flag2)));
- // Because we haven't pumped messages, these should not have run yet.
- EXPECT_FALSE(flag1.get());
- EXPECT_FALSE(flag2.get());
- // Force them to run now.
- EXPECT_TRUE(invoker.Flush());
- EXPECT_TRUE(flag1.get());
- EXPECT_TRUE(flag2.get());
-}
-
-TEST_F(GuardedAsyncInvokeTest, FlushWithIds) {
- GuardedAsyncInvoker invoker;
- AtomicBool flag1;
- AtomicBool flag2;
- // Queue two async calls to the current thread, one with a message id.
- EXPECT_TRUE(invoker.AsyncInvoke<void>(RTC_FROM_HERE, FunctorB(&flag1), 5));
- EXPECT_TRUE(invoker.AsyncInvoke<void>(RTC_FROM_HERE, FunctorB(&flag2)));
- // Because we haven't pumped messages, these should not have run yet.
- EXPECT_FALSE(flag1.get());
- EXPECT_FALSE(flag2.get());
- // Execute pending calls with id == 5.
- EXPECT_TRUE(invoker.Flush(5));
- EXPECT_TRUE(flag1.get());
- EXPECT_FALSE(flag2.get());
- flag1 = false;
- // Execute all pending calls. The id == 5 call should not execute again.
- EXPECT_TRUE(invoker.Flush());
- EXPECT_FALSE(flag1.get());
- EXPECT_TRUE(flag2.get());
-}
« no previous file with comments | « webrtc/base/thread_darwin.mm ('k') | webrtc/base/timedelta.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698