Update libjingle to 61168196

R=mallinath@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/8139004

git-svn-id: http://webrtc.googlecode.com/svn/trunk@5502 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/talk/base/thread_unittest.cc b/talk/base/thread_unittest.cc
index 896fbab..ddf6326 100644
--- a/talk/base/thread_unittest.cc
+++ b/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"
@@ -150,16 +151,22 @@
 };
 
 // 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) {
@@ -289,9 +296,9 @@
   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 +310,152 @@
   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: