diff options
Diffstat (limited to 'chromium/third_party/libjingle/source/talk/base/thread_unittest.cc')
-rw-r--r-- | chromium/third_party/libjingle/source/talk/base/thread_unittest.cc | 191 |
1 files changed, 161 insertions, 30 deletions
diff --git a/chromium/third_party/libjingle/source/talk/base/thread_unittest.cc b/chromium/third_party/libjingle/source/talk/base/thread_unittest.cc index 896fbabc5fd..d7d6a0129e4 100644 --- a/chromium/third_party/libjingle/source/talk/base/thread_unittest.cc +++ b/chromium/third_party/libjingle/source/talk/base/thread_unittest.cc @@ -25,6 +25,7 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include "talk/base/asyncinvoker.h" #include "talk/base/asyncudpsocket.h" #include "talk/base/event.h" #include "talk/base/gunit.h" @@ -38,8 +39,6 @@ using namespace talk_base; -const int MAX = 65536; - // Generates a sequence of numbers (collaboratively). class TestGenerator { public: @@ -87,7 +86,6 @@ class SocketClient : public TestGenerator, public sigslot::has_slots<> { uint32 prev = reinterpret_cast<const uint32*>(buf)[0]; uint32 result = Next(prev); - //socket_->set_readable(last < MAX); post_thread_->PostDelayed(200, post_handler_, 0, new TestMessage(result)); } @@ -101,7 +99,7 @@ class SocketClient : public TestGenerator, public sigslot::has_slots<> { class MessageClient : public MessageHandler, public TestGenerator { public: MessageClient(Thread* pth, Socket* socket) - : thread_(pth), socket_(socket) { + : socket_(socket) { } virtual ~MessageClient() { @@ -116,7 +114,6 @@ class MessageClient : public MessageHandler, public TestGenerator { } private: - Thread* thread_; Socket* socket_; }; @@ -150,16 +147,22 @@ class SignalWhenDestroyedThread : public Thread { }; // Function objects to test Thread::Invoke. -struct Functor1 { +struct FunctorA { int operator()() { return 42; } }; -class Functor2 { +class FunctorB { public: - explicit Functor2(bool* flag) : flag_(flag) {} + explicit FunctorB(bool* flag) : flag_(flag) {} void operator()() { if (flag_) *flag_ = true; } private: bool* 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) { @@ -258,40 +261,22 @@ TEST(ThreadTest, Wrap) { current_thread->UnwrapCurrent(); CustomThread* cthread = new CustomThread(); EXPECT_TRUE(cthread->WrapCurrent()); - EXPECT_TRUE(cthread->started()); + EXPECT_TRUE(cthread->RunningForTest()); EXPECT_FALSE(cthread->IsOwned()); cthread->UnwrapCurrent(); - EXPECT_FALSE(cthread->started()); + EXPECT_FALSE(cthread->RunningForTest()); delete cthread; current_thread->WrapCurrent(); } -// Test that calling Release on a thread causes it to self-destruct when -// it's finished running -TEST(ThreadTest, Release) { - scoped_ptr<Event> event(new Event(true, false)); - // Ensure the event is initialized. - event->Reset(); - - Thread* thread = new SignalWhenDestroyedThread(event.get()); - thread->Start(); - thread->Release(); - - // The event should get signaled when the thread completes, which should - // be nearly instantaneous, since it doesn't do anything. For safety, - // give it 3 seconds in case the machine is under load. - bool signaled = event->Wait(3000); - EXPECT_TRUE(signaled); -} - TEST(ThreadTest, Invoke) { // Create and start the thread. Thread thread; thread.Start(); // Try calling functors. - EXPECT_EQ(42, thread.Invoke<int>(Functor1())); + EXPECT_EQ(42, thread.Invoke<int>(FunctorA())); bool called = false; - Functor2 f2(&called); + FunctorB f2(&called); thread.Invoke<void>(f2); EXPECT_TRUE(called); // Try calling bare functions. @@ -303,6 +288,152 @@ TEST(ThreadTest, Invoke) { thread.Invoke<void>(&LocalFuncs::Func2); } +class AsyncInvokeTest : public testing::Test { + public: + void IntCallback(int value) { + EXPECT_EQ(expected_thread_, Thread::Current()); + int_value_ = value; + } + void AsyncInvokeIntCallback(AsyncInvoker* invoker, Thread* thread) { + expected_thread_ = thread; + invoker->AsyncInvoke(thread, FunctorC(), + &AsyncInvokeTest::IntCallback, + static_cast<AsyncInvokeTest*>(this)); + invoke_started_.Set(); + } + void SetExpectedThreadForIntCallback(Thread* thread) { + expected_thread_ = thread; + } + + protected: + enum { kWaitTimeout = 1000 }; + AsyncInvokeTest() + : int_value_(0), + invoke_started_(true, false), + expected_thread_(NULL) {} + + int int_value_; + Event invoke_started_; + Thread* expected_thread_; +}; + +TEST_F(AsyncInvokeTest, FireAndForget) { + AsyncInvoker invoker; + // Create and start the thread. + Thread thread; + thread.Start(); + // Try calling functor. + bool called = false; + invoker.AsyncInvoke<void>(&thread, FunctorB(&called)); + EXPECT_TRUE_WAIT(called, kWaitTimeout); +} + +TEST_F(AsyncInvokeTest, WithCallback) { + AsyncInvoker invoker; + // Create and start the thread. + Thread thread; + thread.Start(); + // Try calling functor. + SetExpectedThreadForIntCallback(Thread::Current()); + invoker.AsyncInvoke(&thread, FunctorA(), + &AsyncInvokeTest::IntCallback, + static_cast<AsyncInvokeTest*>(this)); + EXPECT_EQ_WAIT(42, int_value_, kWaitTimeout); +} + +TEST_F(AsyncInvokeTest, CancelInvoker) { + // Create and start the thread. + Thread thread; + thread.Start(); + // Try destroying invoker during call. + { + AsyncInvoker invoker; + invoker.AsyncInvoke(&thread, FunctorC(), + &AsyncInvokeTest::IntCallback, + static_cast<AsyncInvokeTest*>(this)); + } + // With invoker gone, callback should be cancelled. + Thread::Current()->ProcessMessages(kWaitTimeout); + EXPECT_EQ(0, int_value_); +} + +TEST_F(AsyncInvokeTest, CancelCallingThread) { + AsyncInvoker invoker; + { // Create and start the thread. + Thread thread; + thread.Start(); + // Try calling functor. + thread.Invoke<void>(Bind(&AsyncInvokeTest::AsyncInvokeIntCallback, + static_cast<AsyncInvokeTest*>(this), + &invoker, Thread::Current())); + // Wait for the call to begin. + ASSERT_TRUE(invoke_started_.Wait(kWaitTimeout)); + } + // Calling thread is gone. Return message shouldn't happen. + Thread::Current()->ProcessMessages(kWaitTimeout); + EXPECT_EQ(0, int_value_); +} + +TEST_F(AsyncInvokeTest, KillInvokerBeforeExecute) { + Thread thread; + thread.Start(); + { + AsyncInvoker invoker; + // Try calling functor. + thread.Invoke<void>(Bind(&AsyncInvokeTest::AsyncInvokeIntCallback, + static_cast<AsyncInvokeTest*>(this), + &invoker, Thread::Current())); + // Wait for the call to begin. + ASSERT_TRUE(invoke_started_.Wait(kWaitTimeout)); + } + // Invoker is destroyed. Function should not execute. + Thread::Current()->ProcessMessages(kWaitTimeout); + EXPECT_EQ(0, int_value_); +} + +TEST_F(AsyncInvokeTest, Flush) { + AsyncInvoker invoker; + bool flag1 = false; + bool flag2 = false; + // Queue two async calls to the current thread. + invoker.AsyncInvoke<void>(Thread::Current(), + FunctorB(&flag1)); + invoker.AsyncInvoke<void>(Thread::Current(), + FunctorB(&flag2)); + // Because we haven't pumped messages, these should not have run yet. + EXPECT_FALSE(flag1); + EXPECT_FALSE(flag2); + // Force them to run now. + invoker.Flush(Thread::Current()); + EXPECT_TRUE(flag1); + EXPECT_TRUE(flag2); +} + +TEST_F(AsyncInvokeTest, FlushWithIds) { + AsyncInvoker invoker; + bool flag1 = false; + bool flag2 = false; + // Queue two async calls to the current thread, one with a message id. + invoker.AsyncInvoke<void>(Thread::Current(), + FunctorB(&flag1), + 5); + invoker.AsyncInvoke<void>(Thread::Current(), + FunctorB(&flag2)); + // Because we haven't pumped messages, these should not have run yet. + EXPECT_FALSE(flag1); + EXPECT_FALSE(flag2); + // Execute pending calls with id == 5. + invoker.Flush(Thread::Current(), 5); + EXPECT_TRUE(flag1); + EXPECT_FALSE(flag2); + flag1 = false; + // Execute all pending calls. The id == 5 call should not execute again. + invoker.Flush(Thread::Current()); + EXPECT_FALSE(flag1); + EXPECT_TRUE(flag2); +} + + #ifdef WIN32 class ComThreadTest : public testing::Test, public MessageHandler { public: |